/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "rfm12B.h"
#include "systick.h"
#include <stdint.h>
#include <stdio.h>

#include "Param.h" 

/* Private variables ---------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
volatile unsigned char delaycnt=0;
volatile unsigned char secflag;

 unsigned char rxbuf[MAX_BUF+1];    // Puffer für empfangene Daten
 unsigned char txbuf[MAX_BUF+1];    // Puffer für zu sendende Daten
unsigned char flags, tx_cnt, rx_cnt, tx_id, tx_status, retrans_cnt;



unsigned char rx_data[41];
uint16_t crc_ccitt_update(uint16_t crc, uint8_t data);
/* Private function prototypes -----------------------------------------------*/
void GPIO_Configuration(void);
//void EXTI_Configuration(void);
void TIM_Configuration(void);
//void NVIC_Configuration(void);


/* Private function prototypes -----------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/*******************************************************************************
* Function Name  : crc_ccitt_update
* Description    : Berechnet Checksumme
* Input          : None
* Output         : None
* Return         : None
* Attention     : None
*******************************************************************************/
#define lo8(x) ((uint16_t)(x)&0xff)
#define hi8(x) ((uint16_t)(x)>>8) 
uint16_t crc_ccitt_update(uint16_t crc, uint8_t data) {

        data ^= lo8 (crc);
        data ^= data << 4;

        return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) ^ ((uint16_t)data << 3));
}
	  


/*******************************************************************************
* Function Name  : TIM2_IRQHandler
* Description    : This function handles TIM2 Handler.
* Input          : None
* Output         : None
* Return         : None
* Attention     : None
*******************************************************************************/
//extern volatile uint8_t delaycnt;
void TIM4_IRQHandler(void){

  static unsigned short secdiv=1000;

   if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
    if (!--secdiv)
    {  
      secdiv=950;
      secflag=1;
    }
    if (delaycnt)
      delaycnt--;
      // Überlauf des Zählregisters
      TIM_ClearITPendingBit(TIM4, TIM_IT_Update);

    }

}

/*******************************************************************************
* Function Name  : EXTI15_10_IRQHandler
* Description    : This function handles External lines 10-15 interrupt request.
* Input          : None
* Output         : None
* Return         : None
* Attention     : None
*******************************************************************************/
//extern void rx_packet(void);
//void EXTI9_5_IRQHandler(void){

  //if(EXTI_GetITStatus(EXTI_Line8) != RESET){
    
    //rx_packet();
    //EXTI_ClearITPendingBit(EXTI_Line8);
      //Toggle Led
      //GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_0))));
    //}
  
//}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
* Attention     : None
*******************************************************************************/
void RFM12_GPIO_Configuration(void)
{

 
   GPIO_InitTypeDef GPIO_InitStructure;

   //Enable SPI1 and GPIOA clocks //
  
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);

   //RFM12 CS
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_Init(GPIOC, &GPIO_InitStructure);
 
   //RFM12 INTERRUPT PIN
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; 
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 	
   GPIO_Init(GPIOC,&GPIO_InitStructure);

   //Configure SPI1 pins: NSS, SCK, MISO and MOSI //
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_Init(GPIOA, &GPIO_InitStructure);



}

/*******************************************************************************
* Function Name  : TIM_Configuration
* Description    : TIM_Configuration program.
* Input          : None
* Output         : None
* Return         : None
* Attention     : Timer für 1 ms
*******************************************************************************/
void TIM_Configuration(void)
{
  #define TIMER_TAKT 10000                                              // Timer wird mit 10kHz getaktet */
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  uint16_t PrescalerValue;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);                // TIMER 2 Takt freigeben

  PrescalerValue = (uint16_t) (SystemCoreClock / TIMER_TAKT) - 1;     // Vorteiler berechnen

  // Timer Grundkonfiguration
  TIM_TimeBaseStructure.TIM_Period = 10;                             // Timer zählt von 0 ... 10 = 1 ms
  //TIM_TimeBaseStructure.TIM_Period = 100;                             // Timer zählt von 0 ... 10 = 10 ms
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);                     // Timer einstellen

  //Timer Vorteiler-Taktkonfiguration
  TIM_PrescalerConfig(TIM4, PrescalerValue, TIM_PSCReloadMode_Immediate); // Auto-Reload

  // Timer Interruptkonfiguration
  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);                        // Interrupt bei Überlauf
  
  // Timer aktivieren
  TIM_Cmd(TIM4, ENABLE);
   
}

/*******************************************************************************
* Function Name  : EXTI_Configuration
* Description    : Configures the different EXTI lines.
* Input          : None
* Output         : None
* Return         : None
* Attention     : None
*******************************************************************************/
//void EXTI_Configuration(void)
//{
//    EXTI_InitTypeDef EXTI_InitStructure;

//    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 
  
  /* Connect EXTI0 Line to PB.08 pin */
//  GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8);
    
//  EXTI_ClearITPendingBit(EXTI_Line8);

//    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    //EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //Falling

//    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
//    EXTI_InitStructure.EXTI_Line = EXTI_Line8;
//    EXTI_InitStructure.EXTI_LineCmd = ENABLE;

//  EXTI_Init(&EXTI_InitStructure); 

//}

