diff options
Diffstat (limited to 'peripheral/libupm/src/sx1276/sx1276.h')
-rw-r--r-- | peripheral/libupm/src/sx1276/sx1276.h | 2036 |
1 files changed, 2036 insertions, 0 deletions
diff --git a/peripheral/libupm/src/sx1276/sx1276.h b/peripheral/libupm/src/sx1276/sx1276.h new file mode 100644 index 0000000..e23a395 --- /dev/null +++ b/peripheral/libupm/src/sx1276/sx1276.h @@ -0,0 +1,2036 @@ +/* + * Author: Jon Trulson <jtrulson@ics.com> + * Copyright (c) 2015 Intel Corporation. + * + * Thanks to Semtech for their example code at: + * https://github.com/Lora-net/LoRaMac-node + * released under a modified BSD license, for many clues as to how to + * initialize and operate this radio properly. + * See src/sx1276/LICENSE.txt + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include <string> + +#include <sys/time.h> +#include <sys/select.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <pthread.h> + +#include <mraa/common.hpp> +#include <mraa/spi.hpp> +#include <mraa/gpio.hpp> + +// Our crystal oscillator frequency (32Mhz) +#define FXOSC_FREQ 32000000.0 + +// Our freq stepping resolution (in Hz) if FXOSC_FREQ is 32Mhz +// (FXOSC_FREQ / 2^19) = +#define FXOSC_STEP 61.03515625 + +namespace upm { + + /** + * @brief SX1276 LoRa/FSK modem + * @defgroup sx1276 libupm-sx1276 + * @ingroup spi gpio wifi + */ + + /** + * @library sx1276 + * @sensor sx1276 + * @comname SX1276 LoRa/FSK modem + * @altname SX1277 SX1278 SX1279 + * @type wifi + * @man semtech + * @con spi gpio + * @web http://www.digikey.com/product-search/en?vendor=0&keywords=SX1276MB1LAS + * + * @brief API for the SX1276 LoRa/FSK modem + * + * The SX1276 is a FSK/OOK/LoRa modem capable of both Low Frequency + * and High Frequency communication. + * + * It requires a 3.3v power supply, do not use 5v. + * + * Frequency Hopping Spread Spectrum (FHSS) is not currently supported. + * + * While not all of the functionality of this device is supported + * initially, methods and register definitions are provided that + * should allow an end user to implement whatever features are + * required. + * + * FSK send/receive example + * @snippet sx1276-fsk.cxx Interesting + * LORA send/receive example + * @snippet sx1276-lora.cxx Interesting + */ + + class SX1276 { + public: + + // The default chip revision + static const uint8_t chipRevision = 0x12; + + + // total FIFO size + static const int FIFO_SIZE = 256; + + // differentiator between high and low bands + static const int RF_MID_BAND_THRESH = 525000000; + + // LoRa RSSI offsets depending on LF or HF bands + static const int LOR_RSSI_OFFSET_HF = -157; + static const int LOR_RSSI_OFFSET_LF = -164; + + /** + * What modem we are configured for + */ + typedef enum { + MODEM_LORA = 0, + MODEM_FSK + } RADIO_MODEM_T; + + /** + * Events that can occurr during a TX or RX operation. + * + * When sending or receiving a packet (calling setTx()/send() or + * setRx()), the state will be initialized to ESTATE_EXEC to + * indicate the operation is in progress. Once an event has + * occurred, this state will be updated accordingly. + * + * For receiving, if RX_DONE is set, then it is safe to retrieve + * the rx buffer (via getRxBuffer()/getRxBufferStr()) as well as + * query the RSSI and SNR. On RX_ERROR, these values will be the + * same as they were last set during the last RX_DONE event. + */ + typedef enum { + REVENT_DONE = 0, // operation completed successfully + REVENT_EXEC, // runninsg something + REVENT_ERROR, // failed, crc error, sync timeout + REVENT_TIMEOUT // timed out + } RADIO_EVENT_T; + + /** + * SX1276 registers + * + * NOTE: reserved registers must not be written into or read from. + * Reserved bitfields must always be 0. + * + * This device has a set of "common" registers, as well as + * registers that represent different things depending on whether + * the device in in LoRa mode or FSK/OOK mode. So here, we will + * prefix the register names with COM (common), LOR (LoRa mode), + * and FSK (FSK/OOK mode) accordingly. + */ + typedef enum { + COM_RegFifo = 0x00, // FIFO r/w access + COM_RegOpMode = 0x01, // LoRa/FSK + + FSK_RegBitrateMsb = 0x02, + LOR_Reserved02 = 0x02, // reserved + + FSK_RegBitrateLsb = 0x03, + LOR_Reserved03 = 0x03, // reserved + + FSK_RegFdevMsb = 0x04, // freq deviation + LOR_Reserved04 = 0x04, // reserved + + FSK_RegFdevLsb = 0x05, + LOR_Reserved05 = 0x05, // reserved + + COM_RegFrfMsb = 0x06, // carrier freq + COM_RegFrfMid = 0x07, + COM_RegFrfLsb = 0x08, + COM_RegPaConfig = 0x09, + COM_RegPaRamp = 0x0a, + + COM_RegOcp = 0x0b, // overcurrent protection + COM_RegLna = 0x0c, + + FSK_RegRxConfig = 0x0d, + LOR_RegFifoAddrPtr = 0x0d, + + FSK_RegRssiConfg = 0x0e, + LOR_RegFifoTxBaseAddr = 0x0e, + + FSK_RegRssiCollision = 0x0f, + LOR_RegFifoRxBaseAddr = 0x0f, + + FSK_RegRssiThresh = 0x10, + LOR_RegFifoRxCurrentAddr = 0x10, + + FSK_RegRssiValue = 0x11, + LOR_RegIrqFlagsMask = 0x11, + + FSK_RegRxBw = 0x12, + LOR_RegIrqFlags = 0x12, + + FSK_RegAfcBw = 0x13, // automatic freq cntrl + LOR_RegRxNbBytes = 0x13, // received pkt len + + FSK_RegOokPeak = 0x14, + LOR_RegRxHeaderCntValueMsb = 0x14, + + FSK_RegOokFix = 0x15, + LOR_RegRxHeaderCntValueLsb = 0x15, + + FSK_RegOokAvg = 0x16, + LOR_RegRxPacketCntValueMsb = 0x16, + + FSK_Reserved17 = 0x17, // reserved + LOR_RegRxPacketCntValueLsb = 0x17, + + FSK_Reserved18 = 0x18, // reserved + LOR_RegModemStat = 0x18, + + FSK_Reserved19 = 0x19, // reserved + LOR_RegPktSnrValue = 0x19, + + FSK_RegAfcFei = 0x1a, + LOR_RegPktRssiValue = 0x1a, + + FSK_RegAfcMsb = 0x1b, + LOR_RegRssiValue = 0x1b, + + FSK_RegAfcLsb = 0x1c, + LOR_RegHopChannel = 0x1c, // fhss starting channel + + FSK_RegFeiMsb = 0x1d, + LOR_RegModemConfig1 = 0x1d, + + FSK_RegFeiLsb = 0x1e, + LOR_RegModemConfig2 = 0x1e, + + FSK_RegPreambleDetect = 0x1f, + LOR_RegSymbTimeoutLsb = 0x1f, + + FSK_RegRxTimeout1 = 0x20, + LOR_RegPreambleMsb = 0x20, + + FSK_RegRxTimeout2 = 0x21, + LOR_RegPreambleLsb = 0x21, + + FSK_RegRxTimeout3 = 0x22, + LOR_RegPayloadLength = 0x22, + + FSK_RegRxDelay = 0x23, + LOR_RegMaxPayloadLength = 0x23, + + FSK_RegOsc = 0x24, + LOR_RegHopPeriod = 0x24, + + FSK_RegPreambleMsb = 0x25, + LOR_RegFifoRxByteAddr = 0x25, + + FSK_RegPreambleLsb = 0x26, + LOR_RegModemConfig3 = 0x26, + + FSK_RegSyncConfig = 0x27, + LOR_Reserved27 = 0x27, // reserved + + FSK_RegSyncValue1 = 0x28, + LOR_RegFeiMsb = 0x28, + + FSK_RegSyncValue2 = 0x29, + LOR_RegFeiMid = 0x29, + + FSK_RegSyncValue3 = 0x2a, + LOR_RegFeiLsb = 0x2a, + + FSK_RegSyncValue4 = 0x2b, + LOR_Reserved2b = 0x2b, // reserved + + FSK_RegSyncValue5 = 0x2c, + LOR_RegRssiWideband = 0x2c, + + FSK_RegSyncValue6 = 0x2d, + LOR_Reserved2d = 0x2d, // reserved + + FSK_RegSyncValue7 = 0x2e, + LOR_Reserved2e = 0x2e, // reserved + + FSK_RegSyncValue8 = 0x2f, + LOR_Reserved2f = 0x2f, // reserved + + FSK_RegPacketConfig1 = 0x30, + LOR_Reserved30 = 0x30, // reserved + + FSK_RegPacketConfig2 = 0x31, + LOR_RegDetectOptimize = 0x31, + + FSK_RegPayloadLength = 0x32, + LOR_Reserved32 = 0x32, // reserved + + FSK_RegNodeAddr = 0x33, + LOR_RegInvertIQ = 0x33, + + FSK_RegBroadcastAddr = 0x34, + LOR_Reserved34 = 0x34, // reserved + + FSK_RegFifoThresh = 0x35, + LOR_Reserved35 = 0x35, // reserved + + FSK_RegSeqConfig1 = 0x36, + LOR_Reserved36 = 0x36, // reserved + + FSK_RegSeqConfig2 = 0x37, + LOR_RegDetectionThreshold = 0x37, + + FSK_RegTimerResol = 0x38, + LOR_Reserved38 = 0x38, // reserved + + FSK_RegTimer1Coeff = 0x39, + LOR_RegSyncWord = 0x39, + + FSK_RegTimer2Coeff = 0x3a, + LOR_Reserved3a = 0x3a, // reserved + + FSK_RegImageCal = 0x3b, + LOR_Reserved3b = 0x3b, // reserved (in datasheet)? + LOR_RegInvertIQ2 = 0x3b, // does not exist in datasheet + // but used in Semtech code. + // UNDOCUMENTED + + FSK_RegTemp = 0x3c, + LOR_Reserved3c = 0x3c, // reserved + + FSK_RegLowBat = 0x3d, + LOR_Reserved3d = 0x3d, // reserved + + FSK_RegIrqFlags1 = 0x3e, + LOR_Reserved3e = 0x3e, // reserved + + FSK_RegIrqFlags2 = 0x3f, + LOR_Reserved3f = 0x3f, // reserved + + COM_RegDioMapping1 = 0x40, // DIO0-DIO3 + COM_RegDioMapping2 = 0x41, // DIO4-DIO5, clk out freq + + COM_RegVersion = 0x42, // Semtech ID (silicon revision) + + // 0x43 reserved + + // The data sheet says this is FSK only, but the semtech code + // implies this is only valid for LoRa. So for now, assume the + // datasheet is wrong. + // + // FSK_RegPllHop = 0x44, + // LOR_Reserved44 = 0x44, // reserved + + FSK_Reserved44 = 0x44, + LOR_RegPllHop = 0x44, + + // 0x45-0x4a reserved + + COM_RegTcxo = 0x4b, + + // 0x4c reserved + + COM_RegPaDac = 0x4d, + + // 0x4e-0x5a reserved + + COM_RegFormerTemp = 0x5b, + + // 0x5c reserved + + FSK_RegBitRateFrac = 0x5d, + LOR_Reserved5d = 0x5d, // reserved + + // 0x5e-0x60 reserved + + COM_RegAgcRef = 0x61, + COM_RegAgcThresh1 = 0x62, + COM_RegAgcThresh2 = 0x63, + COM_RegAgcThresh3 = 0x64, + + // 0x65-0x6f reserved + + COM_RegPll = 0x70 + + // 0x71-0xff reserved + } SX1276_REGS_T; + + /** + * OpMode register (differing bitfields depending on mode) + */ + typedef enum { + OPMODE_Mode0 = 0x01, // operating modes (sleep, etc) + OPMODE_Mode1 = 0x02, + OPMODE_Mode2 = 0x04, + _OPMODE_Mode_MASK = 7, + _OPMODE_Mode_SHIFT = 0, + + OPMODE_LowFrequencyModeOn = 0x08, + + // 0x10 reserved + + OPMODE_FSK_ModulationType0 = 0x20, + OPMODE_FSK_ModulationType1 = 0x40, + _OPMODE_FSK_ModulationType_MASK = 3, + _OPMODE_FSK_ModulationType_SHIFT = 5, + + OPMODE_LOR_Reserved0x20 = 0x20, + + OPMODE_LOR_AccessSharedReg = 0x40, // tmp sw to FSK regs + + OPMODE_LongRangeMode = 0x80 // LoRa mode enable(1), else FSK + } OPMODE_BITS_T; + + + /** + * Mode values + */ + typedef enum { + MODE_Sleep = 0, + MODE_Standby = 1, + MODE_FSTX = 2, // freq synth + MODE_TxMode = 3, + MODE_FSRX = 4, // freq synth + + MODE_FSK_RxMode = 5, + MODE_LOR_RxContinuous = 5, // continuous rx mode + + MODE_FSK_Reserved6 = 6, + MODE_LOR_RxSingle = 6, // single packet rx mode + + MODE_FSK_Reserved7 = 7, + MODE_LOR_CAD = 7 // channel activity detection + } MODE_T; + + /** + * FSK_ModulationType values + */ + typedef enum { + MODULATION_FSK = 0, // freq shift keying + MODULATION_OOK = 1, // on/off keying + // 2-3 reserved + } FSK_MODULATION_TYPE_T; + + /** + * RegPaConfig register + */ + typedef enum { + PACONFIG_OutputPower0 = 0x01, + PACONFIG_OutputPower1 = 0x02, + PACONFIG_OutputPower2 = 0x04, + PACONFIG_OutputPower3 = 0x08, + _PACONFIG_OutputPower_MASK = 15, + _PACONFIG_OutputPower_SHIFT = 0, + + PACONFIG_MaxPower0 = 0x10, + PACONFIG_MaxPower1 = 0x20, + PACONFIG_MaxPower2 = 0x40, + _PACONFIG_MaxPower_MASK = 7, + _PACONFIG_MaxPower_SHIFT = 4, + + PACONFIG_PaSelect = 0x80 // PA output pin, + // 0 = 14dBm, 1 = 20dBm + } PACONFIG_BITS_T; + + /** + * RegPaRamp register + */ + typedef enum { + PARAMP_PaRamp0 = 0x01, // rise/fall of ramp up/down + PARAMP_PaRamp1 = 0x02, + PARAMP_PaRamp2 = 0x04, + PARAMP_PaRamp3 = 0x08, + _PARAMP_PaRamp_MASK = 15, + _PARAMP_PaRamp_SHIFT = 0, + + // 0x10 reserved + + // LORA 0x20-0x40 reserved + + PARAMP_FSK_ModulationShaping0 = 0x20, + PARAMP_FSK_ModulationShaping1 = 0x40, + _PARAMP_FSK_ModulationShaping_MASK = 3, + _PARAMP_FSK_ModulationShaping_SHIFT = 5 + + // 0x80 reserved + } PARAMP_BITS_T; + + /** + * PARAMP_PaRamp values + */ + typedef enum { + PARAMP_3_4MS = 0, // 3.4ms + PARAMP_2MS = 1, + PARAMP_1MS = 2, + PARAMP_500US = 3, // 500us + PARAMP_250US = 4, + PARAMP_125US = 5, + PARAMP_100US = 6, + PARAMP_62US = 7, + PARAMP_50US = 8, + PARAMP_40US = 9, + PARAMP_31US = 10, + PARAMP_25US = 11, + PARAMP_20US = 12, + PARAMP_15US = 13, + PARAMP_12US = 14, + PARAMP_10US = 15 + } PARAMP_T; + + /** + * PARAMP_ModulationShaping values. Note, these mean different + * things depending on whether you are using FSK or OOK. Hence + * the FSK/OOK dups. We will also name these as 'MODSHAPING_', rather + * than the lengthy 'MODULATIONSHAPING... ' + */ + typedef enum { + MODSHAPING_NOSHAPING = 0, + + // FSK + MODSHAPING_FSK_GaussianFilterBT1 = 1, // BT = 1.0 + MODSHAPING_FSK_GaussianFilterBT05 = 2, // BT = 0.5 + MODSHAPING_FSK_GaussianFilterBT03 = 3, // BT = 0.3 + + // OOK + MODSHAPING_OOK_FCutoffBitRate = 1, // Fcutoff = BitRate + MODSHAPING_OOK_FCutoffBitRate2 = 2 // Fcutoff = 2*BitRate + + // for OOK, 3 is reserved + } MODSHAPING_T; + + /** + * RegOcp register (see datasheet for OcpTrim values) + */ + typedef enum { + OCP_OcpTrim0 = 0x01, + OCP_OcpTrim1 = 0x02, + OCP_OcpTrim2 = 0x04, + OCP_OcpTrim3 = 0x08, + _OCP_OcpTrim_MASK = 15, + _OCP_OcpTrim_SHIFT = 0, + + OCP_OcpOn = 0x10 + + // 0x20-0x80 reserved + } OCP_BITS_T; + + /** + * Lna register + */ + typedef enum { + LNA_LnaBoostHf0 = 0x01, + LNA_LnaBoostHf1 = 0x02, + _LNA_LnaBoostHf_MASK = 3, + _LNA_LnaBoostHf_SHIFT = 0, + + // 0x04 reserved + + LNA_LnaBoostLf0 = 0x08, + LNA_LnaBoostLf1 = 0x10, + _LNA_LnaBoostLf_MASK = 3, + _LNA_LnaBoostLf_SHIFT = 3, + + LNA_LnaGain0 = 0x20, + LNA_LnaGain1 = 0x40, + LNA_LnaGain2 = 0x80, + _LNA_LnaGain_MASK = 7, + _LNA_LnaGain_SHIFT = 5 + } LNA_BITS_T; + + /** + * LnaBoostHf values + */ + typedef enum { + LNABOOSTHF_Default = 0, + // 1-2 reserved + LNABOOSTHF_BoostOn = 3, // 150% LNA current + } LNABOOSTHF_T; + + /** + * LnaBoostLf values + */ + typedef enum { + LNABOOSTLF_Default = 0 + // 1-3 reserved + } LNABOOSTLF_T; + + /** + * LnaGain values + */ + typedef enum { + // 0 reserved + LNAGAIN_G1 = 1, // max gain + LNAGAIN_G2 = 2, + LNAGAIN_G3 = 3, + LNAGAIN_G4 = 4, + LNAGAIN_G5 = 5, + LNAGAIN_G6 = 6 // minimum gain + // 7 reserved + } LNAGAIN_T; + + /** + * FSK_RxConfig register. See Table 24 in the data sheet for + * the meanings of the RxTrigger values. + */ + typedef enum { + RXCONFIG_RxTrigger0 = 0x01, + RXCONFIG_RxTrigger1 = 0x02, + RXCONFIG_RxTrigger2 = 0x04, + _RXCONFIG_RxTrigger_MASK = 7, + _RXCONFIG_RxTrigger_SHIFT = 0, + + RXCONFIG_AgcAutoOn = 0x08, + RXCONFIG_AfcAutoOn = 0x10, + RXCONFIG_RestartRxWithPllLock = 0x20, + RXCONFIG_RestartRxWithoutPllLock = 0x40, + RXCONFIG_RestartRxOnCollision = 0x80 + } RXCONFIG_BITS_T; + + /** + * FSK_RssiConfig register + */ + typedef enum { + RSSICONFIG_RssiSmoothing0 = 0x01, // RSSI sampling/averaging + RSSICONFIG_RssiSmoothing1 = 0x02, + RSSICONFIG_RssiSmoothing2 = 0x04, + _RSSICONFIG_RssiSmoothing_MASK = 7, + _RSSICONFIG_RssiSmoothing_SHIFT = 0, + + RSSICONFIG_RssiOffset0 = 0x08, // 2's complement offset + RSSICONFIG_RssiOffset1 = 0x10, + RSSICONFIG_RssiOffset2 = 0x20, + RSSICONFIG_RssiOffset3 = 0x40, + RSSICONFIG_RssiOffset4 = 0x80, + _RSSICONFIG_RssiOffset_MASK = 31, + _RSSICONFIG_RssiOffset_SHIFT = 3 + } RSSICONFIG_BITS_T; + + /** + * RssiSmoothing values + */ + typedef enum { + RSSISMOOTHING_2 = 0, // 2 samples used + RSSISMOOTHING_4 = 1, + RSSISMOOTHING_8 = 2, + RSSISMOOTHING_16 = 3, + RSSISMOOTHING_32 = 4, + RSSISMOOTHING_64 = 5, + RSSISMOOTHING_128 = 6, + RSSISMOOTHING_256 = 7 + } RSSISMOOTHING_T; + + /** + * LOR_RegIrqFlagsMask and LOR_RegIrqFlags registers + */ + typedef enum { + LOR_IRQFLAG_CadDetected = 0x01, + LOR_IRQFLAG_FhssChangeChannel = 0x02, + LOR_IRQFLAG_CadDone = 0x04, + LOR_IRQFLAG_TxDone = 0x08, + + LOR_IRQFLAG_ValidHeader = 0x10, + LOR_IRQFLAG_PayloadCrcError = 0x20, + LOR_IRQFLAG_RxDone = 0x40, + LOR_IRQFLAG_RxTimeout = 0x80 + } LOR_IRQFLAG_BITS_T; + + /** + * FSK_RxBw register and FSK_RegAfcBw registers + */ + typedef enum { + RXBW_RxBwExp0 = 0x01, + RXBW_RxBwExp1 = 0x02, + RXBW_RxBwExp2 = 0x04, + _RXBW_RxBwExp_MASK = 7, + _RXBW_RxBwExp_SHIFT = 0, + + RXBW_RxBwMant0 = 0x08, + RXBW_RxBwMant1 = 0x10, + _RXBW_RxBwMant_MASK = 3, + _RXBW_RxBwMant_SHIFT = 3, + // 0x20-0x80 reserved + } RXBW_BITS_T; + + /** + * RXBW_RxBwMant values + */ + typedef enum { + RXBWMANT_0 = 0, + RXBWMANT_1 = 1, + RXBWMANT_2 = 2 + // 3 reserved + } RXBWMANT_T; + + /** + * RXBW_RxBwExp values + */ + typedef enum { + RXBWEXP_1 = 1, + RXBWEXP_2 = 2, + RXBWEXP_3 = 3, + RXBWEXP_4 = 4, + RXBWEXP_5 = 5, + RXBWEXP_6 = 6, + RXBWEXP_7 = 7 + // other values reserved + } RXBWEXP_T; + + /** + * FSK_OokPeak register + */ + typedef enum { + OOKPEAK_OokPeakThreshStep0 = 0x01, + OOKPEAK_OokPeakThreshStep1 = 0x02, + OOKPEAK_OokPeakThreshStep2 = 0x04, + _OOKPEAK_OokPeakThreshStep_MASK = 7, + _OOKPEAK_OokPeakThreshStep_SHIFT = 0, + + OOKPEAK_OokThreshType0 = 0x08, + OOKPEAK_OokThreshType1 = 0x10, + _OOKPEAK_OokThreshType_MASK = 3, + _OOKPEAK_OokThreshType_SHIFT = 3, + + OOKPEAK_BitSyncOn = 0x20, + + // 0x40-0x80 reserved + } OOKPEAK_BITS_T; + + /** + * OokPeakThreshStep values + */ + typedef enum { + OOKPEAKTHRESHSTEP_05dB = 0, // dec of RSSI threshold 0.5dB + OOKPEAKTHRESHSTEP_1dB = 1, // 1 dB + OOKPEAKTHRESHSTEP_15dB = 2, // 1.5 dB + OOKPEAKTHRESHSTEP_2dB = 3, // 2 dB + OOKPEAKTHRESHSTEP_3dB = 4, + OOKPEAKTHRESHSTEP_4dB = 5, + OOKPEAKTHRESHSTEP_5dB = 6, + OOKPEAKTHRESHSTEP_6dB = 7 + } OOKPEAKTHRESHSTEP_T; + + /** + * OokPeakThreshType values + */ + typedef enum { + OOKTHRESHTYPE_FIXED = 0, + OOKTHRESHTYPE_PEAK = 1, + OOKTHRESHTYPE_AVERAGE = 2 + // 3 reserved + } OOKTHRESHTYPE_T; + + /** + * FSK_OokAvg register + */ + typedef enum { + OOKAVG_OokAvgThreshFilt0 = 0x01, + OOKAVG_OokAvgThreshFilt1 = 0x02, + _OOKAVG_OokAvgThreshFilt_MASK = 3, + _OOKAVG_OokAvgThreshFilt_SHIFT = 0, + + OOKAVG_OokAvgOffset0 = 0x04, + OOKAVG_OokAvgOffset1 = 0x08, + _OOKAVG_OokAvgOffset_MASK = 3, + _OOKAVG_OokAvgOffset_SHIFT = 2, + + // 0x10 reserved + + OOKAVG_OokPeakThreshDec0 = 0x20, + OOKAVG_OokPeakThreshDec1 = 0x40, + OOKAVG_OokPeakThreshDec2 = 0x80, + _OOKAVG_OokPeakThreshDec_MASK = 7, + _OOKAVG_OokPeakThreshDec_SHIFT = 5 + } OOKAVG_BITS_T; + + /** + * OokAvgThreshFilt values + */ + typedef enum { + OOKAVGTHRESHFILT_32 = 0, // filter coedd in avg mode + OOKAVGTHRESHFILT_8 = 1, + OOKAVGTHRESHFILT_4 = 2, + OOKAVGTHRESHFILT_2 = 3 + } OOKAVGTHRESHFILT_T; + + /** + * OokAvgOffset values + */ + typedef enum { + OOKAVGOFFSET_0 = 0, // 0.0dB + OOKAVGOFFSET_2 = 1, + OOKAVGOFFSET_4 = 2, + OOKAVGOFFSET_6 = 3 + } OOKAVGOFFSET_T; + + /** + * OokPeakThreshDec values + */ + typedef enum { + OOKPEAKTHRESHDEC_1_1 = 0, // once per chip + OOKPEAKTHRESHDEC_1_2 = 1, // once every 2 chips... + OOKPEAKTHRESHDEC_1_4 = 2, + OOKPEAKTHRESHDEC_1_8 = 3, + OOKPEAKTHRESHDEC_2_1 = 4, // twice per chip + OOKPEAKTHRESHDEC_4_1 = 5, // 4 times every chip... + OOKPEAKTHRESHDEC_8_1 = 6, + OOKPEAKTHRESHDEC_16_1 = 7 + } OOKPEAKTHRESHDEC_T; + + /** + * LOR_ModemStat register + */ + typedef enum { + MODEMSTAT_SignalDetected = 0x01, + MODEMSTAT_SignalSynchronized = 0x02, + MODEMSTAT_RxOngoing = 0x04, + MODEMSTAT_HeaderInfoValid = 0x08, + MODEMSTAT_ModemClear = 0x10, + + MODEMSTAT_RxCodingRate0 = 0x20, + MODEMSTAT_RxCodingRate1 = 0x40, + MODEMSTAT_RxCodingRate2 = 0x80, + _MODEMSTAT_RxCodingRate_MASK = 7, + _MODEMSTAT_RxCodingRate_SHIFT = 5 + } MODEMSTAT_BITS_T; + + /** + * FSK_RegAfcFei register + */ + typedef enum { + AFCFEI_AfcAutoClearOn = 0x01, + AFCFEI_AfcClear = 0x02, + + // 0x04-0x08 reserved + + AFCFEI_AgcStart = 0x10 + + // 0x20-0x80 reserved + } AFCFEI_BITS_T; + + /** + * LOR_HopChannel register + */ + typedef enum { + HOPCHANNEL_FhssPresentChannel0 = 0x01, // current freq hopping channel + HOPCHANNEL_FhssPresentChannel1 = 0x02, + HOPCHANNEL_FhssPresentChannel2 = 0x04, + HOPCHANNEL_FhssPresentChannel3 = 0x08, + HOPCHANNEL_FhssPresentChannel4 = 0x10, + HOPCHANNEL_FhssPresentChannel5 = 0x20, + _HOPCHANNEL_FhssPresentChannel_MASK = 63, + _HOPCHANNEL_FhssPresentChannel_SHIFT = 0, + + HOPCHANNEL_CrcOnPayload = 0x40, + HOPCHANNEL_PllTimeout = 0x80 + } HOPCHANNEL_BITS_T; + + /** + * LOR_ModemConfig1 register + */ + typedef enum { + MODEMCONFIG1_ImplicitHeaderModeOn = 0x01, + + MODEMCONFIG1_CodingRate0 = 0x02, + MODEMCONFIG1_CodingRate1 = 0x04, + MODEMCONFIG1_CodingRate2 = 0x08, + _MODEMCONFIG1_CodingRate_MASK = 7, + _MODEMCONFIG1_CodingRate_SHIFT = 0, + + MODEMCONFIG1_Bw0 = 0x10, + MODEMCONFIG1_Bw1 = 0x20, + MODEMCONFIG1_Bw2 = 0x40, + MODEMCONFIG1_Bw3 = 0x80, + _MODEMCONFIG1_Bw_MASK = 15, + _MODEMCONFIG1_Bw_SHIFT = 4 + } MODEMCONFIG1_BITS_T; + + /** + * CodingRate values + */ + typedef enum { + CODINGRATE_4_5 = 1, // Error coding rate 4/5 + CODINGRATE_4_6 = 2, + CODINGRATE_4_7 = 3, + CODINGRATE_4_8 = 4 + } CODINGRATE_T; + + /** + * Bw values + */ + typedef enum { + BW_7_8 = 0, // 7.8Khz + BW_10_4 = 1, + BW_15_6 = 2, + BW_20_8 = 3, + BW_31_25 = 4, + BW_41_7 = 5, + BW_62_5 = 6, + BW_125 = 7, + BW_250 = 8, + BW_500 = 9 + + // BW250 and BW500 not supported in lower band (169Mhz) + } BW_T; + + /** + * LOR_ModemConfig2 register + */ + typedef enum { + MODEMCONFIG2_SymbTimeoutMsb0 = 0x01, + MODEMCONFIG2_SymbTimeoutMsb1 = 0x02, + _MODEMCONFIG2_SymbTimeoutMsb_MASK = 3, + _MODEMCONFIG2_SymbTimeoutMsb_SHIFT = 0, + + MODEMCONFIG2_RxPayloadCrcOn = 0x04, + + MODEMCONFIG2_TxContinuousMode = 0x08, + + MODEMCONFIG2_SpreadingFactor0 = 0x10, + MODEMCONFIG2_SpreadingFactor1 = 0x20, + MODEMCONFIG2_SpreadingFactor2 = 0x40, + MODEMCONFIG2_SpreadingFactor3 = 0x80, + _MODEMCONFIG2_SpreadingFactor_MASK = 15, + _MODEMCONFIG2_SpreadingFactor_SHIFT = 4, + } MODEMCONFIG2_BITS_T; + + /** + * SpreadingFactor values (expressed as a base-2 logarithm) + */ + typedef enum { + SPREADINGFACTOR_64 = 6, // 64 chips/symbol + SPREADINGFACTOR_128 = 7, + SPREADINGFACTOR_256 = 8, + SPREADINGFACTOR_512 = 9, + SPREADINGFACTOR_1024 = 10, + SPREADINGFACTOR_2048 = 11, + SPREADINGFACTOR_4096 = 12 + + // other values reserved + } SPREADINGFACTOR_T; + + /** + * FSK_PreableDetect register + */ + typedef enum { + PREABLEDETECT_PreambleDetectorTol0 = 0x01, + PREABLEDETECT_PreambleDetectorTol1 = 0x02, + PREABLEDETECT_PreambleDetectorTol2 = 0x04, + PREABLEDETECT_PreambleDetectorTol3 = 0x08, + PREABLEDETECT_PreambleDetectorTol4 = 0x10, + _PREABLEDETECT_PreambleDetectorTol4_MASK = 31, + _PREABLEDETECT_PreambleDetectorTol4_SHIFT = 0, + + PREABLEDETECT_PreambleDetectorSize0 = 0x20, + PREABLEDETECT_PreambleDetectorSize1 = 0x40, + _PREABLEDETECT_PreambleDetectorSize_MASK = 3, + _PREABLEDETECT_PreambleDetectorSize_SHIFT = 5, + + PREABLEDETECT_PreambleDetectorOn = 0x80 + } PREAMBLEDETECT_BITS_T; + + /** + * PreambleDetectorSize values + */ + typedef enum { + PREAMBLEDETECTORSIZE_1 = 0, // 1 byte + PREAMBLEDETECTORSIZE_2 = 1, + PREAMBLEDETECTORSIZE_3 = 2 + + // other values reserved + } PREAMBLEDETECTORSIZE_T; + + /** + * FSK_Osc register + */ + typedef enum { + OSC_ClkOut0 = 0x01, // clk output freq + OSC_ClkOut1 = 0x02, + OSC_ClkOut2 = 0x04, + _OSC_ClkOut_MASK = 7, + _OSC_ClkOut_SHIFT = 0, + + OSC_RcCalStart = 0x08 + + // other bits reserved + } OSC_BITS_T; + + /** + * ClkOut values + */ + typedef enum { + CLKOUT_1 = 0, // FXOSC + CLKOUT_2 = 1, // FXOSC / 2 ... + CLKOUT_4 = 2, + CLKOUT_8 = 3, + CLKOUT_16 = 4, + CLKOUT_32 = 5, + CLKOUT_RC = 6, // RC, (automatically enabled) + CLKOUT_OFF = 7 // clkout off + } CLKOUT_T; + + /** + * LOR_ModemConfig3 register + */ + typedef enum { + // 0x01-0x02 reserved + + MODEMCONFIG3_AgcAutoOn = 0x04, + MODEMCONFIG3_LowDataRateOptimize = 0x08 // req. for SF11 and SF12 and + // BW125 + + // 0x10-0x80 reserved + } MODEMCONFIG3_BITS_T; + + /** + * FSK_SyncConfig register + */ + typedef enum { + SYNCCONFIG_SyncSize0 = 0x01, + SYNCCONFIG_SyncSize1 = 0x02, + SYNCCONFIG_SyncSize2 = 0x04, + _SYNCCONFIG_SyncSize_MASK = 7, + _SYNCCONFIG_SyncSize_SHIFT = 0, + + // 0x08 reserved + + SYNCCONFIG_SyncOn = 0x10, + SYNCCONFIG_PreamblePolarity = 0x20, + + SYNCCONFIG_AutoRestartMode0 = 0x40, + SYNCCONFIG_AutoRestartMode1 = 0x80, + _SYNCCONFIG_AutoRestartMode_MASK = 3, + _SYNCCONFIG_AutoRestartMode_SHIFT = 6, + } SYNCCONFIG_BITS_T; + + /** + * AutoRestartMode values + */ + typedef enum { + AUTORESTARTMODE_OFF = 0, + AUTORESTARTMODE_ON_NOPLL = 1, // don't wait for PLL resync + AUTORESTARTMODE_ON_PLL = 2 // wait for PLL resync + // other values reserved + } AUTORESTARTMODE_T; + + /** + * LOR_FeiMsb register (4 bit MSB of Fei value) + */ + typedef enum { + FEIMSB_FreqError0 = 0x01, + FEIMSB_FreqError1 = 0x02, + FEIMSB_FreqError2 = 0x04, + FEIMSB_FreqError3 = 0x08, + _FEIMSB_FreqError_MASK = 15, + _FEIMSB_FreqError_SHIFT = 0 + + // 0x10-0x80 reserved + } FEIMSB_BITS_T; + + /** + * FSK_PacketConfig1 register + */ + typedef enum { + PACKETCONFIG1_CrcWhiteningType = 0x01, + + PACKETCONFIG1_AddressFiltering0 = 0x02, + PACKETCONFIG1_AddressFiltering1 = 0x04, + _PACKETCONFIG1_AddressFiltering_MASK = 3, + _PACKETCONFIG1_AddressFiltering_SHIFT = 1, + + PACKETCONFIG1_CrcAutoClearOff = 0x08, + PACKETCONFIG1_CrcOn = 0x10, + + PACKETCONFIG1_DcFree0 = 0x20, + PACKETCONFIG1_DcFree1 = 0x40, + _PACKETCONFIG1_DcFree_MASK = 3, + _PACKETCONFIG1_DcFree_SHIFT = 5, + + PACKETCONFIG1_PacketFormat = 0x80 // fixed(0) or variable(1) + } PACKETCONFIG1_BITS_T; + + /** + * AddressFiltering values + */ + typedef enum { + ADDRESSFILTERING_NONE = 0, + ADDRESSFILTERING_NODE = 1, // must match node addr + ADDRESSFILTERING_NODE_BROADCAST = 2, // match node or broadcast + } ADDRESSFILTERING_T; + + /** + * DcFree values (DC-free encoding/decoding schemes) + */ + typedef enum { + DCFREE_NONE = 0, + DCFREE_MANCHESTER = 1, + DCFREE_WHITENING = 2 + // other values reserved + } DCFREE_T; + + /** + * FSK_PacketConfig2 register + */ + typedef enum { + PACKETCONFIG2_PayloadLengthMsb0 = 0x01, + PACKETCONFIG2_PayloadLengthMsb1 = 0x02, + PACKETCONFIG2_PayloadLengthMsb2 = 0x04, + _PACKETCONFIG2_PayloadLengthMsb_MASK = 7, + _PACKETCONFIG2_PayloadLengthMsb_SHIFT = 0, + + PACKETCONFIG2_BeaconOn = 0x08, + + // 0x10 reserved (linked to io-homecontrol compat mode (?)) + + PACKETCONFIG2_IoHomeOn = 0x20, + PACKETCONFIG2_DataMode = 0x40, // continuous(0), packet(1) + + // 0x80 reserved + } PACKETCONFIG2_BITS_T; + + /** + * LOR_DetectOptimize register + */ + typedef enum { + DETECTOPTIMIZE_DetectionOptimize0 = 0x01, + DETECTOPTIMIZE_DetectionOptimize1 = 0x02, + DETECTOPTIMIZE_DetectionOptimize2 = 0x04, + _DETECTOPTIMIZE_DetectionOptimize_MASK = 7, + _DETECTOPTIMIZE_DetectionOptimize_SHIFT = 0 + + // 0x08-0x80 reserved + } DETECTOPTIMIZE_BITS_T; + + /** + * DetectionOptimize values + */ + typedef enum { + DETECTIONOPTIMIZE_SF7_SF12 = 3, + DETECTIONOPTIMIZE_SF6 = 5 + + // other values reserved + } DETECTIONOPTIMIZE_T; + + /** + * LOR_InvertIQ register + */ + typedef enum { + INVERTIQ_InvertIQTxOff = 0x01, // invert LoRa I & Q signals + // UNDOCUMENTED + + // 0x01-0x20 reserved + + INVERTIQ_InvertIQRx = 0x40 // invert LoRa I & Q signals + + // 0x80 reserved + } INVERTIQ_BITS_T; + + /** + * FSK_FifoThresh register + */ + typedef enum { + FIFOTHRESH_FifoThreshold0 = 0x01, + FIFOTHRESH_FifoThreshold1 = 0x02, + FIFOTHRESH_FifoThreshold2 = 0x04, + FIFOTHRESH_FifoThreshold3 = 0x08, + FIFOTHRESH_FifoThreshold4 = 0x10, + FIFOTHRESH_FifoThreshold5 = 0x20, + _FIFOTHRESH_FifoThreshold_MASK = 63, + _FIFOTHRESH_FifoThreshold_SHIFT = 0, + + // 0x40 reserved + + FIFOTHRESH_TxStartCondition = 0x80 + } FIFOTHRESH_BITS_T; + + /** + * FSK_SeqConfig1 register + */ + typedef enum { + SEQCONFIG1_FromTransit = 0x01, + SEQCONFIG1_FromIdle = 0x02, + SEQCONFIG1_LowPowerSelection = 0x04, + + SEQCONFIG1_FromStart0 = 0x08, + SEQCONFIG1_FromStart1 = 0x10, + _SEQCONFIG1_FromStart_MASK = 3, + _SEQCONFIG1_FromStart_SHIFT = 3, + + SEQCONFIG1_IdleMode = 0x20, + SEQCONFIG1_SequencerStop = 0x40, + SEQCONFIG1_SequencerStart = 0x80 + } SEQCONFIG1_BITS_T; + + /** + * FromStart values + */ + typedef enum { + FROMSTART_ToLowPowerSelection = 0, + FROMSTART_ToReceiveState = 1, + FROMSTART_ToTransmitState = 2, + FROMSTART_ToTransmitStateOnFifoLevel = 3 + } FROMSTART_T; + + /** + * FSK_SeqConfig2 register + */ + typedef enum { + SEQCONFIG2_FromPacketReceived0 = 0x01, + SEQCONFIG2_FromPacketReceived1 = 0x02, + SEQCONFIG2_FromPacketReceived2 = 0x04, + _SEQCONFIG2_FromPacketReceived_MASK = 7, + _SEQCONFIG2_FromPacketReceived_SHIFT = 0, + + SEQCONFIG2_FromRxTimeout0 = 0x08, + SEQCONFIG2_FromRxTimeout1 = 0x10, + _SEQCONFIG2_FromRxTimeout_MASK = 3, + _SEQCONFIG2_FromRxTimeout_SHIFT = 3, + + SEQCONFIG2_FromReceive0 = 0x20, + SEQCONFIG2_FromReceive1 = 0x40, + SEQCONFIG2_FromReceive2 = 0x80, + _SEQCONFIG2_FromReceive_MASK = 3, + _SEQCONFIG2_FromReceive_SHIFT = 5 + } SEQCONFIG2_BITS_T; + + /** + * FromPacketReceived values + */ + typedef enum { + FROMPACKETRECEIVED_ToSequencerOff = 0, + FROMPACKETRECEIVED_ToTransmitStateOnFifoEmpty = 1, + FROMPACKETRECEIVED_ToLowPowerSelection = 2, + FROMPACKETRECEIVED_ToReceiveViaFS = 3, // if freq was changed + FROMPACKETRECEIVED_ToReceive = 4 // if freq was not changed + + // other values reserved + } FROMPACKETRECEIVED_T; + + /** + * FromRxTimeout values + */ + typedef enum { + FROMRXTIMEOUT_ToReceiveViaReceiveStart = 0, + FROMRXTIMEOUT_ToTransmitState = 1, + FROMRXTIMEOUT_ToLowPowerSelection = 2, + FROMRXTIMEOUT_ToSequencerOffState = 3 + } FROMRXTIMEOUT_T; + + /** + * FromReceive values + */ + typedef enum { + FROMRECEIVE_ToPcketReceived = 1, + FROMRECEIVE_ToLowPowerSelection = 2, + FROMRECEIVE_ToPacketReceived = 3, + FROMRECEIVE_ToSequencerOffOnRSSI = 4, // RSSI interrupt + FROMRECEIVE_ToSequencerOffOnSync = 5, // SyncAddr interrupt + FROMRECEIVE_ToSequencerOffOnPreambleDetect = 6, // PreambleDetect intr + // other values reserved + } FROMRECEIVE_T; + + /** + * FSK_TimerResol register + */ + typedef enum { + TIMERRESOL_Timer2Resolution0 = 0x01, + TIMERRESOL_Timer2Resolution1 = 0x02, + _TIMERRESOL_Timer2Resolution_MASK = 3, + _TIMERRESOL_Timer2Resolution_SHIFT = 0, + + TIMERRESOL_Timer1Resolution0 = 0x04, + TIMERRESOL_Timer1Resolution1 = 0x08, + _TIMERRESOL_Timer1Resolution_MASK = 3, + _TIMERRESOL_Timer1Resolution_SHIFT = 2 + + // 0x10-0x80 reserved + } TIMERRESOL_BITS_T; + + /** + * Timer1/Timer2Resolution values + */ + typedef enum { + TIMERRESOLUTION_DISABLED = 0, + TIMERRESOLUTION_64us = 1, // 64us + TIMERRESOLUTION_4_1ms = 2, // 4.1ms + TIMERRESOLUTION_262ms = 3 // 262ms + } TIMERRESOLUTION_T; + + /** + * FSK_ImageCal register + */ + typedef enum { + IMAGECAL_TempMonitorOff = 0x01, + + IMAGECAL_TempThreshold0 = 0x02, + IMAGECAL_TempThreshold1 = 0x04, + _IMAGECAL_TempThreshold_MASK = 3, + _IMAGECAL_TempThreshold_SHIFT = 1, + + IMAGECAL_TenpChange = 0x08, + + // 0x10 reserved + + IMAGECAL_ImageCalRunning = 0x20, + IMAGECAL_ImageCalStart = 0x40, + IMAGECAL_AutoImageCalOn = 0x80 + } IMAGECAL_BITS_T; + + /** + * TempThreshold values + */ + typedef enum { + TEMPTHRESHOLD_5C = 0, // temp change to trigger new I/Q + TEMPTHRESHOLD_10C = 1, // calibration + TEMPTHRESHOLD_15C = 2, + TEMPTHRESHOLD_20C = 3 + } TEMPTHRESHOLD_T; + + /** + * FSK_LowBat register + */ + typedef enum { + LOWBAT_LowBatTrim0 = 0x01, + LOWBAT_LowBatTrim1 = 0x02, + LOWBAT_LowBatTrim2 = 0x04, + _LOWBAT_LowBatTrim_MASK = 7, + _LOWBAT_LowBatTrim_SHIFT = 0, + + LOWBAT_LowBatOn = 0x08 + + // 0x10-0z80 reserved + } LOWBAT_BITS_T; + + /** + * LowBatTrim values + */ + typedef enum { + LOWBATTRIM_1_695 = 0, // 1.695v + LOWBATTRIM_1_764 = 1, + LOWBATTRIM_1_835 = 2, + LOWBATTRIM_1_905 = 3, + LOWBATTRIM_1_976 = 4, + LOWBATTRIM_2_045 = 5, + LOWBATTRIM_2_116 = 6, + LOWBATTRIM_2_185 = 7 + } LOWBATTRIM_T; + + /** + * FSK_IrqFlags1 register + */ + typedef enum { + IRQFLAGS1_SyncAddressMatch = 0x01, + IRQFLAGS1_PreambleDetect = 0x02, + IRQFLAGS1_Timeout = 0x04, + IRQFLAGS1_Rssi = 0x08, + IRQFLAGS1_PllLock = 0x10, + IRQFLAGS1_TxReady = 0x20, + IRQFLAGS1_RxReady = 0x40, + IRQFLAGS1_ModeReady = 0x80 + } IRQFLAGS1_BITS_T; + + /** + * FSK_IrqFlags2 register + */ + typedef enum { + IRQFLAGS2_LowBat = 0x01, + IRQFLAGS2_CrcOk = 0x02, + IRQFLAGS2_PayloadReady = 0x04, + IRQFLAGS2_PacketSent = 0x08, + IRQFLAGS2_FifoOverrun = 0x10, + IRQFLAGS2_FifoLevel = 0x20, + IRQFLAGS2_FifoEmpty = 0x40, + IRQFLAGS2_FifoFull = 0x80 + } IRQFLAGS2_BITS_T; + + /** + * COM_DioMapping1 register. See Tables 18, 29, and 30 in the + * datasheet for the different mappings depending on mode. + */ + typedef enum { + DOIMAPPING1_Dio3Mapping0 = 0x01, + DOIMAPPING1_Dio3Mapping1 = 0x02, + DOIMAPPING1_Dio3Mapping_MASK = 3, + DOIMAPPING1_Dio3Mapping_SHIFT = 0, + + DOIMAPPING1_Dio2Mapping0 = 0x04, + DOIMAPPING1_Dio2Mapping1 = 0x08, + DOIMAPPING1_Dio2Mapping_MASK = 3, + DOIMAPPING1_Dio2Mapping_SHIFT = 2, + + DOIMAPPING1_Dio1Mapping0 = 0x10, + DOIMAPPING1_Dio1Mapping1 = 0x20, + DOIMAPPING1_Dio1Mapping_MASK = 3, + DOIMAPPING1_Dio1Mapping_SHIFT = 4, + + DOIMAPPING1_Dio0Mapping0 = 0x40, + DOIMAPPING1_Dio0Mapping1 = 0x80, + DOIMAPPING1_Dio0Mapping_MASK = 3, + DOIMAPPING1_Dio0Mapping_SHIFT = 6, + } DIOMAPPING1_BITS_T; + + + /** + * COM_DioMapping2 register. See Tables 18, 29, and 30 in the + * datasheet for the different mappings depending on mode. + */ + typedef enum { + DOIMAPPING2_MapPreambleDetect = 0x01, // rssi intr(0), preambledet(1) + + // 0x02-0x08 reserved + + DOIMAPPING2_Dio5Mapping0 = 0x10, + DOIMAPPING2_Dio5Mapping1 = 0x20, + DOIMAPPING2_Dio5Mapping_MASK = 3, + DOIMAPPING2_Dio5Mapping_SHIFT = 4, + + DOIMAPPING2_Dio4Mapping0 = 0x40, + DOIMAPPING2_Dio4Mapping1 = 0x80, + DOIMAPPING2_Dio4Mapping_MASK = 3, + DOIMAPPING2_Dio4Mapping_SHIFT = 6, + } DIOMAPPING2_BITS_T; + + /** + * DioXMapping values + * + * These differ depending on LoRa, FSK packet, and FSK continous + * modes. See Tables 29, 30 (FSK), and 18 (LoRa) in the datasheet + * for details. + */ + typedef enum { + DIOMAPPING_00 = 0, + DIOMAPPING_01 = 1, + DIOMAPPING_10 = 2, + DIOMAPPING_11 = 3 + } DIOMAPPING_T; + + + /** + * LOR_PllHop (or FSK_PllHop depending on who you believe) register + */ + typedef enum { + // 0x01-0x40 reserved + + PLLHOP_FastHopOn = 0x80 + } PLLHOP_BITS_T; + + /** + * COM_Tcxo register + */ + typedef enum { + // 0x01-0x08 reserved + + TCXO_TcxoOn = 0x10 + + // 0x20-0x80 reserved + } TCXO_BITS_T; + + /** + * COM_PaDac register + */ + typedef enum { + PADAC_PaDac0 = 0x01, + PADAC_PaDac1 = 0x02, + PADAC_PaDac2 = 0x04, + _PADAC_PaDac_MASK = 7, + _PADAC_PaDac_SHIFT = 0 + + // 0x08-0x80 reserved + } PADAC_BITS_T; + + /** + * PaDac values + */ + typedef enum { + PADAC_DEFAULT = 4, + PADAC_BOOST = 7 // +20dBm on PA_BOOST when + // OuputPower = 1111 + // other values reserved + } PADAC_T; + + /** + * FSK_BitRateFrac register + */ + typedef enum { + BITRATEFRAC_BitRateFrac0 = 0x01, + BITRATEFRAC_BitRateFrac1 = 0x02, + BITRATEFRAC_BitRateFrac2 = 0x04, + BITRATEFRAC_BitRateFrac3 = 0x08, + _BITRATEFRAC_BitRateFrac_MASK = 15, + _BITRATEFRAC_BitRateFrac_SHIFT = 0 + + // 0x10-0x80 reserved + } BITRATEFRAC_BITS_T; + + /** + * COM_AgcRef register + * + * These registers have 2 sets of values depending on whether + * LowFrequencyModeOn is set or unset. + */ + typedef enum { + AGCREF_AgcReferenceLevel0 = 0x01, + AGCREF_AgcReferenceLevel1 = 0x02, + AGCREF_AgcReferenceLevel2 = 0x04, + AGCREF_AgcReferenceLevel3 = 0x08, + AGCREF_AgcReferenceLevel4 = 0x10, + AGCREF_AgcReferenceLevel5 = 0x20, + _AGCREF_AgcReferenceLevel_MASK = 63, + _AGCREF_AgcReferenceLevel_SHIFT = 0 + + // 0x40-0x80 reserved + } ACFREF_BITS_T; + + /** + * COM_AgcThresh1 register + * + * These registers have 2 sets of values depending on whether + * LowFrequencyModeOn is set or unset. + */ + typedef enum { + AGCTHRESH1_AcgStep10 = 0x01, + AGCTHRESH1_AcgStep11 = 0x02, + AGCTHRESH1_AcgStep12 = 0x04, + AGCTHRESH1_AcgStep13 = 0x08, + _AGCTHRESH1_AcgStep1_MASK = 15, + _AGCTHRESH1_AcgStep1_SHIFT = 0, + + // 0x10-0x80 reserved + } ACGTHRESH1_BITS_T; + + /** + * COM_AgcThresh2 register + * + * These registers have 2 sets of values depending on whether + * LowFrequencyModeOn is set or unset. + */ + typedef enum { + AGCTHRESH2_AcgStep30 = 0x01, + AGCTHRESH2_AcgStep31 = 0x02, + AGCTHRESH2_AcgStep32 = 0x04, + AGCTHRESH2_AcgStep33 = 0x08, + _AGCTHRESH2_AcgStep3_MASK = 15, + _AGCTHRESH2_AcgStep3_SHIFT = 0, + + AGCTHRESH2_AcgStep20 = 0x10, + AGCTHRESH2_AcgStep21 = 0x20, + AGCTHRESH2_AcgStep22 = 0x40, + AGCTHRESH2_AcgStep23 = 0x80, + _AGCTHRESH2_AcgStep2_MASK = 15, + _AGCTHRESH2_AcgStep2_SHIFT = 4 + } ACGTHRESH2_BITS_T; + + /** + * LOR_RegDetectionThreshold values + */ + typedef enum { + LOR_DetectionThreshold_SF7_SF12 = 0x0a, + LOR_DetectionThreshold_SF6 = 0x0c + } LOR_DETECTIONTHRESHOLD_T; + + /** + * COM_AgcThresh3 register + * + * These registers have 2 sets of values depending on whether + * LowFrequencyModeOn is set or unset. + */ + typedef enum { + AGCTHRESH3_AcgStep50 = 0x01, + AGCTHRESH3_AcgStep51 = 0x02, + AGCTHRESH3_AcgStep52 = 0x04, + AGCTHRESH3_AcgStep53 = 0x08, + _AGCTHRESH3_AcgStep5_MASK = 15, + _AGCTHRESH3_AcgStep5_SHIFT = 0, + + AGCTHRESH3_AcgStep40 = 0x10, + AGCTHRESH3_AcgStep41 = 0x20, + AGCTHRESH3_AcgStep42 = 0x40, + AGCTHRESH3_AcgStep43 = 0x80, + _AGCTHRESH3_AcgStep4_MASK = 15, + _AGCTHRESH3_AcgStep4_SHIFT = 4 + } ACGTHRESH3_BITS_T; + + + /** + * SX1276 constructor + * + * Since this is a shield, you will not have much choice as to + * what pins are used. + * + * @param chipRev chip revision, default is 0x12 + * @param bus spi bus to use + * @param cs GPIO pin to use as SPI Chip Select + * @param reset GPIO pin to use as reset (A0=GPIO14) + * @param dio0 GPIO pin to use as reset DIO0 intr + * @param dio1 GPIO pin to use as reset DIO1 intr + * @param dio2 GPIO pin to use as reset DIO2 intr + * @param dio3 GPIO pin to use as reset DIO3 intr + * @param dio4 GPIO pin to use as reset DIO4 intr + * @param dio5 GPIO pin to use as reset DIO5 intr + */ + SX1276(uint8_t chipRev=chipRevision, int bus=1, int cs=10, int resetPin=14, + int dio0=2, int dio1=3, int dio2=4, int dio3=5, int dio4=17, + int dio5=9); + + /** + * SX1276 Destructor + */ + ~SX1276(); + + /** + * read a register + * + * @param reg the register to read + * @return the value of the register + */ + uint8_t readReg(uint8_t reg); + + /** + * write to a register + * + * @param reg the register to write to + * @param val the value to write + * @return true if successful, false otherwise + */ + bool writeReg(uint8_t reg, uint8_t val); + + /** + * return the chip revision + * + * @return the chip revision (usually 0x12) + */ + uint8_t getChipVersion(); + + /** + * reset the modem + */ + void reset(); + + /** + * read the FIFO into a buffer + * + * @param buffer The buffer to read data into + * @param len The length of the buffer + */ + void readFifo(uint8_t *buffer, int len); + + /** + * write a buffer into the FIFO + * + * @param buffer The buffer containing the data to write + * @param len The length of the buffer + */ + void writeFifo(uint8_t *buffer, int len); + + /** + * Set the frequency to transmit and receive on + * + * @param freq The frequency to set + */ + void setChannel(uint32_t freq); + + /** + * Set the operating mode + * + * @param opMode One of the MODE_T values + */ + void setOpMode(MODE_T opMode); + + /** + * Set the modem to access. This can be either the LORA or + * KSK/OOK modem. + * + * @param modem One of the MODEM_T values + */ + void setModem(RADIO_MODEM_T modem); + + /** + * Place the SX1276 into sleep mode + */ + void setSleep(); + + /** + * Place the SX1276 into standby mode + */ + void setStandby(); + + /** + * Return the current Received Signal Strength Indicator for the + * given modem + * + * @param modem One of the MODEM_T values + */ + int16_t getRSSI(RADIO_MODEM_T modem); + + /** + * Check to see if a given channel is free by comparing the RSSI + * to the supplied threshold. + * + * @param modem One of the MODEM_T values + * @param freq The channel to check + * @param rssiThreshold The RSSI threshold, over which the channel + * os considerd in use. + */ + bool isChannelFree(RADIO_MODEM_T modem, uint32_t freq, int16_t rssiThresh); + + /** + * Send the supplied string. This writes the string into the FIFO + * and places the modem in transmit mode (via setTx()). This is a + * wrapper around send(). + * + * @param buffer The buffer to send + * @param timeout The timeout in milliseconds + * @return one of the RADIO_EVENT_T values + */ + RADIO_EVENT_T sendStr(std::string buffer, int timeout); + + /** + * Send the supplied buffer. The writes the buffer into the FIFO + * and places the modem in transmit mode (via setTx()). + * + * @param buffer The buffer to send + * @param size The size of the buffer + * @param timeout The timeout in milliseconds + * @return one of the RADIO_EVENT_T values + */ + RADIO_EVENT_T send(uint8_t *buffer, uint8_t size, int timeout); + + /** + * Set the receive configuration for a modem. It is important + * that both the receive and transmit configurations match in order + * for communication to work between two radios. + * + * @param modem One of the MODEM_T values + + * @param bandwidth The bandwidth to use. Valid values are + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [125 kHz, 250 kHz, 500 kHz] + * @param 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 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 bandwidthAfc Sets the AFC Bandwidth (FSK only) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * @param preambleLen Sets the Preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds + * 4 more symbols) + * @param symbTimeout Sets the RxSingle timeout value (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: timeout in symbols + * @param fixLen Fixed length packets [false: variable, true: fixed] + * @param payloadLen Sets payload length when fixed lenght is used + * @param crcOn Enables/Disables the CRC [false: OFF, true: ON] + * @param FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [false: OFF, true: ON] + * @param HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * @param iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [false: not inverted, true: inverted] + * @param rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ + void setRxConfig(RADIO_MODEM_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); + + /** + * Set the transmit configuration for a modem. It is important + * that both the receive and transmit configurations match in order + * for communication to work between two radios. + * + * @param modem One of the MODEM_T values + * @param power Sets the output power [dBm] + * @param fdev Sets the frequency deviation (FSK only) + * FSK : [Hz] + * LoRa: 0 + * @param bandwidth Sets the bandwidth (LoRa only) + * FSK : 0 + * LoRa: [125 kHz, 250 kHz, + * or 500 kHz] + * @param 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 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 preambleLen Sets the preamble length + * FSK : Number of bytes + * LoRa: Length in symbols (the hardware adds + * 4 more symbols) + * @param fixLen Fixed length packets [false: variable, true: fixed] + * @param crcOn Enables disables the CRC [false: OFF, true: ON] + * @param FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [false: OFF, true: ON] + * @param HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols + * @param iqInverted Inverts IQ signals (LoRa only) + * FSK : N/A ( set to 0 ) + * LoRa: [false: not inverted, true: inverted] + */ + void setTxConfig(RADIO_MODEM_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); + + /** + * Start a receive operation. The method will return when + * completed, either successfully, or in error (crc, or other + * issue). If completed successfully, the returned buffer can be + * read via getRxBuffer() or getRxBufferStr(). In addition, + * values for RSSI and SNR (Lora only) can be retrieved. + * + * @param timeout The timeout in milliseconds + * @return one of the RADIO_EVENT_T values + */ + RADIO_EVENT_T setRx(uint32_t timeout); + + /** + * Upon a successful receive, this method can be used to retrieve + * the received packet. + * + * @return The received buffer in a std::string + */ + std::string getRxBufferStr() + { + std::string rBuffer((char *)m_rxBuffer, getRxLen()); + return rBuffer; + }; + + /** + * Upon a successful receive, this method can be used to retrieve + * the received packet. + * + * @return a pointer to the received buffer. You can use + * getRxLen() to determine the number of valid bytes present. + */ + uint8_t *getRxBuffer() + { + return (uint8_t*)m_rxBuffer; + }; + + /** + * Upon a successful receive, this method can be used to retrieve + * the received packet's Received Signal Strength Indicator (RSSI) + * value. + * + * @return RSSI value + */ + int getRxRSSI() + { + return m_rxRSSI; + }; + + /** + * Upon a successful receive, this method can be used to retrieve + * the received packet's Signal to Noise (SNR) value. + * + * @return SNR value + */ + int getRxSNR() + { + return m_rxSNR; + }; + + /** + * Upon a successful receive, this method can be used to retrieve + * the number of bytes received. + * + * @return the number of bytes received + */ + int getRxLen() + { + return m_rxLen; + }; + + + protected: + // I/O + mraa::Spi m_spi; + mraa::Gpio m_gpioCS; + mraa::Gpio m_gpioReset; + + mraa::Gpio m_gpioDIO0; + mraa::Gpio m_gpioDIO1; + mraa::Gpio m_gpioDIO2; + mraa::Gpio m_gpioDIO3; + mraa::Gpio m_gpioDIO4; + mraa::Gpio m_gpioDIO5; + + // calibration called during init() + void rxChainCalibration(); + + // interrupt handlers + static void onDio0Irq(void *ctx); + static void onDio1Irq(void *ctx); + static void onDio2Irq(void *ctx); + static void onDio3Irq(void *ctx); + static void onDio4Irq(void *ctx); + static void onDio5Irq(void *ctx); + + /** + * What internal state are we in + */ + typedef enum { + STATE_IDLE = 0, + STATE_RX_RUNNING, + STATE_TX_RUNNING, + STATE_CAD + } RADIO_STATES_T; + + // needs to be OR'd onto registers for SPI write + static const uint8_t m_writeMode = 0x80; + + // initialize the chip + void init(); + + // Start a transmit event (you should use send() or sendStr() + // rather than call this function directly. + RADIO_EVENT_T setTx(int timeout); + + void startCAD(); // non-functional/non-tested + + // not really used, maybe it should be + void setMaxPayloadLength(RADIO_MODEM_T modem, uint8_t max); + + // Chip Select control (active LOW) + void csOn() + { + m_gpioCS.write(0); + }; + + void csOff() + { + m_gpioCS.write(1); + }; + + private: + // Thse structs will generate SWIG warnings, as we do not expose + // this data, they can be ignored. + + // stored settings for the FSK modem + typedef struct + { + int8_t Power; + uint32_t Fdev; + uint32_t Bandwidth; + uint32_t BandwidthAfc; + uint32_t Datarate; + uint16_t PreambleLen; + bool FixLen; + uint8_t PayloadLen; + bool CrcOn; + bool IqInverted; + bool RxContinuous; + } radioFskSettings_t; + + // stored settings for the LoRa modem + typedef struct + { + int8_t Power; + uint32_t Bandwidth; + uint32_t Datarate; + bool LowDatarateOptimize; + uint8_t Coderate; + uint16_t PreambleLen; + bool FixLen; + uint8_t PayloadLen; + bool CrcOn; + bool FreqHopOn; + uint8_t HopPeriod; + bool IqInverted; + bool RxContinuous; + } radioLoRaSettings_t; + + // FSK packet handler state + typedef struct + { + uint8_t PreambleDetected; + uint8_t SyncWordDetected; + int8_t RssiValue; + int32_t AfcValue; + uint8_t RxGain; + uint16_t Size; + uint16_t NbBytes; + uint8_t FifoThresh; + uint8_t ChunkSize; + } radioFskPacketHandler_t; + + // LoRa packet handler state + typedef struct + { + int8_t SnrValue; + int16_t RssiValue; + uint8_t Size; + } radioLoRaPacketHandler_t; + + // our radio settings + struct { + RADIO_MODEM_T modem; + volatile RADIO_STATES_T state; + uint32_t channel; + + radioFskSettings_t fskSettings; + volatile radioFskPacketHandler_t fskPacketHandler; + + radioLoRaSettings_t loraSettings; + volatile radioLoRaPacketHandler_t loraPacketHandler; + } m_settings; + + uint8_t lookupFSKBandWidth(uint32_t bw); + + // received data (on successfull completion) + volatile int m_rxRSSI; + volatile int m_rxSNR; + volatile int m_rxLen; + uint8_t m_rxBuffer[FIFO_SIZE]; + + // for coordinating interrupt access + pthread_mutex_t m_intrLock; + + void lockIntrs() { pthread_mutex_lock(&m_intrLock); }; + void unlockIntrs() { pthread_mutex_unlock(&m_intrLock); }; + + // current radio event status + volatile RADIO_EVENT_T m_radioEvent; + + // timer support + struct timeval m_startTime; + void initClock(); + uint32_t getMillis(); + }; +} + + |