SX1261 and sx1262 common library

Dependents:   SX126xDevKit SX1262PingPong SX126X_TXonly SX126X_PingPong_Demo ... more

Fork of SX126xLib by Gregory Cristian

Revision:
4:c6ef863d0b07
Parent:
3:7e3595a9ebe0
Child:
5:e488e6f185f3
--- a/sx126x.cpp	Wed Oct 12 08:49:58 2016 +0000
+++ b/sx126x.cpp	Mon Sep 04 15:16:44 2017 +0000
@@ -1,26 +1,24 @@
 /*
+  ______                              _
  / _____)             _              | |
 ( (____  _____ ____ _| |_ _____  ____| |__
  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
  _____) ) ____| | | || |_| ____( (___| | | |
 (______/|_____)_|_|_| \__)_____)\____)_| |_|
-    (C)2016 Semtech
+    (C)2017 Semtech
 
-Description: Handling of the node configuration protocol
+Description: Generic SX126x driver implementation
 
 License: Revised BSD License, see LICENSE.TXT file include in the project
 
-Maintainer: Miguel Luis, Gregory Cristian and Matthieu Verdy
+Authors: Miguel Luis, Gregory Cristian
 */
 #include "mbed.h"
 #include "sx126x.h"
 #include "sx126x-hal.h"
 
-#include "pram_c005.h"
-
 /*!
- * Radio registers definition
- *
+ * \brief Radio registers definition
  */
 typedef struct
 {
@@ -28,424 +26,77 @@
     uint8_t       Value;                            //!< The value of the register
 }RadioRegisters_t;
 
-// [TODO] Is this also applicable for the V2 version of the chip
 /*!
- * \brief Radio hardware registers initialization definition
+ * \brief Stores the last frequency error measured on LoRa received packet
  */
-// { Address, RegValue }
-
-#define RADIO_INIT_REGISTERS_VALUE \
-{                                  \
-    { 0x0722, 0x53 },              \
-    { 0x0889, 0x01 },              \
-}
-
-/*!
- * \brief Radio hardware registers initialization
- */
-const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE;
+volatile uint32_t FrequencyError = 0;
 
 void SX126x::Init( void )
 {
+    /*!
+     * \brief pin OPT is used to detect if the board has a TCXO or a XTAL
+     *
+     * OPT = 0 >> TCXO; OPT = 1 >> XTAL
+     */
+    DigitalIn OPT( A3 );
+    
     Reset( );
+
     IoIrqInit( dioIrq );
+
     Wakeup( );
-/****************************************************/
     SetStandby( STDBY_RC );
-    WriteRegister( 0x610, 0x10 );
-    for( uint16_t i = 0; i < PRAM_COUNT; i++ )
+
+    if( OPT == 0 )
     {
-        uint32_t val = pram[i];
-        WriteRegister( 0x8000 + 4 * i, 0 );
-        WriteRegister( 0x8001 + 4 * i, ( val >> 16 ) & 0xff );
-        WriteRegister( 0x8002 + 4 * i, ( val >> 8 ) & 0xff  );
-        WriteRegister( 0x8003 + 4 * i, val & 0xff );
+        SetDio3AsTcxoCtrl( TCXO_CTRL_1_7V, 6400 ); //100 ms
+        WriteReg( REG_XTA_TRIM, 0x2F );
     }
-    WriteRegister( 0x610, 0x00 );
-    WriteCommand( RADIO_SET_PRAMSWAPCMD, ( uint8_t[] ) { 2 } , 1 );  //  RADIO_SET_PRAMSWAPCMD      = 0x8D,
-/****************************************************/
-    SetRegistersDefault( );
-}
+
+    SetPollingMode( );
+    
+    AntSwOn( );
+    SetDio2AsRfSwitchCtrl( true );
+
+    SetPacketType( PACKET_TYPE_LORA );
 
-void SX126x::SetRegistersDefault( void )
-{
-    for( uint8_t i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters_t ); i++ )
-    {
-        WriteRegister( RadioRegsInit[i].Addr, RadioRegsInit[i].Value );
-    }
+#ifdef USE_CONFIG_PUBLIC_NETOWRK
+    // Change LoRa modem Sync Word for Public Networks
+    WriteReg( REG_LR_SYNCWORD, ( LORA_MAC_PUBLIC_SYNCWORD >> 8 ) & 0xFF );
+    WriteReg( REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF );
+#else
+    // Change LoRa modem SyncWord for Private Networks
+    WriteReg( REG_LR_SYNCWORD, ( LORA_MAC_PRIVATE_SYNCWORD >> 8 ) & 0xFF );
+    WriteReg( REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF );
+#endif
 }
 
-uint16_t SX126x::GetFirmwareVersion( void )
-{
-    return( ( ( ReadRegister( 0xA8 ) ) << 8 ) | ( ReadRegister( 0xA9 ) ) );
-}
-
-RadioStatus_t SX126x::GetStatus( void )
+RadioOperatingModes_t SX126x::GetOperatingMode( void )
 {
-    uint8_t stat = 0;
-    RadioStatus_t status;
-
-    ReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 );
-    status.Value = stat;
-    
-    
-    return( status );
+    return OperatingMode;
 }
 
-void SX126x::SetSleep( SleepParams_t sleepConfig )
-{
-
-    WriteCommand( RADIO_SET_SLEEP, &sleepConfig.Value, 1 );
-    OperatingMode = MODE_SLEEP;
-}
-
-void SX126x::SetStandby( RadioStandbyModes_t standbyConfig )
+void SX126x::CheckDeviceReady( void )
 {
-    WriteCommand( RADIO_SET_STANDBY, ( uint8_t* )&standbyConfig, 1 );
-    if( standbyConfig == STDBY_RC )
+    if( ( GetOperatingMode( ) == MODE_SLEEP ) || ( GetOperatingMode( ) == MODE_RX_DC ) )
     {
-        OperatingMode = MODE_STDBY_RC;
-    }
-    else
-    {
-        OperatingMode = MODE_STDBY_XOSC;
+        Wakeup( );
+        // Switch is turned off when device is in sleep mode and turned on is all other modes
+        AntSwOn( );
     }
 }
 
