Uttam Bhat / SX1280Lib

Fork of SX1280Lib by Semtech

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     RadioSpi->frequency( 4000000 );
00139 #elif defined( TARGET_NUCLEO_L476RG )
00140     RadioSpi->frequency( 8000000 );
00141 #else
00142     RadioSpi->frequency( 8000000 );
00143 #endif
00144 
00145     wait( 0.1 );
00146 }
00147 
00148 void SX1280Hal::UartInit( void )
00149 {
00150     RadioUart->format( 9, SerialBase::Even, 1 ); // 8 data bits + 1 even parity bit + 1 stop bit
00151     RadioUart->baud( 115200 );
00152 
00153     // By default the SX1280 UART is setup to handle bytes MSB first.
00154     // In order to setup the radio to use the UART standard way we first send
00155     // the equivalent of a WriteRegister with reversed bit order in order to
00156     // change the endianness.
00157     uint8_t regVal = 0;
00158     RadioUart->putc( 0x98 );            // Reversed opcode for read register (0x19)
00159     RadioUart->putc( 0x10 );            // Reversed MSB register address (0x08)
00160     RadioUart->putc( 0x18 );            // Reversed LSB register address (0x18)
00161     RadioUart->putc( 0x80 );            // Reversed value for reading only 1 byte (0x01)
00162     regVal = RadioUart->getc( )& 0xF3;  // Read reversed value and mask it
00163 
00164     RadioUart->putc( 0x18 );            // Reversed opcode for read register (0x18)
00165     RadioUart->putc( 0x10 );            // Reversed MSB register address (0x08)
00166     RadioUart->putc( 0x18 );            // Reversed LSB register address (0x18)
00167     RadioUart->putc( 0x80 );            // Reversed value for writing only 1 byte (0x01)
00168     RadioUart->putc( regVal );          // The new value of the register
00169 
00170     // After this point, the UART is running standard mode: 8 data bit, 1 even
00171     // parity bit, 1 stop bit, 115200 baud, LSB first
00172     wait_us( 10 );
00173 }
00174 
00175 void SX1280Hal::IoIrqInit( DioIrqHandler irqHandler )
00176 {
00177     assert_param( RadioSpi != NULL || RadioUart != NULL );
00178     if( RadioSpi != NULL )
00179     {
00180         SpiInit( );
00181     }
00182     if( RadioUart != NULL )
00183     {
00184         UartInit( );
00185     }
00186 
00187     BUSY.mode( PullNone );
00188 
00189     DioAssignCallback( DIO1, PullNone, irqHandler );
00190     DioAssignCallback( DIO2, PullNone, irqHandler );
00191     DioAssignCallback( DIO3, PullNone, irqHandler );
00192 }
00193 
00194 void SX1280Hal::Reset( void )
00195 {
00196     __disable_irq( );
00197     wait_ms( 20 );
00198     RadioReset.output( );
00199     RadioReset = 0;
00200     wait_ms( 50 );
00201     RadioReset = 1;
00202     RadioReset.input( ); // Using the internal pull-up
00203     wait_ms( 20 );
00204     __enable_irq( );
00205 }
00206 
00207 void SX1280Hal::Wakeup( void )
00208 {
00209     __disable_irq( );
00210 
00211     //Don't wait for BUSY here
00212 
00213     if( RadioSpi != NULL )
00214     {
00215         RadioNss = 0;
00216         RadioSpi->write( RADIO_GET_STATUS );
00217         RadioSpi->write( 0 );
00218         RadioNss = 1;
00219     }
00220     if( RadioUart != NULL )
00221     {
00222         RadioUart->putc( RADIO_GET_STATUS );
00223         WaitUartReadable( );
00224         RadioUart->getc( );
00225     }
00226 
00227     // Wait for chip to be ready.
00228     WaitOnBusy( );
00229 
00230     __enable_irq( );
00231 }
00232 
00233 void SX1280Hal::WriteCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
00234 {
00235     WaitOnBusy( );
00236 
00237     if( RadioSpi != NULL )
00238     {
00239         RadioNss = 0;
00240         RadioSpi->write( ( uint8_t )command );
00241         for( uint16_t i = 0; i < size; i++ )
00242         {
00243             RadioSpi->write( buffer[i] );
00244         }
00245         RadioNss = 1;
00246     }
00247     if( RadioUart != NULL )
00248     {
00249         RadioUart->putc( command );
00250         if( size > 0 )
00251         {
00252             RadioUart->putc( size );
00253             for( uint16_t i = 0; i < size; i++ )
00254             {
00255                 RadioUart->putc( buffer[i] );
00256             }
00257         }
00258     }
00259 
00260     if( command != RADIO_SET_SLEEP )
00261     {
00262         WaitOnBusy( );
00263     }
00264 }
00265 
00266 void SX1280Hal::ReadCommand( RadioCommands_t command, uint8_t *buffer, uint16_t size )
00267 {
00268     WaitOnBusy( );
00269 
00270     if( RadioSpi != NULL )
00271     {
00272         RadioNss = 0;
00273         RadioSpi->write( ( uint8_t )command );
00274         RadioSpi->write( 0 );
00275         for( uint16_t i = 0; i < size; i++ )
00276         {
00277              buffer[i] = RadioSpi->write( 0 );
00278         }
00279         RadioNss = 1;
00280     }
00281     if( RadioUart != NULL )
00282     {
00283         RadioUart->putc( command );
00284 
00285         // Behavior on the UART is different depending of the opcode command
00286         if( ( command == RADIO_GET_PACKETTYPE ) ||
00287             ( command == RADIO_GET_RXBUFFERSTATUS ) ||
00288             ( command == RADIO_GET_RSSIINST ) ||
00289             ( command == RADIO_GET_PACKETSTATUS ) ||
00290             ( command == RADIO_GET_IRQSTATUS ) )
00291         {
00292             /*
00293              * TODO : Check size size in UART (uint8_t in putc)
00294              */
00295             RadioUart->putc( size );
00296         }
00297 
00298         WaitUartReadable( );
00299         for( uint16_t i = 0; i < size; i++ )
00300         {
00301              buffer[i] = RadioUart->getc( );
00302         }
00303     }
00304 
00305     WaitOnBusy( );
00306 }
00307 
00308 void SX1280Hal::WriteRegister( uint16_t address, uint8_t *buffer, uint16_t size )
00309 {
00310     WaitOnBusy( );
00311 
00312     if( RadioSpi != NULL )
00313     {
00314         RadioNss = 0;
00315         RadioSpi->write( RADIO_WRITE_REGISTER );
00316         RadioSpi->write( ( address & 0xFF00 ) >> 8 );
00317         RadioSpi->write( address & 0x00FF );
00318         for( uint16_t i = 0; i < size; i++ )
00319         {
00320             RadioSpi->write( buffer[i] );
00321         }
00322         RadioNss = 1;
00323     }
00324     if( RadioUart != NULL )
00325     {
00326         uint16_t addr = address;
00327         uint16_t i = 0;
00328         for( addr = address; ( addr + 255 ) < ( address + size ); )
00329         {
00330             RadioUart->putc( RADIO_WRITE_REGISTER );
00331             RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00332             RadioUart->putc( addr & 0x00FF );
00333             RadioUart->putc( 255 );
00334             for( uint16_t lastAddr = addr + 255 ; addr < lastAddr; i++, addr++ )
00335             {
00336                 RadioUart->putc( buffer[i] );
00337             }
00338         }
00339         RadioUart->putc( RADIO_WRITE_REGISTER );
00340         RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00341         RadioUart->putc( addr & 0x00FF );
00342         RadioUart->putc( address + size - addr );
00343 
00344         for( ; addr < ( address + size ); addr++, i++ )
00345         {
00346             RadioUart->putc( buffer[i] );
00347         }
00348     }
00349 
00350     WaitOnBusy( );
00351 }
00352 
00353 void SX1280Hal::WriteRegister( uint16_t address, uint8_t value )
00354 {
00355     WriteRegister( address, &value, 1 );
00356 }
00357 
00358 void SX1280Hal::ReadRegister( uint16_t address, uint8_t *buffer, uint16_t size )
00359 {
00360     WaitOnBusy( );
00361 
00362     if( RadioSpi != NULL )
00363     {
00364         RadioNss = 0;
00365         RadioSpi->write( RADIO_READ_REGISTER );
00366         RadioSpi->write( ( address & 0xFF00 ) >> 8 );
00367         RadioSpi->write( address & 0x00FF );
00368         RadioSpi->write( 0 );
00369         for( uint16_t i = 0; i < size; i++ )
00370         {
00371             buffer[i] = RadioSpi->write( 0 );
00372         }
00373         RadioNss = 1;
00374     }
00375     if( RadioUart != NULL )
00376     {
00377         uint16_t addr = address;
00378         uint16_t i = 0;
00379         for( addr = address; ( addr + 255 ) < ( address + size ); )
00380         {
00381             RadioUart->putc( RADIO_READ_REGISTER );
00382             RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00383             RadioUart->putc( addr & 0x00FF );
00384             RadioUart->putc( 255 );
00385             WaitUartReadable( );
00386             for( uint16_t lastAddr = addr + 255 ; addr < lastAddr; i++, addr++ )
00387             {
00388                 buffer[i] = RadioUart->getc( );
00389             }
00390         }
00391         RadioUart->putc( RADIO_READ_REGISTER );
00392         RadioUart->putc( ( addr & 0xFF00 ) >> 8 );
00393         RadioUart->putc( addr & 0x00FF );
00394         RadioUart->putc( address + size - addr );
00395         WaitUartReadable( );
00396         for( ; addr < ( address + size ); addr++, i++ )
00397         {
00398             buffer[i] = RadioUart->getc( );
00399         }
00400     }
00401 
00402     WaitOnBusy( );
00403 }
00404 
00405 uint8_t SX1280Hal::ReadRegister( uint16_t address )
00406 {
00407     uint8_t data;
00408 
00409     ReadRegister( address, &data, 1 );
00410     return data;
00411 }
00412 
00413 void SX1280Hal::WriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
00414 {
00415     WaitOnBusy( );
00416 
00417     if( RadioSpi != NULL )
00418     {
00419         RadioNss = 0;
00420         RadioSpi->write( RADIO_WRITE_BUFFER );
00421         RadioSpi->write( offset );
00422         for( uint16_t i = 0; i < size; i++ )
00423         {
00424             RadioSpi->write( buffer[i] );
00425         }
00426         RadioNss = 1;
00427     }
00428     if( RadioUart != NULL )
00429     {
00430         RadioUart->putc( RADIO_WRITE_BUFFER );
00431         RadioUart->putc( offset );
00432         RadioUart->putc( size );
00433         for( uint16_t i = 0; i < size; i++ )
00434         {
00435             RadioUart->putc( buffer[i] );
00436         }
00437     }
00438 
00439     WaitOnBusy( );
00440 }
00441 
00442 void SX1280Hal::ReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size )
00443 {
00444     WaitOnBusy( );
00445 
00446     if( RadioSpi != NULL )
00447     {
00448         RadioNss = 0;
00449         RadioSpi->write( RADIO_READ_BUFFER );
00450         RadioSpi->write( offset );
00451         RadioSpi->write( 0 );
00452         for( uint16_t i = 0; i < size; i++ )
00453         {
00454             buffer[i] = RadioSpi->write( 0 );
00455         }
00456         RadioNss = 1;
00457     }
00458     if( RadioUart != NULL )
00459     {
00460         RadioUart->putc( RADIO_READ_BUFFER );
00461         RadioUart->putc( offset );
00462         RadioUart->putc( size );
00463         WaitUartReadable( );
00464         for( uint16_t i = 0; i < size; i++ )
00465         {
00466             buffer[i] = RadioUart->getc( );
00467         }
00468     }
00469 
00470     WaitOnBusy( );
00471 }
00472 
00473 uint8_t SX1280Hal::GetDioStatus( void )
00474 {
00475     return ( *DIO3 << 3 ) | ( *DIO2 << 2 ) | ( *DIO1 << 1 ) | ( BUSY << 0 );
00476 }