2018-02-18 14:02:33 +05:30

149 lines
5.8 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// This file is part of RTTeensyLink
//
// Copyright (c) 2015, richards-tech, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
// Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "RTTeensyLink.h"
#include "RTTeensyLinkEEPROM.h"
#include "RTTeensyLinkUtils.h"
#include "Arduino.h"
#include <string.h>
RTTeensyLink::RTTeensyLink()
{
}
RTTeensyLink::~RTTeensyLink()
{
}
void RTTeensyLink::begin(const char *identitySuffix)
{
if (!RTTeensyLinkEEPROMValid())
RTTeensyLinkEEPROMDefault();
m_identitySuffix = identitySuffix;
RTTeensyLinkRXFrameInit(&(m_RXFrame), &(m_RXFrameBuffer));
}
void RTTeensyLink::background()
{
while (Serial.available()) {
if (!RTTeensyLinkReassemble(&(m_RXFrame), Serial.read())) {
sendDebugMessage("Reassembly error");
} else {
if (m_RXFrame.complete) {
processReceivedMessage();
RTTeensyLinkRXFrameInit(&(m_RXFrame), &(m_RXFrameBuffer));
}
}
}
}
void RTTeensyLink::processReceivedMessage()
{
RTTEENSYLINK_MESSAGE *message; // a pointer to the message part of the frame
int identityLength;
int suffixLength;
message = &(m_RXFrameBuffer.message); // get the message pointer
switch (message->messageType)
{
case RTTEENSYLINK_MESSAGE_POLL:
case RTTEENSYLINK_MESSAGE_ECHO:
RTTeensyLinkConvertIntToUC2(RTTEENSYLINK_MY_ADDRESS, message->messageAddress);
sendFrame(&(m_RXFrameBuffer), m_RXFrameBuffer.messageLength); // just send the frame back as received
break;
case RTTEENSYLINK_MESSAGE_IDENTITY:
identityLength = strlen(RTTeensyLinkConfig.identity);
suffixLength = strlen(m_identitySuffix);
memcpy(message->data, RTTeensyLinkConfig.identity, identityLength + 1); // copy in identity
if ((identityLength + suffixLength) < RTTEENSYLINK_DATA_MAX_LEN - 1) {
memcpy(message->data + identityLength, m_identitySuffix, suffixLength + 1); // copy in suffix
} else {
suffixLength = 0;
}
RTTeensyLinkConvertIntToUC2(RTTEENSYLINK_MY_ADDRESS, message->messageAddress);
message->data[RTTEENSYLINK_DATA_MAX_LEN - 1] = 0; // make sure zero terminated if it was truncated
sendFrame(&(m_RXFrameBuffer), RTTEENSYLINK_MESSAGE_HEADER_LEN + identityLength + suffixLength + 1);
break;
default:
if (message->messageType < RTTEENSYLINK_MESSAGE_CUSTOM) { // illegal code
message->data[0] = RTTEENSYLINK_RESPONSE_ILLEGAL_COMMAND;
message->data[1] = message->messageType; // this is the offending code
message->messageType = RTTEENSYLINK_MESSAGE_ERROR;
RTTeensyLinkConvertIntToUC2(RTTEENSYLINK_MY_ADDRESS, message->messageAddress);
sendFrame(&(m_RXFrameBuffer), RTTEENSYLINK_MESSAGE_HEADER_LEN + 2);
break;
}
processCustomMessage(message->messageType, message->messageParam, message->data,
m_RXFrameBuffer.messageLength - RTTEENSYLINK_MESSAGE_HEADER_LEN); // see if anyone wants to process it
break;
}
}
void RTTeensyLink::sendDebugMessage(const char *debugMessage)
{
RTTEENSYLINK_FRAME frame;
int stringLength;
stringLength = strlen(debugMessage);
if (stringLength >= RTTEENSYLINK_DATA_MAX_LEN)
stringLength = RTTEENSYLINK_DATA_MAX_LEN-1;
memcpy(frame.message.data, debugMessage, stringLength);
frame.message.data[stringLength] = 0;
frame.message.messageType = RTTEENSYLINK_MESSAGE_DEBUG;
RTTeensyLinkConvertIntToUC2(RTTEENSYLINK_MY_ADDRESS, frame.message.messageAddress);
sendFrame(&frame, RTTEENSYLINK_MESSAGE_HEADER_LEN + stringLength + 1);
}
void RTTeensyLink::sendMessage(unsigned char messageType, unsigned char messageParam, unsigned char *data, int length)
{
RTTEENSYLINK_FRAME frame;
RTTeensyLinkConvertIntToUC2(RTTEENSYLINK_MY_ADDRESS, frame.message.messageAddress);
frame.message.messageType = messageType;
frame.message.messageParam = messageParam;
if (length > RTTEENSYLINK_DATA_MAX_LEN)
length = RTTEENSYLINK_DATA_MAX_LEN;
memcpy(frame.message.data, data, length);
sendFrame(&frame, length + RTTEENSYLINK_MESSAGE_HEADER_LEN);
}
void RTTeensyLink::sendFrame(RTTEENSYLINK_FRAME *frame, int length)
{
frame->sync0 = RTTEENSYLINK_MESSAGE_SYNC0;
frame->sync1 = RTTEENSYLINK_MESSAGE_SYNC1;
frame->messageLength = length; // set length
RTTeensyLinkSetChecksum(frame); // compute checksum
Serial.write((unsigned char *)frame, frame->messageLength + RTTEENSYLINK_FRAME_HEADER_LEN);
}