/* ********************************************
   STM32F103 Mini Board
   Modul : NRF24L01
   Routinen für dasNRF24L01 Funkmodul
   Autor : Christian Julius
   ********************************************

    SPI2:

    MOSI    = PB15
    MISO    = PB14
    SCLK    = PB13
    CE      = PB11
    CSN     = PB12
    IRQ     = PA2

*/

/* -------------- System Include Files ------------------- */
#include "stm32f10x_conf.h"

/* -------------- Standard Include Files ----------------- */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

/* -------------- Special Include Files / Librarys ------ */
/* -------------- Projekt Include Files ---------------- */
#include "nrf24l01_drv.h"
#include"isrhdl.h"

/* -------------- Defintionen ---------------------------- */


/* Anschluesse der Pins */
#define RF_SPI         SPI2
#define CSN_PORT       GPIOB
#define CSN_PIN        GPIO_Pin_12
#define CE_PORT        GPIOB
#define CE_PIN         GPIO_Pin_11
#define IRQ_PORT       GPIOA
#define IRQ_PIN        GPIO_Pin_2

#define NRF24L01_PORT  GPIOB

#define MOSI_AF        GPIO_PinSource15
#define MISO_AF        GPIO_PinSource14
#define SCK_AF         GPIO_PinSource13

/* CE und CSN Pins schalten */
#define CSN_LOW        GPIO_ResetBits(CSN_PORT,CSN_PIN); ;
#define CSN_HIGH       GPIO_SetBits(CSN_PORT,CSN_PIN);
#define CE_LOW         GPIO_ResetBits(CE_PORT,CE_PIN);
#define CE_HIGH        GPIO_SetBits(CE_PORT,CE_PIN);

/* Makros statt Funktionen */
#define CLEAR_STATUS   RF_WriteRegSingle(NRF24L01_REG_STATUS,0x70)

/* Viele Definitionen des RF Modules einbinden */
#include "rf_defines.h"

#define RF_CONFIG_MASK  ((0 << NRF24L01_MASK_RX_DR) | (1 << NRF24L01_MASK_TX_DS) | (1 << NRF24L01_MASK_MAX_RT) \
                       | (1 << NRF24L01_EN_CRC) | (1 << NRF24L01_CRCO))

#define PAYLOAD_SIZE    32          // Hängt von Groesse des Structs ab
#define TX_CHANNEL      50          // Kanal 50 für uns
#define RX_CHANNEL      20

/* --------------------- Typen Deklarationen ---------------------------- */


/* -------------------- Externe Variablen ------------------------------- */

/* Structs*/
status_t rf_status_reg;                                   // Status (PRX)

/* -------------------- Privat Variablen -------------------------------- */

/* Festgelegte Adressen der Module */
//const uint8_t TSensPipe[5]   = {0x49,0x23,0x06,0x50,0x61};   // Pipe 1 = Empfangsadresse für Temperatursensor

/* Receiver Adresse dieses Gerätes. Auf dieser Adresse empfängt das
   Display Daten vom Masterboard */
const uint8_t RXAdrDisp1[]   = {0xd7,0xd7,0xd7,0xd7,0xd7};     // RX Pipe dieses Gerätes = Empfangsadresse für History Daten

/* Receiver (RX) Adresse des Masterboards. Auf dieser Adresse
   wartet der Master auf Daten vom LED Bar Display Nr. 2*/
const uint8_t RXAdrMaster[] = {0x49,0x23,0x06,0x50,0x61};

/* --------------------- Privat Funktionen Prototypen ------------------- */
void    RF_Init_SPI();
void    RF_WriteRegSingle(uint8_t, uint8_t);
void    RF_WriteRegMulti(uint8_t, const uint8_t*, size_t);
void    RF_ReadRegMulti(uint8_t, void*,size_t);
void    RF_Fill_ACK_Payload(uint8_t,void*,size_t);
uint8_t SPI_TransferByte(uint8_t data);
uint8_t RF_ReadRegSingle(uint8_t);

