/*----------------------------------------------------------------------------
 Copyright:      
 Author:         
 Remarks:        
 known Problems: none
 Version:        16.12.2009
 Description:    RF22 Funkmodule
------------------------------------------------------------------------------*/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "rf22.h"

#include "usart.h"

//###############################################################################################################
static inline unsigned char rf22_trans(unsigned char addr, unsigned char data)
{	
	RF22_PORT &= ~(1<<CS);
	SPDR = addr;
	while(!(SPSR & (1<<SPIF)));
	SPDR = data;
	while(!(SPSR & (1<<SPIF)));
	RF22_PORT |= (1<<CS);
	return SPDR;
}


//###############################################################################################################
void rf22_write(unsigned char addr, unsigned char data)
{
	rf22_trans(128|addr,data);
}


//###############################################################################################################
unsigned char rf22_read(unsigned char addr)
{
	return rf22_trans(addr&127,0);
}


//###############################################################################################################
void rf22_init(void)
{
	DDRB |= 44;
	SPCR=(1<<SPE)|(1<<MSTR);
	SPSR|=(1<<SPI2X);
	
	for(unsigned long a = 0;a<100000;a++){asm("nop");}; // wait until POR done
    rf22_write(0x07, 0x80);		// software reset
	for(unsigned long a = 0;a<100000;a++){asm("nop");}; // wait until software reset done

    rf22_write(0x05, 0x02);		// valid packed received interrupt on

    rf22_write(0x06, 0x00);		// all interrupts off
    rf22_write(0x07, 0x01);		// operating mode: ready mode
    rf22_write(0x09, 0x7f);		// xtal load capacitance
    rf22_write(0x0A, 0x02);		// uC CLK: 10MHz
    
    rf22_write(0x0b, 0xf2);		// GPIO0: TX_ANT - f2 
    rf22_write(0x0c, 0xf5);		// GPIO1: RX ANT - f5
    rf22_write(0x0d, 0x00);		// GPIO2: uC Clock out
    rf22_write(0x0e, 0x00);		
    rf22_write(0x0f, 0x70);		// ADC Input: GND
    rf22_write(0x10, 0x00);		// ADC offset: 0
    rf22_write(0x12, 0x00);		// temp sensor calibration off
    rf22_write(0x13, 0x00);		// temp sensor offset: 0
    rf22_write(0x1d, 0x40);		// enable AFC
    rf22_write(0x1e, 0x0A);		// afc timing
	rf22_write(0x1f, 0x03);		// afc timing
	rf22_write(0x55, 0x0C);      // CHRISTOPH


#elif RF22_BAUD_38400
	rf22_write(0x1C, 0x0A);		// IF bandwidth
	rf22_write(0x1d, 0x40);		// IF bandwidth
	rf22_write(0x20, 0x68);		// Clock Recovery Oversampling Rate
	rf22_write(0x21, 0x01);		// Clock Recovery Offset 2
	rf22_write(0x22, 0x3A);		// Clock Recovery Offset 1
	rf22_write(0x23, 0x93);		// Clock Recovery Offset 0
	rf22_write(0x24, 0x11);		// Clock Recovery Timing Loop Gain 1
	rf22_write(0x25, 0xE6);		// Clock Recovery Timing Loop Gain 0
	rf22_write(0x2A, 0x2C);
	

	rf22_write(0x27, 0x10);		// RSSI Threashold: -120dB

    rf22_write(0x30, 0x8c);		// data access: RX/TX packet handling, enable crc: CCIT
    rf22_write(0x32, 0xcf);		// header check enable
    rf22_write(0x33, 0x46);		// 2 word synchronisation
    rf22_write(0x34, 0x10);		// preamble length: 16 nibbles, = 64bits
    rf22_write(0x35, 0x30);		// preamble detection control: 6 nibbles = 24bits
    rf22_write(0x36, 0x2d);		// sync word 3
    rf22_write(0x37, 0xd4);		// sync word 2
    rf22_write(0x38, 0xAA);		// sync word 1
    rf22_write(0x39, 0xAA);		// sync word 0
    rf22_write(0x3a, 'h');		// transmit header 3
    rf22_write(0x3b, 'o');		// transmit header 2
    rf22_write(0x3c, 'p');		// transmit header 1
    rf22_write(0x3d, 'e');		// transmit header 0
    rf22_write(0x3e, 17);		// packet length
    rf22_write(0x3f, 'h');		// check header 3
    rf22_write(0x40, 'o');		// check header 2
    rf22_write(0x41, 'p');		// check header 1
    rf22_write(0x42, 'e');		// check header 0
    rf22_write(0x43, 0xff);		// header enable mask 3
    rf22_write(0x44, 0xff);		// header enable mask 2
    rf22_write(0x45, 0xff);		// header enable mask 1
    rf22_write(0x46, 0xff);		// header enable mask 0

	rf22_write(0x69, 0x60);		// AGC on
    rf22_write(0x6a, 0x0b);		// agc override 2
	rf22_write(0x6d, 0x0F);		// tx power: +17dBm
	
	rf22_write(0x6E,0x09);		// set baud high alt 0x13
	rf22_write(0x6F,0xd5);		// set baud low alt 0xa9

    rf22_write(0x70, 0x0C);		// modulation control alt 0x2C
    rf22_write(0x71, 0x23);		// modulation control 2: FIFO mode, OOK  //0x21 / 0x00
	
    rf22_write(0x72, 0x50);		// frequency deviation: 45kHz
	rf22_write(0x73, 0x00);		// offset: 0
	rf22_write(0x74, 0x00);		// offset: 0
	
	rf22_write(0x79, 0x0);		// frequency hopping off
    rf22_write(0x7a, 0x0);		// frequency hopping off
#warning 38400 BAUD

#elif defined RF22_BAUD_40000
	rf22_write(0x1C, 0x07);		// IF bandwidth
	rf22_write(0x1d, 0x40);		// IF bandwidth
	rf22_write(0x20, 0xd0);		// Clock Recovery Oversampling Rate
	rf22_write(0x21, 0x00);		// Clock Recovery Offset 2
	rf22_write(0x22, 0x9d);		// Clock Recovery Offset 1
	rf22_write(0x23, 0x49);		// Clock Recovery Offset 0
	rf22_write(0x24, 0x10);		// Clock Recovery Timing Loop Gain 1
	rf22_write(0x25, 0x7B);		// Clock Recovery Timing Loop Gain 0
	rf22_write(0x2A, 0x28);

	rf22_write(0x27, 0x10);		// RSSI Threashold: -120dB

    rf22_write(0x30, 0x8c);		// data access: RX/TX packet handling, enable crc: CCIT
    rf22_write(0x32, 0xcf);		// header check enable
    rf22_write(0x33, 0x46);		// 2 word synchronisation
    rf22_write(0x34, 0x10);		// preamble length: 16 nibbles, = 64bits
    rf22_write(0x35, 0x30);		// preamble detection control: 6 nibbles = 24bits
    rf22_write(0x36, 0x2d);		// sync word 3
    rf22_write(0x37, 0xd4);		// sync word 2
    rf22_write(0x38, 0xAA);		// sync word 1
    rf22_write(0x39, 0xAA);		// sync word 0
    rf22_write(0x3a, 'h');		// transmit header 3
    rf22_write(0x3b, 'o');		// transmit header 2
    rf22_write(0x3c, 'p');		// transmit header 1
    rf22_write(0x3d, 'e');		// transmit header 0
    rf22_write(0x3e, 17);		// packet length
    rf22_write(0x3f, 'h');		// check header 3
    rf22_write(0x40, 'o');		// check header 2
    rf22_write(0x41, 'p');		// check header 1
    rf22_write(0x42, 'e');		// check header 0
    rf22_write(0x43, 0xff);		// header enable mask 3
    rf22_write(0x44, 0xff);		// header enable mask 2
    rf22_write(0x45, 0xff);		// header enable mask 1
    rf22_write(0x46, 0xff);		// header enable mask 0

	rf22_write(0x69, 0x60);		// AGC on
    rf22_write(0x6a, 0x0b);		// agc override 2
	rf22_write(0x6d, 0x0F);		// tx power: +17dBm
	
	rf22_write(0x6E,0x9d);		// set baud high alt 0x13
	rf22_write(0x6F,0x49);		// set baud low alt 0xa9

    rf22_write(0x70, 0x2C);		// modulation control alt 0x2C
    rf22_write(0x71, 0x23);		// modulation control 2: FIFO mode, OOK  //0x21 / 0x00
	
    rf22_write(0x72, 0x50);		// frequency deviation: 45kHz
	rf22_write(0x73, 0x00);		// offset: 0
	rf22_write(0x74, 0x00);		// offset: 0
	
	rf22_write(0x79, 0x0);		// frequency hopping off
    rf22_write(0x7a, 0x0);		// frequency hopping off
#warning 40000 BAUD

#elif defined RF22_BAUD_200000

rf22_write(0x75, 0x73);
rf22_write(0x76, 0x70);
rf22_write(0x77, 0x80);
rf22_write(0x6E, 0x33);
rf22_write(0x6E, 0x33);
rf22_write(0x70, 0x0C);
rf22_write(0x58, 0xED);
rf22_write(0x72, 0xE0);
rf22_write(0x71, 0x26);
rf22_write(0x1C, 0x8E);
rf22_write(0x20, 0x3C);
rf22_write(0x21, 0x02);
rf22_write(0x22, 0x22);
rf22_write(0x23, 0x22);
rf22_write(0x24, 0x02);
rf22_write(0x25, 0xDA);
rf22_write(0x1D, 0x40);
rf22_write(0x1E, 0x02);
rf22_write(0x2A, 0x50);
rf22_write(0x1F, 0x03);
rf22_write(0x69, 0x60);
rf22_write(0x2C, 0x28);
rf22_write(0x2D, 0x06);
rf22_write(0x2E, 0x27);


#warning 200kb BAUD

#else
	rf22_write(0x1C, 0x9C);		// IF bandwidth
	rf22_write(0x20, 0x96);		// Clock Recovery Oversampling Rate
	rf22_write(0x21, 0x00);		// Clock Recovery Offset 2
	rf22_write(0x22, 0xDA);		// Clock Recovery Offset 1
	rf22_write(0x23, 0x74);		// Clock Recovery Offset 0
	rf22_write(0x24, 0x00);		// Clock Recovery Timing Loop Gain 1
	rf22_write(0x25, 0xB1);		// Clock Recovery Timing Loop Gain 0
	rf22_write(0x2A, 0x50);

	rf22_write(0x27, 0x10);		// RSSI Threashold: -120dB

    rf22_write(0x30, 0x8c);		// data access: RX/TX packet handling, enable crc: CCIT
    rf22_write(0x32, 0xff);		// header check enable
    rf22_write(0x33, 0x42);		// 2 word synchronisation
    rf22_write(0x34, 0x10);		// preamble length: 16 nibbles, = 64bits
    rf22_write(0x35, 0x30);		// preamble detection control: 6 nibbles = 24bits
    rf22_write(0x36, 0x2d);		// sync word 3
    rf22_write(0x37, 0xd4);		// sync word 2
    rf22_write(0x38, 0xAA);		// sync word 1
    rf22_write(0x39, 0xAA);		// sync word 0
    rf22_write(0x3a, 'h');		// transmit header 3
    rf22_write(0x3b, 'o');		// transmit header 2
    rf22_write(0x3c, 'p');		// transmit header 1
    rf22_write(0x3d, 'e');		// transmit header 0
    rf22_write(0x3e, 17);		// packet length
    rf22_write(0x3f, 'h');		// check header 3
    rf22_write(0x40, 'o');		// check header 2
    rf22_write(0x41, 'p');		// check header 1
    rf22_write(0x42, 'e');		// check header 0
    rf22_write(0x43, 0xff);		// header enable mask 3
    rf22_write(0x44, 0xff);		// header enable mask 2
    rf22_write(0x45, 0xff);		// header enable mask 1
    rf22_write(0x46, 0xff);		// header enable mask 0
	rf22_write(0x58, 0x80);

	rf22_write(0x69, 0x60);		// AGC on
    rf22_write(0x6a, 0x0b);		// agc override 2
	rf22_write(0x6d, 0x0F);		// 0x0F tx power: +17dBm  RFM23 +13dBm
	
	rf22_write(0x6E,0x0A);		// set baud high alt 0x13
	rf22_write(0x6F,0x3D);		// set baud low alt 0xa9

    rf22_write(0x70, 0x0C);		// modulation control alt 0x2c
    rf22_write(0x71, 0x22);		// modulation control 2: FIFO mode, OOK  //0x21 / 0x00
	
    rf22_write(0x72, 0xA0);		// frequency deviation: 45kHz
	rf22_write(0x73, 0x00);		// offset: 0
	rf22_write(0x74, 0x00);		// offset: 0
	
	rf22_write(0x76, 0x70);
	rf22_write(0x77, 0x80);
	rf22_write(0x79, 0x0);		// frequency hopping off
    rf22_write(0x7a, 0x0);		// frequency hopping off
#warning 2400 BAUD

#endif


#ifdef BAND_868
	rf22_write(0x75, 0x73);		// 860-880MHz range
#else
	rf22_write(0x75, 0x53);		// 430-440MHz range
#endif


}


