360 lines
8.5 KiB
C
360 lines
8.5 KiB
C
/**********************************************************************
|
||
Project: Automatic cat feeder
|
||
Date: march 19 2006
|
||
Author: Jean-Fran<61>ois Martel
|
||
Target: PIC 18F252
|
||
Compiler: Microchip mcc18
|
||
Filename: Protocol.c
|
||
|
||
File description: Communication protocol implementation.
|
||
|
||
|
||
jean-francois.martel@polymtl.ca
|
||
**********************************************************************/
|
||
#include "define.h"
|
||
#include "NetworkProtocol.h"
|
||
#include "Uart.h"
|
||
#include <string.h>
|
||
|
||
#include "MasterCtrlInterface.h"
|
||
#include "LoraNetworkInterface.h"
|
||
#include "LTENetworkInterface.h"
|
||
|
||
|
||
|
||
|
||
static char MyDeviceID = ID_SPRINKLER_DEVICE;
|
||
|
||
char mFrameData[MAX_MESSAGE_SIZE+10];
|
||
|
||
ProtocolData_t mLoraProtocolData;
|
||
ProtocolData_t mLTEProtocolData;
|
||
|
||
|
||
void ProtocolInit(int User)
|
||
{
|
||
ProtocolData_t *DataStruct;
|
||
switch(User)
|
||
{
|
||
case NETWORK_PROTOCOL_USER_LORA:
|
||
{
|
||
DataStruct = &mLoraProtocolData;
|
||
break;
|
||
}
|
||
case NETWORK_PROTOCOL_USER_LTE:
|
||
{
|
||
DataStruct = &mLTEProtocolData;
|
||
break;
|
||
}
|
||
default:
|
||
return;
|
||
break;
|
||
}
|
||
ResetStateMachine(DataStruct);
|
||
|
||
}
|
||
|
||
void StateMachine(unsigned char Data,ProtocolData_t *ProtocolData )
|
||
{
|
||
switch(ProtocolData->State)
|
||
{
|
||
case Initialization: //Reset all pointers and data...
|
||
{
|
||
ProtocolData->DataSize = 0;
|
||
ProtocolData->BufPtr = 0;
|
||
ProtocolData->RxPtr = 0;
|
||
ProtocolData->Command = 0;
|
||
ProtocolData->CRC = 0;
|
||
ProtocolData->State = RxHeader;
|
||
break;
|
||
}
|
||
case RxHeader: //Wait for data header...
|
||
{
|
||
if(Data == FRAME_HEADER)
|
||
{
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->State = RxAdd;
|
||
ProtocolData->CRC ^= Data;
|
||
}
|
||
else
|
||
{
|
||
ProtocolData->DataSize = 0;
|
||
ResetStateMachine(ProtocolData);
|
||
}
|
||
|
||
break;
|
||
}
|
||
case RxAdd: //Sender Address.
|
||
{
|
||
ProtocolData->SenderAddress = Data;
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->State = RxID;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxID: //Sender ID
|
||
{
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->State = RxMyID;
|
||
ProtocolData->SenderID = Data;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxMyID:
|
||
{
|
||
// if(Data != MyDeviceID && Data != BROADCAST_VALUE) //Message is not for this type of device and it's not a broadcast
|
||
// {
|
||
// ResetStateMachine();
|
||
// break;
|
||
// }
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->State = RxMyAddress;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxMyAddress:
|
||
{
|
||
if(Data != MY_DEVICE_ADDRESS && Data != BROADCAST_VALUE) //Message is not for this device address and it's not a broadcast
|
||
{
|
||
ResetStateMachine(ProtocolData);
|
||
break;
|
||
}
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->State = RxFlags;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxFlags:
|
||
{
|
||
ProtocolData->Flags = Data;
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->State = RxCMD;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxCMD:
|
||
{
|
||
ProtocolData->Command = Data;
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->State = RxSize1;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxSize1: //Data size MSB
|
||
{
|
||
ProtocolData->DataSize = 0;
|
||
ProtocolData->DataSize = (unsigned int)Data;
|
||
ProtocolData->DataSize <<= 8;
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
|
||
|
||
ProtocolData->State = RxSize2;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxSize2: //Data size
|
||
{
|
||
ProtocolData->DataSize |= (unsigned int)Data;
|
||
ProtocolData->DataSize <<= 8;
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
|
||
|
||
ProtocolData->State = RxSize3;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxSize3: //Data size
|
||
{
|
||
ProtocolData->DataSize |= (unsigned int)Data;
|
||
ProtocolData->DataSize <<= 8;
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
|
||
|
||
ProtocolData->State = RxSize4;
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
|
||
case RxSize4: //Data size LSB
|
||
{
|
||
ProtocolData->DataSize |= (unsigned int)Data;
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
|
||
if(ProtocolData->DataSize > MAX_MESSAGE_SIZE)
|
||
ResetStateMachine(ProtocolData);
|
||
|
||
if(ProtocolData->DataSize == 0)
|
||
ProtocolData->State = RxCRC;
|
||
else
|
||
ProtocolData->State = RxData;
|
||
|
||
ProtocolData->CRC ^= Data;
|
||
break;
|
||
}
|
||
case RxData:
|
||
{
|
||
ProtocolData->CRC ^= Data;
|
||
|
||
ProtocolData->mRxData[ProtocolData->BufPtr++] = Data;
|
||
ProtocolData->DataCtr++;
|
||
|
||
if(ProtocolData->DataCtr == ProtocolData->DataSize)
|
||
{
|
||
ProtocolData->State = RxCRC;
|
||
}
|
||
|
||
break;
|
||
}
|
||
case RxCRC:
|
||
{
|
||
if(Data != ProtocolData->CRC)
|
||
{
|
||
ResetStateMachine(ProtocolData);
|
||
// ProtocolAcknowledge(0,Command,0);
|
||
break;
|
||
}
|
||
// NewMasterMessageReceived(mRxData);
|
||
if(ProtocolData == &mLoraProtocolData)
|
||
{
|
||
// ExecuteLoraMasterCommand(ProtocolData->Command,ProtocolMsgDataPtr(ProtocolData),ProtocolData->DataSize);
|
||
}
|
||
else if(ProtocolData == &mLTEProtocolData)
|
||
{
|
||
// ExecuteLTEMasterCommand(ProtocolData->SenderID, ProtocolData->Command,ProtocolMsgDataPtr(ProtocolData),ProtocolData->DataSize);
|
||
}
|
||
ResetStateMachine(ProtocolData);
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
ResetStateMachine(ProtocolData);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
void ProtocolAnalyzeNewData(unsigned char Data, int User)
|
||
{
|
||
ProtocolData_t *DataStruct;
|
||
switch(User)
|
||
{
|
||
case NETWORK_PROTOCOL_USER_LORA:
|
||
{
|
||
DataStruct = &mLoraProtocolData;
|
||
break;
|
||
}
|
||
case NETWORK_PROTOCOL_USER_LTE:
|
||
{
|
||
DataStruct = &mLTEProtocolData;
|
||
break;
|
||
}
|
||
default:
|
||
return;
|
||
break;
|
||
}
|
||
// mRxData[RxPtr] = Data;
|
||
// printf("%X",Data);
|
||
StateMachine(Data, DataStruct);
|
||
}
|
||
|
||
void ResetStateMachine(ProtocolData_t *ProtocolData)
|
||
{
|
||
ProtocolData->DataSize = 0;
|
||
ProtocolData->BufPtr = 0;
|
||
ProtocolData->RxPtr = 0;
|
||
ProtocolData->Command = 0;
|
||
ProtocolData->CRC = 0;
|
||
ProtocolData->State = RxHeader;
|
||
ProtocolData->DataCtr = 0;
|
||
ProtocolData->Flags = 0;
|
||
ProtocolData->SenderAddress = 0;
|
||
}
|
||
|
||
void ProtocolExecCmd(void)
|
||
{
|
||
// switch(Command)
|
||
// {
|
||
// case RX_GET_STATUS:
|
||
// {
|
||
// unsigned char StatusByte =0;
|
||
//// memcpy(&StatusByte, &IRRemoteStatus, sizeof(IRRemoteStatus));
|
||
//// ProtocolSendCmd(TX_DEADBOLT_STATUS,&StatusByte,sizeof(StatusByte),1,0);
|
||
//
|
||
// break;
|
||
// }
|
||
// }
|
||
}
|
||
|
||
void ProtocolAcknowledge(unsigned char Answer,unsigned char Cmd, unsigned char Data)
|
||
{
|
||
unsigned char data[2];
|
||
if(Answer == 1)
|
||
{
|
||
data[0] = PROTOCOL_ACK; //CMD
|
||
}
|
||
else
|
||
{
|
||
data[0] = PROTOCOL_NAK; //CMD
|
||
}
|
||
data[1] = Cmd;
|
||
|
||
// ProtocolSendCmd(TX_NETWORK_ACK,&data[0],2,1,0);
|
||
}
|
||
|
||
|
||
|
||
unsigned char ProtocolCalcCrc(unsigned char* Buffer,unsigned char size)
|
||
{
|
||
unsigned char CRC = 0;
|
||
unsigned char i;
|
||
for(i = 0; i < size; i++)
|
||
CRC ^= Buffer[i];
|
||
|
||
return CRC;
|
||
}
|
||
|
||
unsigned char ProtocolIsReceiving(void)
|
||
{
|
||
// if(State == RxHeader)
|
||
// return 0; // Idle...
|
||
// else
|
||
// return 1; //receiving from serial port
|
||
|
||
}
|
||
|
||
|
||
|
||
unsigned char* ProtocolGetFrame(unsigned char DestDevice,unsigned char DestAddress, unsigned char SenderDevice, unsigned char Cmd, unsigned char *Data,unsigned int Size,unsigned char Flags, int *FrameSize)
|
||
{
|
||
if(Size > MAX_MESSAGE_SIZE)
|
||
{
|
||
*FrameSize = 0;
|
||
return &mFrameData[FRAME_HEADER_INDEX];
|
||
}
|
||
|
||
|
||
|
||
mFrameData[FRAME_HEADER_INDEX] = FRAME_HEADER; //header
|
||
mFrameData[FRAME_SENDER_ADDRESS_INDEX] = MY_DEVICE_ADDRESS; //My Address
|
||
mFrameData[FRAME_SENDER_DEVICE_ID_INDEX] = SenderDevice; //My ID
|
||
mFrameData[FRAME_DEST_DEVICE_ID_INDEX] = DestDevice; //Destination ID
|
||
mFrameData[FRAME_DEST_ADDRESS_INDEX] = DestAddress ;//Address; //Destination Address
|
||
mFrameData[FRAME_FLAGS_INDEX] = Flags; //Flags
|
||
mFrameData[FRAME_COMMAND_INDEX] = Cmd; //Command to send
|
||
mFrameData[FRAME_SIZE1_INDEX] = (unsigned char)((Size >> 24) & 0xFF);
|
||
mFrameData[FRAME_SIZE2_INDEX] = (unsigned char)((Size >> 16) & 0xFF);
|
||
mFrameData[FRAME_SIZE3_INDEX] = (unsigned char)((Size >> 8) & 0xFF);
|
||
mFrameData[FRAME_SIZE4_INDEX] = (unsigned char)(Size & 0xFF);
|
||
memcpy((void*)&mFrameData[FRAME_DATA_INDEX],(void*)Data,Size); //Cmd data
|
||
mFrameData[Size+FRAME_DATA_INDEX] = ProtocolCalcCrc(mFrameData,Size + FRAME_DATA_INDEX); // CRC
|
||
|
||
*FrameSize = Size + FRAME_INDEX_NBR;
|
||
|
||
return &mFrameData[FRAME_HEADER_INDEX];
|
||
|
||
}
|
||
|
||
unsigned char *ProtocolMsgDataPtr(ProtocolData_t *ProtocolData)
|
||
{
|
||
return &ProtocolData->mRxData[FRAME_DATA_INDEX];
|
||
} |