-void SX126x::SetFs( void )
-{
-    WriteCommand( RADIO_SET_FS, 0, 0 );
-    OperatingMode = MODE_FS;
-}
-
-void SX126x::SetTx( uint32_t timeout )
-{
-    uint8_t buf[3];
-    buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF );
-    buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF );
-    buf[2] = ( uint8_t )( timeout & 0xFF );
-    WriteCommand( RADIO_SET_TX, buf, 3 );
-    OperatingMode = MODE_TX;
-}
-
-void SX126x::SetRx( uint32_t timeout )
-{
-    uint8_t buf[3];
-    buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF );
-    buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF );
-    buf[2] = ( uint8_t )( timeout & 0xFF );
-    WriteCommand( RADIO_SET_RX, buf, 3 );
-    OperatingMode = MODE_RX;
-}
-
-void SX126x::SetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime )
-{
-    uint8_t buf[6];
-
-    buf[0] = ( uint8_t )( ( rxTime >> 16 ) & 0xFF );
-    buf[1] = ( uint8_t )( ( rxTime >> 8 ) & 0xFF );
-    buf[2] = ( uint8_t )( rxTime & 0xFF );
-     buf[0] = ( uint8_t )( ( sleepTime >> 16 ) & 0xFF );
-    buf[1] = ( uint8_t )( ( sleepTime >> 8 ) & 0xFF );
-    buf[2] = ( uint8_t )( sleepTime & 0xFF );
-    WriteCommand( RADIO_SET_RXDUTYCYCLE, buf, 6 );
-    OperatingMode = MODE_RX;
-}
-
-void SX126x::SetCad( void )
-{
-    WriteCommand( RADIO_SET_CAD, 0, 0 );
-    OperatingMode = MODE_CAD;
-}
-
-void SX126x::SetAutoTxRx( uint32_t time, uint8_t intMode, uint32_t timeout )
-{
-    uint32_t compensatedTime = time - ( uint16_t )AUTO_RX_TX_OFFSET;
-    uint8_t buf[7];
-
-    buf[0] = ( uint8_t )( ( compensatedTime >> 16 ) & 0xFF );
-    buf[1] = ( uint8_t )( ( compensatedTime >> 8 ) & 0xFF );
-    buf[2] = ( uint8_t )( compensatedTime & 0xFF );
-    buf[3] = intMode;
-    buf[4] = ( uint8_t )( ( timeout >> 16 ) & 0xFF );
-    buf[5] = ( uint8_t )( ( timeout >> 8 ) & 0xFF );
-    buf[6] = ( uint8_t )( timeout & 0xFF );
-    WriteCommand( RADIO_SET_AUTOTXRX, buf, 7 );
-}
-
-
-void SX126x::SetTxContinuousWave( void )
-{
-    WriteCommand( RADIO_SET_TXCONTINUOUSWAVE, 0, 0 );
-}
-
-void SX126x::SetTxContinuousPreamble( void )
-{
-    WriteCommand( RADIO_SET_TXCONTINUOUSPREAMBLE, 0, 0 );
-}
-
-void SX126x::SetPacketType( RadioPacketType_t packetType )
-{
-    // Save packet type internally to avoid questioning the radio
-    this->PacketType = packetType;
-
-    WriteCommand( RADIO_SET_PACKETTYPE, ( uint8_t* )&packetType, 1 );
-}
-
-RadioPacketType_t SX126x::GetPacketType( void )
-{
-    return this->PacketType;
-}
-
-void SX126x::SetRfFrequency( uint32_t frequency )
-{
-    uint8_t buf[4];
-    uint32_t freq = 0;
-
-    freq = ( uint32_t )( ( double )frequency / ( double )FREQ_STEP );
-    buf[0] = ( uint8_t )( ( freq >> 24 ) & 0xFF );
-    buf[1] = ( uint8_t )( ( freq >> 16 ) & 0xFF );
-    buf[2] = ( uint8_t )( ( freq >> 8 ) & 0xFF );
-    buf[3] = ( uint8_t )( freq & 0xFF );
-    WriteCommand( RADIO_SET_RFFREQUENCY, buf, 3 );
-}
-
-void SX126x::SetTxParams( int8_t power, RadioRampTimes_t rampTime )
-{
-    uint8_t buf[2];
-    
-    buf[0] = power ;
-    buf[1] = ( uint8_t )rampTime;
-    WriteCommand( RADIO_SET_TXPARAMS, buf, 2 );
-}
-
-void SX126x::SetCadConfig( RadioLoRaCadSymbols_t cadSymbolNum , uint8_t cadExitMode, uint32_t cadRxTxTimeout)
-{
-    uint8_t buf[5];
-    buf[0] = ( uint8_t )cadSymbolNum;
-    buf[1] = cadExitMode;
-    buf[2] = ( uint8_t )( ( cadRxTxTimeout >> 16 ) & 0xFF );
-    buf[3] = ( uint8_t )( ( cadRxTxTimeout >> 8 ) & 0xFF );
-    buf[4] = ( uint8_t )( cadRxTxTimeout & 0xFF );
-    WriteCommand( RADIO_SET_CADPARAMS, buf, 5 );
-    OperatingMode = MODE_CAD;
-}
-
-void SX126x::SetBufferBaseAddresses( uint8_t txBaseAddress, uint8_t rxBaseAddress )
-{
-    uint8_t buf[2];
-
-    buf[0] = txBaseAddress;
-    buf[1] = rxBaseAddress;
-    WriteCommand( RADIO_SET_BUFFERBASEADDRESS, buf, 2 );
-}
-
-void SX126x::SetModulationParams( ModulationParams_t *modulationParams )
+void SX126x::SetPayload( uint8_t *payload, uint8_t size )
 {
-    uint8_t n;
-    uint32_t tempVal = 0;
-    uint8_t buf[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-    
-    // Check if required configuration corresponds to the stored packet type
-    // If not, silently update radio packet type
-    if( this->PacketType != modulationParams->PacketType )
-    {
-        this->SetPacketType( modulationParams->PacketType );
-    }
-
-    switch( modulationParams->PacketType )
-    {
-        case PACKET_TYPE_GFSK:
-            tempVal = ( uint32_t )( ( double )XTAL_FREQ / ( double )modulationParams->Params.Gfsk.BitRate );
-            tempVal = tempVal * 32;
-            buf[0] = ( tempVal >> 16 ) & 0xFF;
-            buf[1] = ( tempVal >> 8 ) & 0xFF;
-            buf[2] = tempVal & 0xFF;
-            
-            buf[3] = modulationParams->Params.Gfsk.PulseShape;
-            buf[4] = modulationParams->Params.Gfsk.BW;
-        
-            tempVal = ( uint32_t )( ( double )FREQ_STEP * ( double )modulationParams->Params.Gfsk.Fdev );
-            buf[5] = ( tempVal >> 16 ) & 0xFF;
-            buf[6] = ( tempVal >> 8 ) & 0xFF;
-            buf[7] = ( tempVal& 0xFF );
-            n = 8;
-            break;
-        
-        case PACKET_TYPE_LORA:
-            n = 3;
-            buf[0] = modulationParams->Params.LoRa.SpreadingFactor;
-            buf[1] = modulationParams->Params.LoRa.Bandwidth;
-            buf[2] = modulationParams->Params.LoRa.CodingRate;       
-            break;
-        
-        case PACKET_TYPE_RESERVED:
-            return;
-    }
-    WriteCommand( RADIO_SET_MODULATIONPARAMS, buf, n );
-}
-
-void SX126x::SetPacketParams( PacketParams_t *packetParams )
-{
-    uint8_t n;
-    
-    // Check if required configuration corresponds to the stored packet type
-    // If not, silently update radio packet type
-    if( this->PacketType != packetParams->PacketType )
-    {
-        this->SetPacketType( packetParams->PacketType );
-    }
-
-    switch( packetParams->PacketType )
-    {
-        case PACKET_TYPE_GFSK:
-            n = 8;
-            break; 
-        case PACKET_TYPE_LORA:
-            n = 5;
-            break;
-        case PACKET_TYPE_RESERVED:
-           return;
-    }
-    WriteCommand( RADIO_SET_PACKETPARAMS, packetParams->Params.Buffer, n );
-}
-
-void SX126x::GetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPointer )
-{
-    uint8_t status[2];
-
-    ReadCommand( RADIO_GET_RXBUFFERSTATUS, status, 2 );
-
-    *payloadLength = status[0];
-    *rxStartBufferPointer = status[1];
-}
-
-void SX126x::GetPacketStatus( PacketStatus_t *pktStatus )
-{
-    uint8_t status[3];
-
-
-    ReadCommand( RADIO_GET_PACKETSTATUS, status, 3 );
-
-    pktStatus->packetType = this -> GetPacketType( );
-    switch( pktStatus->packetType )
-    {
-        case PACKET_TYPE_GFSK:
-            pktStatus->Gfsk.RxStatus = status[0];
-            pktStatus->Gfsk.RssiSync = -status[1] / 2;
-            pktStatus->Gfsk.RssiAvg = -status[2] / 2;
-            break;
-
-        case PACKET_TYPE_LORA:
-            pktStatus->LoRa.RssiPkt = -status[0] / 2;
-            ( status[1] < 128 ) ? ( pktStatus->LoRa.SnrPkt = status[1] / 4 ) : ( pktStatus->LoRa.SnrPkt = ( ( status[1] - 256 ) /4 ) );
-            pktStatus->LoRa.SignalRssiPkt = -status[2] / 2;
-            break;
-
-        case PACKET_TYPE_RESERVED:
-            // In that specific case, we set everything in the pktStatus to zeros
-            // and reset the packet type accordingly
-            memset( pktStatus, 0, sizeof( PacketStatus_t ) );
-            pktStatus->packetType = PACKET_TYPE_RESERVED;
-            break;
-    }
-}
-
-int8_t SX126x::GetRssiInst( void )
-{
-    int8_t rssi;
-
-    ReadCommand( RADIO_GET_RSSIINST, ( uint8_t* )&rssi, 1 );
-    return -rssi / 2;
-}
-
-void SX126x::GetStats( RxCounter_t *rxCounter )
-{
-    uint8_t status[6];
-
-
-    rxCounter->packetType = this -> GetPacketType( );
-    ReadCommand( RADIO_GET_STATS, status, 6 );
-    rxCounter->NbPktReceived = ( status[0] << 8 ) | status[1];
-    rxCounter->NbPktCrcOk = ( status[2] << 8 ) | status[3];
-    rxCounter->NbPktLengthError = ( status[4] << 8 ) | status[4];
-}
-
-void SX126x::ResetStats(  )
-{
-    uint8_t status[6];
-
-    memset( status, 0, sizeof( status ) );
-    WriteCommand( RADIO_RESET_STATS, status, 6 );
-}
-
-uint8_t SX126x::GetError()
-{
-    uint8_t error;
-
-    ReadCommand( RADIO_GET_ERROR, &error, 1 );
-    return error; 
-}
-
-
-void SX126x::SetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask )
-{
-    uint8_t buf[8];
-
-    buf[0] = ( uint8_t )( ( irqMask >> 8 ) & 0x00FF );
-    buf[1] = ( uint8_t )( irqMask & 0x00FF );
-    buf[2] = ( uint8_t )( ( dio1Mask >> 8 ) & 0x00FF );
-    buf[3] = ( uint8_t )( dio1Mask & 0x00FF );
-    buf[4] = ( uint8_t )( ( dio2Mask >> 8 ) & 0x00FF );
-    buf[5] = ( uint8_t )( dio2Mask & 0x00FF );
-    buf[6] = ( uint8_t )( ( dio3Mask >> 8 ) & 0x00FF );
-    buf[7] = ( uint8_t )( dio3Mask & 0x00FF );
-    WriteCommand( RADIO_CFG_DIOIRQ, buf, 8 );
-}
-
-uint16_t SX126x::GetIrqStatus( void )
-{
-    uint8_t irqStatus[2];
-    ReadCommand( RADIO_GET_IRQSTATUS, irqStatus, 2 );
-    return ( irqStatus[0] << 8 ) | irqStatus[1];
-}
-
-void SX126x::ClearIrqStatus( uint16_t irq )
-{
-    uint8_t buf[2];
-
-    buf[0] = ( uint8_t )( ( ( uint16_t )irq >> 8 ) & 0x00FF );
-    buf[1] = ( uint8_t )( ( uint16_t )irq & 0x00FF );
-    WriteCommand( RADIO_CLR_IRQSTATUS, buf, 2 );
-}
-
-void SX126x::Calibrate( CalibrationParams_t calibParam )
-{
-    WriteCommand( RADIO_CALIBRATE, &calibParam.Value, 1 );
-}
-
-void SX126x::SetRegulatorMode( uint8_t mode )
-{
-    WriteCommand( RADIO_SET_REGULATORMODE, &mode, 1 );
-}
-
-
-void SX126x::SetLongPreamble( uint8_t enable )
-{
-    WriteCommand( RADIO_SET_LONGPREAMBLE, &enable, 1 );
-}
-
-void SX126x::SetPayload( uint8_t *buffer, uint8_t size )
-{
-    WriteBuffer( 0x00, buffer, size );
+    WriteBuffer( 0x00, payload, size );
 }
 
 uint8_t SX126x::GetPayload( uint8_t *buffer, uint8_t *size,  uint8_t maxSize )
 {
-    uint8_t offset;
+    uint8_t offset = 0;
 
     GetRxBufferStatus( size, &offset );
-    if(*size > maxSize)
+    if( *size > maxSize )
     {
         return 1;
     }
@@ -468,14 +119,16 @@
 void SX126x::SetCrcSeed( uint16_t seed )
 {
     uint8_t buf[2];
+
     buf[0] = ( uint8_t )( ( seed >> 8 ) & 0xFF );
     buf[1] = ( uint8_t )( seed & 0xFF );
-    
+
     switch( GetPacketType( ) )
     {
         case PACKET_TYPE_GFSK:
             WriteRegister( REG_LR_CRCSEEDBASEADDR, buf, 2 );
             break;
+
         default:
             break;
     }
@@ -484,147 +137,721 @@
 void SX126x::SetCrcPolynomial( uint16_t polynomial )
 {
     uint8_t buf[2];
+
     buf[0] = ( uint8_t )( ( polynomial >> 8 ) & 0xFF );
     buf[1] = ( uint8_t )( polynomial & 0xFF );
-    
+
     switch( GetPacketType( ) )
     {
         case PACKET_TYPE_GFSK:
             WriteRegister( REG_LR_CRCPOLYBASEADDR, buf, 2 );
             break;
+
         default:
             break;
     }
 }
 
-void SX126x::SetWhiteningSeed( uint8_t seed )
+void SX126x::SetWhiteningSeed( uint16_t seed )
 {
+    uint8_t regValue = 0;
+
     switch( GetPacketType( ) )
     {
         case PACKET_TYPE_GFSK:
-            WriteRegister( REG_LR_WHITSEEDBASEADDR, seed );
+            regValue = ReadReg( REG_LR_WHITSEEDBASEADDR_MSB ) & 0xFE;
+            regValue = ( ( seed >> 8 ) & 0x01 ) | regValue;
+            WriteReg( REG_LR_WHITSEEDBASEADDR_MSB, regValue ); // only 1 bit.
+            WriteReg( REG_LR_WHITSEEDBASEADDR_LSB, ( uint8_t )seed );
             break;
+
         default:
             break;
     }
 }
 
-int8_t SX126x::ParseHexFileLine( char* line )
+uint32_t SX126x::GetRandom( void )
+{
+    uint8_t buf[] = { 0, 0, 0, 0 };
+
+    // Set radio in continuous reception
+    SetRx( 0 );
+
+    wait_ms( 1 );
+
+    ReadRegister( RANDOM_NUMBER_GENERATORBASEADDR, buf, 4 );
+
+    SetStandby( STDBY_RC );
+
+    return ( buf[0] << 24 ) | ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3];
+}
+
+void SX126x::SetSleep( SleepParams_t sleepConfig )
 {
-    uint16_t addr;
-    uint16_t n;
-    uint8_t code;
-    uint8_t bytes[256];
+#ifdef ADV_DEBUG
+    printf("SetSleep ");
+#endif
+
+    AntSwOff( );
+
+    WriteCommand( RADIO_SET_SLEEP, &sleepConfig.Value, 1 );
+    OperatingMode = MODE_SLEEP;
+}
 
-    if( GetHexFileLineFields( line, bytes, &addr, &n, &code ) != 0 )
+void SX126x::SetStandby( RadioStandbyModes_t standbyConfig )
+{
+#ifdef ADV_DEBUG
+    printf("SetStandby ");
+#endif
+    WriteCommand( RADIO_SET_STANDBY, ( uint8_t* )&standbyConfig, 1 );
+    if( standbyConfig == STDBY_RC )
+    {
+        OperatingMode = MODE_STDBY_RC;
+    }
+    else
     {
-        if( code == 0 )
+        OperatingMode = MODE_STDBY_XOSC;
+    }
+}
+
+void SX126x::SetFs( void )
+{
+#ifdef ADV_DEBUG
+    printf("SetFs ");
+#endif
+    WriteCommand( RADIO_SET_FS, 0, 0 );
+    OperatingMode = MODE_FS;
+}
+
+void SX126x::SetTx( uint32_t timeout )
+{
+    uint8_t buf[3];
+
+    OperatingMode = MODE_TX;
+ 
+#ifdef ADV_DEBUG
+    printf("SetTx ");
+#endif
+
+    buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF );
+    buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF );
+    buf[2] = ( uint8_t )( timeout & 0xFF );
+    WriteCommand( RADIO_SET_TX, buf, 3 );
+}
+
+void SX126x::SetRxBoosted( uint32_t timeout )
+{
+    uint8_t buf[3];
+
+    OperatingMode = MODE_RX;
+
+#ifdef ADV_DEBUG
+    printf("SetRxBoosted ");
+#endif
+
+    WriteReg( REG_RX_GAIN, 0x96 ); // max LNA gain, increase current by ~2mA for around ~3dB in sensivity
+
+    buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF );
+    buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF );
+    buf[2] = ( uint8_t )( timeout & 0xFF );
+    WriteCommand( RADIO_SET_RX, buf, 3 );
+}
+
+void SX126x::SetRx( uint32_t timeout )
+{
+    uint8_t buf[3];
+
+    OperatingMode = MODE_RX;
+
+#ifdef ADV_DEBUG
+    printf("SetRx ");
+#endif
+
+    buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF );
+    buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF );
+    buf[2] = ( uint8_t )( timeout & 0xFF );
+    WriteCommand( RADIO_SET_RX, buf, 3 );
+}
+
+void SX126x::SetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime )
+{
+    uint8_t buf[6];
+
+    SetLongPreamble( true );
+
+    buf[0] = ( uint8_t )( ( rxTime >> 16 ) & 0xFF );
+    buf[1] = ( uint8_t )( ( rxTime >> 8 ) & 0xFF );
+    buf[2] = ( uint8_t )( rxTime & 0xFF );
+    buf[3] = ( uint8_t )( ( sleepTime >> 16 ) & 0xFF );
+    buf[4] = ( uint8_t )( ( sleepTime >> 8 ) & 0xFF );
+    buf[5] = ( uint8_t )( sleepTime & 0xFF );
+    WriteCommand( RADIO_SET_RXDUTYCYCLE, buf, 6 );
+    OperatingMode = MODE_RX_DC;
+}
+
+void SX126x::SetCad( void )
+{
+    WriteCommand( RADIO_SET_CAD, 0, 0 );
+    OperatingMode = MODE_CAD;
+}
+
+void SX126x::SetTxContinuousWave( void )
+{
+#ifdef ADV_DEBUG
+    printf("SetTxContinuousWave ");
+#endif
+    WriteCommand( RADIO_SET_TXCONTINUOUSWAVE, 0, 0 );
+}
+
+void SX126x::SetTxInfinitePreamble( void )
+{
+#ifdef ADV_DEBUG
+    printf("SetTxContinuousPreamble ");
+#endif
+    WriteCommand( RADIO_SET_TXCONTINUOUSPREAMBLE, 0, 0 );
+}
+
+void SX126x::SetStopRxTimerOnPreambleDetect( bool enable )
+{
+    WriteCommand( RADIO_SET_STOPRXTIMERONPREAMBLE, ( uint8_t* )&enable, 1 );
+}
+
+void SX126x::SetLoRaSymbNumTimeout( uint8_t SymbNum )
+{
+    WriteCommand( RADIO_SET_LORASYMBTIMEOUT, &SymbNum, 1 );
+}
+
+void SX126x::SetRegulatorMode( RadioRegulatorMode_t mode )
+{
+#ifdef ADV_DEBUG
+    printf("SetRegulatorMode ");
+#endif
+    WriteCommand( RADIO_SET_REGULATORMODE, ( uint8_t* )&mode, 1 );
+}
+
+void SX126x::Calibrate( CalibrationParams_t calibParam )
+{
+    WriteCommand( RADIO_CALIBRATE, &calibParam.Value, 1 );
+}
+
+void SX126x::SetLongPreamble( uint8_t enable )
+{
+    WriteCommand( RADIO_SET_LONGPREAMBLE, &enable, 1 );
+}
+
+void SX126x::SetPaConfig( uint8_t paDutyCycle, uint8_t HpMax, uint8_t deviceSel, uint8_t paLUT )
+{
+    uint8_t buf[4];
+
+#ifdef ADV_DEBUG
+    printf("SetPaConfig ");
+#endif
+
+    buf[0] = paDutyCycle;
+    buf[1] = HpMax;
+    buf[2] = deviceSel;
+    buf[3] = paLUT;
+    WriteCommand( RADIO_SET_PACONFIG, buf, 4 );
+}
+
+void SX126x::SetRxTxFallbackMode( uint8_t fallbackMode )
+{
+    WriteCommand( RADIO_SET_TXFALLBACKMODE, &fallbackMode, 1 );
+}
+
+void SX126x::SetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask )
+{
+    uint8_t buf[8];
+
+#ifdef ADV_DEBUG
+    printf("SetDioIrqParams ");
+#endif
+
+    buf[0] = ( uint8_t )( ( irqMask >> 8 ) & 0x00FF );
+    buf[1] = ( uint8_t )( irqMask & 0x00FF );
+    buf[2] = ( uint8_t )( ( dio1Mask >> 8 ) & 0x00FF );
+    buf[3] = ( uint8_t )( dio1Mask & 0x00FF );
+    buf[4] = ( uint8_t )( ( dio2Mask >> 8 ) & 0x00FF );
+    buf[5] = ( uint8_t )( dio2Mask & 0x00FF );
+    buf[6] = ( uint8_t )( ( dio3Mask >> 8 ) & 0x00FF );
+    buf[7] = ( uint8_t )( dio3Mask & 0x00FF );
+    WriteCommand( RADIO_CFG_DIOIRQ, buf, 8 );
+}
+
+uint16_t SX126x::GetIrqStatus( void )
+{
+    uint8_t irqStatus[2];
+
+    ReadCommand( RADIO_GET_IRQSTATUS, irqStatus, 2 );
+    return ( irqStatus[0] << 8 ) | irqStatus[1];
+}
+
+void SX126x::SetDio2AsRfSwitchCtrl( uint8_t enable )
+{
+#ifdef ADV_DEBUG
+    printf("SetDio2AsRfSwitchCtrl ");
+#endif
+    WriteCommand( RADIO_SET_RFSWITCHMODE, &enable, 1 );
+}
+
+void SX126x::SetDio3AsTcxoCtrl( RadioTcxoCtrlVoltage_t tcxoVoltage, uint32_t timeout )
+{
+    uint8_t buf[4];
+    
+    buf[0] = tcxoVoltage & 0x08;
+    buf[1] = ( uint8_t )( ( timeout >> 16 ) & 0xFF );
+    buf[2] = ( uint8_t )( ( timeout >> 8 ) & 0xFF );
+    buf[3] = ( uint8_t )( timeout & 0xFF );
+
+    WriteCommand( RADIO_SET_TCXOMODE, buf, 4 );
+}
+
+void SX126x::SetRfFrequency( uint32_t frequency )
+{
+    uint8_t buf[4];
+    uint32_t freq = 0;
+
+#ifdef ADV_DEBUG
+    printf("SetRfFrequency ");
+#endif
+
+    freq = ( uint32_t )( ( double )frequency / ( double )FREQ_STEP );
+    buf[0] = ( uint8_t )( ( freq >> 24 ) & 0xFF );
+    buf[1] = ( uint8_t )( ( freq >> 16 ) & 0xFF );
+    buf[2] = ( uint8_t )( ( freq >> 8 ) & 0xFF );
+    buf[3] = ( uint8_t )( freq & 0xFF );
+    WriteCommand( RADIO_SET_RFFREQUENCY, buf, 4 );
+}
+
+void SX126x::SetPacketType( RadioPacketTypes_t packetType )
+{
+#ifdef ADV_DEBUG
+    printf("SetPacketType ");
+#endif
+
+    // Save packet type internally to avoid questioning the radio
+    this->PacketType = packetType;
+
+    if( packetType == PACKET_TYPE_GFSK )
+    {
+        WriteReg( REG_BIT_SYNC, 0x00 );
+    }
+
+    WriteCommand( RADIO_SET_PACKETTYPE, ( uint8_t* )&packetType, 1 );
+}
+
+RadioPacketTypes_t SX126x::GetPacketType( void )
+{
+    return this->PacketType;
+}
+
+void SX126x::SetTxParams( int8_t power, RadioRampTimes_t rampTime )
+{
+    uint8_t buf[2];
+    DigitalIn OPT( A3 );
+
+#ifdef ADV_DEBUG
+    printf("SetTxParams ");
+#endif
+
+    if( GetDeviceType( ) == 1 ) // sx1261
+    {
+        if( power == 15 )
         {
-            WriteRegister( addr, bytes, n );
+            SetPaConfig( 0x06, 0x00, 0x01, 0x00 );
         }
-        if( code == 1 )
-        { // end of file
-            //return 2;
+        else
+        {
+            SetPaConfig( 0x04, 0x00, 0x01, 0x00 );  
+        }
+        if( power >= 14 )
+        {
+            power = 14;
+        } 
+        else if( power < -3 )
+        {
+            power = -3;
         }
-        if( code == 2 )
-        { // begin of file
-            //return 3;
+    }
+    else // sx1262
+    {
+        SetPaConfig( 0x04, 0x07, 0x00, 0x01 );
+        if( power > 22 )
+        {
+            power = 22;
+        } 
+        else if( power < -3 )
+        {
+            power = -3;
+        }
+    }
+    buf[0] = power;
+    if( OPT == 0 )
+    {
+        if( ( uint8_t )rampTime < RADIO_RAMP_200_US )
+        {
+            buf[1] = RADIO_RAMP_200_US;
+        }
+        else
+        {
+            buf[1] = ( uint8_t )rampTime;
         }
     }
     else
     {
-        return 0;
+        buf[1] = ( uint8_t )rampTime;
+    }
+    WriteCommand( RADIO_SET_TXPARAMS, buf, 2 );
+}
+
+void SX126x::SetModulationParams( ModulationParams_t *modulationParams )
+{
+    uint8_t n;
+    uint32_t tempVal = 0;
+    uint8_t buf[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+#ifdef ADV_DEBUG
+    printf("SetModulationParams ");
+#endif
+
+    // Check if required configuration corresponds to the stored packet type
+    // If not, silently update radio packet type
+    if( this->PacketType != modulationParams->PacketType )
+    {
+        this->SetPacketType( modulationParams->PacketType );
     }
-    return 1;
+
+    switch( modulationParams->PacketType )
+    {
+    case PACKET_TYPE_GFSK:
+        n = 8;
+        tempVal = ( uint32_t )( 32 * ( ( double )XTAL_FREQ / ( double )modulationParams->Params.Gfsk.BitRate ) );
+        buf[0] = ( tempVal >> 16 ) & 0xFF;
+        buf[1] = ( tempVal >> 8 ) & 0xFF;
+        buf[2] = tempVal & 0xFF;
+        buf[3] = modulationParams->Params.Gfsk.ModulationShaping;
+        buf[4] = modulationParams->Params.Gfsk.Bandwidth;
+        tempVal = ( uint32_t )( ( double )modulationParams->Params.Gfsk.Fdev / ( double )FREQ_STEP );
+        buf[5] = ( tempVal >> 16 ) & 0xFF;
+        buf[6] = ( tempVal >> 8 ) & 0xFF;
+        buf[7] = ( tempVal& 0xFF );
+        break;
+    case PACKET_TYPE_LORA:
+        n = 4;
+        switch( modulationParams->Params.LoRa.Bandwidth )
+        {
+            case LORA_BW_500:
+                 modulationParams->Params.LoRa.LowDatarateOptimize = 0x00;
+                break;
+            case LORA_BW_250:
+                if( modulationParams->Params.LoRa.SpreadingFactor == 12 )
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x01;
+                }
+                else
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x00;
+                }
+                break;
+            case LORA_BW_125:
+                if( modulationParams->Params.LoRa.SpreadingFactor >= 11 )
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x01;
+                }
+                else
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x00;
+                }
+                break;
+            case LORA_BW_062:
+                if( modulationParams->Params.LoRa.SpreadingFactor >= 10 )
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x01;
+                }
+                else
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x00;
+                }
+                break;
+            case LORA_BW_041:
+                if( modulationParams->Params.LoRa.SpreadingFactor >= 9 )
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x01;
+                }
+                else
+                {
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x00;
+                }
+                break;
+            case LORA_BW_031:
+            case LORA_BW_020:
+            case LORA_BW_015:
+            case LORA_BW_010:
+            case LORA_BW_007:
+                    modulationParams->Params.LoRa.LowDatarateOptimize = 0x01;
+                break;
+            default:
+                break;
+        }
+        buf[0] = modulationParams->Params.LoRa.SpreadingFactor;
+        buf[1] = modulationParams->Params.LoRa.Bandwidth;
+        buf[2] = modulationParams->Params.LoRa.CodingRate;
+        buf[3] = modulationParams->Params.LoRa.LowDatarateOptimize;
+        break;
+    default:
+    case PACKET_TYPE_NONE:
+        return;
+    }
+    WriteCommand( RADIO_SET_MODULATIONPARAMS, buf, n );
 }
 
