/*********************************************
*
* RFM01 simple library
* 
* $HeadURL: svn://www.mlab.cz/home/MLAB/Designs/duckweed_collector/SW/library/RF02/RF02.cpp $
* $Id: RF02.cpp 2129 2011-08-18 18:40:43Z kakl $
*
* code based on the code of "benedikt k." and "contrechoc" 
*
* tested on arduino 22
*
*********************************************/

#include <avr/io.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 2 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

unsigned char  _rx_buffer[32];  // recv buf

#include <util/delay.h>

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(0x0000);     // cargo cult settings 
        rf01_trans(0x8000|0x1000|0x70|0x02); //band
        rf01_trans(0xA640); // freq
        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);
                sbi(RF_PORT, SCK);
                sbi(RF_PORT, SCK);
                wert<<=1;
                cbi(RF_PORT, SCK);
        }
        sbi(RF_PORT, CS);
}

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

        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");
                        cbi(RF_PORT, SCK);
                        asm("nop");
                        asm("nop");
                        asm("nop");
                }
                *data++=c;
                sbi(RF_PORT, CS);
                        asm("nop");
                        asm("nop");
                        asm("nop");
        }
}