Semtech / SX126xLib

Dependents:   SX126xDevKit SX1262PingPong SX126X_TXonly SX126X_PingPong_Demo ... more

Fork of SX126xLib by Gregory Cristian

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sx126x-hal.cpp Source File

sx126x-hal.cpp

00001 /*
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2016 Semtech
00008 
00009 Description: Handling of the node configuration protocol
00010 
00011 License: Revised BSD License, see LICENSE.TXT file include in the project
00012 
00013 Maintainer: Miguel Luis, Gregory Cristian and Matthieu Verdy
00014 */
00015 #include "sx126x-hal.h"
00016 
00017 /*!
00018  * \brief Helper macro to create Interrupt objects only if the pin name is
00019  *        different from NC
00020  */
00021 #define CreateDioPin( pinName, dio )                 \
00022             if( pinName == NC )                      \
00023             {                                        \
00024                 dio = NULL;                          \
00025             }                                        \
00026             else                                     \
00027             {                                        \
00028                 dio = new InterruptIn( pinName );    \
00029             }
00030 
00031 /*!
00032  * \brief Helper macro to avoid duplicating code for setting dio pins parameters
00033  */
00034 #define DioAssignCallback( dio, pinMode, callback )                    \
00035             if( dio != NULL )                                          \
00036             {                                                          \
00037                 dio->mode( pinMode );                                  \
00038                 dio->rise( this, static_cast <Trigger>( callback ) );  \
00039             }
00040 
00041 /*!
00042  * \brief Used to block execution waiting for low state on radio busy pin.
00043  */
00044 #define WaitOnBusy( )             while( BUSY == 1 ){ }
00045 
00046 /*!
00047  * \brief Used to block execution to give enough time to Busy to go up
00048  *        in order to respect Tsw, see datasheet ยง8.3.1
00049  */
00050 #define WaitOnCounter( )          for( uint8_t counter = 0; counter < 15; counter++ ) \
00051                                   {  __NOP( ); }
00052 
00053                                   
00054 // This code handles cases where assert_param is undefined
00055 #ifndef assert_param
00056 #define assert_param( ... )
00057 #endif
00058 
00059 SX126xHal::SX126xHal( PinName mosi, PinName miso, PinName sclk, PinName nss,
00060                       PinName busy, PinName dio1, PinName dio2, PinName dio3, PinName rst,
00061                       PinName freqSel, PinName deviceSelect, PinName antSwPower, RadioCallbacks_t *callbacks )
00062         :   SX126x( callbacks ),
00063             RadioNss( nss ),
00064             RadioReset( rst ),
00065             BUSY( busy ),
00066             FreqSelect( freqSel ),
00067             DeviceSelect( deviceSelect ),
00068             antSwitchPower( antSwPower )
00069 {
00070     CreateDioPin( dio1, DIO1 );
00071     CreateDioPin( dio2, DIO2 );
00072     CreateDioPin( dio3, DIO3 );
00073     RadioSpi = new SPI( mosi, miso, sclk );
00074 
00075     RadioNss = 1;
00076     RadioReset = 1;
00077 }
00078 
00079 SX126xHal::~SX126xHal( void )
00080 {
00081     if( this->RadioSpi != NULL )
00082     {
00083         delete RadioSpi;
00084     }
00085     if( DIO1 != NULL )
00086     {
00087         delete DIO1;
00088     }
00089     if( DIO2 != NULL )
00090     {
00091         delete DIO2;
00092     }
00093     if( DIO3 != NULL )
00094     {
00095         delete DIO3;
00096     }
00097 };
00098 
00099 void SX126xHal::SpiInit( void )
00100 {
00101     RadioNss = 1;
00102     RadioSpi->format( 8, 0 );
00103     RadioSpi->frequency( SX126x_SPI_FREQ_DEFAULT );
00104 
00105     wait( 0.1 );
00106 }
00107 
00108 
00109 void SX126xHal::IoIrqInit( DioIrqHandler irqHandler )
00110 {
00111     assert_param( RadioSpi != NULL );
00112     if( RadioSpi != NULL )
00113     {
00114         SpiInit( );
00115     }
00116 
00117     BUSY.mode( PullNone );
00118     DioAssignCallback( DIO1, PullNone, irqHandler );
00119 //    DioAssignCallback( DIO2, PullNone, irqHandler );
00120 //    DioAssignCallback( DIO3, PullNone, irqHandler );
00121 
00122 }
00123 
00124 void SX126xHal::Reset( void )
00125 {
00126     __disable_irq( );
00127     wait_ms( 20 );
00128     RadioReset.output( );
00129     RadioReset = 0;
00130     wait_ms( 50 );
00131     RadioReset = 1;
00132     RadioReset.input( ); // Using the internal pull-up
00133     wait_ms( 20 );
00134     __enable_irq( );
00135 }
00136 
00137 void SX126xHal::Wakeup( void )
00138 {
00139     __disable_irq( );
00140 
00141     //Don't wait for BUSY here
00142 
00143     if( RadioSpi != NULL )
00144     {
00145         RadioNss = 0;
00146         RadioSpi->write( RADIO_GET_STATUS );
00147         RadioSpi->write( 0 );
00148         RadioNss = 1;
00149     }
00150 
00151     // Wait for chip to be ready.
00152     WaitOnBusy( );
00153 
00154     __enable_irq( );
00155     
00156     AntSwOn( );
00157 }
00158 
00159 void SX126xHal::WriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
00160 {
00161 #ifdef ADV_DEBUG
00162     printf("cmd: 0x%02x", command );
00163     for( uint8_t i = 0; i < size; i++ )
00164     {
00165         printf("-%02x", buffer[i] );
00166     }
00167     printf("\n\r");
00168 #endif
00169     
00170     WaitOnBusy( );
00171 
00172     if( RadioSpi != NULL )
00173     {
00174         RadioNss = 0;
00175         RadioSpi->write( ( uint8_t )command );
00176         for( uint16_t i = 0; i < size; i++ )
00177         {
00178             RadioSpi->write( buffer[i] );
00179         }
00180         RadioNss = 1;
00181     }
00182     WaitOnCounter( );
00183 }
00184 
00185 void SX126xHal::ReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
00186 {
00187     WaitOnBusy( );
00188 
00189     if( RadioSpi != NULL )
00190     {
00191         RadioNss = 0;
00192         RadioSpi->write( ( uint8_t )command );
00193         RadioSpi->write( 0 );
00194         for( uint16_t i = 0; i < size; i++ )
00195         {
00196              buffer[i] = RadioSpi->write( 0 );
00197         }
00198         RadioNss = 1;
00199     }
00200 }
00201 
00202 void SX126xHal::WriteRegister( uint16_t address, uint8_t *buffer, uint16_t size )
00203 {
00204     WaitOnBusy( );
00205 
00206     if( RadioSpi != NULL )
00207     {
00208         RadioNss = 0;
00209         RadioSpi->write( RADIO_WRITE_REGISTER );
00210         RadioSpi->write( ( address & 0xFF00 ) >> 8 );
00211         RadioSpi->write( address & 0x00FF );
00212         for( uint16_t i = 0; i < size; i++ )
00213         {
00214             RadioSpi->write( buffer[i] );
00215         }
00216         RadioNss = 1;
00217     }
00218 }
00219 
00220 void SX126xHal::WriteReg( uint16_t address, uint8_t value )
00221 {
00222     WriteRegister( address, &value, 1 );
00223 }
00224 
00225 void SX126xHal::ReadRegister( uint16_t address, uint8_t *buffer, uint16_t size )
00226 {
00227     WaitOnBusy( );
00228 
00229     if( RadioSpi != NULL )
00230     {
00231         RadioNss = 0;
00232         RadioSpi->write( RADIO_READ_REGISTER );
00233         RadioSpi->write( ( address & 0xFF00 ) >> 8 );
00234         RadioSpi->write( address & 0x00FF );
00235         RadioSpi->write( 0 );
00236         for( uint16_t i = 0; i < size; i++ )
00237         {
00238             buffer[i] = RadioSpi->write( 0 );
00239         }
00240         RadioNss = 1;
00241     }
00242 }
00243 
00244 uint8_t SX126xHal::ReadReg( uint16_t address )
00245 {
00246     uint8_t data;
00247 
00248     ReadRegister( address, &data, 1 );
00249     return data;
00250 }
00251 
00252 void SX126xHal::WriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
00253 {
00254     WaitOnBusy( );
00255 
00256     if( RadioSpi != NULL )
00257     {
00258         RadioNss = 0;
00259         RadioSpi->write( RADIO_WRITE_BUFFER );
00260         RadioSpi->write( offset );
00261         for( uint16_t i = 0; i < size; i++ )
00262         {
00263             RadioSpi->write( buffer[i] );
00264         }
00265         RadioNss = 1;
00266     }
00267 }
00268 
00269 void SX126xHal::ReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
00270 {
00271     WaitOnBusy( );
00272 
00273     if( RadioSpi != NULL )
00274     {
00275         RadioNss = 0;
00276         RadioSpi->write( RADIO_READ_BUFFER );
00277         RadioSpi->write( offset );
00278         RadioSpi->write( 0 );
00279         for( uint16_t i = 0; i < size; i++ )
00280         {
00281             buffer[i] = RadioSpi->write( 0 );
00282         }
00283         RadioNss = 1;
00284     }
00285 }
00286 
00287 uint8_t SX126xHal::GetDioStatus( void )
00288 {
00289     return ( *DIO3 << 3 ) | ( *DIO2 << 2 ) | ( *DIO1 << 1 ) | ( BUSY << 0 );
00290 }
00291 
00292 uint8_t SX126xHal::GetDeviceType( void )
00293 {
00294     uint16_t val = 0;
00295     val = DeviceSelect.read_u16( );
00296 
00297     if( val <= 0x2000 )
00298     {
00299         return( SX1262 );
00300     }
00301     else if( val <= 0xA000 )
00302     {
00303         return( SX1268 );
00304     }
00305     else 
00306     {
00307         return( SX1261 );
00308     }
00309 }
00310 
00311 uint8_t SX126xHal::GetFreqSelect( void )
00312 {
00313     uint16_t val = 0;
00314     val = FreqSelect.read_u16( );
00315 
00316     if( val < 100 )
00317     {
00318         return( MATCHING_FREQ_915 );
00319     }
00320     else if( val <= 0x3000 )
00321     {
00322         return( MATCHING_FREQ_780 );
00323     }
00324     else if( val <= 0x4900 )       // 0x4724
00325     {
00326         return( MATCHING_FREQ_490 );
00327     }
00328     else if( val <= 1 )
00329     {
00330         return( MATCHING_FREQ_434 );
00331     }
00332     else if( val <= 1 )
00333     {
00334         return( MATCHING_FREQ_280 );
00335     }
00336     else if( val <= 0xF000 )
00337     {
00338         return( MATCHING_FREQ_169 );
00339     }
00340     else
00341     {
00342         return( MATCHING_FREQ_868 );
00343     }
00344 }
00345 
00346 void SX126xHal::AntSwOn( void )
00347 {
00348     antSwitchPower = 1;
00349 }
00350 
00351 void SX126xHal::AntSwOff( void )
00352 {
00353     antSwitchPower = 0;
00354 }