#include "sx1281_driver.h"

#include <string.h>
#include "stdio.h"
#include "radio.h"
#include "usart.h"
#include "bsp/uart.h"
#include "sx1281_header.h"
#include "sx1281.h"
#include "device/device.h"

/* --------------SX1281 Work mode------------- */
#define SX1281_INTERRUP_MODE   /* 中断模式 */
// #define SX1281_POLLING_MODE /* 轮询模式 */ 
/* ------------SX1281 Work mode end----------- */

/* ----------------SX1281 debug--------------- */
#define SX1281_VIEW

#ifdef SX1281_VIEW
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据，超时时间设置为无限等待
HAL_UART_Transmit(BSP_UART_GetHandle(BSP_UART_SX1281),(uint8_t *)&ch,1,HAL_MAX_DELAY);
return ch;
}
#endif
/* --------------SX1281 debug end------------- */

#if defined(SX1281_INTERRUP_MODE) && defined(SX1281_POLLING_MODE)
#error "Both SX1281_INTERRUP_MODE and SX1281_POLLING_MODE are defined. Only one can be defined."
#elif !defined(SX1281_INTERRUP_MODE) && !defined(SX1281_POLLING_MODE)
#error "Neither SX1281_INTERRUP_MODE nor SX1281_POLLING_MODE is defined. One of them must be defined."
#endif


/*!
 * \brief Used to display firmware version UART flow
 */
#define FIRMWARE_VERSION    ( ( char* )"Firmware Version: 170919A" )

#define RF_BL_ADV_CHANNEL_38                        2426000000 // Hz

/*!
 * \brief Defines the nominal frequency
 */
#define RF_FREQUENCY                                RF_BL_ADV_CHANNEL_38 // Hz

/*!
 * \brief Defines the buffer size, i.e. the payload size
 */
#define BUFFER_SIZE                                 5

/*!
 * \brief Number of tick size steps for tx timeout
 */
#define TX_TIMEOUT_VALUE                            10000 // ms

/*!
 * \brief Number of tick size steps for rx timeout
 */
#define RX_TIMEOUT_VALUE                            1000 // ms

/*!
 * \brief Size of ticks (used for Tx and Rx timeout)
 */
#define RX_TIMEOUT_TICK_SIZE                        RADIO_TICK_SIZE_1000_US

/**-------------------------radio params----------------------------------**/
const SX1281_LORAConfig_t loraConfigList[RF_BAUDRATE_LORA_NUM] = 
{
    {//216.264204545455bps,SF=12,BW=203kHz,CR=7
    .SpreadingFactor = LORA_SF12,        
    .SignalBw = LORA_BW_0200,               
    .ErrorCoding = LORA_CR_LI_4_7,            
    },
    {//991.2109375bps,SF=10,BW=203kHz,CR=4
    .SpreadingFactor = LORA_SF10,        
    .SignalBw = LORA_BW_0200,               
    .ErrorCoding = LORA_CR_4_8,            
    },
    {//4987.44419642857bps,SF=11,BW=1625kHz,CR=3
    .SpreadingFactor = LORA_SF11,        
    .SignalBw = LORA_BW_1600,               
    .ErrorCoding = LORA_CR_4_7,            
    },
    {//10150bps,SF=8,BW=812kHz,CR=6
    .SpreadingFactor = LORA_SF8,        
    .SignalBw = LORA_BW_0800,               
    .ErrorCoding = LORA_CR_LI_4_6,            
    },
    {//20300bps,SF=8,BW=812kHz,CR=1
    .SpreadingFactor = LORA_SF8,        
    .SignalBw = LORA_BW_0800,               
    .ErrorCoding = LORA_CR_4_5,            
    },
    {//60900bps,SF=6,BW=812kHz,CR=1
    .SpreadingFactor = LORA_SF6,                                                                                
    .SignalBw = LORA_BW_0800,               
    .ErrorCoding = LORA_CR_4_5,            
    },
    {//126953.125bps,SF=5,BW=1625kHz,CR=4
    .SpreadingFactor = LORA_SF5,        
    .SignalBw = LORA_BW_1600,               
    .ErrorCoding = LORA_CR_4_8,            
    },
    {//203125bps,SF=5,BW=1625kHz,CR=1
    .SpreadingFactor = LORA_SF5,        
    .SignalBw = LORA_BW_1600,               
    .ErrorCoding = LORA_CR_4_5,            
    },
};
const SX1281_FLRCConfig_t flrcConfigList[RF_BAUDRATE_FLRC_NUM-RF_BAUDRATE_LORA_NUM-1] = 
{
    {//0.13Mbps
        .BitrateBandwidth       =FLRC_BR_0_260_BW_0_3,
        .CodingRate             =FLRC_CR_1_2, 
        .ModulationShaping      =RADIO_MOD_SHAPING_BT_1_0,
    },
    {//0.26Mbps
        .BitrateBandwidth       =FLRC_BR_0_520_BW_0_6,
        .CodingRate             =FLRC_CR_1_2, 
        .ModulationShaping      =RADIO_MOD_SHAPING_BT_1_0,
    },
    {//0.52Mbps
        .BitrateBandwidth       =FLRC_BR_1_040_BW_1_2,
        .CodingRate             =FLRC_CR_1_2, 
        .ModulationShaping      =RADIO_MOD_SHAPING_BT_1_0,
    },
    {//1.04Mbps
        .BitrateBandwidth       =FLRC_BR_1_040_BW_1_2,
        .CodingRate             =FLRC_CR_1_0, 
        .ModulationShaping      =RADIO_MOD_SHAPING_BT_1_0,
    },
};