/* ----------------------------------------------------------------------*/
/* ------------------------ Funktion Bodys  ---------------------------- */
/* ----------------------------------------------------------------------*/

/* Fordere kompletten Datensatz vom Master an */
void RF_RequestMasterData()
{
    // Simulierter Datensatz vom Arduino Sensor
    struct {
        uint16_t    id;
        uint8_t dummy[4];
    } __attribute__((packed)) data;

    uint8_t *ptr = (uint8_t*)&data;

    data.id = 0x1234;           // Kommando für "Gib mir Daten!"

    /* TX und ACK Pipe setzen */
    CE_LOW;
    RF_SetChannel(TX_CHANNEL);
    RF_WriteRegMulti(NRF24L01_REG_TX_ADDR,RXAdrMaster,0x05);
    RF_WriteRegMulti(NRF24L01_REG_RX_ADDR_P0,RXAdrMaster,0x05);
	RF_PowerUpTX();

	CSN_LOW;
    /* Kommando Wort senden fuer Payload mit ACK*/
    SPI_TransferByte(NRF24L01_CMD_W_TX_PAYLOAD);
	for (uint8_t i = 0; i < sizeof(data); i++)
        SPI_TransferByte(*(ptr++));
    CSN_HIGH;

    /* RF Modul sendet jetzt */
    CE_HIGH;
    DelayMs(10);     // Einfach pausieren, keine Abfrage des Status
    CE_LOW;

    /* Modul ist jetzt im Standby-II Mode, zurückschalten in RX Mode */
    RF_SetChannel(RX_CHANNEL);
    RF_PowerUpRx();
}


/*  ----------------------------------------------------------------------
      Sendet eine Paypload an einen Empfänger
      danach geht Modul in Standyby Mode. TX
    ------------------------------------------------------------------- */

RF_Response_t RF_SendPayload(uint8_t* receiver, void* payload,size_t len)
{
	uint8_t *ptr = (uint8_t*) payload;

    if (len > 32)
        return RF_ERROR;

    /* TX und ACK Pipe setzen */
    RF_WriteRegMulti(NRF24L01_REG_TX_ADDR,receiver,0x05);
    RF_WriteRegMulti(NRF24L01_REG_RX_ADDR_P0,receiver,0x05);
	RF_PowerUpTX();

	CSN_LOW;
    /* Kommando Wort senden fuer Payload mit ACK*/
    SPI_TransferByte(NRF24L01_CMD_W_TX_PAYLOAD);
	for (uint8_t i = 0; i < len; i++)
        SPI_TransferByte(*(ptr++));
    CSN_HIGH;

    /* RF Modul sendet jetzt */
    CE_HIGH;

    /* Ende der Übertragung abwarten... */
    uint16_t to = 50000;
    do {
        RF_GetStatus(&rf_status_reg);
        if (!to--) {
            CE_LOW;
            RF_PowerUpRx();
            return RF_TIMEOUT;
        }
    } while ((rf_status_reg.tx_ds == false) && (rf_status_reg.max_rt == false));

    CE_LOW;

    /* Modul ist jetzt im Standby-II Mode, zurückschalten in RX Mode */
    RF_PowerUpRx();

    /* Keine Antwort? */
    if (!rf_status_reg.tx_ds)
        return RF_NO_ACK;

    /* Gegenstelle hat geantwortet */
    return RF_OK;
}

/* -------------------------------------------------------------------- */
/*                                                                      */
/*                         NRF24L01 DRIVER                              */
/*                                                                      */
/* -------------------------------------------------------------------- */

/* Merker, ob SPI initialisiert wurde */
volatile _Bool spi_initialized = false;

/* ----------------------------------------------------------------------
   Ist das Funkmodul ansprechbar ?
   Dazu wird das SETUP_RETR Register beschrieben
  --------------------------------------------------------------------- */
