
1st Fork
Dependencies: mbed QEI DmTftLibrary
Diff: Demo/DemoApplication.cpp
- Revision:
- 0:9c0917bfde97
- Child:
- 1:dbcb3698f73a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Demo/DemoApplication.cpp Mon Mar 13 15:12:05 2017 +0000 @@ -0,0 +1,2044 @@ +/* + ______ _ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2016 Semtech + +Description: PingPong, PER and Ranging demo implementation. + +Maintainer: Gregory Cristian & Gilbert Menth +*/ + +#include "mbed.h" +#include "radio.h" +#include "sx1280-hal.h" +#include "Eeprom.h" +#include "DemoApplication.h" +#include "FreqLUT.h" + +/*! + * \brief Defines the local payload buffer size + */ +#define BUFFER_SIZE 255 + +/*! + * \brief Defines the size of the token defining message type in the payload + * cf. above. + */ +#define PINGPONG_SIZE 4 +#define PER_SIZE 3 + +/*! + * \brief Define time used in PingPong demo to synch with cycle + * RX_TIMEOUT_MARGIN is the free time between each cycle (time reserve) + */ +#define RX_TIMEOUT_MARGIN 50 // ms +#define RX_TX_TRANSITION_WAIT 5 // ms + +/*! + * \brief Size of ticks (used for Tx and Rx timeout) + */ +#define RX_TIMEOUT_TICK_SIZE RADIO_TICK_SIZE_1000_US + +#define RNG_TIMER_MS 384 // ms +#define RNG_COM_TIMEOUT 100 // ms + +/*! + * \brief Ranging raw factors + * SF5 SF6 SF7 SF8 SF9 SF10 + */ +const uint16_t RNG_CALIB_0400[] = { 10299, 10271, 10244, 10242, 10230, 10246 }; +const uint16_t RNG_CALIB_0800[] = { 11486, 11474, 11453, 11426, 11417, 11401 }; +const uint16_t RNG_CALIB_1600[] = { 13308, 13493, 13528, 13515, 13430, 13376 }; +const double RNG_FGRAD_0400[] = { -0.148, -0.214, -0.419, -0.853, -1.686, -3.423 }; +const double RNG_FGRAD_0800[] = { -0.041, -0.811, -0.218, -0.429, -0.853, -1.737 }; +const double RNG_FGRAD_1600[] = { 0.103, -0.041, -0.101, -0.211, -0.424, -0.87 }; + +/*! + * \brief Define the possible message type for the Ping-Pong and PER apps + */ +const uint8_t PingMsg[] = "PING"; +const uint8_t PongMsg[] = "PONG"; +const uint8_t PerMsg[] = "PER"; + +const uint32_t RefreshScreenDelayMs = 300; // in ms + +/*! + * \brief Backup registers for patchRAM + */ +static uint8_t BackupReg_1 = 0x00; +static uint8_t BackupReg_2 = 0x00; +static uint8_t BackupReg_3 = 0x00; +static uint8_t BackupReg_4 = 0x00; +static uint8_t BackupReg_5 = 0x00; +static uint8_t BackupReg_6 = 0x00; + +/*! + * \brief Buffer and its size + */ +uint8_t BufferSize = BUFFER_SIZE; +uint8_t Buffer[BUFFER_SIZE]; + +static uint8_t CurrentChannel; +static uint8_t MeasuredChannels; +int RngResultIndex; +double RawRngResults[DEMO_RNG_CHANNELS_COUNT_MAX]; + +/*! + * \brief Function to be executed on Radio Tx Done event + */ +void OnTxDone( void ); + +/*! + * \brief Function to be executed on Radio Rx Done event + */ +void OnRxDone( void ); + +/*! + * \brief Function executed on Radio Tx Timeout event + */ +void OnTxTimeout( void ); + +/*! + * \brief Function executed on Radio Rx Timeout event + */ +void OnRxTimeout( void ); + +/*! + * \brief Function executed on Radio Rx Error event + */ +void OnRxError( IrqErrorCode_t ); + +/*! + * \brief Function executed on Radio Rx Error event + */ +void OnRangingDone( IrqRangingCode_t ); + +/*! + * \brief All the callbacks are stored in a structure + */ +RadioCallbacks_t Callbacks = +{ + &OnTxDone, // txDone + &OnRxDone, // rxDone + NULL, // syncWordDone + NULL, // headerDone + &OnTxTimeout, // txTimeout + &OnRxTimeout, // rxTimeout + &OnRxError, // rxError + &OnRangingDone, // rangingDone + NULL, // cadDone +}; + +/*! + * \brief Define IO and callbacks for radio + * mosi, miso, sclk, nss, busy, dio1, dio2, dio3, rst, callbacks + */ +SX1280Hal Radio( D11, D12, D13, D7, D3, D5, NC, NC, A0, &Callbacks ); + +/*! + * \brief Control the Antenna Diversity switch + */ +DigitalOut ANT_SW( A3 ); + +/*! + * \brief Tx LED toggling on transmition success + */ +DigitalOut TX_LED( A4 ); + +/*! + * \brief Rx LED toggling on reception success + */ +DigitalOut RX_LED( A5 ); + +/*! + * \brief Mask of IRQs + */ +uint16_t IrqMask = 0x0000; + +/*! + * \brief Locals parameters and status for radio API + * NEED TO BE OPTIMIZED, COPY OF STUCTURE ALREADY EXISTING + */ +PacketParams_t PacketParams; +PacketStatus_t PacketStatus; +ModulationParams_t ModulationParams; + +/*! + * \brief Flag to indicate if the demo is already running + */ +static bool DemoRunning = false; + +/*! + * \brief Flag holding the current internal state of the demo application + */ +static uint8_t DemoInternalState = APP_IDLE; + +/*! + * \brief Ticker for master to synch Tx frames. Flags for PER and PingPong demo + * for Synch TX in cycle. + */ +Ticker SendNextPacket; +static bool SendNext = false; + +/*! + * \brief Hold last Rx packet number to compute PER in PER and PingPong demo + */ +static uint32_t PacketRxSequence = 0; +static uint32_t PacketRxSequencePrev = 0; + + +void SetAntennaSwitch( void ); +void LedBlink( void ); +void InitializeDemoParameters( uint8_t modulation ); +uint16_t GetTimeOnAir( uint8_t modulation ); +void SendNextPacketEvent( void ); +uint8_t CheckDistance( void ); + +// ************************** RF Test Demo ****************************** +// * * +// * * +// * * +// ***************************************************************************** + +uint8_t RunDemoSleepMode( void ) +{ + SleepParams_t SleepParam; + + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; + } + if( DemoRunning == false ) + { + DemoRunning = true; + InitializeDemoParameters( PACKET_TYPE_LORA ); + TX_LED = 0; + RX_LED = 0; + SleepParam.WakeUpRTC = 0; //!< Get out of sleep mode if wakeup signal received from RTC + SleepParam.InstructionRamRetention = 0; //!< InstructionRam is conserved during sleep + SleepParam.DataBufferRetention = 0; //!< Data buffer is conserved during sleep + SleepParam.DataRamRetention = 0; //!< Data ram is conserved during sleep + Radio.SetSleep( SleepParam ); + } + else + { + LedBlink( ); + } + return 0; +} + +uint8_t RunDemoStandbyRcMode( void ) +{ + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; + } + if( DemoRunning == false ) + { + DemoRunning = true; + InitializeDemoParameters( PACKET_TYPE_LORA ); + TX_LED = 0; + RX_LED = 0; + Radio.SetRegulatorMode( ( RadioRegulatorModes_t )Eeprom.EepromData.DemoSettings.RadioPowerMode ); + Radio.SetStandby( STDBY_RC ); + DemoRunning = true; + } + else + { + LedBlink( ); + } + return 0; +} + +uint8_t RunDemoStandbyXoscMode( void ) +{ + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; + } + if( DemoRunning == false ) + { + DemoRunning = true; + InitializeDemoParameters( PACKET_TYPE_LORA ); + TX_LED = 0; + RX_LED = 0; + Radio.SetRegulatorMode( ( RadioRegulatorModes_t )Eeprom.EepromData.DemoSettings.RadioPowerMode ); + Radio.SetStandby( STDBY_XOSC ); + DemoRunning = true; + } + else + { + LedBlink( ); + } + return 0; +} + +uint8_t RunDemoTxCw( void ) +{ + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; + } + if( DemoRunning == false ) + { + DemoRunning = true; + InitializeDemoParameters( PACKET_TYPE_LORA ); + TX_LED = 0; + RX_LED = 0; + SetAntennaSwitch( ); + Radio.SetStandby( STDBY_RC ); + Radio.SetRegulatorMode( ( RadioRegulatorModes_t )Eeprom.EepromData.DemoSettings.RadioPowerMode ); + Radio.SetRfFrequency( Eeprom.EepromData.DemoSettings.Frequency ); + Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_20_US ); + Radio.SetTxContinuousWave( ); + DemoRunning = true; + } + else + { + LedBlink( ); + } + return 0; +} + +uint8_t RunDemoTxContinuousModulation( void ) +{ + uint8_t localPayloadSize = 250; + uint8_t i = 0; + + if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_RANGING ) + { + Eeprom.EepromData.DemoSettings.ModulationType = PACKET_TYPE_LORA; + } + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; + } + + if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_FLRC ) + { + localPayloadSize = 120; // Encoded in 4/8 so 240 bytes in total + } + if( DemoRunning == false ) + { + DemoRunning = true; + + TX_LED = 0; + RX_LED = 0; + + InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType ); + + // Send the next PING frame + IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + for( i = 0; i < localPayloadSize; i++ ) + { + Buffer[i] = ( uint8_t )rand( ); + } +// Radio.SetAutoFS( true ); // no need to relock the PLL between packets + Radio.SendPayload( Buffer, localPayloadSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, 10000 } ); + DemoInternalState = APP_IDLE; + } + else + { + switch( DemoInternalState ) + { + case APP_RX: + break; + + case APP_TX: + DemoInternalState = APP_IDLE; + LedBlink( ); + // Send the next frame + IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + for( i = 0; i < localPayloadSize; i++ ) + { + Buffer[i] = ( uint8_t )rand( ); + } +// Radio.SetAutoFS( true ); // no need to relock the PLL between packets + Radio.SendPayload( Buffer, localPayloadSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, 0xFFFF } ); + break; + + case APP_RX_TIMEOUT: + DemoInternalState = APP_IDLE; + break; + + case APP_RX_ERROR: + DemoInternalState = APP_IDLE; + break; + + case APP_TX_TIMEOUT: + DemoInternalState = APP_IDLE; + break; + + case APP_IDLE: + break; + + default: + break; + } + } + return 0; +} + +// ************************* PER Demo ****************************** +// * * +// * * +// * * +// ***************************************************************************** +uint8_t RunDemoApplicationPer( void ) +{ + uint8_t i = 0; + uint8_t refreshDisplay = 0; + + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; + } + + if( DemoRunning == false ) + { + DemoRunning = true; + + printf( "Start RunDemoApplicationPer\n\r" ); + + TX_LED = 0; + RX_LED = 0; + SetAntennaSwitch( ); + Eeprom.EepromData.DemoSettings.CntPacketTx = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxOK = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxKO = 0; + Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0; + + InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType ); + + Eeprom.EepromData.DemoSettings.InterPacketDelay = GetTimeOnAir( Eeprom.EepromData.DemoSettings.ModulationType ) + RefreshScreenDelayMs; + + if( Eeprom.EepromData.DemoSettings.Entity == MASTER ) + { + SendNextPacket.attach_us( &SendNextPacketEvent, Eeprom.EepromData.DemoSettings.InterPacketDelay * 1000 ); + DemoInternalState = APP_TX; + } + else + { + IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + // Rx Single without timeout for the start + Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0x0000 } ); + DemoInternalState = APP_IDLE; + } + } + + if( Eeprom.EepromData.DemoSettings.MaxNumPacket > 0 ) // != Infinite + { + if( ( Eeprom.EepromData.DemoSettings.CntPacketRxOK + \ + Eeprom.EepromData.DemoSettings.CntPacketRxKO + \ + Eeprom.EepromData.DemoSettings.RxTimeOutCount) >= \ + Eeprom.EepromData.DemoSettings.MaxNumPacket ) + { + RX_LED = 0; + TX_LED = 0; + DemoInternalState = APP_IDLE; + Radio.SetStandby( STDBY_RC ); + SendNextPacket.detach( ); + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; + } + } + + switch( DemoInternalState ) + { + case PER_TX_START: + Eeprom.EepromData.DemoSettings.CntPacketTx++; + DemoInternalState = APP_IDLE; + + Buffer[0] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 24 ) & 0xFF; + Buffer[1] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 16 ) & 0xFF; + Buffer[2] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 8 ) & 0xFF; + Buffer[3] = Eeprom.EepromData.DemoSettings.CntPacketTx & 0xFF; + Buffer[4] = PerMsg[0]; + Buffer[5] = PerMsg[1]; + Buffer[6] = PerMsg[2]; + for( i = 7; i < Eeprom.EepromData.DemoSettings.PayloadLength; i++ ) + { + Buffer[i] = i; + } + TX_LED = !TX_LED; + IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SendPayload( Buffer, Eeprom.EepromData.DemoSettings.PayloadLength, \ + ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay } ); + break; + + case PER_RX_START: + IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay + RX_TIMEOUT_MARGIN } ); + DemoInternalState = APP_IDLE; + break; + + case APP_TX: + if( SendNext == true ) + { + SendNext = false; + if( Eeprom.EepromData.DemoSettings.MaxNumPacket == 0 ) + { + DemoInternalState = PER_TX_START; // Infinite -> send next + refreshDisplay = 1; + } + else if( Eeprom.EepromData.DemoSettings.CntPacketTx < \ + Eeprom.EepromData.DemoSettings.MaxNumPacket ) + { + DemoInternalState = PER_TX_START; // MaxNumPacket not sent + refreshDisplay = 1; + } + else // MaxNumPacket sent -> end of demo + { + RX_LED = 0; + TX_LED = 0; + DemoInternalState = APP_IDLE; + Radio.SetStandby( STDBY_RC ); + SendNextPacket.detach( ); + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; + } + } + break; + + case APP_RX: + RX_LED = !RX_LED; + Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); + Radio.GetPacketStatus( &PacketStatus ); + if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_LORA ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.LoRa.RssiPkt; + Eeprom.EepromData.DemoSettings.SnrValue = PacketStatus.LoRa.SnrPkt; + } + else if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_FLRC ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Flrc.RssiSync; + Eeprom.EepromData.DemoSettings.SnrValue = 0; + } + else if( Eeprom.EepromData.DemoSettings.ModulationType == PACKET_TYPE_GFSK ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Gfsk.RssiSync; + Eeprom.EepromData.DemoSettings.SnrValue = 0; + } + DemoInternalState = PER_RX_START; + if( ( BufferSize >= PER_SIZE ) && ( strncmp( ( const char* )( Buffer + 4 ), ( const char* )PerMsg, PER_SIZE ) == 0 ) ) + { + ComputePerPayload( Buffer, BufferSize ); + refreshDisplay = 1; + } + else + { + Eeprom.EepromData.DemoSettings.RxTimeOutCount++; + } + break; + + case APP_RX_ERROR: + case APP_RX_TIMEOUT: + Eeprom.EepromData.DemoSettings.RxTimeOutCount++; + DemoInternalState = PER_RX_START; + refreshDisplay = 1; + break; + + case APP_TX_TIMEOUT: + printf( "Failure: timeout in Tx is shorter than the packet time on air\n\r" ); + DemoInternalState = APP_IDLE; + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; + break; + + case APP_IDLE: // do nothing + break; + + default: + break; + } + return refreshDisplay; +} + +void ComputePerPayload( uint8_t *buffer, uint8_t bufferSize ) +{ + uint32_t i = 0; + + Eeprom.EepromData.DemoSettings.CntPacketRxOK++; + PacketRxSequence = ( ( uint32_t )buffer[0] << 24 ) | \ + ( ( uint32_t )buffer[1] << 16 ) | \ + ( ( uint32_t )buffer[2] << 8 ) | \ + buffer[3]; + + if( ( PacketRxSequence <= PacketRxSequencePrev ) || \ + ( PacketRxSequencePrev == 0 ) ) + { + // Sequence went back => resynchronization + // Don't count missed packets this time + i = 0; + } + else + { + // Determine number of missed packets + i = PacketRxSequence - PacketRxSequencePrev - 1; + } + // Be ready for the next + PacketRxSequencePrev = PacketRxSequence; + // increment 'missed' counter for the RX session + Eeprom.EepromData.DemoSettings.CntPacketRxKO += i; + Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0; +} + +// ************************ Ping Pong Demo ***************************** +// * * +// * * +// * * +// ***************************************************************************** +uint8_t RunDemoApplicationPingPong( void ) +{ + uint8_t i = 0; + uint8_t refreshDisplay = 0; + + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; // quit without refresh display + } + + if( DemoRunning == false ) + { + DemoRunning = true; + TX_LED = 0; + RX_LED = 0; + SetAntennaSwitch( ); + Eeprom.EepromData.DemoSettings.CntPacketTx = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxOK = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxKO = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave = 0; + Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0; + + InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType ); + + Eeprom.EepromData.DemoSettings.InterPacketDelay = ( 2 * \ + GetTimeOnAir( Eeprom.EepromData.DemoSettings.ModulationType ) ) + \ + RX_TIMEOUT_MARGIN + RefreshScreenDelayMs; + + printf( "Start RunDemoApplicationPingPong.\n\r" ); + if( Eeprom.EepromData.DemoSettings.Entity == MASTER ) + { + DemoInternalState = SEND_PING_MSG; + SendNextPacket.attach_us( &SendNextPacketEvent, \ + ( Eeprom.EepromData.DemoSettings.InterPacketDelay * 1000 ) ); + } + else + { + IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + // Rx Single without timeout for the start + RX_LED = !RX_LED; + Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0x0000 } ); + DemoInternalState = APP_IDLE; + } + } + + if( Eeprom.EepromData.DemoSettings.Entity == MASTER ) + { + switch( DemoInternalState ) + { + case SEND_PING_MSG: + if( ( Eeprom.EepromData.DemoSettings.MaxNumPacket != 0 ) \ + && ( Eeprom.EepromData.DemoSettings.CntPacketTx >= Eeprom.EepromData.DemoSettings.MaxNumPacket ) ) + { + SendNextPacket.detach( ); + SendNext = false; + RX_LED = 0; + TX_LED = 0; + DemoInternalState = APP_IDLE; + Radio.SetStandby( STDBY_RC ); + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; + } + else + { + if( SendNext == true ) + { + SendNext = false; + + DemoInternalState = APP_IDLE; + Eeprom.EepromData.DemoSettings.CntPacketTx++; + // Send the next PING frame + Buffer[0] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 24 ) & 0xFF; + Buffer[1] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 16 ) & 0xFF; + Buffer[2] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 8 ) & 0xFF; + Buffer[3] = ( Eeprom.EepromData.DemoSettings.CntPacketTx & 0xFF ); + Buffer[4] = PingMsg[0]; + Buffer[5] = PingMsg[1]; + Buffer[6] = PingMsg[2]; + Buffer[7] = PingMsg[3]; + for( i = 8; i < Eeprom.EepromData.DemoSettings.PayloadLength; i++ ) + { + Buffer[i] = i; + } + TX_LED = !TX_LED; + IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SendPayload( Buffer, Eeprom.EepromData.DemoSettings.PayloadLength, \ + ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay - \ + ( RX_TIMEOUT_MARGIN / 2 ) } ); + } + } + break; + + case APP_TX: + DemoInternalState = APP_IDLE; + TX_LED = !TX_LED; + RX_LED = !RX_LED; + IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay - \ + ( RX_TIMEOUT_MARGIN / 2 ) } ); + break; + + case APP_RX: + RX_LED = !RX_LED; + Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); + Radio.GetPacketStatus( &PacketStatus ); + if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_LORA ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.LoRa.RssiPkt; + Eeprom.EepromData.DemoSettings.SnrValue = PacketStatus.LoRa.SnrPkt; + } + else if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_FLRC ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Flrc.RssiSync; + Eeprom.EepromData.DemoSettings.SnrValue = 0; + } + else if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_GFSK ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Gfsk.RssiSync; + Eeprom.EepromData.DemoSettings.SnrValue = 0; + } + if( ( BufferSize >= PINGPONG_SIZE ) && ( strncmp( ( const char* )( Buffer + 8 ), ( const char* )PongMsg, PINGPONG_SIZE ) == 0 ) ) + { + ComputePingPongPayload( Buffer, BufferSize ); + } + else + { + Eeprom.EepromData.DemoSettings.CntPacketRxKO++; + } + DemoInternalState = SEND_PING_MSG; + refreshDisplay = 1; + break; + + case APP_RX_TIMEOUT: + case APP_RX_ERROR: + RX_LED = !RX_LED; + Eeprom.EepromData.DemoSettings.CntPacketRxKO++; + DemoInternalState = SEND_PING_MSG; + refreshDisplay = 1; + break; + + case APP_TX_TIMEOUT: + printf( "Failure: timeout in Tx is shorter than the packet time on air\n\r" ); + DemoInternalState = APP_IDLE; + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; + break; + + case APP_IDLE: // do nothing + break; + + default: + break; + } + } + else // SLAVE + { + switch( DemoInternalState ) + { + case SEND_PONG_MSG: + wait_ms( RX_TX_TRANSITION_WAIT ); + + DemoInternalState = APP_IDLE; + // Send the next PING frame + Buffer[0] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 24 ) & 0xFF; + Buffer[1] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 16 ) & 0xFF; + Buffer[2] = ( Eeprom.EepromData.DemoSettings.CntPacketTx >> 8 ) & 0xFF; + Buffer[3] = ( Eeprom.EepromData.DemoSettings.CntPacketTx & 0xFF ); + Buffer[4] = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \ + Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >> 24 ) & 0xFF; + Buffer[5] = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \ + Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >> 16 ) & 0xFF; + Buffer[6] = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \ + Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >> 8 ) & 0xFF; + Buffer[7] = ( ( Eeprom.EepromData.DemoSettings.CntPacketRxKO + \ + Eeprom.EepromData.DemoSettings.RxTimeOutCount ) & 0xFF ); + Buffer[8] = PongMsg[0]; + Buffer[9] = PongMsg[1]; + Buffer[10] = PongMsg[2]; + Buffer[11] = PongMsg[3]; + for( i = 12; i < Eeprom.EepromData.DemoSettings.PayloadLength; i++ ) + { + Buffer[i] = i; + } + TX_LED = !TX_LED; + IrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SendPayload( Buffer, Eeprom.EepromData.DemoSettings.PayloadLength, \ + ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay } ); + break; + + case APP_TX: + if( ( Eeprom.EepromData.DemoSettings.MaxNumPacket != 0 ) \ + && ( ( Eeprom.EepromData.DemoSettings.CntPacketRxOK + Eeprom.EepromData.DemoSettings.CntPacketRxKO + \ + Eeprom.EepromData.DemoSettings.RxTimeOutCount ) >= Eeprom.EepromData.DemoSettings.MaxNumPacket ) ) + { + SendNextPacket.detach( ); + SendNext = false; + RX_LED = 0; + TX_LED = 0; + DemoInternalState = APP_IDLE; + Radio.SetStandby( STDBY_RC ); + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; + } + else + { + DemoInternalState = APP_IDLE; + TX_LED = !TX_LED; + RX_LED = !RX_LED; + IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SetRx( ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay } ); + refreshDisplay = 1; + } + break; + + case APP_RX: + DemoInternalState = APP_IDLE; + RX_LED = !RX_LED; + Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); + Radio.GetPacketStatus( &PacketStatus ); + if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_LORA ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.LoRa.RssiPkt; + Eeprom.EepromData.DemoSettings.SnrValue = PacketStatus.LoRa.SnrPkt; + } + else if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_FLRC ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Flrc.RssiSync; + Eeprom.EepromData.DemoSettings.SnrValue = 0; + } + else if( Eeprom.EepromData.ModulationParams.PacketType == PACKET_TYPE_GFSK ) + { + Eeprom.EepromData.DemoSettings.RssiValue = PacketStatus.Gfsk.RssiSync; + Eeprom.EepromData.DemoSettings.SnrValue = 0; + } + if( ( BufferSize >= PINGPONG_SIZE ) && ( strncmp( ( const char* )( Buffer + 4 ), ( const char* )PingMsg, PINGPONG_SIZE ) == 0 ) ) + { + ComputePingPongPayload( Buffer, BufferSize ); + DemoInternalState = SEND_PONG_MSG; + } + else + { + Eeprom.EepromData.DemoSettings.CntPacketRxKO++; + RX_LED = !RX_LED; + IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay } ); + refreshDisplay = 1; + } + break; + + case APP_RX_TIMEOUT: + case APP_RX_ERROR: + DemoInternalState = APP_IDLE; + Eeprom.EepromData.DemoSettings.RxTimeOutCount++; + IrqMask = IRQ_RX_DONE | IRQ_CRC_ERROR | IRQ_RX_TX_TIMEOUT; + Radio.SetDioIrqParams( IrqMask, IrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, \ + Eeprom.EepromData.DemoSettings.InterPacketDelay } ); + refreshDisplay = 1; + break; + + case APP_TX_TIMEOUT: + printf( "Failure: timeout in Tx is shorter than the packet time on air\n\r" ); + DemoInternalState = APP_IDLE; + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; + break; + + case APP_IDLE: // do nothing + break; + + default: + break; + } + } + return refreshDisplay; +} + +void ComputePingPongPayload( uint8_t *buffer, uint8_t bufferSize ) +{ + uint32_t i = 0; + + PacketRxSequence = ( ( uint32_t )buffer[0] << 24 ) | \ + ( ( uint32_t )buffer[1] << 16 ) | \ + ( ( uint32_t )buffer[2] << 8 ) | \ + buffer[3]; + + if( Eeprom.EepromData.DemoSettings.Entity == MASTER ) + { + Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave = + ( ( uint32_t )buffer[4] << 24 ) | \ + ( ( uint32_t )buffer[5] << 16 ) | \ + ( ( uint32_t )buffer[6] << 8 ) | \ + buffer[7]; + if( PacketRxSequence > Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave ) + { + Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = PacketRxSequence - \ + Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave; + } + else + { + Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = 0; + } + + if( PacketRxSequence == Eeprom.EepromData.DemoSettings.CntPacketTx ) + { + Eeprom.EepromData.DemoSettings.CntPacketRxOK += 1; + } + else + { + Eeprom.EepromData.DemoSettings.CntPacketRxKO += 1; + } + } + else + { + Eeprom.EepromData.DemoSettings.CntPacketRxOK += 1; + if( ( PacketRxSequence <= PacketRxSequencePrev ) || \ + ( PacketRxSequencePrev == 0 ) ) + { + // Sequence went back => resynchronization + // Don't count missed packets this time + i = 0; + } + else + { + // Determine number of missed packets + i = PacketRxSequence - PacketRxSequencePrev - 1; + } + // Be ready for the next + PacketRxSequencePrev = PacketRxSequence; + Eeprom.EepromData.DemoSettings.CntPacketTx = PacketRxSequence; + // increment 'missed' counter for the RX session + Eeprom.EepromData.DemoSettings.CntPacketRxKO += i; + Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0; + } +} + +// ************************ Ranging Demo ***************************** +// * * +// * * +// * * +// ***************************************************************************** +uint8_t RunDemoApplicationRanging( void ) +{ + uint8_t refreshDisplay = 0; + + if( Eeprom.EepromData.DemoSettings.HoldDemo == true ) + { + return 0; // quit without refresh display + } + + if( DemoRunning == false ) + { + DemoRunning = true; + TX_LED = 0; + RX_LED = 0; + ANT_SW = 1; + + printf( "Start RunDemoApplicationRanging\r\n" ); + + Eeprom.EepromData.DemoSettings.CntPacketTx = 0; + Eeprom.EepromData.DemoSettings.RngFei = 0.0; + Eeprom.EepromData.DemoSettings.RngStatus = RNG_INIT; + InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType ); + + if( Eeprom.EepromData.DemoSettings.Entity == MASTER ) + { + Eeprom.EepromData.DemoSettings.InterPacketDelay = RefreshScreenDelayMs; + Radio.SetDioIrqParams( IRQ_RX_DONE | IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT | IRQ_RANGING_MASTER_RESULT_VALID | IRQ_RANGING_MASTER_RESULT_TIMEOUT, + IRQ_RX_DONE | IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT | IRQ_RANGING_MASTER_RESULT_VALID | IRQ_RANGING_MASTER_RESULT_TIMEOUT, + IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + Eeprom.EepromData.DemoSettings.RngDistance = 0.0; + DemoInternalState = APP_RANGING_CONFIG; + } + else + { + Radio.SetDioIrqParams( IRQ_RADIO_ALL, IRQ_RADIO_ALL, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + DemoInternalState = APP_RANGING_CONFIG; + } + } + + if( Eeprom.EepromData.DemoSettings.Entity == MASTER ) + { + switch( DemoInternalState ) + { + case APP_RANGING_CONFIG: + if( Eeprom.EepromData.DemoSettings.HoldDemo == false ) + { + Eeprom.EepromData.DemoSettings.RngStatus = RNG_INIT; + Eeprom.EepromData.DemoSettings.CntPacketTx++; + ModulationParams.PacketType = PACKET_TYPE_LORA; + PacketParams.PacketType = PACKET_TYPE_LORA; + memcpy( &( ModulationParams.Params.LoRa.SpreadingFactor ), Eeprom.Buffer + MOD_RNG_SPREADF_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.Bandwidth ), Eeprom.Buffer + MOD_RNG_BW_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.CodingRate ), Eeprom.Buffer + MOD_RNG_CODERATE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.PreambleLength ), Eeprom.Buffer + PAK_RNG_PREAMBLE_LEN_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.HeaderType ), Eeprom.Buffer + PAK_RNG_HEADERTYPE_EEPROM_ADDR, 1 ); + PacketParams.Params.LoRa.PayloadLength = 7; + memcpy( &( PacketParams.Params.LoRa.CrcMode ), Eeprom.Buffer + PAK_RNG_CRC_MODE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.InvertIQ ), Eeprom.Buffer + PAK_RNG_IQ_INV_EEPROM_ADDR, 1 ); + Radio.SetPacketType( ModulationParams.PacketType ); + Radio.WriteRegister( 0x880, Radio.ReadRegister( 0x880 ) & ( ~0x08 ) ); + Radio.SetModulationParams( &ModulationParams ); + Radio.SetPacketParams( &PacketParams ); + Radio.SetRfFrequency( Eeprom.EepromData.DemoSettings.Frequency ); + Eeprom.EepromData.DemoSettings.CntPacketRxOK = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = 0; + MeasuredChannels = 0; + CurrentChannel = 0; + Buffer[0] = ( Eeprom.EepromData.DemoSettings.RngAddress >> 24 ) & 0xFF; + Buffer[1] = ( Eeprom.EepromData.DemoSettings.RngAddress >> 16 ) & 0xFF; + Buffer[2] = ( Eeprom.EepromData.DemoSettings.RngAddress >> 8 ) & 0xFF; + Buffer[3] = ( Eeprom.EepromData.DemoSettings.RngAddress & 0xFF ); + Buffer[4] = CurrentChannel; // set the first channel to use + Buffer[5] = Eeprom.EepromData.DemoSettings.RngAntenna; // set the antenna strategy + Buffer[6] = Eeprom.EepromData.DemoSettings.RngRequestCount; // set the number of hops + TX_LED = 1; + Radio.SendPayload( Buffer, PacketParams.Params.LoRa.PayloadLength, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, RNG_COM_TIMEOUT } ); + DemoInternalState = APP_IDLE; + } + break; + + case APP_RNG: + if( SendNext == true ) + { + SendNext = false; + MeasuredChannels++; + if( MeasuredChannels <= Eeprom.EepromData.DemoSettings.RngRequestCount ) + { + Radio.SetRfFrequency( Channels[CurrentChannel] ); + TX_LED = 1; + switch( Eeprom.EepromData.DemoSettings.RngAntenna ) + { + case DEMO_RNG_ANT_1: + ANT_SW = 1; // ANT1 + CurrentChannel++; + if( CurrentChannel >= CHANNELS ) + { + CurrentChannel -= CHANNELS; + } + break; + + case DEMO_RNG_ANT_2: + ANT_SW = 0; // ANT2 + CurrentChannel++; + if( CurrentChannel >= CHANNELS ) + { + CurrentChannel -= CHANNELS; + } + break; + + case DEMO_RNG_ANT_BOTH: + if( ANT_SW == 1 ) + { + ANT_SW = 0; + } + else + { + ANT_SW = 1; + CurrentChannel++; + if( CurrentChannel >= CHANNELS ) + { + CurrentChannel -= CHANNELS; + } + } + break; + } + SetAntennaSwitch( ); + DemoInternalState = APP_IDLE; + Radio.SetTx( ( TickTime_t ){ RADIO_TICK_SIZE_1000_US, 0xFFFF } ); + } + else + { + Eeprom.EepromData.DemoSettings.CntPacketRxOKSlave = CheckDistance( ); + refreshDisplay = 1; + SendNextPacket.detach( ); + Eeprom.EepromData.DemoSettings.HoldDemo = true; + SendNext = false; + DemoInternalState = APP_RANGING_CONFIG; + } + } + break; + + case APP_RANGING_DONE: + TX_LED = 0; + RawRngResults[RngResultIndex++] = Radio.GetRangingResult( RANGING_RESULT_RAW ); + Eeprom.EepromData.DemoSettings.CntPacketRxOK++; + DemoInternalState = APP_RNG; + break; + + case APP_RANGING_TIMEOUT: + TX_LED = 0; + DemoInternalState = APP_RNG; + break; + + case APP_RX: + RX_LED = 0; + if( Eeprom.EepromData.DemoSettings.RngStatus == RNG_INIT ) + { + Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); + if( BufferSize > 0 ) + { + Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0; + Eeprom.EepromData.DemoSettings.RngStatus = RNG_PROCESS; + Eeprom.EepromData.DemoSettings.RngFei = ( double )( ( ( int32_t )Buffer[4] << 24 ) | \ + ( ( int32_t )Buffer[5] << 16 ) | \ + ( ( int32_t )Buffer[6] << 8 ) | \ + Buffer[7] ); + Eeprom.EepromData.DemoSettings.RssiValue = Buffer[8]; // for ranging post-traitment (since V3 only) + ModulationParams.PacketType = PACKET_TYPE_RANGING; + PacketParams.PacketType = PACKET_TYPE_RANGING; + + memcpy( &( ModulationParams.Params.LoRa.SpreadingFactor ), Eeprom.Buffer + MOD_RNG_SPREADF_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.Bandwidth ), Eeprom.Buffer + MOD_RNG_BW_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.CodingRate ), Eeprom.Buffer + MOD_RNG_CODERATE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.PreambleLength ), Eeprom.Buffer + PAK_RNG_PREAMBLE_LEN_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.HeaderType ), Eeprom.Buffer + PAK_RNG_HEADERTYPE_EEPROM_ADDR, 1 ); + PacketParams.Params.LoRa.PayloadLength = 10; + memcpy( &( PacketParams.Params.LoRa.CrcMode ), Eeprom.Buffer + PAK_RNG_CRC_MODE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.InvertIQ ), Eeprom.Buffer + PAK_RNG_IQ_INV_EEPROM_ADDR, 1 ); + + Radio.SetPacketType( ModulationParams.PacketType ); + Radio.WriteRegister( 0x880, Radio.ReadRegister( 0x880 ) & ( ~0x08 ) ); + Radio.SetModulationParams( &ModulationParams ); + Radio.SetPacketParams( &PacketParams ); + Radio.SetRangingRequestAddress( Eeprom.EepromData.DemoSettings.RngAddress ); + Radio.SetRangingCalibration( Eeprom.EepromData.DemoSettings.RngCalib ); + Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_20_US ); + + MeasuredChannels = 0; + RngResultIndex = 0; + SendNextPacket.attach_us( &SendNextPacketEvent, Eeprom.EepromData.DemoSettings.RngReqDelay * 1000 ); + DemoInternalState = APP_RNG; + } + else + { + DemoInternalState = APP_RANGING_CONFIG; + } + } + else + { + DemoInternalState = APP_RANGING_CONFIG; + } + break; + + case APP_TX: + TX_LED = 0; + if( Eeprom.EepromData.DemoSettings.RngStatus == RNG_INIT ) + { + RX_LED = 1; + Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RNG_COM_TIMEOUT } ); + DemoInternalState = APP_IDLE; + } + else + { + DemoInternalState = APP_RANGING_CONFIG; + } + break; + + case APP_RX_TIMEOUT: + RX_LED = 0; + Eeprom.EepromData.DemoSettings.RngStatus = RNG_TIMEOUT; + DemoInternalState = APP_RANGING_CONFIG; + Eeprom.EepromData.DemoSettings.HoldDemo = true; + refreshDisplay = 1; // display error on token color (RNG_TIMEOUT) + break; + + case APP_RX_ERROR: + RX_LED = 0; + DemoInternalState = APP_RANGING_CONFIG; + Eeprom.EepromData.DemoSettings.HoldDemo = true; + break; + + case APP_TX_TIMEOUT: + TX_LED = 0; + DemoInternalState = APP_RANGING_CONFIG; + Eeprom.EepromData.DemoSettings.HoldDemo = true; + break; + + case APP_IDLE: // do nothing + break; + + default: + DemoInternalState = APP_RANGING_CONFIG; + Eeprom.EepromData.DemoSettings.HoldDemo = true; + break; + } + } + else // Slave + { + switch( DemoInternalState ) + { + case APP_RANGING_CONFIG: + Eeprom.EepromData.DemoSettings.RngStatus = RNG_INIT; + ModulationParams.PacketType = PACKET_TYPE_LORA; + PacketParams.PacketType = PACKET_TYPE_LORA; + memcpy( &( ModulationParams.Params.LoRa.SpreadingFactor ), Eeprom.Buffer + MOD_RNG_SPREADF_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.Bandwidth ), Eeprom.Buffer + MOD_RNG_BW_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.CodingRate ), Eeprom.Buffer + MOD_RNG_CODERATE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.PreambleLength ), Eeprom.Buffer + PAK_RNG_PREAMBLE_LEN_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.HeaderType ), Eeprom.Buffer + PAK_RNG_HEADERTYPE_EEPROM_ADDR, 1 ); + PacketParams.Params.LoRa.PayloadLength = 9; + memcpy( &( PacketParams.Params.LoRa.CrcMode ), Eeprom.Buffer + PAK_RNG_CRC_MODE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.InvertIQ ), Eeprom.Buffer + PAK_RNG_IQ_INV_EEPROM_ADDR, 1 ); + Radio.SetPacketType( ModulationParams.PacketType ); + Radio.WriteRegister( 0x880, Radio.ReadRegister( 0x880 ) & ( ~0x08 ) ); + Radio.SetModulationParams( &ModulationParams ); + Radio.SetPacketParams( &PacketParams ); + Radio.SetRfFrequency( Eeprom.EepromData.DemoSettings.Frequency ); + RX_LED = 1; + // use listen mode here instead of rx continuous + Radio.SetRx( ( TickTime_t ) { RADIO_TICK_SIZE_1000_US, 0xFFFF } ); + DemoInternalState = APP_IDLE; + break; + + case APP_RNG: + if( SendNext == true ) + { + SendNext = false; + MeasuredChannels++; + if( MeasuredChannels <= Eeprom.EepromData.DemoSettings.RngRequestCount ) + { + Radio.SetRfFrequency( Channels[CurrentChannel] ); + RX_LED = 1; + switch( Eeprom.EepromData.DemoSettings.RngAntenna ) + { + case DEMO_RNG_ANT_1: + ANT_SW = 1; // ANT1 + CurrentChannel++; + if( CurrentChannel >= CHANNELS ) + { + CurrentChannel -= CHANNELS; + } + break; + + case DEMO_RNG_ANT_2: + ANT_SW = 0; // ANT2 + CurrentChannel++; + if( CurrentChannel >= CHANNELS ) + { + CurrentChannel -= CHANNELS; + } + break; + + case DEMO_RNG_ANT_BOTH: + if( ANT_SW == 1 ) + { + ANT_SW = 0; + } + else + { + ANT_SW = 1; + CurrentChannel++; + if( CurrentChannel >= CHANNELS ) + { + CurrentChannel -= CHANNELS; + } + } + break; + } + SetAntennaSwitch( ); + DemoInternalState = APP_IDLE; + Radio.SetRx( ( TickTime_t ){ RADIO_TICK_SIZE_1000_US, Eeprom.EepromData.DemoSettings.RngReqDelay } ); + } + else + { + refreshDisplay = 1; + SendNextPacket.detach( ); + Eeprom.EepromData.DemoSettings.RngStatus = RNG_VALID; + DemoInternalState = APP_RANGING_CONFIG; + } + } + break; + + case APP_RANGING_DONE: + RX_LED = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxOK++; + DemoInternalState = APP_RNG; + break; + + case APP_RANGING_TIMEOUT: + RX_LED = 0; + DemoInternalState = APP_RNG; + break; + + case APP_RX: + RX_LED = 0; + if( Eeprom.EepromData.DemoSettings.RngStatus == RNG_INIT ) + { + Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); + if( ( BufferSize > 0 ) && \ + ( Buffer[0] == ( ( Eeprom.EepromData.DemoSettings.RngAddress >> 24 ) & 0xFF ) ) && \ + ( Buffer[1] == ( ( Eeprom.EepromData.DemoSettings.RngAddress >> 16 ) & 0xFF ) ) && \ + ( Buffer[2] == ( ( Eeprom.EepromData.DemoSettings.RngAddress >> 8 ) & 0xFF ) ) && \ + ( Buffer[3] == ( Eeprom.EepromData.DemoSettings.RngAddress & 0xFF ) ) ) + { + Eeprom.EepromData.DemoSettings.RngFei = Radio.GetFrequencyError( ); + Eeprom.EepromData.DemoSettings.RssiValue = Radio.GetRssiInst( ); + Eeprom.EepromData.DemoSettings.CntPacketTx++; + CurrentChannel = Buffer[4]; + Eeprom.EepromData.DemoSettings.RngAntenna = Buffer[5]; + Eeprom.EepromData.DemoSettings.RngRequestCount = Buffer[6]; + wait_us( 10 ); + Buffer[4] = ( ( ( int32_t )Eeprom.EepromData.DemoSettings.RngFei ) >> 24 ) & 0xFF ; + Buffer[5] = ( ( ( int32_t )Eeprom.EepromData.DemoSettings.RngFei ) >> 16 ) & 0xFF ; + Buffer[6] = ( ( ( int32_t )Eeprom.EepromData.DemoSettings.RngFei ) >> 8 ) & 0xFF ; + Buffer[7] = ( ( ( int32_t )Eeprom.EepromData.DemoSettings.RngFei ) & 0xFF ); + Buffer[8] = Eeprom.EepromData.DemoSettings.RssiValue; + TX_LED = 1; + Radio.SendPayload( Buffer, 9, ( TickTime_t ){ RADIO_TICK_SIZE_1000_US, RNG_COM_TIMEOUT } ); + DemoInternalState = APP_IDLE; + } + } + else + { + DemoInternalState = APP_RANGING_CONFIG; + } + break; + + case APP_TX: + TX_LED = 0; + if( Eeprom.EepromData.DemoSettings.RngStatus == RNG_INIT ) + { + Eeprom.EepromData.DemoSettings.RngStatus = RNG_PROCESS; + + ModulationParams.PacketType = PACKET_TYPE_RANGING; + PacketParams.PacketType = PACKET_TYPE_RANGING; + + memcpy( &( ModulationParams.Params.LoRa.SpreadingFactor ), Eeprom.Buffer + MOD_RNG_SPREADF_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.Bandwidth ), Eeprom.Buffer + MOD_RNG_BW_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.CodingRate ), Eeprom.Buffer + MOD_RNG_CODERATE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.PreambleLength ), Eeprom.Buffer + PAK_RNG_PREAMBLE_LEN_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.HeaderType ), Eeprom.Buffer + PAK_RNG_HEADERTYPE_EEPROM_ADDR, 1 ); + PacketParams.Params.LoRa.PayloadLength = 10; + memcpy( &( PacketParams.Params.LoRa.CrcMode ), Eeprom.Buffer + PAK_RNG_CRC_MODE_EEPROM_ADDR, 1 ); + memcpy( &( PacketParams.Params.LoRa.InvertIQ ), Eeprom.Buffer + PAK_RNG_IQ_INV_EEPROM_ADDR, 1 ); + + Radio.SetPacketType( ModulationParams.PacketType ); + Radio.WriteRegister( 0x880, Radio.ReadRegister( 0x880 ) & ( ~0x08 ) ); + Radio.SetModulationParams( &ModulationParams ); + Radio.SetPacketParams( &PacketParams ); + Radio.SetDeviceRangingAddress( Eeprom.EepromData.DemoSettings.RngAddress ); + Radio.SetRangingCalibration( Eeprom.EepromData.DemoSettings.RngCalib ); + Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_20_US ); + Eeprom.EepromData.DemoSettings.CntPacketRxOK = 0; + MeasuredChannels = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave = 0; + SendNextPacket.attach_us( &SendNextPacketEvent, Eeprom.EepromData.DemoSettings.RngReqDelay * 1000 ); + DemoInternalState = APP_RNG; + } + else + { + DemoInternalState = APP_RANGING_CONFIG; + } + break; + + case APP_RX_TIMEOUT: + RX_LED = 0; + DemoInternalState = APP_RANGING_CONFIG; + break; + + case APP_RX_ERROR: + RX_LED = 0; + DemoInternalState = APP_RANGING_CONFIG; + break; + + case APP_TX_TIMEOUT: + TX_LED = 0; + DemoInternalState = APP_RANGING_CONFIG; + break; + + case APP_IDLE: // do nothing + if( Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave > DEMO_RNG_CHANNELS_COUNT_MAX ) + { + Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave = 0; + refreshDisplay = 1; + RX_LED = 0; + DemoInternalState = APP_RANGING_CONFIG; + SendNextPacket.detach( ); + } + break; + + default: + DemoInternalState = APP_RANGING_CONFIG; + SendNextPacket.detach( ); + break; + } + } + return refreshDisplay; +} + +// ************************ Utils **************************** +// * * +// * * +// * * +// ***************************************************************************** + +void InitDemoApplication( void ) +{ + RX_LED = 1; + TX_LED = 1; + + SetAntennaSwitch( ); + + wait_ms( 500 ); // wait for on board DC/DC start-up time + + Radio.Init( ); + + Radio.ReadRegister( 0x0A08, &BackupReg_1, 1 ); + Radio.ReadRegister( 0x0A07, &BackupReg_2, 1 ); + Radio.ReadRegister( 0x0A23, &BackupReg_3, 1 ); + Radio.ReadRegister( 0x0A41, &BackupReg_4, 1 ); + Radio.ReadRegister( 0x0A42, &BackupReg_5, 1 ); + Radio.ReadRegister( 0x0A43, &BackupReg_6, 1 ); + + // Can also be set in LDO mode but consume more power + Radio.SetRegulatorMode( ( RadioRegulatorModes_t )Eeprom.EepromData.DemoSettings.RadioPowerMode ); + Radio.SetStandby( STDBY_RC ); + + memset( &Buffer, 0x00, BufferSize ); + + RX_LED = 0; + TX_LED = 0; + + PacketRxSequence = 0; + PacketRxSequencePrev = 0; + Eeprom.EepromData.DemoSettings.CntPacketTx = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxOK = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxKO = 0; + Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0; +} + +void StopDemoApplication( void ) +{ + if( DemoRunning == true ) + { + __disable_irq( ); // Disable Interrupts + + printf( "StopDemoApplication\n\r" ); + if( Radio.GetOpMode( ) == MODE_SLEEP ) + { + InitializeDemoParameters( Eeprom.EepromData.DemoSettings.ModulationType ); + } + RX_LED = 0; + TX_LED = 0; + DemoRunning = false; + SendNext = false; + PacketRxSequence = 0; + PacketRxSequencePrev = 0; + Eeprom.EepromData.DemoSettings.CntPacketTx = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxOK = 0; + Eeprom.EepromData.DemoSettings.CntPacketRxKO = 0; + Eeprom.EepromData.DemoSettings.RxTimeOutCount = 0; + + Radio.SetAutoFs( false ); + DemoInternalState = APP_IDLE; + Radio.SetStandby( STDBY_RC ); + Radio.ClearIrqStatus( IRQ_RADIO_ALL ); + SendNextPacket.detach( ); + + __enable_irq( ); // Enable Interrupts + } +} + +/* + * Function still being implemented >>> To be completed + * WARNING: Computation is in float and his really slow + * LongInterLeaving vs LegacyInterLeaving has no influence on TimeOnAir. + */ +uint16_t GetTimeOnAir( uint8_t modulation ) +{ + uint16_t result = 2000; + + if( modulation == PACKET_TYPE_LORA ) + { + double bw = 0.0; + + switch( Eeprom.EepromData.ModulationParams.Params.LoRa.Bandwidth ) + { + case LORA_BW_0200: + bw = 203e3; + break; + + case LORA_BW_0400: + bw = 406e3; + break; + + case LORA_BW_0800: + bw = 812e3; + break; + + case LORA_BW_1600: + bw = 1625e3; + break; + + default: + bw = 100e3; + break; + } + double rs = bw / ( 1 << ( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) ); // Symbol rate : time for one symbol (secs) + double ts = 1 / rs; + double tPreamble = ( Eeprom.EepromData.PacketParams.Params.LoRa.PreambleLength + 4.25 ) * ts; // time of preamble + uint8_t de = 1; // always 1 on SX1280. "low data rate optimization" condition. + double tmp = ceil( ( 8 * Eeprom.EepromData.PacketParams.Params.LoRa.PayloadLength - 4 * ( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) + + 28 + 16 * ( ( Eeprom.EepromData.PacketParams.Params.LoRa.CrcMode == 0x00 ) ? 0 : 1 ) - \ + ( ( Eeprom.EepromData.PacketParams.Params.LoRa.HeaderType >> 7 ) ? 20 : 0 ) ) / \ + ( double )( 4 * ( ( Eeprom.EepromData.ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) - ( de * 2 ) ) ) * \ + ( ( Eeprom.EepromData.ModulationParams.Params.LoRa.CodingRate % 4 ) + 4 ) ); // Symbol length of payload and time + double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); + double tPayload = nPayload * ts; + + // Time on air [ms] + result = floor( ( ( tPreamble + tPayload ) * 1000 * 1.2 ) + 0.999 ); // Set some margin + result *= 1.8; // Set some margin + } + else if( modulation == PACKET_TYPE_FLRC ) + { + uint16_t packetBitCount; + + switch( Eeprom.EepromData.PacketParams.Params.Flrc.PreambleLength ) + { + case PREAMBLE_LENGTH_04_BITS: // Preamble length: 04 bits + case PREAMBLE_LENGTH_08_BITS: // Preamble length: 08 bits + packetBitCount = 1; + break; + + case PREAMBLE_LENGTH_12_BITS: // Preamble length: 12 bits + case PREAMBLE_LENGTH_16_BITS: // Preamble length: 16 bits + packetBitCount = 2; + break; + + case PREAMBLE_LENGTH_20_BITS: // Preamble length: 20 bits + case PREAMBLE_LENGTH_24_BITS: // Preamble length: 24 bits + packetBitCount = 3; + break; + + case PREAMBLE_LENGTH_28_BITS: // Preamble length: 28 bits + case PREAMBLE_LENGTH_32_BITS: // Preamble length: 32 bits + packetBitCount = 4; + break; + + default: + packetBitCount = 4; + break; + } + packetBitCount += 3; // Preamble 21 bits + switch( Eeprom.EepromData.PacketParams.Params.Flrc.SyncWordLength ) + { + case FLRC_SYNCWORD_LENGTH_4_BYTE: + packetBitCount += 4; + break; + + case FLRC_NO_SYNCWORD: + default: + break; + } + switch( Eeprom.EepromData.ModulationParams.Params.Flrc.CodingRate ) + { + // += 7; // CRC length is maximum 4 bytes (short-cut) + 2 Header + 6 bits Tail + case FLRC_CR_3_4: + packetBitCount += ( uint16_t )( ceil( ( ( float )( Eeprom.EepromData.PacketParams.Params.Flrc.PayloadLength + 7 ) * 4 ) / 3 ) ); + break; + + case FLRC_CR_1_0: + packetBitCount += Eeprom.EepromData.PacketParams.Params.Flrc.PayloadLength + 7; + break; + + default: + case FLRC_CR_1_2: + packetBitCount += ( Eeprom.EepromData.PacketParams.Params.Flrc.PayloadLength + 7 ) * 2; + break; + } + packetBitCount *= 8; + switch( Eeprom.EepromData.ModulationParams.Params.Flrc.BitrateBandwidth ) + { + case FLRC_BR_1_300_BW_1_2: + result = ( uint16_t )( ceil( ( float )packetBitCount / 1300 ) ); + break; + + case FLRC_BR_1_040_BW_1_2: + result = ( uint16_t )( ceil( ( float )packetBitCount / 1040 ) ); + break; + + case FLRC_BR_0_650_BW_0_6: + result = ( uint16_t )( ceil( ( float )packetBitCount / 650 ) ); + break; + + case FLRC_BR_0_520_BW_0_6: + result = ( uint16_t )( ceil( ( float )packetBitCount / 520 ) ); + break; + + case FLRC_BR_0_325_BW_0_3: + result = ( uint16_t )( ceil( ( float )packetBitCount / 325 ) ); + break; + + default: + case FLRC_BR_0_260_BW_0_3: + result = ( uint16_t )( ceil( ( float )packetBitCount / 260 ) ); + break; + } + result *= 2; // Set some margin + } + else if( modulation == PACKET_TYPE_GFSK ) + { + uint16_t packetBitCount; + + switch( Eeprom.EepromData.PacketParams.Params.Gfsk.PreambleLength ) + { + case PREAMBLE_LENGTH_04_BITS: // Preamble length: 04 bits + case PREAMBLE_LENGTH_08_BITS: // Preamble length: 08 bits + packetBitCount = 1; + break; + + case PREAMBLE_LENGTH_12_BITS: // Preamble length: 12 bits + case PREAMBLE_LENGTH_16_BITS: // Preamble length: 16 bits + packetBitCount = 2; + break; + + case PREAMBLE_LENGTH_20_BITS: // Preamble length: 20 bits + case PREAMBLE_LENGTH_24_BITS: // Preamble length: 24 bits + packetBitCount = 3; + break; + + case PREAMBLE_LENGTH_28_BITS: // Preamble length: 28 bits + case PREAMBLE_LENGTH_32_BITS: // Preamble length: 32 bits + packetBitCount = 4; + break; + + default: + packetBitCount = 4; + break; + } + switch( Eeprom.EepromData.PacketParams.Params.Gfsk.SyncWordLength ) + { + case GFSK_SYNCWORD_LENGTH_1_BYTE: // Sync word length: 1 byte + packetBitCount += 1; + break; + + case GFSK_SYNCWORD_LENGTH_2_BYTE: // Sync word length: 2 bytes + packetBitCount += 2; + break; + + case GFSK_SYNCWORD_LENGTH_3_BYTE: // Sync word length: 3 bytes + packetBitCount += 3; + break; + + case GFSK_SYNCWORD_LENGTH_4_BYTE: // Sync word length: 4 bytes + packetBitCount += 4; + break; + + case GFSK_SYNCWORD_LENGTH_5_BYTE: // Sync word length: 5 bytes + packetBitCount += 5; + break; + + default: + packetBitCount += 5; + break; + } + packetBitCount += Eeprom.EepromData.PacketParams.Params.Gfsk.PayloadLength + 3; + packetBitCount *= 8; + switch( Eeprom.EepromData.ModulationParams.Params.Gfsk.BitrateBandwidth ) + { + case GFSK_BLE_BR_2_000_BW_2_4: + result = ( uint16_t )( ceil( ( float )packetBitCount / 2000 ) ); + break; + + case GFSK_BLE_BR_1_600_BW_2_4: + result = ( uint16_t )( ceil( ( float )packetBitCount / 1600 ) ); + break; + + case GFSK_BLE_BR_1_000_BW_2_4: + case GFSK_BLE_BR_1_000_BW_1_2: + result = ( uint16_t )( ceil( ( float )packetBitCount / 1000 ) ); + break; + + case GFSK_BLE_BR_0_800_BW_2_4: + case GFSK_BLE_BR_0_800_BW_1_2: + result = ( uint16_t )( ceil( ( float )packetBitCount / 800 ) ); + break; + + case GFSK_BLE_BR_0_500_BW_1_2: + case GFSK_BLE_BR_0_500_BW_0_6: + result = ( uint16_t )( ceil( ( float )packetBitCount / 500 ) ); + break; + + case GFSK_BLE_BR_0_400_BW_1_2: + case GFSK_BLE_BR_0_400_BW_0_6: + result = ( uint16_t )( ceil( ( float )packetBitCount / 400 ) ); + break; + + case GFSK_BLE_BR_0_250_BW_0_6: + case GFSK_BLE_BR_0_250_BW_0_3: + result = ( uint16_t )( ceil( ( float )packetBitCount / 250 ) ); + break; + + case GFSK_BLE_BR_0_125_BW_0_3: + result = ( uint16_t )( ceil( ( float )packetBitCount / 125 ) ); + break; + + default: + result = 100; + break; + } + result *= 1.5; // Set 50% margin + } + return result; +} + +void InitializeDemoParameters( uint8_t modulation ) +{ +/* + SetAntennaSwitch( ); + Radio.Init( ); +*/ + Radio.SetStandby( STDBY_RC ); + + Radio.SetRegulatorMode( ( RadioRegulatorModes_t )Eeprom.EepromData.DemoSettings.RadioPowerMode ); + + printf("> InitializeDemoParameters\n\r"); + if( modulation == PACKET_TYPE_LORA ) + { + printf("set param LORA for demo\n\r"); + ModulationParams.PacketType = PACKET_TYPE_LORA; + PacketParams.PacketType = PACKET_TYPE_LORA; + + ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t ) Eeprom.EepromData.DemoSettings.ModulationParam1; + ModulationParams.Params.LoRa.Bandwidth = ( RadioLoRaBandwidths_t ) Eeprom.EepromData.DemoSettings.ModulationParam2; + ModulationParams.Params.LoRa.CodingRate = ( RadioLoRaCodingRates_t ) Eeprom.EepromData.DemoSettings.ModulationParam3; + PacketParams.Params.LoRa.PreambleLength = Eeprom.EepromData.DemoSettings.PacketParam1; + PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsModes_t )Eeprom.EepromData.DemoSettings.PacketParam2; + PacketParams.Params.LoRa.PayloadLength = Eeprom.EepromData.DemoSettings.PacketParam3; + PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t ) Eeprom.EepromData.DemoSettings.PacketParam4; + PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t ) Eeprom.EepromData.DemoSettings.PacketParam5; + + Eeprom.EepromData.DemoSettings.PayloadLength = PacketParams.Params.LoRa.PayloadLength; + } + else if( modulation == PACKET_TYPE_FLRC ) + { + printf("set param FLRC for demo\n\r"); + ModulationParams.PacketType = PACKET_TYPE_FLRC; + PacketParams.PacketType = PACKET_TYPE_FLRC; + + ModulationParams.Params.Flrc.BitrateBandwidth = ( RadioFlrcBitrates_t ) Eeprom.EepromData.DemoSettings.ModulationParam1; + ModulationParams.Params.Flrc.CodingRate = ( RadioFlrcCodingRates_t ) Eeprom.EepromData.DemoSettings.ModulationParam2; + ModulationParams.Params.Flrc.ModulationShaping = ( RadioModShapings_t ) Eeprom.EepromData.DemoSettings.ModulationParam3; + PacketParams.Params.Flrc.PreambleLength = ( RadioPreambleLengths_t ) Eeprom.EepromData.DemoSettings.PacketParam1; + PacketParams.Params.Flrc.SyncWordLength = ( RadioFlrcSyncWordLengths_t )Eeprom.EepromData.DemoSettings.PacketParam2; + PacketParams.Params.Flrc.SyncWordMatch = ( RadioSyncWordRxMatchs_t ) Eeprom.EepromData.DemoSettings.PacketParam3; + PacketParams.Params.Flrc.HeaderType = ( RadioPacketLengthModes_t ) Eeprom.EepromData.DemoSettings.PacketParam4; + PacketParams.Params.Flrc.PayloadLength = Eeprom.EepromData.DemoSettings.PacketParam5; + PacketParams.Params.Flrc.CrcLength = ( RadioCrcTypes_t ) Eeprom.EepromData.DemoSettings.PacketParam6; + PacketParams.Params.Flrc.Whitening = ( RadioWhiteningModes_t ) Eeprom.EepromData.DemoSettings.PacketParam7; + + Eeprom.EepromData.DemoSettings.PayloadLength = PacketParams.Params.Flrc.PayloadLength; + } + else if( modulation == PACKET_TYPE_GFSK ) + { + printf("set param GFSK for demo\n\r"); + ModulationParams.PacketType = PACKET_TYPE_GFSK; + PacketParams.PacketType = PACKET_TYPE_GFSK; + + ModulationParams.Params.Gfsk.BitrateBandwidth = ( RadioGfskBleBitrates_t ) Eeprom.EepromData.DemoSettings.ModulationParam1; + ModulationParams.Params.Gfsk.ModulationIndex = ( RadioGfskBleModIndexes_t )Eeprom.EepromData.DemoSettings.ModulationParam2; + ModulationParams.Params.Gfsk.ModulationShaping = ( RadioModShapings_t ) Eeprom.EepromData.DemoSettings.ModulationParam3; + PacketParams.Params.Gfsk.PreambleLength = ( RadioPreambleLengths_t ) Eeprom.EepromData.DemoSettings.PacketParam1; + PacketParams.Params.Gfsk.SyncWordLength = ( RadioSyncWordLengths_t ) Eeprom.EepromData.DemoSettings.PacketParam2; + PacketParams.Params.Gfsk.SyncWordMatch = ( RadioSyncWordRxMatchs_t ) Eeprom.EepromData.DemoSettings.PacketParam3; + PacketParams.Params.Gfsk.HeaderType = ( RadioPacketLengthModes_t )Eeprom.EepromData.DemoSettings.PacketParam4; + PacketParams.Params.Gfsk.PayloadLength = Eeprom.EepromData.DemoSettings.PacketParam5; + PacketParams.Params.Gfsk.CrcLength = ( RadioCrcTypes_t ) Eeprom.EepromData.DemoSettings.PacketParam6; + PacketParams.Params.Gfsk.Whitening = ( RadioWhiteningModes_t ) Eeprom.EepromData.DemoSettings.PacketParam7; + + Eeprom.EepromData.DemoSettings.PayloadLength = PacketParams.Params.Gfsk.PayloadLength; + } + if( modulation == PACKET_TYPE_RANGING ) + { + Radio.SetBufferBaseAddresses( 0x00, 0x00 ); + Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_20_US ); + memcpy( &( ModulationParams.Params.LoRa.SpreadingFactor ), Eeprom.Buffer + MOD_RNG_SPREADF_EEPROM_ADDR, 1 ); + memcpy( &( ModulationParams.Params.LoRa.Bandwidth ), Eeprom.Buffer + MOD_RNG_BW_EEPROM_ADDR, 1 ); + switch( Eeprom.EepromData.ModulationParams.Params.LoRa.Bandwidth ) + { + case LORA_BW_0400: + Eeprom.EepromData.DemoSettings.RngCalib = RNG_CALIB_0400[ ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) - 5 ]; + Eeprom.EepromData.DemoSettings.RngFeiFactor = ( double )RNG_FGRAD_0400[ ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) - 5 ]; + Eeprom.EepromData.DemoSettings.RngReqDelay = RNG_TIMER_MS >> ( 0 + 10 - ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) ); + break; + + case LORA_BW_0800: + Eeprom.EepromData.DemoSettings.RngCalib = RNG_CALIB_0800[ ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) - 5 ]; + Eeprom.EepromData.DemoSettings.RngFeiFactor = ( double )RNG_FGRAD_0800[ ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) - 5 ]; + Eeprom.EepromData.DemoSettings.RngReqDelay = RNG_TIMER_MS >> ( 1 + 10 - ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) ); + break; + + case LORA_BW_1600: + Eeprom.EepromData.DemoSettings.RngCalib = RNG_CALIB_1600[ ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) - 5 ]; + Eeprom.EepromData.DemoSettings.RngFeiFactor = ( double )RNG_FGRAD_1600[ ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) - 5 ]; + Eeprom.EepromData.DemoSettings.RngReqDelay = RNG_TIMER_MS >> ( 2 + 10 - ( ModulationParams.Params.LoRa.SpreadingFactor >> 4 ) ); + break; + } + } + else + { + Radio.SetStandby( STDBY_RC ); + Radio.SetPacketType( ModulationParams.PacketType ); + Radio.SetRfFrequency( Eeprom.EepromData.DemoSettings.Frequency ); + Radio.SetBufferBaseAddresses( 0x00, 0x00 ); + Radio.SetModulationParams( &ModulationParams ); + Radio.SetPacketParams( &PacketParams ); + // only used in GFSK, FLRC (4 bytes max) and BLE mode + Radio.SetSyncWord( 1, ( uint8_t[] ){ 0xDD, 0xA0, 0x96, 0x69, 0xDD } ); + // only used in GFSK, FLRC + Radio.SetCrcSeed( 0x4567 ); + Radio.SetCrcPolynomial( 0x0123 ); + Radio.SetTxParams( Eeprom.EepromData.DemoSettings.TxPower, RADIO_RAMP_20_US ); + } +} + +/*! + * \brief Callback of ticker PerSendNextPacket + */ +void SendNextPacketEvent( void ) +{ + SendNext = true; + if( Eeprom.EepromData.DemoSettings.RngStatus == RNG_PROCESS ) + { + Eeprom.EepromData.DemoSettings.CntPacketRxKOSlave++; + } +} + +uint8_t CheckDistance( void ) +{ + double mean = 0.0; + double meanRaw = 0.0; + double total = 0.0; + double squareDeviation = 0.0; + double squareDeviationRaw = 0.0; + uint8_t j = 0; + uint8_t i; + + printf( "#id: %d", Eeprom.EepromData.DemoSettings.CntPacketTx ); + if( RngResultIndex > 0 ) + { + // compute average and std deviation w/o frequency correction + for( i = 0; i < RngResultIndex; ++i ) + { + total += RawRngResults[i]; + squareDeviationRaw += RawRngResults[i] * RawRngResults[i]; + } + meanRaw = total / RngResultIndex; + squareDeviationRaw = sqrt( ( squareDeviationRaw / RngResultIndex ) - ( meanRaw * meanRaw ) ); + + // compute average and std deviation + total = 0.0; + for( i = 0; i < RngResultIndex; ++i ) + { + RawRngResults[i] -= ( Eeprom.EepromData.DemoSettings.RngFeiFactor * Eeprom.EepromData.DemoSettings.RngFei / 1000 ); + total += RawRngResults[i]; + squareDeviation += RawRngResults[i] * RawRngResults[i]; + } + mean = total / RngResultIndex; + squareDeviation = sqrt( ( squareDeviation / RngResultIndex ) - ( mean * mean ) ); + printf( ", Moy: %5.1f, Std: %6.3f", mean, squareDeviation ); + +/* + * also use RSSI since chip V3 for filter ranging values + */ + total = 0.0; + // select measure with correct Z Score + for( i = 0; i < RngResultIndex; ++i ) + { + if( ( fabs( RawRngResults[i] - meanRaw ) / squareDeviationRaw ) <= ( double )Eeprom.EepromData.DemoSettings.RngZscoreMax ) + { + total += RawRngResults[i]; + j++; + } + } + if( j > 0 ) + { + meanRaw = total / j; + } + else + { + meanRaw = 0.0; + } + Eeprom.EepromData.DemoSettings.RngRawDistance = meanRaw; + total = 0.0; + j = 0; + // select measure with correct Z Score + for( i = 0; i < RngResultIndex; ++i ) + { + if( ( fabs( RawRngResults[i] - mean ) / squareDeviation ) <= ( double )Eeprom.EepromData.DemoSettings.RngZscoreMax ) + { + total += RawRngResults[i]; + j++; + } + } + if( j > 0 ) + { + mean = total / j; + } + else + { + mean = 0.0; + } + if( j < DEMO_RNG_CHANNELS_COUNT_MIN ) + { + Eeprom.EepromData.DemoSettings.RngStatus = RNG_PER_ERROR; + } + else + { + Eeprom.EepromData.DemoSettings.RngStatus = RNG_VALID; + } + if( mean <= 18.5 ) + { + // _TCO_ acces à la correction frequence et rssi +// double RngFei; // Ranging Frequency Error Indicator +// double RngFeiFactor; // Ranging frequency correction factor +// int8_t RssiValue; // Demo Rssi Value + //Eeprom.EepromData.DemoSettings.xxx + // example : if( ( double )Eeprom.EepromData.DemoSettings.RssiValue > 1.0 ) + mean = exp( ( mean + 2.4917 ) / 7.2262 ); + } + if( mean < 0 ) + { + Eeprom.EepromData.DemoSettings.RngDistance = 0.0; + } + else + { + switch( Eeprom.EepromData.DemoSettings.RngUnit ) + { + case DEMO_RNG_UNIT_SEL_M: + Eeprom.EepromData.DemoSettings.RngDistance = mean; + break; + + case DEMO_RNG_UNIT_SEL_YD: + Eeprom.EepromData.DemoSettings.RngDistance = mean * DEMO_RNG_UNIT_CONV_YD; + break; + + case DEMO_RNG_UNIT_SEL_MI: + Eeprom.EepromData.DemoSettings.RngDistance = mean * DEMO_RNG_UNIT_CONV_MI; + break; + } + } + } + printf( ", Rssi: %d, Zn: %3d, Zmoy: %5.1f, FEI: %d\r\n", Eeprom.EepromData.DemoSettings.RssiValue, j, mean, ( int32_t )Eeprom.EepromData.DemoSettings.RngFei ); + + return j; +} + +void LedBlink( void ) +{ + if( ( TX_LED == 0 ) && ( RX_LED == 0 ) ) + { + TX_LED = 1; + } + else if( ( TX_LED == 1 ) && ( RX_LED == 0 ) ) + { + RX_LED = 1; + } + else if( ( TX_LED == 1 ) && ( RX_LED == 1 ) ) + { + TX_LED = 0; + } + else + { + RX_LED = 0; + } +} + +void SetAntennaSwitch( void ) +{ + if( Eeprom.EepromData.DemoSettings.AntennaSwitch == 0 ) + { + ANT_SW = 1; // ANT1 + } + else + { + ANT_SW = 0; // ANT2 + } +} + +// ************************ Radio Callbacks **************************** +// * * +// * These functions are called through function pointer by the Radio low * +// * level drivers * +// * * +// ***************************************************************************** +void OnTxDone( void ) +{ + DemoInternalState = APP_TX; +} + +void OnRxDone( void ) +{ + DemoInternalState = APP_RX; +} + +void OnTxTimeout( void ) +{ + DemoInternalState = APP_TX_TIMEOUT; +} + +void OnRxTimeout( void ) +{ + DemoInternalState = APP_RX_TIMEOUT; +} + +void OnRxError( IrqErrorCode_t errorCode ) +{ + DemoInternalState = APP_RX_ERROR; +} + +void OnRangingDone( IrqRangingCode_t val ) +{ + if( val == IRQ_RANGING_MASTER_VALID_CODE || val == IRQ_RANGING_SLAVE_VALID_CODE ) + { + DemoInternalState = APP_RANGING_DONE; + } + else if( val == IRQ_RANGING_MASTER_ERROR_CODE || val == IRQ_RANGING_SLAVE_ERROR_CODE ) + { + DemoInternalState = APP_RANGING_TIMEOUT; + } + else + { + DemoInternalState = APP_RANGING_TIMEOUT; + } +} + +void OnCadDone( bool channelActivityDetected ) +{ +}