SX1276GenericLib to support sx1276 bassed LoRa modules, including HopeRF RFM95, Murata CMWX1ZZABZ and Semtech SX1276MB1MAS/SX1276MB1LAS modules

Dependents:   DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_PingPong DISCO-L072CZ-LRWAN1_LoRa_USB_Rx ... more

Fork of SX1276Lib by Semtech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sx1276-mbed-hal.cpp Source File

sx1276-mbed-hal.cpp

00001 /*
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C) 2014 Semtech
00008 
00009 Description: -
00010 
00011 License: Revised BSD License, see LICENSE.TXT file include in the project
00012 
00013 Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin
00014 */
00015 
00016 /*
00017  * additional development to make it more generic across multiple OS versions
00018  * (c) 2017 Helmut Tschemernjak
00019  * 30826 Garbsen (Hannover) Germany
00020  */
00021 
00022 #ifdef ARDUINO
00023  #include "arduino-mbed.h"
00024 #endif
00025 
00026 #include "sx1276-mbed-hal.h"
00027 
00028 
00029 
00030 SX1276Generic::SX1276Generic( RadioEvents_t *events, BoardType_t board,
00031                             PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset,
00032                             PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5,
00033                             PinName antSwitch, PinName antSwitchTX, PinName antSwitchTXBoost, PinName tcxo)
00034                             : SX1276 ( events)
00035 {
00036     Sleep_ms( 10 );
00037     this->RadioEvents = events;
00038     boardConnected = board;
00039     
00040     _antSwitchPwr = NULL;
00041     _antSwitch = NULL;
00042     _antSwitchTX = NULL;
00043     _antSwitchTXBoost = NULL;
00044     
00045     _tcxo = NULL;
00046     if (tcxo != NC)
00047         _tcxo = new DigitalOut(tcxo);
00048     
00049     switch(boardConnected) {
00050         case SX1276MB1MAS:
00051         case SX1276MB1LAS:
00052             _antSwitch = new DigitalOut(antSwitch);
00053             break;
00054         case RFM95_SX1276:
00055             break;
00056         case HELTEC_L4_1276:
00057             _antSwitchPwr = new DigitalOut(antSwitch);
00058             break;
00059         case MURATA_SX1276:
00060             _antSwitch = new DigitalOut(antSwitch);
00061             _antSwitchTX = new DigitalOut(antSwitchTX);
00062             _antSwitchTXBoost = new DigitalOut(antSwitchTXBoost);
00063             break;
00064         default:
00065             break;
00066     }
00067     _spi = new XSPI(mosi, miso, sclk );
00068     _nss = new DigitalOut(nss);
00069     
00070     _reset = new DigitalInOut(reset);
00071     
00072     _dio0 = NULL;
00073     _dio1 = NULL;
00074     _dio2 = NULL;
00075     _dio3 = NULL;
00076     _dio4 = NULL;
00077     _dio5 = NULL;
00078     if (dio0 != NC)
00079         _dio0 = new InterruptIn(dio0);
00080     if (dio1 != NC)
00081         _dio1 = new InterruptIn(dio1);
00082     if (dio2 != NC)
00083         _dio2 = new InterruptIn(dio2);
00084     if (dio3 != NC)
00085         _dio3 = new InterruptIn(dio3);
00086     if (dio4 != NC)
00087         _dio4 = new InterruptIn(dio4);
00088     if (dio5 != NC)
00089         _dio5 = new DigitalIn(dio5);
00090    
00091     Reset( );
00092 
00093     IoInit( );
00094 
00095     RxChainCalibration( );
00096  
00097     SetOpMode( RF_OPMODE_SLEEP );
00098 
00099     IoIrqInit( dioIrq );
00100 
00101     RadioRegistersInit( );
00102 
00103     SetModem( MODEM_FSK );
00104 }
00105 
00106 SX1276Generic::~SX1276Generic()
00107 {
00108     txTimeoutTimer .detach();
00109     rxTimeoutTimer.detach();
00110     rxTimeoutSyncWord.detach();
00111     
00112     if (_antSwitchPwr )
00113         delete(_antSwitchPwr );
00114     if (_antSwitch)
00115         delete _antSwitch;
00116     if (_antSwitchTX)
00117         delete _antSwitchTX;
00118     if (_antSwitchTXBoost)
00119         delete _antSwitchTXBoost;
00120     
00121     if (_tcxo ) {
00122         *_tcxo  = 0;
00123         delete (_tcxo );
00124     }
00125     /*
00126      * Reset(); // to put chip back into fresh state
00127      * We disabled the Reset() to allow the destructor to keep the
00128      * chip in Sleep() mode to stay turned off with little energy 
00129      * consumption.
00130      */
00131     delete _reset ;
00132     delete _spi ;
00133     delete _nss;
00134     
00135     if (_dio0 )
00136         delete _dio0 ;
00137     if (_dio1)
00138         delete _dio1;
00139     if (_dio2)
00140         delete _dio2;
00141     if (_dio3)
00142         delete _dio3;
00143     if (_dio4)
00144         delete _dio4;
00145     if (_dio5)
00146         delete _dio5;
00147 }
00148 
00149 
00150 //-------------------------------------------------------------------------
00151 //                      Board relative functions
00152 //-------------------------------------------------------------------------
00153 uint8_t SX1276Generic::DetectBoardType( void )
00154 {
00155     return boardConnected;
00156 }
00157 
00158 void SX1276Generic::IoInit( void )
00159 {
00160     if (_tcxo )
00161         *_tcxo  = 1;
00162     AntSwInit( );
00163     SpiInit( );
00164 }
00165 
00166 
00167 void SX1276Generic::SpiInit( void )
00168 {
00169     *_nss = 1;
00170     _spi ->format( 8,0 );
00171     uint32_t frequencyToSet = 8000000;
00172 #ifdef TARGET_KL25Z //busclock frequency is halved -> double the spi frequency to compensate
00173     _spi ->frequency( frequencyToSet * 2 );
00174 #else
00175     _spi ->frequency( frequencyToSet );
00176 #endif
00177     wait_ms(100);
00178 }
00179 
00180 void SX1276Generic::IoIrqInit( DioIrqHandler *irqHandlers )
00181 {
00182     if (_dio0 )
00183         _dio0 ->rise(callback(this, static_cast< Trigger > ( irqHandlers[0] )));
00184     else
00185         irqHandlers[0] = NULL;
00186     
00187     if (_dio1)
00188         _dio1->rise(callback(this, static_cast< Trigger > ( irqHandlers[1] )));
00189     else
00190         irqHandlers[1] = NULL;
00191     
00192     if (_dio2)
00193         _dio2->rise(callback(this, static_cast< Trigger > ( irqHandlers[2] )));
00194     else
00195         irqHandlers[2] = NULL;
00196     
00197     if (_dio3)
00198         _dio3->rise(callback(this, static_cast< Trigger > ( irqHandlers[3] )));
00199     else
00200         irqHandlers[3] = NULL;
00201     
00202     if (_dio4)
00203         _dio4->rise(callback(this, static_cast< Trigger > ( irqHandlers[4] )));
00204     else
00205         irqHandlers[4] = NULL;
00206 }
00207 
00208 void SX1276Generic::IoDeInit( void )
00209 {
00210     //nothing
00211 }
00212 
00213 void SX1276Generic::SetRfTxPower( int8_t power )
00214 {
00215     uint8_t paConfig = 0;
00216     uint8_t paDac = 0;
00217     
00218     paConfig = Read( REG_PACONFIG );
00219     paDac = Read( REG_PADAC );
00220     
00221     paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | GetPaSelect( this->settings.Channel );
00222     paConfig = ( paConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70;
00223     
00224     if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST )
00225     {
00226         if( power > 17 )
00227         {
00228             paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON;
00229         }
00230         else
00231         {
00232             paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF;
00233         }
00234         if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON )
00235         {
00236             if( power < 5 )
00237             {
00238                 power = 5;
00239             }
00240             if( power > 20 )
00241             {
00242                 power = 20;
00243             }
00244             paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F );
00245         }
00246         else
00247         {
00248             if( power < 2 )
00249             {
00250                 power = 2;
00251             }
00252             if( power > 17 )
00253             {
00254                 power = 17;
00255             }
00256             paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F );
00257         }
00258     }
00259     else
00260     {
00261         if( power < -1 )
00262         {
00263             power = -1;
00264         }
00265         if( power > 14 )
00266         {
00267             power = 14;
00268         }
00269         paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F );
00270     }
00271     Write( REG_PACONFIG, paConfig );
00272     Write( REG_PADAC, paDac );
00273 }
00274 
00275 
00276 uint8_t SX1276Generic::GetPaSelect( uint32_t channel )
00277 {
00278     if( channel > RF_MID_BAND_THRESH )
00279     {
00280         if (boardConnected == SX1276MB1LAS || boardConnected == RFM95_SX1276 || boardConnected == MURATA_SX1276 || boardConnected == HELTEC_L4_1276)
00281         {
00282             return RF_PACONFIG_PASELECT_PABOOST;
00283         }
00284         else
00285         {
00286             return RF_PACONFIG_PASELECT_RFO;
00287         }
00288     }
00289     else
00290     {
00291         return RF_PACONFIG_PASELECT_RFO;
00292     }
00293 }
00294 
00295 void SX1276Generic::SetAntSwLowPower( bool status )
00296 {
00297     if( isRadioActive != status )
00298     {
00299         isRadioActive = status;
00300     
00301         if( status == false )
00302         {
00303             AntSwInit( );
00304         }
00305         else
00306         {
00307             AntSwDeInit( );
00308         }
00309     }
00310 }
00311 
00312 void SX1276Generic::AntSwInit( void )
00313 {
00314     if (_antSwitch)
00315         *_antSwitch = 0;
00316     if (boardConnected == MURATA_SX1276) {
00317         *_antSwitchTX = 0;
00318         *_antSwitchTXBoost = 0;
00319     }
00320     if (boardConnected == HELTEC_L4_1276)
00321         *_antSwitchPwr  = PWR_OFF;
00322 }
00323 
00324 void SX1276Generic::AntSwDeInit( void )
00325 {
00326     if (_antSwitch)
00327         *_antSwitch = 0;
00328     if (boardConnected == MURATA_SX1276) {
00329         *_antSwitchTX = 0;
00330         *_antSwitchTXBoost = 0;
00331     }
00332     if (boardConnected == HELTEC_L4_1276)
00333         *_antSwitchPwr  = PWR_OFF;
00334 }
00335 
00336 
00337 void SX1276Generic::SetAntSw( uint8_t opMode )
00338 {
00339     switch( opMode )
00340     {
00341         case RFLR_OPMODE_TRANSMITTER:
00342             if (boardConnected == MURATA_SX1276) {
00343                 *_antSwitch = 0;// Murata-RX
00344                 if (Read( REG_PACONFIG) & RF_PACONFIG_PASELECT_PABOOST)
00345                     *_antSwitchTXBoost = 1;
00346                 else
00347                     *_antSwitchTX = 1;  // alternate: antSwitchTXBoost = 1
00348             } else {
00349                 if (_antSwitch)
00350                     *_antSwitch = 1;
00351             }
00352             if (boardConnected == HELTEC_L4_1276)
00353                 *_antSwitchPwr  = PWR_ON;
00354             break;
00355         case RFLR_OPMODE_RECEIVER:
00356         case RFLR_OPMODE_RECEIVER_SINGLE:
00357         case RFLR_OPMODE_CAD:
00358             if (boardConnected == MURATA_SX1276) {
00359                 *_antSwitch = 1;  // Murata-RX
00360                 *_antSwitchTX = 0;
00361                 *_antSwitchTXBoost = 0;
00362             } else if (boardConnected == HELTEC_L4_1276) {
00363                 *_antSwitchPwr  = PWR_ON;
00364             } else {
00365                 if (_antSwitch)
00366                     _antSwitch = 0;
00367             }
00368             break;
00369         case RFLR_OPMODE_SLEEP:
00370         case RFLR_OPMODE_STANDBY:
00371         default:
00372             if (boardConnected == MURATA_SX1276) {
00373                 *_antSwitch = 0;  //Murata-RX
00374                 *_antSwitchTX = 0;
00375                 *_antSwitchTXBoost = 0;
00376             } else if (boardConnected == HELTEC_L4_1276) {
00377                 *_antSwitchPwr  = PWR_OFF;
00378             } else {
00379                 if (_antSwitch)
00380                     *_antSwitch = 0;
00381             }
00382             break;
00383     }
00384 }
00385 
00386 void SX1276Generic::SetTimeout(TimeoutTimer_t timer, timeoutFuncPtr func, int timeout_ms)
00387 {
00388     switch(timer) {
00389         case RXTimeoutTimer:
00390             if (func)
00391                 rxTimeoutTimer.attach_us(callback(this, func), timeout_ms);
00392             else
00393                 rxTimeoutTimer.detach();
00394             break;
00395         case TXTimeoutTimer:
00396             if (func)
00397                 txTimeoutTimer .attach_us(callback(this, func), timeout_ms);
00398             else
00399                 txTimeoutTimer .detach();
00400             break;
00401         case RXTimeoutSyncWordTimer:
00402             if (func)
00403                 rxTimeoutSyncWord.attach_us(callback(this, func), timeout_ms);
00404             else
00405                 rxTimeoutSyncWord.detach();
00406             break;
00407     }
00408 }
00409 
00410 void
00411 SX1276Generic::Sleep_ms(int ms)
00412 {
00413     wait_ms(ms);
00414 }
00415 
00416 bool SX1276Generic::CheckRfFrequency( uint32_t frequency )
00417 {
00418     if (frequency > 1200000)
00419         return false;
00420     // Implement check. Currently all frequencies are supported
00421     return true;
00422 }
00423 
00424 void SX1276Generic::Reset( void )
00425 {
00426     _reset ->output();
00427     *_reset  = 0;
00428     wait_ms( 1 );
00429     *_reset  = 1;
00430     _reset ->input();    // I don't know why input again, maybe to save power (Helmut T)
00431     wait_ms( 6 );
00432 }
00433 
00434 void SX1276Generic::Write( uint8_t addr, uint8_t data )
00435 {
00436     Write( addr, &data, 1 );
00437 }
00438 
00439 uint8_t SX1276Generic::Read( uint8_t addr )
00440 {
00441     uint8_t data;
00442     Read( addr, &data, 1 );
00443     return data;
00444 }
00445 
00446 void SX1276Generic::Write( uint8_t addr, void *buffer, uint8_t size )
00447 {
00448     uint8_t i;
00449     uint8_t *p = (uint8_t *)buffer;
00450 
00451     *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut
00452     _spi ->write( addr | 0x80 );
00453     for( i = 0; i < size; i++ )
00454     {
00455         _spi ->write(*p++);
00456     }
00457     *_nss = 1;
00458 }
00459 
00460 void SX1276Generic::Read( uint8_t addr, void *buffer, uint8_t size )
00461 {
00462     uint8_t i;
00463     uint8_t *p = (uint8_t *)buffer;
00464     
00465     *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut
00466     _spi ->write( addr & 0x7F );
00467     for( i = 0; i < size; i++ )
00468     {
00469         *p++ = _spi ->write( 0 );
00470     }
00471     *_nss = 1;
00472 }
00473 
00474 void SX1276Generic::WriteFifo( void *buffer, uint8_t size )
00475 {
00476     Write( 0, buffer, size );
00477 }
00478 
00479 void SX1276Generic::ReadFifo( void *buffer, uint8_t size )
00480 {
00481     Read( 0, buffer, size );
00482 }