uint8_t RF_Available()
{
    if (!spi_initialized)
        RF_Init_SPI();

    /* Register sichern */
    CE_LOW;
    uint8_t backup = RF_ReadRegSingle(NRF24L01_REG_SETUP_RETR);

    /* 0x9d einschreiben */
    RF_WriteRegSingle(NRF24L01_REG_SETUP_RETR,0x55);

    /* Auslesen und Backup zurück */
    uint8_t val = RF_ReadRegSingle(NRF24L01_REG_SETUP_RETR);
    RF_WriteRegSingle(NRF24L01_REG_SETUP_RETR,backup);

    return ((val == 0x55) ? SUCCESS:ERROR);
}

/* -------------------------------------------------------------------- */
/* Füllt den TX Fifo (Pipe x) des PRX Moduls mit einer ACK Payload      */
/* -------------------------------------------------------------------- */
void RF_Fill_ACK_Payload(uint8_t pipe,void *payload, size_t len)
{
    uint8_t *ptr = (uint8_t*) payload;

    if (pipe > 5) pipe = 5;
    uint8_t cmd = NRF24L01_CMD_W_ACK_PAYLOAD | pipe;
    CSN_LOW;
    // Kommando W_ACK_PAYLOAD + Pipe senden
    SPI_TransferByte(cmd);
    // TX ACK Payload einfüllen
    for (uint8_t i = 0; i< len; i++) {
        SPI_TransferByte(*(ptr++));
    }
    CSN_HIGH;
}


/* ----------------------------------------------------------------------- */
/* --- Sind Daten da ? -----*/
uint8_t RF_DataReady() {

    /* Status auslesen */
    CSN_LOW;
    uint8_t stat = SPI_TransferByte(0xff);
    CSN_HIGH;

    if (stat & (1 << NRF24L01_RX_DR))
        return SUCCESS;

    return ERROR;
}

/* -------------------- Ist der RX FIFO leer ? --------------------------- */
_Bool RF_RX_DataInFifo()
{
    CSN_LOW;
    /* Lese FIFO Status Register aus */
    SPI_TransferByte(NRF24L01_REG_FIFO_STATUS);
    uint8_t val = SPI_TransferByte(0xff);
    CSN_HIGH;

    /* Prüfe das RX_EMPTY Bit */
    if (val & 0x01)
        return false;

    return true;
}

/* -------------- Setzt oder löscht CE Leitung (Modul Steuerung TX, RX ----- */
inline void RF_CE_Enable(FunctionalState stat)
{
    switch (stat) {
        case ENABLE:  CE_HIGH;
                  break;
        case DISABLE: CE_LOW;
                  break;
    }
}

/* ---------------- In welcher Pipe sind Daten? 7 =  In keiner -------------- */
inline uint8_t RF_GetFilledPipe()
{
      RF_GetStatus(&rf_status_reg);
      return (rf_status_reg.rx_p_no);
}

/* -------------- Status Register des RF löschen ----------------------------- */
inline void RF_ClearStatus() {
    CLEAR_STATUS;
}


/* --------------- Liest die Payload aus, wenn Grösse bekannt ist ------------ */
void RF_ReadPayload(uint8_t* ptr, size_t len)
{
    CSN_LOW;
    SPI_TransferByte(NRF24L01_CMD_R_RX_PAYLOAD);
    for (uint8_t i = 0; i < len; i++)
        *(ptr++) = SPI_TransferByte(0xff);
    CSN_HIGH;
}

/* ---------------- Neuen Kanal setzen ------------------------------------------*/
inline void RF_SetChannel(uint8_t channel) {
    RF_WriteRegSingle(NRF24L01_REG_RF_CH,channel);
}

/* ----------------- Setze neue Zieladresse für TXSendungen -------------------- */
inline void RF_SetTxAddress(uint8_t* adr) {
    RF_WriteRegMulti(NRF24L01_REG_TX_ADDR,adr,0x05);     // TX Pipe Adresse

}

/* ------------------ Setze Pipe 0 ACK Adresse --------------------------------- */
inline void RF_SetMyAddress(uint8_t* receiver)
{
    RF_WriteRegMulti(NRF24L01_REG_RX_ADDR_P0,receiver,0x05);     // TX Pipe Adresse
}


