diff --git a/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-10-14_215638.zip b/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-10-14_215638.zip deleted file mode 100644 index 2b12719c..00000000 Binary files a/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-10-14_215638.zip and /dev/null differ diff --git a/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-10-14_220824.zip b/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-10-14_220824.zip deleted file mode 100644 index 7b4bde40..00000000 Binary files a/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-10-14_220824.zip and /dev/null differ diff --git a/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-11-05_222516.zip b/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-11-05_222516.zip new file mode 100644 index 00000000..f5fb56df Binary files /dev/null and b/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-11-05_222516.zip differ diff --git a/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-11-05_223753.zip b/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-11-05_223753.zip new file mode 100644 index 00000000..f5fb56df Binary files /dev/null and b/Boards/BITSv5/BITSv5/BITSv5-backups/BITSv5-2023-11-05_223753.zip differ diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/Arduino-DRF1262T-RX.ino b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/Arduino-DRF1262T-RX.ino new file mode 100644 index 00000000..beaa3899 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/Arduino-DRF1262T-RX.ino @@ -0,0 +1,165 @@ +#include +#include +#include +#include "radio.h" +#include "timer1.h" +#include "sx126x.h" +#include "sx126x-board.h" +#define Get_NIRQ() digitalRead(Dio1Pin) +/* + * if you want to use TCXO please open sx1262.h line 29 +*/ + +uint8_t mode = USER_MODE_RX; /*mode SET current work mode: TX or RX*/ +/*Default frequency:868MHZ Bandwidth:125KHZ,RF_FACTOR:11 */ + +#define RF_FREQUENCY 868000000 // Hz center frequency +#define TX_OUTPUT_POWER 22 // dBm tx output power +#define LORA_BANDWIDTH 1 // bandwidth=125khz 0:250kHZ,1:125kHZ,2:62kHZ,3:20kHZ.... look for radio line 392 +#define LORA_SPREADING_FACTOR 11 // spreading factor=11 [SF5..SF12] +#define LORA_CODINGRATE 1 // [1: 4/5, + // 2: 4/6, + // 3: 4/7, + // 4: 4/8] +#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx +#define LORA_SYMBOL_TIMEOUT 0 // Symbols +#define LORA_FIX_LENGTH_PAYLOAD_ON false // variable data payload +#define LORA_IQ_INVERSION_ON false + +typedef enum +{ + LOWPOWER, + RX, + RX_TIMEOUT, + RX_ERROR, + TX, + TX_TIMEOUT, +}States_t; + +#define RX_TIMEOUT_VALUE 1000 +#define BUFFER_SIZE 64 // Define the payload size here +States_t State = LOWPOWER; + +RadioEvents_t RadioEvents; +uint16_t BufferSize = BUFFER_SIZE; +uint8_t Buffer[BUFFER_SIZE]; +int8_t RssiValue = 0; +int8_t SnrValue = 0; + +void OnTxDone( void ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); +void OnTxTimeout( void ); +void OnRxTimeout( void ); +void OnRxError( void ); + +uint8_t i = 0; + +void setup() +{ + timer1_init(); + SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0)); + Serial.begin(9600); // set baud rate + SX126xIoInit(); //Initializes the radio I/Os pins + SPI.begin(); + + pinMode (Led1BluePin, OUTPUT); + pinMode (Led1RedPin, OUTPUT); + digitalWrite(Led1BluePin,1); + digitalWrite(Led1RedPin,1); + + // Radio initialization + RadioEvents.TxDone = OnTxDone; + RadioEvents.RxDone = OnRxDone; + RadioEvents.TxTimeout = OnTxTimeout; + RadioEvents.RxTimeout = OnRxTimeout; + RadioEvents.RxError = OnRxError; + + Radio.Init( &RadioEvents ); + Radio.SetChannel( RF_FREQUENCY ); + + Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0,LORA_BANDWIDTH, + LORA_SPREADING_FACTOR, LORA_CODINGRATE, + LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, + true, 0, 0, LORA_IQ_INVERSION_ON, 3000 ); + + Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH,LORA_SPREADING_FACTOR, + LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, + LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); + + if(USER_MODE_RX == mode) + { + + Radio.Rx(0); + digitalWrite(Led1BluePin,0); + Serial.println("Now is RX"); + }else + { + Radio.Send((uint8_t*)&i, 1 ); + } +} + +void loop() +{ + // put your main code here, to run repeatedly: + if(USER_MODE_RX == mode) + { + if( 0 != State ) + { + Serial.println(Buffer[0],DEC); // print received characters + + digitalWrite(Led1BluePin,digitalRead(Led1BluePin)^1); + State = LOWPOWER; + + } + }else if(TX == State) + { + delay(500); + i++; + Radio.Send((uint8_t*)&i, 1 ); //send one testing character, users can change the content + digitalWrite(Led1RedPin,digitalRead(Led1RedPin)^1); + } + // Process Radio IRQ + if(Get_NIRQ()) + { + Radio.IrqProcess( ); + } + + } + + + + +void OnTxDone( void ) +{ +// Radio.Sleep( ); + State = TX; +} + +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) +{ +// Radio.Sleep( ); + BufferSize = size; + memcpy( Buffer, payload, BufferSize ); + RssiValue = rssi; + SnrValue = snr; + State = RX; +} + +void OnTxTimeout( void ) +{ + // Radio.Sleep( ); + State = TX_TIMEOUT; +} + +void OnRxTimeout( void ) +{ + // Radio.Sleep( ); + State = RX_TIMEOUT; +} + +void OnRxError( void ) +{ + // Radio.Sleep( ); + State = RX_ERROR; +} diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/radio.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/radio.cpp new file mode 100644 index 00000000..1ca1b623 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/radio.cpp @@ -0,0 +1,1016 @@ +/*! + * \file radio.c + * + * \brief Radio driver API definition + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#include +#include +#include "sx126x.h" +#include "radio.h" +#include "sx126x-board.h" + +/*! + * \brief Initializes the radio + * + * \param [IN] events Structure containing the driver callback functions + */ +void RadioInit( RadioEvents_t *events ); + +/*! + * Return current radio status + * + * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] + */ +RadioState_t RadioGetStatus( void ); + +/*! + * \brief Configures the radio with the given modem + * + * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ +void RadioSetModem( uint8_t modem ); + +/*! + * \brief Sets the channel frequency + * + * \param [IN] freq Channel RF frequency + */ +void RadioSetChannel( uint32_t freq ); + +/*! + * \brief Checks if the channel is free for the given time + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] freq Channel RF frequency + * \param [IN] rssiThresh RSSI threshold + * \param [IN] maxCarrierSenseTime Max time while the RSSI is measured + * + * \retval isFree [true: Channel is free, false: Channel is not free] + */ +bool RadioIsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ); + +/*! + * \brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * \retval randomValue 32 bits random value + */ +uint32_t RadioRandom( void ); + +/*! + * \brief Sets the reception parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * \param [IN] preambleLen Sets the Preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout in number of bytes + * LoRa: timeout in symbols + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] payloadLen Sets payload length when fixed length is used + * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ +void RadioSetRxConfig( uint8_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool FreqHopOn, uint8_t HopPeriod, + bool iqInverted, bool rxContinuous ); + +/*! + * \brief Sets the transmission parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] power Sets the output power [dBm] + * \param [IN] fdev Sets the frequency deviation (FSK only) + * FSK : [Hz] + * LoRa: 0 + * \param [IN] bandwidth Sets the bandwidth (LoRa only) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] preambleLen Sets the preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] timeout Transmission timeout [ms] + */ +void RadioSetTxConfig( uint8_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool FreqHopOn, + uint8_t HopPeriod, bool iqInverted, uint32_t timeout ); + +/*! + * \brief Checks if the given RF frequency is supported by the hardware + * + * \param [IN] frequency RF frequency to be checked + * \retval isSupported [true: supported, false: unsupported] + */ +bool RadioCheckRfFrequency( uint32_t frequency ); + +/*! + * \brief Computes the packet time on air in ms for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] pktLen Packet payload length + * + * \retval airTime Computed airTime (ms) for the given packet payload length + */ +uint32_t RadioTimeOnAir( RadioModems_t modem, uint8_t pktLen ); + +/*! + * \brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * \param [IN]: buffer Buffer pointer + * \param [IN]: size Buffer size + */ +void RadioSend( uint8_t *buffer, uint8_t size ); + +/*! + * \brief Sets the radio in sleep mode + */ +void RadioSleep( void ); + +/*! + * \brief Sets the radio in standby mode + */ +void RadioStandby( void ); + +/*! + * \brief Sets the radio in reception mode for the given time + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ +void RadioRx( uint32_t timeout ); + +/*! + * \brief Start a Channel Activity Detection + */ +void RadioStartCad( void ); + +/*! + * \brief Sets the radio in continuous wave transmission mode + * + * \param [IN]: freq Channel RF frequency + * \param [IN]: power Sets the output power [dBm] + * \param [IN]: time Transmission mode timeout [s] + */ +void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ); + +/*! + * \brief Reads the current RSSI value + * + * \retval rssiValue Current RSSI value in [dBm] + */ +int16_t RadioRssi( RadioModems_t modem ); + +/*! + * \brief Writes the radio register at the specified address + * + * \param [IN]: addr Register address + * \param [IN]: data New register value + */ +void RadioWrite( uint16_t addr, uint8_t data ); + +/*! + * \brief Reads the radio register at the specified address + * + * \param [IN]: addr Register address + * \retval data Register value + */ +uint8_t RadioRead( uint16_t addr ); + +/*! + * \brief Writes multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [IN] buffer Buffer containing the new register's values + * \param [IN] size Number of registers to be written + */ +void RadioWriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Reads multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [OUT] buffer Buffer where to copy the registers data + * \param [IN] size Number of registers to be read + */ +void RadioReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Sets the maximum payload length. + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] max Maximum payload length in bytes + */ +void RadioSetMaxPayloadLength( RadioModems_t modem, uint8_t max ); + +/*! + * \brief Sets the network to public or private. Updates the sync byte. + * + * \remark Applies to LoRa modem only + * + * \param [IN] enable if true, it enables a public network + */ +void RadioSetPublicNetwork( bool enable ); + +/*! + * \brief Gets the time required for the board plus radio to get out of sleep.[ms] + * + * \retval time Radio plus board wakeup time in ms. + */ +uint32_t RadioGetWakeupTime( void ); + +/*! + * \brief Process radio irq + */ +void RadioIrqProcess( void ); + +/*! + * \brief Sets the radio in reception mode with Max LNA gain for the given time + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ +void RadioRxBoosted( uint32_t timeout ); + +/*! + * \brief Sets the Rx duty cycle management parameters + * + * \param [in] rxTime Structure describing reception timeout value + * \param [in] sleepTime Structure describing sleep timeout value + */ +void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ); + +/*! + * Radio driver structure initialization + */ + struct Radio_s Radio = +{ + RadioInit, + RadioGetStatus, + RadioSetModem, + RadioSetChannel, + RadioIsChannelFree, + RadioRandom, + RadioSetRxConfig, + RadioSetTxConfig, + RadioCheckRfFrequency, + RadioTimeOnAir, + RadioSend, + RadioSleep, + RadioStandby, + RadioRx, + RadioStartCad, + RadioSetTxContinuousWave, + RadioRssi, + RadioWrite, + RadioRead, + RadioWriteBuffer, + RadioReadBuffer, + RadioSetMaxPayloadLength, + RadioSetPublicNetwork, + RadioGetWakeupTime, + RadioIrqProcess, + // Available on SX126x only + RadioRxBoosted, + RadioSetRxDutyCycle +}; + +/* + * Local types definition + */ + + + /*! + * FSK bandwidth definition + */ +typedef struct +{ + uint32_t bandwidth; + uint8_t RegValue; +}FskBandwidth_t; + +/*! + * Precomputed FSK bandwidth registers values + */ +const FskBandwidth_t FskBandwidths[] = +{ + { 4800 , 0x1F }, + { 5800 , 0x17 }, + { 7300 , 0x0F }, + { 9700 , 0x1E }, + { 11700 , 0x16 }, + { 14600 , 0x0E }, + { 19500 , 0x1D }, + { 23400 , 0x15 }, + { 29300 , 0x0D }, + { 39000 , 0x1C }, + { 46900 , 0x14 }, + { 58600 , 0x0C }, + { 78200 , 0x1B }, + { 93800 , 0x13 }, + { 117300, 0x0B }, + { 156200, 0x1A }, + { 187200, 0x12 }, + { 234300, 0x0A }, + { 312000, 0x19 }, + { 373600, 0x11 }, + { 467000, 0x09 }, + { 500000, 0x00 }, // Invalid Bandwidth +}; + +const RadioLoRaBandwidths_t Bandwidths[] = {LORA_BW_250,LORA_BW_125, LORA_BW_062,LORA_BW_020,\ + LORA_BW_041,LORA_BW_015,LORA_BW_007,LORA_BW_500,\ + LORA_BW_031,LORA_BW_010,LORA_BW_500,LORA_BW_500,\ + LORA_BW_500,LORA_BW_500,LORA_BW_500,LORA_BW_500}; + +// SF12 SF11 SF10 SF9 SF8 SF7 +static double RadioLoRaSymbTime[3][6] = {{ 32.768, 16.384, 8.192, 4.096, 2.048, 1.024 }, // 125 KHz + { 16.384, 8.192, 4.096, 2.048, 1.024, 0.512 }, // 250 KHz + { 8.192, 4.096, 2.048, 1.024, 0.512, 0.256 }}; // 500 KHz + +uint8_t MaxPayloadLength = 0xFF; + +uint32_t TxTimeout = 0; +uint32_t RxTimeout = 0; + +bool RxContinuous = false; + + +PacketStatus_t RadioPktStatus; +uint8_t RadioRxPayload[255]; + +bool IrqFired = false; + +/* + * SX126x DIO IRQ callback functions prototype + */ + +/*! + * \brief DIO 0 IRQ callback + */ +void RadioOnDioIrq( void ); + +/*! + * \brief Tx timeout timer callback + */ +void RadioOnTxTimeoutIrq( void ); + +/*! + * \brief Rx timeout timer callback + */ +void RadioOnRxTimeoutIrq( void ); + +/* + * Private global variables + */ + + +/*! + * Holds the current network type for the radio + */ +typedef struct +{ + bool Previous; + bool Current; +}RadioPublicNetwork_t; + +static RadioPublicNetwork_t RadioPublicNetwork = { false }; + +/*! + * Radio callbacks variable + */ + RadioEvents_t* RadioEvents_Ptr; + +/* + * Public global variables + */ + +/*! + * Radio hardware and global parameters + */ +SX126x_t SX126x; + + + + +void RadioInit( RadioEvents_t *events ) +{ + RadioEvents_Ptr = events; + + SX126xInit( ); + SX126xSetStandby( STDBY_RC ); + SX126xSetRegulatorMode( USE_DCDC ); + + SX126xSetBufferBaseAddress( 0x00, 0x00 ); + SX126xSetTxParams( 0, RADIO_RAMP_200_US ); + SX126xSetDioIrqParams( IRQ_RADIO_ALL, IRQ_RADIO_ALL, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + + + IrqFired = false; +} + +RadioState_t RadioGetStatus( void ) +{ + switch( SX126xGetOperatingMode( ) ) + { + case MODE_TX: + return RF_TX_RUNNING; + case MODE_RX: + return RF_RX_RUNNING; + case RF_CAD: + return RF_CAD; + default: + return RF_IDLE; + } +} + +void RadioSetModem( uint8_t modem ) +{ + switch( modem ) + { + default: + case MODEM_FSK: + SX126xSetPacketType( PACKET_TYPE_GFSK ); + // When switching to GFSK mode the LoRa SyncWord register value is reset + // Thus, we also reset the RadioPublicNetwork variable + RadioPublicNetwork.Current = false; + break; + case MODEM_LORA: + SX126xSetPacketType( PACKET_TYPE_LORA ); + // Public/Private network register is reset when switching modems + if( RadioPublicNetwork.Current != RadioPublicNetwork.Previous ) + { + RadioPublicNetwork.Current = RadioPublicNetwork.Previous; + RadioSetPublicNetwork( RadioPublicNetwork.Current ); + } + break; + } +} + +void RadioSetChannel( uint32_t freq ) +{ + SX126xSetRfFrequency( freq ); +} + +bool RadioIsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ) +{ + bool status = true; + int16_t rssi = 0; + uint32_t carrierSenseTime = 0; + + RadioSetModem( modem ); + + RadioSetChannel( freq ); + + RadioRx( 0 ); + + DelayMs( 1 ); + + carrierSenseTime = GET_TICK_COUNT( ); + + // Perform carrier sense for maxCarrierSenseTime + while( GET_TICK_COUNT()-carrierSenseTime< maxCarrierSenseTime ) + { + rssi = RadioRssi( modem ); + + if( rssi > rssiThresh ) + { + status = false; + break; + } + } + RadioSleep( ); + return status; +} + +uint32_t RadioRandom( void ) +{ + uint8_t i; + uint32_t rnd = 0; + + /* + * Radio setup for random number generation + */ + // Set LoRa modem ON + RadioSetModem( MODEM_LORA ); + + // Set radio in continuous reception + SX126xSetRx( 0 ); + + for( i = 0; i < 32; i++ ) + { + DelayMs( 1 ); + // Unfiltered RSSI value reading. Only takes the LSB value + rnd |= ( ( uint32_t )SX126xGetRssiInst( ) & 0x01 ) << i; + } + + RadioSleep( ); + + return rnd; +} + +void RadioSetRxConfig( uint8_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) +{ + + RxContinuous = rxContinuous; + + if( fixLen == true ) + { + MaxPayloadLength = payloadLen; + } + else + { + MaxPayloadLength = 0xFF; + } + + SX126xSetStopRxTimerOnPreambleDetect( false ); + SX126xSetLoRaSymbNumTimeout( symbTimeout ); + SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA; + SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t )datarate; + SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth]; + SX126x.ModulationParams.Params.LoRa.CodingRate = ( RadioLoRaCodingRates_t )coderate; + + if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) || + ( ( bandwidth == 1 ) && ( datarate == 12 ) ) ) + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01; + } + else + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00; + } + + SX126x.PacketParams.PacketType = PACKET_TYPE_LORA; + + if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) || + ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) ) + { + if( preambleLen < 12 ) + { + SX126x.PacketParams.Params.LoRa.PreambleLength = 12; + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + + SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen; + + SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength; + SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn; + SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted; + + RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA ); + SX126xSetModulationParams( &SX126x.ModulationParams ); + SX126xSetPacketParams( &SX126x.PacketParams ); + + // Timeout Max, Timeout handled directly in SetRx function + RxTimeout = 0xFFFF; + +} + +void RadioSetTxConfig( uint8_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) +{ + + SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA; + SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t ) datarate; + SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth]; + SX126x.ModulationParams.Params.LoRa.CodingRate= ( RadioLoRaCodingRates_t )coderate; + + if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) || + ( ( bandwidth == 1 ) && ( datarate == 12 ) ) ) + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01; + } + else + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00; + } + + SX126x.PacketParams.PacketType = PACKET_TYPE_LORA; + + if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) || + ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) ) + { + if( preambleLen < 12 ) + { + SX126x.PacketParams.Params.LoRa.PreambleLength = 12; + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + + SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen; + SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength; + SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn; + SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted; + + RadioStandby( ); + RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA ); + SX126xSetModulationParams( &SX126x.ModulationParams ); + SX126xSetPacketParams( &SX126x.PacketParams ); + + + SX126xSetRfTxPower( power ); + TxTimeout = timeout; +} + +bool RadioCheckRfFrequency( uint32_t frequency ) +{ + return true; +} + +uint32_t RadioTimeOnAir( RadioModems_t modem, uint8_t pktLen ) +{ + uint32_t airTime = 0; + double ts = RadioLoRaSymbTime[SX126x.ModulationParams.Params.LoRa.Bandwidth - 4][12 - SX126x.ModulationParams.Params.LoRa.SpreadingFactor]; + // time of preamble + double tPreamble = ( SX126x.PacketParams.Params.LoRa.PreambleLength + 4.25 ) * ts; + // Symbol length of payload and time + double tmp = ceil( ( 8 * pktLen - 4 * SX126x.ModulationParams.Params.LoRa.SpreadingFactor + + 28 + 16 * SX126x.PacketParams.Params.LoRa.CrcMode - + ( ( SX126x.PacketParams.Params.LoRa.HeaderType == LORA_PACKET_FIXED_LENGTH ) ? 20 : 0 ) ) / + ( double )( 4 * ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor - + ( ( SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * + ( ( SX126x.ModulationParams.Params.LoRa.CodingRate % 4 ) + 4 ); + double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); + double tPayload = nPayload * ts; + // Time on air + double tOnAir = tPreamble + tPayload; + // return milli seconds + airTime = floor( tOnAir + 0.999 ); + + + return airTime; +} + +void RadioSend( uint8_t *buffer, uint8_t size ) +{ + SX126xSetDioIrqParams( IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_NONE, + IRQ_RADIO_NONE ); + + if( SX126xGetPacketType( ) == PACKET_TYPE_LORA ) + { + SX126x.PacketParams.Params.LoRa.PayloadLength = size; + } + else + { + SX126x.PacketParams.Params.Gfsk.PayloadLength = size; + } + SX126xSetPacketParams( &SX126x.PacketParams ); + + SX126xSendPayload( buffer, size, 0 ); + +} + +void RadioSleep( void ) +{ + SleepParams_t params = { 0 }; + + params.Fields.WarmStart = 1; + SX126xSetSleep( params.Value ); + + DelayMs( 2 ); +} + +void RadioStandby( void ) +{ + SX126xSetStandby( STDBY_RC ); +} + +void RadioRx( uint32_t timeout ) +{ + SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_NONE, + IRQ_RADIO_NONE ); + + + if( RxContinuous == true ) + { + SX126xSetRx( 0xFFFFFF ); // Rx Continuous + } + else + { + SX126xSetRx( RxTimeout << 6 ); + } +} + +void RadioRxBoosted( uint32_t timeout ) +{ + SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_NONE, + IRQ_RADIO_NONE ); + + if( RxContinuous == true ) + { + SX126xSetRxBoosted( 0xFFFFFF ); // Rx Continuous + } + else + { + SX126xSetRxBoosted( RxTimeout << 6 ); + } +} + +void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ) +{ + SX126xSetRxDutyCycle( rxTime, sleepTime ); +} + +void RadioStartCad( void ) +{ + SX126xSetCad( ); +} + +void RadioTx( uint32_t timeout ) +{ + SX126xSetTx( timeout << 6 ); +} + +void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ) +{ + SX126xSetRfFrequency( freq ); + SX126xSetRfTxPower( power ); + SX126xSetTxContinuousWave( ); + +} + +int16_t RadioRssi( RadioModems_t modem ) +{ + return SX126xGetRssiInst( ); +} + +void RadioWrite( uint16_t addr, uint8_t data ) +{ + SX126xWriteRegister( addr, data ); +} + +uint8_t RadioRead( uint16_t addr ) +{ + return SX126xReadRegister( addr ); +} + +void RadioWriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ) +{ + SX126xWriteRegisters( addr, buffer, size ); +} + +void RadioReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ) +{ + SX126xReadRegisters( addr, buffer, size ); +} + +void RadioWriteFifo( uint8_t *buffer, uint8_t size ) +{ + SX126xWriteBuffer( 0, buffer, size ); +} + +void RadioReadFifo( uint8_t *buffer, uint8_t size ) +{ + SX126xReadBuffer( 0, buffer, size ); +} + +void RadioSetMaxPayloadLength( uint8_t modem, uint8_t max ) +{ + if( modem == MODEM_LORA ) + { + SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength = max; + SX126xSetPacketParams( &SX126x.PacketParams ); + } + else + { + if( SX126x.PacketParams.Params.Gfsk.HeaderType == RADIO_PACKET_VARIABLE_LENGTH ) + { + SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength = max; + SX126xSetPacketParams( &SX126x.PacketParams ); + } + } +} + +void RadioSetPublicNetwork( bool enable ) +{ + RadioPublicNetwork.Current = RadioPublicNetwork.Previous = enable; + + RadioSetModem( MODEM_LORA ); + if( enable == true ) + { + // Change LoRa modem SyncWord + SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PUBLIC_SYNCWORD >> 8 ) & 0xFF ); + SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF ); + } + else + { + // Change LoRa modem SyncWord + SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PRIVATE_SYNCWORD >> 8 ) & 0xFF ); + SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF ); + } +} + +uint32_t RadioGetWakeupTime( void ) +{ + return( RADIO_TCXO_SETUP_TIME + RADIO_WAKEUP_TIME ); +} + +void RadioOnTxTimeoutIrq( void ) +{ + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->TxTimeout != NULL ) ) + { + RadioEvents_Ptr->TxTimeout( ); + } +} + +void RadioOnRxTimeoutIrq( void ) +{ + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxTimeout != NULL ) ) + { + RadioEvents_Ptr->RxTimeout( ); + } +} + +void RadioOnDioIrq( void ) +{ + IrqFired = true; +} + +void RadioIrqProcess( void ) +{ + + BoardDisableIrq( ); + IrqFired = false; + BoardEnableIrq( ); + + uint16_t irqRegs = SX126xGetIrqStatus( ); + SX126xClearIrqStatus( IRQ_RADIO_ALL ); + + if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->TxDone != NULL ) ) + { + RadioEvents_Ptr->TxDone( ); + } + } + + if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE ) + { + uint8_t size; + + SX126xGetPayload( RadioRxPayload, &size , 255 ); + SX126xGetPacketStatus( &RadioPktStatus ); + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxDone != NULL ) ) + { + RadioEvents_Ptr->RxDone( RadioRxPayload, size, RadioPktStatus.Params.LoRa.RssiPkt, RadioPktStatus.Params.LoRa.SnrPkt ); + } + } + + if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxError ) ) + { + RadioEvents_Ptr->RxError( ); + } + } + + if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->CadDone != NULL ) ) + { + RadioEvents_Ptr->CadDone( ( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED ) ); + } + } + + if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT ) + { + if( SX126xGetOperatingMode( ) == MODE_TX ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->TxTimeout != NULL ) ) + { + RadioEvents_Ptr->TxTimeout( ); + } + } + else if( SX126xGetOperatingMode( ) == MODE_RX ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxTimeout != NULL ) ) + { + RadioEvents_Ptr->RxTimeout( ); + } + } + } + + if( ( irqRegs & IRQ_PREAMBLE_DETECTED ) == IRQ_PREAMBLE_DETECTED ) + { + //__NOP( ); + } + + if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID ) + { + //__NOP( ); + } + + if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID ) + { + //__NOP( ); + } + + if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxTimeout != NULL ) ) + { + RadioEvents_Ptr->RxTimeout( ); + } + } +} diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/radio.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/radio.h new file mode 100644 index 00000000..b7fa8a25 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/radio.h @@ -0,0 +1,376 @@ +/*! + * \file radio.h + * + * \brief Radio driver API definition + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#ifndef __RADIO_H__ +#define __RADIO_H__ +#include "sx126x-board.h" + +/*! + * Radio driver supported modems + */ +typedef enum +{ + MODEM_FSK = 0, + MODEM_LORA, +}RadioModems_t; + +/*! + * Radio driver internal state machine states definition + */ +typedef enum +{ + RF_IDLE = 0, //!< The radio is idle + RF_RX_RUNNING, //!< The radio is in reception state + RF_TX_RUNNING, //!< The radio is in transmission state + RF_CAD, //!< The radio is doing channel activity detection +}RadioState_t; + +/*! + * \brief Radio driver callback functions + */ +typedef struct +{ + /*! + * \brief Tx Done callback prototype. + */ + void ( *TxDone )( void ); + /*! + * \brief Tx Timeout callback prototype. + */ + void ( *TxTimeout )( void ); + /*! + * \brief Rx Done callback prototype. + * + * \param [IN] payload Received buffer pointer + * \param [IN] size Received buffer size + * \param [IN] rssi RSSI value computed while receiving the frame [dBm] + * \param [IN] snr Raw SNR value given by the radio hardware + * FSK : N/A ( set to 0 ) + * LoRa: SNR value in dB + */ + void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); + /*! + * \brief Rx Timeout callback prototype. + */ + void ( *RxTimeout )( void ); + /*! + * \brief Rx Error callback prototype. + */ + void ( *RxError )( void ); + /*! + * \brief FHSS Change Channel callback prototype. + * + * \param [IN] currentChannel Index number of the current channel + */ + void ( *FhssChangeChannel )( uint8_t currentChannel ); + + /*! + * \brief CAD Done callback prototype. + * + * \param [IN] channelDetected Channel Activity detected during the CAD + */ + void ( *CadDone ) ( bool channelActivityDetected ); +}RadioEvents_t; + +/*! + * \brief Radio driver definition + */ +struct Radio_s +{ + /*! + * \brief Initializes the radio + * + * \param [IN] events Structure containing the driver callback functions + */ + void ( *Init )( RadioEvents_t *events ); + /*! + * Return current radio status + * + * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] + */ + RadioState_t ( *GetStatus )( void ); + /*! + * \brief Configures the radio with the given modem + * + * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ + void ( *SetModem )( uint8_t modem ); + /*! + * \brief Sets the channel frequency + * + * \param [IN] freq Channel RF frequency + */ + void ( *SetChannel )( uint32_t freq ); + /*! + * \brief Checks if the channel is free for the given time + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] freq Channel RF frequency + * \param [IN] rssiThresh RSSI threshold + * \param [IN] maxCarrierSenseTime Max time while the RSSI is measured + * + * \retval isFree [true: Channel is free, false: Channel is not free] + */ + bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ); + /*! + * \brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * \retval randomValue 32 bits random value + */ + uint32_t ( *Random )( void ); + /*! + * \brief Sets the reception parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * \param [IN] preambleLen Sets the Preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout in number of bytes + * LoRa: timeout in symbols + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] payloadLen Sets payload length when fixed length is used + * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] hopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ + void ( *SetRxConfig )( uint8_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ); + /*! + * \brief Sets the transmission parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] power Sets the output power [dBm] + * \param [IN] fdev Sets the frequency deviation (FSK only) + * FSK : [Hz] + * LoRa: 0 + * \param [IN] bandwidth Sets the bandwidth (LoRa only) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] preambleLen Sets the preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] hopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] timeout Transmission timeout [ms] + */ + void ( *SetTxConfig )( uint8_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ); + /*! + * \brief Checks if the given RF frequency is supported by the hardware + * + * \param [IN] frequency RF frequency to be checked + * \retval isSupported [true: supported, false: unsupported] + */ + bool ( *CheckRfFrequency )( uint32_t frequency ); + /*! + * \brief Computes the packet time on air in ms for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] pktLen Packet payload length + * + * \retval airTime Computed airTime (ms) for the given packet payload length + */ + uint32_t ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen ); + /*! + * \brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * \param [IN]: buffer Buffer pointer + * \param [IN]: size Buffer size + */ + void ( *Send )( uint8_t *buffer, uint8_t size ); + /*! + * \brief Sets the radio in sleep mode + */ + void ( *Sleep )( void ); + /*! + * \brief Sets the radio in standby mode + */ + void ( *Standby )( void ); + /*! + * \brief Sets the radio in reception mode for the given time + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ + void ( *Rx )( uint32_t timeout ); + /*! + * \brief Start a Channel Activity Detection + */ + void ( *StartCad )( void ); + /*! + * \brief Sets the radio in continuous wave transmission mode + * + * \param [IN]: freq Channel RF frequency + * \param [IN]: power Sets the output power [dBm] + * \param [IN]: time Transmission mode timeout [s] + */ + void ( *SetTxContinuousWave )( uint32_t freq, int8_t power, uint16_t time ); + /*! + * \brief Reads the current RSSI value + * + * \retval rssiValue Current RSSI value in [dBm] + */ + int16_t ( *Rssi )( RadioModems_t modem ); + /*! + * \brief Writes the radio register at the specified address + * + * \param [IN]: addr Register address + * \param [IN]: data New register value + */ + void ( *Write )( uint16_t addr, uint8_t data ); + /*! + * \brief Reads the radio register at the specified address + * + * \param [IN]: addr Register address + * \retval data Register value + */ + uint8_t ( *Read )( uint16_t addr ); + /*! + * \brief Writes multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [IN] buffer Buffer containing the new register's values + * \param [IN] size Number of registers to be written + */ + void ( *WriteBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size ); + /*! + * \brief Reads multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [OUT] buffer Buffer where to copy the registers data + * \param [IN] size Number of registers to be read + */ + void ( *ReadBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size ); + /*! + * \brief Sets the maximum payload length. + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] max Maximum payload length in bytes + */ + void ( *SetMaxPayloadLength )( RadioModems_t modem, uint8_t max ); + /*! + * \brief Sets the network to public or private. Updates the sync byte. + * + * \remark Applies to LoRa modem only + * + * \param [IN] enable if true, it enables a public network + */ + void ( *SetPublicNetwork )( bool enable ); + /*! + * \brief Gets the time required for the board plus radio to get out of sleep.[ms] + * + * \retval time Radio plus board wakeup time in ms. + */ + uint32_t ( *GetWakeupTime )( void ); + /*! + * \brief Process radio irq + */ + void ( *IrqProcess )( void ); + /* + * The next functions are available only on SX126x radios. + */ + /*! + * \brief Sets the radio in reception mode with Max LNA gain for the given time + * + * \remark Available on SX126x radios only. + * + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ + void ( *RxBoosted )( uint32_t timeout ); + /*! + * \brief Sets the Rx duty cycle management parameters + * + * \remark Available on SX126x radios only. + * + * \param [in] rxTime Structure describing reception timeout value + * \param [in] sleepTime Structure describing sleep timeout value + */ + void ( *SetRxDutyCycle ) ( uint32_t rxTime, uint32_t sleepTime ); +}; + +/*! + * \brief Radio driver + * + * \remark This variable is defined and initialized in the specific radio + * board implementation + */ +extern struct Radio_s Radio; +void RadioOnDioIrq( void ); + +#endif // __RADIO_H__ diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x-board.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x-board.cpp new file mode 100644 index 00000000..bd5e4cbe --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x-board.cpp @@ -0,0 +1,225 @@ +/* + ______ _ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: SX126x driver specific target board functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include "sx126x-board.h" +#include "sx126x.h" +#include +static uint8_t IrqNestLevel = 0; + +void DelayMs( uint32_t ms ) +{ + delay( ms ); +} + + void BoardDisableIrq( void ) +{ + noInterrupts(); + IrqNestLevel++; +} + + void BoardEnableIrq( void ) +{ + IrqNestLevel--; + if( IrqNestLevel == 0 ) + { + interrupts(); + } +} + +static uint16_t SpiInOut( uint16_t outData ) +{ + uint8_t rxData = 0; + + rxData = SPI.transfer(outData); + return( rxData ); +} + +/*! + * Antenna switch GPIO pins objects + */ + +void SX126xIoInit( void ) +{ + pinMode (NssPin, OUTPUT); + pinMode (NResetPin, OUTPUT); + pinMode (SwPin, OUTPUT); + + pinMode (BusyPin, INPUT); + pinMode (Dio1Pin, INPUT); + + digitalWrite(NssPin,1); + digitalWrite(NResetPin,1); + digitalWrite(SwPin,1); +} + +void SX126xReset( void ) +{ + delay( 10 ); + digitalWrite(NResetPin,0); + delay( 20 ); + digitalWrite(NResetPin,1); + delay( 10 ); +} + +void SX126xWaitOnBusy( void ) +{ + while( digitalRead(BusyPin) == 1 ); +} + +void SX126xWakeup( void ) +{ + BoardDisableIrq( ); + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_GET_STATUS ); + SpiInOut( 0x00 ); + + digitalWrite(NssPin,1); + + // Wait for chip to be ready. + SX126xWaitOnBusy( ); + + BoardEnableIrq( ); +} +void SX126xWriteCommand( uint8_t command, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( (uint8_t )command ); + + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( buffer[i] ); + } + + digitalWrite(NssPin,1); + + if( command != RADIO_SET_SLEEP ) + { + SX126xWaitOnBusy( ); + } +} + +void SX126xReadCommand( uint8_t command, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut(( uint8_t )command ); + SpiInOut( 0x00 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( 0 ); + } + + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} + +void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + digitalWrite(NssPin,0); + SpiInOut( RADIO_WRITE_REGISTER ); + SpiInOut( ( address & 0xFF00 ) >> 8 ); + SpiInOut( address & 0x00FF ); + + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( buffer[i] ); + } + + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} + +void SX126xWriteRegister( uint16_t address, uint8_t value ) +{ + SX126xWriteRegisters( address, &value, 1 ); +} + +void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_READ_REGISTER ); + SpiInOut( ( address & 0xFF00 ) >> 8 ); + SpiInOut( address & 0x00FF ); + SpiInOut( 0 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( 0 ); + } + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} +uint8_t SX126xReadRegister( uint16_t address ) +{ + uint8_t data; + SX126xReadRegisters( address, &data, 1 ); + return data; +} + +void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_WRITE_BUFFER ); + SpiInOut( offset ); + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( buffer[i] ); + } + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} +void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_READ_BUFFER ); + SpiInOut( offset ); + SpiInOut( 0 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( 0 ); + } + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} +void SX126xSetRfTxPower( int8_t power ) +{ + SX126xSetTxParams( power, RADIO_RAMP_40_US ); +} +bool SX126xCheckRfFrequency( uint32_t frequency ) +{ + // Implement check. Currently all frequencies are supported + return true; +} \ No newline at end of file diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x-board.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x-board.h new file mode 100644 index 00000000..4c54175b --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x-board.h @@ -0,0 +1,137 @@ +/* + ______ _ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: SX126x driver specific target board functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __SX126x_ARCH_H__ +#define __SX126x_ARCH_H__ +#include +#include +#include "sx126x.h" + +#define USER_MODE_TX 1 +#define USER_MODE_RX 0 + +extern uint32_t TickCounter; + + +const int BusyPin = 3; +const int Dio2Pin = 4; +const int Dio1Pin = 5; +const int NssPin = 7; +const int SwPin = 8; + +const int Led1RedPin = 16; +const int Led1BluePin = 15; +const int NResetPin = 14; + + +#define GET_TICK_COUNT() TickCounter +#define TICK_RATE_MS( ms ) ( ms ) + +void DelayMs( uint32_t ms ); +void BoardDisableIrq( void ); +void BoardEnableIrq( void ); + +/*! + * \brief Initializes the radio I/Os pins interface + */ +void SX126xIoInit( void ); + +/*! + * \brief Initializes DIO IRQ handlers + * + * \param [IN] irqHandlers Array containing the IRQ callback functions + */ +void SX126xIoIrqInit( void ); + +/*! + * \brief De-initializes the radio I/Os pins interface. + * + * \remark Useful when going in MCU low power modes + */ +void SX126xIoDeInit( void ); + +/*! + * \brief HW Reset of the radio + */ +void SX126xReset( void ); + +/*! + * \brief Blocking loop to wait while the Busy pin in high + */ +void SX126xWaitOnBusy( void ); + +/*! + * \brief Wakes up the radio + */ +void SX126xWakeup( void ); + +/*! + * \brief Send a command that write data to the radio + * + * \param [in] opcode Opcode of the command + * \param [in] buffer Buffer to be send to the radio + * \param [in] size Size of the buffer to send + */ +void SX126xWriteCommand( uint8_t opcode, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Send a command that read data from the radio + * + * \param [in] opcode Opcode of the command + * \param [out] buffer Buffer holding data from the radio + * \param [in] size Size of the buffer + */ +void SX126xReadCommand( uint8_t opcode, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Write a single byte of data to the radio memory + * + * \param [in] address The address of the first byte to write in the radio + * \param [in] value The data to be written in radio's memory + */ +void SX126xWriteRegister( uint16_t address, uint8_t value ); + +/*! + * \brief Read a single byte of data from the radio memory + * + * \param [in] address The address of the first byte to write in the radio + * + * \retval value The value of the byte at the given address in radio's memory + */ +uint8_t SX126xReadRegister( uint16_t address ); + +/*! + * \brief Sets the radio output power. + * + * \param [IN] power Sets the RF output power + */ +void SX126xSetRfTxPower( int8_t power ); + + +/*! + * \brief Checks if the given RF frequency is supported by the hardware + * + * \param [IN] frequency RF frequency to be checked + * \retval isSupported [true: supported, false: unsupported] + */ +bool SX126xCheckRfFrequency( uint32_t frequency ); + +/*! + * Radio hardware and global parameters + */ +extern SX126x_t SX126x; + + +#endif // __SX126x_ARCH_H__ diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x.cpp new file mode 100644 index 00000000..e728dd28 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x.cpp @@ -0,0 +1,693 @@ +/*! + * \file sx126x.c + * + * \brief SX126x driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#include +#include +#include "sx126x.h" +#include "sx126x-board.h" + +/*! + * \brief Radio registers definition + */ +typedef struct +{ + uint16_t Addr; //!< The address of the register + uint8_t Value; //!< The value of the register +}RadioRegisters_t; + +/*! + * \brief Holds the internal operating mode of the radio + */ +static RadioOperatingModes_t OperatingMode; + +/*! + * \brief Stores the current packet type set in the radio + */ +static RadioPacketTypes_t PacketType; + +/*! + * \brief Stores the last frequency error measured on LoRa received packet + */ +volatile uint32_t FrequencyError = 0; + +/*! + * \brief Hold the status of the Image calibration + */ +static bool ImageCalibrated = false; + +/* + * SX126x DIO IRQ callback functions prototype + */ + +/*! + * \brief DIO 0 IRQ callback + */ +void SX126xOnDioIrq( void ); + +/*! + * \brief DIO 0 IRQ callback + */ +void SX126xSetPollingMode( void ); + +/*! + * \brief DIO 0 IRQ callback + */ +void SX126xSetInterruptMode( void ); + +/* + * \brief Process the IRQ if handled by the driver + */ +void SX126xProcessIrqs( void ); + + +void SX126xInit( void ) +{ + SX126xReset( ); + SX126xWakeup( ); + SX126xSetStandby( STDBY_RC ); + +#ifdef USE_TCXO + CalibrationParams_t calibParam; + + SX126xSetDio3AsTcxoCtrl( TCXO_CTRL_3_3V, RADIO_TCXO_SETUP_TIME << 6 ); // convert from ms to SX126x time base + calibParam.Value = 0x7F; + SX126xCalibrate( calibParam.Value ); +#endif + + SX126xSetDio2AsRfSwitchCtrl( true ); + OperatingMode = MODE_STDBY_RC; +} + +uint8_t SX126xGetOperatingMode( void ) +{ + return OperatingMode; +} + +void SX126xCheckDeviceReady( void ) +{ + if( ( SX126xGetOperatingMode( ) == MODE_SLEEP ) || ( SX126xGetOperatingMode( ) == MODE_RX_DC ) ) + { + SX126xWakeup( ); + + } + SX126xWaitOnBusy( ); +} + +void SX126xSetPayload( uint8_t *payload, uint8_t size ) +{ + SX126xWriteBuffer( 0x00, payload, size ); +} + +uint8_t SX126xGetPayload( uint8_t *buffer, uint8_t *size, uint8_t maxSize ) +{ + uint8_t offset = 0; + + SX126xGetRxBufferStatus( size, &offset ); + if( *size > maxSize ) + { + return 1; + } + SX126xReadBuffer( offset, buffer, *size ); + return 0; +} + +void SX126xSendPayload( uint8_t *payload, uint8_t size, uint32_t timeout ) +{ + SX126xSetPayload( payload, size ); + SX126xSetTx( timeout ); +} + +uint8_t SX126xSetSyncWord( uint8_t *syncWord ) +{ + SX126xWriteRegisters( REG_LR_SYNCWORDBASEADDRESS, syncWord, 8 ); + return 0; +} + +void SX126xSetCrcSeed( uint16_t seed ) +{ + uint8_t buf[2]; + + buf[0] = ( uint8_t )( ( seed >> 8 ) & 0xFF ); + buf[1] = ( uint8_t )( seed & 0xFF ); + + switch( SX126xGetPacketType( ) ) + { + case PACKET_TYPE_GFSK: + SX126xWriteRegisters( REG_LR_CRCSEEDBASEADDR, buf, 2 ); + break; + + default: + break; + } +} + +void SX126xSetCrcPolynomial( uint16_t polynomial ) +{ + uint8_t buf[2]; + + buf[0] = ( uint8_t )( ( polynomial >> 8 ) & 0xFF ); + buf[1] = ( uint8_t )( polynomial & 0xFF ); + + switch( SX126xGetPacketType( ) ) + { + case PACKET_TYPE_GFSK: + SX126xWriteRegisters( REG_LR_CRCPOLYBASEADDR, buf, 2 ); + break; + + default: + break; + } +} + +void SX126xSetWhiteningSeed( uint16_t seed ) +{ + uint8_t regValue = 0; + + switch( SX126xGetPacketType( ) ) + { + case PACKET_TYPE_GFSK: + regValue = SX126xReadRegister( REG_LR_WHITSEEDBASEADDR_MSB ) & 0xFE; + regValue = ( ( seed >> 8 ) & 0x01 ) | regValue; + SX126xWriteRegister( REG_LR_WHITSEEDBASEADDR_MSB, regValue ); // only 1 bit. + SX126xWriteRegister( REG_LR_WHITSEEDBASEADDR_LSB, ( uint8_t )seed ); + break; + + default: + break; + } +} + +uint32_t SX126xGetRandom( void ) +{ + uint8_t buf[] = { 0, 0, 0, 0 }; + uint32_t ret_val = 0; + // Set radio in continuous reception + SX126xSetRx( 0 ); + + DelayMs( 1 ); + + SX126xReadRegisters( RANDOM_NUMBER_GENERATORBASEADDR, buf, 4 ); + + SX126xSetStandby( STDBY_RC ); + ret_val |= buf[0]; + ret_val = (ret_val<<8)+buf[1] ; + ret_val = (ret_val<<8)+buf[2] ; + ret_val = (ret_val<<8)+buf[3] ; + + return ret_val; +} + +void SX126xSetSleep( uint8_t sleepConfig ) +{ + + SX126xWriteCommand( RADIO_SET_SLEEP, &sleepConfig, 1 ); + OperatingMode = MODE_SLEEP; +} + +void SX126xSetStandby( uint8_t standbyConfig ) +{ + SX126xWriteCommand( RADIO_SET_STANDBY, ( uint8_t* )&standbyConfig, 1 ); + if( standbyConfig == STDBY_RC ) + { + OperatingMode = MODE_STDBY_RC; + } + else + { + OperatingMode = MODE_STDBY_XOSC; + } +} + +void SX126xSetFs( void ) +{ + SX126xWriteCommand( RADIO_SET_FS, 0, 0 ); + OperatingMode = MODE_FS; +} + +void SX126xSetTx( uint32_t timeout ) +{ + uint8_t buf[3]; + + OperatingMode = MODE_TX; + + buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( timeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_TX, buf, 3 ); +} + +void SX126xSetRx( uint32_t timeout ) +{ + uint8_t buf[3]; + + OperatingMode = MODE_RX; + + buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( timeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_RX, buf, 3 ); +} + +void SX126xSetRxBoosted( uint32_t timeout ) +{ + uint8_t buf[3]; + + OperatingMode = MODE_RX; + + SX126xWriteRegister( REG_RX_GAIN, 0x96 ); // max LNA gain, increase current by ~2mA for around ~3dB in sensivity + + buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( timeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_RX, buf, 3 ); +} + +void SX126xSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ) +{ + uint8_t buf[6]; + + buf[0] = ( uint8_t )( ( rxTime >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( rxTime >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( rxTime & 0xFF ); + buf[3] = ( uint8_t )( ( sleepTime >> 16 ) & 0xFF ); + buf[4] = ( uint8_t )( ( sleepTime >> 8 ) & 0xFF ); + buf[5] = ( uint8_t )( sleepTime & 0xFF ); + SX126xWriteCommand( RADIO_SET_RXDUTYCYCLE, buf, 6 ); + OperatingMode = MODE_RX_DC; +} + +void SX126xSetCad( void ) +{ + SX126xWriteCommand( RADIO_SET_CAD, 0, 0 ); + OperatingMode = MODE_CAD; +} + +void SX126xSetTxContinuousWave( void ) +{ + SX126xWriteCommand( RADIO_SET_TXCONTINUOUSWAVE, 0, 0 ); +} + +void SX126xSetTxInfinitePreamble( void ) +{ + SX126xWriteCommand( RADIO_SET_TXCONTINUOUSPREAMBLE, 0, 0 ); +} + +void SX126xSetStopRxTimerOnPreambleDetect( bool enable ) +{ + SX126xWriteCommand( RADIO_SET_STOPRXTIMERONPREAMBLE, ( uint8_t* )&enable, 1 ); +} + +void SX126xSetLoRaSymbNumTimeout( uint8_t SymbNum ) +{ + SX126xWriteCommand( RADIO_SET_LORASYMBTIMEOUT, &SymbNum, 1 ); +} + +void SX126xSetRegulatorMode( uint8_t mode ) +{ + SX126xWriteCommand( RADIO_SET_REGULATORMODE, ( uint8_t* )&mode, 1 ); +} + +void SX126xCalibrate( uint8_t calibParam ) +{ + SX126xWriteCommand( RADIO_CALIBRATE, ( uint8_t* )&calibParam, 1 ); +} + +void SX126xCalibrateImage( uint32_t freq ) +{ + uint8_t calFreq[2]; + + if( freq > 900000000 ) + { + calFreq[0] = 0xE1; + calFreq[1] = 0xE9; + } + else if( freq > 850000000 ) + { + calFreq[0] = 0xD7; + calFreq[1] = 0xD8; + } + else if( freq > 770000000 ) + { + calFreq[0] = 0xC1; + calFreq[1] = 0xC5; + } + else if( freq > 460000000 ) + { + calFreq[0] = 0x75; + calFreq[1] = 0x81; + } + else if( freq > 425000000 ) + { + calFreq[0] = 0x6B; + calFreq[1] = 0x6F; + } + SX126xWriteCommand( RADIO_CALIBRATEIMAGE, calFreq, 2 ); +} + +void SX126xSetPaConfig( uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut ) +{ + uint8_t buf[4]; + + buf[0] = paDutyCycle; + buf[1] = hpMax; + buf[2] = deviceSel; + buf[3] = paLut; + SX126xWriteCommand( RADIO_SET_PACONFIG, buf, 4 ); +} + +void SX126xSetRxTxFallbackMode( uint8_t fallbackMode ) +{ + SX126xWriteCommand( RADIO_SET_TXFALLBACKMODE, &fallbackMode, 1 ); +} + +void SX126xSetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ) +{ + uint8_t buf[8]; + + buf[0] = ( uint8_t )( ( irqMask >> 8 ) & 0x00FF ); + buf[1] = ( uint8_t )( irqMask & 0x00FF ); + buf[2] = ( uint8_t )( ( dio1Mask >> 8 ) & 0x00FF ); + buf[3] = ( uint8_t )( dio1Mask & 0x00FF ); + buf[4] = ( uint8_t )( ( dio2Mask >> 8 ) & 0x00FF ); + buf[5] = ( uint8_t )( dio2Mask & 0x00FF ); + buf[6] = ( uint8_t )( ( dio3Mask >> 8 ) & 0x00FF ); + buf[7] = ( uint8_t )( dio3Mask & 0x00FF ); + SX126xWriteCommand( RADIO_CFG_DIOIRQ, buf, 8 ); +} + +uint16_t SX126xGetIrqStatus( void ) +{ + uint8_t irqStatus[2]; + + SX126xReadCommand( RADIO_GET_IRQSTATUS, irqStatus, 2 ); + return ( irqStatus[0] << 8 ) | irqStatus[1]; +} + +void SX126xSetDio2AsRfSwitchCtrl( uint8_t enable ) +{ + SX126xWriteCommand( RADIO_SET_RFSWITCHMODE, &enable, 1 ); +} + +void SX126xSetDio3AsTcxoCtrl( uint8_t tcxoVoltage, uint32_t timeout ) +{ + uint8_t buf[4]; + + buf[0] = tcxoVoltage & 0x07; + buf[1] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[2] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[3] = ( uint8_t )( timeout & 0xFF ); + + SX126xWriteCommand( RADIO_SET_TCXOMODE, buf, 4 ); +} + +void SX126xSetRfFrequency( uint32_t frequency ) +{ + uint8_t buf[4]; + uint32_t freq = 0; + + if( ImageCalibrated == false ) + { + SX126xCalibrateImage( frequency ); + ImageCalibrated = true; + } + + freq = ( uint32_t )( ( double )frequency / ( double )FREQ_STEP ); + buf[0] = ( uint8_t )( ( freq >> 24 ) & 0xFF ); + buf[1] = ( uint8_t )( ( freq >> 16 ) & 0xFF ); + buf[2] = ( uint8_t )( ( freq >> 8 ) & 0xFF ); + buf[3] = ( uint8_t )( freq & 0xFF ); + SX126xWriteCommand( RADIO_SET_RFFREQUENCY, buf, 4 ); +} + +void SX126xSetPacketType( RadioPacketTypes_t packetType ) +{ + // Save packet type internally to avoid questioning the radio + PacketType = packetType; + SX126xWriteCommand( RADIO_SET_PACKETTYPE, ( uint8_t* )&packetType, 1 ); +} + +RadioPacketTypes_t SX126xGetPacketType( void ) +{ + return PacketType; +} + +void SX126xSetTxParams( int8_t power, uint8_t rampTime ) +{ + uint8_t buf[2]; + + + SX126xSetPaConfig( 0x04, 0x07, 0x00, 0x01 ); + if( power > 22 ) + { + power = 22; + } + else if( power < -3 ) + { + power = -3; + } + SX126xWriteRegister( REG_OCP, 0x38 ); // current max 160mA for the whole device + buf[0] = power; + buf[1] = ( uint8_t )rampTime; + SX126xWriteCommand( RADIO_SET_TXPARAMS, buf, 2 ); +} + +void SX126xSetModulationParams( void *input_ptr ) +{ + uint8_t n; + uint32_t tempVal = 0; + uint8_t buf[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + ModulationParams_t* modulationParams = (ModulationParams_t*)input_ptr; + // Check if required configuration corresponds to the stored packet type + // If not, silently update radio packet type + if( PacketType != modulationParams->PacketType ) + { + SX126xSetPacketType( modulationParams->PacketType ); + } + + switch( modulationParams->PacketType ) + { + case PACKET_TYPE_GFSK: + n = 8; + tempVal = ( uint32_t )( 32 * ( ( double )XTAL_FREQ / ( double )modulationParams->Params.Gfsk.BitRate ) ); + buf[0] = ( tempVal >> 16 ) & 0xFF; + buf[1] = ( tempVal >> 8 ) & 0xFF; + buf[2] = tempVal & 0xFF; + buf[3] = modulationParams->Params.Gfsk.ModulationShaping; + buf[4] = modulationParams->Params.Gfsk.Bandwidth; + tempVal = ( uint32_t )( ( double )modulationParams->Params.Gfsk.Fdev / ( double )FREQ_STEP ); + buf[5] = ( tempVal >> 16 ) & 0xFF; + buf[6] = ( tempVal >> 8 ) & 0xFF; + buf[7] = ( tempVal& 0xFF ); + SX126xWriteCommand( RADIO_SET_MODULATIONPARAMS, buf, n ); + break; + case PACKET_TYPE_LORA: + n = 4; + buf[0] = modulationParams->Params.LoRa.SpreadingFactor; + buf[1] = modulationParams->Params.LoRa.Bandwidth; + buf[2] = modulationParams->Params.LoRa.CodingRate; + buf[3] = modulationParams->Params.LoRa.LowDatarateOptimize; + + SX126xWriteCommand( RADIO_SET_MODULATIONPARAMS, buf, n ); + + break; + default: + case PACKET_TYPE_NONE: + return; + } +} + +void SX126xSetPacketParams( void* input_ptr ) +{ + uint8_t n; + uint8_t crcVal = 0; + uint8_t buf[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + PacketParams_t* packetParams = (PacketParams_t*)input_ptr; + // Check if required configuration corresponds to the stored packet type + // If not, silently update radio packet type + if( PacketType != packetParams->PacketType ) + { + SX126xSetPacketType( packetParams->PacketType ); + } + + switch( packetParams->PacketType ) + { + case PACKET_TYPE_GFSK: + if( packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_IBM ) + { + SX126xSetCrcSeed( CRC_IBM_SEED ); + SX126xSetCrcPolynomial( CRC_POLYNOMIAL_IBM ); + crcVal = RADIO_CRC_2_BYTES; + } + else if( packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_CCIT ) + { + SX126xSetCrcSeed( CRC_CCITT_SEED ); + SX126xSetCrcPolynomial( CRC_POLYNOMIAL_CCITT ); + crcVal = RADIO_CRC_2_BYTES_INV; + } + else + { + crcVal = packetParams->Params.Gfsk.CrcLength; + } + n = 9; + buf[0] = ( packetParams->Params.Gfsk.PreambleLength >> 8 ) & 0xFF; + buf[1] = packetParams->Params.Gfsk.PreambleLength; + buf[2] = packetParams->Params.Gfsk.PreambleMinDetect; + buf[3] = ( packetParams->Params.Gfsk.SyncWordLength /*<< 3*/ ); // convert from byte to bit + buf[4] = packetParams->Params.Gfsk.AddrComp; + buf[5] = packetParams->Params.Gfsk.HeaderType; + buf[6] = packetParams->Params.Gfsk.PayloadLength; + buf[7] = crcVal; + buf[8] = packetParams->Params.Gfsk.DcFree; + break; + case PACKET_TYPE_LORA: + n = 6; + buf[0] = ( packetParams->Params.LoRa.PreambleLength >> 8 ) & 0xFF; + buf[1] = packetParams->Params.LoRa.PreambleLength; + buf[2] = packetParams->Params.LoRa.HeaderType; + buf[3] = packetParams->Params.LoRa.PayloadLength; + buf[4] = packetParams->Params.LoRa.CrcMode; + buf[5] = packetParams->Params.LoRa.InvertIQ; + break; + default: + case PACKET_TYPE_NONE: + return; + } + SX126xWriteCommand( RADIO_SET_PACKETPARAMS, buf, n ); +} + +void SX126xSetCadParams( uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout ) +{ + uint8_t buf[7]; + + buf[0] = ( uint8_t )cadSymbolNum; + buf[1] = cadDetPeak; + buf[2] = cadDetMin; + buf[3] = ( uint8_t )cadExitMode; + buf[4] = ( uint8_t )( ( cadTimeout >> 16 ) & 0xFF ); + buf[5] = ( uint8_t )( ( cadTimeout >> 8 ) & 0xFF ); + buf[6] = ( uint8_t )( cadTimeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_CADPARAMS, buf, 5 ); + OperatingMode = MODE_CAD; +} + +void SX126xSetBufferBaseAddress( uint8_t txBaseAddress, uint8_t rxBaseAddress ) +{ + uint8_t buf[2]; + + buf[0] = txBaseAddress; + buf[1] = rxBaseAddress; + SX126xWriteCommand( RADIO_SET_BUFFERBASEADDRESS, buf, 2 ); +} + +uint8_t SX126xGetStatus( void ) +{ + uint8_t stat = 0; + + SX126xReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 ); + + return stat; +} + +int8_t SX126xGetRssiInst( void ) +{ + uint8_t buf[1]; + int8_t rssi = 0; + + SX126xReadCommand( RADIO_GET_RSSIINST, buf, 1 ); + rssi = -buf[0] >> 1; + return rssi; +} + +void SX126xGetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPointer ) +{ + uint8_t status[2]; + + SX126xReadCommand( RADIO_GET_RXBUFFERSTATUS, status, 2 ); + + // In case of LORA fixed header, the payloadLength is obtained by reading + // the register REG_LR_PAYLOADLENGTH + if( ( SX126xGetPacketType( ) == PACKET_TYPE_LORA ) && ( SX126xReadRegister( REG_LR_PACKETPARAMS ) >> 7 == 1 ) ) + { + *payloadLength = SX126xReadRegister( REG_LR_PAYLOADLENGTH ); + } + else + { + *payloadLength = status[0]; + } + *rxStartBufferPointer = status[1]; +} + +void SX126xGetPacketStatus( void* input_ptr ) +{ + uint8_t status[3]; + PacketStatus_t *pktStatus = (PacketStatus_t *)input_ptr; + + SX126xReadCommand( RADIO_GET_PACKETSTATUS, status, 3 ); + + pktStatus->packetType = SX126xGetPacketType( ); + switch( pktStatus->packetType ) + { + case PACKET_TYPE_GFSK: + pktStatus->Params.Gfsk.RxStatus = status[0]; + pktStatus->Params.Gfsk.RssiSync = -status[1] >> 1; + pktStatus->Params.Gfsk.RssiAvg = -status[2] >> 1; + pktStatus->Params.Gfsk.FreqError = 0; + break; + + case PACKET_TYPE_LORA: + pktStatus->Params.LoRa.RssiPkt = -status[0] >> 1; + ( status[1] < 128 ) ? ( pktStatus->Params.LoRa.SnrPkt = status[1] >> 2 ) : ( pktStatus->Params.LoRa.SnrPkt = ( ( status[1] - 256 ) >> 2 ) ); + pktStatus->Params.LoRa.SignalRssiPkt = -status[2] >> 1; + pktStatus->Params.LoRa.FreqError = FrequencyError; + break; + + default: + case PACKET_TYPE_NONE: + // In that specific case, we set everything in the pktStatus to zeros + // and reset the packet type accordingly + memset( pktStatus, 0, sizeof( PacketStatus_t ) ); + pktStatus->packetType = PACKET_TYPE_NONE; + break; + } +} + +uint16_t SX126xGetDeviceErrors( void ) +{ + uint16_t error; + + SX126xReadCommand( RADIO_GET_ERROR, ( uint8_t * )&error, 2 ); + return error; +} + +void SX126xClearDeviceErrors( void ) +{ + uint8_t buf[2] = { 0x00, 0x00 }; + SX126xWriteCommand( RADIO_CLR_ERROR, buf, 2 ); +} + +void SX126xClearIrqStatus( uint16_t irq ) +{ + uint8_t buf[2]; + + buf[0] = ( uint8_t )( ( ( uint16_t )irq >> 8 ) & 0x00FF ); + buf[1] = ( uint8_t )( ( uint16_t )irq & 0x00FF ); + SX126xWriteCommand( RADIO_CLR_IRQSTATUS, buf, 2 ); +} diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x.h new file mode 100644 index 00000000..012124dc --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/sx126x.h @@ -0,0 +1,1115 @@ +/*! + * \file sx126x.h + * + * \brief SX126x driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#ifndef __SX126x_H__ +#define __SX126x_H__ +#include "stdint.h" +#include "stdbool.h" + + +#define USE_TCXO +#define SX1261 1 +#define SX1262 2 + +#ifdef USE_TCXO + /*! + * Radio complete Wake-up Time with TCXO stabilisation time + */ + #define RADIO_TCXO_SETUP_TIME 5 // [ms] +#else + /*! + * Radio complete Wake-up Time with TCXO stabilisation time + */ + #define RADIO_TCXO_SETUP_TIME 0 // No Used +#endif + +/*! + * Radio complete Wake-up Time with margin for temperature compensation + */ +#define RADIO_WAKEUP_TIME 3 // [ms] + +/*! + * \brief Compensation delay for SetAutoTx/Rx functions in 15.625 microseconds + */ +#define AUTO_RX_TX_OFFSET 2 + +/*! + * \brief LFSR initial value to compute IBM type CRC + */ +#define CRC_IBM_SEED 0xFFFF + +/*! + * \brief LFSR initial value to compute CCIT type CRC + */ +#define CRC_CCITT_SEED 0x1D0F + +/*! + * \brief Polynomial used to compute IBM CRC + */ +#define CRC_POLYNOMIAL_IBM 0x8005 + +/*! + * \brief Polynomial used to compute CCIT CRC + */ +#define CRC_POLYNOMIAL_CCITT 0x1021 + +/*! + * \brief The address of the register holding the first byte defining the CRC seed + * + */ +#define REG_LR_CRCSEEDBASEADDR 0x06BC + +/*! + * \brief The address of the register holding the first byte defining the CRC polynomial + */ +#define REG_LR_CRCPOLYBASEADDR 0x06BE + +/*! + * \brief The address of the register holding the first byte defining the whitening seed + */ +#define REG_LR_WHITSEEDBASEADDR_MSB 0x06B8 +#define REG_LR_WHITSEEDBASEADDR_LSB 0x06B9 + +/*! + * \brief The address of the register holding the packet configuration + */ +#define REG_LR_PACKETPARAMS 0x0704 + +/*! + * \brief The address of the register holding the payload size + */ +#define REG_LR_PAYLOADLENGTH 0x0702 + +/*! + * \brief The addresses of the registers holding SyncWords values + */ +#define REG_LR_SYNCWORDBASEADDRESS 0x06C0 + +/*! + * \brief The addresses of the register holding LoRa Modem SyncWord value + */ +#define REG_LR_SYNCWORD 0x0740 + +/*! + * Syncword for Private LoRa networks + */ +#define LORA_MAC_PRIVATE_SYNCWORD 0x1424 + +/*! + * Syncword for Public LoRa networks + */ +#define LORA_MAC_PUBLIC_SYNCWORD 0x3444 + +/*! + * The address of the register giving a 4 bytes random number + */ +#define RANDOM_NUMBER_GENERATORBASEADDR 0x0819 + +/*! + * The address of the register holding RX Gain value (0x94: power saving, 0x96: rx boosted) + */ +#define REG_RX_GAIN 0x08AC + +/*! + * Change the value on the device internal trimming capacitor + */ +#define REG_XTA_TRIM 0x0911 + +/*! + * Set the current max value in the over current protection + */ +#define REG_OCP 0x08E7 + +/*! + * \brief Structure describing the radio status + */ +typedef union RadioStatus_u +{ + uint8_t Value; + struct + { //bit order is lsb -> msb + uint8_t Reserved : 1; //!< Reserved + uint8_t CmdStatus : 3; //!< Command status + uint8_t ChipMode : 3; //!< Chip mode + uint8_t CpuBusy : 1; //!< Flag for CPU radio busy + }Fields; +}RadioStatus_t; + +/*! + * \brief Structure describing the error codes for callback functions + */ +typedef enum +{ + IRQ_HEADER_ERROR_CODE = 0x01, + IRQ_SYNCWORD_ERROR_CODE = 0x02, + IRQ_CRC_ERROR_CODE = 0x04, +}IrqErrorCode_t; + +enum IrqPblSyncHeaderCode_t +{ + IRQ_PBL_DETECT_CODE = 0x01, + IRQ_SYNCWORD_VALID_CODE = 0x02, + IRQ_HEADER_VALID_CODE = 0x04, +}; + +/*! + * \brief Represents the operating mode the radio is actually running + */ +typedef enum +{ + MODE_SLEEP = 0x00, //! The radio is in sleep mode + MODE_STDBY_RC, //! The radio is in standby mode with RC oscillator + MODE_STDBY_XOSC, //! The radio is in standby mode with XOSC oscillator + MODE_FS, //! The radio is in frequency synthesis mode + MODE_TX, //! The radio is in transmit mode + MODE_RX, //! The radio is in receive mode + MODE_RX_DC, //! The radio is in receive duty cycle mode + MODE_CAD //! The radio is in channel activity detection mode +}RadioOperatingModes_t; + +/*! + * \brief Declares the oscillator in use while in standby mode + * + * Using the STDBY_RC standby mode allow to reduce the energy consumption + * STDBY_XOSC should be used for time critical applications + */ +typedef enum +{ + STDBY_RC = 0x00, + STDBY_XOSC = 0x01, +}RadioStandbyModes_t; + +/*! + * \brief Declares the power regulation used to power the device + * + * This command allows the user to specify if DC-DC or LDO is used for power regulation. + * Using only LDO implies that the Rx or Tx current is doubled + */ +typedef enum +{ + USE_LDO = 0x00, // default + USE_DCDC = 0x01, +}RadioRegulatorMode_t; + +/*! + * \brief Represents the possible packet type (i.e. modem) used + */ +typedef enum +{ + PACKET_TYPE_GFSK = 0x00, + PACKET_TYPE_LORA = 0x01, + PACKET_TYPE_NONE = 0x0F, +}RadioPacketTypes_t; + +/*! + * \brief Represents the ramping time for power amplifier + */ +typedef enum +{ + RADIO_RAMP_10_US = 0x00, + RADIO_RAMP_20_US = 0x01, + RADIO_RAMP_40_US = 0x02, + RADIO_RAMP_80_US = 0x03, + RADIO_RAMP_200_US = 0x04, + RADIO_RAMP_800_US = 0x05, + RADIO_RAMP_1700_US = 0x06, + RADIO_RAMP_3400_US = 0x07, +}RadioRampTimes_t; + +/*! + * \brief Represents the number of symbols to be used for channel activity detection operation + */ +typedef enum +{ + LORA_CAD_01_SYMBOL = 0x00, + LORA_CAD_02_SYMBOL = 0x01, + LORA_CAD_04_SYMBOL = 0x02, + LORA_CAD_08_SYMBOL = 0x03, + LORA_CAD_16_SYMBOL = 0x04, +}RadioLoRaCadSymbols_t; + +/*! + * \brief Represents the Channel Activity Detection actions after the CAD operation is finished + */ +typedef enum +{ + LORA_CAD_ONLY = 0x00, + LORA_CAD_RX = 0x01, + LORA_CAD_LBT = 0x10, +}RadioCadExitModes_t; + +/*! + * \brief Represents the modulation shaping parameter + */ +typedef enum +{ + MOD_SHAPING_OFF = 0x00, + MOD_SHAPING_G_BT_03 = 0x08, + MOD_SHAPING_G_BT_05 = 0x09, + MOD_SHAPING_G_BT_07 = 0x0A, + MOD_SHAPING_G_BT_1 = 0x0B, +}RadioModShapings_t; + +/*! + * \brief Represents the modulation shaping parameter + */ +typedef enum +{ + RX_BW_4800 = 0x1F, + RX_BW_5800 = 0x17, + RX_BW_7300 = 0x0F, + RX_BW_9700 = 0x1E, + RX_BW_11700 = 0x16, + RX_BW_14600 = 0x0E, + RX_BW_19500 = 0x1D, + RX_BW_23400 = 0x15, + RX_BW_29300 = 0x0D, + RX_BW_39000 = 0x1C, + RX_BW_46900 = 0x14, + RX_BW_58600 = 0x0C, + RX_BW_78200 = 0x1B, + RX_BW_93800 = 0x13, + RX_BW_117300 = 0x0B, + RX_BW_156200 = 0x1A, + RX_BW_187200 = 0x12, + RX_BW_234300 = 0x0A, + RX_BW_312000 = 0x19, + RX_BW_373600 = 0x11, + RX_BW_467000 = 0x09, +}RadioRxBandwidth_t; + +/*! + * \brief Represents the possible spreading factor values in LoRa packet types + */ +typedef enum +{ + LORA_SF5 = 0x05, + LORA_SF6 = 0x06, + LORA_SF7 = 0x07, + LORA_SF8 = 0x08, + LORA_SF9 = 0x09, + LORA_SF10 = 0x0A, + LORA_SF11 = 0x0B, + LORA_SF12 = 0x0C, +}RadioLoRaSpreadingFactors_t; + +/*! + * \brief Represents the bandwidth values for LoRa packet type + */ +typedef enum +{ + LORA_BW_500 = 6, + LORA_BW_250 = 5, + LORA_BW_125 = 4, + LORA_BW_062 = 3, + LORA_BW_041 = 10, + LORA_BW_031 = 2, + LORA_BW_020 = 9, + LORA_BW_015 = 1, + LORA_BW_010 = 8, + LORA_BW_007 = 0, +}RadioLoRaBandwidths_t; + +/*! + * \brief Represents the coding rate values for LoRa packet type + */ +typedef enum +{ + LORA_CR_4_5 = 0x01, + LORA_CR_4_6 = 0x02, + LORA_CR_4_7 = 0x03, + LORA_CR_4_8 = 0x04, +}RadioLoRaCodingRates_t; + +/*! + * \brief Represents the preamble length used to detect the packet on Rx side + */ +typedef enum +{ + RADIO_PREAMBLE_DETECTOR_OFF = 0x00, //!< Preamble detection length off + RADIO_PREAMBLE_DETECTOR_08_BITS = 0x04, //!< Preamble detection length 8 bits + RADIO_PREAMBLE_DETECTOR_16_BITS = 0x05, //!< Preamble detection length 16 bits + RADIO_PREAMBLE_DETECTOR_24_BITS = 0x06, //!< Preamble detection length 24 bits + RADIO_PREAMBLE_DETECTOR_32_BITS = 0x07, //!< Preamble detection length 32 bit +}RadioPreambleDetection_t; + +/*! + * \brief Represents the possible combinations of SyncWord correlators activated + */ +typedef enum +{ + RADIO_ADDRESSCOMP_FILT_OFF = 0x00, //!< No correlator turned on, i.e. do not search for SyncWord + RADIO_ADDRESSCOMP_FILT_NODE = 0x01, + RADIO_ADDRESSCOMP_FILT_NODE_BROAD = 0x02, +}RadioAddressComp_t; + +/*! + * \brief Radio GFSK packet length mode + */ +typedef enum +{ + RADIO_PACKET_FIXED_LENGTH = 0x00, //!< The packet is known on both sides, no header included in the packet + RADIO_PACKET_VARIABLE_LENGTH = 0x01, //!< The packet is on variable size, header included +}RadioPacketLengthModes_t; + +/*! + * \brief Represents the CRC length + */ +typedef enum +{ + RADIO_CRC_OFF = 0x01, //!< No CRC in use + RADIO_CRC_1_BYTES = 0x00, + RADIO_CRC_2_BYTES = 0x02, + RADIO_CRC_1_BYTES_INV = 0x04, + RADIO_CRC_2_BYTES_INV = 0x06, + RADIO_CRC_2_BYTES_IBM = 0xF1, + RADIO_CRC_2_BYTES_CCIT = 0xF2, +}RadioCrcTypes_t; + +/*! + * \brief Radio whitening mode activated or deactivated + */ +typedef enum +{ + RADIO_DC_FREE_OFF = 0x00, + RADIO_DC_FREEWHITENING = 0x01, +}RadioDcFree_t; + +/*! + * \brief Holds the Radio lengths mode for the LoRa packet type + */ +typedef enum +{ + LORA_PACKET_VARIABLE_LENGTH = 0x00, //!< The packet is on variable size, header included + LORA_PACKET_FIXED_LENGTH = 0x01, //!< The packet is known on both sides, no header included in the packet + LORA_PACKET_EXPLICIT = LORA_PACKET_VARIABLE_LENGTH, + LORA_PACKET_IMPLICIT = LORA_PACKET_FIXED_LENGTH, +}RadioLoRaPacketLengthsMode_t; + +/*! + * \brief Represents the CRC mode for LoRa packet type + */ +typedef enum +{ + LORA_CRC_ON = 0x01, //!< CRC activated + LORA_CRC_OFF = 0x00, //!< CRC not used +}RadioLoRaCrcModes_t; + +/*! + * \brief Represents the IQ mode for LoRa packet type + */ +typedef enum +{ + LORA_IQ_NORMAL = 0x00, + LORA_IQ_INVERTED = 0x01, +}RadioLoRaIQModes_t; + +/*! + * \brief Represents the voltage used to control the TCXO on/off from DIO3 + */ +typedef enum +{ + TCXO_CTRL_1_6V = 0x00, + TCXO_CTRL_1_7V = 0x01, + TCXO_CTRL_1_8V = 0x02, + TCXO_CTRL_2_2V = 0x03, + TCXO_CTRL_2_4V = 0x04, + TCXO_CTRL_2_7V = 0x05, + TCXO_CTRL_3_0V = 0x06, + TCXO_CTRL_3_3V = 0x07, +}RadioTcxoCtrlVoltage_t; + +/*! + * \brief Represents the interruption masks available for the radio + * + * \remark Note that not all these interruptions are available for all packet types + */ +typedef enum +{ + IRQ_RADIO_NONE = 0x0000, + IRQ_TX_DONE = 0x0001, + IRQ_RX_DONE = 0x0002, + IRQ_PREAMBLE_DETECTED = 0x0004, + IRQ_SYNCWORD_VALID = 0x0008, + IRQ_HEADER_VALID = 0x0010, + IRQ_HEADER_ERROR = 0x0020, + IRQ_CRC_ERROR = 0x0040, + IRQ_CAD_DONE = 0x0080, + IRQ_CAD_ACTIVITY_DETECTED = 0x0100, + IRQ_RX_TX_TIMEOUT = 0x0200, + IRQ_RADIO_ALL = 0xFFFF, +}RadioIrqMasks_t; + +/*! + * \brief Represents all possible opcode understood by the radio + */ +typedef enum RadioCommands_e +{ + RADIO_GET_STATUS = 0xC0, + RADIO_WRITE_REGISTER = 0x0D, + RADIO_READ_REGISTER = 0x1D, + RADIO_WRITE_BUFFER = 0x0E, + RADIO_READ_BUFFER = 0x1E, + RADIO_SET_SLEEP = 0x84, + RADIO_SET_STANDBY = 0x80, + RADIO_SET_FS = 0xC1, + RADIO_SET_TX = 0x83, + RADIO_SET_RX = 0x82, + RADIO_SET_RXDUTYCYCLE = 0x94, + RADIO_SET_CAD = 0xC5, + RADIO_SET_TXCONTINUOUSWAVE = 0xD1, + RADIO_SET_TXCONTINUOUSPREAMBLE = 0xD2, + RADIO_SET_PACKETTYPE = 0x8A, + RADIO_GET_PACKETTYPE = 0x11, + RADIO_SET_RFFREQUENCY = 0x86, + RADIO_SET_TXPARAMS = 0x8E, + RADIO_SET_PACONFIG = 0x95, + RADIO_SET_CADPARAMS = 0x88, + RADIO_SET_BUFFERBASEADDRESS = 0x8F, + RADIO_SET_MODULATIONPARAMS = 0x8B, + RADIO_SET_PACKETPARAMS = 0x8C, + RADIO_GET_RXBUFFERSTATUS = 0x13, + RADIO_GET_PACKETSTATUS = 0x14, + RADIO_GET_RSSIINST = 0x15, + RADIO_GET_STATS = 0x10, + RADIO_RESET_STATS = 0x00, + RADIO_CFG_DIOIRQ = 0x08, + RADIO_GET_IRQSTATUS = 0x12, + RADIO_CLR_IRQSTATUS = 0x02, + RADIO_CALIBRATE = 0x89, + RADIO_CALIBRATEIMAGE = 0x98, + RADIO_SET_REGULATORMODE = 0x96, + RADIO_GET_ERROR = 0x17, + RADIO_CLR_ERROR = 0x07, + RADIO_SET_TCXOMODE = 0x97, + RADIO_SET_TXFALLBACKMODE = 0x93, + RADIO_SET_RFSWITCHMODE = 0x9D, + RADIO_SET_STOPRXTIMERONPREAMBLE = 0x9F, + RADIO_SET_LORASYMBTIMEOUT = 0xA0, +}RadioCommands_t; + +/*! + * \brief The type describing the modulation parameters for every packet types + */ +typedef struct +{ + RadioPacketTypes_t PacketType; //!< Packet to which the modulation parameters are referring to. + struct + { + struct + { + uint32_t BitRate; + uint32_t Fdev; + RadioModShapings_t ModulationShaping; + uint8_t Bandwidth; + }Gfsk; + struct + { + RadioLoRaSpreadingFactors_t SpreadingFactor; //!< Spreading Factor for the LoRa modulation + RadioLoRaBandwidths_t Bandwidth; //!< Bandwidth for the LoRa modulation + RadioLoRaCodingRates_t CodingRate; //!< Coding rate for the LoRa modulation + uint8_t LowDatarateOptimize; //!< Indicates if the modem uses the low datarate optimization + }LoRa; + }Params; //!< Holds the modulation parameters structure +}ModulationParams_t; + +/*! + * \brief The type describing the packet parameters for every packet types + */ +typedef struct +{ + RadioPacketTypes_t PacketType; //!< Packet to which the packet parameters are referring to. + struct + { + /*! + * \brief Holds the GFSK packet parameters + */ + struct + { + uint16_t PreambleLength; //!< The preamble Tx length for GFSK packet type in bit + RadioPreambleDetection_t PreambleMinDetect; //!< The preamble Rx length minimal for GFSK packet type + uint8_t SyncWordLength; //!< The synchronization word length for GFSK packet type + RadioAddressComp_t AddrComp; //!< Activated SyncWord correlators + RadioPacketLengthModes_t HeaderType; //!< If the header is explicit, it will be transmitted in the GFSK packet. If the header is implicit, it will not be transmitted + uint8_t PayloadLength; //!< Size of the payload in the GFSK packet + RadioCrcTypes_t CrcLength; //!< Size of the CRC block in the GFSK packet + RadioDcFree_t DcFree; + }Gfsk; + /*! + * \brief Holds the LoRa packet parameters + */ + struct + { + uint16_t PreambleLength; //!< The preamble length is the number of LoRa symbols in the preamble + RadioLoRaPacketLengthsMode_t HeaderType; //!< If the header is explicit, it will be transmitted in the LoRa packet. If the header is implicit, it will not be transmitted + uint8_t PayloadLength; //!< Size of the payload in the LoRa packet + RadioLoRaCrcModes_t CrcMode; //!< Size of CRC block in LoRa packet + RadioLoRaIQModes_t InvertIQ; //!< Allows to swap IQ for LoRa packet + }LoRa; + }Params; //!< Holds the packet parameters structure +}PacketParams_t; + +/*! + * \brief Represents the packet status for every packet type + */ +typedef struct +{ + RadioPacketTypes_t packetType; //!< Packet to which the packet status are referring to. + struct + { + struct + { + uint8_t RxStatus; + int8_t RssiAvg; //!< The averaged RSSI + int8_t RssiSync; //!< The RSSI measured on last packet + uint32_t FreqError; + }Gfsk; + struct + { + int8_t RssiPkt; //!< The RSSI of the last packet + int8_t SnrPkt; //!< The SNR of the last packet + int8_t SignalRssiPkt; + uint32_t FreqError; + }LoRa; + }Params; +}PacketStatus_t; + +/*! + * \brief Represents the Rx internal counters values when GFSK or LoRa packet type is used + */ +typedef struct +{ + RadioPacketTypes_t packetType; //!< Packet to which the packet status are referring to. + uint16_t PacketReceived; + uint16_t CrcOk; + uint16_t LengthError; +}RxCounter_t; + +/*! + * \brief Represents a calibration configuration + */ +typedef union +{ + struct + { + uint8_t RC64KEnable : 1; //!< Calibrate RC64K clock + uint8_t RC13MEnable : 1; //!< Calibrate RC13M clock + uint8_t PLLEnable : 1; //!< Calibrate PLL + uint8_t ADCPulseEnable : 1; //!< Calibrate ADC Pulse + uint8_t ADCBulkNEnable : 1; //!< Calibrate ADC bulkN + uint8_t ADCBulkPEnable : 1; //!< Calibrate ADC bulkP + uint8_t ImgEnable : 1; + uint8_t : 1; + }Fields; + uint8_t Value; +}CalibrationParams_t; + +/*! + * \brief Represents a sleep mode configuration + */ +typedef union +{ + struct + { + uint8_t WakeUpRTC : 1; //!< Get out of sleep mode if wakeup signal received from RTC + uint8_t Reset : 1; + uint8_t WarmStart : 1; + uint8_t Reserved : 5; + }Fields; + uint8_t Value; +}SleepParams_t; + +/*! + * \brief Represents the possible radio system error states + */ +typedef union +{ + struct + { + uint8_t Rc64kCalib : 1; //!< RC 64kHz oscillator calibration failed + uint8_t Rc13mCalib : 1; //!< RC 13MHz oscillator calibration failed + uint8_t PllCalib : 1; //!< PLL calibration failed + uint8_t AdcCalib : 1; //!< ADC calibration failed + uint8_t ImgCalib : 1; //!< Image calibration failed + uint8_t XoscStart : 1; //!< XOSC oscillator failed to start + uint8_t PllLock : 1; //!< PLL lock failed + uint8_t BuckStart : 1; //!< Buck converter failed to start + uint8_t PaRamp : 1; //!< PA ramp failed + uint8_t : 7; //!< Reserved + }Fields; + uint16_t Value; +}RadioError_t; + +/*! + * Radio hardware and global parameters + */ +typedef struct SX126x_s +{ +// Gpio_t Reset; +// Gpio_t BUSY; +// Gpio_t DIO1; +// Gpio_t DIO2; +// Gpio_t DIO3; +// Spi_t Spi; + PacketParams_t PacketParams; + PacketStatus_t PacketStatus; + ModulationParams_t ModulationParams; +}SX126x_t; + +/*! + * Hardware IO IRQ callback function definition + */ +typedef void ( DioIrqHandler )( void ); + +/*! + * SX126x definitions + */ + +/*! + * \brief Provides the frequency of the chip running on the radio and the frequency step + * + * \remark These defines are used for computing the frequency divider to set the RF frequency + */ +#define XTAL_FREQ ( double )32000000 +#define FREQ_DIV ( double )pow( 2.0, 25.0 ) +#define FREQ_STEP ( double )( XTAL_FREQ / FREQ_DIV ) + +#define RX_BUFFER_SIZE 256 + +/*! + * \brief The radio callbacks structure + * Holds function pointers to be called on radio interrupts + */ +typedef struct +{ + void ( *txDone )( void ); //!< Pointer to a function run on successful transmission + void ( *rxDone )( void ); //!< Pointer to a function run on successful reception + void ( *rxPreambleDetect )( void ); //!< Pointer to a function run on successful Preamble detection + void ( *rxSyncWordDone )( void ); //!< Pointer to a function run on successful SyncWord reception + void ( *rxHeaderDone )( bool isOk ); //!< Pointer to a function run on successful Header reception + void ( *txTimeout )( void ); //!< Pointer to a function run on transmission timeout + void ( *rxTimeout )( void ); //!< Pointer to a function run on reception timeout + void ( *rxError )( IrqErrorCode_t errCode ); //!< Pointer to a function run on reception error + void ( *cadDone )( bool cadFlag ); //!< Pointer to a function run on channel activity detected +}SX126xCallbacks_t; + +/*! + * ============================================================================ + * Public functions prototypes + * ============================================================================ + */ + +/*! + * \brief Initializes the radio driver + */ +void SX126xInit( void ); + +/*! + * \brief Gets the current Operation Mode of the Radio + * + * \retval RadioOperatingModes_t last operating mode + */ +uint8_t SX126xGetOperatingMode( void ); + +/*! + * \brief Wakeup the radio if it is in Sleep mode and check that Busy is low + */ +void SX126xCheckDeviceReady( void ); + +/*! + * \brief Saves the payload to be send in the radio buffer + * + * \param [in] payload A pointer to the payload + * \param [in] size The size of the payload + */ +void SX126xSetPayload( uint8_t *payload, uint8_t size ); + +/*! + * \brief Reads the payload received. If the received payload is longer + * than maxSize, then the method returns 1 and do not set size and payload. + * + * \param [out] payload A pointer to a buffer into which the payload will be copied + * \param [out] size A pointer to the size of the payload received + * \param [in] maxSize The maximal size allowed to copy into the buffer + */ +uint8_t SX126xGetPayload( uint8_t *payload, uint8_t *size, uint8_t maxSize ); + +/*! + * \brief Sends a payload + * + * \param [in] payload A pointer to the payload to send + * \param [in] size The size of the payload to send + * \param [in] timeout The timeout for Tx operation + */ +void SX126xSendPayload( uint8_t *payload, uint8_t size, uint32_t timeout ); + +/*! + * \brief Sets the Sync Word given by index used in GFSK + * + * \param [in] syncWord SyncWord bytes ( 8 bytes ) + * + * \retval status [0: OK, 1: NOK] + */ +uint8_t SX126xSetSyncWord( uint8_t *syncWord ); + +/*! + * \brief Sets the Initial value for the LFSR used for the CRC calculation + * + * \param [in] seed Initial LFSR value ( 2 bytes ) + * + */ +void SX126xSetCrcSeed( uint16_t seed ); + +/*! + * \brief Sets the seed used for the CRC calculation + * + * \param [in] seed The seed value + * + */ +void SX126xSetCrcPolynomial( uint16_t polynomial ); + +/*! + * \brief Sets the Initial value of the LFSR used for the whitening in GFSK protocols + * + * \param [in] seed Initial LFSR value + */ +void SX126xSetWhiteningSeed( uint16_t seed ); + +/*! + * \brief Gets a 32 bits random value generated by the radio + * + * \remark The radio must be in reception mode before executing this function + * + * \retval randomValue 32 bits random value + */ +uint32_t SX126xGetRandom( void ); + +/*! + * \brief Sets the radio in sleep mode + * + * \param [in] sleepConfig The sleep configuration describing data + * retention and RTC wake-up + */ +void SX126xSetSleep( uint8_t sleepConfig ); + +/*! + * \brief Sets the radio in configuration mode + * + * \param [in] mode The standby mode to put the radio into + */ +void SX126xSetStandby( uint8_t mode ); + +/*! + * \brief Sets the radio in FS mode + */ +void SX126xSetFs( void ); + +/*! + * \brief Sets the radio in transmission mode + * + * \param [in] timeout Structure describing the transmission timeout value + */ +void SX126xSetTx( uint32_t timeout ); + +/*! + * \brief Sets the radio in reception mode + * + * \param [in] timeout Structure describing the reception timeout value + */ +void SX126xSetRx( uint32_t timeout ); + +/*! + * \brief Sets the radio in reception mode with Boosted LNA gain + * + * \param [in] timeout Structure describing the reception timeout value + */ +void SX126xSetRxBoosted( uint32_t timeout ); + +/*! + * \brief Sets the Rx duty cycle management parameters + * + * \param [in] rxTime Structure describing reception timeout value + * \param [in] sleepTime Structure describing sleep timeout value + */ +void SX126xSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ); + +/*! + * \brief Sets the radio in CAD mode + */ +void SX126xSetCad( void ); + +/*! + * \brief Sets the radio in continuous wave transmission mode + */ +void SX126xSetTxContinuousWave( void ); + +/*! + * \brief Sets the radio in continuous preamble transmission mode + */ +void SX126xSetTxInfinitePreamble( void ); + +/*! + * \brief Decide which interrupt will stop the internal radio rx timer. + * + * \param [in] enable [0: Timer stop after header/syncword detection + * 1: Timer stop after preamble detection] + */ +void SX126xSetStopRxTimerOnPreambleDetect( bool enable ); + +/*! + * \brief Set the number of symbol the radio will wait to validate a reception + * + * \param [in] SymbNum number of LoRa symbols + */ +void SX126xSetLoRaSymbNumTimeout( uint8_t SymbNum ); + +/*! + * \brief Sets the power regulators operating mode + * + * \param [in] mode [0: LDO, 1:DC_DC] + */ +void SX126xSetRegulatorMode( uint8_t mode ); + +/*! + * \brief Calibrates the given radio block + * + * \param [in] calibParam The description of blocks to be calibrated + */ +void SX126xCalibrate( uint8_t calibParam ); + +/*! + * \brief Calibrates the Image rejection depending of the frequency + * + * \param [in] freq The operating frequency + */ +void SX126xCalibrateImage( uint32_t freq ); + +/*! + * \brief Activate the extention of the timeout when long preamble is used + * + * \param [in] enable The radio will extend the timeout to cope with long preamble + */ +void SX126xSetLongPreamble( uint8_t enable ); + +/*! + * \brief Sets the transmission parameters + * + * \param [in] paDutyCycle Duty Cycle for the PA + * \param [in] hpMax 0 for sx1261, 7 for sx1262 + * \param [in] deviceSel 1 for sx1261, 0 for sx1262 + * \param [in] paLut 0 for 14dBm LUT, 1 for 22dBm LUT + */ +void SX126xSetPaConfig( uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut ); + +/*! + * \brief Defines into which mode the chip goes after a TX / RX done + * + * \param [in] fallbackMode The mode in which the radio goes + */ +void SX126xSetRxTxFallbackMode( uint8_t fallbackMode ); + +/*! + * \brief Write data to the radio memory + * + * \param [in] address The address of the first byte to write in the radio + * \param [in] buffer The data to be written in radio's memory + * \param [in] size The number of bytes to write in radio's memory + */ +void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Read data from the radio memory + * + * \param [in] address The address of the first byte to read from the radio + * \param [out] buffer The buffer that holds data read from radio + * \param [in] size The number of bytes to read from radio's memory + */ +void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Write data to the buffer holding the payload in the radio + * + * \param [in] offset The offset to start writing the payload + * \param [in] buffer The data to be written (the payload) + * \param [in] size The number of byte to be written + */ +void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Read data from the buffer holding the payload in the radio + * + * \param [in] offset The offset to start reading the payload + * \param [out] buffer A pointer to a buffer holding the data from the radio + * \param [in] size The number of byte to be read + */ +void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Sets the IRQ mask and DIO masks + * + * \param [in] irqMask General IRQ mask + * \param [in] dio1Mask DIO1 mask + * \param [in] dio2Mask DIO2 mask + * \param [in] dio3Mask DIO3 mask + */ +void SX126xSetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ); + +/*! + * \brief Returns the current IRQ status + * + * \retval irqStatus IRQ status + */ +uint16_t SX126xGetIrqStatus( void ); + +/*! + * \brief Indicates if DIO2 is used to control an RF Switch + * + * \param [in] enable true of false + */ +void SX126xSetDio2AsRfSwitchCtrl( uint8_t enable ); + +/*! + * \brief Indicates if the Radio main clock is supplied from a tcxo + * + * \param [in] tcxoVoltage voltage used to control the TCXO + * \param [in] timeout time given to the TCXO to go to 32MHz + */ +void SX126xSetDio3AsTcxoCtrl( uint8_t tcxoVoltage, uint32_t timeout ); + +/*! + * \brief Sets the RF frequency + * + * \param [in] frequency RF frequency [Hz] + */ +void SX126xSetRfFrequency( uint32_t frequency ); + +/*! + * \brief Sets the radio for the given protocol + * + * \param [in] packetType [PACKET_TYPE_GFSK, PACKET_TYPE_LORA] + * + * \remark This method has to be called before SetRfFrequency, + * SetModulationParams and SetPacketParams + */ +void SX126xSetPacketType( RadioPacketTypes_t packetType ); + +/*! + * \brief Gets the current radio protocol + * + * \retval packetType [PACKET_TYPE_GFSK, PACKET_TYPE_LORA] + */ +RadioPacketTypes_t SX126xGetPacketType( void ); + +/*! + * \brief Sets the transmission parameters + * + * \param [in] power RF output power [-18..13] dBm + * \param [in] rampTime Transmission ramp up time + */ +void SX126xSetTxParams( int8_t power, uint8_t rampTime ); + +/*! + * \brief Set the modulation parameters + * + * \param [in] modParams A structure describing the modulation parameters + */ +void SX126xSetModulationParams( void *input_ptr ); + +/*! + * \brief Sets the packet parameters + * + * \param [in] packetParams A structure describing the packet parameters + */ +void SX126xSetPacketParams( void *packetParams ); + +/*! + * \brief Sets the Channel Activity Detection (CAD) parameters + * + * \param [in] cadSymbolNum The number of symbol to use for CAD operations + * [LORA_CAD_01_SYMBOL, LORA_CAD_02_SYMBOL, + * LORA_CAD_04_SYMBOL, LORA_CAD_08_SYMBOL, + * LORA_CAD_16_SYMBOL] + * \param [in] cadDetPeak Limit for detection of SNR peak used in the CAD + * \param [in] cadDetMin Set the minimum symbol recognition for CAD + * \param [in] cadExitMode Operation to be done at the end of CAD action + * [LORA_CAD_ONLY, LORA_CAD_RX, LORA_CAD_LBT] + * \param [in] cadTimeout Defines the timeout value to abort the CAD activity + */ +void SX126xSetCadParams( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, RadioCadExitModes_t cadExitMode, uint32_t cadTimeout ); + +/*! + * \brief Sets the data buffer base address for transmission and reception + * + * \param [in] txBaseAddress Transmission base address + * \param [in] rxBaseAddress Reception base address + */ +void SX126xSetBufferBaseAddress( uint8_t txBaseAddress, uint8_t rxBaseAddress ); + +/*! + * \brief Gets the current radio status + * + * \retval status Radio status + */ +uint8_t SX126xGetStatus( void ); + +/*! + * \brief Returns the instantaneous RSSI value for the last packet received + * + * \retval rssiInst Instantaneous RSSI + */ +int8_t SX126xGetRssiInst( void ); + +/*! + * \brief Gets the last received packet buffer status + * + * \param [out] payloadLength Last received packet payload length + * \param [out] rxStartBuffer Last received packet buffer address pointer + */ +void SX126xGetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBuffer ); + +/*! + * \brief Gets the last received packet payload length + * + * \param [out] pktStatus A structure of packet status + */ +void SX126xGetPacketStatus( void *pktStatus ); + +/*! + * \brief Returns the possible system errors + * + * \retval sysErrors Value representing the possible sys failures + */ +uint16_t SX126xGetDeviceErrors( void ); + +/*! + * \brief Clear all the errors in the device + */ +void SX126xClearDeviceErrors( void ); + +/*! + * \brief Clears the IRQs + * + * \param [in] irq IRQ(s) to be cleared + */ +void SX126xClearIrqStatus( uint16_t irq ); + +#endif // __SX126x_H__ diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/timer.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/timer.cpp new file mode 100644 index 00000000..96b22367 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/timer.cpp @@ -0,0 +1,29 @@ +#include +#include +#include "timer1.h" +unsigned int timer1_counter = 0; +uint32_t TickCounter = 0; + +void timer1_init(void) +{ + // Initializing timer1 + cli(); //disable global interrupt + TCCR1A = 0; //set TCCR1A to 0 + TCCR1B = 0; + + timer1_counter = 64911; + TCNT1 = timer1_counter; + + TCCR1B |= (1 << CS12); //256 frequency divider + + // enable overflow interrupt for timer + TIMSK1 = (1 << TOIE1); + //enable global interrupt + sei(); +} + +ISR(TIMER1_OVF_vect) +{ + TCNT1 = timer1_counter; + TickCounter++; +} \ No newline at end of file diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/timer1.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/timer1.h new file mode 100644 index 00000000..d59c9193 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-RX/timer1.h @@ -0,0 +1,5 @@ +#ifndef _TIMER1_H_ +#define _TIMER1_H_ +void timer1_init(void); + +#endif diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/Arduino-DRF1262T-TX.ino b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/Arduino-DRF1262T-TX.ino new file mode 100644 index 00000000..59c288ad --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/Arduino-DRF1262T-TX.ino @@ -0,0 +1,161 @@ +#include +#include +#include +#include "radio.h" +#include "timer1.h" +#include "sx126x.h" +#include "sx126x-board.h" +#define Get_NIRQ() digitalRead(Dio1Pin) +/* + * if you want to use TCXO please open sx1262.h line 29 + */ + +uint8_t mode = USER_MODE_TX; /*mode SET current work mode: TX or RX*/ +/*Default frequency:868MHZ Bandwidth:125KHZ,RF_FACTOR:11 */ +#define RF_FREQUENCY 868000000 // Hz center frequency +#define TX_OUTPUT_POWER 22 // dBm tx output power +#define LORA_BANDWIDTH 1 // bandwidth=125khz 0:250kHZ,1:125kHZ,2:62kHZ,3:20kHZ.... lookfor radio line 392 +#define LORA_SPREADING_FACTOR 11 // spreading factor=11 [SF5..SF12] +#define LORA_CODINGRATE 1 // [1: 4/5, + // 2: 4/6, + // 3: 4/7, + // 4: 4/8] +#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx +#define LORA_SYMBOL_TIMEOUT 0 // Symbols +#define LORA_FIX_LENGTH_PAYLOAD_ON false // variable data payload +#define LORA_IQ_INVERSION_ON false + +typedef enum +{ + LOWPOWER, + RX, + RX_TIMEOUT, + RX_ERROR, + TX, + TX_TIMEOUT, +} States_t; + +#define RX_TIMEOUT_VALUE 1000 +#define BUFFER_SIZE 64 // Define the payload size here +States_t State = LOWPOWER; + +RadioEvents_t RadioEvents; +uint16_t BufferSize = BUFFER_SIZE; +uint8_t Buffer[BUFFER_SIZE]; +int8_t RssiValue = 0; +int8_t SnrValue = 0; + +void OnTxDone(void); +void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr); +void OnTxTimeout(void); +void OnRxTimeout(void); +void OnRxError(void); + +uint8_t i = 0; + +void setup() +{ + timer1_init(); + SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0)); + Serial.begin(9600); // set baud rate + SX126xIoInit(); // Initializes the radio I/Os pins + SPI.begin(); + + pinMode(Led1BluePin, OUTPUT); + pinMode(Led1RedPin, OUTPUT); + digitalWrite(Led1BluePin, 1); + digitalWrite(Led1RedPin, 1); + + // Radio initialization + RadioEvents.TxDone = OnTxDone; + RadioEvents.RxDone = OnRxDone; + RadioEvents.TxTimeout = OnTxTimeout; + RadioEvents.RxTimeout = OnRxTimeout; + RadioEvents.RxError = OnRxError; + + Radio.Init(&RadioEvents); + Radio.SetChannel(RF_FREQUENCY); + + Radio.SetTxConfig(MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, + LORA_SPREADING_FACTOR, LORA_CODINGRATE, + LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, + true, 0, 0, LORA_IQ_INVERSION_ON, 3000); + + Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, + LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, + LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true); + + if (USER_MODE_RX == mode) + { + + Radio.Rx(0); + digitalWrite(Led1BluePin, 0); + Serial.println("Now is RX"); + } + else + { + Radio.Send((uint8_t *)&i, 1); + } +} + +void loop() +{ + // put your main code here, to run repeatedly: + if (USER_MODE_RX == mode) + { + if (0 != State) + { + Serial.println(Buffer[0], DEC); // print received characters + + digitalWrite(Led1BluePin, digitalRead(Led1BluePin) ^ 1); + State = LOWPOWER; + } + } + else if (TX == State) + { + delay(500); + i++; + Radio.Send((uint8_t *)&i, 1); // send one testing character, users can change the content + digitalWrite(Led1RedPin, digitalRead(Led1RedPin) ^ 1); + } + // Process Radio IRQ + if (Get_NIRQ()) + { + Radio.IrqProcess(); + } +} + +void OnTxDone(void) +{ + // Radio.Sleep( ); + State = TX; +} + +void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) +{ + // Radio.Sleep( ); + BufferSize = size; + memcpy(Buffer, payload, BufferSize); + RssiValue = rssi; + SnrValue = snr; + State = RX; +} + +void OnTxTimeout(void) +{ + // Radio.Sleep( ); + State = TX_TIMEOUT; +} + +void OnRxTimeout(void) +{ + // Radio.Sleep( ); + State = RX_TIMEOUT; +} + +void OnRxError(void) +{ + // Radio.Sleep( ); + State = RX_ERROR; +} diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/radio.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/radio.cpp new file mode 100644 index 00000000..1ca1b623 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/radio.cpp @@ -0,0 +1,1016 @@ +/*! + * \file radio.c + * + * \brief Radio driver API definition + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#include +#include +#include "sx126x.h" +#include "radio.h" +#include "sx126x-board.h" + +/*! + * \brief Initializes the radio + * + * \param [IN] events Structure containing the driver callback functions + */ +void RadioInit( RadioEvents_t *events ); + +/*! + * Return current radio status + * + * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] + */ +RadioState_t RadioGetStatus( void ); + +/*! + * \brief Configures the radio with the given modem + * + * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ +void RadioSetModem( uint8_t modem ); + +/*! + * \brief Sets the channel frequency + * + * \param [IN] freq Channel RF frequency + */ +void RadioSetChannel( uint32_t freq ); + +/*! + * \brief Checks if the channel is free for the given time + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] freq Channel RF frequency + * \param [IN] rssiThresh RSSI threshold + * \param [IN] maxCarrierSenseTime Max time while the RSSI is measured + * + * \retval isFree [true: Channel is free, false: Channel is not free] + */ +bool RadioIsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ); + +/*! + * \brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * \retval randomValue 32 bits random value + */ +uint32_t RadioRandom( void ); + +/*! + * \brief Sets the reception parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * \param [IN] preambleLen Sets the Preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout in number of bytes + * LoRa: timeout in symbols + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] payloadLen Sets payload length when fixed length is used + * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ +void RadioSetRxConfig( uint8_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool FreqHopOn, uint8_t HopPeriod, + bool iqInverted, bool rxContinuous ); + +/*! + * \brief Sets the transmission parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] power Sets the output power [dBm] + * \param [IN] fdev Sets the frequency deviation (FSK only) + * FSK : [Hz] + * LoRa: 0 + * \param [IN] bandwidth Sets the bandwidth (LoRa only) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] preambleLen Sets the preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] timeout Transmission timeout [ms] + */ +void RadioSetTxConfig( uint8_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool FreqHopOn, + uint8_t HopPeriod, bool iqInverted, uint32_t timeout ); + +/*! + * \brief Checks if the given RF frequency is supported by the hardware + * + * \param [IN] frequency RF frequency to be checked + * \retval isSupported [true: supported, false: unsupported] + */ +bool RadioCheckRfFrequency( uint32_t frequency ); + +/*! + * \brief Computes the packet time on air in ms for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] pktLen Packet payload length + * + * \retval airTime Computed airTime (ms) for the given packet payload length + */ +uint32_t RadioTimeOnAir( RadioModems_t modem, uint8_t pktLen ); + +/*! + * \brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * \param [IN]: buffer Buffer pointer + * \param [IN]: size Buffer size + */ +void RadioSend( uint8_t *buffer, uint8_t size ); + +/*! + * \brief Sets the radio in sleep mode + */ +void RadioSleep( void ); + +/*! + * \brief Sets the radio in standby mode + */ +void RadioStandby( void ); + +/*! + * \brief Sets the radio in reception mode for the given time + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ +void RadioRx( uint32_t timeout ); + +/*! + * \brief Start a Channel Activity Detection + */ +void RadioStartCad( void ); + +/*! + * \brief Sets the radio in continuous wave transmission mode + * + * \param [IN]: freq Channel RF frequency + * \param [IN]: power Sets the output power [dBm] + * \param [IN]: time Transmission mode timeout [s] + */ +void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ); + +/*! + * \brief Reads the current RSSI value + * + * \retval rssiValue Current RSSI value in [dBm] + */ +int16_t RadioRssi( RadioModems_t modem ); + +/*! + * \brief Writes the radio register at the specified address + * + * \param [IN]: addr Register address + * \param [IN]: data New register value + */ +void RadioWrite( uint16_t addr, uint8_t data ); + +/*! + * \brief Reads the radio register at the specified address + * + * \param [IN]: addr Register address + * \retval data Register value + */ +uint8_t RadioRead( uint16_t addr ); + +/*! + * \brief Writes multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [IN] buffer Buffer containing the new register's values + * \param [IN] size Number of registers to be written + */ +void RadioWriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Reads multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [OUT] buffer Buffer where to copy the registers data + * \param [IN] size Number of registers to be read + */ +void RadioReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Sets the maximum payload length. + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] max Maximum payload length in bytes + */ +void RadioSetMaxPayloadLength( RadioModems_t modem, uint8_t max ); + +/*! + * \brief Sets the network to public or private. Updates the sync byte. + * + * \remark Applies to LoRa modem only + * + * \param [IN] enable if true, it enables a public network + */ +void RadioSetPublicNetwork( bool enable ); + +/*! + * \brief Gets the time required for the board plus radio to get out of sleep.[ms] + * + * \retval time Radio plus board wakeup time in ms. + */ +uint32_t RadioGetWakeupTime( void ); + +/*! + * \brief Process radio irq + */ +void RadioIrqProcess( void ); + +/*! + * \brief Sets the radio in reception mode with Max LNA gain for the given time + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ +void RadioRxBoosted( uint32_t timeout ); + +/*! + * \brief Sets the Rx duty cycle management parameters + * + * \param [in] rxTime Structure describing reception timeout value + * \param [in] sleepTime Structure describing sleep timeout value + */ +void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ); + +/*! + * Radio driver structure initialization + */ + struct Radio_s Radio = +{ + RadioInit, + RadioGetStatus, + RadioSetModem, + RadioSetChannel, + RadioIsChannelFree, + RadioRandom, + RadioSetRxConfig, + RadioSetTxConfig, + RadioCheckRfFrequency, + RadioTimeOnAir, + RadioSend, + RadioSleep, + RadioStandby, + RadioRx, + RadioStartCad, + RadioSetTxContinuousWave, + RadioRssi, + RadioWrite, + RadioRead, + RadioWriteBuffer, + RadioReadBuffer, + RadioSetMaxPayloadLength, + RadioSetPublicNetwork, + RadioGetWakeupTime, + RadioIrqProcess, + // Available on SX126x only + RadioRxBoosted, + RadioSetRxDutyCycle +}; + +/* + * Local types definition + */ + + + /*! + * FSK bandwidth definition + */ +typedef struct +{ + uint32_t bandwidth; + uint8_t RegValue; +}FskBandwidth_t; + +/*! + * Precomputed FSK bandwidth registers values + */ +const FskBandwidth_t FskBandwidths[] = +{ + { 4800 , 0x1F }, + { 5800 , 0x17 }, + { 7300 , 0x0F }, + { 9700 , 0x1E }, + { 11700 , 0x16 }, + { 14600 , 0x0E }, + { 19500 , 0x1D }, + { 23400 , 0x15 }, + { 29300 , 0x0D }, + { 39000 , 0x1C }, + { 46900 , 0x14 }, + { 58600 , 0x0C }, + { 78200 , 0x1B }, + { 93800 , 0x13 }, + { 117300, 0x0B }, + { 156200, 0x1A }, + { 187200, 0x12 }, + { 234300, 0x0A }, + { 312000, 0x19 }, + { 373600, 0x11 }, + { 467000, 0x09 }, + { 500000, 0x00 }, // Invalid Bandwidth +}; + +const RadioLoRaBandwidths_t Bandwidths[] = {LORA_BW_250,LORA_BW_125, LORA_BW_062,LORA_BW_020,\ + LORA_BW_041,LORA_BW_015,LORA_BW_007,LORA_BW_500,\ + LORA_BW_031,LORA_BW_010,LORA_BW_500,LORA_BW_500,\ + LORA_BW_500,LORA_BW_500,LORA_BW_500,LORA_BW_500}; + +// SF12 SF11 SF10 SF9 SF8 SF7 +static double RadioLoRaSymbTime[3][6] = {{ 32.768, 16.384, 8.192, 4.096, 2.048, 1.024 }, // 125 KHz + { 16.384, 8.192, 4.096, 2.048, 1.024, 0.512 }, // 250 KHz + { 8.192, 4.096, 2.048, 1.024, 0.512, 0.256 }}; // 500 KHz + +uint8_t MaxPayloadLength = 0xFF; + +uint32_t TxTimeout = 0; +uint32_t RxTimeout = 0; + +bool RxContinuous = false; + + +PacketStatus_t RadioPktStatus; +uint8_t RadioRxPayload[255]; + +bool IrqFired = false; + +/* + * SX126x DIO IRQ callback functions prototype + */ + +/*! + * \brief DIO 0 IRQ callback + */ +void RadioOnDioIrq( void ); + +/*! + * \brief Tx timeout timer callback + */ +void RadioOnTxTimeoutIrq( void ); + +/*! + * \brief Rx timeout timer callback + */ +void RadioOnRxTimeoutIrq( void ); + +/* + * Private global variables + */ + + +/*! + * Holds the current network type for the radio + */ +typedef struct +{ + bool Previous; + bool Current; +}RadioPublicNetwork_t; + +static RadioPublicNetwork_t RadioPublicNetwork = { false }; + +/*! + * Radio callbacks variable + */ + RadioEvents_t* RadioEvents_Ptr; + +/* + * Public global variables + */ + +/*! + * Radio hardware and global parameters + */ +SX126x_t SX126x; + + + + +void RadioInit( RadioEvents_t *events ) +{ + RadioEvents_Ptr = events; + + SX126xInit( ); + SX126xSetStandby( STDBY_RC ); + SX126xSetRegulatorMode( USE_DCDC ); + + SX126xSetBufferBaseAddress( 0x00, 0x00 ); + SX126xSetTxParams( 0, RADIO_RAMP_200_US ); + SX126xSetDioIrqParams( IRQ_RADIO_ALL, IRQ_RADIO_ALL, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); + + + IrqFired = false; +} + +RadioState_t RadioGetStatus( void ) +{ + switch( SX126xGetOperatingMode( ) ) + { + case MODE_TX: + return RF_TX_RUNNING; + case MODE_RX: + return RF_RX_RUNNING; + case RF_CAD: + return RF_CAD; + default: + return RF_IDLE; + } +} + +void RadioSetModem( uint8_t modem ) +{ + switch( modem ) + { + default: + case MODEM_FSK: + SX126xSetPacketType( PACKET_TYPE_GFSK ); + // When switching to GFSK mode the LoRa SyncWord register value is reset + // Thus, we also reset the RadioPublicNetwork variable + RadioPublicNetwork.Current = false; + break; + case MODEM_LORA: + SX126xSetPacketType( PACKET_TYPE_LORA ); + // Public/Private network register is reset when switching modems + if( RadioPublicNetwork.Current != RadioPublicNetwork.Previous ) + { + RadioPublicNetwork.Current = RadioPublicNetwork.Previous; + RadioSetPublicNetwork( RadioPublicNetwork.Current ); + } + break; + } +} + +void RadioSetChannel( uint32_t freq ) +{ + SX126xSetRfFrequency( freq ); +} + +bool RadioIsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ) +{ + bool status = true; + int16_t rssi = 0; + uint32_t carrierSenseTime = 0; + + RadioSetModem( modem ); + + RadioSetChannel( freq ); + + RadioRx( 0 ); + + DelayMs( 1 ); + + carrierSenseTime = GET_TICK_COUNT( ); + + // Perform carrier sense for maxCarrierSenseTime + while( GET_TICK_COUNT()-carrierSenseTime< maxCarrierSenseTime ) + { + rssi = RadioRssi( modem ); + + if( rssi > rssiThresh ) + { + status = false; + break; + } + } + RadioSleep( ); + return status; +} + +uint32_t RadioRandom( void ) +{ + uint8_t i; + uint32_t rnd = 0; + + /* + * Radio setup for random number generation + */ + // Set LoRa modem ON + RadioSetModem( MODEM_LORA ); + + // Set radio in continuous reception + SX126xSetRx( 0 ); + + for( i = 0; i < 32; i++ ) + { + DelayMs( 1 ); + // Unfiltered RSSI value reading. Only takes the LSB value + rnd |= ( ( uint32_t )SX126xGetRssiInst( ) & 0x01 ) << i; + } + + RadioSleep( ); + + return rnd; +} + +void RadioSetRxConfig( uint8_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) +{ + + RxContinuous = rxContinuous; + + if( fixLen == true ) + { + MaxPayloadLength = payloadLen; + } + else + { + MaxPayloadLength = 0xFF; + } + + SX126xSetStopRxTimerOnPreambleDetect( false ); + SX126xSetLoRaSymbNumTimeout( symbTimeout ); + SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA; + SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t )datarate; + SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth]; + SX126x.ModulationParams.Params.LoRa.CodingRate = ( RadioLoRaCodingRates_t )coderate; + + if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) || + ( ( bandwidth == 1 ) && ( datarate == 12 ) ) ) + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01; + } + else + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00; + } + + SX126x.PacketParams.PacketType = PACKET_TYPE_LORA; + + if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) || + ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) ) + { + if( preambleLen < 12 ) + { + SX126x.PacketParams.Params.LoRa.PreambleLength = 12; + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + + SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen; + + SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength; + SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn; + SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted; + + RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA ); + SX126xSetModulationParams( &SX126x.ModulationParams ); + SX126xSetPacketParams( &SX126x.PacketParams ); + + // Timeout Max, Timeout handled directly in SetRx function + RxTimeout = 0xFFFF; + +} + +void RadioSetTxConfig( uint8_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) +{ + + SX126x.ModulationParams.PacketType = PACKET_TYPE_LORA; + SX126x.ModulationParams.Params.LoRa.SpreadingFactor = ( RadioLoRaSpreadingFactors_t ) datarate; + SX126x.ModulationParams.Params.LoRa.Bandwidth = Bandwidths[bandwidth]; + SX126x.ModulationParams.Params.LoRa.CodingRate= ( RadioLoRaCodingRates_t )coderate; + + if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) || + ( ( bandwidth == 1 ) && ( datarate == 12 ) ) ) + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x01; + } + else + { + SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize = 0x00; + } + + SX126x.PacketParams.PacketType = PACKET_TYPE_LORA; + + if( ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF5 ) || + ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor == LORA_SF6 ) ) + { + if( preambleLen < 12 ) + { + SX126x.PacketParams.Params.LoRa.PreambleLength = 12; + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + } + else + { + SX126x.PacketParams.Params.LoRa.PreambleLength = preambleLen; + } + + SX126x.PacketParams.Params.LoRa.HeaderType = ( RadioLoRaPacketLengthsMode_t )fixLen; + SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength; + SX126x.PacketParams.Params.LoRa.CrcMode = ( RadioLoRaCrcModes_t )crcOn; + SX126x.PacketParams.Params.LoRa.InvertIQ = ( RadioLoRaIQModes_t )iqInverted; + + RadioStandby( ); + RadioSetModem( ( SX126x.ModulationParams.PacketType == PACKET_TYPE_GFSK ) ? MODEM_FSK : MODEM_LORA ); + SX126xSetModulationParams( &SX126x.ModulationParams ); + SX126xSetPacketParams( &SX126x.PacketParams ); + + + SX126xSetRfTxPower( power ); + TxTimeout = timeout; +} + +bool RadioCheckRfFrequency( uint32_t frequency ) +{ + return true; +} + +uint32_t RadioTimeOnAir( RadioModems_t modem, uint8_t pktLen ) +{ + uint32_t airTime = 0; + double ts = RadioLoRaSymbTime[SX126x.ModulationParams.Params.LoRa.Bandwidth - 4][12 - SX126x.ModulationParams.Params.LoRa.SpreadingFactor]; + // time of preamble + double tPreamble = ( SX126x.PacketParams.Params.LoRa.PreambleLength + 4.25 ) * ts; + // Symbol length of payload and time + double tmp = ceil( ( 8 * pktLen - 4 * SX126x.ModulationParams.Params.LoRa.SpreadingFactor + + 28 + 16 * SX126x.PacketParams.Params.LoRa.CrcMode - + ( ( SX126x.PacketParams.Params.LoRa.HeaderType == LORA_PACKET_FIXED_LENGTH ) ? 20 : 0 ) ) / + ( double )( 4 * ( SX126x.ModulationParams.Params.LoRa.SpreadingFactor - + ( ( SX126x.ModulationParams.Params.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * + ( ( SX126x.ModulationParams.Params.LoRa.CodingRate % 4 ) + 4 ); + double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); + double tPayload = nPayload * ts; + // Time on air + double tOnAir = tPreamble + tPayload; + // return milli seconds + airTime = floor( tOnAir + 0.999 ); + + + return airTime; +} + +void RadioSend( uint8_t *buffer, uint8_t size ) +{ + SX126xSetDioIrqParams( IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_NONE, + IRQ_RADIO_NONE ); + + if( SX126xGetPacketType( ) == PACKET_TYPE_LORA ) + { + SX126x.PacketParams.Params.LoRa.PayloadLength = size; + } + else + { + SX126x.PacketParams.Params.Gfsk.PayloadLength = size; + } + SX126xSetPacketParams( &SX126x.PacketParams ); + + SX126xSendPayload( buffer, size, 0 ); + +} + +void RadioSleep( void ) +{ + SleepParams_t params = { 0 }; + + params.Fields.WarmStart = 1; + SX126xSetSleep( params.Value ); + + DelayMs( 2 ); +} + +void RadioStandby( void ) +{ + SX126xSetStandby( STDBY_RC ); +} + +void RadioRx( uint32_t timeout ) +{ + SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_NONE, + IRQ_RADIO_NONE ); + + + if( RxContinuous == true ) + { + SX126xSetRx( 0xFFFFFF ); // Rx Continuous + } + else + { + SX126xSetRx( RxTimeout << 6 ); + } +} + +void RadioRxBoosted( uint32_t timeout ) +{ + SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT, + IRQ_RADIO_NONE, + IRQ_RADIO_NONE ); + + if( RxContinuous == true ) + { + SX126xSetRxBoosted( 0xFFFFFF ); // Rx Continuous + } + else + { + SX126xSetRxBoosted( RxTimeout << 6 ); + } +} + +void RadioSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ) +{ + SX126xSetRxDutyCycle( rxTime, sleepTime ); +} + +void RadioStartCad( void ) +{ + SX126xSetCad( ); +} + +void RadioTx( uint32_t timeout ) +{ + SX126xSetTx( timeout << 6 ); +} + +void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ) +{ + SX126xSetRfFrequency( freq ); + SX126xSetRfTxPower( power ); + SX126xSetTxContinuousWave( ); + +} + +int16_t RadioRssi( RadioModems_t modem ) +{ + return SX126xGetRssiInst( ); +} + +void RadioWrite( uint16_t addr, uint8_t data ) +{ + SX126xWriteRegister( addr, data ); +} + +uint8_t RadioRead( uint16_t addr ) +{ + return SX126xReadRegister( addr ); +} + +void RadioWriteBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ) +{ + SX126xWriteRegisters( addr, buffer, size ); +} + +void RadioReadBuffer( uint16_t addr, uint8_t *buffer, uint8_t size ) +{ + SX126xReadRegisters( addr, buffer, size ); +} + +void RadioWriteFifo( uint8_t *buffer, uint8_t size ) +{ + SX126xWriteBuffer( 0, buffer, size ); +} + +void RadioReadFifo( uint8_t *buffer, uint8_t size ) +{ + SX126xReadBuffer( 0, buffer, size ); +} + +void RadioSetMaxPayloadLength( uint8_t modem, uint8_t max ) +{ + if( modem == MODEM_LORA ) + { + SX126x.PacketParams.Params.LoRa.PayloadLength = MaxPayloadLength = max; + SX126xSetPacketParams( &SX126x.PacketParams ); + } + else + { + if( SX126x.PacketParams.Params.Gfsk.HeaderType == RADIO_PACKET_VARIABLE_LENGTH ) + { + SX126x.PacketParams.Params.Gfsk.PayloadLength = MaxPayloadLength = max; + SX126xSetPacketParams( &SX126x.PacketParams ); + } + } +} + +void RadioSetPublicNetwork( bool enable ) +{ + RadioPublicNetwork.Current = RadioPublicNetwork.Previous = enable; + + RadioSetModem( MODEM_LORA ); + if( enable == true ) + { + // Change LoRa modem SyncWord + SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PUBLIC_SYNCWORD >> 8 ) & 0xFF ); + SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF ); + } + else + { + // Change LoRa modem SyncWord + SX126xWriteRegister( REG_LR_SYNCWORD, ( LORA_MAC_PRIVATE_SYNCWORD >> 8 ) & 0xFF ); + SX126xWriteRegister( REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF ); + } +} + +uint32_t RadioGetWakeupTime( void ) +{ + return( RADIO_TCXO_SETUP_TIME + RADIO_WAKEUP_TIME ); +} + +void RadioOnTxTimeoutIrq( void ) +{ + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->TxTimeout != NULL ) ) + { + RadioEvents_Ptr->TxTimeout( ); + } +} + +void RadioOnRxTimeoutIrq( void ) +{ + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxTimeout != NULL ) ) + { + RadioEvents_Ptr->RxTimeout( ); + } +} + +void RadioOnDioIrq( void ) +{ + IrqFired = true; +} + +void RadioIrqProcess( void ) +{ + + BoardDisableIrq( ); + IrqFired = false; + BoardEnableIrq( ); + + uint16_t irqRegs = SX126xGetIrqStatus( ); + SX126xClearIrqStatus( IRQ_RADIO_ALL ); + + if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->TxDone != NULL ) ) + { + RadioEvents_Ptr->TxDone( ); + } + } + + if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE ) + { + uint8_t size; + + SX126xGetPayload( RadioRxPayload, &size , 255 ); + SX126xGetPacketStatus( &RadioPktStatus ); + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxDone != NULL ) ) + { + RadioEvents_Ptr->RxDone( RadioRxPayload, size, RadioPktStatus.Params.LoRa.RssiPkt, RadioPktStatus.Params.LoRa.SnrPkt ); + } + } + + if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxError ) ) + { + RadioEvents_Ptr->RxError( ); + } + } + + if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->CadDone != NULL ) ) + { + RadioEvents_Ptr->CadDone( ( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED ) ); + } + } + + if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT ) + { + if( SX126xGetOperatingMode( ) == MODE_TX ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->TxTimeout != NULL ) ) + { + RadioEvents_Ptr->TxTimeout( ); + } + } + else if( SX126xGetOperatingMode( ) == MODE_RX ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxTimeout != NULL ) ) + { + RadioEvents_Ptr->RxTimeout( ); + } + } + } + + if( ( irqRegs & IRQ_PREAMBLE_DETECTED ) == IRQ_PREAMBLE_DETECTED ) + { + //__NOP( ); + } + + if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID ) + { + //__NOP( ); + } + + if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID ) + { + //__NOP( ); + } + + if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR ) + { + if( ( RadioEvents_Ptr != NULL ) && ( RadioEvents_Ptr->RxTimeout != NULL ) ) + { + RadioEvents_Ptr->RxTimeout( ); + } + } +} diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/radio.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/radio.h new file mode 100644 index 00000000..b7fa8a25 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/radio.h @@ -0,0 +1,376 @@ +/*! + * \file radio.h + * + * \brief Radio driver API definition + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#ifndef __RADIO_H__ +#define __RADIO_H__ +#include "sx126x-board.h" + +/*! + * Radio driver supported modems + */ +typedef enum +{ + MODEM_FSK = 0, + MODEM_LORA, +}RadioModems_t; + +/*! + * Radio driver internal state machine states definition + */ +typedef enum +{ + RF_IDLE = 0, //!< The radio is idle + RF_RX_RUNNING, //!< The radio is in reception state + RF_TX_RUNNING, //!< The radio is in transmission state + RF_CAD, //!< The radio is doing channel activity detection +}RadioState_t; + +/*! + * \brief Radio driver callback functions + */ +typedef struct +{ + /*! + * \brief Tx Done callback prototype. + */ + void ( *TxDone )( void ); + /*! + * \brief Tx Timeout callback prototype. + */ + void ( *TxTimeout )( void ); + /*! + * \brief Rx Done callback prototype. + * + * \param [IN] payload Received buffer pointer + * \param [IN] size Received buffer size + * \param [IN] rssi RSSI value computed while receiving the frame [dBm] + * \param [IN] snr Raw SNR value given by the radio hardware + * FSK : N/A ( set to 0 ) + * LoRa: SNR value in dB + */ + void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); + /*! + * \brief Rx Timeout callback prototype. + */ + void ( *RxTimeout )( void ); + /*! + * \brief Rx Error callback prototype. + */ + void ( *RxError )( void ); + /*! + * \brief FHSS Change Channel callback prototype. + * + * \param [IN] currentChannel Index number of the current channel + */ + void ( *FhssChangeChannel )( uint8_t currentChannel ); + + /*! + * \brief CAD Done callback prototype. + * + * \param [IN] channelDetected Channel Activity detected during the CAD + */ + void ( *CadDone ) ( bool channelActivityDetected ); +}RadioEvents_t; + +/*! + * \brief Radio driver definition + */ +struct Radio_s +{ + /*! + * \brief Initializes the radio + * + * \param [IN] events Structure containing the driver callback functions + */ + void ( *Init )( RadioEvents_t *events ); + /*! + * Return current radio status + * + * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] + */ + RadioState_t ( *GetStatus )( void ); + /*! + * \brief Configures the radio with the given modem + * + * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ + void ( *SetModem )( uint8_t modem ); + /*! + * \brief Sets the channel frequency + * + * \param [IN] freq Channel RF frequency + */ + void ( *SetChannel )( uint32_t freq ); + /*! + * \brief Checks if the channel is free for the given time + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] freq Channel RF frequency + * \param [IN] rssiThresh RSSI threshold + * \param [IN] maxCarrierSenseTime Max time while the RSSI is measured + * + * \retval isFree [true: Channel is free, false: Channel is not free] + */ + bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime ); + /*! + * \brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * \retval randomValue 32 bits random value + */ + uint32_t ( *Random )( void ); + /*! + * \brief Sets the reception parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * \param [IN] preambleLen Sets the Preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout in number of bytes + * LoRa: timeout in symbols + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] payloadLen Sets payload length when fixed length is used + * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] hopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ + void ( *SetRxConfig )( uint8_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ); + /*! + * \brief Sets the transmission parameters + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] power Sets the output power [dBm] + * \param [IN] fdev Sets the frequency deviation (FSK only) + * FSK : [Hz] + * LoRa: 0 + * \param [IN] bandwidth Sets the bandwidth (LoRa only) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * \param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * \param [IN] coderate Sets the coding rate (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * \param [IN] preambleLen Sets the preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds 4 more symbols) + * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * \param [IN] freqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] hopPeriod Number of symbols between each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * \param [IN] iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * \param [IN] timeout Transmission timeout [ms] + */ + void ( *SetTxConfig )( uint8_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ); + /*! + * \brief Checks if the given RF frequency is supported by the hardware + * + * \param [IN] frequency RF frequency to be checked + * \retval isSupported [true: supported, false: unsupported] + */ + bool ( *CheckRfFrequency )( uint32_t frequency ); + /*! + * \brief Computes the packet time on air in ms for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] pktLen Packet payload length + * + * \retval airTime Computed airTime (ms) for the given packet payload length + */ + uint32_t ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen ); + /*! + * \brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * \param [IN]: buffer Buffer pointer + * \param [IN]: size Buffer size + */ + void ( *Send )( uint8_t *buffer, uint8_t size ); + /*! + * \brief Sets the radio in sleep mode + */ + void ( *Sleep )( void ); + /*! + * \brief Sets the radio in standby mode + */ + void ( *Standby )( void ); + /*! + * \brief Sets the radio in reception mode for the given time + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ + void ( *Rx )( uint32_t timeout ); + /*! + * \brief Start a Channel Activity Detection + */ + void ( *StartCad )( void ); + /*! + * \brief Sets the radio in continuous wave transmission mode + * + * \param [IN]: freq Channel RF frequency + * \param [IN]: power Sets the output power [dBm] + * \param [IN]: time Transmission mode timeout [s] + */ + void ( *SetTxContinuousWave )( uint32_t freq, int8_t power, uint16_t time ); + /*! + * \brief Reads the current RSSI value + * + * \retval rssiValue Current RSSI value in [dBm] + */ + int16_t ( *Rssi )( RadioModems_t modem ); + /*! + * \brief Writes the radio register at the specified address + * + * \param [IN]: addr Register address + * \param [IN]: data New register value + */ + void ( *Write )( uint16_t addr, uint8_t data ); + /*! + * \brief Reads the radio register at the specified address + * + * \param [IN]: addr Register address + * \retval data Register value + */ + uint8_t ( *Read )( uint16_t addr ); + /*! + * \brief Writes multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [IN] buffer Buffer containing the new register's values + * \param [IN] size Number of registers to be written + */ + void ( *WriteBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size ); + /*! + * \brief Reads multiple radio registers starting at address + * + * \param [IN] addr First Radio register address + * \param [OUT] buffer Buffer where to copy the registers data + * \param [IN] size Number of registers to be read + */ + void ( *ReadBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size ); + /*! + * \brief Sets the maximum payload length. + * + * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * \param [IN] max Maximum payload length in bytes + */ + void ( *SetMaxPayloadLength )( RadioModems_t modem, uint8_t max ); + /*! + * \brief Sets the network to public or private. Updates the sync byte. + * + * \remark Applies to LoRa modem only + * + * \param [IN] enable if true, it enables a public network + */ + void ( *SetPublicNetwork )( bool enable ); + /*! + * \brief Gets the time required for the board plus radio to get out of sleep.[ms] + * + * \retval time Radio plus board wakeup time in ms. + */ + uint32_t ( *GetWakeupTime )( void ); + /*! + * \brief Process radio irq + */ + void ( *IrqProcess )( void ); + /* + * The next functions are available only on SX126x radios. + */ + /*! + * \brief Sets the radio in reception mode with Max LNA gain for the given time + * + * \remark Available on SX126x radios only. + * + * \param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ + void ( *RxBoosted )( uint32_t timeout ); + /*! + * \brief Sets the Rx duty cycle management parameters + * + * \remark Available on SX126x radios only. + * + * \param [in] rxTime Structure describing reception timeout value + * \param [in] sleepTime Structure describing sleep timeout value + */ + void ( *SetRxDutyCycle ) ( uint32_t rxTime, uint32_t sleepTime ); +}; + +/*! + * \brief Radio driver + * + * \remark This variable is defined and initialized in the specific radio + * board implementation + */ +extern struct Radio_s Radio; +void RadioOnDioIrq( void ); + +#endif // __RADIO_H__ diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x-board.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x-board.cpp new file mode 100644 index 00000000..bd5e4cbe --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x-board.cpp @@ -0,0 +1,225 @@ +/* + ______ _ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: SX126x driver specific target board functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include "sx126x-board.h" +#include "sx126x.h" +#include +static uint8_t IrqNestLevel = 0; + +void DelayMs( uint32_t ms ) +{ + delay( ms ); +} + + void BoardDisableIrq( void ) +{ + noInterrupts(); + IrqNestLevel++; +} + + void BoardEnableIrq( void ) +{ + IrqNestLevel--; + if( IrqNestLevel == 0 ) + { + interrupts(); + } +} + +static uint16_t SpiInOut( uint16_t outData ) +{ + uint8_t rxData = 0; + + rxData = SPI.transfer(outData); + return( rxData ); +} + +/*! + * Antenna switch GPIO pins objects + */ + +void SX126xIoInit( void ) +{ + pinMode (NssPin, OUTPUT); + pinMode (NResetPin, OUTPUT); + pinMode (SwPin, OUTPUT); + + pinMode (BusyPin, INPUT); + pinMode (Dio1Pin, INPUT); + + digitalWrite(NssPin,1); + digitalWrite(NResetPin,1); + digitalWrite(SwPin,1); +} + +void SX126xReset( void ) +{ + delay( 10 ); + digitalWrite(NResetPin,0); + delay( 20 ); + digitalWrite(NResetPin,1); + delay( 10 ); +} + +void SX126xWaitOnBusy( void ) +{ + while( digitalRead(BusyPin) == 1 ); +} + +void SX126xWakeup( void ) +{ + BoardDisableIrq( ); + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_GET_STATUS ); + SpiInOut( 0x00 ); + + digitalWrite(NssPin,1); + + // Wait for chip to be ready. + SX126xWaitOnBusy( ); + + BoardEnableIrq( ); +} +void SX126xWriteCommand( uint8_t command, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( (uint8_t )command ); + + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( buffer[i] ); + } + + digitalWrite(NssPin,1); + + if( command != RADIO_SET_SLEEP ) + { + SX126xWaitOnBusy( ); + } +} + +void SX126xReadCommand( uint8_t command, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut(( uint8_t )command ); + SpiInOut( 0x00 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( 0 ); + } + + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} + +void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + digitalWrite(NssPin,0); + SpiInOut( RADIO_WRITE_REGISTER ); + SpiInOut( ( address & 0xFF00 ) >> 8 ); + SpiInOut( address & 0x00FF ); + + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( buffer[i] ); + } + + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} + +void SX126xWriteRegister( uint16_t address, uint8_t value ) +{ + SX126xWriteRegisters( address, &value, 1 ); +} + +void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_READ_REGISTER ); + SpiInOut( ( address & 0xFF00 ) >> 8 ); + SpiInOut( address & 0x00FF ); + SpiInOut( 0 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( 0 ); + } + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} +uint8_t SX126xReadRegister( uint16_t address ) +{ + uint8_t data; + SX126xReadRegisters( address, &data, 1 ); + return data; +} + +void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_WRITE_BUFFER ); + SpiInOut( offset ); + for( uint16_t i = 0; i < size; i++ ) + { + SpiInOut( buffer[i] ); + } + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} +void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ) +{ + // SX126xCheckDeviceReady( ); // undetermined + + digitalWrite(NssPin,0); + + SpiInOut( RADIO_READ_BUFFER ); + SpiInOut( offset ); + SpiInOut( 0 ); + for( uint16_t i = 0; i < size; i++ ) + { + buffer[i] = SpiInOut( 0 ); + } + digitalWrite(NssPin,1); + + SX126xWaitOnBusy( ); +} +void SX126xSetRfTxPower( int8_t power ) +{ + SX126xSetTxParams( power, RADIO_RAMP_40_US ); +} +bool SX126xCheckRfFrequency( uint32_t frequency ) +{ + // Implement check. Currently all frequencies are supported + return true; +} \ No newline at end of file diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x-board.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x-board.h new file mode 100644 index 00000000..4c54175b --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x-board.h @@ -0,0 +1,137 @@ +/* + ______ _ + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: SX126x driver specific target board functions implementation + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __SX126x_ARCH_H__ +#define __SX126x_ARCH_H__ +#include +#include +#include "sx126x.h" + +#define USER_MODE_TX 1 +#define USER_MODE_RX 0 + +extern uint32_t TickCounter; + + +const int BusyPin = 3; +const int Dio2Pin = 4; +const int Dio1Pin = 5; +const int NssPin = 7; +const int SwPin = 8; + +const int Led1RedPin = 16; +const int Led1BluePin = 15; +const int NResetPin = 14; + + +#define GET_TICK_COUNT() TickCounter +#define TICK_RATE_MS( ms ) ( ms ) + +void DelayMs( uint32_t ms ); +void BoardDisableIrq( void ); +void BoardEnableIrq( void ); + +/*! + * \brief Initializes the radio I/Os pins interface + */ +void SX126xIoInit( void ); + +/*! + * \brief Initializes DIO IRQ handlers + * + * \param [IN] irqHandlers Array containing the IRQ callback functions + */ +void SX126xIoIrqInit( void ); + +/*! + * \brief De-initializes the radio I/Os pins interface. + * + * \remark Useful when going in MCU low power modes + */ +void SX126xIoDeInit( void ); + +/*! + * \brief HW Reset of the radio + */ +void SX126xReset( void ); + +/*! + * \brief Blocking loop to wait while the Busy pin in high + */ +void SX126xWaitOnBusy( void ); + +/*! + * \brief Wakes up the radio + */ +void SX126xWakeup( void ); + +/*! + * \brief Send a command that write data to the radio + * + * \param [in] opcode Opcode of the command + * \param [in] buffer Buffer to be send to the radio + * \param [in] size Size of the buffer to send + */ +void SX126xWriteCommand( uint8_t opcode, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Send a command that read data from the radio + * + * \param [in] opcode Opcode of the command + * \param [out] buffer Buffer holding data from the radio + * \param [in] size Size of the buffer + */ +void SX126xReadCommand( uint8_t opcode, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Write a single byte of data to the radio memory + * + * \param [in] address The address of the first byte to write in the radio + * \param [in] value The data to be written in radio's memory + */ +void SX126xWriteRegister( uint16_t address, uint8_t value ); + +/*! + * \brief Read a single byte of data from the radio memory + * + * \param [in] address The address of the first byte to write in the radio + * + * \retval value The value of the byte at the given address in radio's memory + */ +uint8_t SX126xReadRegister( uint16_t address ); + +/*! + * \brief Sets the radio output power. + * + * \param [IN] power Sets the RF output power + */ +void SX126xSetRfTxPower( int8_t power ); + + +/*! + * \brief Checks if the given RF frequency is supported by the hardware + * + * \param [IN] frequency RF frequency to be checked + * \retval isSupported [true: supported, false: unsupported] + */ +bool SX126xCheckRfFrequency( uint32_t frequency ); + +/*! + * Radio hardware and global parameters + */ +extern SX126x_t SX126x; + + +#endif // __SX126x_ARCH_H__ diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x.cpp new file mode 100644 index 00000000..e728dd28 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x.cpp @@ -0,0 +1,693 @@ +/*! + * \file sx126x.c + * + * \brief SX126x driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#include +#include +#include "sx126x.h" +#include "sx126x-board.h" + +/*! + * \brief Radio registers definition + */ +typedef struct +{ + uint16_t Addr; //!< The address of the register + uint8_t Value; //!< The value of the register +}RadioRegisters_t; + +/*! + * \brief Holds the internal operating mode of the radio + */ +static RadioOperatingModes_t OperatingMode; + +/*! + * \brief Stores the current packet type set in the radio + */ +static RadioPacketTypes_t PacketType; + +/*! + * \brief Stores the last frequency error measured on LoRa received packet + */ +volatile uint32_t FrequencyError = 0; + +/*! + * \brief Hold the status of the Image calibration + */ +static bool ImageCalibrated = false; + +/* + * SX126x DIO IRQ callback functions prototype + */ + +/*! + * \brief DIO 0 IRQ callback + */ +void SX126xOnDioIrq( void ); + +/*! + * \brief DIO 0 IRQ callback + */ +void SX126xSetPollingMode( void ); + +/*! + * \brief DIO 0 IRQ callback + */ +void SX126xSetInterruptMode( void ); + +/* + * \brief Process the IRQ if handled by the driver + */ +void SX126xProcessIrqs( void ); + + +void SX126xInit( void ) +{ + SX126xReset( ); + SX126xWakeup( ); + SX126xSetStandby( STDBY_RC ); + +#ifdef USE_TCXO + CalibrationParams_t calibParam; + + SX126xSetDio3AsTcxoCtrl( TCXO_CTRL_3_3V, RADIO_TCXO_SETUP_TIME << 6 ); // convert from ms to SX126x time base + calibParam.Value = 0x7F; + SX126xCalibrate( calibParam.Value ); +#endif + + SX126xSetDio2AsRfSwitchCtrl( true ); + OperatingMode = MODE_STDBY_RC; +} + +uint8_t SX126xGetOperatingMode( void ) +{ + return OperatingMode; +} + +void SX126xCheckDeviceReady( void ) +{ + if( ( SX126xGetOperatingMode( ) == MODE_SLEEP ) || ( SX126xGetOperatingMode( ) == MODE_RX_DC ) ) + { + SX126xWakeup( ); + + } + SX126xWaitOnBusy( ); +} + +void SX126xSetPayload( uint8_t *payload, uint8_t size ) +{ + SX126xWriteBuffer( 0x00, payload, size ); +} + +uint8_t SX126xGetPayload( uint8_t *buffer, uint8_t *size, uint8_t maxSize ) +{ + uint8_t offset = 0; + + SX126xGetRxBufferStatus( size, &offset ); + if( *size > maxSize ) + { + return 1; + } + SX126xReadBuffer( offset, buffer, *size ); + return 0; +} + +void SX126xSendPayload( uint8_t *payload, uint8_t size, uint32_t timeout ) +{ + SX126xSetPayload( payload, size ); + SX126xSetTx( timeout ); +} + +uint8_t SX126xSetSyncWord( uint8_t *syncWord ) +{ + SX126xWriteRegisters( REG_LR_SYNCWORDBASEADDRESS, syncWord, 8 ); + return 0; +} + +void SX126xSetCrcSeed( uint16_t seed ) +{ + uint8_t buf[2]; + + buf[0] = ( uint8_t )( ( seed >> 8 ) & 0xFF ); + buf[1] = ( uint8_t )( seed & 0xFF ); + + switch( SX126xGetPacketType( ) ) + { + case PACKET_TYPE_GFSK: + SX126xWriteRegisters( REG_LR_CRCSEEDBASEADDR, buf, 2 ); + break; + + default: + break; + } +} + +void SX126xSetCrcPolynomial( uint16_t polynomial ) +{ + uint8_t buf[2]; + + buf[0] = ( uint8_t )( ( polynomial >> 8 ) & 0xFF ); + buf[1] = ( uint8_t )( polynomial & 0xFF ); + + switch( SX126xGetPacketType( ) ) + { + case PACKET_TYPE_GFSK: + SX126xWriteRegisters( REG_LR_CRCPOLYBASEADDR, buf, 2 ); + break; + + default: + break; + } +} + +void SX126xSetWhiteningSeed( uint16_t seed ) +{ + uint8_t regValue = 0; + + switch( SX126xGetPacketType( ) ) + { + case PACKET_TYPE_GFSK: + regValue = SX126xReadRegister( REG_LR_WHITSEEDBASEADDR_MSB ) & 0xFE; + regValue = ( ( seed >> 8 ) & 0x01 ) | regValue; + SX126xWriteRegister( REG_LR_WHITSEEDBASEADDR_MSB, regValue ); // only 1 bit. + SX126xWriteRegister( REG_LR_WHITSEEDBASEADDR_LSB, ( uint8_t )seed ); + break; + + default: + break; + } +} + +uint32_t SX126xGetRandom( void ) +{ + uint8_t buf[] = { 0, 0, 0, 0 }; + uint32_t ret_val = 0; + // Set radio in continuous reception + SX126xSetRx( 0 ); + + DelayMs( 1 ); + + SX126xReadRegisters( RANDOM_NUMBER_GENERATORBASEADDR, buf, 4 ); + + SX126xSetStandby( STDBY_RC ); + ret_val |= buf[0]; + ret_val = (ret_val<<8)+buf[1] ; + ret_val = (ret_val<<8)+buf[2] ; + ret_val = (ret_val<<8)+buf[3] ; + + return ret_val; +} + +void SX126xSetSleep( uint8_t sleepConfig ) +{ + + SX126xWriteCommand( RADIO_SET_SLEEP, &sleepConfig, 1 ); + OperatingMode = MODE_SLEEP; +} + +void SX126xSetStandby( uint8_t standbyConfig ) +{ + SX126xWriteCommand( RADIO_SET_STANDBY, ( uint8_t* )&standbyConfig, 1 ); + if( standbyConfig == STDBY_RC ) + { + OperatingMode = MODE_STDBY_RC; + } + else + { + OperatingMode = MODE_STDBY_XOSC; + } +} + +void SX126xSetFs( void ) +{ + SX126xWriteCommand( RADIO_SET_FS, 0, 0 ); + OperatingMode = MODE_FS; +} + +void SX126xSetTx( uint32_t timeout ) +{ + uint8_t buf[3]; + + OperatingMode = MODE_TX; + + buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( timeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_TX, buf, 3 ); +} + +void SX126xSetRx( uint32_t timeout ) +{ + uint8_t buf[3]; + + OperatingMode = MODE_RX; + + buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( timeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_RX, buf, 3 ); +} + +void SX126xSetRxBoosted( uint32_t timeout ) +{ + uint8_t buf[3]; + + OperatingMode = MODE_RX; + + SX126xWriteRegister( REG_RX_GAIN, 0x96 ); // max LNA gain, increase current by ~2mA for around ~3dB in sensivity + + buf[0] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( timeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_RX, buf, 3 ); +} + +void SX126xSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ) +{ + uint8_t buf[6]; + + buf[0] = ( uint8_t )( ( rxTime >> 16 ) & 0xFF ); + buf[1] = ( uint8_t )( ( rxTime >> 8 ) & 0xFF ); + buf[2] = ( uint8_t )( rxTime & 0xFF ); + buf[3] = ( uint8_t )( ( sleepTime >> 16 ) & 0xFF ); + buf[4] = ( uint8_t )( ( sleepTime >> 8 ) & 0xFF ); + buf[5] = ( uint8_t )( sleepTime & 0xFF ); + SX126xWriteCommand( RADIO_SET_RXDUTYCYCLE, buf, 6 ); + OperatingMode = MODE_RX_DC; +} + +void SX126xSetCad( void ) +{ + SX126xWriteCommand( RADIO_SET_CAD, 0, 0 ); + OperatingMode = MODE_CAD; +} + +void SX126xSetTxContinuousWave( void ) +{ + SX126xWriteCommand( RADIO_SET_TXCONTINUOUSWAVE, 0, 0 ); +} + +void SX126xSetTxInfinitePreamble( void ) +{ + SX126xWriteCommand( RADIO_SET_TXCONTINUOUSPREAMBLE, 0, 0 ); +} + +void SX126xSetStopRxTimerOnPreambleDetect( bool enable ) +{ + SX126xWriteCommand( RADIO_SET_STOPRXTIMERONPREAMBLE, ( uint8_t* )&enable, 1 ); +} + +void SX126xSetLoRaSymbNumTimeout( uint8_t SymbNum ) +{ + SX126xWriteCommand( RADIO_SET_LORASYMBTIMEOUT, &SymbNum, 1 ); +} + +void SX126xSetRegulatorMode( uint8_t mode ) +{ + SX126xWriteCommand( RADIO_SET_REGULATORMODE, ( uint8_t* )&mode, 1 ); +} + +void SX126xCalibrate( uint8_t calibParam ) +{ + SX126xWriteCommand( RADIO_CALIBRATE, ( uint8_t* )&calibParam, 1 ); +} + +void SX126xCalibrateImage( uint32_t freq ) +{ + uint8_t calFreq[2]; + + if( freq > 900000000 ) + { + calFreq[0] = 0xE1; + calFreq[1] = 0xE9; + } + else if( freq > 850000000 ) + { + calFreq[0] = 0xD7; + calFreq[1] = 0xD8; + } + else if( freq > 770000000 ) + { + calFreq[0] = 0xC1; + calFreq[1] = 0xC5; + } + else if( freq > 460000000 ) + { + calFreq[0] = 0x75; + calFreq[1] = 0x81; + } + else if( freq > 425000000 ) + { + calFreq[0] = 0x6B; + calFreq[1] = 0x6F; + } + SX126xWriteCommand( RADIO_CALIBRATEIMAGE, calFreq, 2 ); +} + +void SX126xSetPaConfig( uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut ) +{ + uint8_t buf[4]; + + buf[0] = paDutyCycle; + buf[1] = hpMax; + buf[2] = deviceSel; + buf[3] = paLut; + SX126xWriteCommand( RADIO_SET_PACONFIG, buf, 4 ); +} + +void SX126xSetRxTxFallbackMode( uint8_t fallbackMode ) +{ + SX126xWriteCommand( RADIO_SET_TXFALLBACKMODE, &fallbackMode, 1 ); +} + +void SX126xSetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ) +{ + uint8_t buf[8]; + + buf[0] = ( uint8_t )( ( irqMask >> 8 ) & 0x00FF ); + buf[1] = ( uint8_t )( irqMask & 0x00FF ); + buf[2] = ( uint8_t )( ( dio1Mask >> 8 ) & 0x00FF ); + buf[3] = ( uint8_t )( dio1Mask & 0x00FF ); + buf[4] = ( uint8_t )( ( dio2Mask >> 8 ) & 0x00FF ); + buf[5] = ( uint8_t )( dio2Mask & 0x00FF ); + buf[6] = ( uint8_t )( ( dio3Mask >> 8 ) & 0x00FF ); + buf[7] = ( uint8_t )( dio3Mask & 0x00FF ); + SX126xWriteCommand( RADIO_CFG_DIOIRQ, buf, 8 ); +} + +uint16_t SX126xGetIrqStatus( void ) +{ + uint8_t irqStatus[2]; + + SX126xReadCommand( RADIO_GET_IRQSTATUS, irqStatus, 2 ); + return ( irqStatus[0] << 8 ) | irqStatus[1]; +} + +void SX126xSetDio2AsRfSwitchCtrl( uint8_t enable ) +{ + SX126xWriteCommand( RADIO_SET_RFSWITCHMODE, &enable, 1 ); +} + +void SX126xSetDio3AsTcxoCtrl( uint8_t tcxoVoltage, uint32_t timeout ) +{ + uint8_t buf[4]; + + buf[0] = tcxoVoltage & 0x07; + buf[1] = ( uint8_t )( ( timeout >> 16 ) & 0xFF ); + buf[2] = ( uint8_t )( ( timeout >> 8 ) & 0xFF ); + buf[3] = ( uint8_t )( timeout & 0xFF ); + + SX126xWriteCommand( RADIO_SET_TCXOMODE, buf, 4 ); +} + +void SX126xSetRfFrequency( uint32_t frequency ) +{ + uint8_t buf[4]; + uint32_t freq = 0; + + if( ImageCalibrated == false ) + { + SX126xCalibrateImage( frequency ); + ImageCalibrated = true; + } + + freq = ( uint32_t )( ( double )frequency / ( double )FREQ_STEP ); + buf[0] = ( uint8_t )( ( freq >> 24 ) & 0xFF ); + buf[1] = ( uint8_t )( ( freq >> 16 ) & 0xFF ); + buf[2] = ( uint8_t )( ( freq >> 8 ) & 0xFF ); + buf[3] = ( uint8_t )( freq & 0xFF ); + SX126xWriteCommand( RADIO_SET_RFFREQUENCY, buf, 4 ); +} + +void SX126xSetPacketType( RadioPacketTypes_t packetType ) +{ + // Save packet type internally to avoid questioning the radio + PacketType = packetType; + SX126xWriteCommand( RADIO_SET_PACKETTYPE, ( uint8_t* )&packetType, 1 ); +} + +RadioPacketTypes_t SX126xGetPacketType( void ) +{ + return PacketType; +} + +void SX126xSetTxParams( int8_t power, uint8_t rampTime ) +{ + uint8_t buf[2]; + + + SX126xSetPaConfig( 0x04, 0x07, 0x00, 0x01 ); + if( power > 22 ) + { + power = 22; + } + else if( power < -3 ) + { + power = -3; + } + SX126xWriteRegister( REG_OCP, 0x38 ); // current max 160mA for the whole device + buf[0] = power; + buf[1] = ( uint8_t )rampTime; + SX126xWriteCommand( RADIO_SET_TXPARAMS, buf, 2 ); +} + +void SX126xSetModulationParams( void *input_ptr ) +{ + uint8_t n; + uint32_t tempVal = 0; + uint8_t buf[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + ModulationParams_t* modulationParams = (ModulationParams_t*)input_ptr; + // Check if required configuration corresponds to the stored packet type + // If not, silently update radio packet type + if( PacketType != modulationParams->PacketType ) + { + SX126xSetPacketType( modulationParams->PacketType ); + } + + switch( modulationParams->PacketType ) + { + case PACKET_TYPE_GFSK: + n = 8; + tempVal = ( uint32_t )( 32 * ( ( double )XTAL_FREQ / ( double )modulationParams->Params.Gfsk.BitRate ) ); + buf[0] = ( tempVal >> 16 ) & 0xFF; + buf[1] = ( tempVal >> 8 ) & 0xFF; + buf[2] = tempVal & 0xFF; + buf[3] = modulationParams->Params.Gfsk.ModulationShaping; + buf[4] = modulationParams->Params.Gfsk.Bandwidth; + tempVal = ( uint32_t )( ( double )modulationParams->Params.Gfsk.Fdev / ( double )FREQ_STEP ); + buf[5] = ( tempVal >> 16 ) & 0xFF; + buf[6] = ( tempVal >> 8 ) & 0xFF; + buf[7] = ( tempVal& 0xFF ); + SX126xWriteCommand( RADIO_SET_MODULATIONPARAMS, buf, n ); + break; + case PACKET_TYPE_LORA: + n = 4; + buf[0] = modulationParams->Params.LoRa.SpreadingFactor; + buf[1] = modulationParams->Params.LoRa.Bandwidth; + buf[2] = modulationParams->Params.LoRa.CodingRate; + buf[3] = modulationParams->Params.LoRa.LowDatarateOptimize; + + SX126xWriteCommand( RADIO_SET_MODULATIONPARAMS, buf, n ); + + break; + default: + case PACKET_TYPE_NONE: + return; + } +} + +void SX126xSetPacketParams( void* input_ptr ) +{ + uint8_t n; + uint8_t crcVal = 0; + uint8_t buf[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + PacketParams_t* packetParams = (PacketParams_t*)input_ptr; + // Check if required configuration corresponds to the stored packet type + // If not, silently update radio packet type + if( PacketType != packetParams->PacketType ) + { + SX126xSetPacketType( packetParams->PacketType ); + } + + switch( packetParams->PacketType ) + { + case PACKET_TYPE_GFSK: + if( packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_IBM ) + { + SX126xSetCrcSeed( CRC_IBM_SEED ); + SX126xSetCrcPolynomial( CRC_POLYNOMIAL_IBM ); + crcVal = RADIO_CRC_2_BYTES; + } + else if( packetParams->Params.Gfsk.CrcLength == RADIO_CRC_2_BYTES_CCIT ) + { + SX126xSetCrcSeed( CRC_CCITT_SEED ); + SX126xSetCrcPolynomial( CRC_POLYNOMIAL_CCITT ); + crcVal = RADIO_CRC_2_BYTES_INV; + } + else + { + crcVal = packetParams->Params.Gfsk.CrcLength; + } + n = 9; + buf[0] = ( packetParams->Params.Gfsk.PreambleLength >> 8 ) & 0xFF; + buf[1] = packetParams->Params.Gfsk.PreambleLength; + buf[2] = packetParams->Params.Gfsk.PreambleMinDetect; + buf[3] = ( packetParams->Params.Gfsk.SyncWordLength /*<< 3*/ ); // convert from byte to bit + buf[4] = packetParams->Params.Gfsk.AddrComp; + buf[5] = packetParams->Params.Gfsk.HeaderType; + buf[6] = packetParams->Params.Gfsk.PayloadLength; + buf[7] = crcVal; + buf[8] = packetParams->Params.Gfsk.DcFree; + break; + case PACKET_TYPE_LORA: + n = 6; + buf[0] = ( packetParams->Params.LoRa.PreambleLength >> 8 ) & 0xFF; + buf[1] = packetParams->Params.LoRa.PreambleLength; + buf[2] = packetParams->Params.LoRa.HeaderType; + buf[3] = packetParams->Params.LoRa.PayloadLength; + buf[4] = packetParams->Params.LoRa.CrcMode; + buf[5] = packetParams->Params.LoRa.InvertIQ; + break; + default: + case PACKET_TYPE_NONE: + return; + } + SX126xWriteCommand( RADIO_SET_PACKETPARAMS, buf, n ); +} + +void SX126xSetCadParams( uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout ) +{ + uint8_t buf[7]; + + buf[0] = ( uint8_t )cadSymbolNum; + buf[1] = cadDetPeak; + buf[2] = cadDetMin; + buf[3] = ( uint8_t )cadExitMode; + buf[4] = ( uint8_t )( ( cadTimeout >> 16 ) & 0xFF ); + buf[5] = ( uint8_t )( ( cadTimeout >> 8 ) & 0xFF ); + buf[6] = ( uint8_t )( cadTimeout & 0xFF ); + SX126xWriteCommand( RADIO_SET_CADPARAMS, buf, 5 ); + OperatingMode = MODE_CAD; +} + +void SX126xSetBufferBaseAddress( uint8_t txBaseAddress, uint8_t rxBaseAddress ) +{ + uint8_t buf[2]; + + buf[0] = txBaseAddress; + buf[1] = rxBaseAddress; + SX126xWriteCommand( RADIO_SET_BUFFERBASEADDRESS, buf, 2 ); +} + +uint8_t SX126xGetStatus( void ) +{ + uint8_t stat = 0; + + SX126xReadCommand( RADIO_GET_STATUS, ( uint8_t * )&stat, 1 ); + + return stat; +} + +int8_t SX126xGetRssiInst( void ) +{ + uint8_t buf[1]; + int8_t rssi = 0; + + SX126xReadCommand( RADIO_GET_RSSIINST, buf, 1 ); + rssi = -buf[0] >> 1; + return rssi; +} + +void SX126xGetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBufferPointer ) +{ + uint8_t status[2]; + + SX126xReadCommand( RADIO_GET_RXBUFFERSTATUS, status, 2 ); + + // In case of LORA fixed header, the payloadLength is obtained by reading + // the register REG_LR_PAYLOADLENGTH + if( ( SX126xGetPacketType( ) == PACKET_TYPE_LORA ) && ( SX126xReadRegister( REG_LR_PACKETPARAMS ) >> 7 == 1 ) ) + { + *payloadLength = SX126xReadRegister( REG_LR_PAYLOADLENGTH ); + } + else + { + *payloadLength = status[0]; + } + *rxStartBufferPointer = status[1]; +} + +void SX126xGetPacketStatus( void* input_ptr ) +{ + uint8_t status[3]; + PacketStatus_t *pktStatus = (PacketStatus_t *)input_ptr; + + SX126xReadCommand( RADIO_GET_PACKETSTATUS, status, 3 ); + + pktStatus->packetType = SX126xGetPacketType( ); + switch( pktStatus->packetType ) + { + case PACKET_TYPE_GFSK: + pktStatus->Params.Gfsk.RxStatus = status[0]; + pktStatus->Params.Gfsk.RssiSync = -status[1] >> 1; + pktStatus->Params.Gfsk.RssiAvg = -status[2] >> 1; + pktStatus->Params.Gfsk.FreqError = 0; + break; + + case PACKET_TYPE_LORA: + pktStatus->Params.LoRa.RssiPkt = -status[0] >> 1; + ( status[1] < 128 ) ? ( pktStatus->Params.LoRa.SnrPkt = status[1] >> 2 ) : ( pktStatus->Params.LoRa.SnrPkt = ( ( status[1] - 256 ) >> 2 ) ); + pktStatus->Params.LoRa.SignalRssiPkt = -status[2] >> 1; + pktStatus->Params.LoRa.FreqError = FrequencyError; + break; + + default: + case PACKET_TYPE_NONE: + // In that specific case, we set everything in the pktStatus to zeros + // and reset the packet type accordingly + memset( pktStatus, 0, sizeof( PacketStatus_t ) ); + pktStatus->packetType = PACKET_TYPE_NONE; + break; + } +} + +uint16_t SX126xGetDeviceErrors( void ) +{ + uint16_t error; + + SX126xReadCommand( RADIO_GET_ERROR, ( uint8_t * )&error, 2 ); + return error; +} + +void SX126xClearDeviceErrors( void ) +{ + uint8_t buf[2] = { 0x00, 0x00 }; + SX126xWriteCommand( RADIO_CLR_ERROR, buf, 2 ); +} + +void SX126xClearIrqStatus( uint16_t irq ) +{ + uint8_t buf[2]; + + buf[0] = ( uint8_t )( ( ( uint16_t )irq >> 8 ) & 0x00FF ); + buf[1] = ( uint8_t )( ( uint16_t )irq & 0x00FF ); + SX126xWriteCommand( RADIO_CLR_IRQSTATUS, buf, 2 ); +} diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x.h new file mode 100644 index 00000000..012124dc --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/sx126x.h @@ -0,0 +1,1115 @@ +/*! + * \file sx126x.h + * + * \brief SX126x driver implementation + * + * \copyright Revised BSD License, see section \ref LICENSE. + * + * \code + * ______ _ + * / _____) _ | | + * ( (____ _____ ____ _| |_ _____ ____| |__ + * \____ \| ___ | (_ _) ___ |/ ___) _ \ + * _____) ) ____| | | || |_| ____( (___| | | | + * (______/|_____)_|_|_| \__)_____)\____)_| |_| + * (C)2013-2017 Semtech + * + * \endcode + * + * \author Miguel Luis ( Semtech ) + * + * \author Gregory Cristian ( Semtech ) + */ +#ifndef __SX126x_H__ +#define __SX126x_H__ +#include "stdint.h" +#include "stdbool.h" + + +#define USE_TCXO +#define SX1261 1 +#define SX1262 2 + +#ifdef USE_TCXO + /*! + * Radio complete Wake-up Time with TCXO stabilisation time + */ + #define RADIO_TCXO_SETUP_TIME 5 // [ms] +#else + /*! + * Radio complete Wake-up Time with TCXO stabilisation time + */ + #define RADIO_TCXO_SETUP_TIME 0 // No Used +#endif + +/*! + * Radio complete Wake-up Time with margin for temperature compensation + */ +#define RADIO_WAKEUP_TIME 3 // [ms] + +/*! + * \brief Compensation delay for SetAutoTx/Rx functions in 15.625 microseconds + */ +#define AUTO_RX_TX_OFFSET 2 + +/*! + * \brief LFSR initial value to compute IBM type CRC + */ +#define CRC_IBM_SEED 0xFFFF + +/*! + * \brief LFSR initial value to compute CCIT type CRC + */ +#define CRC_CCITT_SEED 0x1D0F + +/*! + * \brief Polynomial used to compute IBM CRC + */ +#define CRC_POLYNOMIAL_IBM 0x8005 + +/*! + * \brief Polynomial used to compute CCIT CRC + */ +#define CRC_POLYNOMIAL_CCITT 0x1021 + +/*! + * \brief The address of the register holding the first byte defining the CRC seed + * + */ +#define REG_LR_CRCSEEDBASEADDR 0x06BC + +/*! + * \brief The address of the register holding the first byte defining the CRC polynomial + */ +#define REG_LR_CRCPOLYBASEADDR 0x06BE + +/*! + * \brief The address of the register holding the first byte defining the whitening seed + */ +#define REG_LR_WHITSEEDBASEADDR_MSB 0x06B8 +#define REG_LR_WHITSEEDBASEADDR_LSB 0x06B9 + +/*! + * \brief The address of the register holding the packet configuration + */ +#define REG_LR_PACKETPARAMS 0x0704 + +/*! + * \brief The address of the register holding the payload size + */ +#define REG_LR_PAYLOADLENGTH 0x0702 + +/*! + * \brief The addresses of the registers holding SyncWords values + */ +#define REG_LR_SYNCWORDBASEADDRESS 0x06C0 + +/*! + * \brief The addresses of the register holding LoRa Modem SyncWord value + */ +#define REG_LR_SYNCWORD 0x0740 + +/*! + * Syncword for Private LoRa networks + */ +#define LORA_MAC_PRIVATE_SYNCWORD 0x1424 + +/*! + * Syncword for Public LoRa networks + */ +#define LORA_MAC_PUBLIC_SYNCWORD 0x3444 + +/*! + * The address of the register giving a 4 bytes random number + */ +#define RANDOM_NUMBER_GENERATORBASEADDR 0x0819 + +/*! + * The address of the register holding RX Gain value (0x94: power saving, 0x96: rx boosted) + */ +#define REG_RX_GAIN 0x08AC + +/*! + * Change the value on the device internal trimming capacitor + */ +#define REG_XTA_TRIM 0x0911 + +/*! + * Set the current max value in the over current protection + */ +#define REG_OCP 0x08E7 + +/*! + * \brief Structure describing the radio status + */ +typedef union RadioStatus_u +{ + uint8_t Value; + struct + { //bit order is lsb -> msb + uint8_t Reserved : 1; //!< Reserved + uint8_t CmdStatus : 3; //!< Command status + uint8_t ChipMode : 3; //!< Chip mode + uint8_t CpuBusy : 1; //!< Flag for CPU radio busy + }Fields; +}RadioStatus_t; + +/*! + * \brief Structure describing the error codes for callback functions + */ +typedef enum +{ + IRQ_HEADER_ERROR_CODE = 0x01, + IRQ_SYNCWORD_ERROR_CODE = 0x02, + IRQ_CRC_ERROR_CODE = 0x04, +}IrqErrorCode_t; + +enum IrqPblSyncHeaderCode_t +{ + IRQ_PBL_DETECT_CODE = 0x01, + IRQ_SYNCWORD_VALID_CODE = 0x02, + IRQ_HEADER_VALID_CODE = 0x04, +}; + +/*! + * \brief Represents the operating mode the radio is actually running + */ +typedef enum +{ + MODE_SLEEP = 0x00, //! The radio is in sleep mode + MODE_STDBY_RC, //! The radio is in standby mode with RC oscillator + MODE_STDBY_XOSC, //! The radio is in standby mode with XOSC oscillator + MODE_FS, //! The radio is in frequency synthesis mode + MODE_TX, //! The radio is in transmit mode + MODE_RX, //! The radio is in receive mode + MODE_RX_DC, //! The radio is in receive duty cycle mode + MODE_CAD //! The radio is in channel activity detection mode +}RadioOperatingModes_t; + +/*! + * \brief Declares the oscillator in use while in standby mode + * + * Using the STDBY_RC standby mode allow to reduce the energy consumption + * STDBY_XOSC should be used for time critical applications + */ +typedef enum +{ + STDBY_RC = 0x00, + STDBY_XOSC = 0x01, +}RadioStandbyModes_t; + +/*! + * \brief Declares the power regulation used to power the device + * + * This command allows the user to specify if DC-DC or LDO is used for power regulation. + * Using only LDO implies that the Rx or Tx current is doubled + */ +typedef enum +{ + USE_LDO = 0x00, // default + USE_DCDC = 0x01, +}RadioRegulatorMode_t; + +/*! + * \brief Represents the possible packet type (i.e. modem) used + */ +typedef enum +{ + PACKET_TYPE_GFSK = 0x00, + PACKET_TYPE_LORA = 0x01, + PACKET_TYPE_NONE = 0x0F, +}RadioPacketTypes_t; + +/*! + * \brief Represents the ramping time for power amplifier + */ +typedef enum +{ + RADIO_RAMP_10_US = 0x00, + RADIO_RAMP_20_US = 0x01, + RADIO_RAMP_40_US = 0x02, + RADIO_RAMP_80_US = 0x03, + RADIO_RAMP_200_US = 0x04, + RADIO_RAMP_800_US = 0x05, + RADIO_RAMP_1700_US = 0x06, + RADIO_RAMP_3400_US = 0x07, +}RadioRampTimes_t; + +/*! + * \brief Represents the number of symbols to be used for channel activity detection operation + */ +typedef enum +{ + LORA_CAD_01_SYMBOL = 0x00, + LORA_CAD_02_SYMBOL = 0x01, + LORA_CAD_04_SYMBOL = 0x02, + LORA_CAD_08_SYMBOL = 0x03, + LORA_CAD_16_SYMBOL = 0x04, +}RadioLoRaCadSymbols_t; + +/*! + * \brief Represents the Channel Activity Detection actions after the CAD operation is finished + */ +typedef enum +{ + LORA_CAD_ONLY = 0x00, + LORA_CAD_RX = 0x01, + LORA_CAD_LBT = 0x10, +}RadioCadExitModes_t; + +/*! + * \brief Represents the modulation shaping parameter + */ +typedef enum +{ + MOD_SHAPING_OFF = 0x00, + MOD_SHAPING_G_BT_03 = 0x08, + MOD_SHAPING_G_BT_05 = 0x09, + MOD_SHAPING_G_BT_07 = 0x0A, + MOD_SHAPING_G_BT_1 = 0x0B, +}RadioModShapings_t; + +/*! + * \brief Represents the modulation shaping parameter + */ +typedef enum +{ + RX_BW_4800 = 0x1F, + RX_BW_5800 = 0x17, + RX_BW_7300 = 0x0F, + RX_BW_9700 = 0x1E, + RX_BW_11700 = 0x16, + RX_BW_14600 = 0x0E, + RX_BW_19500 = 0x1D, + RX_BW_23400 = 0x15, + RX_BW_29300 = 0x0D, + RX_BW_39000 = 0x1C, + RX_BW_46900 = 0x14, + RX_BW_58600 = 0x0C, + RX_BW_78200 = 0x1B, + RX_BW_93800 = 0x13, + RX_BW_117300 = 0x0B, + RX_BW_156200 = 0x1A, + RX_BW_187200 = 0x12, + RX_BW_234300 = 0x0A, + RX_BW_312000 = 0x19, + RX_BW_373600 = 0x11, + RX_BW_467000 = 0x09, +}RadioRxBandwidth_t; + +/*! + * \brief Represents the possible spreading factor values in LoRa packet types + */ +typedef enum +{ + LORA_SF5 = 0x05, + LORA_SF6 = 0x06, + LORA_SF7 = 0x07, + LORA_SF8 = 0x08, + LORA_SF9 = 0x09, + LORA_SF10 = 0x0A, + LORA_SF11 = 0x0B, + LORA_SF12 = 0x0C, +}RadioLoRaSpreadingFactors_t; + +/*! + * \brief Represents the bandwidth values for LoRa packet type + */ +typedef enum +{ + LORA_BW_500 = 6, + LORA_BW_250 = 5, + LORA_BW_125 = 4, + LORA_BW_062 = 3, + LORA_BW_041 = 10, + LORA_BW_031 = 2, + LORA_BW_020 = 9, + LORA_BW_015 = 1, + LORA_BW_010 = 8, + LORA_BW_007 = 0, +}RadioLoRaBandwidths_t; + +/*! + * \brief Represents the coding rate values for LoRa packet type + */ +typedef enum +{ + LORA_CR_4_5 = 0x01, + LORA_CR_4_6 = 0x02, + LORA_CR_4_7 = 0x03, + LORA_CR_4_8 = 0x04, +}RadioLoRaCodingRates_t; + +/*! + * \brief Represents the preamble length used to detect the packet on Rx side + */ +typedef enum +{ + RADIO_PREAMBLE_DETECTOR_OFF = 0x00, //!< Preamble detection length off + RADIO_PREAMBLE_DETECTOR_08_BITS = 0x04, //!< Preamble detection length 8 bits + RADIO_PREAMBLE_DETECTOR_16_BITS = 0x05, //!< Preamble detection length 16 bits + RADIO_PREAMBLE_DETECTOR_24_BITS = 0x06, //!< Preamble detection length 24 bits + RADIO_PREAMBLE_DETECTOR_32_BITS = 0x07, //!< Preamble detection length 32 bit +}RadioPreambleDetection_t; + +/*! + * \brief Represents the possible combinations of SyncWord correlators activated + */ +typedef enum +{ + RADIO_ADDRESSCOMP_FILT_OFF = 0x00, //!< No correlator turned on, i.e. do not search for SyncWord + RADIO_ADDRESSCOMP_FILT_NODE = 0x01, + RADIO_ADDRESSCOMP_FILT_NODE_BROAD = 0x02, +}RadioAddressComp_t; + +/*! + * \brief Radio GFSK packet length mode + */ +typedef enum +{ + RADIO_PACKET_FIXED_LENGTH = 0x00, //!< The packet is known on both sides, no header included in the packet + RADIO_PACKET_VARIABLE_LENGTH = 0x01, //!< The packet is on variable size, header included +}RadioPacketLengthModes_t; + +/*! + * \brief Represents the CRC length + */ +typedef enum +{ + RADIO_CRC_OFF = 0x01, //!< No CRC in use + RADIO_CRC_1_BYTES = 0x00, + RADIO_CRC_2_BYTES = 0x02, + RADIO_CRC_1_BYTES_INV = 0x04, + RADIO_CRC_2_BYTES_INV = 0x06, + RADIO_CRC_2_BYTES_IBM = 0xF1, + RADIO_CRC_2_BYTES_CCIT = 0xF2, +}RadioCrcTypes_t; + +/*! + * \brief Radio whitening mode activated or deactivated + */ +typedef enum +{ + RADIO_DC_FREE_OFF = 0x00, + RADIO_DC_FREEWHITENING = 0x01, +}RadioDcFree_t; + +/*! + * \brief Holds the Radio lengths mode for the LoRa packet type + */ +typedef enum +{ + LORA_PACKET_VARIABLE_LENGTH = 0x00, //!< The packet is on variable size, header included + LORA_PACKET_FIXED_LENGTH = 0x01, //!< The packet is known on both sides, no header included in the packet + LORA_PACKET_EXPLICIT = LORA_PACKET_VARIABLE_LENGTH, + LORA_PACKET_IMPLICIT = LORA_PACKET_FIXED_LENGTH, +}RadioLoRaPacketLengthsMode_t; + +/*! + * \brief Represents the CRC mode for LoRa packet type + */ +typedef enum +{ + LORA_CRC_ON = 0x01, //!< CRC activated + LORA_CRC_OFF = 0x00, //!< CRC not used +}RadioLoRaCrcModes_t; + +/*! + * \brief Represents the IQ mode for LoRa packet type + */ +typedef enum +{ + LORA_IQ_NORMAL = 0x00, + LORA_IQ_INVERTED = 0x01, +}RadioLoRaIQModes_t; + +/*! + * \brief Represents the voltage used to control the TCXO on/off from DIO3 + */ +typedef enum +{ + TCXO_CTRL_1_6V = 0x00, + TCXO_CTRL_1_7V = 0x01, + TCXO_CTRL_1_8V = 0x02, + TCXO_CTRL_2_2V = 0x03, + TCXO_CTRL_2_4V = 0x04, + TCXO_CTRL_2_7V = 0x05, + TCXO_CTRL_3_0V = 0x06, + TCXO_CTRL_3_3V = 0x07, +}RadioTcxoCtrlVoltage_t; + +/*! + * \brief Represents the interruption masks available for the radio + * + * \remark Note that not all these interruptions are available for all packet types + */ +typedef enum +{ + IRQ_RADIO_NONE = 0x0000, + IRQ_TX_DONE = 0x0001, + IRQ_RX_DONE = 0x0002, + IRQ_PREAMBLE_DETECTED = 0x0004, + IRQ_SYNCWORD_VALID = 0x0008, + IRQ_HEADER_VALID = 0x0010, + IRQ_HEADER_ERROR = 0x0020, + IRQ_CRC_ERROR = 0x0040, + IRQ_CAD_DONE = 0x0080, + IRQ_CAD_ACTIVITY_DETECTED = 0x0100, + IRQ_RX_TX_TIMEOUT = 0x0200, + IRQ_RADIO_ALL = 0xFFFF, +}RadioIrqMasks_t; + +/*! + * \brief Represents all possible opcode understood by the radio + */ +typedef enum RadioCommands_e +{ + RADIO_GET_STATUS = 0xC0, + RADIO_WRITE_REGISTER = 0x0D, + RADIO_READ_REGISTER = 0x1D, + RADIO_WRITE_BUFFER = 0x0E, + RADIO_READ_BUFFER = 0x1E, + RADIO_SET_SLEEP = 0x84, + RADIO_SET_STANDBY = 0x80, + RADIO_SET_FS = 0xC1, + RADIO_SET_TX = 0x83, + RADIO_SET_RX = 0x82, + RADIO_SET_RXDUTYCYCLE = 0x94, + RADIO_SET_CAD = 0xC5, + RADIO_SET_TXCONTINUOUSWAVE = 0xD1, + RADIO_SET_TXCONTINUOUSPREAMBLE = 0xD2, + RADIO_SET_PACKETTYPE = 0x8A, + RADIO_GET_PACKETTYPE = 0x11, + RADIO_SET_RFFREQUENCY = 0x86, + RADIO_SET_TXPARAMS = 0x8E, + RADIO_SET_PACONFIG = 0x95, + RADIO_SET_CADPARAMS = 0x88, + RADIO_SET_BUFFERBASEADDRESS = 0x8F, + RADIO_SET_MODULATIONPARAMS = 0x8B, + RADIO_SET_PACKETPARAMS = 0x8C, + RADIO_GET_RXBUFFERSTATUS = 0x13, + RADIO_GET_PACKETSTATUS = 0x14, + RADIO_GET_RSSIINST = 0x15, + RADIO_GET_STATS = 0x10, + RADIO_RESET_STATS = 0x00, + RADIO_CFG_DIOIRQ = 0x08, + RADIO_GET_IRQSTATUS = 0x12, + RADIO_CLR_IRQSTATUS = 0x02, + RADIO_CALIBRATE = 0x89, + RADIO_CALIBRATEIMAGE = 0x98, + RADIO_SET_REGULATORMODE = 0x96, + RADIO_GET_ERROR = 0x17, + RADIO_CLR_ERROR = 0x07, + RADIO_SET_TCXOMODE = 0x97, + RADIO_SET_TXFALLBACKMODE = 0x93, + RADIO_SET_RFSWITCHMODE = 0x9D, + RADIO_SET_STOPRXTIMERONPREAMBLE = 0x9F, + RADIO_SET_LORASYMBTIMEOUT = 0xA0, +}RadioCommands_t; + +/*! + * \brief The type describing the modulation parameters for every packet types + */ +typedef struct +{ + RadioPacketTypes_t PacketType; //!< Packet to which the modulation parameters are referring to. + struct + { + struct + { + uint32_t BitRate; + uint32_t Fdev; + RadioModShapings_t ModulationShaping; + uint8_t Bandwidth; + }Gfsk; + struct + { + RadioLoRaSpreadingFactors_t SpreadingFactor; //!< Spreading Factor for the LoRa modulation + RadioLoRaBandwidths_t Bandwidth; //!< Bandwidth for the LoRa modulation + RadioLoRaCodingRates_t CodingRate; //!< Coding rate for the LoRa modulation + uint8_t LowDatarateOptimize; //!< Indicates if the modem uses the low datarate optimization + }LoRa; + }Params; //!< Holds the modulation parameters structure +}ModulationParams_t; + +/*! + * \brief The type describing the packet parameters for every packet types + */ +typedef struct +{ + RadioPacketTypes_t PacketType; //!< Packet to which the packet parameters are referring to. + struct + { + /*! + * \brief Holds the GFSK packet parameters + */ + struct + { + uint16_t PreambleLength; //!< The preamble Tx length for GFSK packet type in bit + RadioPreambleDetection_t PreambleMinDetect; //!< The preamble Rx length minimal for GFSK packet type + uint8_t SyncWordLength; //!< The synchronization word length for GFSK packet type + RadioAddressComp_t AddrComp; //!< Activated SyncWord correlators + RadioPacketLengthModes_t HeaderType; //!< If the header is explicit, it will be transmitted in the GFSK packet. If the header is implicit, it will not be transmitted + uint8_t PayloadLength; //!< Size of the payload in the GFSK packet + RadioCrcTypes_t CrcLength; //!< Size of the CRC block in the GFSK packet + RadioDcFree_t DcFree; + }Gfsk; + /*! + * \brief Holds the LoRa packet parameters + */ + struct + { + uint16_t PreambleLength; //!< The preamble length is the number of LoRa symbols in the preamble + RadioLoRaPacketLengthsMode_t HeaderType; //!< If the header is explicit, it will be transmitted in the LoRa packet. If the header is implicit, it will not be transmitted + uint8_t PayloadLength; //!< Size of the payload in the LoRa packet + RadioLoRaCrcModes_t CrcMode; //!< Size of CRC block in LoRa packet + RadioLoRaIQModes_t InvertIQ; //!< Allows to swap IQ for LoRa packet + }LoRa; + }Params; //!< Holds the packet parameters structure +}PacketParams_t; + +/*! + * \brief Represents the packet status for every packet type + */ +typedef struct +{ + RadioPacketTypes_t packetType; //!< Packet to which the packet status are referring to. + struct + { + struct + { + uint8_t RxStatus; + int8_t RssiAvg; //!< The averaged RSSI + int8_t RssiSync; //!< The RSSI measured on last packet + uint32_t FreqError; + }Gfsk; + struct + { + int8_t RssiPkt; //!< The RSSI of the last packet + int8_t SnrPkt; //!< The SNR of the last packet + int8_t SignalRssiPkt; + uint32_t FreqError; + }LoRa; + }Params; +}PacketStatus_t; + +/*! + * \brief Represents the Rx internal counters values when GFSK or LoRa packet type is used + */ +typedef struct +{ + RadioPacketTypes_t packetType; //!< Packet to which the packet status are referring to. + uint16_t PacketReceived; + uint16_t CrcOk; + uint16_t LengthError; +}RxCounter_t; + +/*! + * \brief Represents a calibration configuration + */ +typedef union +{ + struct + { + uint8_t RC64KEnable : 1; //!< Calibrate RC64K clock + uint8_t RC13MEnable : 1; //!< Calibrate RC13M clock + uint8_t PLLEnable : 1; //!< Calibrate PLL + uint8_t ADCPulseEnable : 1; //!< Calibrate ADC Pulse + uint8_t ADCBulkNEnable : 1; //!< Calibrate ADC bulkN + uint8_t ADCBulkPEnable : 1; //!< Calibrate ADC bulkP + uint8_t ImgEnable : 1; + uint8_t : 1; + }Fields; + uint8_t Value; +}CalibrationParams_t; + +/*! + * \brief Represents a sleep mode configuration + */ +typedef union +{ + struct + { + uint8_t WakeUpRTC : 1; //!< Get out of sleep mode if wakeup signal received from RTC + uint8_t Reset : 1; + uint8_t WarmStart : 1; + uint8_t Reserved : 5; + }Fields; + uint8_t Value; +}SleepParams_t; + +/*! + * \brief Represents the possible radio system error states + */ +typedef union +{ + struct + { + uint8_t Rc64kCalib : 1; //!< RC 64kHz oscillator calibration failed + uint8_t Rc13mCalib : 1; //!< RC 13MHz oscillator calibration failed + uint8_t PllCalib : 1; //!< PLL calibration failed + uint8_t AdcCalib : 1; //!< ADC calibration failed + uint8_t ImgCalib : 1; //!< Image calibration failed + uint8_t XoscStart : 1; //!< XOSC oscillator failed to start + uint8_t PllLock : 1; //!< PLL lock failed + uint8_t BuckStart : 1; //!< Buck converter failed to start + uint8_t PaRamp : 1; //!< PA ramp failed + uint8_t : 7; //!< Reserved + }Fields; + uint16_t Value; +}RadioError_t; + +/*! + * Radio hardware and global parameters + */ +typedef struct SX126x_s +{ +// Gpio_t Reset; +// Gpio_t BUSY; +// Gpio_t DIO1; +// Gpio_t DIO2; +// Gpio_t DIO3; +// Spi_t Spi; + PacketParams_t PacketParams; + PacketStatus_t PacketStatus; + ModulationParams_t ModulationParams; +}SX126x_t; + +/*! + * Hardware IO IRQ callback function definition + */ +typedef void ( DioIrqHandler )( void ); + +/*! + * SX126x definitions + */ + +/*! + * \brief Provides the frequency of the chip running on the radio and the frequency step + * + * \remark These defines are used for computing the frequency divider to set the RF frequency + */ +#define XTAL_FREQ ( double )32000000 +#define FREQ_DIV ( double )pow( 2.0, 25.0 ) +#define FREQ_STEP ( double )( XTAL_FREQ / FREQ_DIV ) + +#define RX_BUFFER_SIZE 256 + +/*! + * \brief The radio callbacks structure + * Holds function pointers to be called on radio interrupts + */ +typedef struct +{ + void ( *txDone )( void ); //!< Pointer to a function run on successful transmission + void ( *rxDone )( void ); //!< Pointer to a function run on successful reception + void ( *rxPreambleDetect )( void ); //!< Pointer to a function run on successful Preamble detection + void ( *rxSyncWordDone )( void ); //!< Pointer to a function run on successful SyncWord reception + void ( *rxHeaderDone )( bool isOk ); //!< Pointer to a function run on successful Header reception + void ( *txTimeout )( void ); //!< Pointer to a function run on transmission timeout + void ( *rxTimeout )( void ); //!< Pointer to a function run on reception timeout + void ( *rxError )( IrqErrorCode_t errCode ); //!< Pointer to a function run on reception error + void ( *cadDone )( bool cadFlag ); //!< Pointer to a function run on channel activity detected +}SX126xCallbacks_t; + +/*! + * ============================================================================ + * Public functions prototypes + * ============================================================================ + */ + +/*! + * \brief Initializes the radio driver + */ +void SX126xInit( void ); + +/*! + * \brief Gets the current Operation Mode of the Radio + * + * \retval RadioOperatingModes_t last operating mode + */ +uint8_t SX126xGetOperatingMode( void ); + +/*! + * \brief Wakeup the radio if it is in Sleep mode and check that Busy is low + */ +void SX126xCheckDeviceReady( void ); + +/*! + * \brief Saves the payload to be send in the radio buffer + * + * \param [in] payload A pointer to the payload + * \param [in] size The size of the payload + */ +void SX126xSetPayload( uint8_t *payload, uint8_t size ); + +/*! + * \brief Reads the payload received. If the received payload is longer + * than maxSize, then the method returns 1 and do not set size and payload. + * + * \param [out] payload A pointer to a buffer into which the payload will be copied + * \param [out] size A pointer to the size of the payload received + * \param [in] maxSize The maximal size allowed to copy into the buffer + */ +uint8_t SX126xGetPayload( uint8_t *payload, uint8_t *size, uint8_t maxSize ); + +/*! + * \brief Sends a payload + * + * \param [in] payload A pointer to the payload to send + * \param [in] size The size of the payload to send + * \param [in] timeout The timeout for Tx operation + */ +void SX126xSendPayload( uint8_t *payload, uint8_t size, uint32_t timeout ); + +/*! + * \brief Sets the Sync Word given by index used in GFSK + * + * \param [in] syncWord SyncWord bytes ( 8 bytes ) + * + * \retval status [0: OK, 1: NOK] + */ +uint8_t SX126xSetSyncWord( uint8_t *syncWord ); + +/*! + * \brief Sets the Initial value for the LFSR used for the CRC calculation + * + * \param [in] seed Initial LFSR value ( 2 bytes ) + * + */ +void SX126xSetCrcSeed( uint16_t seed ); + +/*! + * \brief Sets the seed used for the CRC calculation + * + * \param [in] seed The seed value + * + */ +void SX126xSetCrcPolynomial( uint16_t polynomial ); + +/*! + * \brief Sets the Initial value of the LFSR used for the whitening in GFSK protocols + * + * \param [in] seed Initial LFSR value + */ +void SX126xSetWhiteningSeed( uint16_t seed ); + +/*! + * \brief Gets a 32 bits random value generated by the radio + * + * \remark The radio must be in reception mode before executing this function + * + * \retval randomValue 32 bits random value + */ +uint32_t SX126xGetRandom( void ); + +/*! + * \brief Sets the radio in sleep mode + * + * \param [in] sleepConfig The sleep configuration describing data + * retention and RTC wake-up + */ +void SX126xSetSleep( uint8_t sleepConfig ); + +/*! + * \brief Sets the radio in configuration mode + * + * \param [in] mode The standby mode to put the radio into + */ +void SX126xSetStandby( uint8_t mode ); + +/*! + * \brief Sets the radio in FS mode + */ +void SX126xSetFs( void ); + +/*! + * \brief Sets the radio in transmission mode + * + * \param [in] timeout Structure describing the transmission timeout value + */ +void SX126xSetTx( uint32_t timeout ); + +/*! + * \brief Sets the radio in reception mode + * + * \param [in] timeout Structure describing the reception timeout value + */ +void SX126xSetRx( uint32_t timeout ); + +/*! + * \brief Sets the radio in reception mode with Boosted LNA gain + * + * \param [in] timeout Structure describing the reception timeout value + */ +void SX126xSetRxBoosted( uint32_t timeout ); + +/*! + * \brief Sets the Rx duty cycle management parameters + * + * \param [in] rxTime Structure describing reception timeout value + * \param [in] sleepTime Structure describing sleep timeout value + */ +void SX126xSetRxDutyCycle( uint32_t rxTime, uint32_t sleepTime ); + +/*! + * \brief Sets the radio in CAD mode + */ +void SX126xSetCad( void ); + +/*! + * \brief Sets the radio in continuous wave transmission mode + */ +void SX126xSetTxContinuousWave( void ); + +/*! + * \brief Sets the radio in continuous preamble transmission mode + */ +void SX126xSetTxInfinitePreamble( void ); + +/*! + * \brief Decide which interrupt will stop the internal radio rx timer. + * + * \param [in] enable [0: Timer stop after header/syncword detection + * 1: Timer stop after preamble detection] + */ +void SX126xSetStopRxTimerOnPreambleDetect( bool enable ); + +/*! + * \brief Set the number of symbol the radio will wait to validate a reception + * + * \param [in] SymbNum number of LoRa symbols + */ +void SX126xSetLoRaSymbNumTimeout( uint8_t SymbNum ); + +/*! + * \brief Sets the power regulators operating mode + * + * \param [in] mode [0: LDO, 1:DC_DC] + */ +void SX126xSetRegulatorMode( uint8_t mode ); + +/*! + * \brief Calibrates the given radio block + * + * \param [in] calibParam The description of blocks to be calibrated + */ +void SX126xCalibrate( uint8_t calibParam ); + +/*! + * \brief Calibrates the Image rejection depending of the frequency + * + * \param [in] freq The operating frequency + */ +void SX126xCalibrateImage( uint32_t freq ); + +/*! + * \brief Activate the extention of the timeout when long preamble is used + * + * \param [in] enable The radio will extend the timeout to cope with long preamble + */ +void SX126xSetLongPreamble( uint8_t enable ); + +/*! + * \brief Sets the transmission parameters + * + * \param [in] paDutyCycle Duty Cycle for the PA + * \param [in] hpMax 0 for sx1261, 7 for sx1262 + * \param [in] deviceSel 1 for sx1261, 0 for sx1262 + * \param [in] paLut 0 for 14dBm LUT, 1 for 22dBm LUT + */ +void SX126xSetPaConfig( uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut ); + +/*! + * \brief Defines into which mode the chip goes after a TX / RX done + * + * \param [in] fallbackMode The mode in which the radio goes + */ +void SX126xSetRxTxFallbackMode( uint8_t fallbackMode ); + +/*! + * \brief Write data to the radio memory + * + * \param [in] address The address of the first byte to write in the radio + * \param [in] buffer The data to be written in radio's memory + * \param [in] size The number of bytes to write in radio's memory + */ +void SX126xWriteRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Read data from the radio memory + * + * \param [in] address The address of the first byte to read from the radio + * \param [out] buffer The buffer that holds data read from radio + * \param [in] size The number of bytes to read from radio's memory + */ +void SX126xReadRegisters( uint16_t address, uint8_t *buffer, uint16_t size ); + +/*! + * \brief Write data to the buffer holding the payload in the radio + * + * \param [in] offset The offset to start writing the payload + * \param [in] buffer The data to be written (the payload) + * \param [in] size The number of byte to be written + */ +void SX126xWriteBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Read data from the buffer holding the payload in the radio + * + * \param [in] offset The offset to start reading the payload + * \param [out] buffer A pointer to a buffer holding the data from the radio + * \param [in] size The number of byte to be read + */ +void SX126xReadBuffer( uint8_t offset, uint8_t *buffer, uint8_t size ); + +/*! + * \brief Sets the IRQ mask and DIO masks + * + * \param [in] irqMask General IRQ mask + * \param [in] dio1Mask DIO1 mask + * \param [in] dio2Mask DIO2 mask + * \param [in] dio3Mask DIO3 mask + */ +void SX126xSetDioIrqParams( uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask ); + +/*! + * \brief Returns the current IRQ status + * + * \retval irqStatus IRQ status + */ +uint16_t SX126xGetIrqStatus( void ); + +/*! + * \brief Indicates if DIO2 is used to control an RF Switch + * + * \param [in] enable true of false + */ +void SX126xSetDio2AsRfSwitchCtrl( uint8_t enable ); + +/*! + * \brief Indicates if the Radio main clock is supplied from a tcxo + * + * \param [in] tcxoVoltage voltage used to control the TCXO + * \param [in] timeout time given to the TCXO to go to 32MHz + */ +void SX126xSetDio3AsTcxoCtrl( uint8_t tcxoVoltage, uint32_t timeout ); + +/*! + * \brief Sets the RF frequency + * + * \param [in] frequency RF frequency [Hz] + */ +void SX126xSetRfFrequency( uint32_t frequency ); + +/*! + * \brief Sets the radio for the given protocol + * + * \param [in] packetType [PACKET_TYPE_GFSK, PACKET_TYPE_LORA] + * + * \remark This method has to be called before SetRfFrequency, + * SetModulationParams and SetPacketParams + */ +void SX126xSetPacketType( RadioPacketTypes_t packetType ); + +/*! + * \brief Gets the current radio protocol + * + * \retval packetType [PACKET_TYPE_GFSK, PACKET_TYPE_LORA] + */ +RadioPacketTypes_t SX126xGetPacketType( void ); + +/*! + * \brief Sets the transmission parameters + * + * \param [in] power RF output power [-18..13] dBm + * \param [in] rampTime Transmission ramp up time + */ +void SX126xSetTxParams( int8_t power, uint8_t rampTime ); + +/*! + * \brief Set the modulation parameters + * + * \param [in] modParams A structure describing the modulation parameters + */ +void SX126xSetModulationParams( void *input_ptr ); + +/*! + * \brief Sets the packet parameters + * + * \param [in] packetParams A structure describing the packet parameters + */ +void SX126xSetPacketParams( void *packetParams ); + +/*! + * \brief Sets the Channel Activity Detection (CAD) parameters + * + * \param [in] cadSymbolNum The number of symbol to use for CAD operations + * [LORA_CAD_01_SYMBOL, LORA_CAD_02_SYMBOL, + * LORA_CAD_04_SYMBOL, LORA_CAD_08_SYMBOL, + * LORA_CAD_16_SYMBOL] + * \param [in] cadDetPeak Limit for detection of SNR peak used in the CAD + * \param [in] cadDetMin Set the minimum symbol recognition for CAD + * \param [in] cadExitMode Operation to be done at the end of CAD action + * [LORA_CAD_ONLY, LORA_CAD_RX, LORA_CAD_LBT] + * \param [in] cadTimeout Defines the timeout value to abort the CAD activity + */ +void SX126xSetCadParams( RadioLoRaCadSymbols_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, RadioCadExitModes_t cadExitMode, uint32_t cadTimeout ); + +/*! + * \brief Sets the data buffer base address for transmission and reception + * + * \param [in] txBaseAddress Transmission base address + * \param [in] rxBaseAddress Reception base address + */ +void SX126xSetBufferBaseAddress( uint8_t txBaseAddress, uint8_t rxBaseAddress ); + +/*! + * \brief Gets the current radio status + * + * \retval status Radio status + */ +uint8_t SX126xGetStatus( void ); + +/*! + * \brief Returns the instantaneous RSSI value for the last packet received + * + * \retval rssiInst Instantaneous RSSI + */ +int8_t SX126xGetRssiInst( void ); + +/*! + * \brief Gets the last received packet buffer status + * + * \param [out] payloadLength Last received packet payload length + * \param [out] rxStartBuffer Last received packet buffer address pointer + */ +void SX126xGetRxBufferStatus( uint8_t *payloadLength, uint8_t *rxStartBuffer ); + +/*! + * \brief Gets the last received packet payload length + * + * \param [out] pktStatus A structure of packet status + */ +void SX126xGetPacketStatus( void *pktStatus ); + +/*! + * \brief Returns the possible system errors + * + * \retval sysErrors Value representing the possible sys failures + */ +uint16_t SX126xGetDeviceErrors( void ); + +/*! + * \brief Clear all the errors in the device + */ +void SX126xClearDeviceErrors( void ); + +/*! + * \brief Clears the IRQs + * + * \param [in] irq IRQ(s) to be cleared + */ +void SX126xClearIrqStatus( uint16_t irq ); + +#endif // __SX126x_H__ diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/timer.cpp b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/timer.cpp new file mode 100644 index 00000000..96b22367 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/timer.cpp @@ -0,0 +1,29 @@ +#include +#include +#include "timer1.h" +unsigned int timer1_counter = 0; +uint32_t TickCounter = 0; + +void timer1_init(void) +{ + // Initializing timer1 + cli(); //disable global interrupt + TCCR1A = 0; //set TCCR1A to 0 + TCCR1B = 0; + + timer1_counter = 64911; + TCNT1 = timer1_counter; + + TCCR1B |= (1 << CS12); //256 frequency divider + + // enable overflow interrupt for timer + TIMSK1 = (1 << TOIE1); + //enable global interrupt + sei(); +} + +ISR(TIMER1_OVF_vect) +{ + TCNT1 = timer1_counter; + TickCounter++; +} \ No newline at end of file diff --git a/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/timer1.h b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/timer1.h new file mode 100644 index 00000000..d59c9193 --- /dev/null +++ b/Code/BITS/BITSv5/Arduino_code_for_sx1262_tcxo_module_DRF1262T_EN/Arduino-DRF1262T-TX/timer1.h @@ -0,0 +1,5 @@ +#ifndef _TIMER1_H_ +#define _TIMER1_H_ +void timer1_init(void); + +#endif diff --git a/Code/BITS/BITSv5/reference/getting-started-with-pico.pdf b/Code/BITS/BITSv5/reference/getting-started-with-pico.pdf new file mode 100644 index 00000000..dbf1f3f8 Binary files /dev/null and b/Code/BITS/BITSv5/reference/getting-started-with-pico.pdf differ diff --git a/Code/BITS/BITSv5/reference/raspberry-pi-pico-c-sdk.pdf b/Code/BITS/BITSv5/reference/raspberry-pi-pico-c-sdk.pdf new file mode 100644 index 00000000..58ac1238 Binary files /dev/null and b/Code/BITS/BITSv5/reference/raspberry-pi-pico-c-sdk.pdf differ