/*!
 * \brief Defines the states of the application
 */
typedef enum
{
    APP_LOWPOWER,
    APP_RX,
    APP_RX_TIMEOUT,
    APP_RX_ERROR,
    APP_TX,
    APP_TX_TIMEOUT,
}AppStates_t;

/*!
 * \brief Function to be executed on Radio Tx Done event
 */
void OnTxDone( void );

/*!
 * \brief Function to be executed on Radio Rx Done event
 */
void OnRxDone( void );

/*!
 * \brief Function executed on Radio Tx Timeout event
 */
void OnTxTimeout( void );

/*!
 * \brief Function executed on Radio Rx Timeout event
 */
void OnRxTimeout( void );

/*!
 * \brief Function executed on Radio Rx Error event
 */
void OnRxError( IrqErrorCode_t );

/*!
 * \brief All the callbacks are stored in a structure
 */
RadioCallbacks_t Callbacks =
{
    &OnTxDone,        // txDone
    &OnRxDone,        // rxDone
    NULL,             // syncWordDone
    NULL,             // headerDone
    &OnTxTimeout,     // txTimeout
    &OnRxTimeout,     // rxTimeout
    &OnRxError,       // rxError
    NULL,             // cadDone
};

/*!
 * \brief The size of the buffer
 */
uint8_t BufferSize = BUFFER_SIZE;

/*!
 * \brief The buffer
 */
uint8_t Buffer[BUFFER_SIZE]={0};

/*!
 * \brief Mask of IRQs to listen to in rx mode
 */
uint16_t RxIrqMask = IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT;

/*!
 * \brief Mask of IRQs to listen to in tx mode
 */
uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;

/*!
 * \brief The State of the application
 */
SX1281_States_t sx1281_state = LOWPOWER;


/*!
 * \brief In case of BLE, the payload must contain the header
 */
typedef union
{
    struct BleAdvHeaderField_s
    {
        uint8_t pduType: 4;
        uint8_t rfu1:2;
        uint8_t txAddr:1;
        uint8_t rxAddr:1;
        uint8_t length:6;
        uint8_t rfu2:2;
    } Fields;
    uint8_t Serial[ 2 ];
}BleAdvHeaders_t;
BleAdvHeaders_t ble_header_adv;


PacketParams_t packetParams;

ModulationParams_t modulationParams;


int8_t SX1281_SetMode(SX1281_t *radio, SX1281_Mode_t mode) {
  if (radio==NULL) {
    return DEVICE_ERR;
  }

  radio->mode = mode;
  
  return DEVICE_OK;
}