/* ----------------------------------------------------------------------------- */
/* Schaltet Enhanced ShockBurst ein/aus */
void RF_EnableShockburst(uint8_t pipe, FunctionalState state)
{
    uint8_t val;

    /* Aktuelles Register lesen */
    val = RF_ReadRegSingle(NRF24L01_REG_EN_AA);

    if (state == ENABLE) {
        val = val | (1 << pipe);
        RF_WriteRegSingle (NRF24L01_REG_EN_AA,val);
    }
    else {
        val &= ~ (1 << pipe);
        RF_WriteRegSingle (NRF24L01_REG_EN_AA, ~(1 << pipe));
    }
}

/* ------------------------------------------------------------------------------- */
/* Schaltet den Empfang dynamischer Payload ein/aus
   Betrifft PRX  */
void RF_Enable_Dynamic_Payload(uint8_t pipe, FunctionalState state)
{
    uint8_t val;

    if (pipe > 5) pipe = 5;

    if (state == ENABLE) {
        /* Dynamic Payload Length im Feature Reg einschalten */
        val = RF_ReadRegSingle(NRF24L01_REG_FEATURE);
        val |= (1 << NRF24L01_EN_DPL);
        RF_WriteRegSingle(NRF24L01_REG_FEATURE,val);
        /* Dyn Payload Length in Pipe n einschalten */
        val = RF_ReadRegSingle(NRF24L01_REG_DYNPD);
        val |= (1 << pipe);
        RF_WriteRegSingle(NRF24L01_REG_DYNPD,val);
    } else {
        /* Dyn Payload Length in Pipe abschalten */
        val = RF_ReadRegSingle(NRF24L01_REG_DYNPD);
        val &= ~(1 << pipe);
        RF_WriteRegSingle(NRF24L01_REG_DYNPD,val);
    }

}

/* ----------------------------------------------------------------------------------
   Setze das Modul auf ACK mit Payload, d.h. bei jedem empfangenen
   Paket wird der hinterlegte Inhalt des TX Fifo zurück an den
   Sender gefunkt. Es muss gleichzeitig Dynamic Payload aktiviert
   sein!
   Betrifft: PRX
---------------------------------------------------------------------------------- */

void RF_Enable_ACK_with_Payload(uint8_t pipe, FunctionalState state)
{
    if (pipe > 5) pipe = 5;

    /* Zufällig ist die Bitnummer im DYNPD gleich
       der jeweiligen Pipe Nummer, daher reicht es
       1 << pipe zu maskieren */

    if (state == ENABLE) {
        /* Dynamic Payload für Pipe einschalten */
        RF_Enable_Dynamic_Payload(pipe,ENABLE);
        /* ACK mit Payload im Feature Reg einschalten */
        RF_WriteRegSingle(NRF24L01_REG_FEATURE,(1 << NRF24L01_EN_ACK_PAY ));
    } else {
        /* Dynamic Payload Length / ACK mit Payload im Feature Reg abschalten */
        RF_WriteRegSingle(NRF24L01_REG_FEATURE,(0 << NRF24L01_EN_ACK_PAY ));
    }
}

/* ------------------------------------------------------------------------------- */
/* Setze Datenrate des Moduls, PRX und PTX */
void RF_SetDataRate(NRF24L01_DataRate_t rate)
{

    /* Register einlesen und Datenrate ausmaskieren*/
    uint8_t val = RF_ReadRegSingle(NRF24L01_REG_RF_SETUP) & 0xD7;

    switch (rate) {
        case Rate_250kBit: val |= 0x20;
                           break;
        case Rate_1Mbit:   val |= 0x00;
                           break;
        case Rate_2Mbit:   val |= 0x08;
                           break;
        default:           val |= 0x20;
                           break;
    }

    RF_WriteRegSingle(NRF24L01_REG_RF_SETUP,val);
}