//###############################################################################################################
void rf22_rxmode(void)
{	
	rf22_read(0x03);			// clear interrupt status
    rf22_read(0x04);			// clear interrupt status
	rf22_write(0x07, 0x01);		// to_ready_mode();
	
	rf22_write(0x07, 0x01);		// to_ready_mode();
	rf22_write(0x7e, 0x17);		// threshold for rx almost full, interrupt when 1 byte received
	
	rf22_write(0x08, 0x03);		// clear RX fifo
	rf22_write(0x08, 0x00);		// clear fifo, disable multi packet
	
	rf22_write(0x07, 0x05);		// RX on
	
    rf22_read(0x03);			// clear interrupt status
    rf22_read(0x04);			// clear interrupt status
}


//###############################################################################################################
void rf22_setfreq(unsigned short freq)
{	
    rf22_write(0x76, (freq&0xFF00)>>8);
    rf22_write(0x77, (freq&0x00FF));
}

//###############################################################################################################
void rf22_sendpacket(unsigned char *data, unsigned char size)
{	
	unsigned char i;

	if (size>64) size=64;
	
	rf22_write(0x07, 0x03);		// switch to ready mode
	rf22_read(0x03);			// clear interrupt status
	rf22_read(0x04);			// clear interrupt status

	rf22_write(0x08, 0x01);		// clear TX fifo
	rf22_write(0x08, 0x00);		// clear TX fifo
	
	rf22_write(0x34, 32);		// premable length: 32 nibbles -> 128 Bits
	rf22_write(0x3e, size);		// packet length
	
	for (i = 0; i<size; i++)
	{    
		rf22_write(0x7f, *data++);
	}
	
	rf22_write(0x05, 0x04);		// enable packet send
	rf22_write(0x07, 0x09);		// TX on
	
	while (nIRQ);
	
	rf22_write(0x07, 0x01);		//	switch to ready mode
}

//###############################################################################################################
void rf22_sendString( const char* str )
{
  rf22_sendpacket((unsigned char*)str, strlen(str));
}

//###############################################################################################################

void rf22_sendInt( int value )
{
  char buffer[10];
  itoa( value, buffer, 10 );
  rf22_sendString( buffer );
}

//###############################################################################################################
unsigned char rf22_getpacket(unsigned char *data)
{	
	unsigned char i, cnt;

	if(rf22_read(0x31)&0x1A)		// receiving a packet
	{
		if ((rf22_read(0x03)&2)&&(!(rf22_read(0x02)&32)))	// packet received & not read
		{
			cnt=rf22_read(0x4B);		// packet length
			
			for (i=0; i<cnt; i++)		// Daten (cnt - 2 für CRC)
			{
				*data++=rf22_read(0x7f);
			}
			
			rf22_rxmode();	
			return (cnt);
		}
	}
	return 0;
}
