#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/crc16.h>
#include <portbits.h>
#include "global.h"
#include "rfm12b.h"
//#include "leds.h"
#include "param.h"
#define F_CPU 16000000UL
#include <util/delay.h>

#define USE_868				// notwendig für die 868MHz Variante

#define USE_soft_spi				// notwendig für SOFT SPI Variante



/*
#define RF_PORT	PORTB
#define RF_DDR	DDRB
#define RF_PIN	PINB

#define SDI		3
#define SCK		5
#define CS		2
#define SDO		4
*/
#define MAX_BUF		128		// maximale Paketgröße (muss >= dem Wert in der main.c sein)

unsigned short rf12_trans(unsigned short wert)
{
#ifdef USE_soft_spi
/*	
	unsigned char i;

	cbi(PORTD, CS);
	for (i=0; i<16; i++)
	{	if (wert&32768)
			sbi(PORTC, SDI);
		else
			cbi(PORTC, SDI);
		wert<<=1;
		if (PINC&(1<<SDO))
			wert|=1;
		sbi(PORTD, SCK);
		asm("nop");
		asm("nop");
		cbi(PORTD, SCK);
	}
	sbi(PORTD, CS);
	return wert;
*/

  unsigned short werti=0;
  unsigned char i;

  cbi(PORTD, CS);
  for (i=0; i<16; i++)
  {  if (wert&32768)
      sbi(PORTC, SDI);
    else
      cbi(PORTC, SDI);
    werti<<=1;
    if (PINC&(1<<SDO))
      werti|=1;
    sbi(PORTD, SCK);
    wert<<=1;
    		asm("nop");
		asm("nop");
    		
		
	cbi(PORTD, SCK);
  }
  sbi(PORTD, CS);
  return werti;

#else
	CONVERTW val;
	val.w=wert;
	cbi(RF_PORT, CS);
	SPDR = val.b[1];
	while(!(SPSR & (1<<SPIF)));
	val.b[1]=SPDR;
	SPDR = val.b[0];
	while(!(SPSR & (1<<SPIF)));
	val.b[0]=SPDR;
	sbi(RF_PORT, CS);
	return val.w;
#endif




}

void rf12_init(void)
{
#ifdef USE_soft_spi


#else
	RF_PORT=(1<<CS);
	RF_DDR&=~((1<<SDO));
	RF_DDR|=(1<<SDI)|(1<<SCK)|(1<<CS);
	SPCR=(1<<SPE)|(1<<MSTR);
#endif


	for (unsigned char i=0; i<20; i++)
		_delay_ms(10);					// wait until POR done
	rf12_trans(0xC060);					// AVR CLK: 2MHz
	rf12_trans(0xC0C0);					// AVR CLK: 5MHz
	rf12_trans(0xC0E0);					// AVR CLK: 10MHz
#ifdef USE_868
	rf12_trans(0x80E7);					// Enable FIFO, 868MHz
#else
	rf12_trans(0x80D7);					// Enable FIFO, 433MHz
#endif
	rf12_trans(0xC2AB);					// Data Filter: internal
	rf12_trans(0xCA81);					// Set FIFO mode
	rf12_trans(0xE000);					// disable wakeuptimer
	rf12_trans(0xC800);					// disable low duty cycle
	rf12_trans(0xC4F7);					// AFC settings: autotuning: -10kHz...+7,5kHz
}