-int8_t SX126x::GetHexFileLineFields( char* line, uint8_t *bytes, uint16_t *addr, uint16_t *num, uint8_t *code )
+void SX126x::SetPacketParams( PacketParams_t *packetParams )
 {
-    uint16_t sum, len, cksum;
-    char *ptr;
+    uint8_t n;
+    uint8_t crcVal = 0;
+    uint8_t buf[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-    *num = 0;
-    if( line[0] != ':' )
-    {
-        return 0;
-    }
-    if( strlen( line ) < 11 )
-    {
-        return 0;
-    }
-    ptr = line + 1;
-    if( !sscanf( ptr, "%02hx", &len ) )
-    {
-        return 0;
-    }
-    ptr += 2;
-    if( strlen( line ) < ( 11 + ( len * 2 ) ) )
-    {
-        return 0;
-    }
-    if( !sscanf( ptr, "%04hx", addr ) )
+#ifdef ADV_DEBUG
+    printf("SetPacketParams ");
+#endif
+
+    // Check if required configuration corresponds to the stored packet type
+    // If not, silently update radio packet type
+    if( this->PacketType != packetParams->PacketType )
     {
-        return 0;
-    }
-    ptr += 4;
-    if( !sscanf( ptr, "%02hhx", code ) )
-    {
-        return 0;
-    }
-    ptr += 2;
-    sum = ( len & 255 ) + ( ( *addr >> 8 ) & 255 ) + ( *addr & 255 ) + ( ( *code >> 8 ) & 255 ) + ( *code & 255 );
-    while( *num != len )
-    {
-        if( !sscanf( ptr, "%02hhx", &bytes[*num] ) )
-        {
-            return 0;
-        }
-        ptr += 2;
-        sum += bytes[*num] & 255;
-        ( *num )++;
-        if( *num >= 256 )
-        {
-            return 0;
-        }
-    }
-    if( !sscanf( ptr, "%02hx", &cksum ) )
-    {
-        return 0;
-    }
-    if( ( ( sum & 255 ) + ( cksum & 255 ) ) & 255 )
-    {
-        return 0; // checksum error
+        this->SetPacketType( packetParams->PacketType );
     }
 
-    return 1;
+    switch( packetParams->PacketType )
+    {
+    case PACKET_TYPE_GFSK:
+        if( packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_IBM )
+        {
+            SetCrcSeed( CRC_IBM_SEED );
+            SetCrcPolynomial( CRC_POLYNOMIAL_IBM );
+            crcVal = RADIO_CRC_2_BYTES;
+        }
+        else if(  packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_CCIT )
+        {
+            SetCrcSeed( CRC_CCITT_SEED );
+            SetCrcPolynomial( CRC_POLYNOMIAL_CCITT );
+            crcVal = RADIO_CRC_2_BYTES_INV;
+        }
+        else
+        {
+            crcVal = packetParams->Params.Gfsk.CrcLength;
+        }
+        n = 9;
+        // convert preamble length from byte to bit
+        packetParams->Params.Gfsk.PreambleLength = packetParams->Params.Gfsk.PreambleLength << 3;
+
+        buf[0] = ( packetParams->Params.Gfsk.PreambleLength >> 8 ) & 0xFF;
+        buf[1] = packetParams->Params.Gfsk.PreambleLength;
+        buf[2] = packetParams->Params.Gfsk.PreambleMinDetect;
+        buf[3] = ( packetParams->Params.Gfsk.SyncWordLength << 3 ); // convert from byte to bit
+        buf[4] = packetParams->Params.Gfsk.AddrComp;
+        buf[5] = packetParams->Params.Gfsk.HeaderType;
+        buf[6] = packetParams->Params.Gfsk.PayloadLength;
+        buf[7] = crcVal;
+        buf[8] = packetParams->Params.Gfsk.DcFree;
+        break;
+    case PACKET_TYPE_LORA:
+        n = 6;
+        buf[0] = ( packetParams->Params.LoRa.PreambleLength >> 8 ) & 0xFF;
+        buf[1] = packetParams->Params.LoRa.PreambleLength;
+        buf[2] = packetParams->Params.LoRa.HeaderType;
+        buf[3] = packetParams->Params.LoRa.PayloadLength;
+        buf[4] = packetParams->Params.LoRa.CrcMode;
+        buf[5] = packetParams->Params.LoRa.InvertIQ;
+        break;
+    default:
+    case PACKET_TYPE_NONE:
+        return;
+    }
+    WriteCommand( RADIO_SET_PACKETPARAMS, buf, n );
+}
+
+void SX126x::SetCadParams( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, RadioCadExitModes_t cadExitMode, uint32_t cadTimeout )
+{
+    uint8_t buf[7];
+
+    buf[0] = ( uint8_t )cadSymbolNum;
+    buf[1] = cadDetPeak;
+    buf[2] = cadDetMin;
+    buf[3] = ( uint8_t )cadExitMode;
+    buf[4] = ( uint8_t )( ( cadTimeout >> 16 ) & 0xFF );
+    buf[5] = ( uint8_t )( ( cadTimeout >> 8 ) & 0xFF );
+    buf[6] = ( uint8_t )( cadTimeout & 0xFF );
+    WriteCommand( RADIO_SET_CADPARAMS, buf, 5 );
+    OperatingMode = MODE_CAD;
+}
+
+void SX126x::SetBufferBaseAddresses( uint8_t txBaseAddress, uint8_t rxBaseAddress )
+{
+    uint8_t buf[2];
+
+#ifdef ADV_DEBUG
+    printf("SetBufferBaseAddresses ");
+#endif
+
+    buf[0] = txBaseAddress;
+    buf[1] = rxBaseAddress;
+    WriteCommand( RADIO_SET_BUFFERBASEADDRESS, buf, 2 );
+}
+
+RadioStatus_t SX126x::GetStatus( void )
+{
+    uint8_t stat = 0;
+    RadioStatus_t status;
+
+    ReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 );
+    status.Value = stat;
+    return status;
+}
+
+int8_t SX126x::GetRssiInst( void )
+{
+    int8_t rssi;
+
+    ReadCommand( RADIO_GET_RSSIINST, ( uint8_t* )&rssi, 1 );
+    return( -( rssi / 2 ) );
+}
+
+void SX126x::GetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPointer )
+{
+    uint8_t status[2];
+
+    ReadCommand( RADIO_GET_RXBUFFERSTATUS, status, 2 );
+
+    // In case of LORA fixed header, the payloadLength is obtained by reading
+    // the register REG_LR_PAYLOADLENGTH
+    if( ( this->GetPacketType( ) == PACKET_TYPE_LORA ) && ( ReadReg( REG_LR_PACKETPARAMS ) >> 7 == 1 ) )
+    {
+        *payloadLength = ReadReg( REG_LR_PAYLOADLENGTH );
+    }
+    else
+    {
+        *payloadLength = status[0];
+    }
+    *rxStartBufferPointer = status[1];
+}
+
+void SX126x::GetPacketStatus( PacketStatus_t *pktStatus )
+{
+    uint8_t status[3];
+
+    ReadCommand( RADIO_GET_PACKETSTATUS, status, 3 );
+
+    pktStatus->packetType = this -> GetPacketType( );
+    switch( pktStatus->packetType )
+    {
+        case PACKET_TYPE_GFSK:
+            pktStatus->Params.Gfsk.RxStatus = status[0];
+            pktStatus->Params.Gfsk.RssiSync = -status[1] / 2;
+            pktStatus->Params.Gfsk.RssiAvg = -status[2] / 2;
+            pktStatus->Params.Gfsk.FreqError = 0;
+            break;
+
+        case PACKET_TYPE_LORA:
+            pktStatus->Params.LoRa.RssiPkt = -status[0] / 2;
+            ( status[1] < 128 ) ? ( pktStatus->Params.LoRa.SnrPkt = status[1] / 4 ) : ( pktStatus->Params.LoRa.SnrPkt = ( ( status[1] - 256 ) /4 ) );
+            pktStatus->Params.LoRa.SignalRssiPkt = -status[2] / 2;
+            pktStatus->Params.LoRa.FreqError = FrequencyError;
+            break;
+
+        default:
+        case PACKET_TYPE_NONE:
+            // In that specific case, we set everything in the pktStatus to zeros
+            // and reset the packet type accordingly
+            memset( pktStatus, 0, sizeof( PacketStatus_t ) );
+            pktStatus->packetType = PACKET_TYPE_NONE;
+            break;
+    }
+}
+
+RadioError_t SX126x::GetDeviceErrors( void )
+{
+    RadioError_t error;
+
+    ReadCommand( RADIO_GET_ERROR, ( uint8_t * )&error, 2 );
+    return error; 
+}
+
+void SX126x::ClearIrqStatus( uint16_t irq )
+{
+    uint8_t buf[2];
+#ifdef ADV_DEBUG
+    printf("ClearIrqStatus ");
+#endif
+    buf[0] = ( uint8_t )( ( ( uint16_t )irq >> 8 ) & 0x00FF );
+    buf[1] = ( uint8_t )( ( uint16_t )irq & 0x00FF );
+    WriteCommand( RADIO_CLR_IRQSTATUS, buf, 2 );
+}
+
+void SX126x::SetPollingMode( void )
+{
+    this->PollingMode = true;
+}
+
+void SX126x::SetInterruptMode( void )
+{
+    this->PollingMode = false;
 }
 
 void SX126x::OnDioIrq( void )
 {
-    if( onCustomDioIrq != NULL )
+    /*
+     * When polling mode is activated, it is up to the application to call
+     * ProcessIrqs( ). Otherwise, the driver automatically calls ProcessIrqs( )
+     * on radio interrupt.
+     */
+    if( this->PollingMode == true )
+    {
+        this->IrqState = true;
+    }
+    else
     {
-        onCustomDioIrq();
-        return;
+        this->ProcessIrqs( );
+    }
+}
+
+void SX126x::ProcessIrqs( void )
+{
+    if( this->PollingMode == true )
+    {
+        if( this->IrqState == true )
+        {
+            __disable_irq( );
+            this->IrqState = false;
+            __enable_irq( );
+        }
+        else
+        {
+            return;
+        }
     }
 
     uint16_t irqRegs = GetIrqStatus( );
-    LastIrqs = irqRegs;
-//    printf("0x%04x\n\r", irqRegs );
     ClearIrqStatus( IRQ_RADIO_ALL );
 
+#ifdef ADV_DEBUG
+    printf("0x%04x\n\r", irqRegs );
+#endif
 
-#if( SX126x_DEBUG == 1 )
-    DigitalOut TEST_PIN_1( D14 );
-    DigitalOut TEST_PIN_2( D15 );
-    for( int i = 0x8000; i != 0; i >>= 1 )
+    if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
     {
-        TEST_PIN_2 = 0;
-        TEST_PIN_1 = ( ( irqRegs & i ) != 0 ) ? 1 : 0;
-        TEST_PIN_2 = 1;
+        // LoRa Only
+        FrequencyError = 0x000000 | ( ( 0x0F & ReadReg( 0x076A ) ) << 16 );
+        FrequencyError = FrequencyError | ( ReadReg( 0x076B ) << 8 );
+        FrequencyError = FrequencyError | ( ReadReg( 0x076c ) );
     }
-    TEST_PIN_1 = 0;
-    TEST_PIN_2 = 0;
-#endif
+
+    if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID )
+    {
+        // GFSK Only
+        FrequencyError = 0x000000 | ( ( 0x0F & ReadReg( 0x06B0 ) ) << 8 );
+        FrequencyError = FrequencyError | ( ReadReg( 0x06B1 ) );
+    }
 
     if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
     {
@@ -652,19 +879,27 @@
         }
     }
 
