/********************************************************************** Project: Automatic cat feeder Date: march 19 2006 Author: Jean-Fran�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 #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]; }