void rf12_config(unsigned short baudrate, unsigned char channel, unsigned char power, unsigned char environment)
{
#ifdef USE_868
	if (channel==0)
		rf12_setfreq(RF12FREQ868(868.3));	 // Sende/Empfangsfrequenz auf 868,3MHz einstellen
	else if (channel==1)
		rf12_setfreq(RF12FREQ868(869.0));	 // Sende/Empfangsfrequenz auf 869,0MHz einstellen
	else if (channel==2)
		rf12_setfreq(RF12FREQ868(869.525));	 // Sende/Empfangsfrequenz auf 869,525MHz einstellen
	else
		rf12_setfreq(RF12FREQ868(869.85));	 // Sende/Empfangsfrequenz auf 869,85MHz einstellen
#else
	rf12_setfreq(RF12FREQ(433.4)+128*channel); // Sende/Empfangsfrequenz auf 433,4MHz + channel * 325kHz einstellen
#endif
   	rf12_setpower(0, 5);					// 6mW Ausgangangsleistung, 90kHz Frequenzshift
   	rf12_setbandwidth(4, environment, 1);	// 200kHz Bandbreite, Verstärkung je nach Umgebungsbedingungen, DRSSI threshold: -97dBm (-environment*6dB)
	rf12_setbaud(baudrate);					// Baudrate
}

void rf12_rxmode(void)
{
	rf12_trans(0x82C8);					// RX on
	rf12_trans(0xCA81);					// set FIFO mode
	_delay_ms(.8);
	rf12_trans(0xCA83);					// enable FIFO: sync word search
}

void rf12_stoprx(void)
{
	rf12_trans(0x8208);					// RX off
	_delay_ms(1);
}

void rf12_setbandwidth(unsigned char bandwidth, unsigned char gain, unsigned char drssi)
{
	rf12_trans(0x9500|((bandwidth&7)<<5)|((gain&3)<<3)|(drssi&7));
}

void rf12_setfreq(unsigned short freq)
{	if (freq<96)						// 430,2400MHz
		freq=96;
	else if (freq>3903)					// 439,7575MHz
		freq=3903;
	rf12_trans(0xA000|freq);
}

void rf12_setbaud(unsigned short baud)
{
	if (baud<664)
		baud=664;
	if (baud<5400)						// Baudrate= 344827,58621/(R+1)/(1+CS*7)
		rf12_trans(0xC680|((43104/baud)-1));	// R=(344828/8)/Baud-1
	else
		rf12_trans(0xC600|((344828UL/baud)-1));	// R=344828/Baud-1
}

void rf12_setpower(unsigned char power, unsigned char mod)
{	
	rf12_trans(0x9800|(power&7)|((mod&15)<<4));
}

static inline void rf12_ready(void)
{
	
	/*cbi(RF_cl_PORT, CS);
	asm("nop");
	asm("nop");
	while (!(RF_io_PIN&(1<<SDO)));			// wait until FIFO ready
    setReceiveMode();
    sbi(RF_cl_PORT, CS);  
  
	cbi(RF_PORT, SDI);
	cbi(RF_PORT, CS);
	asm("nop");
	while (!(PINC&(1<<SDO))); // wait until FIFO ready
*/

	/*
	cbi(PORTD, CS);
	asm("nop");
	asm("nop");
	while (!(PINC&(1<<SDO)));			// wait until FIFO ready
 */ 
 	cbi(PORTC, SDI);
	cbi(PORTD, CS);
	asm("nop");
	asm("nop");
	while (!(PINC&(1<<SDO)));


	
	
}

unsigned rf12_data(void)
{	unsigned char status;
	cbi(PORTD, CS);
	asm("nop");
	asm("nop");
	status=PINC&(1<<SDO);
	sbi(PORTD, CS);
	if(status)
		return 1;
	else
		return 0;
}

void rf12_txbyte(unsigned char val)
{
	rf12_ready();
	rf12_trans(0xB800|val);
	if ((val==0x00)||(val==0xFF))		// Stuffbyte einfügen um ausreichend Pegelwechsel zu haben
	{	rf12_ready();
		rf12_trans(0xB8AA);
	}
}

unsigned char rf12_rxbyte(void)
{	unsigned char val;
	rf12_ready();
	val =rf12_trans(0xB000);
	if ((val==0x00)||(val==0xFF))		// Stuffbyte wieder entfernen
	{	rf12_ready();
		rf12_trans(0xB000);
	}
	return val;
}

