/*********************************************
*
* draft version v 0.1, experimental
*
* code based on the code of "benedikt k."
* this was an avr project from the site: http://www.mikrocontroller.net/topic/65984#541030
*
*
* code should be matched with RF01
*
* up to now no transmission between the RF12 modules and Jeelabs.com RF12 lib
*
* this code has worked: transmitting using atmega168 and atmega328 in combination with RF01s and RF02s
*
* arduino 18
*
* five march, contrechoc.com, june 2010 , october 2010
*
*
*********************************************/

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <stdlib.h>

#include "rf01.h"

#define F_CPU 16000000UL
#include <util/delay.h>

#define RF_PORT	PORTB
#define RF_DDR	DDRB
#define RF_PIN	PINB

#define SDI		5	// RF01  SDI,  arduino  13 cannot be changed
#define SCK		4	// RF01  SCK,  arduino  12 cannot be changed
#define CS		3	// RF01  nSEL, arduino  11 cannot be changed
#define SDO		2	// RF01  SDO,  arduino  10 cannot be changed
//----------------- // RF01  niRQ, arduino  02 cannot be changed
//------------------// RF01  nFFS: 1-10k Pullup too Vcc

#define LED_PORT	PORTD
#define LED_DDR		DDRD
#define LED_PIN		PIND

#define LED0	5
#define LED1	6 //not used

// nFFS: 1-10k Pullup an Vcc !!!

#ifndef cbi
#define cbi(sfr, bit)     (_SFR_BYTE(sfr) &= ~_BV(bit)) 
#endif
#ifndef sbi
#define sbi(sfr, bit)     (_SFR_BYTE(sfr) |= _BV(bit))  
#endif

#ifndef cLED0
#define cLED0()     (LED_PORT &= ~(1<<LED0)) 
#endif
#ifndef sLED0
#define sLED0()     (LED_PORT |= (1<<LED0) )  
#endif

#ifndef cLED1
#define cLED1()     (LED_PORT &= ~(1<<LED1)) 
#endif
#ifndef sLED1
#define sLED1()     (LED_PORT |= (1<<LED1) )  
#endif

// maximum receive buffer
#define RF_MAX   32
unsigned char  rf01_buf[RF_MAX];  // recv buf

#include <util/delay.h>

void rf01_receive(){
	rf01_rxdata(rf01_data, 32);
}

void rf01_prepAll(){
	rf01_init();					// ein paar Register setzen (z.B. CLK auf 10MHz)
	rf01_setfreq(RF01FREQ(434));	// Sende/Empfangsfrequenz auf 433,92MHz einstellen
	rf01_setbandwidth(4);			// 4 200kHz Bandbreite
	rf01_setreceiver(2,4);			//2,4 -6dB Verstärkung, DRSSI threshold: -79dBm 
	rf01_setbaud(57600);			// 19200 Baud

}

static unsigned char sdrssi, sgain;

void rf01_trans(unsigned short wert)
{	unsigned char i;

	cbi(RF_PORT, CS);
	for (i=0; i<16; i++)
	{	if (wert&32768)
			sbi(RF_PORT, SDI);
		else
			cbi(RF_PORT, SDI);
		sbi(RF_PORT, SCK);
		wert<<=1;
		_delay_us(0.2);
		cbi(RF_PORT, SCK);
	}
	sbi(RF_PORT, CS);
}

void rf01_init(void)
{	unsigned char i;

	RF_PORT=(1<<CS);
	RF_DDR=(1<<SDI)|(1<<SCK)|(1<<CS);

	for (i=0; i<11; i++)
		_delay_ms(10);			// wait until POR done

	rf01_trans(0xC2E0);			// AVR CLK: 10MHz
	rf01_trans(0xC42B);			// Data Filter: internal
	rf01_trans(0xCE88);			// FIFO mode
	rf01_trans(0xC6F7);			// AFC settings: autotuning: -10kHz...+7,5kHz
	rf01_trans(0xE000);			// disable wakeuptimer
	rf01_trans(0xCC00);			// disable low duty cycle

	LED_DDR= 0xFF;//(1<<LED0)|(1<<LED1);
	blinkLED();

}

void rf01_setbandwidth(unsigned char bandwidth)
{
	rf01_trans(0x8970|((bandwidth&7)<<1));
}

void rf01_setreceiver(unsigned char gain, unsigned char drssi)
{
	sdrssi=drssi;
	sgain=gain;
}

void rf01_setfreq(unsigned short freq)
{	if (freq<96)				// 430,2400MHz
		freq=96;
	else if (freq>3903)			// 439,7575MHz
		freq=3903;
	rf01_trans(0xA000|freq);
}

void rf01_setbaud(unsigned short baud)
{
	if (baud<336)
		return;
	if (baud<5400)				// Baudrate= 344827,58621/(R+1)/(1+CS*7)
		rf01_trans(0xC880|((43104/baud)-1));
	else
		rf01_trans(0xC800|((344828UL/baud)-1));

	rf01_trans(0xC806);
}

void rf01_rxdata(unsigned char *data, unsigned char number)
{	unsigned char i,j,c;

	rf01_trans(0xC0C1|((sgain&3)<<4)|((sdrssi&7)<<1));	// RX on
	rf01_trans(0xCE89);			// set FIFO mode
	rf01_trans(0xCE8B);			// enable FIFO
	cbi(RF_PORT, SDI);
	for (i=0; i<number; i++)
	{	cbi(RF_PORT, CS);
		while (!(RF_PIN&(1<<SDO))); // wait until data in FIFO
		for (j=0; j<16; j++)	// read and discard status register
		{	sbi(RF_PORT, SCK);
			asm("nop");
			cbi(RF_PORT, SCK);
		}
		c=0;
		for (j=0; j<8; j++)
		{	c<<=1;
			if (RF_PIN&(1<<SDO))
				c|=1;
			sbi(RF_PORT, SCK);
			_delay_us(0.2);
			cbi(RF_PORT, SCK);
		}
		*data++=c;
		sbi(RF_PORT, CS);
	}
	//blinkLED();
	rf01_trans(0xC0C0|((sgain&3)<<4)|((sdrssi&7)<<1));	// RX off
}

void blinkLED(void){
	for (unsigned char i=0; i<15; i++)
		_delay_ms(5);
	sLED1();

	for (unsigned char i=0; i<15; i++)
		_delay_ms(5);
	cLED1();

}

void makePulse(int numberOfPulses){
	if ( numberOfPulses > 0)
	{
	for (unsigned char i=0; i<numberOfPulses; i++)
		{
			_delay_ms(20);
			sLED0();
			_delay_ms(20);
			cLED0();			
		}
		_delay_ms(50);
		}

}