int8_t SX1281_Init(SX1281_t *radio, SX1281_Mode_t mode) {
  if (radio==NULL) {
    return DEVICE_ERR;
  }
  radio->mode = mode;

  
  SX1281_BSPInit() ;
  HAL_Delay( 500 );/* let DC/DC power ramp up */   
  Radio.Init( &Callbacks );
  
//  memset( &radio->rxBuffer, 0x00, BufferSize );
  
  #ifdef SX1281_VIEW
  /* 打印版本号，检查SPI是否跑通 */
  printf( "\n\n\r     SX1281 Ping Pong Demo Application. %s\n\n\r", FIRMWARE_VERSION );
  printf( "\n\n\r     Radio firmware version 0x%x\n\n\r", Radio.GetFirmwareVersion( ) );
  #endif //SX1281_VIEW

  /* 根据模式选择属性 */
  switch (mode) {
    case MODE_BLE:
        #ifdef SX1281_VIEW
        printf( "\nrunning in BLE mode\n\r" );
        #endif //SX1281_VIEW
        radio->modulationParams.PacketType = PACKET_TYPE_BLE;
        radio->modulationParams.Params.Ble.BitrateBandwidth = GFS_BLE_BR_1_000_BW_1_2;
        radio->modulationParams.Params.Ble.ModulationIndex = GFS_BLE_MOD_IND_0_50;
        radio->modulationParams.Params.Ble.ModulationShaping = RADIO_MOD_SHAPING_BT_0_5;

        radio->packetParams.PacketType = PACKET_TYPE_BLE;
        radio->packetParams.Params.Ble.BlePacketType = BLE_EYELONG_1_0;
        radio->packetParams.Params.Ble.ConnectionState = BLE_ADVERTISER;
        radio->packetParams.Params.Ble.CrcField = BLE_CRC_3B;
        radio->packetParams.Params.Ble.Whitening = RADIO_WHITENING_ON;
        
        radio->baudrate=RF_BAUDRATE_NONE;
      break;
    case MODE_LORA:
        #ifdef SX1281_VIEW
        printf( "\nrunning in LORA mode\n\r" );
        #endif //SX1281_VIEW
        radio->modulationParams.PacketType = PACKET_TYPE_LORA;
        radio->modulationParams.Params.LoRa.SpreadingFactor = LORA_SF11;
        radio->modulationParams.Params.LoRa.Bandwidth = LORA_BW_1600;
        radio->modulationParams.Params.LoRa.CodingRate = LORA_CR_LI_4_7;

        radio->packetParams.PacketType = PACKET_TYPE_LORA;
        radio->packetParams.Params.LoRa.PreambleLength = 12;
        radio->packetParams.Params.LoRa.HeaderType = LORA_PACKET_VARIABLE_LENGTH;
        radio->packetParams.Params.LoRa.PayloadLength = BUFFER_SIZE;
        radio->packetParams.Params.LoRa.CrcMode = LORA_CRC_ON;
        radio->packetParams.Params.LoRa.InvertIQ = LORA_IQ_NORMAL;

        radio->baudrate=RF_BAUDRATE_LORA_005K;
      break;
    case MODE_GFSK:
        #ifdef SX1281_VIEW
        printf( "\nrunning in GFSK mode\n\r" );
        #endif //SX1281_VIEW
        radio->modulationParams.PacketType = PACKET_TYPE_GFSK;
        radio->modulationParams.Params.Gfsk.BitrateBandwidth = GFS_BLE_BR_0_125_BW_0_3;
        radio->modulationParams.Params.Gfsk.ModulationIndex = GFS_BLE_MOD_IND_1_00;
        radio->modulationParams.Params.Gfsk.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0;

        radio->packetParams.PacketType = PACKET_TYPE_GFSK;
        radio->packetParams.Params.Gfsk.PreambleLength = PREAMBLE_LENGTH_32_BITS;
        radio->packetParams.Params.Gfsk.SyncWordLength = GFS_SYNCWORD_LENGTH_5_BYTE;
        radio->packetParams.Params.Gfsk.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1;
        radio->packetParams.Params.Gfsk.HeaderType = RADIO_PACKET_VARIABLE_LENGTH;
        radio->packetParams.Params.Gfsk.PayloadLength = BUFFER_SIZE;
        radio->packetParams.Params.Gfsk.CrcLength = RADIO_CRC_3_BYTES;
        radio->packetParams.Params.Gfsk.Whitening = RADIO_WHITENING_ON;

        radio->baudrate=RF_BAUDRATE_NONE;
      break;
    case MODE_FLRC:
        #ifdef SX1281_VIEW
        printf( "\nrunning in FLRC mode\n\r" );
        #endif //SX1281_VIEW
        radio->modulationParams.PacketType = PACKET_TYPE_FLRC;
        radio->modulationParams.Params.Flrc.BitrateBandwidth = FLRC_BR_0_260_BW_0_3;
        radio->modulationParams.Params.Flrc.CodingRate = FLRC_CR_1_2;
        radio->modulationParams.Params.Flrc.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0;

        radio->packetParams.PacketType = PACKET_TYPE_FLRC;
        radio->packetParams.Params.Flrc.PreambleLength = PREAMBLE_LENGTH_32_BITS;
        radio->packetParams.Params.Flrc.SyncWordLength = FLRC_SYNCWORD_LENGTH_4_BYTE;
        radio->packetParams.Params.Flrc.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1;
        radio->packetParams.Params.Flrc.HeaderType = RADIO_PACKET_VARIABLE_LENGTH;
        radio->packetParams.Params.Flrc.PayloadLength = BUFFER_SIZE;
        radio->packetParams.Params.Flrc.CrcLength = RADIO_CRC_3_BYTES;
        radio->packetParams.Params.Flrc.Whitening = RADIO_WHITENING_OFF;

        radio->baudrate=RF_BAUDRATE_FLRC_130K;
      break;
    default:
        return DEVICE_ERR;
  }

  /* 默认功率13dBm */
  radio->txOutputPower=13;

  /* 设置属性 */
  Radio.SetStandby( STDBY_RC );
  Radio.SetPacketType( modulationParams.PacketType );
  Radio.SetModulationParams( &modulationParams );
  Radio.SetPacketParams( &packetParams );
  Radio.SetRfFrequency( RF_FREQUENCY );//设置射频工作中心频率
  Radio.SetBufferBaseAddresses( 0x00, 0x00 );
  Radio.SetTxParams( radio->txOutputPower, RADIO_RAMP_02_US );

  #ifdef SX1281_INTERRUP_MODE
  /* 中断模式 */
  Radio.SetInterruptMode(); 
  #endif
  #ifdef SX1281_POLLING_MODE
  /* 轮询模式 */
  Radio.SetPollingMode();
  #endif

  /* 还没搞懂这里是干啥的 */
  // if (radio->mode==MODE_BLE) {
  //   // only used in GENERIC and BLE mode
  //   Radio.SetSyncWord( 1, ( uint8_t[] ){ 0xDD, 0xA0, 0x96, 0x69, 0xDD } );
  //   Radio.WriteRegister(0x9c7, 0x55 );
  //   Radio.WriteRegister(0x9c8, 0x55 );
  //   Radio.WriteRegister(0x9c9, 0x55 );
  //   //Radio.WriteRegister( 0x9c5, 0x33 );
  //   Radio.SetBleAdvertizerAccessAddress( );
  //   Radio.SetWhiteningSeed( 0x33 );
  //   ble_header_adv.Fields.length = PINGPONGSIZE + 2;
  //   ble_header_adv.Fields.pduType = 2;
  // }


  
  


  return DEVICE_OK;
}

