/*********************************************
*
* 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, 2010, june
*
*
*********************************************/


#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
 
 #include <string.h>
 
#include "rf02.h"
#include <util/delay.h>

#define F_CPU 16000000UL
 
#define RF_PORT PORTB
#define RF_DDR  DDRB
#define RF_PIN  PINB

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

#define LED0    4 -- PD4
#define LED1    2 -- PD2

#define SDI             0        // SDI,  -> RF02   Atmega PB0 Arduino 8
#define SCK             1       // SCK,  -> RF02   Atmega PB1 Arduino 9 
#define CS              2       // nSEL, -> RF02   Atmega PB2 Arduino 10 
#define IRQ             4       // nIRQ, <- RF02   Atmega PB4 Arduino 12
//------------------// FSK: Pullupto 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



unsigned char test[32]="     55555      \n";

void rf02_changeText( unsigned char* ptr, uint8_t number){

        if (number> 32)number = 32;
                memcpy( test, ptr, number);
 
}

void rf02_prepAll434(){

        rf02_init();                                    // ein paar Register setzen (z.B. CLK auf 10MHz)
        rf02_setfreq(RF02FREQ(434));    // 433,92MHz
        rf02_setpower(1);                               // -12dBm Ausgangangsleistung
        rf02_setmodfreq(3);                             // 120kHz Frequenzshift
        rf02_setbaud(19200);                    // 19200 Baud

}//

void rf02_prepAll(unsigned short freq, uint8_t setPower,uint8_t modFreq,unsigned short baudRate){

        rf02_init();                                    // ein paar Register setzen (z.B. CLK auf 10MHz)
        rf02_setfreq( RF02FREQ(freq) ); // Sende/Empfangsfrequenz auf 433,92MHz einstellen
        
        if ( setPower < 0 ) setPower = 0;
        if ( setPower > 4 ) setPower = 4;
        rf02_setpower(setPower);                                // -12dBm Ausgangangsleistung
        
        if ( modFreq < 0 ) modFreq = 0;
        if ( modFreq > 8 ) modFreq = 8;
        rf02_setmodfreq(modFreq);                               // 120kHz Frequenzshift
        
        rf02_setbaud(baudRate);                 // 19200 Baud

}//


void rf02_sendData(){

        rf02_txdata( test, sizeof test);
}



void rf02_trans(unsigned short  value)
{       uint8_t i;

        cbi(RF_PORT, CS);

        for (i=0; i<16; i++)
        {       if (value&0x8000) //0x8000
                        sbi(RF_PORT, SDI);
                else
                        cbi(RF_PORT, SDI);

                sbi(RF_PORT, SCK);
                value<<=1;
                _delay_us(0.3);
                cbi(RF_PORT, SCK);
        }
        sbi(RF_PORT, CS);
}



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

        for (unsigned char i=0; i<15; i++)
                _delay_ms(10);                  // wait until POR done
        rf02_trans(0xC0E0);                     // power settings
        rf02_trans(0x8A75);// fsk in rfm02 = afc in rf12
//              rf02_trans(0x80C7);
        rf02_trans(0xC2A0);                     // enable tx sync bit, disable low bat detector

        //LED_DDR= 0xFF;
}

void rf02_setmodfreq(uint8_t bandwidth)
{
        rf02_trans(0x8F80|(bandwidth&7));
        //rf02_trans(0x8F70);
}

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

        //rf02_trans(0xA640); //= 434 MHz
}

void rf02_setpower(uint8_t power)
{
        rf02_trans(0xB000|((power&7)<<8));
}

void rf02_setbaud(unsigned short baud)
{
 
        if (baud<1345)
                baud=1345;
        if (baud<19000)
                rf02_trans(0xD240);             // 25% PLL current
        else if (baud<37000)
                rf02_trans(0xD2C0);             // 33% PLL current
        else
                rf02_trans(0xD200);             // 50% PLL current

        //rf02_trans(0xC800|((344828UL/baud)-1));       // Baudrate= 344827,59/(R+1)
 
        rf02_trans(0xC806);
}

void rf02_txdata( unsigned char * data, uint8_t number)
{       
        uint8_t i,value;
        value=0xC6;          //1100 0110
        cbi(RF_PORT, CS);   //nSel

        for (i=0; i<8; i++)
                {       if (value&0x80)   //1000 0000 = 80
                                sbi(RF_PORT, SDI);
                        else
                                cbi(RF_PORT, SDI);

                        sbi(RF_PORT, SCK);
                        value<<=1;
                        _delay_us(0.2);
                        cbi(RF_PORT, SCK);
                }

        rf02_shiftout(0xAA);//10101010
        rf02_shiftout(0xAA);
        rf02_shiftout(0xAA);
        rf02_shiftout(0x2D);//00101101
        rf02_shiftout(0xD4);//11010100
        
        // no checkbit, in experimenting some letters were transmitted wrong!

        for (i=0; i<number; i++)
                rf02_shiftout(*data++);

        sbi(RF_PORT, CS);
        while(RF_PIN&(1<<IRQ));         // wait until transfer done
        rf02_trans(0xC464);                             // TX off after 10us

}

void rf02_shiftout(unsigned char value)
{       uint8_t j;
        for (j=0; j<8; j++)
        {       while(RF_PIN&(1<<IRQ));
        while(!(RF_PIN&(1<<IRQ)));

                if (value&128)             //100101000
                sbi(RF_PORT, SDI);
        else
                cbi(RF_PORT, SDI);
        value<<=1;
    }
}