/********************************************************************** 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 #include "ProtocolDefs.h" #include "BootloaderProtocol.h" #include "BootloaderInterface.h" #include "WiFiCtrl.h" unsigned int BootloaderHeader = 0; unsigned int BootloaderDataSize = 0; unsigned int BootloaderDataCtr = 0; unsigned int BootloaderBufPtr = 0; unsigned int BootloaderCRC = 0; unsigned char *BootloaderRxPtr; unsigned char BootloaderCommand = 0; unsigned char BootloaderState = RxHeader1; const unsigned char *BootloaderDataStartPtr = &BootloaderBuffer[9]; static char MyDeviceID = ID_SPRINKLER_DEVICE; void BootloaderProtocolInit(void) { BootloaderProtocolResetStateMachine(); } void BootloaderProtocolStateMachine(unsigned char Data) { switch(BootloaderState) { case Initialization: //Reset all pointers and data... { BootloaderDataSize = 0; BootloaderBufPtr = 0; BootloaderCommand = 0; BootloaderCRC = 0; BootloaderState = RxHeader1; break; } case RxHeader1: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xDE if(Data == BOOTLOADER_FRAME_HEADER_1) { BootloaderState = RxHeader2; } else { BootloaderProtocolResetStateMachine(); } break; } case RxHeader2: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xAD if(Data == BOOTLOADER_FRAME_HEADER_2) { BootloaderState = RxHeader3; } else { BootloaderProtocolResetStateMachine(); } break; } case RxHeader3: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xBE if(Data == BOOTLOADER_FRAME_HEADER_3) { BootloaderState = RxHeader4; } else { BootloaderProtocolResetStateMachine(); } break; } case RxHeader4: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xEF if(BootloaderHeader != BOOTLOADER_FRAME_HEADER) { //TODO, send NACK? BootloaderProtocolResetStateMachine(); break; } else { BootloaderState = RxCmd; } break; } case RxCmd: { BootloaderCommand = Data; BootloaderState = RxPayloadSize1; break; } case RxPayloadSize1: { BootloaderDataSize = Data; BootloaderState = RxPayloadSize2; break; } case RxPayloadSize2: { BootloaderDataSize <<= 8; BootloaderDataSize += Data; BootloaderState = RxPayloadSize3; break; } case RxPayloadSize3: { BootloaderDataSize <<= 8; BootloaderDataSize += Data; BootloaderState = RxPayloadSize4; break; } case RxPayloadSize4: { BootloaderDataSize <<= 8; BootloaderDataSize += Data; if(BootloaderDataSize > MAX_BOOTLOADER_PAYLOAD_SIZE) { //TODO, send NACK? BootloaderProtocolResetStateMachine(); break; } if(BootloaderDataSize == 0) { BootloaderState = RxCRC1; } else { BootloaderState = RxPayload; } break; } case RxPayload: //Data size { *BootloaderRxPtr = Data; BootloaderRxPtr++; BootloaderDataCtr++; if(BootloaderDataCtr == BootloaderDataSize) { BootloaderState = RxCRC1; break; } break; } case RxCRC1: //Data size { BootloaderCRC = Data; BootloaderState = RxCRC2; break; } case RxCRC2: //Data size { BootloaderCRC <<= 8; BootloaderCRC += Data; BootloaderState = RxCRC3; break; } case RxCRC3: //Data size { BootloaderCRC <<= 8; BootloaderCRC += Data; BootloaderState = RxCRC4; break; } case RxCRC4: //Data size { BootloaderCRC <<= 8; BootloaderCRC += Data; BootloaderState = RxCRC3; //TODO: Compute and Compare CRC. if(BootloaderCRC != 0xBAADCAFE) { BootloaderProtocolResetStateMachine(); } BootloaderExecuteCmd(BootloaderCommand); BootloaderProtocolResetStateMachine(); break; } default: { BootloaderProtocolResetStateMachine(); break; } } } void BootloaderProtocolProtocolAnalyzeNewData(unsigned char *DataBuf, int size) { int i; for(i = 0; i < size; i++) { BootloaderProtocolStateMachine(*DataBuf++); } } void BootloaderProtocolResetStateMachine() { BootloaderDataSize = 0; BootloaderHeader = 0; BootloaderBufPtr = 0; BootloaderCommand = 0; BootloaderCRC = 0; BootloaderState = RxHeader1; BootloaderDataCtr = 0; BootloaderRxPtr = &BootloaderBuffer[0]; } void BootloaderProtocolSendFrame(unsigned char Cmd, int Size) { //Header BootloaderBuffer[0] = BOOTLOADER_FRAME_HEADER_1; //Header BootloaderBuffer[1] = BOOTLOADER_FRAME_HEADER_2; BootloaderBuffer[2] = BOOTLOADER_FRAME_HEADER_3; BootloaderBuffer[3] = BOOTLOADER_FRAME_HEADER_4; BootloaderBuffer[4] = Cmd; char nibble = (char)((Size >> 24) &0x000000FF); BootloaderBuffer[5] = nibble; nibble = (char)((Size >> 16) &0x000000FF); BootloaderBuffer[6] = nibble; nibble = (char)((Size >> 8) &0x000000FF); BootloaderBuffer[7] = nibble; nibble = (char)(Size &0x000000FF); BootloaderBuffer[8] = nibble; unsigned char* CRCPtr = (unsigned char*)BootloaderDataStartPtr + Size; *CRCPtr++ = 0xBA; *CRCPtr++ = 0xAD; *CRCPtr++ = 0xCA; *CRCPtr++ = 0xFE; SendBootloaderData(&BootloaderBuffer[0],Size + PROTOCOL_INFO_DATA_SIZE); } unsigned char *BootloaderProtocolGetDataBufferPtr() { return (unsigned char*)BootloaderDataStartPtr; } void BootloaderProtocolSendHeartbeat() { *BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK; BootloaderProtocolSendFrame(BOOTLOADER_HEARTBEAT_RESPONSE,1); } void BootloaderProtocolSendACK(unsigned char Cmd) { *BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK; BootloaderProtocolSendFrame(Cmd,1); } void BootloaderProtocolSendNACK(unsigned char Cmd) { *BootloaderProtocolGetDataBufferPtr() = 0; BootloaderProtocolSendFrame(Cmd,1); } void BootloaderProtocolSendInitUploadResponse(char result) { int MaxSize = MAX_BOOTLOADER_PAYLOAD_SIZE; char* DataPtr = BootloaderProtocolGetDataBufferPtr(); *DataPtr++ = result; if(result == 1) { char nibble = (char)((MaxSize >> 24) &0x000000FF); *DataPtr++ = nibble; nibble = (char)((MaxSize >> 16) &0x000000FF); *DataPtr++ = nibble; nibble = (char)((MaxSize >> 8) &0x000000FF); *DataPtr++ = nibble; nibble = (char)(MaxSize &0x000000FF); *DataPtr++ = nibble; } else { *DataPtr++ = 0; *DataPtr++ = 0; *DataPtr++ = 0; *DataPtr++ = 0; } BootloaderProtocolSendFrame(BOOTLOADER_INIT_UPLOAD_RESPONSE,5); } void BootloaderProtocolSendDataChunkResult(char ErrorCode, int ChunkValue) { char* DataPtr = BootloaderProtocolGetDataBufferPtr(); *DataPtr++ = ErrorCode; char nibble = (char)((ChunkValue >> 24) &0x000000FF); *DataPtr++ = nibble; nibble = (char)((ChunkValue >> 16) &0x000000FF); *DataPtr++ = nibble; nibble = (char)((ChunkValue >> 8) &0x000000FF); *DataPtr++ = nibble; nibble = (char)(ChunkValue &0x000000FF); *DataPtr++ = nibble; BootloaderProtocolSendFrame(BOOTLOADER_SEND_DATA_CHUNK_RESPONSE,5); }