int8_t SX1281_SetRXSingle(void) {
  Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
  Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } );
  return DEVICE_OK;
}

int8_t SX1281_SetRXSuccessive(void) {
  Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
  Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0xFFFF } );
  return DEVICE_OK;
}

int8_t SX1281_SetTX (void) {
  Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
  Radio.SendPayload((uint8_t*)"12345",5, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE });
  return DEVICE_OK;
}

int8_t SX1281_SetBaudrate(SX1281_t *radio, SX1281_Baudrate_t baudrate) {
  if (radio==NULL) {
    return DEVICE_ERR;
  }
  radio->baudrate=baudrate;
  Radio.SetStandby( STDBY_RC );

  switch (radio->mode) {
    case MODE_BLE:
    case MODE_GFSK:
      return DEVICE_OK;
    case MODE_LORA:
      if (radio->modulationParams.PacketType != PACKET_TYPE_LORA) {
        #ifdef SX1281_VIEW
        printf("error: <sx1281.c> Incorrect parameter");
        #endif
        return DEVICE_ERR;
      }
//      radio->modulationParams.Params.LoRa.SpreadingFactor = loraConfigList[baudrate].SpreadingFactor;
//      radio->modulationParams.Params.LoRa.Bandwidth = loraConfigList[baudrate].SignalBw;
//      radio->modulationParams.Params.LoRa.CodingRate = loraConfigList[baudrate].ErrorCoding;
      break;

    case MODE_FLRC:
      if (radio->modulationParams.PacketType != PACKET_TYPE_FLRC) {
        #ifdef SX1281_VIEW
        printf("error: <sx1281.c> Incorrect parameter");
        #endif
        return DEVICE_ERR;
      }
//      radio->modulationParams.Params.Flrc.BitrateBandwidth = flrcConfigList[baudrate-(RF_BAUDRATE_LORA_NUM+1)].BitrateBandwidth;
//      radio->modulationParams.Params.Flrc.CodingRate = flrcConfigList[baudrate-(RF_BAUDRATE_LORA_NUM+1)].CodingRate;
//      radio->modulationParams.Params.Flrc.ModulationShaping = flrcConfigList[baudrate-(RF_BAUDRATE_LORA_NUM+1)].ModulationShaping;
      break;
    default:
      return DEVICE_ERR;
      break;
  }
  Radio.SetModulationParams( &radio->modulationParams );

  return DEVICE_OK;
}

