Dan Fay / SX1276GenericLib
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     return RF_PACONFIG_PASELECT_PABOOST;    
00279     if( channel > RF_MID_BAND_THRESH )
00280     {
00281         if (boardConnected == SX1276MB1LAS || boardConnected == RFM95_SX1276 || boardConnected == MURATA_SX1276 || boardConnected == HELTEC_L4_1276)
00282         {
00283             return RF_PACONFIG_PASELECT_PABOOST;
00284         }
00285         else
00286         {
00287             return RF_PACONFIG_PASELECT_RFO;
00288         }
00289     }
00290     else
00291     {
00292         return RF_PACONFIG_PASELECT_RFO;
00293     }
00294 }
00295 
00296 void SX1276Generic::SetAntSwLowPower( bool status )
00297 {
00298     if( isRadioActive != status )
00299     {
00300         isRadioActive = status;
00301     
00302         if( status == false )
00303         {
00304             AntSwInit( );
00305         }
00306         else
00307         {
00308             AntSwDeInit( );
00309         }
00310     }
00311 }
00312 
00313 void SX1276Generic::AntSwInit( void )
00314 {
00315     if (_antSwitch)
00316         *_antSwitch = 0;
00317     if (boardConnected == MURATA_SX1276) {
00318         *_antSwitchTX = 0;
00319         *_antSwitchTXBoost = 0;
00320     }
00321     if (boardConnected == HELTEC_L4_1276)
00322         *_antSwitchPwr  = PWR_OFF;
00323 }
00324 
00325 void SX1276Generic::AntSwDeInit( void )
00326 {
00327     if (_antSwitch)
00328         *_antSwitch = 0;
00329     if (boardConnected == MURATA_SX1276) {
00330         *_antSwitchTX = 0;
00331         *_antSwitchTXBoost = 0;
00332     }
00333     if (boardConnected == HELTEC_L4_1276)
00334         *_antSwitchPwr  = PWR_OFF;
00335 }
00336 
00337 
00338 void SX1276Generic::SetAntSw( uint8_t opMode )
00339 {
00340     switch( opMode )
00341     {
00342         case RFLR_OPMODE_TRANSMITTER:
00343             if (boardConnected == MURATA_SX1276) {
00344                 *_antSwitch = 0;// Murata-RX
00345                 if (Read( REG_PACONFIG) & RF_PACONFIG_PASELECT_PABOOST)
00346                     *_antSwitchTXBoost = 1;
00347                 else
00348                     *_antSwitchTX = 1;  // alternate: antSwitchTXBoost = 1
00349             } else {
00350                 if (_antSwitch)
00351                     *_antSwitch = 1;
00352             }
00353             if (boardConnected == HELTEC_L4_1276)
00354                 *_antSwitchPwr  = PWR_ON;
00355             break;
00356         case RFLR_OPMODE_RECEIVER:
00357         case RFLR_OPMODE_RECEIVER_SINGLE:
00358         case RFLR_OPMODE_CAD:
00359             if (boardConnected == MURATA_SX1276) {
00360                 *_antSwitch = 1;  // Murata-RX
00361                 *_antSwitchTX = 0;
00362                 *_antSwitchTXBoost = 0;
00363             } else if (boardConnected == HELTEC_L4_1276) {
00364                 *_antSwitchPwr  = PWR_ON;
00365             } else {
00366                 if (_antSwitch)
00367                     _antSwitch = 0;
00368             }
00369             break;
00370         case RFLR_OPMODE_SLEEP:
00371         case RFLR_OPMODE_STANDBY:
00372         default:
00373             if (boardConnected == MURATA_SX1276) {
00374                 *_antSwitch = 0;  //Murata-RX
00375                 *_antSwitchTX = 0;
00376                 *_antSwitchTXBoost = 0;
00377             } else if (boardConnected == HELTEC_L4_1276) {
00378                 *_antSwitchPwr  = PWR_OFF;
00379             } else {
00380                 if (_antSwitch)
00381                     *_antSwitch = 0;
00382             }
00383             break;
00384     }
00385 }
00386 
00387 void SX1276Generic::SetTimeout(TimeoutTimer_t timer, timeoutFuncPtr func, int timeout_ms)
00388 {
00389     switch(timer) {
00390         case RXTimeoutTimer:
00391             if (func)
00392                 rxTimeoutTimer.attach_us(callback(this, func), timeout_ms);
00393             else
00394                 rxTimeoutTimer.detach();
00395             break;
00396         case TXTimeoutTimer:
00397             if (func)
00398                 txTimeoutTimer .attach_us(callback(this, func), timeout_ms);
00399             else
00400                 txTimeoutTimer .detach();
00401             break;
00402         case RXTimeoutSyncWordTimer:
00403             if (func)
00404                 rxTimeoutSyncWord.attach_us(callback(this, func), timeout_ms);
00405             else
00406                 rxTimeoutSyncWord.detach();
00407             break;
00408     }
00409 }
00410 
00411 void
00412 SX1276Generic::Sleep_ms(int ms)
00413 {
00414     wait_ms(ms);
00415 }
00416 
00417 bool SX1276Generic::CheckRfFrequency( uint32_t frequency )
00418 {
00419     if (frequency > 1200000)
00420         return false;
00421     // Implement check. Currently all frequencies are supported
00422     return true;
00423 }
00424 
00425 void SX1276Generic::Reset( void )
00426 {
00427     _reset ->output();
00428     *_reset  = 0;
00429     wait_ms( 1 );
00430     *_reset  = 1;
00431     _reset ->input();    // I don't know why input again, maybe to save power (Helmut T)
00432     wait_ms( 6 );
00433 }
00434 
00435 void SX1276Generic::Write( uint8_t addr, uint8_t data )
00436 {
00437     Write( addr, &data, 1 );
00438 }
00439 
00440 uint8_t SX1276Generic::Read( uint8_t addr )
00441 {
00442     uint8_t data;
00443     Read( addr, &data, 1 );
00444     return data;
00445 }
00446 
00447 void SX1276Generic::Write( uint8_t addr, void *buffer, uint8_t size )
00448 {
00449     uint8_t i;
00450     uint8_t *p = (uint8_t *)buffer;
00451 
00452     *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut
00453     _spi ->write( addr | 0x80 );
00454     for( i = 0; i < size; i++ )
00455     {
00456         _spi ->write(*p++);
00457     }
00458     *_nss = 1;
00459 }
00460 
00461 void SX1276Generic::Read( uint8_t addr, void *buffer, uint8_t size )
00462 {
00463     uint8_t i;
00464     uint8_t *p = (uint8_t *)buffer;
00465     
00466     *_nss = 0; // what about SPI hold/release timing on fast MCUs? Helmut
00467     _spi ->write( addr & 0x7F );
00468     for( i = 0; i < size; i++ )
00469     {
00470         *p++ = _spi ->write( 0 );
00471     }
00472     *_nss = 1;
00473 }
00474 
00475 void SX1276Generic::WriteFifo( void *buffer, uint8_t size )
00476 {
00477     Write( 0, buffer, size );
00478 }
00479 
00480 void SX1276Generic::ReadFifo( void *buffer, uint8_t size )
00481 {
00482     Read( 0, buffer, size );
00483 }