/* --------------------------------------------------------------------------------- */
/* Sende Power setzen, PRX und PTX */
void RF_SetOutputPower(NRF24L01_Power_t power)
{

    uint8_t old = RF_ReadRegSingle(NRF24L01_REG_RF_SETUP);      // Akt. Register einlesen
    old = old & 0xf9;       // Power Bits ausmaskieren

    switch (power) {

        case NRF24L01_Power_Min : old |= 0b000;
                                  break;
        case NRF24L01_Power_Low:  old |= 0b010;
                                  break;
        case NRF24L01_Power_High: old |= 0b100;
                                  break;
        case NRF24L01_Power_Max:  old |= 0b110;
                                  break;
        default:                  old |= 0b100;
                                  break;
    }

    // Neue Werte zurückschreiben
    RF_WriteRegSingle(NRF24L01_REG_RF_SETUP,old);
}

/* ----- Aktiviere eine RX Pipe für Empfang ---------
   Eingabe: Pipe Nr. 0..5, Payload Grösse, RX Addresse der Pipe
*/
//void RF_Set_RX_Pipe(uint8_t pipe, uint8_t load_size, char* rx_address)
//{
//    /* Gültigkeiten prüfen */
//    if (pipe > 5) pipe = 5;
//    if (load_size > 32) load_size = 32;
//
//    // TODO...
//
//}

/* ----------------------------------------------------------------------------- */
/*  RX Mode einschalten, 16 Bit CRC, PRX */
void RF_PowerUpRx()
{
    CE_LOW;
    /* Alle Buffer leer machen */
    RF_FlushRX();
    RF_WriteRegSingle(NRF24L01_REG_CONFIG, RF_CONFIG_MASK | (1 << NRF24L01_PRIM_RX) | (1 << NRF24L01_PWR_UP));
    CLEAR_STATUS;
    CE_HIGH;
}

/* ----------------------------------------------------------------------------- */
/* Modul in Sendebereitschaft bringen, PTX */
void  RF_PowerUpTX()
{
    CE_LOW;
    RF_FlushTX();
    // Power Up, CRC8
    RF_WriteRegSingle(NRF24L01_REG_CONFIG, RF_CONFIG_MASK | (0 << NRF24L01_PRIM_RX) | (1 << NRF24L01_PWR_UP));
    CLEAR_STATUS;
}

/* ------------------------------------------------------------------------------ */
/* Modul abschalten */
void RF_PowerDown()
{
    CE_LOW;
    /* Power Up Bit löschen */
	RF_WriteRegSingle(NRF24L01_REG_CONFIG,  RF_CONFIG_MASK | (1 << NRF24L01_PRIM_RX) | (0 << NRF24L01_PWR_UP));
}

/* ------------------------------------------------------------------------------- */
/* TX FIFO löschen */
void RF_FlushTX()
{
    CSN_LOW;
    SPI_TransferByte(NRF24L01_CMD_FLUSH_TX);
    CSN_HIGH;
}

/* ------------------------------------------------------------------------------- */
/* RX FIFO löschen */
void RF_FlushRX() {
    CSN_LOW;
    SPI_TransferByte(NRF24L01_CMD_FLUSH_RX);
    CSN_HIGH;
}

/* ------------------------------------------------------------------------------- */
/* Holt den Status des Moduls und splittet ihn auf
   Eingabe: Zeiger auf Status */
/* --- Holt den Status des Moduls und splittet ihn auf --- */
void RF_GetStatus(status_t* status)
{
    uint8_t stat;

    CSN_LOW;
    stat = SPI_TransferByte(0xff);
    CSN_HIGH;

    /* Bits extrahieren */
    status->rx_dr   = stat & (1 << NRF24L01_RX_DR);
    status->tx_ds   = stat & (1 << NRF24L01_TX_DS);
    status->tx_full = stat & (1 << NRF24L01_TX_FULL);
    status->max_rt  = stat & (1 << NRF24L01_MAX_RT);
    status->rx_p_no = ((stat & 0x0e) >> 1);
}

