426 lines
9.4 KiB
C
426 lines
9.4 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 <string.h>
|
||
#include "ProtocolDefs.h"
|
||
#include "BootloaderProtocol.h"
|
||
#include "BootloaderInterface.h"
|
||
#include "WiFiCtrl.h"
|
||
#include "checksum.h"
|
||
|
||
|
||
|
||
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();
|
||
}
|
||
|
||
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);
|
||
} |