Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SX1280Lib by
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 }
Generated on Thu Jul 21 2022 00:08:48 by
1.7.2