/*******************************************************************************
* Function Name  : RFM12_SPI_Init
* Description    : RFM12 SPI
* Input          : None
* Output         : None
* Return         : None
* Attention     : None
*******************************************************************************/
void RFM12_SPI_Init(void) 
{/**/ 
  SPI_InitTypeDef SPI_InitStructure;
  
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  SPI_Cmd(SPI1, DISABLE);

  SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize          = SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL              = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA              = SPI_CPHA_1Edge;
  SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 36MHz/256=140kHz < 400kHz
  SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial     = 7;
  SPI_Init(SPI1, &SPI_InitStructure);

  //SPI_CalculateCRC(SPI1, DISABLE);
  SPI_Cmd(SPI1, ENABLE);

} 

/*******************************************************************************
* Function Name  : NVIC_Configuration
* Description    : Configures the nested vectored interrupt controller.
* Input          : None
* Output         : None
* Return         : None
* Attention     : None
*******************************************************************************/
//void NVIC_Configuration(void)
//{
//    NVIC_InitTypeDef NVIC_InitStructure; 

    // Timer delaycnt
//    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);                            

//    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;    
//    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
//    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
//    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
//    NVIC_Init(&NVIC_InitStructure);

    // Interrupt
  //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);                            
 //   NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;   
 //   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 //   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;    
 //   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 //   NVIC_Init(&NVIC_InitStructure);
     
//}

 
void rf12_init(void){

    /* GPIO configuration ----------------------------------------------------*/
  RFM12_GPIO_Configuration();
    /* SPI configuration -----------------------------------------------------*/
  RFM12_SPI_Init();
    /* NVIC_Configuration ----------------------------------------------------*/
  //NVIC_Configuration();
    /* Timer configuration ---------------------------------------------------*/
  TIM_Configuration();
    /* Interrupt configuration -----------------------------------------------*/
  //EXTI_Configuration();

  delay_ms(200);   // delay 200ms
  

	rf12_trans(0xC060);					// AVR CLK: 2MHz
	rf12_trans(0xC0C0);					// AVR CLK: 5MHz
	rf12_trans(0xC0E0);					// AVR CLK: 10MHz
	rf12_trans(0x80E7);					// Enable FIFO, 868MHz
	//rf12_trans(0x80D7);				// Enable FIFO, 433MHz
	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)
{
 
	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

	//rf12_setfreq(RF12FREQ(433.4)+128*channel); // Sende/Empfangsfrequenz auf 433,4MHz + channel * 325kHz einstellen

   	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_us(800);
	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));
}


void rf12_ready(void){

  unsigned long timeout = 0;
  
  RFM12_CS(0);                             //activate the module
  delay_us(1);               //let it respond
  //__NOP();
  while (!(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6))); // wait until FIFO ready
   //while (!(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5))) // wait until FIFO ready
  //{
    //  if ((timeout++)>100000){break;}
  //}
  RFM12_CS(1);              //deactivate the module

 }

/******************************************************************
 *****************************************************************/
unsigned  rf12_data(void){
  
  unsigned char status;
  RFM12_CS(0);
  delay_us(1);                     //let it respond
  status=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);   //Speichert den Zustand von Pin12 am GPIOA in die 8-bit-Variable Status
  //status=GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5);   //Speichert den Zustand von Pin12 am GPIOA in die 8-bit-Variable Status
  RFM12_CS(1);

  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);
  }
}

/******************************************************************
 *****************************************************************/
uint8_t rf12_rxbyte(void){
  
  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;
   
  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

  rf12_trans(0x0000);          // enable FIFO
}


/******************************************************************
 *****************************************************************/
void rf12_txdata_TEST(unsigned 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

}

void rf12_rxdata_test(unsigned char *data, unsigned char number)
{

	unsigned char i;
	rf12_rxmode();
	
	
	//rf12_trans(0x82C8);					// RX on
	//rf12_trans(0xCA81);					// set FIFO mode
	//delay_us(1);   
	//rf12_trans(0xCA83);					// enable FIFO: sync word search
	for (i=0; i<number; i++)
	{	//rf12_ready();
		//*data++=rf12_trans(0xB000);
		*data++=rf12_rxbyte	();

	}


	rf12_stoprx();					// RX off
}


/******************************************************************
 *****************************************************************/
unsigned char rf12_rxdata(unsigned char *data, unsigned char *status, unsigned char *id){
  
  unsigned char i, number;
  unsigned short crc, crcref;
  
  *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

  if (crcref!=crc)
    return 255;            // checksum error
  else
    return number;          // data ok
}


/*******************************************************************************
*******************************************************************************/
unsigned short rf12_trans(unsigned short wert){
  SPI_InitTypeDef SPI_InitStructure;
  unsigned char status;

  RFM12_CS(0);
  SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize          = SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL              = SPI_CPOL_Low;
  SPI_InitStructure.SPI_CPHA              = SPI_CPHA_1Edge;
  SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 36MHz/256=140kHz < 400kHz
  SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial     = 7;
  SPI_Init(SPI1, &SPI_InitStructure);

  //SPI_CalculateCRC(SPI1, DISABLE);
  SPI_Cmd(SPI1, ENABLE);

   /* Loop while DR register in not emplty */
   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

   /* Send byte through the SPI1 peripheral */
   SPI_I2S_SendData(SPI1, wert);

   /* Wait to receive a byte */
   while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

   /* Return the byte read from the SPI bus */
   status =  SPI_I2S_ReceiveData(SPI1); 
  RFM12_CS(1);

   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
   SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//_4;
   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
   SPI_InitStructure.SPI_CRCPolynomial = 7;
   SPI_Init(SPI1, &SPI_InitStructure);
   SPI_Cmd(SPI1, ENABLE);
    return status; 
}


		 




/*********************************************************************************************************
      END FILE
*********************************************************************************************************/
