Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: SX126xDevKit SX1262PingPong SX126X_TXonly SX126X_PingPong_Demo ... more
Fork of SX126xLib by
sx126x.cpp
00001 /* 00002 ______ _ 00003 / _____) _ | | 00004 ( (____ _____ ____ _| |_ _____ ____| |__ 00005 \____ \| ___ | (_ _) ___ |/ ___) _ \ 00006 _____) ) ____| | | || |_| ____( (___| | | | 00007 (______/|_____)_|_|_| \__)_____)\____)_| |_| 00008 (C)2017 Semtech 00009 00010 Description: Generic SX126x driver implementation 00011 00012 License: Revised BSD License, see LICENSE.TXT file include in the project 00013 00014 Authors: Miguel Luis, Gregory Cristian 00015 */ 00016 #include "mbed.h" 00017 #include "sx126x.h" 00018 #include "sx126x-hal.h" 00019 00020 /*! 00021 * \brief Radio registers definition 00022 */ 00023 typedef struct 00024 { 00025 uint16_t Addr; //!< The address of the register 00026 uint8_t Value; //!< The value of the register 00027 }RadioRegisters_t; 00028 00029 /*! 00030 * \brief Stores the last frequency error measured on LoRa received packet 00031 */ 00032 volatile uint32_t FrequencyError = 0; 00033 00034 /*! 00035 * \brief Hold the status of the Image calibration 00036 */ 00037 static bool ImageCalibrated = false; 00038 00039 00040 void SX126x::Init( void ) 00041 { 00042 CalibrationParams_t calibParam; 00043 00044 /*! 00045 * \brief pin OPT is used to detect if the board has a TCXO or a XTAL 00046 * 00047 * OPT = 0 >> TCXO; OPT = 1 >> XTAL 00048 */ 00049 DigitalIn OPT( A3 ); 00050 00051 Reset( ); 00052 00053 IoIrqInit( dioIrq ); 00054 00055 Wakeup( ); 00056 SetStandby( STDBY_RC ); 00057 00058 if( OPT == 0 ) 00059 { 00060 SetDio3AsTcxoCtrl( TCXO_CTRL_1_7V, 320 ); //5 ms 00061 calibParam.Value = 0x7F; 00062 Calibrate( calibParam ); 00063 } 00064 00065 SetPollingMode( ); 00066 00067 AntSwOn( ); 00068 SetDio2AsRfSwitchCtrl( true ); 00069 00070 OperatingMode = MODE_STDBY_RC; 00071 00072 SetPacketType( PACKET_TYPE_LORA ); 00073 00074 #ifdef USE_CONFIG_PUBLIC_NETOWRK 00075 // Change LoRa modem Sync Word for Public Networks 00076 WriteReg( REG_LR_SYNCWORD, ( LORA_MAC_PUBLIC_SYNCWORD >> 8 ) & 0xFF ); 00077 WriteReg( REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF ); 00078 #else 00079 // Change LoRa modem SyncWord for Private Networks 00080 WriteReg( REG_LR_SYNCWORD, ( LORA_MAC_PRIVATE_SYNCWORD >> 8 ) & 0xFF ); 00081 WriteReg( REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF ); 00082 #endif 00083 } 00084 00085 RadioOperatingModes_t SX126x::GetOperatingMode( void ) 00086 { 00087 return OperatingMode; 00088 } 00089 00090 void SX126x::CheckDeviceReady( void ) 00091 { 00092 if( ( GetOperatingMode( ) == MODE_SLEEP ) || ( GetOperatingMode( ) == MODE_RX_DC ) ) 00093 { 00094 Wakeup( ); 00095 // Switch is turned off when device is in sleep mode and turned on is all other modes 00096 AntSwOn( ); 00097 } 00098 } 00099 00100 void SX126x::SetPayload( uint8_t *payload, uint8_t size ) 00101 { 00102 WriteBuffer( 0x00, payload, size ); 00103 } 00104 00105 uint8_t SX126x::GetPayload( uint8_t *buffer, uint8_t *size, uint8_t maxSize ) 00106 { 00107 uint8_t offset = 0; 00108 00109 GetRxBufferStatus( size, &offset ); 00110 if( *size > maxSize ) 00111 { 00112 return 1; 00113 } 00114 ReadBuffer( offset, buffer, *size ); 00115 return 0; 00116 } 00117 00118 void SX126x::SendPayload( uint8_t *payload, uint8_t size, uint32_t timeout ) 00119 { 00120 SetPayload( payload, size ); 00121 SetTx( timeout ); 00122 } 00123 00124 uint8_t SX126x::SetSyncWord( uint8_t *syncWord ) 00125 { 00126 WriteRegister( REG_LR_SYNCWORDBASEADDRESS, syncWord, 8 ); 00127 return 0; 00128 } 00129 00130 void SX126x::SetCrcSeed( uint16_t seed ) 00131 { 00132 uint8_t buf[2]; 00133 00134 buf[0] = ( uint8_t )( ( seed >> 8 ) & 0xFF ); 00135 buf[1] = ( uint8_t )( seed & 0xFF ); 00136 00137 switch( GetPacketType( ) ) 00138 { 00139 case PACKET_TYPE_GFSK: 00140 WriteRegister( REG_LR_CRCSEEDBASEADDR, buf, 2 ); 00141 break; 00142 00143 default: 00144 break; 00145 } 00146 } 00147 00148 void SX126x::SetCrcPolynomial( uint16_t polynomial ) 00149 { 00150 uint8_t buf[2]; 00151 00152 buf[0] = ( uint8_t )( ( polynomial >> 8 ) & 0xFF ); 00153 buf[1] = ( uint8_t )( polynomial & 0xFF ); 00154 00155 switch( GetPacketType( ) ) 00156 { 00157 case PACKET_TYPE_GFSK: 00158 WriteRegister( REG_LR_CRCPOLYBASEADDR, buf, 2 ); 00159 break; 00160 00161 default: 00162 break; 00163 } 00164 } 00165 00166 void SX126x::SetWhiteningSeed( uint16_t seed ) 00167 { 00168 uint8_t regValue = 0; 00169 00170 switch( GetPacketType( ) ) 00171 { 00172 case PACKET_TYPE_GFSK: 00173 regValue = ReadReg( REG_LR_WHITSEEDBASEADDR_MSB ) & 0xFE; 00174 regValue = ( ( seed >> 8 ) & 0x01 ) | regValue; 00175 WriteReg( REG_LR_WHITSEEDBASEADDR_MSB, regValue ); // only 1 bit. 00176 WriteReg( REG_LR_WHITSEEDBASEADDR_LSB, ( uint8_t )seed ); 00177 break; 00178 00179 default: 00180 break; 00181 } 00182 } 00183 00184 uint32_t SX126x::GetRandom( void ) 00185 { 00186 uint8_t buf[] = { 0, 0, 0, 0 }; 00187 00188 // Set radio in continuous reception 00189 SetRx( 0 ); 00190 00191 wait_ms( 1 ); 00192 00193 ReadRegister( RANDOM_NUMBER_GENERATORBASEADDR, buf, 4 ); 00194 00195 SetStandby( STDBY_RC ); 00196 00197 return ( buf[0] << 24 ) | ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3]; 00198 } 00199 00200 void SX126x::SetSleep( SleepParams_t sleepConfig ) 00201 { 00202 #ifdef ADV_DEBUG 00203 printf("SetSleep "); 00204 #endif 00205 00206 AntSwOff( ); 00207 00208 WriteCommand( RADIO_SET_SLEEP, &sleepConfig.Value, 1 ); 00209 OperatingMode = MODE_SLEEP; 00210 } 00211 00212 void SX126x::SetStandby( RadioStandbyModes_t standbyConfig ) 00213 { 00214 #ifdef ADV_DEBUG 00215 printf("SetStandby "); 00216 #endif 00217 WriteCommand( RADIO_SET_STANDBY, ( uint8_t* )&standbyConfig, 1 ); 00218 if( standbyConfig == STDBY_RC ) 00219 { 00220 OperatingMode = MODE_STDBY_RC; 00221 } 00222 else 00223 { 00224 OperatingMode = MODE_STDBY_XOSC; 00225 } 00226 } 00227 00228 void SX126x::SetFs( void ) 00229 { 00230 #ifdef ADV_DEBUG 00231 printf("SetFs "); 00232 #endif 00233 WriteCommand( RADIO_SET_FS, 0, 0 ); 00234 OperatingMode = MODE_FS; 00235 } 00236 00237 void SX126x::SetTx( uint32_t timeout ) 00238 { 00239 uint8_t buf[3]; 00240 00241 OperatingMode = MODE_TX; 00242 00243 #ifdef ADV_DEBUG 00244 printf("SetTx "); 00245 #endif 00246 00247 buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); 00248 buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); 00249 buf[2] = ( uint8_t )( timeout & 0xFF ); 00250 WriteCommand( RADIO_SET_TX, buf, 3 ); 00251 } 00252 00253 void SX126x::SetRxBoosted( uint32_t timeout ) 00254 { 00255 uint8_t buf[3]; 00256 00257 OperatingMode = MODE_RX; 00258 00259 #ifdef ADV_DEBUG 00260 printf("SetRxBoosted "); 00261 #endif 00262 00263 WriteReg( REG_RX_GAIN, 0x96 ); // max LNA gain, increase current by ~2mA for around ~3dB in sensivity 00264 00265 buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); 00266 buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); 00267 buf[2] = ( uint8_t )( timeout & 0xFF ); 00268 WriteCommand( RADIO_SET_RX, buf, 3 ); 00269 } 00270 00271 void SX126x::SetRx( uint32_t timeout ) 00272 { 00273 uint8_t buf[3]; 00274 00275 OperatingMode = MODE_RX; 00276 00277 #ifdef ADV_DEBUG 00278 printf("SetRx "); 00279 #endif 00280 00281 buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); 00282 buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); 00283 buf[2] = ( uint8_t )( timeout & 0xFF ); 00284 WriteCommand( RADIO_SET_RX, buf, 3 ); 00285 } 00286 00287 void SX126x::SetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ) 00288 { 00289 uint8_t buf[6]; 00290 00291 buf[0] = ( uint8_t )( ( rxTime >> 16 ) & 0xFF ); 00292 buf[1] = ( uint8_t )( ( rxTime >> 8 ) & 0xFF ); 00293 buf[2] = ( uint8_t )( rxTime & 0xFF ); 00294 buf[3] = ( uint8_t )( ( sleepTime >> 16 ) & 0xFF ); 00295 buf[4] = ( uint8_t )( ( sleepTime >> 8 ) & 0xFF ); 00296 buf[5] = ( uint8_t )( sleepTime & 0xFF ); 00297 WriteCommand( RADIO_SET_RXDUTYCYCLE, buf, 6 ); 00298 OperatingMode = MODE_RX_DC; 00299 } 00300 00301 void SX126x::SetCad( void ) 00302 { 00303 WriteCommand( RADIO_SET_CAD, 0, 0 ); 00304 OperatingMode = MODE_CAD; 00305 } 00306 00307 void SX126x::SetTxContinuousWave( void ) 00308 { 00309 #ifdef ADV_DEBUG 00310 printf("SetTxContinuousWave "); 00311 #endif 00312 WriteCommand( RADIO_SET_TXCONTINUOUSWAVE, 0, 0 ); 00313 } 00314 00315 void SX126x::SetTxInfinitePreamble( void ) 00316 { 00317 #ifdef ADV_DEBUG 00318 printf("SetTxContinuousPreamble "); 00319 #endif 00320 WriteCommand( RADIO_SET_TXCONTINUOUSPREAMBLE, 0, 0 ); 00321 } 00322 00323 void SX126x::SetStopRxTimerOnPreambleDetect( bool enable ) 00324 { 00325 WriteCommand( RADIO_SET_STOPRXTIMERONPREAMBLE, ( uint8_t* )&enable, 1 ); 00326 } 00327 00328 void SX126x::SetLoRaSymbNumTimeout( uint8_t SymbNum ) 00329 { 00330 WriteCommand( RADIO_SET_LORASYMBTIMEOUT, &SymbNum, 1 ); 00331 } 00332 00333 void SX126x::SetRegulatorMode( RadioRegulatorMode_t mode ) 00334 { 00335 #ifdef ADV_DEBUG 00336 printf("SetRegulatorMode "); 00337 #endif 00338 WriteCommand( RADIO_SET_REGULATORMODE, ( uint8_t* )&mode, 1 ); 00339 } 00340 00341 void SX126x::Calibrate( CalibrationParams_t calibParam ) 00342 { 00343 WriteCommand( RADIO_CALIBRATE, &calibParam.Value, 1 ); 00344 } 00345 00346 void SX126x::CalibrateImage( uint32_t freq ) 00347 { 00348 uint8_t calFreq[2]; 00349 00350 if( freq > 900000000 ) 00351 { 00352 calFreq[0] = 0xE1; 00353 calFreq[1] = 0xE9; 00354 } 00355 else if( freq > 850000000 ) 00356 { 00357 calFreq[0] = 0xD7; 00358 calFreq[1] = 0xD8; 00359 } 00360 else if( freq > 770000000 ) 00361 { 00362 calFreq[0] = 0xC1; 00363 calFreq[1] = 0xC5; 00364 } 00365 else if( freq > 460000000 ) 00366 { 00367 calFreq[0] = 0x75; 00368 calFreq[1] = 0x81; 00369 } 00370 else if( freq > 425000000 ) 00371 { 00372 calFreq[0] = 0x6B; 00373 calFreq[1] = 0x6F; 00374 } 00375 WriteCommand( RADIO_CALIBRATEIMAGE, calFreq, 2 ); 00376 } 00377 00378 void SX126x::SetPaConfig( uint8_t paDutyCycle, uint8_t HpMax, uint8_t deviceSel, uint8_t paLUT ) 00379 { 00380 uint8_t buf[4]; 00381 00382 #ifdef ADV_DEBUG 00383 printf("SetPaConfig "); 00384 #endif 00385 00386 buf[0] = paDutyCycle; 00387 buf[1] = HpMax; 00388 buf[2] = deviceSel; 00389 buf[3] = paLUT; 00390 WriteCommand( RADIO_SET_PACONFIG, buf, 4 ); 00391 } 00392 00393 void SX126x::SetRxTxFallbackMode( uint8_t fallbackMode ) 00394 { 00395 WriteCommand( RADIO_SET_TXFALLBACKMODE, &fallbackMode, 1 ); 00396 } 00397 00398 void SX126x::SetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ) 00399 { 00400 uint8_t buf[8]; 00401 00402 #ifdef ADV_DEBUG 00403 printf("SetDioIrqParams "); 00404 #endif 00405 00406 buf[0] = ( uint8_t )( ( irqMask >> 8 ) & 0x00FF ); 00407 buf[1] = ( uint8_t )( irqMask & 0x00FF ); 00408 buf[2] = ( uint8_t )( ( dio1Mask >> 8 ) & 0x00FF ); 00409 buf[3] = ( uint8_t )( dio1Mask & 0x00FF ); 00410 buf[4] = ( uint8_t )( ( dio2Mask >> 8 ) & 0x00FF ); 00411 buf[5] = ( uint8_t )( dio2Mask & 0x00FF ); 00412 buf[6] = ( uint8_t )( ( dio3Mask >> 8 ) & 0x00FF ); 00413 buf[7] = ( uint8_t )( dio3Mask & 0x00FF ); 00414 WriteCommand( RADIO_CFG_DIOIRQ, buf, 8 ); 00415 } 00416 00417 uint16_t SX126x::GetIrqStatus( void ) 00418 { 00419 uint8_t irqStatus[2]; 00420 00421 ReadCommand( RADIO_GET_IRQSTATUS, irqStatus, 2 ); 00422 return ( irqStatus[0] << 8 ) | irqStatus[1]; 00423 } 00424 00425 void SX126x::SetDio2AsRfSwitchCtrl( uint8_t enable ) 00426 { 00427 #ifdef ADV_DEBUG 00428 printf("SetDio2AsRfSwitchCtrl "); 00429 #endif 00430 WriteCommand( RADIO_SET_RFSWITCHMODE, &enable, 1 ); 00431 } 00432 00433 void SX126x::SetDio3AsTcxoCtrl( RadioTcxoCtrlVoltage_t tcxoVoltage, uint32_t timeout ) 00434 { 00435 uint8_t buf[4]; 00436 00437 buf[0] = tcxoVoltage & 0x07; 00438 buf[1] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); 00439 buf[2] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); 00440 buf[3] = ( uint8_t )( timeout & 0xFF ); 00441 00442 WriteCommand( RADIO_SET_TCXOMODE, buf, 4 ); 00443 } 00444 00445 void SX126x::SetRfFrequency( uint32_t frequency ) 00446 { 00447 uint8_t buf[4]; 00448 uint32_t freq = 0; 00449 00450 #ifdef ADV_DEBUG 00451 printf("SetRfFrequency "); 00452 #endif 00453 00454 if( ImageCalibrated == false ) 00455 { 00456 CalibrateImage( frequency ); 00457 ImageCalibrated = true; 00458 } 00459 00460 freq = ( uint32_t )( ( double )frequency / ( double )FREQ_STEP ); 00461 buf[0] = ( uint8_t )( ( freq >> 24 ) & 0xFF ); 00462 buf[1] = ( uint8_t )( ( freq >> 16 ) & 0xFF ); 00463 buf[2] = ( uint8_t )( ( freq >> 8 ) & 0xFF ); 00464 buf[3] = ( uint8_t )( freq & 0xFF ); 00465 WriteCommand( RADIO_SET_RFFREQUENCY, buf, 4 ); 00466 } 00467 00468 void SX126x::SetPacketType( RadioPacketTypes_t packetType ) 00469 { 00470 #ifdef ADV_DEBUG 00471 printf("SetPacketType "); 00472 #endif 00473 00474 // Save packet type internally to avoid questioning the radio 00475 this->PacketType = packetType; 00476 WriteCommand( RADIO_SET_PACKETTYPE, ( uint8_t* )&packetType, 1 ); 00477 } 00478 00479 RadioPacketTypes_t SX126x::GetPacketType( void ) 00480 { 00481 return this->PacketType; 00482 } 00483 00484 void SX126x::SetTxParams( int8_t power, RadioRampTimes_t rampTime ) 00485 { 00486 uint8_t buf[2]; 00487 DigitalIn OPT( A3 ); 00488 00489 #ifdef ADV_DEBUG 00490 printf("SetTxParams "); 00491 #endif 00492 00493 if( GetDeviceType( ) == SX1261 ) 00494 { 00495 if( power == 15 ) 00496 { 00497 SetPaConfig( 0x06, 0x00, 0x01, 0x01 ); 00498 } 00499 else 00500 { 00501 SetPaConfig( 0x04, 0x00, 0x01, 0x01 ); 00502 } 00503 if( power >= 14 ) 00504 { 00505 power = 14; 00506 } 00507 else if( power < -3 ) 00508 { 00509 power = -3; 00510 } 00511 WriteReg( REG_OCP, 0x18 ); // current max is 80 mA for the whole device 00512 } 00513 else // sx1262 or sx1268 00514 { 00515 SetPaConfig( 0x04, 0x07, 0x00, 0x01 ); 00516 if( power > 22 ) 00517 { 00518 power = 22; 00519 } 00520 else if( power < -3 ) 00521 { 00522 power = -3; 00523 } 00524 WriteReg( REG_OCP, 0x38 ); // current max 160mA for the whole device 00525 } 00526 buf[0] = power; 00527 if( OPT == 0 ) 00528 { 00529 if( ( uint8_t )rampTime < RADIO_RAMP_200_US ) 00530 { 00531 buf[1] = RADIO_RAMP_200_US; 00532 } 00533 else 00534 { 00535 buf[1] = ( uint8_t )rampTime; 00536 } 00537 } 00538 else 00539 { 00540 buf[1] = ( uint8_t )rampTime; 00541 } 00542 WriteCommand( RADIO_SET_TXPARAMS, buf, 2 ); 00543 } 00544 00545 void SX126x::SetModulationParams( ModulationParams_t *modulationParams ) 00546 { 00547 uint8_t n; 00548 uint32_t tempVal = 0; 00549 uint8_t buf[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 00550 00551 #ifdef ADV_DEBUG 00552 printf("SetModulationParams "); 00553 #endif 00554 00555 // Check if required configuration corresponds to the stored packet type 00556 // If not, silently update radio packet type 00557 if( this->PacketType != modulationParams->PacketType ) 00558 { 00559 this->SetPacketType( modulationParams->PacketType ); 00560 } 00561 00562 switch( modulationParams->PacketType ) 00563 { 00564 case PACKET_TYPE_GFSK: 00565 n = 8; 00566 tempVal = ( uint32_t )( 32 * ( ( double )XTAL_FREQ / ( double )modulationParams->Params.Gfsk.BitRate ) ); 00567 buf[0] = ( tempVal >> 16 ) & 0xFF; 00568 buf[1] = ( tempVal >> 8 ) & 0xFF; 00569 buf[2] = tempVal & 0xFF; 00570 buf[3] = modulationParams->Params.Gfsk.ModulationShaping; 00571 buf[4] = modulationParams->Params.Gfsk.Bandwidth; 00572 tempVal = ( uint32_t )( ( double )modulationParams->Params.Gfsk.Fdev / ( double )FREQ_STEP ); 00573 buf[5] = ( tempVal >> 16 ) & 0xFF; 00574 buf[6] = ( tempVal >> 8 ) & 0xFF; 00575 buf[7] = ( tempVal& 0xFF ); 00576 break; 00577 case PACKET_TYPE_LORA: 00578 n = 4; 00579 switch( modulationParams->Params.LoRa.Bandwidth ) 00580 { 00581 case LORA_BW_500: 00582 modulationParams->Params.LoRa.LowDatarateOptimize = 0x00; 00583 break; 00584 case LORA_BW_250: 00585 if( modulationParams->Params.LoRa.SpreadingFactor == 12 ) 00586 { 00587 modulationParams->Params.LoRa.LowDatarateOptimize = 0x01; 00588 } 00589 else 00590 { 00591 modulationParams->Params.LoRa.LowDatarateOptimize = 0x00; 00592 } 00593 break; 00594 case LORA_BW_125: 00595 if( modulationParams->Params.LoRa.SpreadingFactor >= 11 ) 00596 { 00597 modulationParams->Params.LoRa.LowDatarateOptimize = 0x01; 00598 } 00599 else 00600 { 00601 modulationParams->Params.LoRa.LowDatarateOptimize = 0x00; 00602 } 00603 break; 00604 case LORA_BW_062: 00605 if( modulationParams->Params.LoRa.SpreadingFactor >= 10 ) 00606 { 00607 modulationParams->Params.LoRa.LowDatarateOptimize = 0x01; 00608 } 00609 else 00610 { 00611 modulationParams->Params.LoRa.LowDatarateOptimize = 0x00; 00612 } 00613 break; 00614 case LORA_BW_041: 00615 if( modulationParams->Params.LoRa.SpreadingFactor >= 9 ) 00616 { 00617 modulationParams->Params.LoRa.LowDatarateOptimize = 0x01; 00618 } 00619 else 00620 { 00621 modulationParams->Params.LoRa.LowDatarateOptimize = 0x00; 00622 } 00623 break; 00624 case LORA_BW_031: 00625 case LORA_BW_020: 00626 case LORA_BW_015: 00627 case LORA_BW_010: 00628 case LORA_BW_007: 00629 modulationParams->Params.LoRa.LowDatarateOptimize = 0x01; 00630 break; 00631 default: 00632 break; 00633 } 00634 buf[0] = modulationParams->Params.LoRa.SpreadingFactor; 00635 buf[1] = modulationParams->Params.LoRa.Bandwidth; 00636 buf[2] = modulationParams->Params.LoRa.CodingRate; 00637 buf[3] = modulationParams->Params.LoRa.LowDatarateOptimize; 00638 break; 00639 default: 00640 case PACKET_TYPE_NONE: 00641 return; 00642 } 00643 WriteCommand( RADIO_SET_MODULATIONPARAMS, buf, n ); 00644 } 00645 00646 void SX126x::SetPacketParams( PacketParams_t *packetParams ) 00647 { 00648 uint8_t n; 00649 uint8_t crcVal = 0; 00650 uint8_t buf[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 00651 00652 #ifdef ADV_DEBUG 00653 printf("SetPacketParams "); 00654 #endif 00655 00656 // Check if required configuration corresponds to the stored packet type 00657 // If not, silently update radio packet type 00658 if( this->PacketType != packetParams->PacketType ) 00659 { 00660 this->SetPacketType( packetParams->PacketType ); 00661 } 00662 00663 switch( packetParams->PacketType ) 00664 { 00665 case PACKET_TYPE_GFSK: 00666 if( packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_IBM ) 00667 { 00668 SetCrcSeed( CRC_IBM_SEED ); 00669 SetCrcPolynomial( CRC_POLYNOMIAL_IBM ); 00670 crcVal = RADIO_CRC_2_BYTES; 00671 } 00672 else if( packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_CCIT ) 00673 { 00674 SetCrcSeed( CRC_CCITT_SEED ); 00675 SetCrcPolynomial( CRC_POLYNOMIAL_CCITT ); 00676 crcVal = RADIO_CRC_2_BYTES_INV; 00677 } 00678 else 00679 { 00680 crcVal = packetParams->Params.Gfsk.CrcLength; 00681 } 00682 n = 9; 00683 // convert preamble length from byte to bit 00684 packetParams->Params.Gfsk.PreambleLength = packetParams->Params.Gfsk.PreambleLength << 3; 00685 00686 buf[0] = ( packetParams->Params.Gfsk.PreambleLength >> 8 ) & 0xFF; 00687 buf[1] = packetParams->Params.Gfsk.PreambleLength; 00688 buf[2] = packetParams->Params.Gfsk.PreambleMinDetect; 00689 buf[3] = ( packetParams->Params.Gfsk.SyncWordLength << 3 ); // convert from byte to bit 00690 buf[4] = packetParams->Params.Gfsk.AddrComp; 00691 buf[5] = packetParams->Params.Gfsk.HeaderType; 00692 buf[6] = packetParams->Params.Gfsk.PayloadLength; 00693 buf[7] = crcVal; 00694 buf[8] = packetParams->Params.Gfsk.DcFree; 00695 break; 00696 case PACKET_TYPE_LORA: 00697 n = 6; 00698 buf[0] = ( packetParams->Params.LoRa.PreambleLength >> 8 ) & 0xFF; 00699 buf[1] = packetParams->Params.LoRa.PreambleLength; 00700 buf[2] = packetParams->Params.LoRa.HeaderType; 00701 buf[3] = packetParams->Params.LoRa.PayloadLength; 00702 buf[4] = packetParams->Params.LoRa.CrcMode; 00703 buf[5] = packetParams->Params.LoRa.InvertIQ; 00704 break; 00705 default: 00706 case PACKET_TYPE_NONE: 00707 return; 00708 } 00709 WriteCommand( RADIO_SET_PACKETPARAMS, buf, n ); 00710 } 00711 00712 void SX126x::SetCadParams( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, RadioCadExitModes_t cadExitMode, uint32_t cadTimeout ) 00713 { 00714 uint8_t buf[7]; 00715 00716 buf[0] = ( uint8_t )cadSymbolNum; 00717 buf[1] = cadDetPeak; 00718 buf[2] = cadDetMin; 00719 buf[3] = ( uint8_t )cadExitMode; 00720 buf[4] = ( uint8_t )( ( cadTimeout >> 16 ) & 0xFF ); 00721 buf[5] = ( uint8_t )( ( cadTimeout >> 8 ) & 0xFF ); 00722 buf[6] = ( uint8_t )( cadTimeout & 0xFF ); 00723 WriteCommand( RADIO_SET_CADPARAMS, buf, 7 ); 00724 OperatingMode = MODE_CAD; 00725 } 00726 00727 void SX126x::SetBufferBaseAddresses( uint8_t txBaseAddress, uint8_t rxBaseAddress ) 00728 { 00729 uint8_t buf[2]; 00730 00731 #ifdef ADV_DEBUG 00732 printf("SetBufferBaseAddresses "); 00733 #endif 00734 00735 buf[0] = txBaseAddress; 00736 buf[1] = rxBaseAddress; 00737 WriteCommand( RADIO_SET_BUFFERBASEADDRESS, buf, 2 ); 00738 } 00739 00740 RadioStatus_t SX126x::GetStatus( void ) 00741 { 00742 uint8_t stat = 0; 00743 RadioStatus_t status; 00744 00745 ReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 ); 00746 status.Value = stat; 00747 return status; 00748 } 00749 00750 int8_t SX126x::GetRssiInst( void ) 00751 { 00752 uint8_t rssi; 00753 00754 ReadCommand( RADIO_GET_RSSIINST, ( uint8_t* )&rssi, 1 ); 00755 return( -( rssi / 2 ) ); 00756 } 00757 00758 void SX126x::GetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPointer ) 00759 { 00760 uint8_t status[2]; 00761 00762 ReadCommand( RADIO_GET_RXBUFFERSTATUS, status, 2 ); 00763 00764 // In case of LORA fixed header, the payloadLength is obtained by reading 00765 // the register REG_LR_PAYLOADLENGTH 00766 if( ( this->GetPacketType( ) == PACKET_TYPE_LORA ) && ( ReadReg( REG_LR_PACKETPARAMS ) >> 7 == 1 ) ) 00767 { 00768 *payloadLength = ReadReg( REG_LR_PAYLOADLENGTH ); 00769 } 00770 else 00771 { 00772 *payloadLength = status[0]; 00773 } 00774 *rxStartBufferPointer = status[1]; 00775 } 00776 00777 void SX126x::GetPacketStatus( PacketStatus_t *pktStatus ) 00778 { 00779 uint8_t status[3]; 00780 00781 ReadCommand( RADIO_GET_PACKETSTATUS, status, 3 ); 00782 00783 pktStatus->packetType = this -> GetPacketType( ); 00784 switch( pktStatus->packetType ) 00785 { 00786 case PACKET_TYPE_GFSK: 00787 pktStatus->Params.Gfsk.RxStatus = status[0]; 00788 pktStatus->Params.Gfsk.RssiSync = -status[1] / 2; 00789 pktStatus->Params.Gfsk.RssiAvg = -status[2] / 2; 00790 pktStatus->Params.Gfsk.FreqError = 0; 00791 break; 00792 00793 case PACKET_TYPE_LORA: 00794 pktStatus->Params.LoRa.RssiPkt = -status[0] / 2; 00795 ( status[1] < 128 ) ? ( pktStatus->Params.LoRa.SnrPkt = status[1] / 4 ) : ( pktStatus->Params.LoRa.SnrPkt = ( ( status[1] - 256 ) /4 ) ); 00796 pktStatus->Params.LoRa.SignalRssiPkt = -status[2] / 2; 00797 pktStatus->Params.LoRa.FreqError = FrequencyError; 00798 break; 00799 00800 default: 00801 case PACKET_TYPE_NONE: 00802 // In that specific case, we set everything in the pktStatus to zeros 00803 // and reset the packet type accordingly 00804 memset( pktStatus, 0, sizeof( PacketStatus_t ) ); 00805 pktStatus->packetType = PACKET_TYPE_NONE; 00806 break; 00807 } 00808 } 00809 00810 RadioError_t SX126x::GetDeviceErrors( void ) 00811 { 00812 RadioError_t error; 00813 00814 ReadCommand( RADIO_GET_ERROR, ( uint8_t * )&error, 2 ); 00815 return error; 00816 } 00817 00818 void SX126x::ClearIrqStatus( uint16_t irq ) 00819 { 00820 uint8_t buf[2]; 00821 #ifdef ADV_DEBUG 00822 printf("ClearIrqStatus "); 00823 #endif 00824 buf[0] = ( uint8_t )( ( ( uint16_t )irq >> 8 ) & 0x00FF ); 00825 buf[1] = ( uint8_t )( ( uint16_t )irq & 0x00FF ); 00826 WriteCommand( RADIO_CLR_IRQSTATUS, buf, 2 ); 00827 } 00828 00829 void SX126x::SetPollingMode( void ) 00830 { 00831 this->PollingMode = true; 00832 } 00833 00834 void SX126x::SetInterruptMode( void ) 00835 { 00836 this->PollingMode = false; 00837 } 00838 00839 void SX126x::OnDioIrq( void ) 00840 { 00841 /* 00842 * When polling mode is activated, it is up to the application to call 00843 * ProcessIrqs( ). Otherwise, the driver automatically calls ProcessIrqs( ) 00844 * on radio interrupt. 00845 */ 00846 if( this->PollingMode == true ) 00847 { 00848 this->IrqState = true; 00849 } 00850 else 00851 { 00852 this->ProcessIrqs( ); 00853 } 00854 } 00855 00856 void SX126x::ProcessIrqs( void ) 00857 { 00858 if( this->PollingMode == true ) 00859 { 00860 if( this->IrqState == true ) 00861 { 00862 __disable_irq( ); 00863 this->IrqState = false; 00864 __enable_irq( ); 00865 } 00866 else 00867 { 00868 return; 00869 } 00870 } 00871 00872 uint16_t irqRegs = GetIrqStatus( ); 00873 ClearIrqStatus( IRQ_RADIO_ALL ); 00874 00875 #ifdef ADV_DEBUG 00876 printf("0x%04x\n\r", irqRegs ); 00877 #endif 00878 00879 if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID ) 00880 { 00881 // LoRa Only 00882 FrequencyError = 0x000000 | ( ( 0x0F & ReadReg( REG_FREQUENCY_ERRORBASEADDR ) ) << 16 ); 00883 FrequencyError = FrequencyError | ( ReadReg( REG_FREQUENCY_ERRORBASEADDR + 1 ) << 8 ); 00884 FrequencyError = FrequencyError | ( ReadReg( REG_FREQUENCY_ERRORBASEADDR + 2 ) ); 00885 } 00886 00887 if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE ) 00888 { 00889 if( txDone != NULL ) 00890 { 00891 txDone( ); 00892 } 00893 } 00894 00895 if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE ) 00896 { 00897 if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR ) 00898 { 00899 if( rxError != NULL ) 00900 { 00901 rxError( IRQ_CRC_ERROR_CODE ); 00902 } 00903 } 00904 else 00905 { 00906 if( rxDone != NULL ) 00907 { 00908 rxDone( ); 00909 } 00910 } 00911 } 00912 00913 if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE ) 00914 { 00915 if( cadDone != NULL ) 00916 { 00917 cadDone( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED ); 00918 } 00919 } 00920 00921 if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT ) 00922 { 00923 if( ( txTimeout != NULL ) && ( OperatingMode == MODE_TX ) ) 00924 { 00925 txTimeout( ); 00926 } 00927 else if( ( rxTimeout != NULL ) && ( OperatingMode == MODE_RX ) ) 00928 { 00929 rxTimeout( ); 00930 } 00931 else 00932 { 00933 assert_param( FAIL ); 00934 } 00935 } 00936 00937 /* 00938 //IRQ_PREAMBLE_DETECTED = 0x0004, 00939 if( irqRegs & IRQ_PREAMBLE_DETECTED ) 00940 { 00941 if( rxPblSyncWordHeader != NULL ) 00942 { 00943 rxPblSyncWordHeader( IRQ_PBL_DETECT_CODE); 00944 00945 } 00946 } 00947 00948 //IRQ_SYNCWORD_VALID = 0x0008, 00949 if( irqRegs & IRQ_SYNCWORD_VALID ) 00950 { 00951 if( rxPblSyncWordHeader != NULL ) 00952 { 00953 rxPblSyncWordHeader( IRQ_SYNCWORD_VALID_CODE ); 00954 } 00955 } 00956 00957 //IRQ_HEADER_VALID = 0x0010, 00958 if ( irqRegs & IRQ_HEADER_VALID ) 00959 { 00960 if( rxPblSyncWordHeader != NULL ) 00961 { 00962 rxPblSyncWordHeader( IRQ_HEADER_VALID_CODE ); 00963 } 00964 } 00965 00966 //IRQ_HEADER_ERROR = 0x0020, 00967 if( irqRegs & IRQ_HEADER_ERROR ) 00968 { 00969 if( rxError != NULL ) 00970 { 00971 rxError( IRQ_HEADER_ERROR_CODE ); 00972 } 00973 } 00974 */ 00975 } 00976 00977 00978
Generated on Tue Jul 12 2022 15:50:44 by
