Uttam Bhat / SX1280Lib

Fork of SX1280Lib by Semtech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sx1280.cpp Source File

sx1280.cpp

00001 /*
00002   ______                              _
00003  / _____)             _              | |
00004 ( (____  _____ ____ _| |_ _____  ____| |__
00005  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00006  _____) ) ____| | | || |_| ____( (___| | | |
00007 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00008     (C)2016 Semtech
00009 
00010 Description: Driver for SX1280 devices
00011 
00012 License: Revised BSD License, see LICENSE.TXT file include in the project
00013 
00014 Maintainer: Miguel Luis, Gregory Cristian and Matthieu Verdy
00015 */
00016 #include "mbed.h"
00017 #include "sx1280.h"
00018 #include "sx1280-hal.h"
00019 
00020 /*!
00021  * \brief ContinuousMode and SingleMode are two particular values for TickTime.
00022  * The ContinuousMode keeps the radio in Rx or Tx mode, even after successfull reception
00023  * or transmission. It should never generate Timeout interrupt.
00024  * The SingleMode lets the radio enought time to make one reception or transmission.
00025  * No Timeout interrupt is generated, and the radio fall in StandBy mode after
00026  * reception or transmission.
00027 */
00028 TickTime_t  ContinuousMode = { RADIO_TICK_SIZE_0015_US, 0xFFFF };
00029 TickTime_t  SingleMode     = { RADIO_TICK_SIZE_0015_US, 0xFFFF };
00030 
00031 /*!
00032  * \brief Radio registers definition
00033  *
00034  */
00035 typedef struct
00036 {
00037     uint16_t      Addr;                             //!< The address of the register
00038     uint8_t       Value;                            //!< The value of the register
00039 }RadioRegisters_t;
00040 
00041 /*!
00042  * \brief Radio hardware registers initialization definition
00043  */
00044 #define RADIO_INIT_REGISTERS_VALUE  { }
00045 
00046 /*!
00047  * \brief Radio hardware registers initialization
00048  */
00049 const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE;
00050 
00051 void SX1280::Init( void )
00052 {
00053     Reset( );
00054     IoIrqInit( dioIrq );
00055     Wakeup( );
00056     SetRegistersDefault( );
00057 }
00058 
00059 void SX1280::SetRegistersDefault( void )
00060 {
00061     for( int16_t i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters_t ); i++ )
00062     {
00063         WriteRegister( RadioRegsInit[i].Addr, RadioRegsInit[i].Value );
00064     }
00065 }
00066 
00067 uint16_t SX1280::GetFirmwareVersion( void )
00068 {
00069     return( ( ( ReadRegister( 0xA8 ) ) << 8 ) | ( ReadRegister( 0xA9 ) ) );
00070 }
00071 
00072 RadioStatus_t SX1280::GetStatus( void )
00073 {
00074     uint8_t stat = 0;
00075     RadioStatus_t status;
00076 
00077     ReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 );
00078     status.Value = stat;
00079     return( status );
00080 }
00081 
00082 RadioOperatingModes_t SX1280::GetOpMode( void )
00083 {
00084     return( OperatingMode );
00085 }
00086 
00087 void SX1280::SetSleep( SleepParams_t sleepConfig )
00088 {
00089     uint8_t sleep = ( sleepConfig.WakeUpRTC << 3 ) |
00090                     ( sleepConfig.InstructionRamRetention << 2 ) |
00091                     ( sleepConfig.DataBufferRetention << 1 ) |
00092                     ( sleepConfig.DataRamRetention );
00093 
00094     OperatingMode = MODE_SLEEP;
00095     WriteCommand( RADIO_SET_SLEEP, &sleep, 1 );
00096 }
00097 
00098 void SX1280::SetStandby( RadioStandbyModes_t standbyConfig )
00099 {
00100     WriteCommand( RADIO_SET_STANDBY, ( uint8_t* )&standbyConfig, 1 );
00101     if( standbyConfig == STDBY_RC )
00102     {
00103         OperatingMode = MODE_STDBY_RC;
00104     }
00105     else
00106     {
00107         OperatingMode = MODE_STDBY_XOSC;
00108     }
00109 }
00110 
00111 void SX1280::SetFs( void )
00112 {
00113     WriteCommand( RADIO_SET_FS, 0, 0 );
00114     OperatingMode = MODE_FS;
00115 }
00116 
00117 void SX1280::SetTx( TickTime_t timeout )
00118 {
00119     uint8_t buf[3];
00120     buf[0] = timeout.Step;
00121     buf[1] = ( uint8_t )( ( timeout.NbSteps >> 8 ) & 0x00FF );
00122     buf[2] = ( uint8_t )( timeout.NbSteps & 0x00FF );
00123 
00124     ClearIrqStatus( IRQ_RADIO_ALL );
00125     
00126     // If the radio is doing ranging operations, then apply the specific calls
00127     // prior to SetTx
00128     if( GetPacketType( ) == PACKET_TYPE_RANGING )
00129     {
00130         SetRangingRole( RADIO_RANGING_ROLE_MASTER );
00131     }
00132     WriteCommand( RADIO_SET_TX, buf, 3 );
00133     OperatingMode = MODE_TX;
00134 }
00135 
00136 void SX1280::SetRx( TickTime_t timeout )
00137 {
00138     uint8_t buf[3];
00139     buf[0] = timeout.Step;
00140     buf[1] = ( uint8_t )( ( timeout.NbSteps >> 8 ) & 0x00FF );
00141     buf[2] = ( uint8_t )( timeout.NbSteps & 0x00FF );
00142 
00143     ClearIrqStatus( IRQ_RADIO_ALL );
00144     
00145     // If the radio is doing ranging operations, then apply the specific calls
00146     // prior to SetRx
00147     if( GetPacketType( ) == PACKET_TYPE_RANGING )
00148     {
00149         SetRangingRole( RADIO_RANGING_ROLE_SLAVE );
00150     }
00151     WriteCommand( RADIO_SET_RX, buf, 3 );
00152     OperatingMode = MODE_RX;
00153 }
00154 
00155 void SX1280::SetRxDutyCycle( RadioTickSizes_t step, uint16_t nbStepRx, uint16_t nbStepSleep )
00156 {
00157     uint8_t buf[5];
00158 
00159     buf[0] = step;
00160     buf[1] = ( uint8_t )( ( nbStepRx >> 8 ) & 0x00FF );
00161     buf[2] = ( uint8_t )( nbStepRx & 0x00FF );
00162     buf[3] = ( uint8_t )( ( nbStepSleep >> 8 ) & 0x00FF );
00163     buf[4] = ( uint8_t )( nbStepSleep & 0x00FF );
00164     WriteCommand( RADIO_SET_RXDUTYCYCLE, buf, 5 );
00165     OperatingMode = MODE_RX;
00166 }
00167 
00168 void SX1280::SetCad( void )
00169 {
00170     WriteCommand( RADIO_SET_CAD, 0, 0 );
00171     OperatingMode = MODE_CAD;
00172 }
00173 
00174 void SX1280::SetTxContinuousWave( void )
00175 {
00176     WriteCommand( RADIO_SET_TXCONTINUOUSWAVE, 0, 0 );
00177 }
00178 
00179 void SX1280::SetTxContinuousPreamble( void )
00180 {
00181     WriteCommand( RADIO_SET_TXCONTINUOUSPREAMBLE, 0, 0 );
00182 }
00183 
00184 void SX1280::SetPacketType( RadioPacketTypes_t packetType )
00185 {
00186     // Save packet type internally to avoid questioning the radio
00187     this->PacketType = packetType;
00188 
00189     WriteCommand( RADIO_SET_PACKETTYPE, ( uint8_t* )&packetType, 1 );
00190 }
00191 
00192 RadioPacketTypes_t SX1280::GetPacketType( void )
00193 {
00194     return this->PacketType;
00195 }
00196 
00197 void SX1280::SetRfFrequency( uint32_t frequency )
00198 {
00199     uint8_t buf[3];
00200     uint32_t freq = 0;
00201 
00202     freq = ( uint32_t )( ( double )frequency / ( double )FREQ_STEP );
00203     buf[0] = ( uint8_t )( ( freq >> 16 ) & 0xFF );
00204     buf[1] = ( uint8_t )( ( freq >> 8 ) & 0xFF );
00205     buf[2] = ( uint8_t )( freq & 0xFF );
00206     WriteCommand( RADIO_SET_RFFREQUENCY, buf, 3 );
00207 }
00208 
00209 void SX1280::SetTxParams( int8_t power, RadioRampTimes_t rampTime )
00210 {
00211     uint8_t buf[2];
00212 
00213     // The power value to send on SPI/UART is in the range [0..31] and the
00214     // physical output power is in the range [-18..13]dBm
00215     buf[0] = power + 18;
00216     buf[1] = ( uint8_t )rampTime;
00217     WriteCommand( RADIO_SET_TXPARAMS, buf, 2 );
00218 }
00219 
00220 void SX1280::SetCadParams( RadioLoRaCadSymbols_t cadSymbolNum )
00221 {
00222     WriteCommand( RADIO_SET_CADPARAMS, ( uint8_t* )&cadSymbolNum, 1 );
00223     OperatingMode = MODE_CAD;
00224 }
00225 
00226 void SX1280::SetBufferBaseAddresses( uint8_t txBaseAddress, uint8_t rxBaseAddress )
00227 {
00228     uint8_t buf[2];
00229 
00230     buf[0] = txBaseAddress;
00231     buf[1] = rxBaseAddress;
00232     WriteCommand( RADIO_SET_BUFFERBASEADDRESS, buf, 2 );
00233 }
00234 
00235 void SX1280::SetModulationParams( ModulationParams_t *modulationParams )
00236 {
00237     uint8_t buf[3];
00238 
00239     // Check if required configuration corresponds to the stored packet type
00240     // If not, silently update radio packet type
00241     if( this->PacketType != modulationParams->PacketType )
00242     {
00243         this->SetPacketType( modulationParams->PacketType );
00244     }
00245 
00246     switch( modulationParams->PacketType )
00247     {
00248         case PACKET_TYPE_GFSK:
00249             buf[0] = modulationParams->Params.Gfsk.BitrateBandwidth;
00250             buf[1] = modulationParams->Params.Gfsk.ModulationIndex;
00251             buf[2] = modulationParams->Params.Gfsk.ModulationShaping;
00252             break;
00253         case PACKET_TYPE_LORA:
00254         case PACKET_TYPE_RANGING:
00255             buf[0] = modulationParams->Params.LoRa.SpreadingFactor;
00256             buf[1] = modulationParams->Params.LoRa.Bandwidth;
00257             buf[2] = modulationParams->Params.LoRa.CodingRate;
00258             this->LoRaBandwidth = modulationParams->Params.LoRa.Bandwidth;
00259             break;
00260         case PACKET_TYPE_FLRC:
00261             buf[0] = modulationParams->Params.Flrc.BitrateBandwidth;
00262             buf[1] = modulationParams->Params.Flrc.CodingRate;
00263             buf[2] = modulationParams->Params.Flrc.ModulationShaping;
00264             break;
00265         case PACKET_TYPE_BLE:
00266             buf[0] = modulationParams->Params.Ble.BitrateBandwidth;
00267             buf[1] = modulationParams->Params.Ble.ModulationIndex;
00268             buf[2] = modulationParams->Params.Ble.ModulationShaping;
00269             break;
00270         case PACKET_TYPE_NONE:
00271             buf[0] = NULL;
00272             buf[1] = NULL;
00273             buf[2] = NULL;
00274             break;
00275     }
00276     WriteCommand( RADIO_SET_MODULATIONPARAMS, buf, 3 );
00277 }
00278 
00279 void SX1280::SetPacketParams( PacketParams_t *packetParams )
00280 {
00281     uint8_t buf[7];
00282     // Check if required configuration corresponds to the stored packet type
00283     // If not, silently update radio packet type
00284     if( this->PacketType != packetParams->PacketType )
00285     {
00286         this->SetPacketType( packetParams->PacketType );
00287     }
00288 
00289     switch( packetParams->PacketType )
00290     {
00291         case PACKET_TYPE_GFSK:
00292             buf[0] = packetParams->Params.Gfsk.PreambleLength;
00293             buf[1] = packetParams->Params.Gfsk.SyncWordLength;
00294             buf[2] = packetParams->Params.Gfsk.SyncWordMatch;
00295             buf[3] = packetParams->Params.Gfsk.HeaderType;
00296             buf[4] = packetParams->Params.Gfsk.PayloadLength;
00297             buf[5] = packetParams->Params.Gfsk.CrcLength;
00298             buf[6] = packetParams->Params.Gfsk.Whitening;
00299             break;
00300         case PACKET_TYPE_LORA:
00301         case PACKET_TYPE_RANGING:
00302             buf[0] = packetParams->Params.LoRa.PreambleLength;
00303             buf[1] = packetParams->Params.LoRa.HeaderType;
00304             buf[2] = packetParams->Params.LoRa.PayloadLength;
00305             buf[3] = packetParams->Params.LoRa.CrcMode;
00306             buf[4] = packetParams->Params.LoRa.InvertIQ;
00307             buf[5] = NULL;
00308             buf[6] = NULL;
00309             break;
00310         case PACKET_TYPE_FLRC:
00311             buf[0] = packetParams->Params.Flrc.PreambleLength;
00312             buf[1] = packetParams->Params.Flrc.SyncWordLength;
00313             buf[2] = packetParams->Params.Flrc.SyncWordMatch;
00314             buf[3] = packetParams->Params.Flrc.HeaderType;
00315             buf[4] = packetParams->Params.Flrc.PayloadLength;
00316             buf[5] = packetParams->Params.Flrc.CrcLength;
00317             buf[6] = packetParams->Params.Flrc.Whitening;
00318             break;
00319         case PACKET_TYPE_BLE:
00320             buf[0] = packetParams->Params.Ble.ConnectionState;
00321             buf[1] = packetParams->Params.Ble.CrcField;
00322             buf[2] = packetParams->Params.Ble.BlePacketType;
00323             buf[3] = packetParams->Params.Ble.Whitening;
00324             buf[4] = NULL;
00325             buf[5] = NULL;
00326             buf[6] = NULL;
00327             break;
00328         case PACKET_TYPE_NONE:
00329             buf[0] = NULL;
00330             buf[1] = NULL;
00331             buf[2] = NULL;
00332             buf[3] = NULL;
00333             buf[4] = NULL;
00334             buf[5] = NULL;
00335             buf[6] = NULL;
00336             break;
00337     }
00338     WriteCommand( RADIO_SET_PACKETPARAMS, buf, 7 );
00339 }
00340 
00341 void SX1280::GetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPointer )
00342 {
00343     uint8_t status[2];
00344 
00345     ReadCommand( RADIO_GET_RXBUFFERSTATUS, status, 2 );
00346 
00347     // In case of LORA fixed header, the payloadLength is obtained by reading
00348     // the register REG_LR_PAYLOADLENGTH
00349     if( ( this -> GetPacketType( ) == PACKET_TYPE_LORA ) && ( ReadRegister( REG_LR_PACKETPARAMS ) >> 7 == 1 ) )
00350     {
00351         *payloadLength = ReadRegister( REG_LR_PAYLOADLENGTH );
00352     }
00353     else
00354     {
00355         *payloadLength = status[0];
00356     }
00357 
00358     *rxStartBufferPointer = status[1];
00359 }
00360 
00361 void SX1280::GetPacketStatus( PacketStatus_t *pktStatus )
00362 {
00363     uint8_t status[5];
00364 
00365     ReadCommand( RADIO_GET_PACKETSTATUS, status, 5 );
00366 
00367     pktStatus->packetType = this -> GetPacketType( );
00368     switch( pktStatus->packetType )
00369     {
00370         case PACKET_TYPE_GFSK:
00371             pktStatus->Gfsk.RssiSync = -( status[1] / 2 );
00372 
00373             pktStatus->Gfsk.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
00374             pktStatus->Gfsk.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
00375             pktStatus->Gfsk.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
00376             pktStatus->Gfsk.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
00377             pktStatus->Gfsk.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
00378             pktStatus->Gfsk.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
00379             pktStatus->Gfsk.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
00380 
00381             pktStatus->Gfsk.TxRxStatus.RxNoAck = ( status[3] >> 5 ) & 0x01;
00382             pktStatus->Gfsk.TxRxStatus.PacketSent = status[3] & 0x01;
00383 
00384             pktStatus->Gfsk.SyncAddrStatus = status[4] & 0x07;
00385             break;
00386 
00387         case PACKET_TYPE_LORA:
00388         case PACKET_TYPE_RANGING:
00389             pktStatus->LoRa.RssiPkt = -( status[0] / 2 );
00390             ( status[1] < 128 ) ? ( pktStatus->LoRa.SnrPkt = status[1] / 4 ) : ( pktStatus->LoRa.SnrPkt = ( ( status[1] - 256 ) /4 ) );
00391 
00392             pktStatus->LoRa.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
00393             pktStatus->LoRa.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
00394             pktStatus->LoRa.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
00395             pktStatus->LoRa.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
00396             pktStatus->LoRa.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
00397             pktStatus->LoRa.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
00398             pktStatus->LoRa.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
00399 
00400             pktStatus->LoRa.TxRxStatus.RxNoAck = ( status[3] >> 5 ) & 0x01;
00401             pktStatus->LoRa.TxRxStatus.PacketSent = status[3] & 0x01;
00402 
00403             pktStatus->LoRa.SyncAddrStatus = status[4] & 0x07;
00404             break;
00405 
00406         case PACKET_TYPE_FLRC:
00407             pktStatus->Flrc.RssiSync = -( status[1] / 2 );
00408 
00409             pktStatus->Flrc.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
00410             pktStatus->Flrc.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
00411             pktStatus->Flrc.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
00412             pktStatus->Flrc.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
00413             pktStatus->Flrc.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
00414             pktStatus->Flrc.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
00415             pktStatus->Flrc.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
00416 
00417             pktStatus->Flrc.TxRxStatus.RxPid = ( status[3] >> 6 ) & 0x03;
00418             pktStatus->Flrc.TxRxStatus.RxNoAck = ( status[3] >> 5 ) & 0x01;
00419             pktStatus->Flrc.TxRxStatus.RxPidErr = ( status[3] >> 4 ) & 0x01;
00420             pktStatus->Flrc.TxRxStatus.PacketSent = status[3] & 0x01;
00421 
00422             pktStatus->Flrc.SyncAddrStatus = status[4] & 0x07;
00423             break;
00424 
00425         case PACKET_TYPE_BLE:
00426             pktStatus->Ble.RssiSync =  -( status[1] / 2 );
00427 
00428             pktStatus->Ble.ErrorStatus.SyncError = ( status[2] >> 6 ) & 0x01;
00429             pktStatus->Ble.ErrorStatus.LengthError = ( status[2] >> 5 ) & 0x01;
00430             pktStatus->Ble.ErrorStatus.CrcError = ( status[2] >> 4 ) & 0x01;
00431             pktStatus->Ble.ErrorStatus.AbortError = ( status[2] >> 3 ) & 0x01;
00432             pktStatus->Ble.ErrorStatus.HeaderReceived = ( status[2] >> 2 ) & 0x01;
00433             pktStatus->Ble.ErrorStatus.PacketReceived = ( status[2] >> 1 ) & 0x01;
00434             pktStatus->Ble.ErrorStatus.PacketControlerBusy = status[2] & 0x01;
00435 
00436             pktStatus->Ble.TxRxStatus.PacketSent = status[3] & 0x01;
00437 
00438             pktStatus->Ble.SyncAddrStatus = status[4] & 0x07;
00439             break;
00440 
00441         case PACKET_TYPE_NONE:
00442             // In that specific case, we set everything in the pktStatus to zeros
00443             // and reset the packet type accordingly
00444             memset( pktStatus, 0, sizeof( PacketStatus_t ) );
00445             pktStatus->packetType = PACKET_TYPE_NONE;
00446             break;
00447     }
00448 }
00449 
00450 int8_t SX1280::GetRssiInst( void )
00451 {
00452     uint8_t raw = 0;
00453 
00454     ReadCommand( RADIO_GET_RSSIINST, &raw, 1 );
00455 
00456     return ( int8_t ) ( -raw / 2 );
00457 }
00458 
00459 void SX1280::SetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask )
00460 {
00461     uint8_t buf[8];
00462 
00463     buf[0] = ( uint8_t )( ( irqMask >> 8 ) & 0x00FF );
00464     buf[1] = ( uint8_t )( irqMask & 0x00FF );
00465     buf[2] = ( uint8_t )( ( dio1Mask >> 8 ) & 0x00FF );
00466     buf[3] = ( uint8_t )( dio1Mask & 0x00FF );
00467     buf[4] = ( uint8_t )( ( dio2Mask >> 8 ) & 0x00FF );
00468     buf[5] = ( uint8_t )( dio2Mask & 0x00FF );
00469     buf[6] = ( uint8_t )( ( dio3Mask >> 8 ) & 0x00FF );
00470     buf[7] = ( uint8_t )( dio3Mask & 0x00FF );
00471     WriteCommand( RADIO_SET_DIOIRQPARAMS, buf, 8 );
00472 }
00473 
00474 uint16_t SX1280::GetIrqStatus( void )
00475 {
00476     uint8_t irqStatus[2];
00477     ReadCommand( RADIO_GET_IRQSTATUS, irqStatus, 2 );
00478     return ( irqStatus[0] << 8 ) | irqStatus[1];
00479 }
00480 
00481 void SX1280::ClearIrqStatus( uint16_t irq )
00482 {
00483     uint8_t buf[2];
00484 
00485     buf[0] = ( uint8_t )( ( ( uint16_t )irq >> 8 ) & 0x00FF );
00486     buf[1] = ( uint8_t )( ( uint16_t )irq & 0x00FF );
00487     WriteCommand( RADIO_CLR_IRQSTATUS, buf, 2 );
00488 }
00489 
00490 void SX1280::Calibrate( CalibrationParams_t calibParam )
00491 {
00492     uint8_t cal = ( calibParam.ADCBulkPEnable << 5 ) |
00493                   ( calibParam.ADCBulkNEnable << 4 ) |
00494                   ( calibParam.ADCPulseEnable << 3 ) |
00495                   ( calibParam.PLLEnable << 2 ) |
00496                   ( calibParam.RC13MEnable << 1 ) |
00497                   ( calibParam.RC64KEnable );
00498     WriteCommand( RADIO_CALIBRATE, &cal, 1 );
00499 }
00500 
00501 void SX1280::SetRegulatorMode( RadioRegulatorModes_t mode )
00502 {
00503     WriteCommand( RADIO_SET_REGULATORMODE, ( uint8_t* )&mode, 1 );
00504 }
00505 
00506 void SX1280::SetSaveContext( void )
00507 {
00508     WriteCommand( RADIO_SET_SAVECONTEXT, 0, 0 );
00509 }
00510 
00511 void SX1280::SetAutoTx( uint16_t time )
00512 {
00513     uint16_t compensatedTime = time - ( uint16_t )AUTO_TX_OFFSET;
00514     uint8_t buf[2];
00515 
00516     buf[0] = ( uint8_t )( ( compensatedTime >> 8 ) & 0x00FF );
00517     buf[1] = ( uint8_t )( compensatedTime & 0x00FF );
00518     WriteCommand( RADIO_SET_AUTOTX, buf, 2 );
00519 }
00520 
00521 void SX1280::SetAutoFs( bool enableAutoFs )
00522 {
00523     WriteCommand( RADIO_SET_AUTORX, ( uint8_t * )&enableAutoFs, 1 );
00524 }
00525 
00526 void SX1280::SetLongPreamble( bool enable )
00527 {
00528     WriteCommand( RADIO_SET_LONGPREAMBLE, ( uint8_t * )&enable, 1 );
00529 }
00530 
00531 void SX1280::SetPayload( uint8_t *buffer, uint8_t size, uint8_t offset )
00532 {
00533     WriteBuffer( offset, buffer, size );
00534 }
00535 
00536 uint8_t SX1280::GetPayload( uint8_t *buffer, uint8_t *size , uint8_t maxSize )
00537 {
00538     uint8_t offset;
00539 
00540     GetRxBufferStatus( size, &offset );
00541     if( *size > maxSize )
00542     {
00543         return 1;
00544     }
00545     ReadBuffer( offset, buffer, *size );
00546     return 0;
00547 }
00548 
00549 void SX1280::SendPayload( uint8_t *payload, uint8_t size, TickTime_t timeout, uint8_t offset )
00550 {
00551     SetPayload( payload, size, offset );
00552     SetTx( timeout );
00553 }
00554 
00555 uint8_t SX1280::SetSyncWord( uint8_t syncWordIdx, uint8_t *syncWord )
00556 {
00557     uint16_t addr;
00558     uint8_t syncwordSize = 0;
00559 
00560     switch( GetPacketType( ) )
00561     {
00562         case PACKET_TYPE_GFSK:
00563             syncwordSize = 5;
00564             switch( syncWordIdx )
00565             {
00566                 case 1:
00567                     addr = REG_LR_SYNCWORDBASEADDRESS1;
00568                     break;
00569                 case 2:
00570                     addr = REG_LR_SYNCWORDBASEADDRESS2;
00571                     break;
00572                 case 3:
00573                     addr = REG_LR_SYNCWORDBASEADDRESS3;
00574                     break;
00575                 default:
00576                     return 1;
00577             }
00578             break;
00579         case PACKET_TYPE_FLRC:
00580             // For FLRC packet type, the SyncWord is one byte shorter and
00581             // the base address is shifted by one byte
00582             syncwordSize = 4;
00583             switch( syncWordIdx )
00584             {
00585                 case 1:
00586                     addr = REG_LR_SYNCWORDBASEADDRESS1 + 1;
00587                     break;
00588                 case 2:
00589                     addr = REG_LR_SYNCWORDBASEADDRESS2 + 1;
00590                     break;
00591                 case 3:
00592                     addr = REG_LR_SYNCWORDBASEADDRESS3 + 1;
00593                     break;
00594                 default:
00595                     return 1;
00596             }
00597             break;
00598         case PACKET_TYPE_BLE:
00599             // For Ble packet type, only the first SyncWord is used and its
00600             // address is shifted by one byte
00601             syncwordSize = 4;
00602             switch( syncWordIdx )
00603             {
00604                 case 1:
00605                     addr = REG_LR_SYNCWORDBASEADDRESS1 + 1;
00606                     break;
00607                 default:
00608                     return 1;
00609             }
00610             break;
00611         default:
00612             return 1;
00613     }
00614     WriteRegister( addr, syncWord, syncwordSize );
00615     return 0;
00616 }
00617 
00618 void SX1280::SetSyncWordErrorTolerance( uint8_t ErrorBits )
00619 {
00620     ErrorBits = ( ReadRegister( REG_LR_SYNCWORDTOLERANCE ) & 0xF0 ) | ( ErrorBits & 0x0F );
00621     WriteRegister( REG_LR_SYNCWORDTOLERANCE, ErrorBits );
00622 }
00623 
00624 void SX1280::SetCrcSeed( uint16_t seed )
00625 {
00626     uint8_t val[2];
00627 
00628     val[0] = ( uint8_t )( seed >> 8 ) & 0xFF;
00629     val[1] = ( uint8_t )( seed  & 0xFF );
00630 
00631     switch( GetPacketType( ) )
00632     {
00633         case PACKET_TYPE_GFSK:
00634         case PACKET_TYPE_FLRC:
00635             WriteRegister( REG_LR_CRCSEEDBASEADDR, val, 2 );
00636             break;
00637         default:
00638             break;
00639     }
00640 }
00641 
00642 void SX1280::SetCrcPolynomial( uint16_t polynomial )
00643 {
00644     uint8_t val[2];
00645 
00646     val[0] = ( uint8_t )( polynomial >> 8 ) & 0xFF;
00647     val[1] = ( uint8_t )( polynomial  & 0xFF );
00648 
00649     switch( GetPacketType( ) )
00650     {
00651         case PACKET_TYPE_GFSK:
00652         case PACKET_TYPE_FLRC:
00653             WriteRegister( REG_LR_CRCPOLYBASEADDR, val, 2 );
00654             break;
00655         default:
00656             break;
00657     }
00658 }
00659 
00660 void SX1280::SetWhiteningSeed( uint8_t seed )
00661 {
00662     switch( GetPacketType( ) )
00663     {
00664         case PACKET_TYPE_GFSK:
00665         case PACKET_TYPE_FLRC:
00666         case PACKET_TYPE_BLE:
00667             WriteRegister( REG_LR_WHITSEEDBASEADDR, seed );
00668             break;
00669         default:
00670             break;
00671     }
00672 }
00673 
00674 void SX1280::SetRangingIdLength( RadioRangingIdCheckLengths_t length )
00675 {
00676     switch( GetPacketType( ) )
00677     {
00678         case PACKET_TYPE_RANGING:
00679             WriteRegister( REG_LR_RANGINGIDCHECKLENGTH, ( ( ( ( uint8_t )length ) & 0x03 ) << 6 ) | ( ReadRegister( REG_LR_RANGINGIDCHECKLENGTH ) & 0x3F ) );
00680             break;
00681         default:
00682             break;
00683     }
00684 }
00685 
00686 void SX1280::SetDeviceRangingAddress( uint32_t address )
00687 {
00688     uint8_t addrArray[] = { address >> 24, address >> 16, address >> 8, address };
00689 
00690     switch( GetPacketType( ) )
00691     {
00692         case PACKET_TYPE_RANGING:
00693             WriteRegister( REG_LR_DEVICERANGINGADDR, addrArray, 4 );
00694             break;
00695         default:
00696             break;
00697     }
00698 }
00699 
00700 void SX1280::SetRangingRequestAddress( uint32_t address )
00701 {
00702     uint8_t addrArray[] = { address >> 24, address >> 16, address >> 8, address };
00703 
00704     switch( GetPacketType( ) )
00705     {
00706         case PACKET_TYPE_RANGING:
00707             WriteRegister( REG_LR_REQUESTRANGINGADDR, addrArray, 4 );
00708             break;
00709         default:
00710             break;
00711     }
00712 }
00713 
00714 double SX1280::GetRangingResult( RadioRangingResultTypes_t resultType )
00715 {
00716     uint32_t valLsb = 0;
00717     double val = 0.0;
00718 
00719     switch( GetPacketType( ) )
00720     {
00721         case PACKET_TYPE_RANGING:
00722             this->SetStandby( STDBY_XOSC );
00723             this->WriteRegister( 0x97F, this->ReadRegister( 0x97F ) | ( 1 << 1 ) ); // enable LORA modem clock
00724             WriteRegister( REG_LR_RANGINGRESULTCONFIG, ( ReadRegister( REG_LR_RANGINGRESULTCONFIG ) & MASK_RANGINGMUXSEL ) | ( ( ( ( uint8_t )resultType ) & 0x03 ) << 4 ) );
00725             valLsb = ( ( ReadRegister( REG_LR_RANGINGRESULTBASEADDR ) << 16 ) | ( ReadRegister( REG_LR_RANGINGRESULTBASEADDR + 1 ) << 8 ) | ( ReadRegister( REG_LR_RANGINGRESULTBASEADDR + 2 ) ) );
00726             this->SetStandby( STDBY_RC );
00727 
00728             // Convertion from LSB to distance. For explanation on the formula, refer to Datasheet of SX1280
00729             switch( resultType )
00730             {
00731                 case RANGING_RESULT_RAW:
00732                     // Convert the ranging LSB to distance in meter
00733                     // The theoretical conversion from register value to distance [m] is given by:
00734                     //distance [m] = ( complement2( register ) * 150 ) / ( 2^12 * bandwidth[MHz] ) )
00735                     // The API provide BW in [Hz] so the implemented formula is complement2( register ) / bandwidth[Hz] * A,
00736                     // where A = 150 / (2^12 / 1e6) = 36621.09
00737                     val = ( double )complement2( valLsb, 24 ) / ( double )this->GetLoRaBandwidth( ) * 36621.09375;
00738                     break;
00739 
00740                 case RANGING_RESULT_AVERAGED:
00741                 case RANGING_RESULT_DEBIASED:
00742                 case RANGING_RESULT_FILTERED:
00743                     val = ( double )valLsb * 20.0 / 100.0;
00744                     break;
00745                 default:
00746                     val = 0.0;
00747             }
00748             break;
00749         default:
00750             break;
00751     }
00752     return val;
00753 }
00754 
00755 void SX1280::SetRangingCalibration( uint16_t cal )
00756 {
00757     switch( GetPacketType( ) )
00758     {
00759         case PACKET_TYPE_RANGING:
00760             WriteRegister( REG_LR_RANGINGRERXTXDELAYCAL, ( uint8_t )( ( cal >> 8 ) & 0xFF ) );
00761             WriteRegister( REG_LR_RANGINGRERXTXDELAYCAL + 1, ( uint8_t )( ( cal ) & 0xFF ) );
00762             break;
00763         default:
00764             break;
00765     }
00766 }
00767 
00768 void SX1280::RangingClearFilterResult( void )
00769 {
00770     uint8_t regVal = ReadRegister( REG_LR_RANGINGRESULTCLEARREG );
00771 
00772     // To clear result, set bit 5 to 1 then to 0
00773     WriteRegister( REG_LR_RANGINGRESULTCLEARREG, regVal | ( 1 << 5 ) );
00774     WriteRegister( REG_LR_RANGINGRESULTCLEARREG, regVal & ( ~( 1 << 5 ) ) );
00775 }
00776 
00777 void SX1280::RangingSetFilterNumSamples( uint8_t num )
00778 {
00779     // Silently set 8 as minimum value
00780     WriteRegister( REG_LR_RANGINGFILTERWINDOWSIZE, ( num < DEFAULT_RANGING_FILTER_SIZE ) ? DEFAULT_RANGING_FILTER_SIZE : num );
00781 }
00782 
00783 void SX1280::SetRangingRole( RadioRangingRoles_t role )
00784 {
00785     uint8_t buf[1];
00786 
00787     buf[0] = role;
00788     WriteCommand( RADIO_SET_RANGING_ROLE, &buf[0], 1 );
00789 }
00790 
00791 double SX1280::GetFrequencyError( )
00792 {
00793     uint8_t efeRaw[3] = {0};
00794     uint32_t efe = 0;
00795     double efeHz = 0.0;
00796 
00797     switch( this->GetPacketType( ) )
00798     {
00799         case PACKET_TYPE_LORA:
00800         case PACKET_TYPE_RANGING:
00801             efeRaw[0] = this->ReadRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB );
00802             efeRaw[1] = this->ReadRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 1 );
00803             efeRaw[2] = this->ReadRegister( REG_LR_ESTIMATED_FREQUENCY_ERROR_MSB + 2 );
00804             efe = ( efeRaw[0]<<16 ) | ( efeRaw[1]<<8 ) | efeRaw[2];
00805             efe &= REG_LR_ESTIMATED_FREQUENCY_ERROR_MASK;
00806 
00807             efeHz = 1.55 * ( double )complement2( efe, 20 ) / ( 1600.0 / ( double )this->GetLoRaBandwidth( ) * 1000.0 );
00808             break;
00809 
00810         case PACKET_TYPE_NONE:
00811         case PACKET_TYPE_BLE:
00812         case PACKET_TYPE_FLRC:
00813         case PACKET_TYPE_GFSK:
00814             break;
00815     }
00816 
00817     return efeHz;
00818 }
00819 
00820 void SX1280::SetPollingMode( void )
00821 {
00822     this->PollingMode = true;
00823 }
00824 
00825 int32_t SX1280::complement2( const uint32_t num, const uint8_t bitCnt )
00826 {
00827     int32_t retVal = ( int32_t )num;
00828     if( num >= 2<<( bitCnt - 2 ) )
00829     {
00830         retVal -= 2<<( bitCnt - 1 );
00831     }
00832     return retVal;
00833 }
00834 
00835 int32_t SX1280::GetLoRaBandwidth( )
00836 {
00837     int32_t bwValue = 0;
00838 
00839     switch( this->LoRaBandwidth )
00840     {
00841         case LORA_BW_0200:
00842             bwValue = 203125;
00843             break;
00844         case LORA_BW_0400:
00845             bwValue = 406250;
00846             break;
00847         case LORA_BW_0800:
00848             bwValue = 812500;
00849             break;
00850         case LORA_BW_1600:
00851             bwValue = 1625000;
00852             break;
00853         default:
00854             bwValue = 0;
00855     }
00856     return bwValue;
00857 }
00858 
00859 void SX1280::SetInterruptMode( void )
00860 {
00861     this->PollingMode = false;
00862 }
00863 
00864 void SX1280::OnDioIrq( void )
00865 {
00866     /*
00867      * When polling mode is activated, it is up to the application to call
00868      * ProcessIrqs( ). Otherwise, the driver automatically calls ProcessIrqs( )
00869      * on radio interrupt.
00870      */
00871     if( this->PollingMode == true )
00872     {
00873         this->IrqState = true;
00874     }
00875     else
00876     {
00877         this->ProcessIrqs( );
00878     }
00879 }
00880 
00881 void SX1280::ProcessIrqs( void )
00882 {
00883     RadioPacketTypes_t packetType = PACKET_TYPE_NONE;
00884 
00885     if( this->PollingMode == true )
00886     {
00887         if( this->IrqState == true )
00888         {
00889             __disable_irq( );
00890             this->IrqState = false;
00891             __enable_irq( );
00892         }
00893         else
00894         {
00895             return;
00896         }
00897     }
00898 
00899     packetType = GetPacketType( );
00900     uint16_t irqRegs = GetIrqStatus( );
00901     ClearIrqStatus( IRQ_RADIO_ALL );
00902 
00903 #if( SX1280_DEBUG == 1 )
00904     DigitalOut TEST_PIN_1( D14 );
00905     DigitalOut TEST_PIN_2( D15 );
00906     for( int i = 0x8000; i != 0; i >>= 1 )
00907     {
00908         TEST_PIN_2 = 0;
00909         TEST_PIN_1 = ( ( irqRegs & i ) != 0 ) ? 1 : 0;
00910         TEST_PIN_2 = 1;
00911     }
00912     TEST_PIN_1 = 0;
00913     TEST_PIN_2 = 0;
00914 #endif
00915 
00916     switch( packetType )
00917     {
00918         case PACKET_TYPE_GFSK:
00919         case PACKET_TYPE_FLRC:
00920         case PACKET_TYPE_BLE:
00921             switch( OperatingMode )
00922             {
00923                 case MODE_RX:
00924                     if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
00925                     {
00926                         if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
00927                         {
00928                             if( rxError != NULL )
00929                             {
00930                                 rxError( IRQ_CRC_ERROR_CODE );
00931                             }
00932                         }
00933                         else if( ( irqRegs & IRQ_SYNCWORD_ERROR ) == IRQ_SYNCWORD_ERROR )
00934                         {
00935                             if( rxError != NULL )
00936                             {
00937                                 rxError( IRQ_SYNCWORD_ERROR_CODE );
00938                             }
00939                         }
00940                         else
00941                         {
00942                             if( rxDone != NULL )
00943                             {
00944                                 rxDone( );
00945                             }
00946                         }
00947                     }
00948                     if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID )
00949                     {
00950                         if( rxSyncWordDone != NULL )
00951                         {
00952                             rxSyncWordDone( );
00953                         }
00954                     }
00955                     if( ( irqRegs & IRQ_SYNCWORD_ERROR ) == IRQ_SYNCWORD_ERROR )
00956                     {
00957                         if( rxError != NULL )
00958                         {
00959                             rxError( IRQ_SYNCWORD_ERROR_CODE );
00960                         }
00961                     }
00962                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
00963                     {
00964                         if( rxTimeout != NULL )
00965                         {
00966                             rxTimeout( );
00967                         }
00968                     }
00969                     break;
00970                 case MODE_TX:
00971                     if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
00972                     {
00973                         if( txDone != NULL )
00974                         {
00975                             txDone( );
00976                         }
00977                     }
00978                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
00979                     {
00980                         if( txTimeout != NULL )
00981                         {
00982                             txTimeout( );
00983                         }
00984                     }
00985                     break;
00986                 default:
00987                     // Unexpected IRQ: silently returns
00988                     break;
00989             }
00990             break;
00991         case PACKET_TYPE_LORA:
00992             switch( OperatingMode )
00993             {
00994                 case MODE_RX:
00995                     if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
00996                     {
00997                         if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
00998                         {
00999                             if( rxError != NULL )
01000                             {
01001                                 rxError( IRQ_CRC_ERROR_CODE );
01002                             }
01003                         }
01004                         else
01005                         {
01006                             if( rxDone != NULL )
01007                             {
01008                                 rxDone( );
01009                             }
01010                         }
01011                     }
01012                     if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
01013                     {
01014                         if( rxHeaderDone != NULL )
01015                         {
01016                             rxHeaderDone( );
01017                         }
01018                     }
01019                     if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR )
01020                     {
01021                         if( rxError != NULL )
01022                         {
01023                             rxError( IRQ_HEADER_ERROR_CODE );
01024                         }
01025                     }
01026                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
01027                     {
01028                         if( rxTimeout != NULL )
01029                         {
01030                             rxTimeout( );
01031                         }
01032                     }
01033                     if( ( irqRegs & IRQ_RANGING_SLAVE_REQUEST_DISCARDED ) == IRQ_RANGING_SLAVE_REQUEST_DISCARDED )
01034                     {
01035                         if( rxError != NULL )
01036                         {
01037                             rxError( IRQ_RANGING_ON_LORA_ERROR_CODE );
01038                         }
01039                     }
01040                     break;
01041                 case MODE_TX:
01042                     if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
01043                     {
01044                         if( txDone != NULL )
01045                         {
01046                             txDone( );
01047                         }
01048                     }
01049                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
01050                     {
01051                         if( txTimeout != NULL )
01052                         {
01053                             txTimeout( );
01054                         }
01055                     }
01056                     break;
01057                 case MODE_CAD:
01058                     if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE )
01059                     {
01060                         if( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED )
01061                         {
01062                             if( cadDone != NULL )
01063                             {
01064                                 cadDone( true );
01065                             }
01066                         }
01067                         else
01068                         {
01069                             if( cadDone != NULL )
01070                             {
01071                                 cadDone( false );
01072                             }
01073                         }
01074                     }
01075                     else if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
01076                     {
01077                         if( rxTimeout != NULL )
01078                         {
01079                             rxTimeout( );
01080                         }
01081                     }
01082                     break;
01083                 default:
01084                     // Unexpected IRQ: silently returns
01085                     break;
01086             }
01087             break;
01088         case PACKET_TYPE_RANGING:
01089             switch( OperatingMode )
01090             {
01091                 // MODE_RX indicates an IRQ on the Slave side
01092                 case MODE_RX:
01093                     if( ( irqRegs & IRQ_RANGING_SLAVE_REQUEST_DISCARDED ) == IRQ_RANGING_SLAVE_REQUEST_DISCARDED )
01094                     {
01095                         if( rangingDone != NULL )
01096                         {
01097                             rangingDone( IRQ_RANGING_SLAVE_ERROR_CODE );
01098                         }
01099                     }
01100                     if( ( irqRegs & IRQ_RANGING_SLAVE_REQUEST_VALID ) == IRQ_RANGING_SLAVE_REQUEST_VALID )
01101                     {
01102                         if( rangingDone != NULL )
01103                         {
01104                             rangingDone( IRQ_RANGING_SLAVE_VALID_CODE );
01105                         }
01106                     }
01107                     if( ( irqRegs & IRQ_RANGING_SLAVE_RESPONSE_DONE ) == IRQ_RANGING_SLAVE_RESPONSE_DONE )
01108                     {
01109                         if( rangingDone != NULL )
01110                         {
01111                             rangingDone( IRQ_RANGING_SLAVE_VALID_CODE );
01112                         }
01113                     }
01114                     if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
01115                     {
01116                         if( rangingDone != NULL )
01117                         {
01118                             rangingDone( IRQ_RANGING_SLAVE_ERROR_CODE );
01119                         }
01120                     }
01121                     if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
01122                     {
01123                         if( rxHeaderDone != NULL )
01124                         {
01125                             rxHeaderDone( );
01126                         }
01127                     }
01128                     if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR )
01129                     {
01130                         if( rxError != NULL )
01131                         {
01132                             rxError( IRQ_HEADER_ERROR_CODE );
01133                         }
01134                     }
01135                     break;
01136                 // MODE_TX indicates an IRQ on the Master side
01137                 case MODE_TX:
01138                     if( ( irqRegs & IRQ_RANGING_MASTER_RESULT_TIMEOUT ) == IRQ_RANGING_MASTER_RESULT_TIMEOUT )
01139                     {
01140                         if( rangingDone != NULL )
01141                         {
01142                             rangingDone( IRQ_RANGING_MASTER_ERROR_CODE );
01143                         }
01144                     }
01145                     if( ( irqRegs & IRQ_RANGING_MASTER_RESULT_VALID ) == IRQ_RANGING_MASTER_RESULT_VALID )
01146                     {
01147                         if( rangingDone != NULL )
01148                         {
01149                             rangingDone( IRQ_RANGING_MASTER_VALID_CODE );
01150                         }
01151                     }
01152                     break;
01153                 default:
01154                     // Unexpected IRQ: silently returns
01155                     break;
01156             }
01157             break;
01158         default:
01159             // Unexpected IRQ: silently returns
01160             break;
01161     }
01162 }