Source code for the SX126xDVK1xAS Dev Kit. This example code has only been tested on the Nucleo L476RG

Dependencies:   mbed DmTftLibrary SX126xLib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DemoApplication.cpp Source File

DemoApplication.cpp

00001 /*
00002   ______                              _
00003  / _____)             _              | |
00004 ( (____  _____ ____ _| |_ _____  ____| |__
00005  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00006  _____) ) ____| | | || |_| ____( (___| | | |
00007 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00008     (C)2016 Semtech
00009 
00010 Description: PingPong, PER demo implementation.
00011 
00012 Maintainer: Gregory Cristian & Gilbert Menth
00013 */
00014 
00015 #include "mbed.h"
00016 #include "radio.h"
00017 #include "sx126x-hal.h"
00018 #include "Eeprom.h"
00019 #include "DemoApplication.h"
00020 
00021 /*!
00022  * \brief Defines the local payload buffer size
00023  */
00024 #define BUFFER_SIZE                     255
00025 
00026 /*!
00027  * \brief Defines the size of the token defining message type in the payload
00028  *        cf. above.
00029  */
00030 #define PINGPONG_SIZE                   4
00031 #define PER_SIZE                        3
00032 
00033 /*!
00034  * \brief Define time used in PingPong demo to synch with cycle
00035  * RX_TIMEOUT_MARGIN is the free time between each cycle (time reserve)
00036  */
00037 #define RX_TIMEOUT_MARGIN               150  // ms
00038 #define RX_TX_TRANSITION_WAIT           5    // ms
00039 
00040 
00041 /*!
00042  * \brief Define the possible message type for the Ping-Pong and PER apps
00043  */
00044 const uint8_t PingMsg[] = "PING";
00045 const uint8_t PongMsg[] = "PONG";
00046 const uint8_t PerMsg[]  = "PER";
00047 
00048 /*!
00049  * \brief Buffer and its size
00050  */
00051 uint8_t BufferSize = BUFFER_SIZE;
00052 uint8_t Buffer[BUFFER_SIZE];
00053 
00054 /*!
00055  * \brief Function to be executed on Radio Tx Done event
00056  */
00057 void OnTxDone( void );
00058 
00059 /*!
00060  * \brief Function to be executed on Radio Rx Done event
00061  */
00062 void OnRxDone( void );
00063 
00064 /*!
00065  * \brief Function executed on Radio Tx Timeout event
00066  */
00067 void OnTxTimeout( void );
00068 
00069 /*!
00070  * \brief Function executed on Radio Rx Timeout event
00071  */
00072 void OnRxTimeout( void );
00073 
00074 /*!
00075  * \brief Function executed on Radio Rx Error event
00076  */
00077 void OnRxError( IrqErrorCode_t );
00078 
00079 /*!
00080  * \brief Function executed on Radio CAD Done event
00081  */
00082 void OnCadDone( bool channelActivityDetected );
00083 
00084 /*!
00085  * \brief All the callbacks are stored in a structure
00086  */
00087 RadioCallbacks_t RadioEvents =
00088 {
00089     &OnTxDone,        // txDone
00090     &OnRxDone,        // rxDone
00091     NULL,             // rxPreambleDetect
00092     NULL,             // rxSyncWordDone
00093     NULL,             // rxHeaderDone
00094     &OnTxTimeout,     // txTimeout
00095     &OnRxTimeout,     // rxTimeout
00096     &OnRxError,       // rxError
00097     &OnCadDone,       // cadDone
00098 };
00099 
00100 // SPI
00101 // mosi, miso, sclk, nss, dio0, dio1, dio2, dio3, rst, freqSel, deviceSel, antSwPower, callbacks...
00102 SX126xHal Radio( D11, D12, D13, D7, D3, D5, NC, NC, A0, A1, A2, D8, &RadioEvents );
00103 
00104 /*!
00105  * \brief Tx LED toggling on transmition success
00106  */
00107 DigitalOut TX_LED( A4 );
00108 
00109 /*!
00110  * \brief Rx LED toggling on reception success
00111  */
00112 DigitalOut RX_LED( A5 );
00113 
00114 /*!
00115  * \brief Mask of IRQs
00116  */
00117 uint16_t IrqMask = 0x0000;
00118 
00119 /*!
00120  * \brief Locals parameters and status for radio API
00121  * NEED TO BE OPTIMIZED, COPY OF STUCTURE ALREADY EXISTING
00122  */
00123 PacketParams_t PacketParams;
00124 PacketStatus_t PacketStatus;
00125 ModulationParams_t ModulationParams;
00126 
00127 /*!
00128  * \brief Flag to indicate if the demo is already running
00129  */
00130 static bool DemoRunning = false;
00131 
00132 /*!
00133  * \brief Frequency Error (only LSB)
00134  */
00135 static double FreErrorLsb = 0.0;
00136 
00137 /*!
00138  * \brief Flag holding the current internal state of the demo application
00139  */
00140 static uint8_t DemoInternalState = APP_IDLE;
00141 
00142 /*!
00143  * \brief Ticker for master to synch Tx frames. Flags for PER and PingPong demo
00144  * for Synch TX in cycle.
00145  */
00146 Ticker SendNextPacket;
00147 static bool SendNext = false;
00148 
00149 /*!
00150  * \brief Hold last Rx packet number to compute PER in PER and PingPong demo
00151  */
00152 static uint32_t PacketRxSequence = 0;
00153 static uint32_t PacketRxSequencePrev = 0;
00154 
00155 void LedBlink( void );
00156 void InitializeDemoParameters( uint8_t modulation );
00157 uint16_t GetTimeOnAir( uint8_t modulation );
00158 void SendNextPacketEvent( void );
00159 
00160 // **************************     RF Test Demo    ******************************
00161 // *                                                                           *
00162 // *                                                                           *
00163 // *                                                                           *
00164 // *****************************************************************************
00165 uint8_t RunDemoTestRssi( void )
00166 {
00167     uint8_t refreshDisplay = 0;
00168     static uint16_t i;
00169     
00170     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00171     {
00172         return 0;
00173     }
00174 
00175     if( DemoRunning == false )
00176     {
00177         DemoRunning = true;
00178 
00179         printf( "Start RunDemoTestRssi\n\r" );
00180 
00181         TX_LED = 0;
00182         RX_LED = 0;
00183 
00184         Eeprom.EepromData.DemoSettings.CntPacketTx    = 0;
00185         Eeprom.EepromData.DemoSettings.CntPacketRxOK  = 0;
00186         Eeprom.EepromData.DemoSettings.CntPacketRxKO  = 0;
00187 
00188         InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType );
00189 
00190         IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00191         Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00192         // Rx Continuous
00193         if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
00194         {
00195             Radio.SetRx( 0xFFFFFF );
00196         }
00197         else
00198         {
00199             Radio.SetRxBoosted( 0xFFFFFF );
00200         }
00201         DemoInternalState = APP_IDLE;
00202         i = 0;
00203     }
00204 
00205     Radio.ProcessIrqs( );
00206 
00207     if( i < 5000 )
00208     {
00209         i++;
00210     }
00211     else
00212     {
00213         i = 0;
00214         Eeprom.EepromData.DemoSettings.RssiValue = Radio.GetRssiInst( );
00215         refreshDisplay = 1;
00216     }
00217 
00218     return refreshDisplay;
00219 }
00220 
00221 uint8_t RunDemoSleepMode( void )
00222 {
00223     SleepParams_t SleepParam;
00224     
00225     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00226     {
00227         return 0;
00228     }
00229 
00230     if( DemoRunning == false )
00231     {
00232         DemoRunning = true;
00233         InitializeDemoParameters( PACKET_TYPE_LORA );
00234         TX_LED = 0;
00235         RX_LED = 0;
00236 
00237         SleepParam.Fields.WakeUpRTC = 0;       //!< Get out of sleep mode if wakeup signal received from RTC
00238         SleepParam.Fields.Reset = 0;           //!< 
00239         SleepParam.Fields.WarmStart = 1;       //!< 
00240         Radio.SetSleep( SleepParam );
00241     }
00242     else
00243     {
00244         LedBlink( );
00245     }
00246     return 0;
00247 }
00248 
00249 uint8_t RunDemoStandbyRcMode( void )
00250 {
00251     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00252     {
00253         return 0;
00254     }
00255 
00256     if( DemoRunning == false )
00257     {
00258         DemoRunning = true;
00259         InitializeDemoParameters( PACKET_TYPE_LORA );
00260         TX_LED = 0;
00261         RX_LED = 0;
00262         Radio.SetRegulatorMode( ( RadioRegulatorMode_t )Eeprom.EepromData.DemoSettings.RadioPowerMode );
00263         Radio.SetStandby( STDBY_RC );
00264         DemoRunning = true;
00265     }
00266     else
00267     {
00268         LedBlink( );
00269     }
00270     return 0;
00271 }
00272 
00273 uint8_t RunDemoStandbyXoscMode( void )
00274 {
00275     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00276     {
00277         return 0;
00278     }
00279     if( DemoRunning == false )
00280     {
00281         DemoRunning = true;
00282         InitializeDemoParameters( PACKET_TYPE_LORA );
00283         TX_LED = 0;
00284         RX_LED = 0;
00285         Radio.SetRegulatorMode( ( RadioRegulatorMode_t )Eeprom.EepromData.DemoSettings.RadioPowerMode );
00286         Radio.SetStandby( STDBY_XOSC );
00287         DemoRunning = true;
00288     }
00289     else
00290     {
00291         LedBlink( );
00292     }
00293     return 0;
00294 }
00295 
00296 uint8_t RunDemoTxCw( void )
00297 {
00298     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00299     {
00300         return 0;
00301     }
00302 
00303     if( DemoRunning == false )
00304     {
00305         DemoRunning = true;
00306         InitializeDemoParameters( PACKET_TYPE_LORA );
00307         TX_LED = 0;
00308         RX_LED = 0;
00309         Radio.SetStandby( STDBY_RC );
00310         Radio.SetRegulatorMode( ( RadioRegulatorMode_t )Eeprom.EepromData.DemoSettings.RadioPowerMode );
00311         Radio.SetRfFrequency( Eeprom.EepromData.DemoSettings.Frequency );
00312         Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_200_US );
00313         Radio.SetTxContinuousWave( );
00314         DemoRunning = true;
00315     }
00316     else
00317     {
00318         LedBlink( );
00319     }
00320     return 0;
00321 }
00322 
00323 uint8_t RunDemoTxContinuousModulation( void )
00324 {
00325     uint8_t localPayloadSize = 250;
00326     uint8_t i = 0;
00327 
00328     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00329     {
00330         return 0;
00331     }
00332 
00333     Radio.ProcessIrqs( );
00334 
00335     if( DemoRunning == false )
00336     {
00337         DemoRunning = true;
00338         InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType );
00339         Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_3400_US );
00340         TX_LED = 0;
00341         RX_LED = 0;
00342         IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
00343         Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00344         for( i = 0; i < localPayloadSize; i++ )
00345         {
00346             Buffer[i] = ( uint8_t )rand( );
00347         }
00348         Radio.SendPayload( Buffer, localPayloadSize, 0xFFFFFF );
00349         DemoInternalState = APP_IDLE;
00350     }
00351     else
00352     {
00353         switch( DemoInternalState )
00354         {
00355             case APP_RX:
00356                 break;
00357 
00358             case APP_TX:
00359                 DemoInternalState = APP_IDLE;
00360                 LedBlink( );
00361                 // Send the next frame
00362                 IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
00363                 Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00364 
00365                 Radio.SendPayload( Buffer, localPayloadSize, 0xFFFFFF );
00366                 // we prepare next payload during transmission
00367                 for( i = 0; i < localPayloadSize; i++ )
00368                 {
00369                     Buffer[i] = ( uint8_t )rand( );
00370                 }
00371                 break;
00372 
00373             case APP_RX_TIMEOUT:
00374                 DemoInternalState = APP_IDLE;
00375                 break;
00376 
00377             case APP_RX_ERROR:
00378                 DemoInternalState = APP_IDLE;
00379                 break;
00380 
00381             case APP_TX_TIMEOUT:
00382                 DemoInternalState = APP_IDLE; 
00383                 break;
00384 
00385             case APP_IDLE:
00386                 break;
00387 
00388             default:
00389                 break;
00390         }
00391     }
00392 
00393     return 0;
00394 }
00395 
00396 uint8_t RunDemoRxContinuous( void )
00397 {
00398     uint8_t refreshDisplay = 0;
00399 
00400     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00401     {
00402         return 0;
00403     }
00404 
00405     if( DemoRunning == false )
00406     {
00407         DemoRunning = true;
00408 
00409         printf( "Start RunDemoRxContinuous\n\r" );
00410 
00411         TX_LED = 0;
00412         RX_LED = 0;
00413 
00414         Eeprom.EepromData.DemoSettings.CntPacketTx    = 0;
00415         Eeprom.EepromData.DemoSettings.CntPacketRxOK  = 0;
00416         Eeprom.EepromData.DemoSettings.CntPacketRxKO  = 0;
00417 
00418         InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType );
00419 
00420         // set preamble to max size to avoid filtering of the receiver on preamble lenght
00421         if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_LORA )
00422         {
00423             PacketParams.Params.LoRa.PreambleLength      = 0xFFFF;
00424             PacketParams.Params.LoRa.HeaderType          = ( RadioLoRaPacketLengthsMode_t )Eeprom.EepromData.DemoSettings.PacketParam2;
00425             PacketParams.Params.LoRa.PayloadLength       =                                 Eeprom.EepromData.DemoSettings.PacketParam3;
00426             PacketParams.Params.LoRa.CrcMode             = ( RadioLoRaCrcModes_t )         Eeprom.EepromData.DemoSettings.PacketParam4;
00427             PacketParams.Params.LoRa.InvertIQ            = ( RadioLoRaIQModes_t )          Eeprom.EepromData.DemoSettings.PacketParam5;
00428             Radio.SetPacketParams( &PacketParams );
00429         }
00430 
00431         IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00432         Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00433         // Rx Continuous
00434         if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
00435         {
00436             Radio.SetRx( 0xFFFFFF );
00437         }
00438         else
00439         {
00440             Radio.SetRxBoosted( 0xFFFFFF );
00441         }
00442         DemoInternalState = APP_IDLE;
00443 
00444     }
00445 
00446     if( Eeprom.EepromData.DemoSettings.MaxNumPacket > 0 ) // != Infinite
00447     {
00448         if( ( Eeprom.EepromData.DemoSettings.CntPacketRxOK + \
00449               Eeprom.EepromData.DemoSettings.CntPacketRxKO ) >= \
00450             Eeprom.EepromData.DemoSettings.MaxNumPacket )
00451         {
00452             RX_LED = 0;
00453             TX_LED = 0;
00454             DemoInternalState = APP_IDLE;
00455             Radio.SetStandby( STDBY_RC );
00456             SendNextPacket.detach( );
00457             Eeprom.EepromData.DemoSettings.HoldDemo = true;
00458             refreshDisplay = 1;
00459         }
00460     }
00461 
00462     Radio.ProcessIrqs( );
00463 
00464     switch( DemoInternalState )
00465     {
00466         case APP_TX:
00467             break;
00468 
00469         case APP_RX:
00470             RX_LED = !RX_LED;
00471             Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
00472             Radio.GetPacketStatus( &PacketStatus );
00473             if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_LORA )
00474             {
00475                 Eeprom.EepromData.DemoSettings.RssiValue    = PacketStatus.Params.LoRa.RssiPkt;
00476                 Eeprom.EepromData.DemoSettings.SnrValue     = PacketStatus.Params.LoRa.SnrPkt;
00477                 if( ( PacketStatus.Params.LoRa.FreqError & 0x00080000 ) == 0x00080000 )
00478                 {
00479                     PacketStatus.Params.LoRa.FreqError = 0xFFFFF - PacketStatus.Params.LoRa.FreqError;
00480                 }
00481                 Eeprom.EepromData.DemoSettings.FreqErrorEst = ( double )PacketStatus.Params.LoRa.FreqError * FreErrorLsb;
00482             }
00483             else // Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_GFSK
00484             {
00485                 Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Params.Gfsk.RssiAvg;
00486                 Eeprom.EepromData.DemoSettings.SnrValue = 0;
00487             }
00488 
00489             DemoInternalState = APP_IDLE;
00490             Eeprom.EepromData.DemoSettings.CntPacketRxOK ++;
00491             refreshDisplay = 1;
00492             break;
00493 
00494         case APP_RX_ERROR:
00495         case APP_RX_TIMEOUT:
00496             Eeprom.EepromData.DemoSettings.CntPacketRxKO ++;
00497             DemoInternalState = APP_IDLE;
00498             refreshDisplay = 1;
00499             break;
00500 
00501         case APP_TX_TIMEOUT:
00502             break;
00503 
00504         case APP_IDLE:
00505             break;
00506 
00507         default:
00508             break;
00509     }
00510     return refreshDisplay;
00511 }
00512 
00513 // *************************       PER Demo       ******************************
00514 // *                                                                           *
00515 // *                                                                           *
00516 // *                                                                           *
00517 // *****************************************************************************
00518 uint8_t RunDemoApplicationPer( void )
00519 {
00520     uint8_t i = 0;
00521     uint8_t refreshDisplay = 0;
00522 
00523     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00524     {
00525         return 0;
00526     }
00527 
00528     if( DemoRunning == false )
00529     {
00530         DemoRunning = true;
00531 
00532         printf( "Start RunDemoApplicationPer\n\r" );
00533 
00534         TX_LED = 0;
00535         RX_LED = 0;
00536 
00537         Eeprom.EepromData.DemoSettings.CntPacketTx    = 0;
00538         Eeprom.EepromData.DemoSettings.CntPacketRxOK  = 0;
00539         Eeprom.EepromData.DemoSettings.CntPacketRxKO  = 0;
00540         Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0;
00541 
00542         InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType );
00543 
00544         Eeprom.EepromData.DemoSettings.InterPacketDelay = GetTimeOnAir( Eeprom.EepromData.DemoSettings.ModulationType ) + RX_TX_TRANSITION_WAIT;
00545 
00546         if( Eeprom.EepromData.DemoSettings.Entity == MASTER )
00547         {
00548             SendNextPacket.attach_us( &SendNextPacketEvent, ( uint32_t )( ( Eeprom.EepromData.DemoSettings.InterPacketDelay + RX_TIMEOUT_MARGIN ) * 1000 ) );
00549             DemoInternalState = APP_TX;
00550         }
00551         else
00552         {
00553             IrqMask = /*0xFFFF; */IRQ_HEADER_VALID | IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00554             Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00555             // Rx Single without timeout for the start
00556             if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
00557             {
00558                 Radio.SetRx( 0x0000 );
00559             }
00560             else
00561             {
00562                 Radio.SetRxBoosted( 0x0000 );
00563             }
00564             DemoInternalState = APP_IDLE;
00565         }
00566     }
00567 
00568     Radio.ProcessIrqs( );
00569 
00570     if( Eeprom.EepromData.DemoSettings.MaxNumPacket > 0 ) // != Infinite
00571     {
00572         if( ( Eeprom.EepromData.DemoSettings.CntPacketRxOK + \
00573               Eeprom.EepromData.DemoSettings.CntPacketRxKO + \
00574               Eeprom.EepromData.DemoSettings.RxTimeOutCount) >= \
00575             Eeprom.EepromData.DemoSettings.MaxNumPacket )
00576         {
00577             RX_LED = 0;
00578             TX_LED = 0;
00579             DemoInternalState = APP_IDLE;
00580             Radio.SetStandby( STDBY_RC );
00581             SendNextPacket.detach( );
00582             Eeprom.EepromData.DemoSettings.HoldDemo = true;
00583             refreshDisplay = 1;
00584         }
00585     }
00586 
00587     switch( DemoInternalState )
00588     {
00589         case PER_TX_START:
00590             Eeprom.EepromData.DemoSettings.CntPacketTx++;
00591             DemoInternalState = APP_IDLE;
00592 
00593             Buffer[0] = 0x00;
00594             Buffer[1] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 24 ) & 0xFF;
00595             Buffer[2] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 16 ) & 0xFF;
00596             Buffer[3] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 8 )  & 0xFF;
00597             Buffer[4] = Eeprom.EepromData.DemoSettings.CntPacketTx & 0xFF;
00598             Buffer[5] = PerMsg[0];
00599             Buffer[6] = PerMsg[1];
00600             Buffer[7] = PerMsg[2];
00601             for( i = 8; i < Eeprom.EepromData.DemoSettings.PayloadLength; i++ )
00602             {
00603                 Buffer[i] = i;
00604             }
00605             TX_LED = !TX_LED;
00606             IrqMask = 0xFFFF; //IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
00607             Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00608             Radio.SendPayload( Buffer, Eeprom.EepromData.DemoSettings.PayloadLength, ( Eeprom.EepromData.DemoSettings.InterPacketDelay ) << 6 );
00609             break;
00610 
00611         case PER_RX_START:
00612             IrqMask = /*0xFFFF;*/ IRQ_HEADER_VALID | IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00613             Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00614             if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
00615             {
00616                 Radio.SetRx( ( Eeprom.EepromData.DemoSettings.InterPacketDelay + RX_TIMEOUT_MARGIN ) << 6 );
00617             }
00618             else
00619             {
00620                 Radio.SetRxBoosted( ( Eeprom.EepromData.DemoSettings.InterPacketDelay + RX_TIMEOUT_MARGIN ) << 6 );
00621             }
00622             DemoInternalState = APP_IDLE;
00623             break;
00624 
00625         case APP_TX:
00626             if( SendNext == true )
00627             {
00628                 SendNext = false;
00629                 if( Eeprom.EepromData.DemoSettings.MaxNumPacket == 0 )
00630                 {
00631                     DemoInternalState = PER_TX_START;  // Infinite -> send next
00632                     refreshDisplay = 1;
00633                 }
00634                 else if( Eeprom.EepromData.DemoSettings.CntPacketTx < \
00635                          Eeprom.EepromData.DemoSettings.MaxNumPacket )
00636                 {
00637                     DemoInternalState = PER_TX_START;  // MaxNumPacket not sent
00638                     refreshDisplay = 1;
00639                 }
00640                 else    // MaxNumPacket sent -> end of demo
00641                 {
00642                     RX_LED = 0;
00643                     TX_LED = 0;
00644                     DemoInternalState = APP_IDLE;
00645                     Radio.SetStandby( STDBY_RC );
00646                     SendNextPacket.detach( );
00647                     Eeprom.EepromData.DemoSettings.HoldDemo = true;
00648                     refreshDisplay = 1;
00649                 }
00650             }
00651             break;
00652 
00653         case APP_RX:
00654             RX_LED = !RX_LED;
00655             Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
00656             Radio.GetPacketStatus( &PacketStatus );
00657             if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_LORA )
00658             {
00659                 Eeprom.EepromData.DemoSettings.RssiValue    = PacketStatus.Params.LoRa.RssiPkt;
00660                 Eeprom.EepromData.DemoSettings.SnrValue     = PacketStatus.Params.LoRa.SnrPkt;
00661                 if( ( PacketStatus.Params.LoRa.FreqError & 0x00080000 ) == 0x00080000 )
00662                 {
00663                     PacketStatus.Params.LoRa.FreqError = 0xFFFFF - PacketStatus.Params.LoRa.FreqError;
00664                 }
00665                 Eeprom.EepromData.DemoSettings.FreqErrorEst = ( double )PacketStatus.Params.LoRa.FreqError * FreErrorLsb;
00666             }
00667             else // Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_GFSK
00668             {
00669                 Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Params.Gfsk.RssiAvg;
00670                 Eeprom.EepromData.DemoSettings.SnrValue = 0;
00671                 if( ( PacketStatus.Params.Gfsk.FreqError & 0x00000800 ) == 0x00000800 )
00672                 {
00673                     PacketStatus.Params.Gfsk.FreqError = 0x00000FFF - PacketStatus.Params.Gfsk.FreqError;
00674                 }
00675                 PacketStatus.Params.LoRa.FreqError = PacketStatus.Params.LoRa.FreqError / 2048;
00676                 Eeprom.EepromData.DemoSettings.FreqErrorEst = ( ( double )PacketStatus.Params.Gfsk.FreqError / 2048.0 );
00677             }
00678 
00679             DemoInternalState = PER_RX_START;
00680             if( ( BufferSize >= PER_SIZE ) && ( strncmp( ( const char* )( Buffer + 5 ), ( const char* )PerMsg, PER_SIZE ) == 0 ) )
00681             {
00682                 ComputePerPayload( Buffer, BufferSize );
00683                 refreshDisplay = 1;
00684             }
00685             else
00686             {
00687                 Eeprom.EepromData.DemoSettings.RxTimeOutCount++;
00688             }
00689             break;
00690 
00691         case APP_RX_ERROR:
00692         case APP_RX_TIMEOUT:
00693             Eeprom.EepromData.DemoSettings.RxTimeOutCount++;
00694             DemoInternalState = PER_RX_START;
00695             refreshDisplay = 1;
00696             break;
00697 
00698         case APP_TX_TIMEOUT:
00699             printf( "Failure: timeout in Tx is shorter than the packet time on air\n\r" );
00700             DemoInternalState = APP_IDLE;
00701             Eeprom.EepromData.DemoSettings.HoldDemo = true;
00702             refreshDisplay = 1;
00703             break;
00704 
00705         case APP_IDLE: // do nothing
00706             /*
00707             val = Radio.GetSysErrors( );
00708             if( val.Value != 0x0000 )
00709             {
00710                 printf(" Dev Error = 0x%04x \n\r", val.Value );
00711             }
00712             */
00713             break;
00714 
00715         default:
00716             break;
00717     }
00718     return refreshDisplay;
00719 }
00720 
00721 void ComputePerPayload( uint8_t *buffer, uint8_t bufferSize )
00722 {
00723     uint32_t i = 0;
00724 
00725     Eeprom.EepromData.DemoSettings.CntPacketRxOK++;
00726     PacketRxSequence = ( ( uint32_t )buffer[1] << 24 ) | \
00727                        ( ( uint32_t )buffer[2] << 16 ) | \
00728                        ( ( uint32_t )buffer[3] << 8 )  | \
00729                                      buffer[4];
00730 
00731     if( ( PacketRxSequence <= PacketRxSequencePrev ) || \
00732         ( PacketRxSequencePrev == 0xFFFFFFFF ) )
00733     {
00734         // Sequence went back => resynchronization
00735         // Don't count missed packets this time
00736         i = 0;
00737     }
00738     else
00739     {
00740         // Determine number of missed packets
00741         i = PacketRxSequence - PacketRxSequencePrev - 1;
00742     }
00743     // Be ready for the next
00744     PacketRxSequencePrev = PacketRxSequence;
00745     // increment 'missed' counter for the RX session
00746     Eeprom.EepromData.DemoSettings.CntPacketRxKO += i;
00747     Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0;
00748 }
00749 
00750 // ************************     Ping Pong Demo     *****************************
00751 // *                                                                           *
00752 // *                                                                           *
00753 // *                                                                           *
00754 // *****************************************************************************
00755 uint8_t RunDemoApplicationPingPong( void )
00756 {
00757     uint8_t i = 0;
00758     uint8_t refreshDisplay = 0;
00759 
00760     if( Eeprom.EepromData.DemoSettings.HoldDemo == true )
00761     {
00762         return 0;   // quit without refresh display
00763     }
00764 
00765     if( DemoRunning == false )
00766     {
00767         DemoRunning = true;
00768         TX_LED = 0;
00769         RX_LED = 0;
00770         Eeprom.EepromData.DemoSettings.CntPacketTx        = 0;
00771         Eeprom.EepromData.DemoSettings.CntPacketRxOK      = 0;
00772         Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = 0;
00773         Eeprom.EepromData.DemoSettings.CntPacketRxKO      = 0;
00774         Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave = 0;
00775         Eeprom.EepromData.DemoSettings.RxTimeOutCount     = 0;
00776 
00777         InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType );
00778 
00779         Eeprom.EepromData.DemoSettings.InterPacketDelay = GetTimeOnAir( Eeprom.EepromData.DemoSettings.ModulationType ) + RX_TX_TRANSITION_WAIT;
00780 
00781         printf( "Start RunDemoApplicationPingPong.\n\r" );
00782 
00783         if( Eeprom.EepromData.DemoSettings.Entity == MASTER )
00784         {
00785             DemoInternalState = SEND_PING_MSG;
00786             uint32_t temp = ( Eeprom.EepromData.DemoSettings.InterPacketDelay << 1 ) + RX_TIMEOUT_MARGIN;
00787             float val = ( float )temp / 1000.0;
00788             SendNextPacket.attach( &SendNextPacketEvent, val );
00789         }
00790         else
00791         {
00792             IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00793             Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00794             // Rx Single without timeout for the start
00795             RX_LED = !RX_LED;
00796             
00797             if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
00798             {
00799                 Radio.SetRx( 0x0000 );
00800             }
00801             else
00802             {
00803                 Radio.SetRxBoosted( 0x0000 );
00804             }
00805             DemoInternalState = APP_IDLE;
00806         }
00807     }
00808 
00809     Radio.ProcessIrqs( );
00810 
00811     if( Eeprom.EepromData.DemoSettings.Entity == MASTER )
00812     {
00813         switch( DemoInternalState )
00814         {
00815             case SEND_PING_MSG:
00816                 if( ( Eeprom.EepromData.DemoSettings.MaxNumPacket != 0 ) \
00817                     && ( Eeprom.EepromData.DemoSettings.CntPacketTx >= Eeprom.EepromData.DemoSettings.MaxNumPacket ) )
00818                 {
00819                     SendNextPacket.detach( );
00820                     SendNext = false;
00821                     RX_LED = 0;
00822                     TX_LED = 0;
00823                     DemoInternalState = APP_IDLE;
00824                     Radio.SetStandby( STDBY_RC );
00825                     Eeprom.EepromData.DemoSettings.HoldDemo = true;
00826                     refreshDisplay = 1;
00827                 }
00828                 else
00829                 {
00830                     if( SendNext == true )
00831                     {
00832                         SendNext = false;
00833                         Radio.SetStandby( STDBY_RC );
00834                         DemoInternalState = APP_IDLE;
00835                         Eeprom.EepromData.DemoSettings.CntPacketTx++;
00836                         // Send the next PING frame
00837                         Buffer[0] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 24 ) & 0xFF;
00838                         Buffer[1] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 16 ) & 0xFF;
00839                         Buffer[2] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 8 )  & 0xFF;
00840                         Buffer[3] = ( Eeprom.EepromData.DemoSettings.CntPacketTx & 0xFF );
00841                         Buffer[4] = PingMsg[0];
00842                         Buffer[5] = PingMsg[1];
00843                         Buffer[6] = PingMsg[2];
00844                         Buffer[7] = PingMsg[3];
00845                         for( i = 8; i < Eeprom.EepromData.DemoSettings.PayloadLength; i++ )
00846                         {
00847                             Buffer[i] = i;
00848                         }
00849                         TX_LED = !TX_LED;
00850                         IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
00851                         Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00852                         Radio.SendPayload( Buffer, Eeprom.EepromData.DemoSettings.PayloadLength, \
00853                                            Eeprom.EepromData.DemoSettings.InterPacketDelay << 6 );
00854                     }
00855                 }
00856                 break;
00857 
00858             case APP_TX:
00859                 DemoInternalState = APP_IDLE;
00860                 TX_LED = !TX_LED;
00861                 RX_LED = !RX_LED;
00862                 IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00863                 Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00864 
00865                 if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
00866                 {
00867                     Radio.SetRx( ( ( Eeprom.EepromData.DemoSettings.InterPacketDelay << 1 ) + RX_TIMEOUT_MARGIN ) << 6 );
00868                 }
00869                 else
00870                 {
00871                     Radio.SetRxBoosted( ( ( Eeprom.EepromData.DemoSettings.InterPacketDelay << 1 ) + RX_TIMEOUT_MARGIN ) << 6 );
00872                 }
00873                 break;
00874 
00875             case APP_RX:
00876                 RX_LED = !RX_LED;
00877                 Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
00878                 Radio.GetPacketStatus( &PacketStatus );
00879                 if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_LORA )
00880                 {
00881                     Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Params.LoRa.RssiPkt;
00882                     Eeprom.EepromData.DemoSettings.SnrValue = PacketStatus.Params.LoRa.SnrPkt;
00883                 }
00884                 else // Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_GFSK
00885                 {
00886                     Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Params.Gfsk.RssiAvg;
00887                     Eeprom.EepromData.DemoSettings.SnrValue = 0;
00888                 }
00889 
00890                 if( ( BufferSize >= PINGPONG_SIZE ) && ( strncmp( ( const char* )( Buffer + 8 ), ( const char* )PongMsg, PINGPONG_SIZE ) == 0 ) )
00891                 {
00892                     ComputePingPongPayload( Buffer, BufferSize );
00893                 }
00894                 else
00895                 {
00896                     Eeprom.EepromData.DemoSettings.CntPacketRxKO++;
00897                 }
00898                 DemoInternalState = SEND_PING_MSG;
00899                 refreshDisplay = 1;
00900                 break;
00901 
00902             case APP_RX_TIMEOUT:
00903             case APP_RX_ERROR:
00904                 RX_LED = !RX_LED;
00905                 Eeprom.EepromData.DemoSettings.CntPacketRxKO++;
00906                 DemoInternalState = SEND_PING_MSG;
00907                 refreshDisplay = 1;
00908                 break;
00909 
00910             case APP_TX_TIMEOUT:
00911                 printf( "Failure: timeout in Tx is shorter than the packet time on air\n\r" );
00912                 DemoInternalState = APP_IDLE;
00913                 Eeprom.EepromData.DemoSettings.HoldDemo = true;
00914                 refreshDisplay = 1;
00915                 break;
00916 
00917             case APP_IDLE: // do nothing
00918                 break;
00919 
00920             default:
00921                 break;
00922         }
00923     }
00924     else // SLAVE
00925     {
00926         switch( DemoInternalState )
00927         {
00928             case SEND_PONG_MSG:
00929                 wait_ms( RX_TX_TRANSITION_WAIT );
00930 
00931                 DemoInternalState = APP_IDLE;
00932                 // Send the next PING frame
00933                 Buffer[0]  = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 24 ) & 0xFF;
00934                 Buffer[1]  = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 16 ) & 0xFF;
00935                 Buffer[2]  = ( Eeprom.EepromData.DemoSettings.CntPacketTx >>  8 ) & 0xFF;
00936                 Buffer[3]  = ( Eeprom.EepromData.DemoSettings.CntPacketTx & 0xFF );
00937                 Buffer[4]  = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \
00938                                  Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >> 24 ) & 0xFF;
00939                 Buffer[5]  = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \
00940                                  Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >> 16 ) & 0xFF;
00941                 Buffer[6]  = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \
00942                                  Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >> 8 ) & 0xFF;
00943                 Buffer[7]  = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \
00944                                  Eeprom.EepromData.DemoSettings.RxTimeOutCount ) & 0xFF );
00945                 Buffer[8]  = PongMsg[0];
00946                 Buffer[9]  = PongMsg[1];
00947                 Buffer[10] = PongMsg[2];
00948                 Buffer[11] = PongMsg[3];
00949                 for( i = 12; i < Eeprom.EepromData.DemoSettings.PayloadLength; i++ )
00950                 {
00951                     Buffer[i] = i;
00952                 }
00953                 TX_LED = !TX_LED;
00954                 IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT;
00955                 Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00956                 Radio.SendPayload( Buffer, Eeprom.EepromData.DemoSettings.PayloadLength, \
00957                                    ( Eeprom.EepromData.DemoSettings.InterPacketDelay ) << 6 );
00958                 break;
00959 
00960             case APP_TX:
00961                 if( ( Eeprom.EepromData.DemoSettings.MaxNumPacket != 0 ) \
00962                     && ( ( Eeprom.EepromData.DemoSettings.CntPacketRxOK + Eeprom.EepromData.DemoSettings.CntPacketRxKO + \
00963                            Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >= Eeprom.EepromData.DemoSettings.MaxNumPacket ) )
00964                 {
00965                     SendNextPacket.detach( ); 
00966                     SendNext = false;
00967                     RX_LED = 0;
00968                     TX_LED = 0;
00969                     DemoInternalState = APP_IDLE;
00970                     Radio.SetStandby( STDBY_RC );
00971                     Eeprom.EepromData.DemoSettings.HoldDemo = true;
00972                     refreshDisplay = 1;
00973                 }
00974                 else
00975                 {
00976                     DemoInternalState = APP_IDLE;
00977                     TX_LED = !TX_LED;
00978                     RX_LED = !RX_LED;
00979                     IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
00980                     Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
00981                     if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
00982                     {
00983                         Radio.SetRx( ( ( Eeprom.EepromData.DemoSettings.InterPacketDelay << 1 ) + RX_TIMEOUT_MARGIN ) << 6 );
00984                     }
00985                     else
00986                     {
00987                         Radio.SetRxBoosted( ( ( Eeprom.EepromData.DemoSettings.InterPacketDelay << 1 ) + RX_TIMEOUT_MARGIN ) << 6 );
00988                     }
00989                     refreshDisplay = 1;
00990                 }
00991                 break;
00992 
00993             case APP_RX:
00994                 DemoInternalState = APP_IDLE;
00995                 RX_LED = !RX_LED;
00996                 Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE );
00997                 Radio.GetPacketStatus( &PacketStatus );
00998                 if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_LORA )
00999                 {
01000                     Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Params.LoRa.RssiPkt;
01001                     Eeprom.EepromData.DemoSettings.SnrValue = PacketStatus.Params.LoRa.SnrPkt;
01002                 }
01003                 else // Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_GFSK
01004                 {
01005                     Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Params.Gfsk.RssiAvg;
01006                     Eeprom.EepromData.DemoSettings.SnrValue = 0;
01007                 }
01008 
01009                 if( ( BufferSize >= PINGPONG_SIZE ) && ( strncmp( ( const char* )( Buffer + 4 ), ( const char* )PingMsg, PINGPONG_SIZE ) == 0 ) )
01010                 {
01011                     ComputePingPongPayload( Buffer, BufferSize );
01012                     DemoInternalState = SEND_PONG_MSG;
01013                 }
01014                 else
01015                 {
01016                     Eeprom.EepromData.DemoSettings.CntPacketRxKO++;
01017                     RX_LED = !RX_LED;
01018                     IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
01019                     Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
01020                     if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
01021                     {
01022                         Radio.SetRx( ( Eeprom.EepromData.DemoSettings.InterPacketDelay ) << 6 );
01023                     }
01024                     else
01025                     {
01026                         Radio.SetRxBoosted( ( Eeprom.EepromData.DemoSettings.InterPacketDelay ) << 6 );
01027                     }
01028                     refreshDisplay = 1;
01029                 }
01030                 break;
01031 
01032             case APP_RX_TIMEOUT:
01033             case APP_RX_ERROR:
01034                 DemoInternalState = APP_IDLE;
01035                 Eeprom.EepromData.DemoSettings.RxTimeOutCount++;
01036                 IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT;
01037                 Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
01038                 if( Eeprom.EepromData.DemoSettings.BoostedRx == false )
01039                 {
01040                     Radio.SetRx( ( ( Eeprom.EepromData.DemoSettings.InterPacketDelay << 1 ) + RX_TIMEOUT_MARGIN ) << 6 );
01041                 }
01042                 else
01043                 {
01044                     Radio.SetRxBoosted( ( ( Eeprom.EepromData.DemoSettings.InterPacketDelay << 1 ) + RX_TIMEOUT_MARGIN ) << 6 );
01045                 }
01046                 refreshDisplay = 1;
01047                 break;
01048 
01049             case APP_TX_TIMEOUT:
01050                 printf( "Failure: timeout in Tx is shorter than the packet time on air\n\r" );
01051                 DemoInternalState = APP_IDLE;
01052                 Eeprom.EepromData.DemoSettings.HoldDemo = true;
01053                 refreshDisplay = 1;
01054                 break;
01055 
01056             case APP_IDLE: // do nothing
01057                 break;
01058 
01059             default:
01060                 break;
01061         }
01062     }
01063     return refreshDisplay;
01064 }
01065 
01066 void ComputePingPongPayload( uint8_t *buffer, uint8_t bufferSize )
01067 {
01068     uint32_t i = 0;
01069 
01070     PacketRxSequence = ( ( uint32_t )buffer[0] << 24 ) | \
01071                        ( ( uint32_t )buffer[1] << 16 ) | \
01072                        ( ( uint32_t )buffer[2] << 8 )  | \
01073                                      buffer[3];
01074 
01075     if( Eeprom.EepromData.DemoSettings.Entity == MASTER )
01076     {
01077         Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave = 
01078                        ( ( uint32_t )buffer[4] << 24 ) | \
01079                        ( ( uint32_t )buffer[5] << 16 ) | \
01080                        ( ( uint32_t )buffer[6] << 8 )  | \
01081                                      buffer[7];
01082         if( PacketRxSequence > Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave )
01083         {
01084             Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = PacketRxSequence - \
01085                 Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave;
01086         }
01087         else
01088         {
01089             Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = 0;
01090         }
01091         
01092         if( PacketRxSequence == Eeprom.EepromData.DemoSettings.CntPacketTx )
01093         {
01094             Eeprom.EepromData.DemoSettings.CntPacketRxOK += 1;
01095         }
01096         else
01097         {
01098             Eeprom.EepromData.DemoSettings.CntPacketRxKO += 1;
01099         }
01100     }
01101     else
01102     {
01103         Eeprom.EepromData.DemoSettings.CntPacketRxOK += 1;
01104         if( ( PacketRxSequence <= PacketRxSequencePrev ) || \
01105             ( PacketRxSequencePrev == 0 ) )
01106         {
01107             // Sequence went back => resynchronization
01108             // Don't count missed packets this time
01109             i = 0;
01110         }
01111         else
01112         {
01113             // Determine number of missed packets
01114             i = PacketRxSequence - PacketRxSequencePrev - 1;
01115         }
01116         // Be ready for the next
01117         PacketRxSequencePrev = PacketRxSequence;
01118         Eeprom.EepromData.DemoSettings.CntPacketTx = PacketRxSequence;
01119         // increment 'missed' counter for the RX session
01120         Eeprom.EepromData.DemoSettings.CntPacketRxKO += i;
01121         Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0;
01122     }
01123 }
01124 
01125 // ************************        Utils            ****************************
01126 // *                                                                           *
01127 // *                                                                           *
01128 // *                                                                           *
01129 // *****************************************************************************
01130 
01131 uint8_t GetConnectedDevice( void )
01132 {
01133     return( Radio.GetDeviceType( ) );
01134 }
01135 
01136 uint8_t GetMatchingFrequency( void )
01137 {
01138     return( Radio.GetFreqSelect( ) );
01139 }
01140 
01141 void InitDemoApplication( void )
01142 {
01143     RX_LED = 1;
01144     TX_LED = 1;
01145 
01146     Radio.Init( );
01147 
01148     // Can also be set in LDO mode but consume more power
01149     Radio.SetRegulatorMode( ( RadioRegulatorMode_t )Eeprom.EepromData.DemoSettings.RadioPowerMode );
01150     Radio.SetStandby( STDBY_RC );
01151 
01152     memset( &Buffer, 0x00, BufferSize );
01153     
01154     RX_LED = 0;
01155     TX_LED = 0;
01156 
01157     PacketRxSequence = 0;
01158     PacketRxSequencePrev = 0;
01159     Eeprom.EepromData.DemoSettings.CntPacketTx    = 0;
01160     Eeprom.EepromData.DemoSettings.CntPacketRxOK  = 0;
01161     Eeprom.EepromData.DemoSettings.CntPacketRxKO  = 0;
01162     Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0;
01163 }
01164 
01165 void StopDemoApplication( void )
01166 {
01167     if( DemoRunning == true )
01168     {
01169         Radio.CheckDeviceReady( );
01170 
01171         RX_LED = 0;
01172         TX_LED = 0;
01173         DemoRunning = false;
01174         SendNext = false;
01175         PacketRxSequence = 0;
01176         PacketRxSequencePrev = 0;
01177         Eeprom.EepromData.DemoSettings.CntPacketTx    = 0;
01178         Eeprom.EepromData.DemoSettings.CntPacketRxOK  = 0;
01179         Eeprom.EepromData.DemoSettings.CntPacketRxKO  = 0;
01180         Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0;
01181         
01182         DemoInternalState = APP_IDLE;
01183         Radio.SetStandby( STDBY_RC );
01184         Radio.ClearIrqStatus( IRQ_RADIO_ALL );
01185         SendNextPacket.detach( ); 
01186     }
01187 }
01188 
01189 /*
01190  * Function still being implemented >>> To be completed 
01191  * WARNING: Computation is in float and his really slow
01192  * LongInterLeaving vs LegacyInterLeaving has no influence on TimeOnAir.
01193  */
01194 uint16_t GetTimeOnAir( uint8_t modulation )
01195 {
01196     uint16_t result = 2000;
01197     uint8_t LowDatarateOptimize = 0;
01198 
01199     if( modulation == PACKET_TYPE_LORA )
01200     {
01201         volatile double loraBw = 0.0;
01202         volatile double FreqErrorUnits = 0.0;
01203         
01204         switch( Eeprom.EepromData.ModulationParams.Params.LoRa.Bandwidth )
01205         {
01206             case LORA_BW_500:
01207                 loraBw = 500e3;
01208                 break;
01209 
01210             case LORA_BW_250:
01211                 loraBw = 250e3;
01212                 break;
01213 
01214             case LORA_BW_125:
01215                 loraBw = 125e3;
01216                 break;
01217 
01218             case LORA_BW_062:
01219                 loraBw = 62e3;
01220                 break;
01221 
01222             case LORA_BW_041:
01223                 loraBw = 41e3;
01224                 break;
01225 
01226             case LORA_BW_031:
01227                 loraBw = 31e3;
01228                 break;
01229 
01230             case LORA_BW_020:
01231                 loraBw = 20e3;
01232                 break;
01233 
01234             case LORA_BW_015:
01235                 loraBw = 15e3;
01236                 break;
01237 
01238             case LORA_BW_010:
01239                 loraBw = 10e3;
01240                 break;
01241 
01242             case LORA_BW_007:
01243                 loraBw = 7e3;
01244                 break;
01245 
01246             default:
01247                 loraBw = 7e3;
01248                 break;
01249         }
01250 
01251         /* Used to compute the freq Error */
01252         FreqErrorUnits = FREQ_ERR;
01253         FreErrorLsb = FreqErrorUnits * ( ( double )loraBw / 1000 ) / 500;
01254 
01255         float ts = 1 << Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor; // time for one symbol in ms
01256               ts = (float)ts / (float)loraBw;
01257               ts = ts * 1000; // from seconds to miliseconds
01258 
01259         float tPreamble = ( Eeprom.EepromData.PacketParams.Params.LoRa.PreambleLength + 4.25 + ( ( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor > 6 ) ? 2 : 0 )) * ts; // time of preamble
01260 
01261         switch( Eeprom.EepromData.ModulationParams.Params.LoRa.Bandwidth )
01262         {
01263             case LORA_BW_500:
01264                 break;
01265 
01266             case LORA_BW_250:
01267                 if( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF12 )
01268                 {
01269                     LowDatarateOptimize = 1;
01270                 }
01271                 break;
01272 
01273             case LORA_BW_125:
01274                 if( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >= LORA_SF11 )
01275                 {
01276                     LowDatarateOptimize = 1;
01277                 }
01278                 break;
01279 
01280             case LORA_BW_062:
01281                 if( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >= LORA_SF10 )
01282                 {
01283                     LowDatarateOptimize = 1;
01284                 }
01285                 break;
01286 
01287             case LORA_BW_041:
01288             case LORA_BW_031:
01289                 if( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >= LORA_SF9 )
01290                 {
01291                     LowDatarateOptimize = 1;
01292                 }
01293                 break;
01294 
01295             case LORA_BW_020:
01296             case LORA_BW_015:
01297                 if( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >= LORA_SF8 )
01298                 {
01299                     LowDatarateOptimize = 1;
01300                 }
01301                 break;
01302 
01303             case LORA_BW_010:
01304             case LORA_BW_007:
01305                 if( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >= LORA_SF7 )
01306                 {
01307                     LowDatarateOptimize = 1;
01308                 }
01309                 break;
01310         }
01311 
01312         float nData = ceil( ( float )( ( 8 * Eeprom.EepromData.PacketParams.Params.LoRa.PayloadLength +                                           \
01313                        16 * ( ( Eeprom.EepromData.PacketParams.Params.LoRa.CrcMode == LORA_CRC_OFF ) ? 0 : 1 ) +                \
01314                        ( ( Eeprom.EepromData.PacketParams.Params.LoRa.HeaderType == LORA_PACKET_VARIABLE_LENGTH ) ? 20 : 0 ) -  \
01315                        ( 4 * Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor ) + 8 -                             \
01316                        ( 8 *( ( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor > 6 ) ? 1 : 0 ) ) ) / 4 ) );
01317 
01318                nData = ceil( ( float )nData / ( ( float )( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor - \
01319                               ( LowDatarateOptimize * 2 ) ) ) * ( ( Eeprom.EepromData.ModulationParams.Params.LoRa.CodingRate % 4 ) + 4 ) );
01320 
01321         float tPayload = nData * ts;
01322 
01323         float tHeader = 8 * ts;
01324         // Time on air [ms]
01325         float ToA = ceil( tPreamble + tPayload + tHeader );
01326 
01327         result = ( uint16_t )ToA + ( ( uint16_t )ToA >> 1 );   // Set some margin
01328     }
01329     else if( modulation == PACKET_TYPE_GFSK )
01330     {
01331         uint16_t packetBitCount = Eeprom.EepromData.PacketParams.Params.Gfsk.PreambleLength;
01332 
01333         packetBitCount += ( Eeprom.EepromData.PacketParams.Params.Gfsk.SyncWordLength + 1 );
01334         packetBitCount += Eeprom.EepromData.PacketParams.Params.Gfsk.PayloadLength + 3;
01335         packetBitCount *= 8;
01336         // 1500 = 1000 * 1.5 : 1000 for translate s in ms and 1.5 is some margin
01337         result = ( uint16_t )( ceil( 1500 * ( float )packetBitCount / Eeprom.EepromData.ModulationParams.Params.Gfsk.BitRate ) );
01338     }
01339     return result;
01340 }
01341 
01342 void InitializeDemoParameters( uint8_t modulation )
01343 {
01344     Radio.SetStandby( STDBY_RC );
01345 
01346     Radio.SetRegulatorMode( ( RadioRegulatorMode_t )Eeprom.EepromData.DemoSettings.RadioPowerMode );
01347 
01348     printf("> InitializeDemoParameters\n\r");
01349     if( modulation == PACKET_TYPE_LORA )
01350     {
01351         printf("set param LORA for demo\n\r");
01352         ModulationParams.PacketType = PACKET_TYPE_LORA;
01353         PacketParams.PacketType     = PACKET_TYPE_LORA;
01354 
01355         ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t ) Eeprom.EepromData.DemoSettings.ModulationParam1;
01356         ModulationParams.Params.LoRa.Bandwidth       = ( RadioLoRaBandwidths_t )       Eeprom.EepromData.DemoSettings.ModulationParam2;
01357         ModulationParams.Params.LoRa.CodingRate      = ( RadioLoRaCodingRates_t )      Eeprom.EepromData.DemoSettings.ModulationParam3;
01358 
01359         PacketParams.Params.LoRa.PreambleLength      =                                 Eeprom.EepromData.DemoSettings.PacketParam1;
01360         PacketParams.Params.LoRa.HeaderType          = ( RadioLoRaPacketLengthsMode_t )Eeprom.EepromData.DemoSettings.PacketParam2;
01361         PacketParams.Params.LoRa.PayloadLength       =                                 Eeprom.EepromData.DemoSettings.PacketParam3;
01362         PacketParams.Params.LoRa.CrcMode             = ( RadioLoRaCrcModes_t )         Eeprom.EepromData.DemoSettings.PacketParam4;
01363         PacketParams.Params.LoRa.InvertIQ            = ( RadioLoRaIQModes_t )          Eeprom.EepromData.DemoSettings.PacketParam5;
01364 
01365         Eeprom.EepromData.DemoSettings.PayloadLength = PacketParams.Params.LoRa.PayloadLength;
01366         
01367         if( ( ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) || ( ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) )
01368         {
01369             if( PacketParams.Params.LoRa.PreambleLength < 12 )
01370             {
01371                 PacketParams.Params.LoRa.PreambleLength = 12;
01372             }
01373         }
01374     }
01375     else// if( modulation == PACKET_TYPE_GFSK )
01376     {
01377         printf("set param GFSK for demo\n\r");
01378         ModulationParams.PacketType = PACKET_TYPE_GFSK;
01379         PacketParams.PacketType     = PACKET_TYPE_GFSK;
01380 
01381         ModulationParams.Params.Gfsk.BitRate           =                             Eeprom.EepromData.DemoSettings.ModulationParam1;
01382         ModulationParams.Params.Gfsk.Fdev              =                             Eeprom.EepromData.DemoSettings.ModulationParam2;
01383         ModulationParams.Params.Gfsk.ModulationShaping = ( RadioModShapings_t )      Eeprom.EepromData.DemoSettings.ModulationParam3;
01384         ModulationParams.Params.Gfsk.Bandwidth         = ( RadioRxBandwidth_t )      Eeprom.EepromData.DemoSettings.ModulationParam4;
01385         PacketParams.Params.Gfsk.PreambleLength        =                             Eeprom.EepromData.DemoSettings.PacketParam1;
01386         PacketParams.Params.Gfsk.PreambleMinDetect     = ( RadioPreambleDetection_t )Eeprom.EepromData.DemoSettings.PacketParam2;
01387         PacketParams.Params.Gfsk.SyncWordLength        =                             Eeprom.EepromData.DemoSettings.PacketParam3;
01388         PacketParams.Params.Gfsk.AddrComp              = ( RadioAddressComp_t )      Eeprom.EepromData.DemoSettings.PacketParam4;
01389         PacketParams.Params.Gfsk.HeaderType            = ( RadioPacketLengthModes_t )Eeprom.EepromData.DemoSettings.PacketParam5;
01390         PacketParams.Params.Gfsk.PayloadLength         =                             Eeprom.EepromData.DemoSettings.PacketParam6;
01391 
01392         PacketParams.Params.Gfsk.CrcLength             = ( RadioCrcTypes_t )         Eeprom.EepromData.DemoSettings.PacketParam7;
01393         PacketParams.Params.Gfsk.DcFree                = ( RadioDcFree_t )           Eeprom.EepromData.DemoSettings.PacketParam8;
01394 
01395         Eeprom.EepromData.DemoSettings.PayloadLength = PacketParams.Params.Gfsk.PayloadLength;
01396     }
01397 
01398     Radio.SetStandby( STDBY_RC );
01399     Radio.ClearIrqStatus( IRQ_RADIO_ALL );
01400     Radio.SetPacketType( ModulationParams.PacketType );
01401     Radio.SetModulationParams( &ModulationParams );
01402     Radio.SetPacketParams( &PacketParams );
01403 
01404     Radio.SetRfFrequency( Eeprom.EepromData.DemoSettings.Frequency );
01405     Radio.SetBufferBaseAddresses( 0x00, 0x00 );
01406     
01407     
01408     Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_200_US );
01409 
01410     // only used in GFSK
01411     Radio.SetSyncWord( ( uint8_t[] ){ 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 } );
01412     Radio.SetWhiteningSeed( 0x01FF );
01413 
01414     RX_LED = 0;
01415     TX_LED = 0;
01416 }
01417 
01418 /*!
01419  * \brief Callback of ticker PerSendNextPacket
01420  */
01421 void SendNextPacketEvent( void )
01422 {
01423     SendNext = true;
01424 }
01425 
01426 void LedBlink( void )
01427 {
01428     if( ( TX_LED == 0 ) && ( RX_LED == 0 ) )
01429     {
01430         TX_LED = 1;
01431     }
01432     else if( ( TX_LED == 1 ) && ( RX_LED == 0 ) )
01433     {
01434         RX_LED = 1;
01435     }
01436     else if( ( TX_LED == 1 ) && ( RX_LED == 1 ) )
01437     {
01438         TX_LED = 0;
01439     }
01440     else
01441     {
01442         RX_LED = 0;
01443     }
01444 }
01445 
01446 // ************************     Radio Callbacks     ****************************
01447 // *                                                                           *
01448 // * These functions are called through function pointer by the Radio low      *
01449 // * level drivers                                                             *
01450 // *                                                                           *
01451 // *****************************************************************************
01452 void OnTxDone( void )
01453 {
01454     DemoInternalState = APP_TX;
01455 }
01456 
01457 void OnRxDone( void )
01458 {
01459     DemoInternalState = APP_RX;
01460 }
01461 
01462 void OnTxTimeout( void )
01463 {
01464     DemoInternalState = APP_TX_TIMEOUT;
01465 }
01466 
01467 void OnRxTimeout( void )
01468 {
01469     DemoInternalState = APP_RX_TIMEOUT;
01470 }
01471 
01472 void OnRxError( IrqErrorCode_t errorCode )
01473 {
01474     DemoInternalState = APP_RX_ERROR;
01475     
01476     if( errorCode == IRQ_HEADER_ERROR_CODE )
01477     {
01478 #ifdef ADV_DEBUG
01479         printf( ">> IRQ_HEADER_ERROR_CODE\n\r" );
01480 #endif
01481     }
01482     else if( errorCode == IRQ_SYNCWORD_ERROR_CODE )
01483     {
01484 #ifdef ADV_DEBUG
01485         printf( ">> IRQ_SYNCWORD_ERROR_CODE\n\r" );
01486 #endif
01487     }
01488     else if( errorCode == IRQ_CRC_ERROR_CODE )
01489     {
01490 #ifdef ADV_DEBUG
01491         printf( ">> IRQ_CRC_ERROR_CODE\n\r" );
01492 #endif
01493     }
01494     else
01495     {
01496 #ifdef ADV_DEBUG
01497         printf( "unknown error\n\r" );
01498 #endif
01499     }
01500     Radio.GetPacketStatus( &PacketStatus );
01501 }
01502 
01503 void OnCadDone( bool channelActivityDetected )
01504 {
01505     if( channelActivityDetected == true )
01506     {
01507         DemoInternalState = CAD_DONE_CHANNEL_DETECTED;
01508     }
01509     else
01510     {
01511         DemoInternalState = CAD_DONE;
01512     }
01513 }