/* -------------------------------------------------------------------------------- */
/* Ermittelt die Anzahl Bytes, die im FIFO bereit liegen
   mittels CMD_R_RX_PL_WID */
uint8_t RF_GetPayloadSize()
{
    CSN_LOW;
    SPI_TransferByte(NRF24L01_CMD_R_RX_PL_WID);
    uint8_t val = SPI_TransferByte(0xff);
    CSN_HIGH;

    /* Wert gültig ? */
    if (val > 32) {
        RF_FlushRX();
        val = 0;
    }

    return val;
}

/* -----------------------------------------------------------------------------------
    NRF24L01 Register mit 1 Byte beschreiben
    Eingabe: Register, neuer Wert
  ---------------------------------------------------------------------------------- */

void RF_WriteRegSingle(uint8_t nrf_reg, uint8_t value)
{
    CSN_LOW;
    SPI_TransferByte(NRF24L01_CMD_WRITE(nrf_reg));
    SPI_TransferByte(value);
    CSN_HIGH;
}

/* -----------------------------------------------------------------------------------
   NRF24L01 Register mit 1-n Bytes beschreiben, n < 32
   Eingabe: Register, Zeiger auf Daten, Länge der Daten
   -------------------------------------------------------------------------------- */

void RF_WriteRegMulti(uint8_t nrf_reg, const uint8_t* data, size_t len)
{
    CSN_LOW;
    SPI_TransferByte(NRF24L01_CMD_WRITE(nrf_reg));
    for (uint8_t i = 0; i < len; i++)
        SPI_TransferByte(*(data++));

    CSN_HIGH;
}

/* ----------------------- NRF24L01 Register: 1 Byte auslesen ---------------------- */
uint8_t RF_ReadRegSingle(uint8_t nrf_reg)
{
    CSN_LOW;
    SPI_TransferByte(NRF24L01_CMD_READ(nrf_reg));
    uint8_t val = SPI_TransferByte(0xff);
    CSN_HIGH;
    return val;
}

/* ----------------------- NRF24L01 Register: Mehrere Bytes auslesen --------------- */
void RF_ReadRegMulti(uint8_t nrf_reg, void *data, size_t len)
{
    uint8_t *ptr = (uint8_t*) data;

    if (!spi_initialized)
        RF_Init_SPI();

    CSN_LOW;

    SPI_TransferByte(NRF24L01_CMD_READ(nrf_reg));
    for (uint8_t i = 0; i < len; i++)
        *(ptr++) = SPI_TransferByte(0xff);

    CSN_HIGH;
}

/* ------------------------ Schaltet den Int Pin als Interruptquelle ab --------------*/
void RF_Interrupts(FunctionalState state)
{
    if (state == ENABLE)
        NVIC_EnableIRQ(EXTI2_IRQn);
    else
        NVIC_DisableIRQ(EXTI2_IRQn);
}


/* ---------------------------------------------------------------------------------- */

/* Feste Einstellung des Funkmoduls für die Anwendung

   Auto ACK         : fuer alle Pipes
   INT              : nur bei Empfang eines Pakets
   Sende Power      : Maximum
   CRC              : 16 Bit
   Rate             : 250kBit/s
   Pipe             : 1-5, ACK Adresse aber nur für 0
   Payload Size     : dyn. für alle Pipes
   Kanal            : 50
*/