/*
void rf12_txdata(unsigned char *data, unsigned char number, unsigned char status, unsigned char id)
{	unsigned char i;
	unsigned short crc;
	//LED_TX=1;
	rf12_trans(0x8238);					// TX on
	rf12_ready();
	rf12_trans(0xB8AA);					// Sync Data
	rf12_ready();
	rf12_trans(0xB8AA);
	rf12_ready();
	rf12_trans(0xB8AA);
	rf12_ready();
	rf12_trans(0xB82D);
	rf12_ready();
	rf12_trans(0xB8D4);
	crc=_crc_ccitt_update (0, status);
	rf12_txbyte(status);				// Status
	crc=_crc_ccitt_update (crc, number);
	rf12_txbyte(number);				// Anzahl der zu sendenden Bytes übertragen
	if (number)							// nur Status ? Dann keine Daten senden
	{	crc=_crc_ccitt_update (crc, id);
		rf12_txbyte(id);				// Paket ID
		for (i=0; i<number; i++)
		{	rf12_txbyte(*data);
			crc=_crc_ccitt_update (crc, *data);
			data++;
		}
	}
	rf12_txbyte(crc);					// Checksumme hinterher senden
	rf12_txbyte(crc/256);				// Checksumme hinterher senden
	rf12_txbyte(0);						// dummy data
	rf12_txbyte(0);						// dummy data
	rf12_trans(0x8208);					// TX off
	//LED_TX=0;
}
*/
/*
unsigned char rf12_rxdata(unsigned char *data, unsigned char *status, unsigned char *id)
{	unsigned char i, number;
	unsigned short crc, crcref;
	//LED_RX=1;
	*status=rf12_rxbyte();				// Status
	crc=_crc_ccitt_update (0, *status);
	number=rf12_rxbyte();				// Anzahl der zu empfangenden Bytes
	crc=_crc_ccitt_update (crc, number);
	if (number>MAX_BUF)
		number=MAX_BUF;
	if (number)
	{	*id=rf12_rxbyte();				// Paketnummer
		crc=_crc_ccitt_update (crc, *id);
		for (i=0; i<number; i++)
		{	*data=rf12_rxbyte();
			crc=_crc_ccitt_update (crc, *data);
			data++;
		}
	}
	crcref=rf12_rxbyte();				// CRC empfangen
	crcref|=rf12_rxbyte()*256;			// CRC empfangen
	rf12_trans(0xCA81);					// restart syncword detection:
	rf12_trans(0xCA83);					// enable FIFO
	//LED_RX=0;
	if (crcref!=crc)
		return 255;						// checksum error
	else
		return number;					// data ok
}
*/
void rf12_rxdata_test(unsigned char *data, unsigned char number)
{

	unsigned char i;
	rf12_trans(0x82C8);					// RX on
	rf12_trans(0xCA81);					// set FIFO mode
	_delay_ms(.8);
	rf12_trans(0xCA83);					// enable FIFO: sync word search
	for (i=0; i<number; i++)
	{	rf12_ready();
		*data++=rf12_trans(0xB000);
	}


	rf12_trans(0x8208);
}


void rf12_txdata_TEST(char *data, unsigned char number)
{
  unsigned char i;
     
  rf12_trans(0x8238);          // TX on
  rf12_ready();
  rf12_trans(0xB8AA);          // Sync Data
  rf12_ready();
  rf12_trans(0xB8AA);
  rf12_ready();
  rf12_trans(0xB8AA);
  rf12_ready();
  rf12_trans(0xB82D);
  rf12_ready();
  rf12_trans(0xB8D4);

    for (i=0; i<number; i++)
    {  
	  rf12_txbyte(*data);
      data++;
    }

  rf12_txbyte(0);            // dummy data
  rf12_txbyte(0);            // dummy data
  rf12_trans(0x8208);          // TX off

  rf12_trans(0x0000);          // enable FIFO

}

