/**************************************************************************************************
---------------------------------------------------------------------------------------------------
	Copyright (c) 2004, Jonathan Bagg
	All rights reserved.

	 Redistribution and use in source and binary forms, with or without modification, are permitted 
	 provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of 
	  conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of 
	  conditions and the following disclaimer in the documentation and/or other materials provided 
	  with the distribution.
    * Neither the name of Jonathan Bagg nor the names of its contributors may be used to 
	  endorse or promote products derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
  POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------------------------------
   Project name : Infidigm AVR Drivers
   Processor	: ATMega64, ATMega128
   File name    : rf.c
---------------------------------------------------------------------------------------------------
   Modifications: 

   Revision 1.0  2004/07/05 	Bagg
   - Finished for release
   - Size = 1346
   - max speed  ~ 28,800
---------------------------------------------------------------------------------------------------
   Created      : 10 March 2004    	           Author(s) : Jonathan Bagg
---------------------------------------------------------------------------------------------------
   RF Communications Module Driver; Model = BiM2 or 3
---------------------------------------------------------------------------------------------------
**************************************************************************************************/

#include <avr/io.h> 
#include <avr/signal.h>
#include <avr/interrupt.h>
#include "rf.h"
#include "tim.h"

/**************************************************************************************************
*   RFtxTABLE[]; TX - Used for Nibble lookup
**************************************************************************************************/
static char RFtxTABLE[] = {
	//0x07									000111	- Not Used (long runs)
	0x0B,				// 0x00				001011
	0x0D,				// 0x01				001101
	0x0E,				// 0x02				001110
	0x13,				// 0x03				010011
	// 0x15									010101	- Reserved for Start Byte
	0x16,				// 0x04				010110
	0x19,				// 0x05				011001
	0x1A,				// 0x06				011010
	0x1C,				// 0x07				011100
	0x23,				// 0x08				100011
	0x25,				// 0x09				100101
	0x26,				// 0x0A				100110
	0x29,				// 0x0B				101001
	// 0x2A									101010	- Reserved for Start Byte
	0x2C,				// 0x0C				101100
	0x31,				// 0x0D				110001
	0x32,				// 0x0E				110010
	0x34				// 0x0F				110100
	// 0x38									111000	- Not Used (long runs)
};

/**************************************************************************************************
*   RFrxTABLE(); RX - See 'rf.h' Header file for Description
**************************************************************************************************/
static char RFrxTABLE[] = {
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0xff,				// 0x07				000111	- Not Used (long runs)
	0xff, 0xff, 0xff,
	0x00,				// 0x0B				001011
	0xff,
	0x01,				// 0x0D				001101
	0x02, 				// 0x0E				001110
	0xff, 0xff, 0xff, 0xff,
	0x03,				// 0x13				010011
	0xff,
	0xff,				// 0x15				010101	- Reserved for Start Byte
	0x04,				// 0x16				010110
	0xff, 0xff,
	0x05,				// 0x19				011001
	0x06,				// 0x1A				011010
	0xff,
	0x07,				// 0x1C				011100
	0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
	0x08,				// 0x23				100011
	0xff,
	0x09,				// 0x25				100101
	0x0A,				// 0x26 			100110
	0xff,0xff,
	0x0B,				// 0x29				101001
	0xff,				// 0x2A				101010	- Reserved for Start Byte
	0xff,
	0x0C,				// 0x2C				101100
	0xff, 0xff, 0xff, 0xff,
	0x0D,				// 0x31				110001
	0x0E,				// 0x32				110010
	0xff,
	0x0F				// 0x34				110100
						// 0x38				111000	- Not Used (long runs)
};

/**************************************************************************************************
*   INTERNAL Function declaration - See 'rf.h' Header file for Descriptions
**************************************************************************************************/
static void RFencode(char input[]);
static void RFtxbyte(char data);
static char RFdecode(char input[]);
static unsigned char rx_lookup(unsigned char data);

/**************************************************************************************************
*   startRF(); - See 'rf.h' Header file for Description
**************************************************************************************************/
void startRF(void) {
	RFmode=RFrx;						//Set RF Mode = RX
	RFenPort&= ~_BV(EnRX);	
	RFenPort|= _BV(EnTX);	
	delay(1);
	UBRR0L = (char)RF_BAUD_SELECT;		//Setup UART0
	UCSR0A = 0x00;
	UCSR0B = 0xD8;	 					//enable Rx, TX, Rx IQR, & Tx IRQ
}

/**************************************************************************************************
*   RFsend(); TX - See 'rf.h' Header file for Description
**************************************************************************************************/
void RFsend(char address, void *data, char length)
{
 char i,checksum, *temp, hold[2];
 temp = data;
 checksum = address;
 checksum+= length;
 while (newmsg);							//wait if Recieving Message (Half Duplex RF Device)
 //Check if need to change mode to RFTX
 cli();
 if (RFmode!=RFtx) {
	RFmode=RFtx;
	RFenPort&= ~_BV(EnTX);	
	RFenPort|= _BV(EnRX);	
	delay(1);
	UDR0 = 0xAA;							//Start Interrupts
 }
 else 
	RFtxbyte(0xAA);
 sei();
 RFtxbyte(0xAA);
 RFtxbyte(0x95);							//Send Start Byte
 hold[0] = address;
 hold[1] = length;
 RFencode(hold);							//encode address and length of packet
   //Encode and Copy data into buffer
 for (i=0;i<=length;i++) {
	if (i!=length) {
		hold[(i&1)] = *(temp + i);			//get 2 bytes ready to encode
		checksum+= *(temp + i);			//build checksum
		if ((i&1)) 
			RFencode(hold);			//encode / send 2 bytes
	}
	else {
		hold[(i&1)]= checksum;
		RFencode(hold);						//encode / send checksum last
	}
	
 }
}