void RF_Configure()
{
    if (!spi_initialized)
        RF_Init_SPI();

     CE_LOW;

    /* Sende/Empfangs Kanal setzen */
    RF_WriteRegSingle(NRF24L01_REG_RF_CH,RX_CHANNEL);

    /* Enhanced Shockburst: Auto ACK für alle Pipes 0 und 1 setzen */
    RF_WriteRegSingle(NRF24L01_REG_EN_AA, 0x03f);

    /* Dyn Payload, No Payload with ACK */
    RF_WriteRegSingle(NRF24L01_REG_FEATURE,0x04);           // Enable dyn. Payload Length
    RF_WriteRegSingle(NRF24L01_REG_DYNPD,0x03f);            // Dyn. Payload Lenght für alle Pipes

    /* Adresslänge */
    RF_WriteRegSingle(NRF24L01_REG_SETUP_AW,0x03);          // 11 = 5 Bytes Adresse

    /* Datenrate auf 250kbit/s setzen, Power = Max */
    RF_WriteRegSingle(NRF24L01_REG_RF_SETUP, (1 << NRF24L01_RF_DR_LOW) | (0 << NRF24L01_RF_DR_HIGH) | 0x06);

    /* Retransmission 15 und Delay 4000us (nicht erforderlich) */
    RF_WriteRegSingle(NRF24L01_REG_SETUP_RETR,0xef);

    /* Erlaubte Pipes 0 - 1  setzen */
    RF_WriteRegSingle(NRF24L01_REG_EN_RXADDR, (1 << NRF24L01_ERX_P0) | (1 << NRF24L01_ERX_P1) \
                                            | (0 << NRF24L01_ERX_P2) | (0 << NRF24L01_ERX_P3) \
                                            | (0 << NRF24L01_ERX_P4) | (0 << NRF24L01_ERX_P5) );
    /* Adressen setzen */
    RF_WriteRegMulti(NRF24L01_REG_RX_ADDR_P1,RXAdrDisp1,sizeof(RXAdrDisp1));     //  RX Pipe 1 für Display

    /* Payload Size für die Pipes setzen (eigentlich unnötig, da dynamisch)*/
    RF_WriteRegSingle(NRF24L01_REG_RX_PW_P0,PAYLOAD_SIZE);
    RF_WriteRegSingle(NRF24L01_REG_RX_PW_P1,PAYLOAD_SIZE);
    RF_WriteRegSingle(NRF24L01_REG_RX_PW_P2,0);
    RF_WriteRegSingle(NRF24L01_REG_RX_PW_P3,0);
    RF_WriteRegSingle(NRF24L01_REG_RX_PW_P4,0);
    RF_WriteRegSingle(NRF24L01_REG_RX_PW_P5,0);

    CE_LOW;
    RF_FlushRX();
    RF_FlushTX();
    CLEAR_STATUS;

    /* Config Register einstellen auf RX Mode, CRC 8 und IRQ Masken*/
    RF_WriteRegSingle(NRF24L01_REG_CONFIG, RF_CONFIG_MASK | (1 << NRF24L01_PRIM_RX) | (1 << NRF24L01_PWR_UP));

    /* Empfangsbereitschaft herstellen */
    CE_HIGH;
}

/* -----------------------------------------------------------------------------------
                                HARDWARE abhängiger Code
-------------------------------------------------------------------------------------*/

/* SPI1 Transfer Routine */
uint8_t SPI_TransferByte(uint8_t data)
{
    while (SPI_I2S_GetFlagStatus(RF_SPI, SPI_I2S_FLAG_TXE) == RESET);  /* Wait for SPIz Tx buffer empty */
    SPI_I2S_SendData(RF_SPI,data);                                     /* Send RF_SPI data */
    while (SPI_I2S_GetFlagStatus(RF_SPI, SPI_I2S_FLAG_RXNE) == RESET); /* Wait for RF_SPI data reception */
    while (SPI_I2S_GetFlagStatus(RF_SPI, SPI_I2S_FLAG_BSY) == SET);    /* Wait for RF_SPI Busy Flag cleared */
    return SPI_I2S_ReceiveData(RF_SPI);                                /* Read RF_SPI received data */
}

/* -------------------------------------------------------------------------------- */

