First attempt at LoRa USB Rx

Dependencies:   BufferedSerial SX1276GenericLib mbed

Fork of DISCO-L072CZ-LRWAN1_LoRa_PingPong by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Copyright (c) 2017 Helmut Tschemernjak
00003  * 30826 Garbsen (Hannover) Germany
00004  * Licensed under the Apache License, Version 2.0);
00005  */
00006  #include "main.h"
00007 
00008 DigitalOut myled(LED1);
00009 BufferedSerial *ser;
00010 
00011 
00012 #ifdef FEATURE_LORA
00013 
00014 /* Set this flag to '1' to display debug messages on the console */
00015 #define DEBUG_MESSAGE   0
00016 
00017 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
00018 #define USE_MODEM_LORA  1
00019 #define USE_MODEM_FSK   !USE_MODEM_LORA
00020 #define RF_FREQUENCY            915000000//RF_FREQUENCY_868_1  // Hz
00021 #define TX_OUTPUT_POWER         20                  // 14 dBm
00022 
00023 #if USE_MODEM_LORA == 1
00024 
00025 #define LORA_BANDWIDTH          125000  // LoRa default, details in SX1276::BandwidthMap
00026 #define LORA_SPREADING_FACTOR   LORA_SF12
00027 #define LORA_CODINGRATE         LORA_ERROR_CODING_RATE_4_5
00028 
00029 #define LORA_PREAMBLE_LENGTH    8       // Same for Tx and Rx
00030 #define LORA_SYMBOL_TIMEOUT     5       // Symbols
00031 #define LORA_FIX_LENGTH_PAYLOAD_ON  false
00032 #define LORA_FHSS_ENABLED       false  
00033 #define LORA_NB_SYMB_HOP        4     
00034 #define LORA_IQ_INVERSION_ON    false
00035 #define LORA_CRC_ENABLED        true
00036     
00037 #elif USE_MODEM_FSK == 1
00038 
00039 #define FSK_FDEV                25000     // Hz
00040 #define FSK_DATARATE            19200     // bps
00041 #define FSK_BANDWIDTH           50000     // Hz
00042 #define FSK_AFC_BANDWIDTH       83333     // Hz
00043 #define FSK_PREAMBLE_LENGTH     5         // Same for Tx and Rx
00044 #define FSK_FIX_LENGTH_PAYLOAD_ON   false
00045 #define FSK_CRC_ENABLED         true
00046     
00047 #else
00048     #error "Please define a modem in the compiler options."
00049 #endif 
00050 
00051 
00052 #define RX_TIMEOUT_VALUE    8000//3500  // in ms
00053 
00054 //#define BUFFER_SIZE       32        // Define the payload size here
00055 #define BUFFER_SIZE         4//64        // Define the payload size here
00056 
00057 /*
00058  *  Global variables declarations
00059  */
00060 typedef enum
00061 {
00062     LOWPOWER = 0,
00063     IDLE,
00064     
00065     RX,
00066     RX_TIMEOUT,
00067     RX_ERROR,
00068     
00069     TX,
00070     TX_TIMEOUT,
00071     
00072     CAD,
00073     CAD_DONE
00074 } AppStates_t;
00075 
00076 volatile AppStates_t State = LOWPOWER;
00077 
00078 /*!
00079  * Radio events function pointer
00080  */
00081 static RadioEvents_t RadioEvents;
00082 
00083 /*
00084  *  Global variables declarations
00085  */
00086 SX1276Generic *Radio;
00087 
00088 
00089 //const uint8_t PingMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'I', 'N', 'G'};// "PING";
00090 const uint8_t PingMsg[] = { 'P', 'I', 'N', 'G'};// "PING";
00091 //const uint8_t PongMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'O', 'N', 'G'};// "PONG";
00092 const uint8_t PongMsg[] = { 'P', 'O', 'N', 'G'};// "PONG";
00093 
00094 uint16_t BufferSize = BUFFER_SIZE;
00095 uint8_t *Buffer;
00096 
00097 DigitalOut *led3;
00098 DigitalOut *led = new DigitalOut(LED1);
00099 
00100 uint8_t i;
00101 bool isMaster = false;
00102 
00103 uint8_t SX1276DataTx[4];
00104 uint8_t SX1276DataRx[4]; 
00105 bool mode = false; // false is slave, true is master
00106 
00107 uint8_t serialRxBuffer[4];
00108 int main() {
00109     SystemClock_Config();
00110     ser = new BufferedSerial(USBTX, USBRX);
00111     ser->baud(115200);
00112     ser->format(8);
00113     ser->printf("Hello World\n\r");
00114     myled = 1;
00115     
00116     #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
00117     DigitalOut *led = new DigitalOut(LED2);
00118 #elif defined(TARGET_NUCLEO_L073RZ)
00119     DigitalOut *led = new DigitalOut(LED4);   // RX red
00120     led3 = new DigitalOut(LED3);  // TX blue
00121 #else
00122     DigitalOut *led = new DigitalOut(LED1);
00123     led3 = led;
00124 #endif
00125     
00126     Buffer = new  uint8_t[BUFFER_SIZE];
00127     *led3 = 1;
00128 
00129 #ifdef B_L072Z_LRWAN1_LORA
00130     Radio = new SX1276Generic(NULL, MURATA_SX1276,
00131             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00132             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
00133             LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO);
00134 #else // RFM95
00135     Radio = new SX1276Generic(NULL, RFM95_SX1276,
00136             LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00137             LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5);
00138 
00139 #endif
00140     
00141     
00142     isMaster = true;
00143     
00144     dprintf("SX1276 Ping Pong Demo Application" );
00145     dprintf("Freqency: %.1f", (double)RF_FREQUENCY/1000000.0);
00146     dprintf("TXPower: %d dBm",  TX_OUTPUT_POWER);
00147 #if USE_MODEM_LORA == 1
00148     dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH);
00149     dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR);
00150 #elif USE_MODEM_FSK == 1
00151     dprintf("Bandwidth: %d kHz",  FSK_BANDWIDTH);
00152     dprintf("Baudrate: %d", FSK_DATARATE);
00153 #endif
00154     // Initialize Radio driver
00155     RadioEvents.TxDone = OnTxDone;
00156     RadioEvents.RxDone = OnRxDone;
00157     RadioEvents.RxError = OnRxError;
00158     RadioEvents.TxTimeout = OnTxTimeout;
00159     RadioEvents.RxTimeout = OnRxTimeout;    
00160     if (Radio->Init( &RadioEvents ) == false) {
00161         while(1) {
00162             dprintf("Radio could not be detected!");
00163             wait( 1 );
00164         }
00165     }
00166 
00167     
00168     switch(Radio->DetectBoardType()) {
00169         case SX1276MB1LAS:
00170             if (DEBUG_MESSAGE)
00171                 dprintf(" > Board Type: SX1276MB1LAS <");
00172             break;
00173         case SX1276MB1MAS:
00174             if (DEBUG_MESSAGE)
00175                 dprintf(" > Board Type: SX1276MB1LAS <");
00176         case MURATA_SX1276:
00177             if (DEBUG_MESSAGE)
00178                 dprintf(" > Board Type: MURATA_SX1276_STM32L0 <");
00179             break;
00180         case RFM95_SX1276:
00181             if (DEBUG_MESSAGE)
00182                 dprintf(" > HopeRF RFM95xx <");
00183             break;
00184         default:
00185             dprintf(" > Board Type: unknown <");
00186     }
00187 
00188     Radio->SetChannel(RF_FREQUENCY ); 
00189 
00190 #if USE_MODEM_LORA == 1
00191     
00192     if (LORA_FHSS_ENABLED)
00193         dprintf("             > LORA FHSS Mode <");
00194     if (!LORA_FHSS_ENABLED)
00195         dprintf("             > LORA Mode <");
00196 
00197     Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
00198                          LORA_SPREADING_FACTOR, LORA_CODINGRATE,
00199                          LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
00200                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00201                          LORA_IQ_INVERSION_ON, 2000 );
00202     
00203     Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
00204                          LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
00205                          LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
00206                          LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, 
00207                          LORA_IQ_INVERSION_ON, true );
00208                          
00209 #elif USE_MODEM_FSK == 1
00210 
00211     dprintf("              > FSK Mode <");
00212     Radio->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
00213                          FSK_DATARATE, 0,
00214                          FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
00215                          FSK_CRC_ENABLED, 0, 0, 0, 2000 );
00216     
00217     Radio->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
00218                          0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
00219                          0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
00220                          0, 0, false, true );
00221                          
00222 #else
00223 
00224 #error "Please define a modem in the compiler options."
00225 
00226 #endif
00227      
00228     if (DEBUG_MESSAGE)
00229         dprintf("Starting Rx loop"); 
00230 
00231         
00232     Radio->Rx( RX_TIMEOUT_VALUE );
00233     /*
00234     SX1276DataTx[0] = 0x0A;
00235     SX1276DataTx[1] = 0x0B;
00236     SX1276DataTx[2] = 0x0C;
00237     SX1276DataTx[3] = 0x0D;
00238     */
00239     
00240     while(1)
00241     SX1276Comm(0, 1); 
00242     //SX1276PingPong();
00243     
00244     
00245 }
00246 
00247 
00248 
00249 
00250 void SystemClock_Config(void)
00251 {
00252 #ifdef B_L072Z_LRWAN1_LORA
00253     /* 
00254      * The L072Z_LRWAN1_LORA clock setup is somewhat differnt from the Nucleo board.
00255      * It has no LSE.
00256      */
00257     RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
00258     RCC_OscInitTypeDef RCC_OscInitStruct = {0};
00259 
00260     /* Enable HSE Oscillator and Activate PLL with HSE as source */
00261     RCC_OscInitStruct.OscillatorType      = RCC_OSCILLATORTYPE_HSI;
00262     RCC_OscInitStruct.HSEState            = RCC_HSE_OFF;
00263     RCC_OscInitStruct.HSIState            = RCC_HSI_ON;
00264     RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
00265     RCC_OscInitStruct.PLL.PLLState        = RCC_PLL_ON;
00266     RCC_OscInitStruct.PLL.PLLSource       = RCC_PLLSOURCE_HSI;
00267     RCC_OscInitStruct.PLL.PLLMUL          = RCC_PLLMUL_6;
00268     RCC_OscInitStruct.PLL.PLLDIV          = RCC_PLLDIV_3;
00269 
00270     if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
00271         // Error_Handler();
00272     }
00273 
00274     /* Set Voltage scale1 as MCU will run at 32MHz */
00275     __HAL_RCC_PWR_CLK_ENABLE();
00276     __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
00277 
00278     /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */
00279     while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {};
00280 
00281     /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
00282     clocks dividers */
00283     RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
00284     RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
00285     RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
00286     RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
00287     RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
00288     if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) {
00289         // Error_Handler();
00290     }
00291 #endif
00292 }
00293 
00294 void dump(const char *title, const void *data, int len, bool dwords)
00295 {
00296     dprintf("dump(\"%s\", 0x%x, %d bytes)", title, data, len);
00297 
00298     int i, j, cnt;
00299     unsigned char *u;
00300     const int width = 16;
00301     const int seppos = 7;
00302 
00303     cnt = 0;
00304     u = (unsigned char *)data;
00305     while (len > 0) {
00306         ser->printf("%08x: ", (unsigned int)data + cnt);
00307         if (dwords) {
00308             unsigned int *ip = ( unsigned int *)u;
00309             ser->printf(" 0x%08x\r\n", *ip);
00310             u+= 4;
00311             len -= 4;
00312             cnt += 4;
00313             continue;
00314         }
00315         cnt += width;
00316         j = len < width ? len : width;
00317         for (i = 0; i < j; i++) {
00318             ser->printf("%2.2x ", *(u + i));
00319             if (i == seppos)
00320                 ser->putc(' ');
00321         }
00322         ser->putc(' ');
00323         if (j < width) {
00324             i = width - j;
00325             if (i > seppos + 1)
00326                 ser->putc(' ');
00327             while (i--) {
00328                 printf("%s", "   ");
00329             }
00330         }
00331         for (i = 0; i < j; i++) {
00332             int c = *(u + i);
00333             if (c >= ' ' && c <= '~')
00334                 ser->putc(c);
00335             else
00336                 ser->putc('.');
00337             if (i == seppos)
00338                 ser->putc(' ');
00339         }
00340         len -= width;
00341         u += width;
00342         ser->printf("\r\n");
00343     }
00344     ser->printf("--\r\n");
00345 }
00346 
00347 
00348 
00349 
00350 int SX1276PingPong() 
00351 {
00352 
00353     
00354     while( 1 )
00355     {
00356 #ifdef TARGET_STM32L4
00357         WatchDogUpdate();
00358 #endif
00359         
00360         switch( State )
00361         {
00362         case RX:
00363             *led3 = 0;
00364             if( isMaster == true )
00365             {
00366                 if( BufferSize > 0 )
00367                 {
00368                     if( memcmp(Buffer, PongMsg, sizeof(PongMsg)) == 0 )
00369                     {
00370                         *led = !*led;
00371                         dprintf( "...Pong" );
00372                         // Send the next PING frame            
00373                         memcpy(Buffer, PingMsg, sizeof(PingMsg));
00374                         // We fill the buffer with numbers for the payload 
00375                         for( i = sizeof(PingMsg); i < BufferSize; i++ )
00376                         {
00377                             Buffer[i] = i - sizeof(PingMsg);
00378                         }
00379                         //wait_ms( 10 ); 
00380                         Radio->Send( Buffer, BufferSize );
00381                     }
00382                     else if( memcmp(Buffer, PingMsg, sizeof(PingMsg)) == 0 )
00383                     { // A master already exists then become a slave
00384                         dprintf( "...Ping" );
00385                         *led = !*led;
00386                         isMaster = false;
00387                         // Send the next PONG frame
00388                         memcpy(Buffer, PongMsg, sizeof(PongMsg));        
00389                         // We fill the buffer with numbers for the payload 
00390                         for( i = sizeof(PongMsg); i < BufferSize; i++ )
00391                         {
00392                             Buffer[i] = i - sizeof(PongMsg);
00393                         }
00394                         //wait_ms( 10 ); 
00395                         Radio->Send( Buffer, BufferSize );
00396                     }
00397                     else // valid reception but neither a PING or a PONG message
00398                     {    // Set device as master ans start again
00399                         isMaster = true;
00400                         Radio->Rx( RX_TIMEOUT_VALUE );
00401                     }    
00402                 }
00403             }
00404             else
00405             {
00406                 if( BufferSize > 0 )
00407                 {
00408                     if( memcmp(Buffer, PingMsg, sizeof(PingMsg)) == 0 )
00409                     {
00410                         *led = !*led;
00411                         dprintf( "...Ping" );
00412                         // Send the reply to the PING string
00413                         memcpy(Buffer, PongMsg, sizeof(PongMsg));
00414                         // We fill the buffer with numbers for the payload 
00415                         for( i = sizeof(PongMsg); i < BufferSize; i++ )
00416                         {
00417                             Buffer[i] = i - sizeof(PongMsg);
00418                         }
00419                         //wait_ms( 10 );  
00420                         Radio->Send( Buffer, BufferSize );
00421                     }
00422                     else // valid reception but not a PING as expected
00423                     {    // Set device as master and start again
00424                         isMaster = true;
00425                         Radio->Rx( RX_TIMEOUT_VALUE );
00426                     }    
00427                 }
00428             }
00429             State = LOWPOWER;
00430             break;
00431         case TX:    
00432             *led3 = 1;
00433             if( isMaster == true )  
00434             {
00435                 dprintf("Ping..." );
00436             }
00437             else
00438             {
00439                 dprintf("Pong..." );
00440             }
00441             Radio->Rx( RX_TIMEOUT_VALUE );
00442             State = LOWPOWER;
00443             break;
00444         case RX_TIMEOUT:
00445             if( isMaster == true )
00446             {
00447                 // Send the next PING frame
00448                 memcpy(Buffer, PingMsg, sizeof(PingMsg));
00449                 for( i = sizeof(PingMsg); i < BufferSize; i++ )
00450                 {
00451                     Buffer[i] = i - sizeof(PingMsg);
00452                 }
00453                 //wait_ms( 10 ); 
00454                 Radio->Send( Buffer, BufferSize );
00455             }
00456             else
00457             {
00458                 Radio->Rx( RX_TIMEOUT_VALUE );  
00459             }             
00460             State = LOWPOWER;
00461             break;
00462         case RX_ERROR:
00463             // We have received a Packet with a CRC error, send reply as if packet was correct
00464             if( isMaster == true )
00465             {
00466                 // Send the next PING frame
00467                 memcpy(Buffer, PingMsg, sizeof(PingMsg));
00468                 for( i = 4; i < BufferSize; i++ )
00469                 {
00470                     Buffer[i] = i - 4;
00471                 }
00472                 //wait_ms( 10 );  
00473                 Radio->Send( Buffer, BufferSize );
00474             }
00475             else
00476             {
00477                 // Send the next PONG frame
00478                 memcpy(Buffer, PongMsg, sizeof(PongMsg));
00479                 for( i = sizeof(PongMsg); i < BufferSize; i++ )
00480                 {
00481                     Buffer[i] = i - sizeof(PongMsg);
00482                 }
00483                 //wait_ms( 10 );  
00484                 Radio->Send( Buffer, BufferSize );
00485             }
00486             State = LOWPOWER;
00487             break;
00488         case TX_TIMEOUT:
00489             Radio->Rx( RX_TIMEOUT_VALUE );
00490             State = LOWPOWER;
00491             break;
00492         case LOWPOWER:
00493             sleep();
00494             break;
00495         default:
00496             State = LOWPOWER;
00497             break;
00498         }    
00499     }
00500 }
00501 
00502 void OnTxDone(void *radio)
00503 {
00504     Radio->Sleep( );
00505     State = TX;
00506     if (DEBUG_MESSAGE)
00507         dprintf("> OnTxDone");
00508 }
00509 
00510 void OnRxDone(void *radio, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
00511 {
00512     Radio->Sleep( );
00513     BufferSize = size;
00514     memcpy( Buffer, payload, BufferSize );
00515     State = RX;
00516     if (DEBUG_MESSAGE)
00517         dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr);
00518     //dump("Data:", payload, size);
00519     //ser->printf("Rx Data ~%x%x%x%x\n", payload[0], payload[1], payload[2], payload[3]);
00520     ser->printf("~%02x%02x%02x%02x\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
00521 }
00522 
00523 void OnTxTimeout(void *radio)
00524 {
00525     *led3 = 0;
00526     Radio->Sleep( );
00527     State = TX_TIMEOUT;
00528     if(DEBUG_MESSAGE)
00529         dprintf("> OnTxTimeout");
00530 }
00531 
00532 void OnRxTimeout(void *radio)
00533 {
00534     *led3 = 0;
00535     Radio->Sleep( );
00536     Buffer[BufferSize-1] = 0;
00537     State = RX_TIMEOUT;
00538     if (DEBUG_MESSAGE)
00539         dprintf("> OnRxTimeout");
00540 }
00541 
00542 void OnRxError(void *radio)
00543 {
00544     Radio->Sleep( );
00545     State = RX_ERROR;
00546     if (DEBUG_MESSAGE)
00547         dprintf("> OnRxError");
00548 }
00549 
00550 #endif
00551 
00552 
00553 int SX1276Comm(bool mode, bool ack)
00554 {    
00555 
00556 
00557     Radio->Rx( RX_TIMEOUT_VALUE );
00558     wait_ms(100);
00559 
00560 
00561 
00562 
00563     /*switch( State ) {
00564     
00565         case RX:
00566             Radio->Rx( RX_TIMEOUT_VALUE );  
00567             
00568             //memcpy(Buffer, commData, sizeof(Buffer));
00569             //ser->printf("Rx Data\n\r", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
00570             
00571             //State = LOWPOWER;
00572             break;
00573         case TX:
00574             
00575             //State = LOWPOWER;
00576             break;
00577         case RX_TIMEOUT:
00578             
00579             Radio->Rx( RX_TIMEOUT_VALUE );
00580             //State = LOWPOWER;
00581             break;
00582         case RX_ERROR:
00583             
00584             //wait_ms(10);
00585             //Radio->Rx( RX_TIMEOUT_VALUE );
00586             State = LOWPOWER;
00587             break;
00588         case TX_TIMEOUT:
00589             
00590             //State = LOWPOWER;
00591             break;
00592         case LOWPOWER:
00593             sleep();
00594             break;
00595         default:
00596             //State = LOWPOWER;
00597             break;
00598     }
00599     */
00600 }