Santiago Gil / Mbed 2 deprecated DISCO-L072CZ-LRWAN1_LoRa_server

Dependencies:   BufferedSerial SX1276GenericLib mbed

Fork of DISCO-L072CZ-LRWAN1_LoRa_PingPong by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GenericPingPong.cpp Source File

GenericPingPong.cpp

00001 /*
00002  * This file contains a copy of the master content sx1276PingPong
00003  * with adaption for the SX1276Generic environment
00004  * (c) 2017 Helmut Tschemernjak
00005  * 30826 Garbsen (Hannover) Germany
00006  */
00007 
00008 #include "mbed.h"
00009 #include "PinMap.h"
00010 #include "GenericPingPong.h"
00011 #include "sx1276-mbed-hal.h"
00012 #include "main.h"
00013 #include <string>
00014 
00015 #ifdef FEATURE_LORA
00016 
00017 /* Set this flag to '1' to display debug messages on the console */
00018 #define DEBUG_MESSAGE   1
00019 
00020 /* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */
00021 #define USE_MODEM_LORA  1
00022 #define USE_MODEM_FSK   !USE_MODEM_LORA
00023 #define RF_FREQUENCY            RF_FREQUENCY_915_0  // Hz
00024 #define TX_OUTPUT_POWER         20                  // 20 dBm
00025 
00026 #if USE_MODEM_LORA == 1
00027 
00028 #define LORA_BANDWIDTH          125000  // LoRa default, details in SX1276::BandwidthMap
00029 #define LORA_SPREADING_FACTOR   LORA_SF7
00030 #define LORA_CODINGRATE         LORA_ERROR_CODING_RATE_4_5
00031 
00032 #define LORA_PREAMBLE_LENGTH    8       // Same for Tx and Rx
00033 #define LORA_SYMBOL_TIMEOUT     5       // Symbols
00034 #define LORA_FIX_LENGTH_PAYLOAD_ON  false
00035 #define LORA_FHSS_ENABLED       true
00036 #define LORA_NB_SYMB_HOP        4
00037 #define LORA_IQ_INVERSION_ON    false
00038 #define LORA_CRC_ENABLED        true
00039 
00040 #elif USE_MODEM_FSK == 1
00041 
00042 #define FSK_FDEV                25000     // Hz
00043 #define FSK_DATARATE            19200     // bps
00044 #define FSK_BANDWIDTH           50000     // Hz
00045 #define FSK_AFC_BANDWIDTH       83333     // Hz
00046 #define FSK_PREAMBLE_LENGTH     5         // Same for Tx and Rx
00047 #define FSK_FIX_LENGTH_PAYLOAD_ON   false
00048 #define FSK_CRC_ENABLED         true
00049 
00050 #else
00051 #error "Please define a modem in the compiler options."
00052 #endif
00053 
00054 
00055 #define RX_TIMEOUT_VALUE    3500    // in ms
00056 
00057 //#define BUFFER_SIZE       32        // Define the payload size here
00058 #define BUFFER_SIZE         256        // Define the payload size here
00059 
00060 /*
00061  *  Global variables declarations
00062  */
00063 typedef enum {
00064     LOWPOWER = 0,
00065     IDLE,
00066 
00067     RX,
00068     RX_TIMEOUT,
00069     RX_ERROR,
00070 
00071     TX,
00072     TX_TIMEOUT,
00073 
00074     CAD,
00075     CAD_DONE
00076 } AppStates_t;
00077 
00078 volatile AppStates_t State = LOWPOWER;
00079 
00080 /*!
00081  * Radio events function pointer
00082  */
00083 static RadioEvents_t RadioEvents;
00084 
00085 /*
00086  *  Global variables declarations
00087  */
00088 SX1276Generic *Radio;
00089 
00090 
00091 //const uint8_t PingMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'I', 'N', 'G'};// "PING";
00092 //const uint8_t PongMsg[] = { 0xff, 0xff, 0x00, 0x00, 'P', 'O', 'N', 'G'};// "PONG";
00093 //const uint8_t PingMsg[] = { 'M', 'S', 'J', ' ','G','I','L'};// "PING";
00094 //const uint8_t PongMsg[] = {  'R', 'P', 'T', 'A',' ','G','I','L'};// "PONG";
00095 
00096 //construccion de la trama
00097 const char EUI[] = "0A01";// 4  bytes que definen el identificador del dispositivo (copiar los bytes en string)
00098 const char AppEUI[] = "AAAA";// 4  bytes que definen el identificador de la aplicacion (copiar los bytes en string)
00099 const char AppKey[] = "1A1B";// 4  bytes que definen la clave de la aplicacion (copiar los bytes en string) - El protocolo LoRaWAN establece la clave de 16 bytes pero para efectos de prueba se hara de 4
00100 char MsgTX[256] = "";// Mensaje de transmision, se pueden usar los 52 bytes faltantes para completar el payload de 64 bytes. Se puede poner directamente en string.
00101 char MsgRX[256] = "";// Mensaje de recepcion, carga el payload entrante a esta cadena.
00102 char MsgRet[] = "RECIBIDO";
00103 char DestEUI[4] = "";
00104 char euiAux[4]="";
00105 uint16_t BufferSize = BUFFER_SIZE;
00106 uint8_t *Buffer;
00107 string msjDeco="";
00108 char *retParse;
00109 char *srcEUI;
00110 char *msjDestEUI;
00111 char *msjContent;
00112 Serial serRPi(PA_9, PA_10);
00113 
00114 DigitalOut *led3;
00115 
00116 
00117 int SX1276PingPong()
00118 {
00119 #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) )
00120     DigitalOut *led = new DigitalOut(LED2);
00121 #elif defined(TARGET_NUCLEO_L073RZ) || defined(TARGET_DISCO_L072CZ_LRWAN1)
00122     DigitalOut *led = new DigitalOut(LED4);   // RX red
00123     led3 = new DigitalOut(LED3);  // TX blue
00124 #else
00125     DigitalOut *led = new DigitalOut(LED1);
00126     led3 = led;
00127 #endif
00128 
00129     Buffer = new  uint8_t[BUFFER_SIZE];
00130     *led3 = 1;
00131 
00132 #ifdef B_L072Z_LRWAN1_LORA
00133     Radio = new SX1276Generic(NULL, MURATA_SX1276,
00134                               LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00135                               LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5,
00136                               LORA_ANT_RX, LORA_ANT_TX, LORA_ANT_BOOST, LORA_TCXO);
00137 #else // RFM95
00138     Radio = new SX1276Generic(NULL, RFM95_SX1276,
00139                               LORA_SPI_MOSI, LORA_SPI_MISO, LORA_SPI_SCLK, LORA_CS, LORA_RESET,
00140                               LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5);
00141 
00142 #endif
00143     //serRPi = new BufferedSerial(PA_9, PA_10);
00144     serRPi.baud(115200);
00145     serRPi.format(8);
00146     uint8_t i;
00147     bool isServer = true;
00148 
00149     dprintf("Aplicacion de comunicacion LoRa punto a punto" );
00150     dprintf("Frecuencia: %.1f", (double)RF_FREQUENCY/1000000.0);
00151     dprintf("TXPower: %d dBm",  TX_OUTPUT_POWER);
00152 #if USE_MODEM_LORA == 1
00153     dprintf("Bandwidth: %d Hz", LORA_BANDWIDTH);
00154     dprintf("Spreading factor: SF%d", LORA_SPREADING_FACTOR);
00155 #elif USE_MODEM_FSK == 1
00156     dprintf("Bandwidth: %d kHz",  FSK_BANDWIDTH);
00157     dprintf("Baudrate: %d", FSK_DATARATE);
00158 #endif
00159     // Initialize Radio driver
00160     RadioEvents.TxDone = OnTxDone;
00161     RadioEvents.RxDone = OnRxDone;
00162     RadioEvents.RxError = OnRxError;
00163     RadioEvents.TxTimeout = OnTxTimeout;
00164     RadioEvents.RxTimeout = OnRxTimeout;
00165     if (Radio->Init( &RadioEvents ) == false) {
00166         while(1) {
00167             dprintf("Radio could not be detected!");
00168             wait( 1 );
00169         }
00170     }
00171 
00172 
00173     switch(Radio->DetectBoardType()) {
00174         case SX1276MB1LAS:
00175             if (DEBUG_MESSAGE)
00176                 dprintf(" > Board Type: SX1276MB1LAS <");
00177             break;
00178         case SX1276MB1MAS:
00179             if (DEBUG_MESSAGE)
00180                 dprintf(" > Board Type: SX1276MB1LAS <");
00181         case MURATA_SX1276:
00182             if (DEBUG_MESSAGE)
00183                 dprintf(" > Board Type: MURATA_SX1276_STM32L0 <");
00184             break;
00185         case RFM95_SX1276:
00186             if (DEBUG_MESSAGE)
00187                 dprintf(" > HopeRF RFM95xx <");
00188             break;
00189         default:
00190             dprintf(" > Board Type: unknown <");
00191     }
00192 
00193     Radio->SetChannel(RF_FREQUENCY );
00194 
00195 #if USE_MODEM_LORA == 1
00196 
00197     if (LORA_FHSS_ENABLED)
00198         dprintf("             > LORA FHSS Mode <");
00199     if (!LORA_FHSS_ENABLED)
00200         dprintf("             > LORA Mode <");
00201 
00202     Radio->SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
00203                         LORA_SPREADING_FACTOR, LORA_CODINGRATE,
00204                         LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
00205                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
00206                         LORA_IQ_INVERSION_ON, 2000 );
00207 
00208     Radio->SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
00209                         LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
00210                         LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0,
00211                         LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP,
00212                         LORA_IQ_INVERSION_ON, true );
00213 
00214 #elif USE_MODEM_FSK == 1
00215 
00216     dprintf("              > FSK Mode <");
00217     Radio->SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
00218                         FSK_DATARATE, 0,
00219                         FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
00220                         FSK_CRC_ENABLED, 0, 0, 0, 2000 );
00221 
00222     Radio->SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
00223                         0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
00224                         0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED,
00225                         0, 0, false, true );
00226 
00227 #else
00228 
00229 #error "Please define a modem in the compiler options."
00230 
00231 #endif
00232 
00233     if (DEBUG_MESSAGE)
00234         dprintf("Inicializando el servidor");
00235     dprintf("EUI (ID): %s",EUI);
00236 
00237     Radio->Rx( RX_TIMEOUT_VALUE );
00238 
00239     while( 1 ) {
00240 #ifdef TARGET_STM32L4
00241         WatchDogUpdate();
00242 #endif
00243 
00244         switch( State ) {
00245             case RX:
00246                 //dprintf( "Recibiendo informacion" );
00247                 *led = !*led;
00248                 dprintf("Mensaje para depurar: %s",MsgRX);
00249                 //strcpy(DestEUI,"A010");
00250                 msjDeco=MsgRX;
00251                 //vector<string> x = split(msjDeco, '|');
00252                 splitOnPosition(MsgRX, 0);
00253                 //msjDestEUI=splitOnPosition(MsgRX, 3);
00254                 //msjContent=splitOnPosition(MsgRX, 4);
00255 
00256                 dprintf("Source EUI: %s, Destination EUI: %s, Content: %s",srcEUI,msjDestEUI,msjContent);
00257                 if(strcmp(EUI,msjDestEUI) == 0) {
00258                     dprintf("Mismo EUI, Soy el destinatario");
00259 
00260                 } else {
00261                     dprintf("Diferente EUI, ignorar mensaje");
00262                     Radio->Rx( RX_TIMEOUT_VALUE );
00263                     wait_ms( 500 );
00264                     *led = !*led;
00265                     State = LOWPOWER;
00266                     break;
00267                 }
00268                 strcpy(MsgRet,"RECIBIDO");
00269                 strcpy(MsgTX, EUI);
00270                 strcat(MsgTX, "|");
00271                 strcat(MsgTX, AppEUI);
00272                 strcat(MsgTX, "|");
00273                 strcat(MsgTX, AppKey);
00274                 strcat(MsgTX, "|");
00275                 strcat(MsgTX, srcEUI);
00276                 strcat(MsgTX, "|");
00277                 strcat(MsgTX, MsgRet);
00278                 //strcat(MsgTX, ";");
00279                 //MsgRX = "RECIBIDO";
00280                 memcpy(Buffer, MsgTX, sizeof(MsgTX));
00281                 // Se llena el buffer con la informacion a enviar
00282                 for( i = sizeof(MsgTX); i < BufferSize; i++ ) {
00283                     Buffer[i] = i - sizeof(MsgTX);
00284                 }
00285                 //dprintf("enviando mensaje a raspberry");
00286                 serRPi.printf("contenido: %s \r\n",msjContent);
00287                 Radio->Send( Buffer, BufferSize );
00288                 Radio->Rx( RX_TIMEOUT_VALUE );
00289                 wait_ms( 500 );
00290                 
00291                 /*Enviar contenido a la raspberry por puerto serial*/
00292                 
00293                 
00294                 /***************************************************/
00295                 
00296                 *led = !*led;
00297                 State = LOWPOWER;
00298                 break;
00299             case TX:
00300                 *led3 = !*led3;
00301                 if( isServer == true ) {
00302                     //dprintf("Enviando respuesta al nodo" );
00303                     //dprintf("Mensaje a enviar: %s",MsgTX);
00304                 }
00305                 wait_ms( 500 );
00306                 *led3 = !*led3;
00307                 Radio->Rx( RX_TIMEOUT_VALUE );
00308                 State = LOWPOWER;
00309                 break;
00310             case RX_TIMEOUT:
00311 
00312                 Radio->Rx( RX_TIMEOUT_VALUE );
00313                 State = LOWPOWER;
00314                 break;
00315             case RX_ERROR:
00316                 // We have received a Packet with a CRC error, send reply as if packet was correct
00317                 /*strcpy(MsgRet,"ERROR");
00318                 strcpy(MsgTX, EUI);
00319                 strcat(MsgTX, "|");
00320                 strcat(MsgTX, AppEUI);
00321                 strcat(MsgTX, "|");
00322                 strcat(MsgTX, AppKey);
00323                 strcat(MsgTX, "|");
00324                 strcat(MsgTX, "A010");
00325                 strcat(MsgTX, "|");
00326                 strcat(MsgTX, MsgRet);
00327                 //MsgRX = "ERROR";
00328                 if( isServer == true ) {
00329                     // Se llena el buffer para el envio del error
00330                     memcpy(Buffer, MsgTX, sizeof(MsgTX));
00331                     for( i = sizeof(MsgTX); i < BufferSize; i++ ) {
00332                         Buffer[i] = i - sizeof(MsgTX);
00333                     }
00334                     wait_ms( 1000 );
00335                     Radio->Send( Buffer, BufferSize );
00336                 }*/
00337                 Radio->Rx( RX_TIMEOUT_VALUE );
00338                 State = LOWPOWER;
00339                 break;
00340             case TX_TIMEOUT:
00341                 Radio->Rx( RX_TIMEOUT_VALUE );
00342                 State = LOWPOWER;
00343                 break;
00344             case LOWPOWER:
00345                 sleep();
00346                 break;
00347             default:
00348                 State = LOWPOWER;
00349                 break;
00350         }
00351     }
00352 }
00353 
00354 char *splitOnPosition(char *msj, int pos)
00355 {
00356 
00357     int i=0;
00358     char *substring = strtok (msj,"|");
00359     char *strOutput="";
00360     while (substring != NULL) {
00361         //dprintf ("substring: %s, index: %d",substring,i);
00362 
00363         if(i == 0) {
00364             srcEUI = substring;
00365         } else if(i == 3) {
00366             msjDestEUI = substring;
00367         } else if(i == 4) {
00368             msjContent = substring;
00369         } else if(i > 4) {
00370             strcat(msjContent," ");
00371             strcat(msjContent,substring);
00372             //dprintf ("contenido: %s, substring: %s, i: %d",msjContent, substring, i);
00373         }
00374         substring = strtok (NULL, "|");
00375         i++;
00376     }
00377     return strOutput;
00378 }
00379 
00380 void OnTxDone(void *radio, void *userThisPtr, void *userData)
00381 {
00382     Radio->Sleep( );
00383     State = TX;
00384     if (DEBUG_MESSAGE)
00385         dprintf("> OnTxDone");
00386 }
00387 
00388 void OnRxDone(void *radio, void *userThisPtr, void *userData, uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
00389 {
00390     Radio->Sleep( );
00391     BufferSize = size;
00392     memcpy( Buffer, payload, BufferSize );
00393     State = RX;
00394     if (DEBUG_MESSAGE)
00395         dprintf("> OnRxDone: RssiValue=%d dBm, SnrValue=%d", rssi, snr);
00396     //dump("Data:", payload, size);
00397     strcpy(MsgRX,(char*)payload);
00398     //dprintf("Msj: %s", MsgRX);
00399 }
00400 
00401 void OnTxTimeout(void *radio, void *userThisPtr, void *userData)
00402 {
00403     *led3 = 0;
00404     Radio->Sleep( );
00405     State = TX_TIMEOUT;
00406     if(DEBUG_MESSAGE)
00407         dprintf("> OnTxTimeout");
00408 }
00409 
00410 void OnRxTimeout(void *radio, void *userThisPtr, void *userData)
00411 {
00412     *led3 = 0;
00413     Radio->Sleep( );
00414     Buffer[BufferSize-1] = 0;
00415     State = RX_TIMEOUT;
00416     if (DEBUG_MESSAGE)
00417         dprintf("> OnRxTimeout");
00418 }
00419 
00420 void OnRxError(void *radio, void *userThisPtr, void *userData)
00421 {
00422     Radio->Sleep( );
00423     State = RX_ERROR;
00424     if (DEBUG_MESSAGE)
00425         dprintf("> OnRxError");
00426 }
00427 
00428 #endif