/******************************************************************************
 * @fn          perCC1120CC1190RegConfig
 *
 * @brief       Configures the CC1120 radio with the selected 
 *              paramteres and test properties or uses the base configuration 
 *              with no address check. Assumes that the radio is in IDLE.
 *
 * input parameters
 *
 * output parameters
 *
 * @return      void
 */
void perCC1120CC1190RegConfig(void)
{
  uint8 data;
  /* Log that radio is in IDLE state */
  cc1120cc1190RxIdle();
  cc1120cc1190RadioTxRx = CC112X_STATE_IDLE;
    
  /* Extract what radio configuration to use */
  /* Only one configuration implemented so far, but keeping structure to add
     more configurations later */
  if((perSettings.masterSlaveLinked==PER_DEVICE_LINKED) || 
      (perSettings.masterSlaveLinked == PER_DEVICE_LINK_BYPASS))
  {
    switch(perSettings.smartRfConfiguration)
    {
     case 0:
        for(uint16 i = 0; i < (sizeof cc1120cc1190LowDataRateRfSettings/sizeof(registerSetting_t));i++)
        {
          data = cc1120cc1190LowDataRateRfSettings[i].data;
          cc112xSpiWriteReg(cc1120cc1190LowDataRateRfSettings[i].addr,&data,1);
        }
        if(perSettings.frequencyBand == 0){
          perSettings.sensitivity = sensitivity869Mhz[0];
          cc1120cc1190RssiOffset = rssiOffset869Mhz[0];          
        }
        else{
          perSettings.sensitivity = sensitivity915Mhz[0];
          cc1120cc1190RssiOffset = rssiOffset915Mhz[0];
        }
        break;
     case 1:
        for(uint16 i = 0; i < (sizeof cc1120cc1190MediumDataRateRfSettings/sizeof(registerSetting_t));i++)
        {
          data = cc1120cc1190MediumDataRateRfSettings[i].data;
          cc112xSpiWriteReg(cc1120cc1190MediumDataRateRfSettings[i].addr,&data,1);
        }
        if(perSettings.frequencyBand == 0){
          perSettings.sensitivity = sensitivity869Mhz[1];
          cc1120cc1190RssiOffset = rssiOffset869Mhz[1];          
        }
        else{
          perSettings.sensitivity = sensitivity915Mhz[1];
          cc1120cc1190RssiOffset = rssiOffset915Mhz[1];
        }
        break;      
      default:
        for(uint16 i = 0; i < (sizeof cc1120cc1190LowDataRateRfSettings/sizeof(registerSetting_t));i++)
        {
          data = cc1120cc1190LowDataRateRfSettings[i].data;
          cc112xSpiWriteReg(cc1120cc1190LowDataRateRfSettings[i].addr,&data,1);
        }
        if(perSettings.frequencyBand == 0){
          perSettings.sensitivity = sensitivity869Mhz[0];
          cc1120cc1190RssiOffset = rssiOffset869Mhz[0];          
        }
        else{
          perSettings.sensitivity = sensitivity915Mhz[0];
          cc1120cc1190RssiOffset = rssiOffset915Mhz[0];
        }
        break;
    }
  }
  else
  {
    /* Base settings for communication */
        for(uint16 i = 0; i < (sizeof cc1120cc1190LowDataRateRfSettings/sizeof(registerSetting_t));i++)
        {
          data = cc1120cc1190LowDataRateRfSettings[i].data;
          cc112xSpiWriteReg(cc1120cc1190LowDataRateRfSettings[i].addr,&data,1);
        }
        if(perSettings.frequencyBand == 0){
          perSettings.sensitivity = sensitivity869Mhz[0];
          cc1120cc1190RssiOffset = rssiOffset869Mhz[0];          
        }
        else{
          perSettings.sensitivity = sensitivity915Mhz[0];
          cc1120cc1190RssiOffset = rssiOffset915Mhz[0];
        }
  }
  /* Correct for chosen frequency band */     
  switch(perSettings.frequencyBand)      
  {  
   case 0:
      cc112xSpiWriteReg(CC112X_FS_CFG,&cc112xFsCfgs[0],1);
      cc112xSpiWriteReg(CC112X_FREQ2,freqConfiguration[0],3);
      break;
   case 1:
      cc112xSpiWriteReg(CC112X_FS_CFG,&cc112xFsCfgs[1],1);
      cc112xSpiWriteReg(CC112X_FREQ2,freqConfiguration[1],3);
      break;
    default: // 869.525 MHz
      cc112xSpiWriteReg(CC112X_FS_CFG,&cc112xFsCfgs[0],1);
      cc112xSpiWriteReg(CC112X_FREQ2,freqConfiguration[0],3);
      break;
  }    


  if(perSettings.masterSlaveLinked==PER_DEVICE_LINKED)
  {
    /* PKT_LEN set to user specified packet length: HW length filtering */
    cc112xSpiWriteReg(CC112X_PKT_LEN, &(perSettings.payloadLength),1);
    /* Turn on HW Address filtering */
    uint8 pkt_cfg1 = 0x10|0x05;
    cc112xSpiWriteReg(CC112X_PKT_CFG1,&pkt_cfg1,1);
    /* Set address */
    cc112xSpiWriteReg(CC112X_DEV_ADDR,&perSettings.address,1);
    /* Note: The Two-way link for the CC1120 PG1.0 use a different implementation
     *       of the two-way link on the master side than what CC1101 and CC1120 PG2.0 
     *       will. RXOFF and TXOFF mode is in this case the same as for the one-way link.
     *       
     */
    if((perSettings.linkTopology == LINK_2_WAY))
    {
      if(perSettings.deviceMode == MASTER_DEVICE)
      {
        /* IDLE after RX, RX after TX */
        data = 0x0F;
        cc112xSpiWriteReg(CC112X_RFEND_CFG1,&data,1);
        data = 0x30;
        cc112xSpiWriteReg(CC112X_RFEND_CFG0,&data,1);
      }
    } 
  }
   else if(perSettings.masterSlaveLinked == PER_DEVICE_LINK_BYPASS)
  {
    //Change sync word to apply to link bypass configuration
    for(uint16 i = 0; i < (sizeof linkBypassSettings/sizeof(registerSetting_t));i++)
    {
      data = linkBypassSettings[i].data;
      cc112xSpiWriteReg(linkBypassSettings[i].addr,&data,1);
    }  
    
    /* PKT_LEN set to user specified packet length: HW length filtering */
    cc112xSpiWriteReg(CC112X_PKT_LEN, &(perSettings.payloadLength),1);  
  }
  else
  {
    /* length of configuration packet + filter byte */
    data = PER_SETTINGS_PACKET_LEN; 
    cc112xSpiWriteReg(CC112X_PKT_LEN, &data,1);
  }  
  
  // do manual calibration according to errata
  manualCalibration();
  
  return;  
}
/*******************************************************************************
*   @fn         main
*
*   @brief      Runs the main routine
*
*   @param      none
*
*   @return     none
*/
void main(void) {

    uint8 writeByte;

    // Initialize MCU and peripherals
    initMCU();

    // Write radio registers (preferred settings from SmartRF Studio)
    registerConfig();

    // Application specific registers
    // FIFO_THR = 120
    // GPIO0 = RXFIFO_THR
    // GPIO2 = PKT_SYNC_RXTX
    // GPIO3 = PKT_SYNC_RXTX
    writeByte = INFINITE_PACKET_LENGTH_MODE;
    cc112xSpiWriteReg(CC112X_PKT_CFG0, &writeByte, 1);
    writeByte = 0x78; cc112xSpiWriteReg(CC112X_FIFO_CFG, &writeByte, 1);
    writeByte = 0x00; cc112xSpiWriteReg(CC112X_IOCFG0,   &writeByte, 1);
    writeByte = 0x06; cc112xSpiWriteReg(CC112X_IOCFG2,   &writeByte, 1);
    writeByte = 0x06; cc112xSpiWriteReg(CC112X_IOCFG3,   &writeByte, 1);

    bspLedSet(BSP_LED_ALL);
    
    // Calibrate the radio according to the errata note
    manualCalibration();

    // Connect ISR function to GPIO0
    ioPinIntRegister(IO_PIN_PORT_1, GPIO0, &rxFifoAboveThresholdISR);

    // Interrupt on falling edge
    ioPinIntTypeSet(IO_PIN_PORT_1, GPIO0, IO_PIN_RISING_EDGE);

    // Clear interrupt
    ioPinIntClear(IO_PIN_PORT_1, GPIO0);

    // Enable interrupt
    ioPinIntEnable(IO_PIN_PORT_1, GPIO0);

    // Connect ISR function to GPIO2
    ioPinIntRegister(IO_PIN_PORT_1, GPIO2, &syncReceivedISR);

    // Interrupt on falling edge
    ioPinIntTypeSet(IO_PIN_PORT_1, GPIO2, IO_PIN_RISING_EDGE);

    // Clear interrupt
    ioPinIntClear(IO_PIN_PORT_1, GPIO2);

    // Enable interrupt
    ioPinIntEnable(IO_PIN_PORT_1, GPIO2);

    // Set up interrupt on GPIO3 (PKT_SYNC_RXTX)
    ioPinIntRegister(IO_PIN_PORT_1, GPIO3, &packetReceivedISR);

    // Interrupt on falling edge
    ioPinIntTypeSet(IO_PIN_PORT_1, GPIO3, IO_PIN_FALLING_EDGE);

    printWelcomeMessage();

    while (TRUE) {
        switch (state) {

            //------------------------------------------------------------------
            case RX_START:
            //------------------------------------------------------------------
            trxSpiCmdStrobe(CC112X_SRX);
            pBufferIndex = rxBuffer;

            // Disable interrupt on GPIO3
            ioPinIntDisable(IO_PIN_PORT_1, GPIO3);

            state = RX_WAIT;

            //------------------------------------------------------------------
            case RX_WAIT:
            //------------------------------------------------------------------
            if (packetReceived) {
                packetReceived = FALSE;

                // Check CRC and update LCD if CRC OK
                if ((rxBuffer[packetLength + 3]) & CRC_OK)
                    updateLcd();

                // Change to infinite packet length mode
                pktFormat = INFINITE;
                writeByte = INFINITE_PACKET_LENGTH_MODE;
                cc112xSpiWriteReg(CC112X_PKT_CFG0, &writeByte, 1);

                state = RX_START;
            }
            break;

            //------------------------------------------------------------------
            default:
            //------------------------------------------------------------------

            break;
        }
    }
}