+    if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE )
+    {
+        if( cadDone != NULL )
+        {
+            cadDone( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED );
+        }
+    }
+
     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
     {
-        if( ( rxTxTimeout != NULL ) && ( OperatingMode == MODE_TX ) )
+        if( ( txTimeout != NULL ) && ( OperatingMode == MODE_TX ) )
         {
-            rxTxTimeout( IRQ_TX_TIMEOUT );
+            txTimeout( );
         }
-        else if( ( rxTxTimeout != NULL ) && ( OperatingMode == MODE_RX ) )
+        else if( ( rxTimeout != NULL ) && ( OperatingMode == MODE_RX ) )
         {
-            rxTxTimeout( IRQ_RX_TIMEOUT );
+            rxTimeout( );
         }
         else
         {
-            rxTxTimeout( IRQ_XYZ );
+            assert_param( FAIL );
         }
     }
     
@@ -697,7 +932,7 @@
         }
     } 
 
-    //IRQ_HEADER_ERROR                        = 0x0020,    
+    //IRQ_HEADER_ERROR                        = 0x0020,
     if( irqRegs & IRQ_HEADER_ERROR )
     {
         if( rxError != NULL )
@@ -705,19 +940,7 @@
             rxError( IRQ_HEADER_ERROR_CODE );
         }
     }  
-    
-    //IRQ_CAD_DONE                            = 0x0080,
-    //IRQ_CAD_ACTIVITY_DETECTED               = 0x0100,
-    if(  irqRegs & IRQ_CAD_DONE )
-    {
-        bool detected = ( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED );
-
-        if( cadDone != NULL )
-        {
-            cadDone( detected );
-        }
-                    
-    }*/
+*/
 }