int8_t SX1281_SetPacketConfig(SX1281_t *radio) {
  if (radio==NULL) {
    return DEVICE_ERR;
  }
  Radio.SetStandby( STDBY_RC );

  return DEVICE_OK;
}

/**
 * @brief 退出射频进入休眠
 * 
 */
int8_t SX1281_SetSleep(SX1281_t *radio)
{
    if (radio == 0)
    {
        return DEVICE_ERR;
    }

    // SleepParams_t SleepParams;
    // SleepParams.DataBufferRetention = 1;
    // SleepParams.DataRamRetention = 1;
    // SleepParams.InstructionRamRetention = 1;
    // SleepParams.WakeUpRTC = 0;
    // // Radio.SetSleep( SleepParams );
    // Radio.SetStandby( STDBY_RC );
	return DEVICE_OK;
}

/**
 * 获取射频波特率
 * @param : br->
*/
//SX1281_Baudrate_t SX1281_GetBaudrate(SX1281_t *radio)
//{
//    if (radio==NULL)
//    {
//        return DEVICE_ERR;
//    }
//    // return radio->baudrate;
//}

int8_t SX1281_Running() {
  SX1281ProcessIrqs();
	HAL_Delay(10);
	return DEVICE_OK;
}

/* Callback function  -------------------------------------------------------- */
__attribute__((weak)) int8_t SX1281_Callback(SX1281_States_t source) {
  switch (source) {
    case RX_DONE:
        /* 打印状态 */
        printf( "<>>>>>>>>OnRxDone\n\r" );
        /* 从缓冲区拿数据 */
        BufferSize = 0;
        Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
        Buffer[BufferSize+1] = 0;
        /* 重启接收 */
        //Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } );
      break;

    case RX_TIMEOUT:
        /* 打印状态 */
        printf( "<>>>>>>>>OnRXTimeout\n\r" );
        //Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } );
        Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0xFFFF } );
      break;

    case RX_ERROR:
        /* 打印状态 */
        printf( "<>>>>>>>>OnRxErr\n\r" );
        Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } );
      break;

    case TX_DONE:
        /* 打印状态 */
        printf( "<>>>>>>>>OnTxDone\n\r" );    
        Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
        Radio.SendPayload((uint8_t*)"hello",5, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE });
      break;

    case TX_TIMEOUT:
        /* 打印状态 */
        printf( "<>>>>>>>>OnTxTimeout\n\r" ); 
        
      break;

    case LORA_CAD_DONE:
        /* 打印状态 */
        printf( "<>>>>>>>>OnCadDone\n\r" );
      break;
    default:
      break;
  }
  return 0;  
}

void OnTxDone( void ) {
  sx1281_state = TX_DONE;
  SX1281_Callback(sx1281_state);
}

void OnRxDone( void ) {
  sx1281_state = RX_DONE;
  SX1281_Callback(sx1281_state);
}

void OnTxTimeout( void ) {
  sx1281_state = TX_TIMEOUT;
  SX1281_Callback(sx1281_state);
}

void OnRxTimeout( void ) {
  sx1281_state = RX_TIMEOUT;
  SX1281_Callback(sx1281_state);
}

void OnRxError( IrqErrorCode_t errorCode ) {
  sx1281_state = RX_ERROR;
  SX1281_Callback(sx1281_state);
}

void OnCadDone( bool channelActivityDetected ) {
  sx1281_state = LORA_CAD_DONE;
  SX1281_Callback(sx1281_state);
}