/**************************************************************************************************
*   RFencode(); TX - See 'rf.h' Header file for Description
**************************************************************************************************/
static void RFencode(char input[])
{
 unsigned char temp[4];
 temp[0] = RFtxTABLE[input[0] >> 4];
 temp[1] = RFtxTABLE[input[0] & 0x0F];
 temp[2] = RFtxTABLE[input[1] >> 4];
 temp[3] = RFtxTABLE[input[1] & 0x0F];
 RFtxbyte((temp[0] << 2) | (temp[1] >> 4));
 RFtxbyte((temp[1] << 4) | (temp[2] >> 2));
 RFtxbyte((temp[2] << 6) | temp[3]);
}



/**************************************************************************************************
*   RFtxbyte(); TX - See 'rf.h' Header file for Description
**************************************************************************************************/
static void RFtxbyte(char data)
{
 static unsigned char RFtxEND;
 char done=1;
 while (done) {
	cli();
	if (RFtxUsed < RFtxSize) 
		done = 0;
	sei();
 }
 RFtxBuff[(RFtxEND & (RFtxSize-1))] = data;
 RFtxEND++;
 RFtxUsed++;
}

/**************************************************************************************************
*   UART0 TX Data Register Empty ISR - See 'rf.h' Header file for Description
**************************************************************************************************/
SIGNAL(SIG_UART0_TRANS)
{
 static unsigned char RFtxpnt;
 if (RFtxUsed) {
	UDR0 = RFtxBuff[(RFtxpnt & (RFtxSize-1))];
	RFtxpnt++;
	RFtxUsed--;
 }
 else {
	RFmode=RFrx;
	RFenPort&= ~_BV(EnRX);	
	RFenPort|= _BV(EnTX);	
	delay(1);
 }
}

/**************************************************************************************************
*   UART0 RX Byte Received ISR - See 'rf.h' Header file for Description
**************************************************************************************************/
SIGNAL(SIG_UART0_RECV) 
{
 static unsigned char rx, watch, length, checksum, pos, spos, slice[3];

 watch = rx;
 rx = UDR0;
 //test for new message
 if (rx==0x95 && watch==0xAA) {
	pos = 0;
	spos = 0;
	checksum = 0;
	RFrxtemp = RFrxEND;
	newmsg = 1;
 }
 else if (newmsg) {
 	slice[spos] = rx;
 	if (spos<2) 
		spos++;
	else {
		spos = 0;
		//check for room on Buffer
		if ((RFrxUsed+2) < RFrxSize) {
			if (RFdecode(slice)) {
				pos+=2;
				RFrxUsed+=2;
			}
			else {
				RFrxUsed-= pos;				//Stop Buffer fillup if Bad Decode
				newmsg = 0;
				return;
			}
		}
		else {
			RFrxUsed-= pos;					//Stop Buffer fillup if Buffer FULL
			newmsg = 0;
			return;
		}
		//check address & Length
		if (pos==2) {
			RFrxtemp-=2;
			//Stop Buffer fillup if Wrong Address
			if (RFrxBuff[(RFrxEND & (RFrxSize-1))] != RFaddress && RFrxBuff[(RFrxEND & (RFrxSize-1))] != 255) {
				newmsg = 0;
				RFrxUsed-= 2;
				return;
			}
			//Stop Buffer fillup if Bad Length
			if (RFrxBuff[((RFrxEND+1) & (RFrxSize-1))] <= RFmsglen) 
				length = RFrxBuff[((RFrxEND+1) & (RFrxSize-1))];
			else {
				newmsg = 0;
				RFrxUsed-= 2;
				return;
			}
			checksum+= RFrxBuff[(RFrxEND & (RFrxSize-1))];
			checksum+= RFrxBuff[((RFrxEND+1) & (RFrxSize-1))];
		}
		//reached end / checksum byte
		if (pos>=length+3) {
			char i;
			for (i=0;i<length;i++) 
				checksum+= RFrxBuff[(RFrxEND + i) & (RFrxSize-1)];
			if (checksum == RFrxBuff[((RFrxEND+length) & (RFrxSize-1))]) {
				RFrxEND+=length;
				if (length&1) 
					RFrxUsed-= 3;
				else 
					RFrxUsed-= 4;
				//Append Message List Array
			}
			else 
				RFrxUsed-= pos;			//Free Space on Buffer if Bad message
			newmsg = 0;
		}
	}
 }
}

/**************************************************************************************************
*   RFdecode(); RX - See 'rf.h' Header file for Description
**************************************************************************************************/
static char RFdecode(char input[])
{
 unsigned char temp[4];
 temp[0] = rx_lookup(input[0] >> 2);
 temp[1] = rx_lookup(((input[0] & 0x03) << 4) | (input[1] >> 4));
 temp[2] = rx_lookup(((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6));
 temp[3] = rx_lookup(input[2] & 0x3F);
 
 if ((temp[0] == 0xFF) || (temp[1] == 0xFF) || (temp[2] == 0xFF) || (temp[3] == 0xFF))
	return 0;								// Return with Bad Decode
 else {
	RFrxBuff [(RFrxtemp & (RFrxSize-1))] = (temp[0] << 4) | temp[1];
	RFrxtemp++;
	RFrxBuff [(RFrxtemp & (RFrxSize-1))] = ((temp[2] << 4) | temp[3]);
	RFrxtemp++;
 }
 return 1;								// Return with Good Decode
}

static unsigned char rx_lookup(unsigned char data)
{
 if (data > 52) 
	return 0xff;
 else
	return RFrxTABLE[data];
}



