/*================================================================================================
 
 pcProtocol.c						SiWiCom copyright 2006	  	       		   v1.0 (2006-06-22)
 
 Name: Christoffer Martinsson 	E-mail: cm@cmtec.se 
 Name: Joakim Nilsson 			E-mail: mail@jopin.se

 Description: Routines for pcProtocol. Uses usart.h as tranceiver
 
	BytePos:	      0          1        2            6       7      
				 ----------- --------- ------       ------ ----------
	Name:		| startbyte | command | data | ... | data | checksum |
				 ----------- --------- ------       ------ ----------
	
	---------------------------------------------------------------------------------------------
	Name:		nrOfBytes:		Value:						PC:			SiWiCom:	
	---------------------------------------------------------------------------------------------
	Start byte 	1				0x0A 						R/W			R/W    

	Command		1				0x11 – GET_LOCAL_DATA		W			R	
								0x22 – LOCAL_DATA			R			W	
								0x33 – REMOTE_DATA			R			W	
								0x44 – LOCAL_UPDATE			W			R
								0x55 – REMOTE_UPDATE		W			R
								0xFE – ACK 					R/W			R/W

	Data		5	Value for the specified command above.	R/W			R/W
	
					GET_LOCAL_DATA	Byte0 – 0x55
									Byte1 – 0x55
									Byte2 – 0x55
									Byte3 – 0x55
									Byte4 – 0x55
			
					LOCAL_DATA:		Byte0 – Device address
									Byte1 – Temp value
									Byte2 – Battery value
									Byte3 – AUX vaule
									Byte4 – 0x00 (not used)
									
					REMOTE_DATA:	Byte0 – Device address
									Byte1 – Temp value
									Byte2 – Battery value
									Byte3 – AUX vaule
									Byte4 – RSSI value

					LOCAL_UPDATE:	Byte0 – New master address (0x00 = no change)
									Byte1 – New device address (0x00 = no change)
									Byte2 – New wakeup time (0x00 = no change)	
									Byte3 – ProgramMode
									
											0x00 = no change
											0x01 = IDLE
											0x02 = MASTER
											0x03 = SLAVE
											0x04 = NOICEMAKER
									
									Byte4 – 0x55 (not used)
									
					REMOTE_UPDATE:	Byte0 – Device address
									Byte1 – New master address (0x00 = no change)
									Byte2 – New device address (0x00 = no change)
									Byte3 – New wakeup time (0x00 = no change)	
									Byte4 – 0x55 (not used)

					ACK:			Byte0 – 0x55
									Byte1 – 0x55
									Byte2 – 0x55
									Byte3 – 0x55
									Byte4 – 0x55 

	Checksum	1	Sum of the previous byte in the packet.	R/W			R/W

 
================================================================================================*/
#include <hardware.h>

#include <inttypes.h>
#include <avr/io.h>

#include <pcProtocol.h>
#include <usart.h>

static uint8_t pcProtocolInputBuffer[8];
static uint8_t pcProtocolByteCount;

/*================================================================================================
 Functions
================================================================================================*/
/*================================================================================================
 calculateChecksum
 
 Description: Calculate checksum for rfProtocol packet.

 Input: *data (array) to calculate from
 Return: checksum
------------------------------------------------------------------------------------------------*/
static uint8_t calculateChecksum(uint8_t *data)
{
    uint16_t checksum = 0;
	uint8_t i;

    for (i = 0; i < sizeof(pcProtocolInputBuffer)-1; i++)
    {
        checksum += data[i];
    }

    checksum &= 0x00FF;

    return (uint8_t)checksum;
}
/*================================================================================================
 pcProtocolSendData
 
 Description: Write a data packet to the usart (command = DATA).

 Input:	dataType (LOCAL_DATA or REMOTE_DATA)
		deviceAddr (address for the slave device), 
		tempValue (value of the temperature sensor),
		batteryValue (value of the battery level),
		rssiValue (value of the RSSI value)
		
 Return: -
------------------------------------------------------------------------------------------------*/
void pcProtocolSendData(uint8_t dataType, uint8_t deviceAddr, uint8_t tempValue, 
						uint8_t batteryValue, uint8_t auxValue, uint8_t rssiValue)
{	
	uint8_t tempBuffer[] = {PC_START_BYTE, dataType, deviceAddr, tempValue, 
							batteryValue, auxValue, rssiValue, 0x00};

	tempBuffer[sizeof(tempBuffer)-1] = calculateChecksum(tempBuffer);
	
	uint8_t i;
	// Sending data packet
	for (i = 0; i < sizeof(pcProtocolInputBuffer); i++)
	{
		usartSend(tempBuffer[i]);
	}
}
/*================================================================================================
 pcProtocolSendACK
 
 Description: Write a data packet to the usart (command = ACK).

 Input:	-
 Return: -
------------------------------------------------------------------------------------------------*/
void pcProtocolSendACK(void)
{	
	uint8_t tempBuffer[] = {PC_START_BYTE, PC_COMMAND_ACK, PC_PADDING, PC_PADDING, 
							PC_PADDING, PC_PADDING, PC_PADDING, 0x00};

	tempBuffer[sizeof(tempBuffer)-1] = calculateChecksum(tempBuffer);
	
	uint8_t i;
	// Sending data packet
	for (i = 0; i < sizeof(pcProtocolInputBuffer); i++)
	{
		usartSend(tempBuffer[i]);
	}
}
/*================================================================================================
 pcProtocolAddByteToBuffer
 
 Description: Add one byte to the input buffer and validate packet when buffer is full. 
 
 Input: data (uint8_t data byte to be added)
 Return: 1 if packet received complete, 0 if not.
------------------------------------------------------------------------------------------------*/
uint8_t pcProtocolAddByteToBuffer(uint8_t data)
{	
	uint8_t gotPacket = 0;
	
	if (pcProtocolByteCount == 0)
	{
		if (data == PC_START_BYTE)
		{
			pcProtocolInputBuffer[pcProtocolByteCount] = data;
			pcProtocolByteCount++;
		}
	}
	else if (pcProtocolByteCount < sizeof(pcProtocolInputBuffer)-1)
	{
		pcProtocolInputBuffer[pcProtocolByteCount] = data;
		pcProtocolByteCount++;
	}
	else if (pcProtocolByteCount == sizeof(pcProtocolInputBuffer)-1)
	{
		if(data == calculateChecksum(pcProtocolInputBuffer))
		{
			gotPacket = 1;			
		}
		else
		{
			pcProtocolByteCount = 0;
		}
	}
	
	if(gotPacket)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
/*================================================================================================
 pcProtocolGetData
 
 Description: Return validated incoming data.
 
 Input: *dataBuffer (pointer to buffer storing the data)
 Return: -
------------------------------------------------------------------------------------------------*/
void pcProtocolGetData(uint8_t *dataBuffer)
{
	uint8_t i;
	for(i = 0; i < sizeof(pcProtocolInputBuffer)-1; i++)
	{	
		dataBuffer[i] = pcProtocolInputBuffer[i];
	}
	pcProtocolByteCount = 0;
}
/*================================================================================================
 pcProtocolClearBuffer
 
 Description: Clear the incoming buffer counter
 
 Input: -
 Return: -
------------------------------------------------------------------------------------------------*/
void pcProtocolClearBuffer(void)
{
	pcProtocolByteCount = 0;
}
/*================================================================================================
 End
================================================================================================*/
