/*********************************************
*
* 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


#ifndef cbi
#define cbi(sfr, bit)     (_SFR_BYTE(sfr) &= ~_BV(bit)) 
#endif
#ifndef sbi
#define sbi(sfr, bit)     (_SFR_BYTE(sfr) |= _BV(bit))  
#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, 23); //!!!32
}

static unsigned char sdrssi, sgain;

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

        for (unsigned char 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(0xC6F7);                     // AFC settings: autotuning: -10kHz...+7,5kHz
//      rf01_trans(0xE000);                     // disable wakeuptimer
//      rf01_trans(0xCC00);                     // disable low duty cycle
//      rf01_trans(0x8978); // band 433MHz, enable crystal + 12pF, 200kHz bandwidth

        rf01_trans(0x0000); 
//      rf01_trans(0x898A); // band 433MHz, 134kHz bandwidth
        rf01_trans(0x8000|0x1000|0x70|0x02); //band
        rf01_trans(0xA640); //434MHz    
        rf01_trans(0xC823); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 9600 Bd
        rf01_trans(0xC69B);     
        rf01_trans(0xC42A);                     
        rf01_trans(0xC240); //*                 
        rf01_trans(0xC080);      //*            
        rf01_trans(0xCE88);     // FIFO mode
        rf01_trans(0xCE8B);         //*
        rf01_trans(0xC081);         //*
}

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_rxdata(unsigned char *data, unsigned char number)
{       unsigned char i,j,c;

  //!!! 
//      sgain=2;                      //2,4 -6dB LNA gain, DRSSI threshold: -79dBm
//      sdrssi=4;
//!!!   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);
                        asm("nop");
                        asm("nop");
                        asm("nop");
        for (i=0; i<number; i++)
        {       cbi(RF_PORT, CS);
                        asm("nop");
                        asm("nop");
                        asm("nop");
                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");
                        asm("nop");
                        asm("nop");
                        cbi(RF_PORT, SCK);
                        asm("nop");
                        asm("nop");
                        asm("nop");
                }
                c=0;
                for (j=0; j<8; j++)
                {       c<<=1;
                        if (RF_PIN&(1<<SDO))
                                c|=1;
                        sbi(RF_PORT, SCK);
                        asm("nop");
                        asm("nop");
                        asm("nop");
//!!!                   _delay_us(0.2);
                        cbi(RF_PORT, SCK);
                        asm("nop");
                        asm("nop");
                        asm("nop");
                }
                *data++=c;
                sbi(RF_PORT, CS);
                        asm("nop");
                        asm("nop");
                        asm("nop");
        }
//!!!   rf01_trans(0xC0C0|((sgain&3)<<4)|((sdrssi&7)<<1));      // RX off
}