LoRaPHY project, based upon SX1276Lib, hardware with NUCLEO-F103EB/L053R8 and other boards as well as multiple Radio modules of SX1272/1276/1278. The code contains MACRO definitions and can be configured as TX/RX only, PINGPONG and consider to be a code base of RTTY.
main.cpp
00001 #include "mbed.h" 00002 #include "main.h" 00003 #include "sx1276-hal.h" 00004 #include "debug.h" 00005 00006 /* Set this flag to '1' to display debug messages on the console */ 00007 #define DEBUG_MESSAGE 0 00008 00009 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */ 00010 #define USE_MODEM_LORA 1 00011 #define USE_MODEM_FSK !USE_MODEM_LORA 00012 00013 //#define RF868 1 00014 00015 #ifdef RF868 00016 00017 #define RF_FREQUENCY 868000000 // Hz 00018 #define TX_OUTPUT_POWER 14 // 14 dBm 00019 00020 #else 00021 00022 #define RF_FREQUENCY 433000000 // Hz 00023 #define TX_OUTPUT_POWER 14 // 26 dBm 00024 00025 #endif 00026 00027 #if USE_MODEM_LORA == 1 00028 #define LORA_BANDWIDTH 0 00029 #define LORA_SPREADING_FACTOR 10 00030 #define LORA_CODINGRATE 2 00031 00032 //#define LORA_BANDWIDTH 2 // [0: 125 kHz, 00033 // 1: 250 kHz, 00034 // 2: 500 kHz, 00035 // 3: Reserved] 00036 //#define LORA_SPREADING_FACTOR 7 // [SF7..SF12] 00037 //#define LORA_CODINGRATE 1 // [1: 4/5, 00038 // 2: 4/6, 00039 // 3: 4/7, 00040 // 4: 4/8] 00041 #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx 00042 #define LORA_SYMBOL_TIMEOUT 5 // Symbols 00043 #define LORA_FIX_LENGTH_PAYLOAD_ON false 00044 #define LORA_FHSS_ENABLED false 00045 #define LORA_NB_SYMB_HOP 4 00046 #define LORA_IQ_INVERSION_ON false 00047 #define LORA_CRC_ENABLED true 00048 00049 #elif USE_MODEM_FSK == 1 00050 00051 #define FSK_FDEV 25000 // Hz 00052 #define FSK_DATARATE 19200 // bps 00053 #define FSK_BANDWIDTH 50000 // Hz 00054 #define FSK_AFC_BANDWIDTH 83333 // Hz 00055 #define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx 00056 #define FSK_FIX_LENGTH_PAYLOAD_ON false 00057 #define FSK_CRC_ENABLED true 00058 00059 #else 00060 #error "Please define a modem in the compiler options." 00061 #endif 00062 00063 #define RX_TIMEOUT_VALUE 3500000 // in us 00064 #define BUFFER_SIZE 32 // Define the payload size here 00065 00066 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) ) 00067 DigitalOut led(LED2); 00068 #else 00069 //DigitalOut led(LED1); 00070 //DigitalOut led2(LED2); 00071 //DigitalOut led3(LED3); 00072 //DigitalOut led4(LED4); 00073 DigitalOut debugled(D6); 00074 DigitalOut debugled2(D7); 00075 00076 #endif 00077 00078 DigitalIn role(USER_BUTTON); // PC_13 in Mini 103RC mini board 00079 Timer tx_tmr; 00080 00081 #define UART_ENABLE 00082 00083 #ifdef UART_ENABLE 00084 //Serial pc(USBTX, USBRX); 00085 Serial pc(SERIAL_TX, SERIAL_RX); 00086 #endif 00087 00088 Ticker nwk_ticker; 00089 00090 bool channelOccupied = false; 00091 00092 #define NWK_SLEEP 0 00093 #define NWK_TX 1 00094 #define NWK_TX_NOK 2 00095 #define NWK_RX_OK 3 00096 #define NWK_RX_NOK 4 00097 00098 //#define PINGPONG 00099 00100 void nwk_toggle() 00101 { 00102 debugled = !debugled; 00103 debugled2 = !debugled2; 00104 } 00105 00106 void nwk_setmode(uint8_t mode) 00107 { 00108 switch(mode){ 00109 case NWK_TX: 00110 case NWK_RX_OK: 00111 nwk_ticker.attach(&nwk_toggle, 1); 00112 break; 00113 case NWK_TX_NOK: 00114 case NWK_RX_NOK: 00115 nwk_ticker.attach(&nwk_toggle, 0.1); 00116 break; 00117 case NWK_SLEEP: 00118 default: 00119 debugled = 0; 00120 debugled2 = 0; 00121 nwk_ticker.detach(); 00122 break; 00123 } 00124 } 00125 00126 /* 00127 * Global variables declarations 00128 */ 00129 typedef enum 00130 { 00131 ST_LOWPOWER = 0, 00132 ST_IDLE, 00133 00134 ST_RX, 00135 ST_RX_TIMEOUT, 00136 ST_RX_ERROR, 00137 00138 ST_TX, 00139 ST_TX_TIMEOUT, 00140 00141 ST_CAD, 00142 ST_CAD_DONE 00143 }AppStates_t; 00144 00145 volatile AppStates_t State = ST_LOWPOWER; 00146 00147 /*! 00148 * Radio events function pointer 00149 */ 00150 static RadioEvents_t RadioEvents; 00151 00152 /* 00153 * Global variables declarations 00154 */ 00155 SX1276MB1xAS Radio( NULL ); 00156 00157 const uint8_t PingMsg[] = "PING"; 00158 const uint8_t PongMsg[] = "PONG"; 00159 const uint8_t TestMsg[] = "LoRa Test"; 00160 00161 uint16_t BufferSize = BUFFER_SIZE; 00162 uint8_t Buffer[BUFFER_SIZE]; 00163 00164 //int16_t RssiValue = 0.0; 00165 //int8_t SnrValue = 0.0; 00166 00167 int16_t RssiValue = 0; 00168 int8_t SnrValue = 0; 00169 00170 #define REG_SIZE 0x70 // see below 00171 #define REG_IDX_SIZE 39 00172 00173 static int my_strncmp(const char *, const char *, int); 00174 static void my_strcpy(char * , const char *); 00175 00176 int my_strncmp(const char * s1, const char * s2, int size) 00177 { 00178 int n = size; 00179 for ( ; n > 0; s1++, s2++, --n) 00180 if (*s1 != *s2) 00181 return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1); 00182 else if (*s1 == '\0') 00183 return 0; 00184 return 0; 00185 } 00186 00187 void my_strcpy(char * s1, const char * s2) 00188 { 00189 char *s = s1; 00190 while ((*s++ = *s2++) != 0) 00191 ; 00192 } 00193 00194 void Sender ( void ) 00195 { 00196 int i; 00197 my_strcpy( ( char* )Buffer, ( char* )PingMsg ); 00198 for( i = 4; i < BufferSize; i++ ){ 00199 Buffer[i] = i - 4; 00200 } 00201 Radio.Send( Buffer, BufferSize ); 00202 } 00203 00204 int main() 00205 { 00206 uint8_t i; 00207 uint8_t regval; 00208 bool isMaster = true; 00209 int begin, end; 00210 00211 uint32_t rand; 00212 debugled = 1; 00213 debugled2 = 1; 00214 00215 isMaster = role.read(); 00216 00217 //debug( "\n\n\r SX1276 Ping Pong Demo Application \n\n\r" ); 00218 00219 // Initialize Radio driver 00220 RadioEvents.TxDone = OnTxDone; 00221 RadioEvents.RxDone = OnRxDone; 00222 RadioEvents.RxError = OnRxError; 00223 RadioEvents.TxTimeout = OnTxTimeout; 00224 RadioEvents.RxTimeout = OnRxTimeout; 00225 Radio.Init( &RadioEvents ); 00226 00227 #ifdef UART_ENABLE 00228 regval = Radio.Read(REG_VERSION); 00229 pc.printf("%s", TestMsg); 00230 pc.printf("IC Version: %02X\r\n", regval); 00231 regval = Radio.Read(REG_OPMODE); 00232 pc.printf("OPMODE: %02X\r\n", regval); 00233 #endif 00234 00235 debugled = 0; 00236 debugled2 = 0; 00237 00238 // verify the connection with the board 00239 while( Radio.Read( REG_VERSION ) == 0x00 ) 00240 { 00241 //debug( "Radio could not be detected!\n\r", NULL ); 00242 wait( 1 ); 00243 } 00244 00245 //debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1LAS ) ) , "\n\r > Board Type: SX1276MB1LAS < \n\r" ); 00246 //debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1276MB1MAS ) ) , "\n\r > Board Type: SX1276MB1MAS < \n\r" ); 00247 00248 Radio.SetChannel( RF_FREQUENCY ); 00249 00250 #if USE_MODEM_LORA == 1 00251 00252 //debug_if( LORA_FHSS_ENABLED, "\n\n\r > LORA FHSS Mode < \n\n\r"); 00253 //debug_if( !LORA_FHSS_ENABLED, "\n\n\r > LORA Mode < \n\n\r"); 00254 00255 Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, 00256 LORA_SPREADING_FACTOR, LORA_CODINGRATE, 00257 LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, 00258 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00259 LORA_IQ_INVERSION_ON, 2000000 ); 00260 00261 Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, 00262 LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, 00263 LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, 00264 LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 00265 LORA_IQ_INVERSION_ON, true ); 00266 00267 #elif USE_MODEM_FSK == 1 00268 00269 //debug("\n\n\r > FSK Mode < \n\n\r"); 00270 Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, 00271 FSK_DATARATE, 0, 00272 FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, 00273 FSK_CRC_ENABLED, 0, 0, 0, 2000000 ); 00274 00275 Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 00276 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, 00277 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, 00278 0, 0, false, true ); 00279 00280 #else 00281 00282 #error "Please define a modem in the compiler options." 00283 00284 #endif 00285 00286 //debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" ); 00287 00288 rand = Radio.Random(); 00289 rand = rand%1000; 00290 wait_ms((uint16_t)rand); 00291 00292 #ifdef PINGPONG 00293 Radio.Rx( RX_TIMEOUT_VALUE ); 00294 00295 00296 while( 1 ) 00297 { 00298 switch( State ) 00299 { 00300 case ST_RX: 00301 if( isMaster == true ) 00302 { 00303 if( BufferSize > 0 ) 00304 { 00305 #ifdef UART_ENABLE 00306 pc.printf("Received message:\r\n"); 00307 pc.printf("%s",Buffer); 00308 #endif 00309 //if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 ) 00310 if( my_strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 ) 00311 { 00312 nwk_setmode(NWK_NORMAL); 00313 //debug( "...Pong\r\n" ); 00314 // Send the next PING frame 00315 my_strcpy( ( char* )Buffer, ( char* )PingMsg ); 00316 //_strcpy( ( char* )Buffer, ( char* )PingMsg ); 00317 // We fill the buffer with numbers for the payload 00318 for( i = 4; i < BufferSize; i++ ) 00319 { 00320 Buffer[i] = i - 4; 00321 } 00322 wait_ms( 10 ); 00323 Radio.Send( Buffer, BufferSize ); 00324 } 00325 else if( my_strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) 00326 { // A master already exists then become a slave 00327 debug( "...Ping\r\n" ); 00328 //nwk_setmode(NWK_NORMAL); 00329 //led = !led; 00330 isMaster = false; 00331 // Send the next PONG frame 00332 my_strcpy( ( char* )Buffer, ( char* )PongMsg ); 00333 // We fill the buffer with numbers for the payload 00334 for( i = 4; i < BufferSize; i++ ) 00335 { 00336 Buffer[i] = i - 4; 00337 } 00338 wait_ms( 10 ); 00339 Radio.Send( Buffer, BufferSize ); 00340 } 00341 else // valid reception but neither a PING or a PONG message 00342 { // Set device as master ans start again 00343 isMaster = true; 00344 Radio.Rx( RX_TIMEOUT_VALUE ); 00345 } 00346 } 00347 } 00348 else 00349 { 00350 if( BufferSize > 0 ) 00351 { 00352 #ifdef UART_ENABLE 00353 pc.printf("Received message:\r\n"); 00354 pc.printf("%s",Buffer); 00355 #endif 00356 00357 if( my_strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) 00358 { 00359 nwk_setmode(NWK_NORMAL); 00360 //led = !led; 00361 //debug( "...Ping\r\n" ); 00362 // Send the reply to the PING string 00363 my_strcpy( ( char* )Buffer, ( char* )PongMsg ); 00364 // We fill the buffer with numbers for the payload 00365 for( i = 4; i < BufferSize; i++ ) 00366 { 00367 Buffer[i] = i - 4; 00368 } 00369 wait_ms( 10 ); 00370 Radio.Send( Buffer, BufferSize ); 00371 } 00372 else // valid reception but not a PING as expected 00373 { // Set device as master and start again 00374 isMaster = true; 00375 Radio.Rx( RX_TIMEOUT_VALUE ); 00376 } 00377 } 00378 } 00379 State = ST_LOWPOWER; 00380 break; 00381 case ST_TX: 00382 //nwk_setmode(NWK_NORMAL); 00383 //led = !led; 00384 if( isMaster == true ) 00385 { 00386 //debug( "Ping...\r\n" ); 00387 } 00388 else 00389 { 00390 //debug( "Pong...\r\n" ); 00391 } 00392 Radio.Rx( RX_TIMEOUT_VALUE ); 00393 State = ST_LOWPOWER; 00394 break; 00395 case ST_RX_TIMEOUT: 00396 //debugled = !debugled; 00397 //debugled2 = !debugled2; 00398 nwk_setmode(NWK_ERR); 00399 if( isMaster == true ) 00400 { 00401 // Send the next PING frame 00402 my_strcpy( ( char* )Buffer, ( char* )PingMsg ); 00403 for( i = 4; i < BufferSize; i++ ) 00404 { 00405 Buffer[i] = i - 4; 00406 } 00407 wait_ms( 10 ); 00408 Radio.Send( Buffer, BufferSize ); 00409 } 00410 else 00411 { 00412 Radio.Rx( RX_TIMEOUT_VALUE ); 00413 } 00414 State = ST_LOWPOWER; 00415 break; 00416 case ST_RX_ERROR: 00417 // We have received a Packet with a CRC error, send reply as if packet was correct 00418 nwk_setmode(NWK_ERR); 00419 if( isMaster == true ) 00420 { 00421 // Send the next PING frame 00422 my_strcpy( ( char* )Buffer, ( char* )PingMsg ); 00423 for( i = 4; i < BufferSize; i++ ) 00424 { 00425 Buffer[i] = i - 4; 00426 } 00427 wait_ms( 10 ); 00428 Radio.Send( Buffer, BufferSize ); 00429 } 00430 else 00431 { 00432 // Send the next PONG frame 00433 my_strcpy( ( char* )Buffer, ( char* )PongMsg ); 00434 for( i = 4; i < BufferSize; i++ ) 00435 { 00436 Buffer[i] = i - 4; 00437 } 00438 wait_ms( 10 ); 00439 Radio.Send( Buffer, BufferSize ); 00440 } 00441 State = ST_LOWPOWER; 00442 break; 00443 case ST_TX_TIMEOUT: 00444 nwk_setmode(NWK_ERR); 00445 Radio.Rx( RX_TIMEOUT_VALUE ); 00446 State = ST_LOWPOWER; 00447 break; 00448 case ST_CAD: 00449 break; 00450 case ST_CAD_DONE: 00451 if(channelOccupied){ 00452 State = ST_LOWPOWER; 00453 }else{ 00454 // start to transmit here. 00455 } 00456 break; 00457 case ST_LOWPOWER: 00458 break; 00459 default: 00460 nwk_setmode(0xFF); 00461 State = ST_LOWPOWER; 00462 break; 00463 } 00464 } 00465 00466 #else 00467 00468 if(isMaster == true){ 00469 tx_tmr.start(); 00470 begin = tx_tmr.read_ms(); 00471 }else{ 00472 Radio.Rx( RX_TIMEOUT_VALUE ); 00473 } 00474 00475 while(1){ 00476 switch(State){ 00477 case ST_RX: 00478 //nwk_setmode(NWK_RX_OK); 00479 Radio.Rx( RX_TIMEOUT_VALUE ); 00480 State = ST_LOWPOWER; 00481 #ifdef UART_ENABLE 00482 //pc.printf("\r\nRX OK\tRSSI:%f SNR:%f \r\n",float(RssiValue),float(SnrValue)); 00483 pc.printf("\r\nRX OK\tRSSI:%d SNR:%d \r\n",RssiValue,SnrValue); 00484 pc.printf("\r\nRSSI: %02X SNR: %01X\r\n", RssiValue, SnrValue); 00485 #endif 00486 break; 00487 case ST_TX: 00488 nwk_setmode(NWK_TX); 00489 State = ST_LOWPOWER; 00490 #ifdef UART_ENABLE 00491 pc.printf("\r\nTX Done.\r\n"); 00492 #endif 00493 break; 00494 case ST_RX_TIMEOUT: 00495 case ST_RX_ERROR: 00496 //nwk_setmode(NWK_RX_NOK); 00497 Radio.Rx( RX_TIMEOUT_VALUE ); 00498 State = ST_LOWPOWER; 00499 #ifdef UART_ENABLE 00500 pc.printf("\r\nRX TIMEOUT or ERROR.\r\n"); 00501 #endif 00502 break; 00503 case ST_TX_TIMEOUT: 00504 State = ST_LOWPOWER; 00505 break; 00506 case ST_LOWPOWER: 00507 if (isMaster){ 00508 end = tx_tmr.read_ms(); 00509 if ((end-begin) >= 2000){ 00510 Sender(); 00511 tx_tmr.stop(); 00512 tx_tmr.start(); 00513 begin = tx_tmr.read_ms(); 00514 } 00515 } 00516 break; 00517 default: 00518 State = ST_LOWPOWER; 00519 break; 00520 } 00521 } 00522 #endif 00523 00524 } 00525 00526 00527 void OnTxDone( void ) 00528 { 00529 Radio.Sleep( ); 00530 State = ST_TX; 00531 //debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" ); 00532 } 00533 00534 void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) 00535 { 00536 Radio.Sleep( ); 00537 BufferSize = size; 00538 memcpy( Buffer, payload, BufferSize ); 00539 RssiValue = rssi; 00540 SnrValue = snr; 00541 State = ST_RX; 00542 nwk_setmode(NWK_RX_OK); 00543 //debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" ); 00544 } 00545 00546 void OnTxTimeout( void ) 00547 { 00548 Radio.Sleep( ); 00549 State = ST_TX_TIMEOUT; 00550 //debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" ); 00551 } 00552 00553 void OnRxTimeout( void ) 00554 { 00555 Radio.Sleep( ); 00556 Buffer[ BufferSize ] = 0; 00557 State = ST_RX_TIMEOUT; 00558 nwk_setmode(NWK_RX_NOK); 00559 //debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" ); 00560 } 00561 00562 void OnRxError( void ) 00563 { 00564 Radio.Sleep( ); 00565 State = ST_RX_ERROR; 00566 //debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" ); 00567 } 00568 00569 // Added by allankliu 00570 void OnCadDone( bool channelActivityDetected ) 00571 { 00572 Radio.Sleep(); 00573 channelOccupied = channelActivityDetected; 00574 State = ST_CAD_DONE; 00575 }
Generated on Thu Jul 21 2022 02:23:05 by 1.7.2