/* Stellt die SPI2 für das RF Modul ein */
void RF_Init_SPI() {

    GPIO_InitTypeDef GPIO_InitStruct;
    SPI_InitTypeDef SPI_InitStruct;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

    /*-------- SCK, MOSI, MISO: PB13,14,15 --------*/
    GPIO_StructInit (&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_AF_PP;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_Init(NRF24L01_PORT, &GPIO_InitStruct);

    CE_LOW;            // Setze Pins passiv
    CSN_HIGH;

    /* CSN (PB12) konfigurieren */
    GPIO_StructInit (&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin    = CSN_PIN;
    GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_Init(CSN_PORT, &GPIO_InitStruct);

    /* CE (PB11) im gleichen Struct konfigurieren*/
    GPIO_InitStruct.GPIO_Pin    = CE_PIN;
    GPIO_Init(CE_PORT, &GPIO_InitStruct);

    /* Die RF_SPI einstellen: Master, 2 Lines, 8 Bit, Mode 0 */
    SPI_StructInit(&SPI_InitStruct);
    SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStruct.SPI_Mode      = SPI_Mode_Master;
    SPI_InitStruct.SPI_DataSize  = SPI_DataSize_8b;
    SPI_InitStruct.SPI_CPOL      = SPI_CPOL_Low;
    SPI_InitStruct.SPI_CPHA      = SPI_CPHA_1Edge;
    SPI_InitStruct.SPI_NSS       = SPI_NSS_Soft;
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;        // 4.5 Mhz
    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_Init(RF_SPI, &SPI_InitStruct);

    SPI_Cmd(RF_SPI, ENABLE);

    spi_initialized = true;
}

/* ----------------------------------------------------------------------------- */

void RF_Init_Handler()
{

    /* PC1 Interrupt Pin konfigurieren auf Line 0 EXTI0_IRQn für Funbkmodul

        Line 0-4 haben einen eigenen Handler, 5-9 haben den Gleichen
        und 10-15 ebenfalls. Alle Px0 sind auf Line 0 angebunden usw.

        EXTI0_IRQn	EXTI0_IRQHandler	Handler for pins connected to line 0
        EXTI1_IRQn	EXTI1_IRQHandler	Handler for pins connected to line 1
        EXTI2_IRQn	EXTI2_IRQHandler	Handler for pins connected to line 2
        EXTI3_IRQn	EXTI3_IRQHandler	Handler for pins connected to line 3
        EXTI4_IRQn	EXTI4_IRQHandler	Handler for pins connected to line 4
        EXTI9_5_IRQn	EXTI9_5_IRQHandler	Handler for pins connected to line 5 to 9
        EXTI15_10_IRQn	EXTI15_10_IRQHandler	Handler for pins connected to line 10 to 15

    */

    GPIO_InitTypeDef GPIO_InitStruct;
    EXTI_InitTypeDef EXTI_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;

    if (!spi_initialized)
       RF_Init_SPI();

     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    /* PA2 als Input */
    GPIO_StructInit (&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin    = IRQ_PIN;
    GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_IN_FLOATING;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_Init(IRQ_PORT, &GPIO_InitStruct);

    // Line einem Port und Pin zuordnen, hier Port A, Pin 2 = PA2
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource2);

    /* Line 2 der External IRQs 2 konfigurieren */
    EXTI_InitStruct.EXTI_Line    = IRQ_LINE;                        /* PA2 ist verbunden mit EXTI_Line2 */
    EXTI_InitStruct.EXTI_LineCmd = ENABLE;                          /* Enable interrupt */
    EXTI_InitStruct.EXTI_Mode    = EXTI_Mode_Interrupt;             /* Interrupt mode */
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;            /* Trigger auf fallende Flanke */
    EXTI_Init(&EXTI_InitStruct);                                    /* Aktivieren und zu EXTI hinzufügen */

    /* NVIC einbinden: PA2 ist auf EXTI_Line1 und hat den Vector EXT2_IRQn */
    NVIC_InitStruct.NVIC_IRQChannel = IRQ_HDL;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 15;          /* Höchste Priorität */
    NVIC_InitStruct.NVIC_IRQChannelSubPriority        = 0;          /* Sub Priorität */
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;                    /* Enable Interrupt */
    NVIC_Init(&NVIC_InitStruct);                                    /* Zum NVIC hinzufügen */

    NVIC_EnableIRQ(IRQ_HDL);                                     /* Interrupt ein */

}

