/********************************************************************** 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" #include "checksum.h" //test unsigned int BootloaderHeader = 0; unsigned int BootloaderDataSize = 0; unsigned int BootloaderDataCtr = 0; unsigned int BootloaderBufPtr = 0; unsigned int BootloaderCRC = 0; unsigned int BtldrComputedCRC = CRC_START_32; 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; BtldrComputedCRC = CRC_START_32; break; } case RxHeader1: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xDE BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); if(Data == BOOTLOADER_FRAME_HEADER_1) { BootloaderState = RxHeader2; } else { BootloaderProtocolResetStateMachine(); } break; } case RxHeader2: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xAD BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); if(Data == BOOTLOADER_FRAME_HEADER_2) { BootloaderState = RxHeader3; } else { BootloaderProtocolResetStateMachine(); } break; } case RxHeader3: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xBE BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); if(Data == BOOTLOADER_FRAME_HEADER_3) { BootloaderState = RxHeader4; } else { BootloaderProtocolResetStateMachine(); } break; } case RxHeader4: //Wait for data header... { BootloaderHeader <<= 8; BootloaderHeader += Data; //0xEF BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); if(BootloaderHeader != BOOTLOADER_FRAME_HEADER) { //TODO, send NACK? BootloaderProtocolResetStateMachine(); break; } else { BootloaderState = RxCmd; } break; } case RxCmd: { BootloaderCommand = Data; BootloaderState = RxPayloadSize1; BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); break; } case RxPayloadSize1: { BootloaderDataSize = Data; BootloaderState = RxPayloadSize2; BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); break; } case RxPayloadSize2: { BootloaderDataSize <<= 8; BootloaderDataSize += Data; BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); BootloaderState = RxPayloadSize3; break; } case RxPayloadSize3: { BootloaderDataSize <<= 8; BootloaderDataSize += Data; BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); BootloaderState = RxPayloadSize4; break; } case RxPayloadSize4: { BootloaderDataSize <<= 8; BootloaderDataSize += Data; BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); if(BootloaderDataSize > MAX_BOOTLOADER_PAYLOAD_SIZE+8) //+8 bytes for the size and index data { //TODO, send NACK? BootloaderProtocolResetStateMachine(); break; } if(BootloaderDataSize == 0) { BootloaderState = RxCRC1; } else { BootloaderState = RxPayload; } break; } case RxPayload: //Data size { *BootloaderRxPtr = Data; BootloaderRxPtr++; BootloaderDataCtr++; BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data); 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; //TODO: Compute and Compare CRC. BtldrComputedCRC ^= 0xffffffffL; //if(BootloaderCRC != 0xBAADCAFE) if(BootloaderCRC != BtldrComputedCRC) { BootloaderExecuteCmd(BootloaderCommand,0); BootloaderProtocolResetStateMachine(); return; } BootloaderExecuteCmd(BootloaderCommand,1); 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; BtldrComputedCRC = CRC_START_32; 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 int CRC = CRC_START_32; CRC = crc_32((const unsigned char*)BootloaderBuffer,Size+9); unsigned char* CRCPtr = (unsigned char*)BootloaderDataStartPtr + Size; nibble = (char)((CRC >> 24) &0x000000FF); *CRCPtr++ = nibble; nibble = (char)((CRC >> 16) &0x000000FF); *CRCPtr++ = nibble; nibble = (char)((CRC >> 8) &0x000000FF); *CRCPtr++ = nibble; nibble = (char)(CRC &0x000000FF); *CRCPtr++ = nibble; // *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); } void BootloaderProtocolSendBootloaderState(char State) { char* DataPtr = BootloaderProtocolGetDataBufferPtr(); *DataPtr++ = State; BootloaderProtocolSendFrame(BOOTLOADER_GET_STATE_RESPONSE,1); } void BootloaderProtocolSendFirmwareUploadResult(char Result) { char* DataPtr = BootloaderProtocolGetDataBufferPtr(); *DataPtr++ = Result; BootloaderProtocolSendFrame(BOOTLOADER_UPLOAD_FINISHED_RESPONSE,1); } void BootloaderProtocolSendFlashCheckResult(char Result) { char* DataPtr = BootloaderProtocolGetDataBufferPtr(); *DataPtr++ = Result; BootloaderProtocolSendFrame(BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_RESPONSE,1); } void BootloaderProtocolSendStoredFirmwareInfoResponse(unsigned char* FirmwareData, int size) { char* DataPtr = BootloaderProtocolGetDataBufferPtr(); int i = 0; for(i = 0; i < size; i++) { *DataPtr++ = *FirmwareData++; } BootloaderProtocolSendFrame(BOOTLOADER_GET_STORED_FIRMWARE_INFO_RESPONSE,size); }