Semtech / SX1280Lib

Dependents:   SX1280PingPong RangignMaster RangingSlave MSNV2-Terminal_V1-6 ... more

Embed: (wiki syntax)

« Back to documentation index

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

sx1280-hal.cpp

00001 /*
00002   ______                              _
00003  / _____)             _              | |
00004 ( (____  _____ ____ _| |_ _____  ____| |__
00005  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00006  _____) ) ____| | | || |_| ____( (___| | | |
00007 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00008     (C)2016 Semtech
00009 
00010 Description: Handling of the node configuration protocol
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 "sx1280-hal.h"
00017 
00018 /*!
00019  * \brief Helper macro to create Interrupt objects only if the pin name is
00020  *        different from NC
00021  */
00022 #define CreateDioPin( pinName, dio )                 \
00023             if( pinName == NC )                      \
00024             {                                        \
00025                 dio = NULL;                          \
00026             }                                        \
00027             else                                     \
00028             {                                        \
00029                 dio = new InterruptIn( pinName );    \
00030             }
00031 
00032 /*!
00033  * \brief Helper macro to avoid duplicating code for setting dio pins parameters
00034  */
00035 #if defined( TARGET_NUCLEO_L476RG )
00036 #define DioAssignCallback( dio, pinMode, callback )                    \
00037             if( dio != NULL )                                          \
00038             {                                                          \
00039                 dio->mode( pinMode );                                  \
00040                 dio->rise( this, static_cast <Trigger>( callback ) );  \
00041             }
00042 #else
00043 #define DioAssignCallback( dio, pinMode, callback )                    \
00044             if( dio != NULL )                                          \
00045             {                                                          \
00046                 dio->rise( this, static_cast <Trigger>( callback ) );  \
00047             }
00048 #endif
00049 /*!
00050  * \brief Used to block execution waiting for low state on radio busy pin.
00051  *        Essentially used in SPI communications
00052  */
00053 #define WaitOnBusy( )          while( BUSY == 1 ){ }
00054 
00055 /*!
00056  * \brief Blocking routine for waiting the UART to be writeable
00057  *
00058  */
00059 #define WaitUartWritable( )  while( RadioUart->writeable( ) == false ){ }
00060 
00061 /*!
00062  * \brief Blocking routine for waiting the UART to be readable
00063  *
00064  */
00065 #define WaitUartReadable( )  while( RadioUart->readable( ) == false ){ }
00066 
00067 // This code handles cases where assert_param is undefined
00068 #ifndef assert_param
00069 #define assert_param( ... )
00070 #endif
00071 
00072 SX1280Hal::SX1280Hal( PinName mosi, PinName miso, PinName sclk, PinName nss,
00073                       PinName busy, PinName dio1, PinName dio2, PinName dio3, PinName rst,
00074                       RadioCallbacks_t *callbacks )
00075         :   SX1280( callbacks ),
00076             RadioNss( nss ),
00077             RadioReset( rst ),
00078             RadioCtsn( NC ),
00079             BUSY( busy )
00080 {
00081     CreateDioPin( dio1, DIO1 );
00082     CreateDioPin( dio2, DIO2 );
00083     CreateDioPin( dio3, DIO3 );
00084     RadioSpi = new SPI( mosi, miso, sclk );
00085     RadioUart = NULL;
00086 
00087     RadioNss = 1;
00088     RadioReset = 1;
00089 }
00090 
00091 SX1280Hal::SX1280Hal( PinName tx, PinName rx, PinName ctsn,
00092                       PinName busy, PinName dio1, PinName dio2, PinName dio3, PinName rst,
00093                       RadioCallbacks_t *callbacks )
00094         :   SX1280( callbacks ),
00095             RadioNss( NC ),
00096             RadioReset( rst ),
00097             RadioCtsn( ctsn ),
00098             BUSY( busy )
00099 {
00100     CreateDioPin( dio1, DIO1 );
00101     CreateDioPin( dio2, DIO2 );
00102     CreateDioPin( dio3, DIO3 );
00103     RadioSpi = NULL;
00104     RadioUart = new Serial( tx, rx );
00105     RadioCtsn = 0;
00106     RadioReset = 1;
00107 }
00108 
00109 SX1280Hal::~SX1280Hal( void )
00110 {
00111     if( this->RadioSpi != NULL )
00112     {
00113         delete RadioSpi;
00114     }
00115     if( this->RadioUart != NULL )
00116     {
00117         delete RadioUart;
00118     }
00119     if( DIO1 != NULL )
00120     {
00121         delete DIO1;
00122     }
00123     if( DIO2 != NULL )
00124     {
00125         delete DIO2;
00126     }
00127     if( DIO3 != NULL )
00128     {
00129         delete DIO3;
00130     }
00131 };
00132 
00133 void SX1280Hal::SpiInit( void )
00134 {
00135     RadioNss = 1;
00136     RadioSpi->format( 8, 0 );
00137 #if defined( TARGET_KL25Z )
00138     this->SetSpiSpeed( 4000000 );
00139 #elif defined( TARGET_NUCLEO_L476RG )
00140     this->SetSpiSpeed( 8000000 );
00141 #else
00142     this->SetSpiSpeed( 8000000 );
00143 #endif
00144     wait( 0.1 );
00145 }
00146 
00147 void SX1280Hal::SetSpiSpeed( uint32_t spiSpeed )
00148 {
00149     RadioSpi->frequency( spiSpeed );
00150 }
00151 
00152 void SX1280Hal::UartInit( void )
00153 {
00154     RadioUart->format( 9, SerialBase::Even, 1 ); // 8 data bits + 1 even parity bit + 1 stop bit
00155     RadioUart->baud( 115200 );
00156     // After this point, the UART is running standard mode: 8 data bit, 1 even
00157     // parity bit, 1 stop bit, 115200 baud, LSB first
00158     wait_us( 10 );
00159 }
00160 
00161 void SX1280Hal::IoIrqInit( DioIrqHandler irqHandler )
00162 {
00163     assert_param( RadioSpi != NULL || RadioUart != NULL );
00164     if( RadioSpi != NULL )
00165     {
00166         SpiInit( );
00167     }
00168     if( RadioUart != NULL )
00169     {
00170         UartInit( );
00171     }
00172 
00173     BUSY.mode( PullNone );
00174 
00175     DioAssignCallback( DIO1, PullNone, irqHandler );
00176     DioAssignCallback( DIO2, PullNone, irqHandler );
00177     DioAssignCallback( DIO3, PullNone, irqHandler );
00178 }
00179 
00180 void SX1280Hal::Reset( void )
00181 {
00182     __disable_irq( );
00183     wait_ms( 20 );
00184     RadioReset.output( );
00185     RadioReset = 0;
00186     wait_ms( 50 );
00187     RadioReset = 1;
00188     RadioReset.input( ); // Using the internal pull-up
00189     wait_ms( 20 );
00190     __enable_irq( );
00191 }
00192 
00193 void SX1280Hal::Wakeup( void )
00194 {
00195     __disable_irq( );
00196 
00197     //Don't wait for BUSY here
00198 
00199     if( RadioSpi != NULL )
00200     {
00201         RadioNss = 0;
00202         RadioSpi->write( RADIO_GET_STATUS );
00203         RadioSpi->write( 0 );
00204         RadioNss = 1;
00205     }
00206     if( RadioUart != NULL )
00207     {
00208         RadioUart->putc( RADIO_GET_STATUS );
00209         WaitUartReadable( );
00210         RadioUart->getc( );
00211     }
00212 
00213     // Wait for chip to be ready.
00214     WaitOnBusy( );
00215 
00216     __enable_irq( );
00217 }
00218 
00219 void SX1280Hal::WriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
00220 {
00221     WaitOnBusy( );
00222 
00223     if( RadioSpi != NULL )
00224     {
00225         RadioNss = 0;
00226         RadioSpi->write( ( uint8_t )command );
00227         for( uint16_t i = 0; i < size; i++ )
00228         {
00229             RadioSpi->write( buffer[i] );
00230         }
00231         RadioNss = 1;
00232     }
00233     if( RadioUart != NULL )
00234     {
00235         RadioUart->putc( command );
00236         if( size > 0 )
00237         {
00238             RadioUart->putc( size );
00239             for( uint16_t i = 0; i < size; i++ )
00240             {
00241                 RadioUart->putc( buffer[i] );
00242             }
00243         }
00244     }
00245 
00246     if( command != RADIO_SET_SLEEP )
00247     {
00248         WaitOnBusy( );
00249     }
00250 }
00251 
00252 void SX1280Hal::ReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
00253 {
00254     WaitOnBusy( );
00255 
00256     if( RadioSpi != NULL )
00257     {
00258         RadioNss = 0;
00259         if( command == RADIO_GET_STATUS )
00260         {
00261             buffer[0] = RadioSpi->write( ( uint8_t )command );
00262             RadioSpi->write( 0 );
00263             RadioSpi->write( 0 );
00264         }
00265         else
00266         {
00267             RadioSpi->write( ( uint8_t )command );
00268             RadioSpi->write( 0 );
00269             for( uint16_t i = 0; i < size; i++ )
00270             {
00271                  buffer[i] = RadioSpi->write( 0 );
00272             }
00273         }
00274         RadioNss = 1;
00275     }
00276     if( RadioUart != NULL )
00277     {
00278         RadioUart->putc( command );
00279 
00280         // Behavior on the UART is different depending of the opcode command
00281         if( ( command == RADIO_GET_PACKETTYPE ) ||
00282             ( command == RADIO_GET_RXBUFFERSTATUS ) ||
00283             ( command == RADIO_GET_RSSIINST ) ||
00284             ( command == RADIO_GET_PACKETSTATUS ) ||
00285             ( command == RADIO_GET_IRQSTATUS ) )
00286         {
00287             /*
00288              * TODO : Check size size in UART (uint8_t in putc)
00289              */
00290             RadioUart->putc( size );
00291         }
00292 
00293         WaitUartReadable( );
00294         for( uint16_t i = 0; i < size; i++ )
00295         {
00296              buffer[i] = RadioUart->getc( );
00297         }
00298     }
00299 
00300     WaitOnBusy( );
00301 }
00302 
00303 void SX1280Hal::WriteRegister( uint16_t address, uint8_t *buffer, uint16_t size )
00304 {
00305     WaitOnBusy( );
00306 
00307     if( RadioSpi != NULL )
00308     {
00309         RadioNss = 0;
00310         RadioSpi->write( RADIO_WRITE_REGISTER );
00311         RadioSpi->write( ( address & 0xFF00 ) >> 8 );
00312         RadioSpi->write( address & 0x00FF );
00313         for( uint16_t i = 0; i < size; i++ )
00314         {
00315             RadioSpi->write( buffer[i] );
00316         }
00317         RadioNss = 1;
00318     }
00319     if( RadioUart != NULL )
00320     {
00321         uint16_t addr = address;
00322         uint16_t i = 0;
00323         for( addr = address; ( addr + 255 ) < ( address + size ); )
00324         {
00325             RadioUart->putc( RADIO_WRITE_REGISTER );
00326             RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00327             RadioUart->putc( addr & 0x00FF );
00328             RadioUart->putc( 255 );
00329             for( uint16_t lastAddr = addr + 255 ; addr < lastAddr; i++, addr++ )
00330             {
00331                 RadioUart->putc( buffer[i] );
00332             }
00333         }
00334         RadioUart->putc( RADIO_WRITE_REGISTER );
00335         RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00336         RadioUart->putc( addr & 0x00FF );
00337         RadioUart->putc( address + size - addr );
00338 
00339         for( ; addr < ( address + size ); addr++, i++ )
00340         {
00341             RadioUart->putc( buffer[i] );
00342         }
00343     }
00344 
00345     WaitOnBusy( );
00346 }
00347 
00348 void SX1280Hal::WriteRegister( uint16_t address, uint8_t value )
00349 {
00350     WriteRegister( address, &value, 1 );
00351 }
00352 
00353 void SX1280Hal::ReadRegister( uint16_t address, uint8_t *buffer, uint16_t size )
00354 {
00355     WaitOnBusy( );
00356 
00357     if( RadioSpi != NULL )
00358     {
00359         RadioNss = 0;
00360         RadioSpi->write( RADIO_READ_REGISTER );
00361         RadioSpi->write( ( address & 0xFF00 ) >> 8 );
00362         RadioSpi->write( address & 0x00FF );
00363         RadioSpi->write( 0 );
00364         for( uint16_t i = 0; i < size; i++ )
00365         {
00366             buffer[i] = RadioSpi->write( 0 );
00367         }
00368         RadioNss = 1;
00369     }
00370     if( RadioUart != NULL )
00371     {
00372         uint16_t addr = address;
00373         uint16_t i = 0;
00374         for( addr = address; ( addr + 255 ) < ( address + size ); )
00375         {
00376             RadioUart->putc( RADIO_READ_REGISTER );
00377             RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00378             RadioUart->putc( addr & 0x00FF );
00379             RadioUart->putc( 255 );
00380             WaitUartReadable( );
00381             for( uint16_t lastAddr = addr + 255 ; addr < lastAddr; i++, addr++ )
00382             {
00383                 buffer[i] = RadioUart->getc( );
00384             }
00385         }
00386         RadioUart->putc( RADIO_READ_REGISTER );
00387         RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00388         RadioUart->putc( addr & 0x00FF );
00389         RadioUart->putc( address + size - addr );
00390         WaitUartReadable( );
00391         for( ; addr < ( address + size ); addr++, i++ )
00392         {
00393             buffer[i] = RadioUart->getc( );
00394         }
00395     }
00396 
00397     WaitOnBusy( );
00398 }
00399 
00400 uint8_t SX1280Hal::ReadRegister( uint16_t address )
00401 {
00402     uint8_t data;
00403 
00404     ReadRegister( address, &data, 1 );
00405     return data;
00406 }
00407 
00408 void SX1280Hal::WriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
00409 {
00410     WaitOnBusy( );
00411 
00412     if( RadioSpi != NULL )
00413     {
00414         RadioNss = 0;
00415         RadioSpi->write( RADIO_WRITE_BUFFER );
00416         RadioSpi->write( offset );
00417         for( uint16_t i = 0; i < size; i++ )
00418         {
00419             RadioSpi->write( buffer[i] );
00420         }
00421         RadioNss = 1;
00422     }
00423     if( RadioUart != NULL )
00424     {
00425         RadioUart->putc( RADIO_WRITE_BUFFER );
00426         RadioUart->putc( offset );
00427         RadioUart->putc( size );
00428         for( uint16_t i = 0; i < size; i++ )
00429         {
00430             RadioUart->putc( buffer[i] );
00431         }
00432     }
00433 
00434     WaitOnBusy( );
00435 }
00436 
00437 void SX1280Hal::ReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
00438 {
00439     WaitOnBusy( );
00440 
00441     if( RadioSpi != NULL )
00442     {
00443         RadioNss = 0;
00444         RadioSpi->write( RADIO_READ_BUFFER );
00445         RadioSpi->write( offset );
00446         RadioSpi->write( 0 );
00447         for( uint16_t i = 0; i < size; i++ )
00448         {
00449             buffer[i] = RadioSpi->write( 0 );
00450         }
00451         RadioNss = 1;
00452     }
00453     if( RadioUart != NULL )
00454     {
00455         RadioUart->putc( RADIO_READ_BUFFER );
00456         RadioUart->putc( offset );
00457         RadioUart->putc( size );
00458         WaitUartReadable( );
00459         for( uint16_t i = 0; i < size; i++ )
00460         {
00461             buffer[i] = RadioUart->getc( );
00462         }
00463     }
00464 
00465     WaitOnBusy( );
00466 }
00467 
00468 uint8_t SX1280Hal::GetDioStatus( void )
00469 {
00470     return ( *DIO3 << 3 ) | ( *DIO2 << 2 ) | ( *DIO1 << 1 ) | ( BUSY << 0 );
00471 }