Driver for SX1272 connected to Pulga devices using only DIO0 pins and polling (error states and timeout).
Dependents: pulga-mbed-lorawan-gps mbed-lorawan-pulga mbed-lorawan-pulga-testing-channel mbed-lorawan-pulga-serial_rx ... more
SX1276/SX1276_LoRaRadio.cpp@0:561d07a737bc, 2020-11-12 (annotated)
- Committer:
- brunnobbco
- Date:
- Thu Nov 12 19:26:24 2020 +0000
- Revision:
- 0:561d07a737bc
SX1272 driver using only DIO0 and polling.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
brunnobbco | 0:561d07a737bc | 1 | /** |
brunnobbco | 0:561d07a737bc | 2 | / _____) _ | | |
brunnobbco | 0:561d07a737bc | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ |
brunnobbco | 0:561d07a737bc | 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ |
brunnobbco | 0:561d07a737bc | 5 | _____) ) ____| | | || |_| ____( (___| | | | |
brunnobbco | 0:561d07a737bc | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| |
brunnobbco | 0:561d07a737bc | 7 | (C)2013 Semtech |
brunnobbco | 0:561d07a737bc | 8 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ |
brunnobbco | 0:561d07a737bc | 9 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| |
brunnobbco | 0:561d07a737bc | 10 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| |
brunnobbco | 0:561d07a737bc | 11 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| |
brunnobbco | 0:561d07a737bc | 12 | embedded.connectivity.solutions=============== |
brunnobbco | 0:561d07a737bc | 13 | |
brunnobbco | 0:561d07a737bc | 14 | Description: LoRaWAN stack layer that controls both MAC and PHY underneath |
brunnobbco | 0:561d07a737bc | 15 | |
brunnobbco | 0:561d07a737bc | 16 | License: Revised BSD License, see LICENSE.TXT file include in the project |
brunnobbco | 0:561d07a737bc | 17 | |
brunnobbco | 0:561d07a737bc | 18 | Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE ) |
brunnobbco | 0:561d07a737bc | 19 | |
brunnobbco | 0:561d07a737bc | 20 | Copyright (c) 2017, Arm Limited and affiliates. |
brunnobbco | 0:561d07a737bc | 21 | |
brunnobbco | 0:561d07a737bc | 22 | SPDX-License-Identifier: BSD-3-Clause |
brunnobbco | 0:561d07a737bc | 23 | */ |
brunnobbco | 0:561d07a737bc | 24 | |
brunnobbco | 0:561d07a737bc | 25 | #include <stdio.h> |
brunnobbco | 0:561d07a737bc | 26 | #include <math.h> //rint |
brunnobbco | 0:561d07a737bc | 27 | #include <string.h> |
brunnobbco | 0:561d07a737bc | 28 | #include "PinNames.h" |
brunnobbco | 0:561d07a737bc | 29 | #include "Callback.h" |
brunnobbco | 0:561d07a737bc | 30 | #include "mbed_wait_api.h" |
brunnobbco | 0:561d07a737bc | 31 | #include "Timer.h" |
brunnobbco | 0:561d07a737bc | 32 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 33 | #include "ThisThread.h" |
brunnobbco | 0:561d07a737bc | 34 | using namespace rtos; |
brunnobbco | 0:561d07a737bc | 35 | #endif |
brunnobbco | 0:561d07a737bc | 36 | #include "SX1276_LoRaRadio.h" |
brunnobbco | 0:561d07a737bc | 37 | #include "sx1276Regs-Fsk.h" |
brunnobbco | 0:561d07a737bc | 38 | #include "sx1276Regs-LoRa.h" |
brunnobbco | 0:561d07a737bc | 39 | |
brunnobbco | 0:561d07a737bc | 40 | /*! |
brunnobbco | 0:561d07a737bc | 41 | * Sync word for Private LoRa networks |
brunnobbco | 0:561d07a737bc | 42 | */ |
brunnobbco | 0:561d07a737bc | 43 | #define LORA_MAC_PRIVATE_SYNCWORD 0x12 |
brunnobbco | 0:561d07a737bc | 44 | |
brunnobbco | 0:561d07a737bc | 45 | /*! |
brunnobbco | 0:561d07a737bc | 46 | * Sync word for Public LoRa networks |
brunnobbco | 0:561d07a737bc | 47 | */ |
brunnobbco | 0:561d07a737bc | 48 | #define LORA_MAC_PUBLIC_SYNCWORD 0x34 |
brunnobbco | 0:561d07a737bc | 49 | |
brunnobbco | 0:561d07a737bc | 50 | /*! |
brunnobbco | 0:561d07a737bc | 51 | * SX1276 definitions |
brunnobbco | 0:561d07a737bc | 52 | */ |
brunnobbco | 0:561d07a737bc | 53 | #define XTAL_FREQ 32000000 |
brunnobbco | 0:561d07a737bc | 54 | #define FREQ_STEP 61.03515625 |
brunnobbco | 0:561d07a737bc | 55 | |
brunnobbco | 0:561d07a737bc | 56 | /*! |
brunnobbco | 0:561d07a737bc | 57 | * Constant values need to compute the RSSI value |
brunnobbco | 0:561d07a737bc | 58 | */ |
brunnobbco | 0:561d07a737bc | 59 | #define RSSI_OFFSET_LF -164.0 |
brunnobbco | 0:561d07a737bc | 60 | #define RSSI_OFFSET_HF -157.0 |
brunnobbco | 0:561d07a737bc | 61 | #define RF_MID_BAND_THRESH 525000000 |
brunnobbco | 0:561d07a737bc | 62 | |
brunnobbco | 0:561d07a737bc | 63 | |
brunnobbco | 0:561d07a737bc | 64 | /*! |
brunnobbco | 0:561d07a737bc | 65 | * FSK bandwidth definition |
brunnobbco | 0:561d07a737bc | 66 | */ |
brunnobbco | 0:561d07a737bc | 67 | typedef struct |
brunnobbco | 0:561d07a737bc | 68 | { |
brunnobbco | 0:561d07a737bc | 69 | uint32_t bandwidth; |
brunnobbco | 0:561d07a737bc | 70 | uint8_t register_value; |
brunnobbco | 0:561d07a737bc | 71 | } fsk_bw_t; |
brunnobbco | 0:561d07a737bc | 72 | |
brunnobbco | 0:561d07a737bc | 73 | /*! |
brunnobbco | 0:561d07a737bc | 74 | * Radio registers definition |
brunnobbco | 0:561d07a737bc | 75 | */ |
brunnobbco | 0:561d07a737bc | 76 | typedef struct |
brunnobbco | 0:561d07a737bc | 77 | { |
brunnobbco | 0:561d07a737bc | 78 | uint8_t modem; |
brunnobbco | 0:561d07a737bc | 79 | uint8_t addr; |
brunnobbco | 0:561d07a737bc | 80 | uint8_t value; |
brunnobbco | 0:561d07a737bc | 81 | } radio_registers_t; |
brunnobbco | 0:561d07a737bc | 82 | |
brunnobbco | 0:561d07a737bc | 83 | #define RADIO_INIT_REGISTERS_VALUE \ |
brunnobbco | 0:561d07a737bc | 84 | { \ |
brunnobbco | 0:561d07a737bc | 85 | { MODEM_FSK , REG_LNA , 0x23 },\ |
brunnobbco | 0:561d07a737bc | 86 | { MODEM_FSK , REG_RXCONFIG , 0x1E },\ |
brunnobbco | 0:561d07a737bc | 87 | { MODEM_FSK , REG_RSSICONFIG , 0xD2 },\ |
brunnobbco | 0:561d07a737bc | 88 | { MODEM_FSK , REG_AFCFEI , 0x01 },\ |
brunnobbco | 0:561d07a737bc | 89 | { MODEM_FSK , REG_PREAMBLEDETECT , 0xAA },\ |
brunnobbco | 0:561d07a737bc | 90 | { MODEM_FSK , REG_OSC , 0x07 },\ |
brunnobbco | 0:561d07a737bc | 91 | { MODEM_FSK , REG_SYNCCONFIG , 0x12 },\ |
brunnobbco | 0:561d07a737bc | 92 | { MODEM_FSK , REG_SYNCVALUE1 , 0xC1 },\ |
brunnobbco | 0:561d07a737bc | 93 | { MODEM_FSK , REG_SYNCVALUE2 , 0x94 },\ |
brunnobbco | 0:561d07a737bc | 94 | { MODEM_FSK , REG_SYNCVALUE3 , 0xC1 },\ |
brunnobbco | 0:561d07a737bc | 95 | { MODEM_FSK , REG_PACKETCONFIG1 , 0xD8 },\ |
brunnobbco | 0:561d07a737bc | 96 | { MODEM_FSK , REG_FIFOTHRESH , 0x8F },\ |
brunnobbco | 0:561d07a737bc | 97 | { MODEM_FSK , REG_IMAGECAL , 0x02 },\ |
brunnobbco | 0:561d07a737bc | 98 | { MODEM_FSK , REG_DIOMAPPING1 , 0x00 },\ |
brunnobbco | 0:561d07a737bc | 99 | { MODEM_FSK , REG_DIOMAPPING2 , 0x30 },\ |
brunnobbco | 0:561d07a737bc | 100 | { MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 },\ |
brunnobbco | 0:561d07a737bc | 101 | } |
brunnobbco | 0:561d07a737bc | 102 | |
brunnobbco | 0:561d07a737bc | 103 | static const fsk_bw_t fsk_bandwidths[] = |
brunnobbco | 0:561d07a737bc | 104 | { |
brunnobbco | 0:561d07a737bc | 105 | { 2600 , 0x17 }, |
brunnobbco | 0:561d07a737bc | 106 | { 3100 , 0x0F }, |
brunnobbco | 0:561d07a737bc | 107 | { 3900 , 0x07 }, |
brunnobbco | 0:561d07a737bc | 108 | { 5200 , 0x16 }, |
brunnobbco | 0:561d07a737bc | 109 | { 6300 , 0x0E }, |
brunnobbco | 0:561d07a737bc | 110 | { 7800 , 0x06 }, |
brunnobbco | 0:561d07a737bc | 111 | { 10400 , 0x15 }, |
brunnobbco | 0:561d07a737bc | 112 | { 12500 , 0x0D }, |
brunnobbco | 0:561d07a737bc | 113 | { 15600 , 0x05 }, |
brunnobbco | 0:561d07a737bc | 114 | { 20800 , 0x14 }, |
brunnobbco | 0:561d07a737bc | 115 | { 25000 , 0x0C }, |
brunnobbco | 0:561d07a737bc | 116 | { 31300 , 0x04 }, |
brunnobbco | 0:561d07a737bc | 117 | { 41700 , 0x13 }, |
brunnobbco | 0:561d07a737bc | 118 | { 50000 , 0x0B }, |
brunnobbco | 0:561d07a737bc | 119 | { 62500 , 0x03 }, |
brunnobbco | 0:561d07a737bc | 120 | { 83333 , 0x12 }, |
brunnobbco | 0:561d07a737bc | 121 | { 100000, 0x0A }, |
brunnobbco | 0:561d07a737bc | 122 | { 125000, 0x02 }, |
brunnobbco | 0:561d07a737bc | 123 | { 166700, 0x11 }, |
brunnobbco | 0:561d07a737bc | 124 | { 200000, 0x09 }, |
brunnobbco | 0:561d07a737bc | 125 | { 250000, 0x01 }, |
brunnobbco | 0:561d07a737bc | 126 | { 300000, 0x00 }, // Invalid bandwidth |
brunnobbco | 0:561d07a737bc | 127 | }; |
brunnobbco | 0:561d07a737bc | 128 | |
brunnobbco | 0:561d07a737bc | 129 | /** |
brunnobbco | 0:561d07a737bc | 130 | * SPI read/write masks |
brunnobbco | 0:561d07a737bc | 131 | */ |
brunnobbco | 0:561d07a737bc | 132 | #define SPI_WRITE_CMD 0x80 |
brunnobbco | 0:561d07a737bc | 133 | #define SPI_READ_CMD 0x7F |
brunnobbco | 0:561d07a737bc | 134 | |
brunnobbco | 0:561d07a737bc | 135 | /** |
brunnobbco | 0:561d07a737bc | 136 | * Signals |
brunnobbco | 0:561d07a737bc | 137 | */ |
brunnobbco | 0:561d07a737bc | 138 | #define SIG_DIO0 0x01 |
brunnobbco | 0:561d07a737bc | 139 | #define SIG_DIO1 0x02 |
brunnobbco | 0:561d07a737bc | 140 | #define SIG_DIO2 0x04 |
brunnobbco | 0:561d07a737bc | 141 | #define SIG_DIO3 0x08 |
brunnobbco | 0:561d07a737bc | 142 | #define SIG_DIO4 0x10 |
brunnobbco | 0:561d07a737bc | 143 | #define SIG_DIO5 0x20 |
brunnobbco | 0:561d07a737bc | 144 | #define SIG_TIMOUT 0x40 |
brunnobbco | 0:561d07a737bc | 145 | |
brunnobbco | 0:561d07a737bc | 146 | /** |
brunnobbco | 0:561d07a737bc | 147 | * Radio hardware registers initialization |
brunnobbco | 0:561d07a737bc | 148 | */ |
brunnobbco | 0:561d07a737bc | 149 | static const radio_registers_t radio_reg_init[] = RADIO_INIT_REGISTERS_VALUE; |
brunnobbco | 0:561d07a737bc | 150 | |
brunnobbco | 0:561d07a737bc | 151 | enum RadioVariant { |
brunnobbco | 0:561d07a737bc | 152 | SX1276UNDEFINED = 0, |
brunnobbco | 0:561d07a737bc | 153 | SX1276MB1LAS, |
brunnobbco | 0:561d07a737bc | 154 | SX1276MB1MAS |
brunnobbco | 0:561d07a737bc | 155 | }; |
brunnobbco | 0:561d07a737bc | 156 | |
brunnobbco | 0:561d07a737bc | 157 | #ifdef MBED_SX1276_LORA_RADIO_SPI_FREQUENCY |
brunnobbco | 0:561d07a737bc | 158 | #define SPI_FREQUENCY MBED_SX1276_LORA_RADIO_SPI_FREQUENCY |
brunnobbco | 0:561d07a737bc | 159 | #else |
brunnobbco | 0:561d07a737bc | 160 | #define SPI_FREQUENCY 8000000 |
brunnobbco | 0:561d07a737bc | 161 | #endif |
brunnobbco | 0:561d07a737bc | 162 | |
brunnobbco | 0:561d07a737bc | 163 | using namespace mbed; |
brunnobbco | 0:561d07a737bc | 164 | /** |
brunnobbco | 0:561d07a737bc | 165 | * Constructor |
brunnobbco | 0:561d07a737bc | 166 | */ |
brunnobbco | 0:561d07a737bc | 167 | SX1276_LoRaRadio::SX1276_LoRaRadio(PinName spi_mosi, |
brunnobbco | 0:561d07a737bc | 168 | PinName spi_miso, |
brunnobbco | 0:561d07a737bc | 169 | PinName spi_sclk, |
brunnobbco | 0:561d07a737bc | 170 | PinName nss, |
brunnobbco | 0:561d07a737bc | 171 | PinName reset, |
brunnobbco | 0:561d07a737bc | 172 | PinName dio0, |
brunnobbco | 0:561d07a737bc | 173 | PinName dio1, |
brunnobbco | 0:561d07a737bc | 174 | PinName dio2, |
brunnobbco | 0:561d07a737bc | 175 | PinName dio3, |
brunnobbco | 0:561d07a737bc | 176 | PinName dio4, |
brunnobbco | 0:561d07a737bc | 177 | PinName dio5, |
brunnobbco | 0:561d07a737bc | 178 | PinName rf_switch_ctl1, |
brunnobbco | 0:561d07a737bc | 179 | PinName rf_switch_ctl2, |
brunnobbco | 0:561d07a737bc | 180 | PinName txctl, |
brunnobbco | 0:561d07a737bc | 181 | PinName rxctl, |
brunnobbco | 0:561d07a737bc | 182 | PinName antswitch, |
brunnobbco | 0:561d07a737bc | 183 | PinName pwr_amp_ctl, |
brunnobbco | 0:561d07a737bc | 184 | PinName tcxo) |
brunnobbco | 0:561d07a737bc | 185 | : _spi(spi_mosi, spi_miso, spi_sclk), |
brunnobbco | 0:561d07a737bc | 186 | _chip_select(nss, 1), |
brunnobbco | 0:561d07a737bc | 187 | _reset_ctl(reset), |
brunnobbco | 0:561d07a737bc | 188 | _dio0_ctl(dio0), _dio1_ctl(dio1), _dio2_ctl(dio2), _dio3_ctl(dio3), _dio4_ctl(dio4), _dio5_ctl(dio5), |
brunnobbco | 0:561d07a737bc | 189 | _rf_switch_ctl1(rf_switch_ctl1, 0), _rf_switch_ctl2(rf_switch_ctl2, 0), |
brunnobbco | 0:561d07a737bc | 190 | _txctl(txctl, 0), _rxctl(rxctl, 0), |
brunnobbco | 0:561d07a737bc | 191 | _ant_switch(antswitch, PIN_INPUT, PullUp, 0), |
brunnobbco | 0:561d07a737bc | 192 | _pwr_amp_ctl(pwr_amp_ctl), |
brunnobbco | 0:561d07a737bc | 193 | _tcxo(tcxo) |
brunnobbco | 0:561d07a737bc | 194 | |
brunnobbco | 0:561d07a737bc | 195 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 196 | , irq_thread(osPriorityRealtime, 1024, NULL, "LR-SX1276") |
brunnobbco | 0:561d07a737bc | 197 | #endif |
brunnobbco | 0:561d07a737bc | 198 | { |
brunnobbco | 0:561d07a737bc | 199 | _rf_ctrls.ant_switch = antswitch; |
brunnobbco | 0:561d07a737bc | 200 | _rf_ctrls.pwr_amp_ctl = pwr_amp_ctl; |
brunnobbco | 0:561d07a737bc | 201 | _rf_ctrls.rf_switch_ctl1 = rf_switch_ctl1; |
brunnobbco | 0:561d07a737bc | 202 | _rf_ctrls.rf_switch_ctl2 = rf_switch_ctl2; |
brunnobbco | 0:561d07a737bc | 203 | _rf_ctrls.rxctl = rxctl; |
brunnobbco | 0:561d07a737bc | 204 | _rf_ctrls.txctl = txctl; |
brunnobbco | 0:561d07a737bc | 205 | _rf_ctrls.tcxo = tcxo; |
brunnobbco | 0:561d07a737bc | 206 | |
brunnobbco | 0:561d07a737bc | 207 | _dio4_pin = dio4; |
brunnobbco | 0:561d07a737bc | 208 | _dio5_pin = dio5; |
brunnobbco | 0:561d07a737bc | 209 | |
brunnobbco | 0:561d07a737bc | 210 | _radio_events = NULL; |
brunnobbco | 0:561d07a737bc | 211 | |
brunnobbco | 0:561d07a737bc | 212 | if (tcxo != NC) { |
brunnobbco | 0:561d07a737bc | 213 | _tcxo = 1; |
brunnobbco | 0:561d07a737bc | 214 | } |
brunnobbco | 0:561d07a737bc | 215 | |
brunnobbco | 0:561d07a737bc | 216 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 217 | irq_thread.start(mbed::callback(this, &SX1276_LoRaRadio::rf_irq_task)); |
brunnobbco | 0:561d07a737bc | 218 | #endif |
brunnobbco | 0:561d07a737bc | 219 | } |
brunnobbco | 0:561d07a737bc | 220 | |
brunnobbco | 0:561d07a737bc | 221 | /** |
brunnobbco | 0:561d07a737bc | 222 | * Destructor |
brunnobbco | 0:561d07a737bc | 223 | */ |
brunnobbco | 0:561d07a737bc | 224 | SX1276_LoRaRadio::~SX1276_LoRaRadio() |
brunnobbco | 0:561d07a737bc | 225 | { |
brunnobbco | 0:561d07a737bc | 226 | |
brunnobbco | 0:561d07a737bc | 227 | } |
brunnobbco | 0:561d07a737bc | 228 | |
brunnobbco | 0:561d07a737bc | 229 | /***************************************************************************** |
brunnobbco | 0:561d07a737bc | 230 | * Public APIs * |
brunnobbco | 0:561d07a737bc | 231 | ****************************************************************************/ |
brunnobbco | 0:561d07a737bc | 232 | /** |
brunnobbco | 0:561d07a737bc | 233 | * Acquire lock |
brunnobbco | 0:561d07a737bc | 234 | */ |
brunnobbco | 0:561d07a737bc | 235 | void SX1276_LoRaRadio::lock(void) |
brunnobbco | 0:561d07a737bc | 236 | { |
brunnobbco | 0:561d07a737bc | 237 | mutex.lock(); |
brunnobbco | 0:561d07a737bc | 238 | } |
brunnobbco | 0:561d07a737bc | 239 | |
brunnobbco | 0:561d07a737bc | 240 | /** |
brunnobbco | 0:561d07a737bc | 241 | * Release lock |
brunnobbco | 0:561d07a737bc | 242 | */ |
brunnobbco | 0:561d07a737bc | 243 | void SX1276_LoRaRadio::unlock(void) |
brunnobbco | 0:561d07a737bc | 244 | { |
brunnobbco | 0:561d07a737bc | 245 | mutex.unlock(); |
brunnobbco | 0:561d07a737bc | 246 | } |
brunnobbco | 0:561d07a737bc | 247 | |
brunnobbco | 0:561d07a737bc | 248 | /** |
brunnobbco | 0:561d07a737bc | 249 | * Initializes radio module |
brunnobbco | 0:561d07a737bc | 250 | */ |
brunnobbco | 0:561d07a737bc | 251 | void SX1276_LoRaRadio::init_radio(radio_events_t *events) |
brunnobbco | 0:561d07a737bc | 252 | { |
brunnobbco | 0:561d07a737bc | 253 | _radio_events = events; |
brunnobbco | 0:561d07a737bc | 254 | |
brunnobbco | 0:561d07a737bc | 255 | // Reset the radio transceiver |
brunnobbco | 0:561d07a737bc | 256 | radio_reset(); |
brunnobbco | 0:561d07a737bc | 257 | |
brunnobbco | 0:561d07a737bc | 258 | // Setup radio variant type |
brunnobbco | 0:561d07a737bc | 259 | set_sx1276_variant_type(); |
brunnobbco | 0:561d07a737bc | 260 | |
brunnobbco | 0:561d07a737bc | 261 | // setup SPI frequency |
brunnobbco | 0:561d07a737bc | 262 | // default is 8MHz although, configurable through |
brunnobbco | 0:561d07a737bc | 263 | // SPI_FREQUENCY macro |
brunnobbco | 0:561d07a737bc | 264 | setup_spi(); |
brunnobbco | 0:561d07a737bc | 265 | |
brunnobbco | 0:561d07a737bc | 266 | // Calibrate radio receiver chain |
brunnobbco | 0:561d07a737bc | 267 | rx_chain_calibration(); |
brunnobbco | 0:561d07a737bc | 268 | |
brunnobbco | 0:561d07a737bc | 269 | // set radio mode to sleep |
brunnobbco | 0:561d07a737bc | 270 | set_operation_mode(RF_OPMODE_SLEEP); |
brunnobbco | 0:561d07a737bc | 271 | |
brunnobbco | 0:561d07a737bc | 272 | // Setup radio registers to defaults |
brunnobbco | 0:561d07a737bc | 273 | setup_registers(); |
brunnobbco | 0:561d07a737bc | 274 | |
brunnobbco | 0:561d07a737bc | 275 | // set modem type - defaults to FSK here |
brunnobbco | 0:561d07a737bc | 276 | set_modem(MODEM_FSK); |
brunnobbco | 0:561d07a737bc | 277 | |
brunnobbco | 0:561d07a737bc | 278 | // set state to be idle |
brunnobbco | 0:561d07a737bc | 279 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 280 | |
brunnobbco | 0:561d07a737bc | 281 | // Setup interrupts on DIO pins |
brunnobbco | 0:561d07a737bc | 282 | setup_interrupts(); |
brunnobbco | 0:561d07a737bc | 283 | } |
brunnobbco | 0:561d07a737bc | 284 | |
brunnobbco | 0:561d07a737bc | 285 | /** |
brunnobbco | 0:561d07a737bc | 286 | * Can be used by application/stack or the driver itself |
brunnobbco | 0:561d07a737bc | 287 | */ |
brunnobbco | 0:561d07a737bc | 288 | void SX1276_LoRaRadio::radio_reset() |
brunnobbco | 0:561d07a737bc | 289 | { |
brunnobbco | 0:561d07a737bc | 290 | _reset_ctl.output(); |
brunnobbco | 0:561d07a737bc | 291 | _reset_ctl = 0; |
brunnobbco | 0:561d07a737bc | 292 | wait_ms(2); |
brunnobbco | 0:561d07a737bc | 293 | _reset_ctl.input(); |
brunnobbco | 0:561d07a737bc | 294 | wait_ms(6); |
brunnobbco | 0:561d07a737bc | 295 | } |
brunnobbco | 0:561d07a737bc | 296 | |
brunnobbco | 0:561d07a737bc | 297 | /** |
brunnobbco | 0:561d07a737bc | 298 | * TODO: The purpose of this API is unclear. |
brunnobbco | 0:561d07a737bc | 299 | * Need to start an internal discussion. |
brunnobbco | 0:561d07a737bc | 300 | */ |
brunnobbco | 0:561d07a737bc | 301 | bool SX1276_LoRaRadio::check_rf_frequency(uint32_t frequency) |
brunnobbco | 0:561d07a737bc | 302 | { |
brunnobbco | 0:561d07a737bc | 303 | // Implement check. Currently all frequencies are supported ? What band ? |
brunnobbco | 0:561d07a737bc | 304 | return true; |
brunnobbco | 0:561d07a737bc | 305 | } |
brunnobbco | 0:561d07a737bc | 306 | |
brunnobbco | 0:561d07a737bc | 307 | /** |
brunnobbco | 0:561d07a737bc | 308 | * Returns current status of the radio state machine |
brunnobbco | 0:561d07a737bc | 309 | */ |
brunnobbco | 0:561d07a737bc | 310 | uint8_t SX1276_LoRaRadio::get_status(void) |
brunnobbco | 0:561d07a737bc | 311 | { |
brunnobbco | 0:561d07a737bc | 312 | return _rf_settings.state; |
brunnobbco | 0:561d07a737bc | 313 | } |
brunnobbco | 0:561d07a737bc | 314 | |
brunnobbco | 0:561d07a737bc | 315 | /** |
brunnobbco | 0:561d07a737bc | 316 | * Sets up carrier frequency |
brunnobbco | 0:561d07a737bc | 317 | */ |
brunnobbco | 0:561d07a737bc | 318 | void SX1276_LoRaRadio::set_channel(uint32_t freq) |
brunnobbco | 0:561d07a737bc | 319 | { |
brunnobbco | 0:561d07a737bc | 320 | _rf_settings.channel = freq; |
brunnobbco | 0:561d07a737bc | 321 | freq = (uint32_t) ((float) freq / (float) FREQ_STEP); |
brunnobbco | 0:561d07a737bc | 322 | write_to_register(REG_FRFMSB, (uint8_t) ((freq >> 16) & 0xFF)); |
brunnobbco | 0:561d07a737bc | 323 | write_to_register(REG_FRFMID, (uint8_t) ((freq >> 8) & 0xFF)); |
brunnobbco | 0:561d07a737bc | 324 | write_to_register(REG_FRFLSB, (uint8_t) (freq & 0xFF)); |
brunnobbco | 0:561d07a737bc | 325 | } |
brunnobbco | 0:561d07a737bc | 326 | |
brunnobbco | 0:561d07a737bc | 327 | /** |
brunnobbco | 0:561d07a737bc | 328 | * Generates 32 bit random number based upon RSSI monitoring |
brunnobbco | 0:561d07a737bc | 329 | * Used for various calculation by the stack for example dev nonce |
brunnobbco | 0:561d07a737bc | 330 | * |
brunnobbco | 0:561d07a737bc | 331 | * When this API is used modem is set in LoRa mode and all interrupts are |
brunnobbco | 0:561d07a737bc | 332 | * masked. If the user had been using FSK mode, it should be noted that a |
brunnobbco | 0:561d07a737bc | 333 | * change of mode is required again because the registers have changed. |
brunnobbco | 0:561d07a737bc | 334 | * In addition to that RX and TX configuration APIs should be called again in |
brunnobbco | 0:561d07a737bc | 335 | * order to have correct desires setup. |
brunnobbco | 0:561d07a737bc | 336 | */ |
brunnobbco | 0:561d07a737bc | 337 | uint32_t SX1276_LoRaRadio::random( void ) |
brunnobbco | 0:561d07a737bc | 338 | { |
brunnobbco | 0:561d07a737bc | 339 | uint8_t i; |
brunnobbco | 0:561d07a737bc | 340 | uint32_t rnd = 0; |
brunnobbco | 0:561d07a737bc | 341 | |
brunnobbco | 0:561d07a737bc | 342 | /* |
brunnobbco | 0:561d07a737bc | 343 | * Radio setup for random number generation |
brunnobbco | 0:561d07a737bc | 344 | */ |
brunnobbco | 0:561d07a737bc | 345 | set_modem( MODEM_LORA ); |
brunnobbco | 0:561d07a737bc | 346 | |
brunnobbco | 0:561d07a737bc | 347 | // Disable LoRa modem interrupts |
brunnobbco | 0:561d07a737bc | 348 | write_to_register(REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | |
brunnobbco | 0:561d07a737bc | 349 | RFLR_IRQFLAGS_RXDONE | |
brunnobbco | 0:561d07a737bc | 350 | RFLR_IRQFLAGS_PAYLOADCRCERROR | |
brunnobbco | 0:561d07a737bc | 351 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 352 | RFLR_IRQFLAGS_TXDONE | |
brunnobbco | 0:561d07a737bc | 353 | RFLR_IRQFLAGS_CADDONE | |
brunnobbco | 0:561d07a737bc | 354 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | |
brunnobbco | 0:561d07a737bc | 355 | RFLR_IRQFLAGS_CADDETECTED ); |
brunnobbco | 0:561d07a737bc | 356 | |
brunnobbco | 0:561d07a737bc | 357 | // Set radio in continuous reception |
brunnobbco | 0:561d07a737bc | 358 | set_operation_mode(RF_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 359 | |
brunnobbco | 0:561d07a737bc | 360 | for (i = 0; i < 32; i++) { |
brunnobbco | 0:561d07a737bc | 361 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 362 | // Unfiltered RSSI value reading. Only takes the LSB value |
brunnobbco | 0:561d07a737bc | 363 | rnd |= ((uint32_t) read_register( REG_LR_RSSIWIDEBAND) & 0x01) << i; |
brunnobbco | 0:561d07a737bc | 364 | } |
brunnobbco | 0:561d07a737bc | 365 | |
brunnobbco | 0:561d07a737bc | 366 | sleep(); |
brunnobbco | 0:561d07a737bc | 367 | |
brunnobbco | 0:561d07a737bc | 368 | return rnd; |
brunnobbco | 0:561d07a737bc | 369 | } |
brunnobbco | 0:561d07a737bc | 370 | |
brunnobbco | 0:561d07a737bc | 371 | /** |
brunnobbco | 0:561d07a737bc | 372 | * Sets up receiver related configurations |
brunnobbco | 0:561d07a737bc | 373 | * |
brunnobbco | 0:561d07a737bc | 374 | * Must be called before setting the radio in rx mode |
brunnobbco | 0:561d07a737bc | 375 | */ |
brunnobbco | 0:561d07a737bc | 376 | void SX1276_LoRaRadio::set_rx_config(radio_modems_t modem, uint32_t bandwidth, |
brunnobbco | 0:561d07a737bc | 377 | uint32_t datarate, uint8_t coderate, |
brunnobbco | 0:561d07a737bc | 378 | uint32_t bandwidth_afc, |
brunnobbco | 0:561d07a737bc | 379 | uint16_t preamble_len, |
brunnobbco | 0:561d07a737bc | 380 | uint16_t symb_timeout, bool fix_len, |
brunnobbco | 0:561d07a737bc | 381 | uint8_t payload_len, bool crc_on, |
brunnobbco | 0:561d07a737bc | 382 | bool freq_hop_on, uint8_t hop_period, |
brunnobbco | 0:561d07a737bc | 383 | bool iq_inverted, bool rx_continuous) |
brunnobbco | 0:561d07a737bc | 384 | { |
brunnobbco | 0:561d07a737bc | 385 | set_modem(modem); |
brunnobbco | 0:561d07a737bc | 386 | |
brunnobbco | 0:561d07a737bc | 387 | switch (modem) { |
brunnobbco | 0:561d07a737bc | 388 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 389 | _rf_settings.fsk.bandwidth = bandwidth; |
brunnobbco | 0:561d07a737bc | 390 | _rf_settings.fsk.datarate = datarate; |
brunnobbco | 0:561d07a737bc | 391 | _rf_settings.fsk.bandwidth_afc = bandwidth_afc; |
brunnobbco | 0:561d07a737bc | 392 | _rf_settings.fsk.fix_len = fix_len; |
brunnobbco | 0:561d07a737bc | 393 | _rf_settings.fsk.payload_len = payload_len; |
brunnobbco | 0:561d07a737bc | 394 | _rf_settings.fsk.crc_on = crc_on; |
brunnobbco | 0:561d07a737bc | 395 | _rf_settings.fsk.iq_inverted = iq_inverted; |
brunnobbco | 0:561d07a737bc | 396 | _rf_settings.fsk.rx_continuous = rx_continuous; |
brunnobbco | 0:561d07a737bc | 397 | _rf_settings.fsk.preamble_len = preamble_len; |
brunnobbco | 0:561d07a737bc | 398 | _rf_settings.fsk.rx_single_timeout = (symb_timeout + 1) / 2; // dividing by 2 as our detector size is 2 symbols (16 bytes) |
brunnobbco | 0:561d07a737bc | 399 | |
brunnobbco | 0:561d07a737bc | 400 | datarate = (uint16_t) ((float) XTAL_FREQ / (float) datarate); |
brunnobbco | 0:561d07a737bc | 401 | write_to_register(REG_BITRATEMSB, (uint8_t) (datarate >> 8)); |
brunnobbco | 0:561d07a737bc | 402 | write_to_register(REG_BITRATELSB, (uint8_t) (datarate & 0xFF)); |
brunnobbco | 0:561d07a737bc | 403 | |
brunnobbco | 0:561d07a737bc | 404 | write_to_register(REG_RXBW, get_fsk_bw_reg_val(bandwidth)); |
brunnobbco | 0:561d07a737bc | 405 | write_to_register(REG_AFCBW, get_fsk_bw_reg_val(bandwidth_afc)); |
brunnobbco | 0:561d07a737bc | 406 | |
brunnobbco | 0:561d07a737bc | 407 | write_to_register(REG_PREAMBLEMSB, (uint8_t) ((preamble_len >> 8) & 0xFF)); |
brunnobbco | 0:561d07a737bc | 408 | write_to_register(REG_PREAMBLELSB, (uint8_t) (preamble_len & 0xFF)); |
brunnobbco | 0:561d07a737bc | 409 | |
brunnobbco | 0:561d07a737bc | 410 | if (fix_len == 1) { |
brunnobbco | 0:561d07a737bc | 411 | write_to_register(REG_PAYLOADLENGTH, payload_len); |
brunnobbco | 0:561d07a737bc | 412 | } else { |
brunnobbco | 0:561d07a737bc | 413 | write_to_register(REG_PAYLOADLENGTH, 0xFF); // Set payload length to the maximum |
brunnobbco | 0:561d07a737bc | 414 | } |
brunnobbco | 0:561d07a737bc | 415 | |
brunnobbco | 0:561d07a737bc | 416 | write_to_register( |
brunnobbco | 0:561d07a737bc | 417 | REG_PACKETCONFIG1, |
brunnobbco | 0:561d07a737bc | 418 | (read_register(REG_PACKETCONFIG1) |
brunnobbco | 0:561d07a737bc | 419 | & RF_PACKETCONFIG1_CRC_MASK |
brunnobbco | 0:561d07a737bc | 420 | & RF_PACKETCONFIG1_PACKETFORMAT_MASK) |
brunnobbco | 0:561d07a737bc | 421 | | ((fix_len == 1) ? |
brunnobbco | 0:561d07a737bc | 422 | RF_PACKETCONFIG1_PACKETFORMAT_FIXED : |
brunnobbco | 0:561d07a737bc | 423 | RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE) |
brunnobbco | 0:561d07a737bc | 424 | | (crc_on << 4)); |
brunnobbco | 0:561d07a737bc | 425 | |
brunnobbco | 0:561d07a737bc | 426 | // TODO why packet mode 2 ? |
brunnobbco | 0:561d07a737bc | 427 | write_to_register(REG_PACKETCONFIG2, (read_register(REG_PACKETCONFIG2) |
brunnobbco | 0:561d07a737bc | 428 | | RF_PACKETCONFIG2_DATAMODE_PACKET)); |
brunnobbco | 0:561d07a737bc | 429 | |
brunnobbco | 0:561d07a737bc | 430 | break; |
brunnobbco | 0:561d07a737bc | 431 | |
brunnobbco | 0:561d07a737bc | 432 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 433 | |
brunnobbco | 0:561d07a737bc | 434 | if (bandwidth > 2) { |
brunnobbco | 0:561d07a737bc | 435 | // Fatal error: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported |
brunnobbco | 0:561d07a737bc | 436 | while (1) |
brunnobbco | 0:561d07a737bc | 437 | ; |
brunnobbco | 0:561d07a737bc | 438 | // TODO Return a proper error from here |
brunnobbco | 0:561d07a737bc | 439 | } |
brunnobbco | 0:561d07a737bc | 440 | |
brunnobbco | 0:561d07a737bc | 441 | // stupid hack. TODO think something better |
brunnobbco | 0:561d07a737bc | 442 | bandwidth+=7; |
brunnobbco | 0:561d07a737bc | 443 | |
brunnobbco | 0:561d07a737bc | 444 | _rf_settings.lora.bandwidth = bandwidth; |
brunnobbco | 0:561d07a737bc | 445 | _rf_settings.lora.datarate = datarate; |
brunnobbco | 0:561d07a737bc | 446 | _rf_settings.lora.coderate = coderate; |
brunnobbco | 0:561d07a737bc | 447 | _rf_settings.lora.preamble_len = preamble_len; |
brunnobbco | 0:561d07a737bc | 448 | _rf_settings.lora.fix_len = fix_len; |
brunnobbco | 0:561d07a737bc | 449 | _rf_settings.lora.payload_len = payload_len; |
brunnobbco | 0:561d07a737bc | 450 | _rf_settings.lora.crc_on = crc_on; |
brunnobbco | 0:561d07a737bc | 451 | _rf_settings.lora.freq_hop_on = freq_hop_on; |
brunnobbco | 0:561d07a737bc | 452 | _rf_settings.lora.hop_period = hop_period; |
brunnobbco | 0:561d07a737bc | 453 | _rf_settings.lora.iq_inverted = iq_inverted; |
brunnobbco | 0:561d07a737bc | 454 | _rf_settings.lora.rx_continuous = rx_continuous; |
brunnobbco | 0:561d07a737bc | 455 | |
brunnobbco | 0:561d07a737bc | 456 | if (datarate > 12) { |
brunnobbco | 0:561d07a737bc | 457 | datarate = 12; |
brunnobbco | 0:561d07a737bc | 458 | } else if (datarate < 6) { |
brunnobbco | 0:561d07a737bc | 459 | datarate = 6; |
brunnobbco | 0:561d07a737bc | 460 | } |
brunnobbco | 0:561d07a737bc | 461 | |
brunnobbco | 0:561d07a737bc | 462 | if (((bandwidth == 7) && ((datarate == 11) || (datarate == 12))) |
brunnobbco | 0:561d07a737bc | 463 | || ((bandwidth == 8) && (datarate == 12))) { |
brunnobbco | 0:561d07a737bc | 464 | _rf_settings.lora.low_datarate_optimize = 0x01; |
brunnobbco | 0:561d07a737bc | 465 | } else { |
brunnobbco | 0:561d07a737bc | 466 | _rf_settings.lora.low_datarate_optimize = 0x00; |
brunnobbco | 0:561d07a737bc | 467 | } |
brunnobbco | 0:561d07a737bc | 468 | |
brunnobbco | 0:561d07a737bc | 469 | write_to_register(REG_LR_MODEMCONFIG1, (read_register( REG_LR_MODEMCONFIG1) |
brunnobbco | 0:561d07a737bc | 470 | & RFLR_MODEMCONFIG1_BW_MASK |
brunnobbco | 0:561d07a737bc | 471 | & RFLR_MODEMCONFIG1_CODINGRATE_MASK |
brunnobbco | 0:561d07a737bc | 472 | & RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK) |
brunnobbco | 0:561d07a737bc | 473 | | (bandwidth << 4) |
brunnobbco | 0:561d07a737bc | 474 | | (coderate << 1) | fix_len); |
brunnobbco | 0:561d07a737bc | 475 | |
brunnobbco | 0:561d07a737bc | 476 | write_to_register(REG_LR_MODEMCONFIG2, (read_register( REG_LR_MODEMCONFIG2) |
brunnobbco | 0:561d07a737bc | 477 | & RFLR_MODEMCONFIG2_SF_MASK |
brunnobbco | 0:561d07a737bc | 478 | & RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK |
brunnobbco | 0:561d07a737bc | 479 | & RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK) |
brunnobbco | 0:561d07a737bc | 480 | | (datarate << 4) |
brunnobbco | 0:561d07a737bc | 481 | | (crc_on << 2) |
brunnobbco | 0:561d07a737bc | 482 | | ((symb_timeout >> 8) |
brunnobbco | 0:561d07a737bc | 483 | & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK)); |
brunnobbco | 0:561d07a737bc | 484 | |
brunnobbco | 0:561d07a737bc | 485 | write_to_register(REG_LR_MODEMCONFIG3, (read_register( REG_LR_MODEMCONFIG3) |
brunnobbco | 0:561d07a737bc | 486 | & RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK) |
brunnobbco | 0:561d07a737bc | 487 | | (_rf_settings.lora.low_datarate_optimize << 3)); |
brunnobbco | 0:561d07a737bc | 488 | |
brunnobbco | 0:561d07a737bc | 489 | write_to_register(REG_LR_SYMBTIMEOUTLSB, (uint8_t) (symb_timeout & 0xFF)); |
brunnobbco | 0:561d07a737bc | 490 | |
brunnobbco | 0:561d07a737bc | 491 | write_to_register(REG_LR_PREAMBLEMSB, (uint8_t) ((preamble_len >> 8) & 0xFF)); |
brunnobbco | 0:561d07a737bc | 492 | write_to_register(REG_LR_PREAMBLELSB, (uint8_t) (preamble_len & 0xFF)); |
brunnobbco | 0:561d07a737bc | 493 | |
brunnobbco | 0:561d07a737bc | 494 | if (fix_len == 1) { |
brunnobbco | 0:561d07a737bc | 495 | write_to_register(REG_LR_PAYLOADLENGTH, payload_len); |
brunnobbco | 0:561d07a737bc | 496 | } |
brunnobbco | 0:561d07a737bc | 497 | |
brunnobbco | 0:561d07a737bc | 498 | if (_rf_settings.lora.freq_hop_on == true) { |
brunnobbco | 0:561d07a737bc | 499 | write_to_register(REG_LR_PLLHOP, (read_register( REG_LR_PLLHOP) |
brunnobbco | 0:561d07a737bc | 500 | & RFLR_PLLHOP_FASTHOP_MASK) |
brunnobbco | 0:561d07a737bc | 501 | | RFLR_PLLHOP_FASTHOP_ON); |
brunnobbco | 0:561d07a737bc | 502 | write_to_register(REG_LR_HOPPERIOD,_rf_settings.lora.hop_period); |
brunnobbco | 0:561d07a737bc | 503 | } |
brunnobbco | 0:561d07a737bc | 504 | |
brunnobbco | 0:561d07a737bc | 505 | if ((bandwidth == 9) && (_rf_settings.channel > RF_MID_BAND_THRESH)) { |
brunnobbco | 0:561d07a737bc | 506 | // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth |
brunnobbco | 0:561d07a737bc | 507 | write_to_register(REG_LR_TEST36, 0x02); |
brunnobbco | 0:561d07a737bc | 508 | write_to_register(REG_LR_TEST3A, 0x64); |
brunnobbco | 0:561d07a737bc | 509 | } else if (bandwidth == 9) { |
brunnobbco | 0:561d07a737bc | 510 | // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth |
brunnobbco | 0:561d07a737bc | 511 | write_to_register(REG_LR_TEST36, 0x02); |
brunnobbco | 0:561d07a737bc | 512 | write_to_register(REG_LR_TEST3A, 0x7F); |
brunnobbco | 0:561d07a737bc | 513 | } else { |
brunnobbco | 0:561d07a737bc | 514 | // ERRATA 2.1 - Sensitivity Optimization with a 500 kHz Bandwidth |
brunnobbco | 0:561d07a737bc | 515 | write_to_register(REG_LR_TEST36, 0x03); |
brunnobbco | 0:561d07a737bc | 516 | } |
brunnobbco | 0:561d07a737bc | 517 | |
brunnobbco | 0:561d07a737bc | 518 | if (datarate == 6) { |
brunnobbco | 0:561d07a737bc | 519 | write_to_register(REG_LR_DETECTOPTIMIZE, (read_register(REG_LR_DETECTOPTIMIZE) |
brunnobbco | 0:561d07a737bc | 520 | & RFLR_DETECTIONOPTIMIZE_MASK) |
brunnobbco | 0:561d07a737bc | 521 | | RFLR_DETECTIONOPTIMIZE_SF6); |
brunnobbco | 0:561d07a737bc | 522 | write_to_register(REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF6); |
brunnobbco | 0:561d07a737bc | 523 | } else { |
brunnobbco | 0:561d07a737bc | 524 | write_to_register(REG_LR_DETECTOPTIMIZE, (read_register(REG_LR_DETECTOPTIMIZE) |
brunnobbco | 0:561d07a737bc | 525 | & RFLR_DETECTIONOPTIMIZE_MASK) |
brunnobbco | 0:561d07a737bc | 526 | | RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12); |
brunnobbco | 0:561d07a737bc | 527 | write_to_register(REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF7_TO_SF12); |
brunnobbco | 0:561d07a737bc | 528 | } |
brunnobbco | 0:561d07a737bc | 529 | break; |
brunnobbco | 0:561d07a737bc | 530 | |
brunnobbco | 0:561d07a737bc | 531 | default: |
brunnobbco | 0:561d07a737bc | 532 | break; |
brunnobbco | 0:561d07a737bc | 533 | } |
brunnobbco | 0:561d07a737bc | 534 | } |
brunnobbco | 0:561d07a737bc | 535 | |
brunnobbco | 0:561d07a737bc | 536 | /** |
brunnobbco | 0:561d07a737bc | 537 | * Sets up transmitter related configuration |
brunnobbco | 0:561d07a737bc | 538 | * |
brunnobbco | 0:561d07a737bc | 539 | * Must be called before putting the radio module in Tx mode or trying |
brunnobbco | 0:561d07a737bc | 540 | * to send |
brunnobbco | 0:561d07a737bc | 541 | */ |
brunnobbco | 0:561d07a737bc | 542 | void SX1276_LoRaRadio::set_tx_config(radio_modems_t modem, int8_t power, |
brunnobbco | 0:561d07a737bc | 543 | uint32_t fdev, uint32_t bandwidth, |
brunnobbco | 0:561d07a737bc | 544 | uint32_t datarate, uint8_t coderate, |
brunnobbco | 0:561d07a737bc | 545 | uint16_t preamble_len, bool fix_len, |
brunnobbco | 0:561d07a737bc | 546 | bool crc_on, bool freq_hop_on, |
brunnobbco | 0:561d07a737bc | 547 | uint8_t hop_period, bool iq_inverted, |
brunnobbco | 0:561d07a737bc | 548 | uint32_t timeout) |
brunnobbco | 0:561d07a737bc | 549 | { |
brunnobbco | 0:561d07a737bc | 550 | set_modem(modem); |
brunnobbco | 0:561d07a737bc | 551 | set_rf_tx_power(power); |
brunnobbco | 0:561d07a737bc | 552 | |
brunnobbco | 0:561d07a737bc | 553 | switch (modem) { |
brunnobbco | 0:561d07a737bc | 554 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 555 | _rf_settings.fsk.power = power; |
brunnobbco | 0:561d07a737bc | 556 | _rf_settings.fsk.f_dev = fdev; |
brunnobbco | 0:561d07a737bc | 557 | _rf_settings.fsk.bandwidth = bandwidth; |
brunnobbco | 0:561d07a737bc | 558 | _rf_settings.fsk.datarate = datarate; |
brunnobbco | 0:561d07a737bc | 559 | _rf_settings.fsk.preamble_len = preamble_len; |
brunnobbco | 0:561d07a737bc | 560 | _rf_settings.fsk.fix_len = fix_len; |
brunnobbco | 0:561d07a737bc | 561 | _rf_settings.fsk.crc_on = crc_on; |
brunnobbco | 0:561d07a737bc | 562 | _rf_settings.fsk.iq_inverted = iq_inverted; |
brunnobbco | 0:561d07a737bc | 563 | _rf_settings.fsk.tx_timeout = timeout; |
brunnobbco | 0:561d07a737bc | 564 | |
brunnobbco | 0:561d07a737bc | 565 | fdev = (uint16_t) ((float) fdev / (float) FREQ_STEP); |
brunnobbco | 0:561d07a737bc | 566 | write_to_register( REG_FDEVMSB, (uint8_t) (fdev >> 8)); |
brunnobbco | 0:561d07a737bc | 567 | write_to_register( REG_FDEVLSB, (uint8_t) (fdev & 0xFF)); |
brunnobbco | 0:561d07a737bc | 568 | |
brunnobbco | 0:561d07a737bc | 569 | datarate = (uint16_t) ((float) XTAL_FREQ / (float) datarate); |
brunnobbco | 0:561d07a737bc | 570 | write_to_register( REG_BITRATEMSB, (uint8_t) (datarate >> 8)); |
brunnobbco | 0:561d07a737bc | 571 | write_to_register( REG_BITRATELSB, (uint8_t) (datarate & 0xFF)); |
brunnobbco | 0:561d07a737bc | 572 | |
brunnobbco | 0:561d07a737bc | 573 | write_to_register( REG_PREAMBLEMSB, (preamble_len >> 8) & 0x00FF); |
brunnobbco | 0:561d07a737bc | 574 | write_to_register( REG_PREAMBLELSB, preamble_len & 0xFF); |
brunnobbco | 0:561d07a737bc | 575 | |
brunnobbco | 0:561d07a737bc | 576 | write_to_register(REG_PACKETCONFIG1, |
brunnobbco | 0:561d07a737bc | 577 | (read_register( REG_PACKETCONFIG1) & |
brunnobbco | 0:561d07a737bc | 578 | RF_PACKETCONFIG1_CRC_MASK & |
brunnobbco | 0:561d07a737bc | 579 | RF_PACKETCONFIG1_PACKETFORMAT_MASK) |
brunnobbco | 0:561d07a737bc | 580 | | ((fix_len == 1) ? |
brunnobbco | 0:561d07a737bc | 581 | RF_PACKETCONFIG1_PACKETFORMAT_FIXED : |
brunnobbco | 0:561d07a737bc | 582 | RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE) |
brunnobbco | 0:561d07a737bc | 583 | | (crc_on << 4)); |
brunnobbco | 0:561d07a737bc | 584 | write_to_register(REG_PACKETCONFIG2, |
brunnobbco | 0:561d07a737bc | 585 | (read_register( REG_PACKETCONFIG2) |
brunnobbco | 0:561d07a737bc | 586 | | RF_PACKETCONFIG2_DATAMODE_PACKET)); |
brunnobbco | 0:561d07a737bc | 587 | |
brunnobbco | 0:561d07a737bc | 588 | break; |
brunnobbco | 0:561d07a737bc | 589 | |
brunnobbco | 0:561d07a737bc | 590 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 591 | _rf_settings.lora.power = power; |
brunnobbco | 0:561d07a737bc | 592 | // Fatal error: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported |
brunnobbco | 0:561d07a737bc | 593 | MBED_ASSERT(bandwidth <= 2); |
brunnobbco | 0:561d07a737bc | 594 | bandwidth += 7; |
brunnobbco | 0:561d07a737bc | 595 | _rf_settings.lora.bandwidth = bandwidth; |
brunnobbco | 0:561d07a737bc | 596 | _rf_settings.lora.datarate = datarate; |
brunnobbco | 0:561d07a737bc | 597 | _rf_settings.lora.coderate = coderate; |
brunnobbco | 0:561d07a737bc | 598 | _rf_settings.lora.preamble_len = preamble_len; |
brunnobbco | 0:561d07a737bc | 599 | _rf_settings.lora.fix_len = fix_len; |
brunnobbco | 0:561d07a737bc | 600 | _rf_settings.lora.freq_hop_on = freq_hop_on; |
brunnobbco | 0:561d07a737bc | 601 | _rf_settings.lora.hop_period = hop_period; |
brunnobbco | 0:561d07a737bc | 602 | _rf_settings.lora.crc_on = crc_on; |
brunnobbco | 0:561d07a737bc | 603 | _rf_settings.lora.iq_inverted = iq_inverted; |
brunnobbco | 0:561d07a737bc | 604 | _rf_settings.lora.tx_timeout = timeout; |
brunnobbco | 0:561d07a737bc | 605 | |
brunnobbco | 0:561d07a737bc | 606 | if (datarate > 12) { |
brunnobbco | 0:561d07a737bc | 607 | datarate = 12; |
brunnobbco | 0:561d07a737bc | 608 | } else if (datarate < 6) { |
brunnobbco | 0:561d07a737bc | 609 | datarate = 6; |
brunnobbco | 0:561d07a737bc | 610 | } |
brunnobbco | 0:561d07a737bc | 611 | if (((bandwidth == 7) && ((datarate == 11) || (datarate == 12))) |
brunnobbco | 0:561d07a737bc | 612 | || ((bandwidth == 8) && (datarate == 12))) { |
brunnobbco | 0:561d07a737bc | 613 | _rf_settings.lora.low_datarate_optimize = 0x01; |
brunnobbco | 0:561d07a737bc | 614 | } else { |
brunnobbco | 0:561d07a737bc | 615 | _rf_settings.lora.low_datarate_optimize = 0x00; |
brunnobbco | 0:561d07a737bc | 616 | } |
brunnobbco | 0:561d07a737bc | 617 | |
brunnobbco | 0:561d07a737bc | 618 | if (_rf_settings.lora.freq_hop_on == true) { |
brunnobbco | 0:561d07a737bc | 619 | write_to_register(REG_LR_PLLHOP, (read_register(REG_LR_PLLHOP) |
brunnobbco | 0:561d07a737bc | 620 | & RFLR_PLLHOP_FASTHOP_MASK) |
brunnobbco | 0:561d07a737bc | 621 | | RFLR_PLLHOP_FASTHOP_ON); |
brunnobbco | 0:561d07a737bc | 622 | write_to_register( REG_LR_HOPPERIOD, _rf_settings.lora.hop_period); |
brunnobbco | 0:561d07a737bc | 623 | } |
brunnobbco | 0:561d07a737bc | 624 | |
brunnobbco | 0:561d07a737bc | 625 | write_to_register(REG_LR_MODEMCONFIG1, (read_register( REG_LR_MODEMCONFIG1) |
brunnobbco | 0:561d07a737bc | 626 | & RFLR_MODEMCONFIG1_BW_MASK |
brunnobbco | 0:561d07a737bc | 627 | & RFLR_MODEMCONFIG1_CODINGRATE_MASK |
brunnobbco | 0:561d07a737bc | 628 | & RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK) | (bandwidth << 4) |
brunnobbco | 0:561d07a737bc | 629 | | (coderate << 1) | fix_len); |
brunnobbco | 0:561d07a737bc | 630 | |
brunnobbco | 0:561d07a737bc | 631 | write_to_register(REG_LR_MODEMCONFIG2, (read_register( REG_LR_MODEMCONFIG2) |
brunnobbco | 0:561d07a737bc | 632 | & RFLR_MODEMCONFIG2_SF_MASK |
brunnobbco | 0:561d07a737bc | 633 | & RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK) |
brunnobbco | 0:561d07a737bc | 634 | | (datarate << 4) |
brunnobbco | 0:561d07a737bc | 635 | | (crc_on << 2)); |
brunnobbco | 0:561d07a737bc | 636 | |
brunnobbco | 0:561d07a737bc | 637 | write_to_register(REG_LR_MODEMCONFIG3, (read_register(REG_LR_MODEMCONFIG3) |
brunnobbco | 0:561d07a737bc | 638 | & RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK) |
brunnobbco | 0:561d07a737bc | 639 | | (_rf_settings.lora.low_datarate_optimize << 3)); |
brunnobbco | 0:561d07a737bc | 640 | |
brunnobbco | 0:561d07a737bc | 641 | write_to_register(REG_LR_PREAMBLEMSB, (preamble_len >> 8) & 0x00FF); |
brunnobbco | 0:561d07a737bc | 642 | write_to_register(REG_LR_PREAMBLELSB, preamble_len & 0xFF); |
brunnobbco | 0:561d07a737bc | 643 | |
brunnobbco | 0:561d07a737bc | 644 | if (datarate == 6) { |
brunnobbco | 0:561d07a737bc | 645 | write_to_register(REG_LR_DETECTOPTIMIZE, (read_register( REG_LR_DETECTOPTIMIZE) |
brunnobbco | 0:561d07a737bc | 646 | & RFLR_DETECTIONOPTIMIZE_MASK) | RFLR_DETECTIONOPTIMIZE_SF6); |
brunnobbco | 0:561d07a737bc | 647 | write_to_register(REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF6); |
brunnobbco | 0:561d07a737bc | 648 | } else { |
brunnobbco | 0:561d07a737bc | 649 | write_to_register(REG_LR_DETECTOPTIMIZE, (read_register( REG_LR_DETECTOPTIMIZE) |
brunnobbco | 0:561d07a737bc | 650 | & RFLR_DETECTIONOPTIMIZE_MASK) | RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12); |
brunnobbco | 0:561d07a737bc | 651 | write_to_register( REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF7_TO_SF12); |
brunnobbco | 0:561d07a737bc | 652 | } |
brunnobbco | 0:561d07a737bc | 653 | |
brunnobbco | 0:561d07a737bc | 654 | break; |
brunnobbco | 0:561d07a737bc | 655 | } |
brunnobbco | 0:561d07a737bc | 656 | } |
brunnobbco | 0:561d07a737bc | 657 | |
brunnobbco | 0:561d07a737bc | 658 | /** |
brunnobbco | 0:561d07a737bc | 659 | * Calculates time on Air i.e., dwell time for a single packet |
brunnobbco | 0:561d07a737bc | 660 | * |
brunnobbco | 0:561d07a737bc | 661 | * Crucial for the stack in order to calculate dwell time so as to control |
brunnobbco | 0:561d07a737bc | 662 | * duty cycling. |
brunnobbco | 0:561d07a737bc | 663 | */ |
brunnobbco | 0:561d07a737bc | 664 | uint32_t SX1276_LoRaRadio::time_on_air(radio_modems_t modem, uint8_t pkt_len) |
brunnobbco | 0:561d07a737bc | 665 | { |
brunnobbco | 0:561d07a737bc | 666 | uint32_t airTime = 0; |
brunnobbco | 0:561d07a737bc | 667 | |
brunnobbco | 0:561d07a737bc | 668 | switch (modem) { |
brunnobbco | 0:561d07a737bc | 669 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 670 | airTime = |
brunnobbco | 0:561d07a737bc | 671 | rint((8 * (_rf_settings.fsk.preamble_len |
brunnobbco | 0:561d07a737bc | 672 | + ((read_register( REG_SYNCCONFIG) |
brunnobbco | 0:561d07a737bc | 673 | & ~RF_SYNCCONFIG_SYNCSIZE_MASK) + 1) |
brunnobbco | 0:561d07a737bc | 674 | + ((_rf_settings.fsk.fix_len == 0x01) ? |
brunnobbco | 0:561d07a737bc | 675 | 0.0f : 1.0f) |
brunnobbco | 0:561d07a737bc | 676 | + (((read_register( REG_PACKETCONFIG1) |
brunnobbco | 0:561d07a737bc | 677 | & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK) |
brunnobbco | 0:561d07a737bc | 678 | != 0x00) ? 1.0f : 0) + pkt_len |
brunnobbco | 0:561d07a737bc | 679 | + ((_rf_settings.fsk.crc_on == 0x01) ? |
brunnobbco | 0:561d07a737bc | 680 | 2.0 : 0)) |
brunnobbco | 0:561d07a737bc | 681 | / _rf_settings.fsk.datarate) * 1000); |
brunnobbco | 0:561d07a737bc | 682 | |
brunnobbco | 0:561d07a737bc | 683 | break; |
brunnobbco | 0:561d07a737bc | 684 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 685 | float bw = 0.0f; |
brunnobbco | 0:561d07a737bc | 686 | // REMARK: When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported |
brunnobbco | 0:561d07a737bc | 687 | switch (_rf_settings.lora.bandwidth) { |
brunnobbco | 0:561d07a737bc | 688 | //case 0: // 7.8 kHz |
brunnobbco | 0:561d07a737bc | 689 | // bw = 78e2; |
brunnobbco | 0:561d07a737bc | 690 | // break; |
brunnobbco | 0:561d07a737bc | 691 | //case 1: // 10.4 kHz |
brunnobbco | 0:561d07a737bc | 692 | // bw = 104e2; |
brunnobbco | 0:561d07a737bc | 693 | // break; |
brunnobbco | 0:561d07a737bc | 694 | //case 2: // 15.6 kHz |
brunnobbco | 0:561d07a737bc | 695 | // bw = 156e2; |
brunnobbco | 0:561d07a737bc | 696 | // break; |
brunnobbco | 0:561d07a737bc | 697 | //case 3: // 20.8 kHz |
brunnobbco | 0:561d07a737bc | 698 | // bw = 208e2; |
brunnobbco | 0:561d07a737bc | 699 | // break; |
brunnobbco | 0:561d07a737bc | 700 | //case 4: // 31.2 kHz |
brunnobbco | 0:561d07a737bc | 701 | // bw = 312e2; |
brunnobbco | 0:561d07a737bc | 702 | // break; |
brunnobbco | 0:561d07a737bc | 703 | //case 5: // 41.4 kHz |
brunnobbco | 0:561d07a737bc | 704 | // bw = 414e2; |
brunnobbco | 0:561d07a737bc | 705 | // break; |
brunnobbco | 0:561d07a737bc | 706 | //case 6: // 62.5 kHz |
brunnobbco | 0:561d07a737bc | 707 | // bw = 625e2; |
brunnobbco | 0:561d07a737bc | 708 | // break; |
brunnobbco | 0:561d07a737bc | 709 | case 7: // 125 kHz |
brunnobbco | 0:561d07a737bc | 710 | bw = 125000; |
brunnobbco | 0:561d07a737bc | 711 | break; |
brunnobbco | 0:561d07a737bc | 712 | case 8: // 250 kHz |
brunnobbco | 0:561d07a737bc | 713 | bw = 250000; |
brunnobbco | 0:561d07a737bc | 714 | break; |
brunnobbco | 0:561d07a737bc | 715 | case 9: // 500 kHz |
brunnobbco | 0:561d07a737bc | 716 | bw = 500000; |
brunnobbco | 0:561d07a737bc | 717 | break; |
brunnobbco | 0:561d07a737bc | 718 | } |
brunnobbco | 0:561d07a737bc | 719 | |
brunnobbco | 0:561d07a737bc | 720 | // Symbol rate : time for one symbol (secs) |
brunnobbco | 0:561d07a737bc | 721 | float rs = bw / (1 << _rf_settings.lora.datarate); |
brunnobbco | 0:561d07a737bc | 722 | float ts = 1 / rs; |
brunnobbco | 0:561d07a737bc | 723 | // time of preamble |
brunnobbco | 0:561d07a737bc | 724 | float tPreamble = (_rf_settings.lora.preamble_len + 4.25f) * ts; |
brunnobbco | 0:561d07a737bc | 725 | // Symbol length of payload and time |
brunnobbco | 0:561d07a737bc | 726 | float tmp = ceil((8 * pkt_len - 4 * _rf_settings.lora.datarate + 28 |
brunnobbco | 0:561d07a737bc | 727 | + 16 * _rf_settings.lora.crc_on |
brunnobbco | 0:561d07a737bc | 728 | - (_rf_settings.lora.fix_len ? 20 : 0)) |
brunnobbco | 0:561d07a737bc | 729 | / (float) (4 |
brunnobbco | 0:561d07a737bc | 730 | * (_rf_settings.lora.datarate |
brunnobbco | 0:561d07a737bc | 731 | - ((_rf_settings.lora.low_datarate_optimize > 0) |
brunnobbco | 0:561d07a737bc | 732 | ? 2 : 0)))) |
brunnobbco | 0:561d07a737bc | 733 | * (_rf_settings.lora.coderate + 4); |
brunnobbco | 0:561d07a737bc | 734 | float nPayload = 8 + ((tmp > 0) ? tmp : 0); |
brunnobbco | 0:561d07a737bc | 735 | float tPayload = nPayload * ts; |
brunnobbco | 0:561d07a737bc | 736 | // Time on air |
brunnobbco | 0:561d07a737bc | 737 | float tOnAir = tPreamble + tPayload; |
brunnobbco | 0:561d07a737bc | 738 | // return ms secs |
brunnobbco | 0:561d07a737bc | 739 | airTime = floor(tOnAir * 1000 + 0.999f); |
brunnobbco | 0:561d07a737bc | 740 | |
brunnobbco | 0:561d07a737bc | 741 | break; |
brunnobbco | 0:561d07a737bc | 742 | } |
brunnobbco | 0:561d07a737bc | 743 | |
brunnobbco | 0:561d07a737bc | 744 | return airTime; |
brunnobbco | 0:561d07a737bc | 745 | } |
brunnobbco | 0:561d07a737bc | 746 | |
brunnobbco | 0:561d07a737bc | 747 | /** |
brunnobbco | 0:561d07a737bc | 748 | * Prepares and sends the radio packet out in the air |
brunnobbco | 0:561d07a737bc | 749 | */ |
brunnobbco | 0:561d07a737bc | 750 | void SX1276_LoRaRadio::send(uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 751 | { |
brunnobbco | 0:561d07a737bc | 752 | uint32_t tx_timeout = 0; |
brunnobbco | 0:561d07a737bc | 753 | |
brunnobbco | 0:561d07a737bc | 754 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 755 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 756 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 757 | _rf_settings.fsk_packet_handler.size = size; |
brunnobbco | 0:561d07a737bc | 758 | |
brunnobbco | 0:561d07a737bc | 759 | if (_rf_settings.fsk.fix_len == false) { |
brunnobbco | 0:561d07a737bc | 760 | write_fifo((uint8_t*) &size, 1); |
brunnobbco | 0:561d07a737bc | 761 | } else { |
brunnobbco | 0:561d07a737bc | 762 | write_to_register(REG_PAYLOADLENGTH, size); |
brunnobbco | 0:561d07a737bc | 763 | } |
brunnobbco | 0:561d07a737bc | 764 | |
brunnobbco | 0:561d07a737bc | 765 | if ((size > 0) && (size <= 64)) { |
brunnobbco | 0:561d07a737bc | 766 | _rf_settings.fsk_packet_handler.chunk_size = size; |
brunnobbco | 0:561d07a737bc | 767 | } else { |
brunnobbco | 0:561d07a737bc | 768 | memcpy(_data_buffer, buffer, size); |
brunnobbco | 0:561d07a737bc | 769 | _rf_settings.fsk_packet_handler.chunk_size = 32; |
brunnobbco | 0:561d07a737bc | 770 | } |
brunnobbco | 0:561d07a737bc | 771 | |
brunnobbco | 0:561d07a737bc | 772 | // Write payload buffer |
brunnobbco | 0:561d07a737bc | 773 | write_fifo(buffer, _rf_settings.fsk_packet_handler.chunk_size); |
brunnobbco | 0:561d07a737bc | 774 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 775 | _rf_settings.fsk_packet_handler.chunk_size; |
brunnobbco | 0:561d07a737bc | 776 | tx_timeout = _rf_settings.fsk.tx_timeout; |
brunnobbco | 0:561d07a737bc | 777 | |
brunnobbco | 0:561d07a737bc | 778 | break; |
brunnobbco | 0:561d07a737bc | 779 | |
brunnobbco | 0:561d07a737bc | 780 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 781 | if (_rf_settings.lora.iq_inverted == true) { |
brunnobbco | 0:561d07a737bc | 782 | write_to_register(REG_LR_INVERTIQ, ((read_register(REG_LR_INVERTIQ) |
brunnobbco | 0:561d07a737bc | 783 | & RFLR_INVERTIQ_TX_MASK |
brunnobbco | 0:561d07a737bc | 784 | & RFLR_INVERTIQ_RX_MASK) |
brunnobbco | 0:561d07a737bc | 785 | | RFLR_INVERTIQ_RX_OFF |
brunnobbco | 0:561d07a737bc | 786 | | RFLR_INVERTIQ_TX_ON)); |
brunnobbco | 0:561d07a737bc | 787 | write_to_register( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON); |
brunnobbco | 0:561d07a737bc | 788 | } else { |
brunnobbco | 0:561d07a737bc | 789 | write_to_register(REG_LR_INVERTIQ, ((read_register( REG_LR_INVERTIQ) |
brunnobbco | 0:561d07a737bc | 790 | & RFLR_INVERTIQ_TX_MASK |
brunnobbco | 0:561d07a737bc | 791 | & RFLR_INVERTIQ_RX_MASK) |
brunnobbco | 0:561d07a737bc | 792 | | RFLR_INVERTIQ_RX_OFF |
brunnobbco | 0:561d07a737bc | 793 | | RFLR_INVERTIQ_TX_OFF)); |
brunnobbco | 0:561d07a737bc | 794 | write_to_register( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF); |
brunnobbco | 0:561d07a737bc | 795 | } |
brunnobbco | 0:561d07a737bc | 796 | |
brunnobbco | 0:561d07a737bc | 797 | _rf_settings.lora_packet_handler.size = size; |
brunnobbco | 0:561d07a737bc | 798 | |
brunnobbco | 0:561d07a737bc | 799 | // Initializes the payload size |
brunnobbco | 0:561d07a737bc | 800 | write_to_register(REG_LR_PAYLOADLENGTH, size); |
brunnobbco | 0:561d07a737bc | 801 | |
brunnobbco | 0:561d07a737bc | 802 | // Full buffer used for Tx |
brunnobbco | 0:561d07a737bc | 803 | write_to_register(REG_LR_FIFOTXBASEADDR, 0); |
brunnobbco | 0:561d07a737bc | 804 | write_to_register(REG_LR_FIFOADDRPTR, 0); |
brunnobbco | 0:561d07a737bc | 805 | |
brunnobbco | 0:561d07a737bc | 806 | // FIFO operations can not take place in Sleep mode |
brunnobbco | 0:561d07a737bc | 807 | if ((read_register( REG_OPMODE) & ~RF_OPMODE_MASK) == RF_OPMODE_SLEEP) { |
brunnobbco | 0:561d07a737bc | 808 | standby(); |
brunnobbco | 0:561d07a737bc | 809 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 810 | } |
brunnobbco | 0:561d07a737bc | 811 | // write_to_register payload buffer |
brunnobbco | 0:561d07a737bc | 812 | write_fifo(buffer, size); |
brunnobbco | 0:561d07a737bc | 813 | tx_timeout = _rf_settings.lora.tx_timeout; |
brunnobbco | 0:561d07a737bc | 814 | |
brunnobbco | 0:561d07a737bc | 815 | break; |
brunnobbco | 0:561d07a737bc | 816 | } |
brunnobbco | 0:561d07a737bc | 817 | |
brunnobbco | 0:561d07a737bc | 818 | transmit(tx_timeout); |
brunnobbco | 0:561d07a737bc | 819 | } |
brunnobbco | 0:561d07a737bc | 820 | |
brunnobbco | 0:561d07a737bc | 821 | /** |
brunnobbco | 0:561d07a737bc | 822 | * sets the radio module to sleep |
brunnobbco | 0:561d07a737bc | 823 | */ |
brunnobbco | 0:561d07a737bc | 824 | |
brunnobbco | 0:561d07a737bc | 825 | void SX1276_LoRaRadio::sleep() |
brunnobbco | 0:561d07a737bc | 826 | { |
brunnobbco | 0:561d07a737bc | 827 | // stop timers |
brunnobbco | 0:561d07a737bc | 828 | tx_timeout_timer.detach(); |
brunnobbco | 0:561d07a737bc | 829 | |
brunnobbco | 0:561d07a737bc | 830 | // put module in sleep mode |
brunnobbco | 0:561d07a737bc | 831 | set_operation_mode(RF_OPMODE_SLEEP); |
brunnobbco | 0:561d07a737bc | 832 | } |
brunnobbco | 0:561d07a737bc | 833 | |
brunnobbco | 0:561d07a737bc | 834 | /** |
brunnobbco | 0:561d07a737bc | 835 | * Put radio in Standby mode |
brunnobbco | 0:561d07a737bc | 836 | */ |
brunnobbco | 0:561d07a737bc | 837 | void SX1276_LoRaRadio::standby( void ) |
brunnobbco | 0:561d07a737bc | 838 | { |
brunnobbco | 0:561d07a737bc | 839 | tx_timeout_timer.detach(); |
brunnobbco | 0:561d07a737bc | 840 | |
brunnobbco | 0:561d07a737bc | 841 | set_operation_mode(RF_OPMODE_STANDBY); |
brunnobbco | 0:561d07a737bc | 842 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 843 | } |
brunnobbco | 0:561d07a737bc | 844 | |
brunnobbco | 0:561d07a737bc | 845 | /** |
brunnobbco | 0:561d07a737bc | 846 | * Sets the radio module in receive mode |
brunnobbco | 0:561d07a737bc | 847 | * |
brunnobbco | 0:561d07a737bc | 848 | * A DIO4 interrupt let's the state machine know that a preamble is detected |
brunnobbco | 0:561d07a737bc | 849 | * and finally a DIO0 interrupt let's the state machine know that a packet is |
brunnobbco | 0:561d07a737bc | 850 | * ready to be read from the FIFO |
brunnobbco | 0:561d07a737bc | 851 | */ |
brunnobbco | 0:561d07a737bc | 852 | void SX1276_LoRaRadio::receive(void) |
brunnobbco | 0:561d07a737bc | 853 | { |
brunnobbco | 0:561d07a737bc | 854 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 855 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 856 | |
brunnobbco | 0:561d07a737bc | 857 | // DIO0=PayloadReady/PacketSent |
brunnobbco | 0:561d07a737bc | 858 | // DIO1=FifoLevel |
brunnobbco | 0:561d07a737bc | 859 | // DIO2=RxTimeout |
brunnobbco | 0:561d07a737bc | 860 | // DIO3=FifoEmpty? |
brunnobbco | 0:561d07a737bc | 861 | // DIO4=PreambleDetect |
brunnobbco | 0:561d07a737bc | 862 | // DIO5=ModeReady? |
brunnobbco | 0:561d07a737bc | 863 | write_to_register(REG_DIOMAPPING1, (read_register( REG_DIOMAPPING1) |
brunnobbco | 0:561d07a737bc | 864 | & RF_DIOMAPPING1_DIO0_MASK |
brunnobbco | 0:561d07a737bc | 865 | & RF_DIOMAPPING1_DIO1_MASK |
brunnobbco | 0:561d07a737bc | 866 | & RF_DIOMAPPING1_DIO2_MASK) |
brunnobbco | 0:561d07a737bc | 867 | | RF_DIOMAPPING1_DIO0_00 |
brunnobbco | 0:561d07a737bc | 868 | | RF_DIOMAPPING1_DIO1_00 |
brunnobbco | 0:561d07a737bc | 869 | | RF_DIOMAPPING1_DIO2_10); |
brunnobbco | 0:561d07a737bc | 870 | |
brunnobbco | 0:561d07a737bc | 871 | write_to_register(REG_DIOMAPPING2, (read_register( REG_DIOMAPPING2) |
brunnobbco | 0:561d07a737bc | 872 | & RF_DIOMAPPING2_DIO4_MASK |
brunnobbco | 0:561d07a737bc | 873 | & RF_DIOMAPPING2_MAP_MASK) |
brunnobbco | 0:561d07a737bc | 874 | | RF_DIOMAPPING2_DIO4_11 |
brunnobbco | 0:561d07a737bc | 875 | | RF_DIOMAPPING2_MAP_PREAMBLEDETECT); |
brunnobbco | 0:561d07a737bc | 876 | |
brunnobbco | 0:561d07a737bc | 877 | _rf_settings.fsk_packet_handler.fifo_thresh = |
brunnobbco | 0:561d07a737bc | 878 | read_register(REG_FIFOTHRESH) & 0x3F; |
brunnobbco | 0:561d07a737bc | 879 | |
brunnobbco | 0:561d07a737bc | 880 | write_to_register(REG_RXCONFIG, RF_RXCONFIG_AFCAUTO_ON |
brunnobbco | 0:561d07a737bc | 881 | | RF_RXCONFIG_AGCAUTO_ON |
brunnobbco | 0:561d07a737bc | 882 | | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT); |
brunnobbco | 0:561d07a737bc | 883 | |
brunnobbco | 0:561d07a737bc | 884 | if (!_rf_settings.fsk.rx_continuous) { |
brunnobbco | 0:561d07a737bc | 885 | // the value for rx timeout in symbols cannot be more than 255 |
brunnobbco | 0:561d07a737bc | 886 | // as the preamble length is fixed. We assert here for quick |
brunnobbco | 0:561d07a737bc | 887 | // diagnostics |
brunnobbco | 0:561d07a737bc | 888 | MBED_ASSERT(_rf_settings.fsk.rx_single_timeout <= 255); |
brunnobbco | 0:561d07a737bc | 889 | write_to_register(REG_RXTIMEOUT2, _rf_settings.fsk.rx_single_timeout); |
brunnobbco | 0:561d07a737bc | 890 | write_to_register(REG_RXTIMEOUT3, 0x00); |
brunnobbco | 0:561d07a737bc | 891 | write_to_register(REG_RXTIMEOUT1, 0x00); |
brunnobbco | 0:561d07a737bc | 892 | } |
brunnobbco | 0:561d07a737bc | 893 | |
brunnobbco | 0:561d07a737bc | 894 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 895 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 896 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 897 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 898 | |
brunnobbco | 0:561d07a737bc | 899 | break; |
brunnobbco | 0:561d07a737bc | 900 | |
brunnobbco | 0:561d07a737bc | 901 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 902 | |
brunnobbco | 0:561d07a737bc | 903 | if (_rf_settings.lora.iq_inverted == true) { |
brunnobbco | 0:561d07a737bc | 904 | write_to_register(REG_LR_INVERTIQ, ((read_register( REG_LR_INVERTIQ) |
brunnobbco | 0:561d07a737bc | 905 | & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK) |
brunnobbco | 0:561d07a737bc | 906 | | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF)); |
brunnobbco | 0:561d07a737bc | 907 | write_to_register( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON); |
brunnobbco | 0:561d07a737bc | 908 | } else { |
brunnobbco | 0:561d07a737bc | 909 | write_to_register(REG_LR_INVERTIQ, ((read_register( REG_LR_INVERTIQ) |
brunnobbco | 0:561d07a737bc | 910 | & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK) |
brunnobbco | 0:561d07a737bc | 911 | | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF)); |
brunnobbco | 0:561d07a737bc | 912 | write_to_register( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF); |
brunnobbco | 0:561d07a737bc | 913 | } |
brunnobbco | 0:561d07a737bc | 914 | |
brunnobbco | 0:561d07a737bc | 915 | // ERRATA 2.3 - Receiver Spurious Reception of a LoRa Signal |
brunnobbco | 0:561d07a737bc | 916 | if (_rf_settings.lora.bandwidth < 9) { |
brunnobbco | 0:561d07a737bc | 917 | write_to_register(REG_LR_DETECTOPTIMIZE, |
brunnobbco | 0:561d07a737bc | 918 | read_register(REG_LR_DETECTOPTIMIZE) & 0x7F); |
brunnobbco | 0:561d07a737bc | 919 | write_to_register(REG_LR_TEST30, 0x00); |
brunnobbco | 0:561d07a737bc | 920 | switch (_rf_settings.lora.bandwidth) { |
brunnobbco | 0:561d07a737bc | 921 | case 0: // 7.8 kHz |
brunnobbco | 0:561d07a737bc | 922 | write_to_register( REG_LR_TEST2F, 0x48); |
brunnobbco | 0:561d07a737bc | 923 | set_channel(_rf_settings.channel + 7.81e3); |
brunnobbco | 0:561d07a737bc | 924 | break; |
brunnobbco | 0:561d07a737bc | 925 | case 1: // 10.4 kHz |
brunnobbco | 0:561d07a737bc | 926 | write_to_register( REG_LR_TEST2F, 0x44); |
brunnobbco | 0:561d07a737bc | 927 | set_channel(_rf_settings.channel + 10.42e3); |
brunnobbco | 0:561d07a737bc | 928 | break; |
brunnobbco | 0:561d07a737bc | 929 | case 2: // 15.6 kHz |
brunnobbco | 0:561d07a737bc | 930 | write_to_register( REG_LR_TEST2F, 0x44); |
brunnobbco | 0:561d07a737bc | 931 | set_channel(_rf_settings.channel + 15.62e3); |
brunnobbco | 0:561d07a737bc | 932 | break; |
brunnobbco | 0:561d07a737bc | 933 | case 3: // 20.8 kHz |
brunnobbco | 0:561d07a737bc | 934 | write_to_register( REG_LR_TEST2F, 0x44); |
brunnobbco | 0:561d07a737bc | 935 | set_channel(_rf_settings.channel + 20.83e3); |
brunnobbco | 0:561d07a737bc | 936 | break; |
brunnobbco | 0:561d07a737bc | 937 | case 4: // 31.2 kHz |
brunnobbco | 0:561d07a737bc | 938 | write_to_register( REG_LR_TEST2F, 0x44); |
brunnobbco | 0:561d07a737bc | 939 | set_channel(_rf_settings.channel + 31.25e3); |
brunnobbco | 0:561d07a737bc | 940 | break; |
brunnobbco | 0:561d07a737bc | 941 | case 5: // 41.4 kHz |
brunnobbco | 0:561d07a737bc | 942 | write_to_register( REG_LR_TEST2F, 0x44); |
brunnobbco | 0:561d07a737bc | 943 | set_channel(_rf_settings.channel + 41.67e3); |
brunnobbco | 0:561d07a737bc | 944 | break; |
brunnobbco | 0:561d07a737bc | 945 | case 6: // 62.5 kHz |
brunnobbco | 0:561d07a737bc | 946 | write_to_register( REG_LR_TEST2F, 0x40); |
brunnobbco | 0:561d07a737bc | 947 | break; |
brunnobbco | 0:561d07a737bc | 948 | case 7: // 125 kHz |
brunnobbco | 0:561d07a737bc | 949 | write_to_register( REG_LR_TEST2F, 0x40); |
brunnobbco | 0:561d07a737bc | 950 | break; |
brunnobbco | 0:561d07a737bc | 951 | case 8: // 250 kHz |
brunnobbco | 0:561d07a737bc | 952 | write_to_register( REG_LR_TEST2F, 0x40); |
brunnobbco | 0:561d07a737bc | 953 | break; |
brunnobbco | 0:561d07a737bc | 954 | } |
brunnobbco | 0:561d07a737bc | 955 | } else { |
brunnobbco | 0:561d07a737bc | 956 | write_to_register( REG_LR_DETECTOPTIMIZE, |
brunnobbco | 0:561d07a737bc | 957 | read_register( REG_LR_DETECTOPTIMIZE) | 0x80); |
brunnobbco | 0:561d07a737bc | 958 | } |
brunnobbco | 0:561d07a737bc | 959 | |
brunnobbco | 0:561d07a737bc | 960 | if (_rf_settings.lora.freq_hop_on == true) { |
brunnobbco | 0:561d07a737bc | 961 | write_to_register(REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_VALIDHEADER |
brunnobbco | 0:561d07a737bc | 962 | | RFLR_IRQFLAGS_TXDONE |
brunnobbco | 0:561d07a737bc | 963 | | RFLR_IRQFLAGS_CADDONE |
brunnobbco | 0:561d07a737bc | 964 | | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 965 | |
brunnobbco | 0:561d07a737bc | 966 | // DIO0=RxDone, DIO2=FhssChangeChannel |
brunnobbco | 0:561d07a737bc | 967 | write_to_register(REG_DIOMAPPING1, (read_register(REG_DIOMAPPING1) |
brunnobbco | 0:561d07a737bc | 968 | & RFLR_DIOMAPPING1_DIO0_MASK |
brunnobbco | 0:561d07a737bc | 969 | & RFLR_DIOMAPPING1_DIO2_MASK) |
brunnobbco | 0:561d07a737bc | 970 | | RFLR_DIOMAPPING1_DIO0_00 |
brunnobbco | 0:561d07a737bc | 971 | | RFLR_DIOMAPPING1_DIO2_00); |
brunnobbco | 0:561d07a737bc | 972 | } else { |
brunnobbco | 0:561d07a737bc | 973 | write_to_register(REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_VALIDHEADER |
brunnobbco | 0:561d07a737bc | 974 | | RFLR_IRQFLAGS_TXDONE |
brunnobbco | 0:561d07a737bc | 975 | | RFLR_IRQFLAGS_CADDONE |
brunnobbco | 0:561d07a737bc | 976 | | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |
brunnobbco | 0:561d07a737bc | 977 | | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 978 | |
brunnobbco | 0:561d07a737bc | 979 | // DIO0=RxDone |
brunnobbco | 0:561d07a737bc | 980 | write_to_register(REG_DIOMAPPING1, (read_register( REG_DIOMAPPING1) |
brunnobbco | 0:561d07a737bc | 981 | & RFLR_DIOMAPPING1_DIO0_MASK) |
brunnobbco | 0:561d07a737bc | 982 | | RFLR_DIOMAPPING1_DIO0_00); |
brunnobbco | 0:561d07a737bc | 983 | } |
brunnobbco | 0:561d07a737bc | 984 | write_to_register(REG_LR_FIFORXBASEADDR, 0); |
brunnobbco | 0:561d07a737bc | 985 | write_to_register(REG_LR_FIFOADDRPTR, 0); |
brunnobbco | 0:561d07a737bc | 986 | |
brunnobbco | 0:561d07a737bc | 987 | break; |
brunnobbco | 0:561d07a737bc | 988 | } |
brunnobbco | 0:561d07a737bc | 989 | |
brunnobbco | 0:561d07a737bc | 990 | memset(_data_buffer, 0, (size_t) MAX_DATA_BUFFER_SIZE_SX1276); |
brunnobbco | 0:561d07a737bc | 991 | |
brunnobbco | 0:561d07a737bc | 992 | _rf_settings.state = RF_RX_RUNNING; |
brunnobbco | 0:561d07a737bc | 993 | |
brunnobbco | 0:561d07a737bc | 994 | if (_rf_settings.modem == MODEM_FSK) { |
brunnobbco | 0:561d07a737bc | 995 | set_operation_mode(RF_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 996 | return; |
brunnobbco | 0:561d07a737bc | 997 | } |
brunnobbco | 0:561d07a737bc | 998 | |
brunnobbco | 0:561d07a737bc | 999 | // If mode is LoRa set mode |
brunnobbco | 0:561d07a737bc | 1000 | if (_rf_settings.lora.rx_continuous == true) { |
brunnobbco | 0:561d07a737bc | 1001 | set_operation_mode(RFLR_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 1002 | } else { |
brunnobbco | 0:561d07a737bc | 1003 | set_operation_mode(RFLR_OPMODE_RECEIVER_SINGLE); |
brunnobbco | 0:561d07a737bc | 1004 | } |
brunnobbco | 0:561d07a737bc | 1005 | } |
brunnobbco | 0:561d07a737bc | 1006 | |
brunnobbco | 0:561d07a737bc | 1007 | |
brunnobbco | 0:561d07a737bc | 1008 | /** |
brunnobbco | 0:561d07a737bc | 1009 | * Perform carrier sensing |
brunnobbco | 0:561d07a737bc | 1010 | * |
brunnobbco | 0:561d07a737bc | 1011 | * Checks for a certain time if the RSSI is above a given threshold. |
brunnobbco | 0:561d07a737bc | 1012 | * This threshold determines if there is already a transmission going on |
brunnobbco | 0:561d07a737bc | 1013 | * in the channel or not. |
brunnobbco | 0:561d07a737bc | 1014 | * |
brunnobbco | 0:561d07a737bc | 1015 | */ |
brunnobbco | 0:561d07a737bc | 1016 | bool SX1276_LoRaRadio::perform_carrier_sense(radio_modems_t modem, |
brunnobbco | 0:561d07a737bc | 1017 | uint32_t freq, |
brunnobbco | 0:561d07a737bc | 1018 | int16_t rssi_threshold, |
brunnobbco | 0:561d07a737bc | 1019 | uint32_t max_carrier_sense_time) |
brunnobbco | 0:561d07a737bc | 1020 | { |
brunnobbco | 0:561d07a737bc | 1021 | bool status = true; |
brunnobbco | 0:561d07a737bc | 1022 | int16_t rssi = 0; |
brunnobbco | 0:561d07a737bc | 1023 | |
brunnobbco | 0:561d07a737bc | 1024 | set_modem(modem); |
brunnobbco | 0:561d07a737bc | 1025 | set_channel(freq); |
brunnobbco | 0:561d07a737bc | 1026 | set_operation_mode(RF_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 1027 | |
brunnobbco | 0:561d07a737bc | 1028 | // hold on a bit, radio turn-around time |
brunnobbco | 0:561d07a737bc | 1029 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 1030 | |
brunnobbco | 0:561d07a737bc | 1031 | Timer elapsed_time; |
brunnobbco | 0:561d07a737bc | 1032 | elapsed_time.start(); |
brunnobbco | 0:561d07a737bc | 1033 | |
brunnobbco | 0:561d07a737bc | 1034 | // Perform carrier sense for maxCarrierSenseTime |
brunnobbco | 0:561d07a737bc | 1035 | while (elapsed_time.read_ms() < (int)max_carrier_sense_time) { |
brunnobbco | 0:561d07a737bc | 1036 | rssi = get_rssi(modem); |
brunnobbco | 0:561d07a737bc | 1037 | |
brunnobbco | 0:561d07a737bc | 1038 | if (rssi > rssi_threshold) { |
brunnobbco | 0:561d07a737bc | 1039 | status = false; |
brunnobbco | 0:561d07a737bc | 1040 | break; |
brunnobbco | 0:561d07a737bc | 1041 | } |
brunnobbco | 0:561d07a737bc | 1042 | } |
brunnobbco | 0:561d07a737bc | 1043 | |
brunnobbco | 0:561d07a737bc | 1044 | sleep(); |
brunnobbco | 0:561d07a737bc | 1045 | return status; |
brunnobbco | 0:561d07a737bc | 1046 | } |
brunnobbco | 0:561d07a737bc | 1047 | |
brunnobbco | 0:561d07a737bc | 1048 | /** |
brunnobbco | 0:561d07a737bc | 1049 | * TODO: Making sure if this API is valid only for LoRa modulation ? |
brunnobbco | 0:561d07a737bc | 1050 | * |
brunnobbco | 0:561d07a737bc | 1051 | * Indicates if the node is part of a private or public network |
brunnobbco | 0:561d07a737bc | 1052 | */ |
brunnobbco | 0:561d07a737bc | 1053 | void SX1276_LoRaRadio::set_public_network(bool enable) |
brunnobbco | 0:561d07a737bc | 1054 | { |
brunnobbco | 0:561d07a737bc | 1055 | set_modem(MODEM_LORA); |
brunnobbco | 0:561d07a737bc | 1056 | |
brunnobbco | 0:561d07a737bc | 1057 | _rf_settings.lora.public_network = enable; |
brunnobbco | 0:561d07a737bc | 1058 | if (enable == true) { |
brunnobbco | 0:561d07a737bc | 1059 | // Change lora modem SyncWord |
brunnobbco | 0:561d07a737bc | 1060 | write_to_register(REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD); |
brunnobbco | 0:561d07a737bc | 1061 | } else { |
brunnobbco | 0:561d07a737bc | 1062 | // Change lora modem SyncWord |
brunnobbco | 0:561d07a737bc | 1063 | write_to_register(REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD); |
brunnobbco | 0:561d07a737bc | 1064 | } |
brunnobbco | 0:561d07a737bc | 1065 | } |
brunnobbco | 0:561d07a737bc | 1066 | |
brunnobbco | 0:561d07a737bc | 1067 | /** |
brunnobbco | 0:561d07a737bc | 1068 | * Puts a limit on the size of payload the module can handle |
brunnobbco | 0:561d07a737bc | 1069 | * By default it is MAX, i.e., 256 bytes |
brunnobbco | 0:561d07a737bc | 1070 | */ |
brunnobbco | 0:561d07a737bc | 1071 | void SX1276_LoRaRadio::set_max_payload_length(radio_modems_t modem, uint8_t max) |
brunnobbco | 0:561d07a737bc | 1072 | { |
brunnobbco | 0:561d07a737bc | 1073 | set_modem(modem); |
brunnobbco | 0:561d07a737bc | 1074 | |
brunnobbco | 0:561d07a737bc | 1075 | switch (modem) { |
brunnobbco | 0:561d07a737bc | 1076 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1077 | if (_rf_settings.fsk.fix_len == false) { |
brunnobbco | 0:561d07a737bc | 1078 | write_to_register(REG_PAYLOADLENGTH, max); |
brunnobbco | 0:561d07a737bc | 1079 | } |
brunnobbco | 0:561d07a737bc | 1080 | break; |
brunnobbco | 0:561d07a737bc | 1081 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1082 | write_to_register(REG_LR_PAYLOADMAXLENGTH, max); |
brunnobbco | 0:561d07a737bc | 1083 | break; |
brunnobbco | 0:561d07a737bc | 1084 | } |
brunnobbco | 0:561d07a737bc | 1085 | } |
brunnobbco | 0:561d07a737bc | 1086 | |
brunnobbco | 0:561d07a737bc | 1087 | /** |
brunnobbco | 0:561d07a737bc | 1088 | * Channel Activity detection (can be done only in LoRa mode) |
brunnobbco | 0:561d07a737bc | 1089 | * |
brunnobbco | 0:561d07a737bc | 1090 | * If any activity on the channel is detected, an interrupt is asserted on |
brunnobbco | 0:561d07a737bc | 1091 | * DIO3. A callback will be generated to the stack/application upon the |
brunnobbco | 0:561d07a737bc | 1092 | * assertion of DIO3. |
brunnobbco | 0:561d07a737bc | 1093 | */ |
brunnobbco | 0:561d07a737bc | 1094 | void SX1276_LoRaRadio::start_cad() |
brunnobbco | 0:561d07a737bc | 1095 | { |
brunnobbco | 0:561d07a737bc | 1096 | uint8_t reg_val; |
brunnobbco | 0:561d07a737bc | 1097 | |
brunnobbco | 0:561d07a737bc | 1098 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 1099 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1100 | break; |
brunnobbco | 0:561d07a737bc | 1101 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1102 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 1103 | RFLR_IRQFLAGS_RXTIMEOUT | |
brunnobbco | 0:561d07a737bc | 1104 | RFLR_IRQFLAGS_RXDONE | |
brunnobbco | 0:561d07a737bc | 1105 | RFLR_IRQFLAGS_PAYLOADCRCERROR | |
brunnobbco | 0:561d07a737bc | 1106 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 1107 | RFLR_IRQFLAGS_TXDONE | |
brunnobbco | 0:561d07a737bc | 1108 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL); |
brunnobbco | 0:561d07a737bc | 1109 | |
brunnobbco | 0:561d07a737bc | 1110 | // DIO3=CADDone |
brunnobbco | 0:561d07a737bc | 1111 | reg_val = read_register(REG_DIOMAPPING1); |
brunnobbco | 0:561d07a737bc | 1112 | write_to_register(REG_DIOMAPPING1, (reg_val & |
brunnobbco | 0:561d07a737bc | 1113 | RFLR_DIOMAPPING1_DIO3_MASK) | |
brunnobbco | 0:561d07a737bc | 1114 | RFLR_DIOMAPPING1_DIO3_00); |
brunnobbco | 0:561d07a737bc | 1115 | |
brunnobbco | 0:561d07a737bc | 1116 | set_operation_mode(RFLR_OPMODE_CAD); |
brunnobbco | 0:561d07a737bc | 1117 | |
brunnobbco | 0:561d07a737bc | 1118 | _rf_settings.state = RF_CAD; |
brunnobbco | 0:561d07a737bc | 1119 | |
brunnobbco | 0:561d07a737bc | 1120 | break; |
brunnobbco | 0:561d07a737bc | 1121 | default: |
brunnobbco | 0:561d07a737bc | 1122 | break; |
brunnobbco | 0:561d07a737bc | 1123 | } |
brunnobbco | 0:561d07a737bc | 1124 | } |
brunnobbco | 0:561d07a737bc | 1125 | |
brunnobbco | 0:561d07a737bc | 1126 | /** |
brunnobbco | 0:561d07a737bc | 1127 | * Set transmission in continuous wave mode |
brunnobbco | 0:561d07a737bc | 1128 | */ |
brunnobbco | 0:561d07a737bc | 1129 | void SX1276_LoRaRadio::set_tx_continuous_wave(uint32_t freq, int8_t power, |
brunnobbco | 0:561d07a737bc | 1130 | uint16_t time) |
brunnobbco | 0:561d07a737bc | 1131 | { |
brunnobbco | 0:561d07a737bc | 1132 | uint8_t reg_val; |
brunnobbco | 0:561d07a737bc | 1133 | |
brunnobbco | 0:561d07a737bc | 1134 | set_channel(freq); |
brunnobbco | 0:561d07a737bc | 1135 | set_tx_config(MODEM_FSK, power, 0, 0, 4800, 0, 5, false, false, 0, 0, 0, time * 1000); |
brunnobbco | 0:561d07a737bc | 1136 | reg_val = read_register(REG_PACKETCONFIG2); |
brunnobbco | 0:561d07a737bc | 1137 | |
brunnobbco | 0:561d07a737bc | 1138 | write_to_register( REG_PACKETCONFIG2, (reg_val & RF_PACKETCONFIG2_DATAMODE_MASK ) ); |
brunnobbco | 0:561d07a737bc | 1139 | // Disable radio interrupts |
brunnobbco | 0:561d07a737bc | 1140 | write_to_register( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 | RF_DIOMAPPING1_DIO1_11 ); |
brunnobbco | 0:561d07a737bc | 1141 | write_to_register( REG_DIOMAPPING2, RF_DIOMAPPING2_DIO4_10 | RF_DIOMAPPING2_DIO5_10 ); |
brunnobbco | 0:561d07a737bc | 1142 | |
brunnobbco | 0:561d07a737bc | 1143 | _rf_settings.state = RF_TX_RUNNING; |
brunnobbco | 0:561d07a737bc | 1144 | tx_timeout_timer.attach_us(callback(this, &SX1276_LoRaRadio::timeout_irq_isr), time * 1000000); |
brunnobbco | 0:561d07a737bc | 1145 | set_operation_mode(RF_OPMODE_TRANSMITTER); |
brunnobbco | 0:561d07a737bc | 1146 | } |
brunnobbco | 0:561d07a737bc | 1147 | |
brunnobbco | 0:561d07a737bc | 1148 | /***************************************************************************** |
brunnobbco | 0:561d07a737bc | 1149 | * Private APIs * |
brunnobbco | 0:561d07a737bc | 1150 | ****************************************************************************/ |
brunnobbco | 0:561d07a737bc | 1151 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1152 | /** |
brunnobbco | 0:561d07a737bc | 1153 | * Thread task handling IRQs |
brunnobbco | 0:561d07a737bc | 1154 | */ |
brunnobbco | 0:561d07a737bc | 1155 | void SX1276_LoRaRadio::rf_irq_task(void) |
brunnobbco | 0:561d07a737bc | 1156 | { |
brunnobbco | 0:561d07a737bc | 1157 | for (;;) { |
brunnobbco | 0:561d07a737bc | 1158 | uint32_t flags = ThisThread::flags_wait_any(0x7FFFFFFF); |
brunnobbco | 0:561d07a737bc | 1159 | |
brunnobbco | 0:561d07a737bc | 1160 | lock(); |
brunnobbco | 0:561d07a737bc | 1161 | if (flags & SIG_DIO0) { |
brunnobbco | 0:561d07a737bc | 1162 | handle_dio0_irq(); |
brunnobbco | 0:561d07a737bc | 1163 | } |
brunnobbco | 0:561d07a737bc | 1164 | if (flags & SIG_DIO1) { |
brunnobbco | 0:561d07a737bc | 1165 | handle_dio1_irq(); |
brunnobbco | 0:561d07a737bc | 1166 | } |
brunnobbco | 0:561d07a737bc | 1167 | if (flags & SIG_DIO2) { |
brunnobbco | 0:561d07a737bc | 1168 | handle_dio2_irq(); |
brunnobbco | 0:561d07a737bc | 1169 | } |
brunnobbco | 0:561d07a737bc | 1170 | if (flags & SIG_DIO3) { |
brunnobbco | 0:561d07a737bc | 1171 | handle_dio3_irq(); |
brunnobbco | 0:561d07a737bc | 1172 | } |
brunnobbco | 0:561d07a737bc | 1173 | if (flags & SIG_DIO4) { |
brunnobbco | 0:561d07a737bc | 1174 | handle_dio4_irq(); |
brunnobbco | 0:561d07a737bc | 1175 | } |
brunnobbco | 0:561d07a737bc | 1176 | if (flags & SIG_DIO5) { |
brunnobbco | 0:561d07a737bc | 1177 | handle_dio5_irq(); |
brunnobbco | 0:561d07a737bc | 1178 | } |
brunnobbco | 0:561d07a737bc | 1179 | if (flags & SIG_TIMOUT) { |
brunnobbco | 0:561d07a737bc | 1180 | handle_timeout_irq(); |
brunnobbco | 0:561d07a737bc | 1181 | } |
brunnobbco | 0:561d07a737bc | 1182 | unlock(); |
brunnobbco | 0:561d07a737bc | 1183 | } |
brunnobbco | 0:561d07a737bc | 1184 | } |
brunnobbco | 0:561d07a737bc | 1185 | #endif |
brunnobbco | 0:561d07a737bc | 1186 | |
brunnobbco | 0:561d07a737bc | 1187 | /** |
brunnobbco | 0:561d07a737bc | 1188 | * Writes a single byte to a given register |
brunnobbco | 0:561d07a737bc | 1189 | */ |
brunnobbco | 0:561d07a737bc | 1190 | void SX1276_LoRaRadio::write_to_register(uint8_t addr, uint8_t data) |
brunnobbco | 0:561d07a737bc | 1191 | { |
brunnobbco | 0:561d07a737bc | 1192 | write_to_register(addr, &data, 1); |
brunnobbco | 0:561d07a737bc | 1193 | } |
brunnobbco | 0:561d07a737bc | 1194 | |
brunnobbco | 0:561d07a737bc | 1195 | /** |
brunnobbco | 0:561d07a737bc | 1196 | * Writes multiple bytes to a given register |
brunnobbco | 0:561d07a737bc | 1197 | */ |
brunnobbco | 0:561d07a737bc | 1198 | void SX1276_LoRaRadio::write_to_register(uint8_t addr, uint8_t *data, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1199 | { |
brunnobbco | 0:561d07a737bc | 1200 | // set chip-select low |
brunnobbco | 0:561d07a737bc | 1201 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 1202 | |
brunnobbco | 0:561d07a737bc | 1203 | // set write command |
brunnobbco | 0:561d07a737bc | 1204 | _spi.write(addr | SPI_WRITE_CMD); |
brunnobbco | 0:561d07a737bc | 1205 | |
brunnobbco | 0:561d07a737bc | 1206 | // write data |
brunnobbco | 0:561d07a737bc | 1207 | for (uint8_t i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 1208 | _spi.write(data[i]); |
brunnobbco | 0:561d07a737bc | 1209 | } |
brunnobbco | 0:561d07a737bc | 1210 | |
brunnobbco | 0:561d07a737bc | 1211 | // set chip-select high |
brunnobbco | 0:561d07a737bc | 1212 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 1213 | } |
brunnobbco | 0:561d07a737bc | 1214 | |
brunnobbco | 0:561d07a737bc | 1215 | /** |
brunnobbco | 0:561d07a737bc | 1216 | * Reads the value of a single register |
brunnobbco | 0:561d07a737bc | 1217 | */ |
brunnobbco | 0:561d07a737bc | 1218 | uint8_t SX1276_LoRaRadio::read_register(uint8_t addr) |
brunnobbco | 0:561d07a737bc | 1219 | { |
brunnobbco | 0:561d07a737bc | 1220 | uint8_t data; |
brunnobbco | 0:561d07a737bc | 1221 | read_register(addr, &data, 1); |
brunnobbco | 0:561d07a737bc | 1222 | return data; |
brunnobbco | 0:561d07a737bc | 1223 | } |
brunnobbco | 0:561d07a737bc | 1224 | |
brunnobbco | 0:561d07a737bc | 1225 | /** |
brunnobbco | 0:561d07a737bc | 1226 | * Reads multiple values from a given register |
brunnobbco | 0:561d07a737bc | 1227 | */ |
brunnobbco | 0:561d07a737bc | 1228 | void SX1276_LoRaRadio::read_register(uint8_t addr, uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1229 | { |
brunnobbco | 0:561d07a737bc | 1230 | // set chip-select low |
brunnobbco | 0:561d07a737bc | 1231 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 1232 | |
brunnobbco | 0:561d07a737bc | 1233 | // set read command |
brunnobbco | 0:561d07a737bc | 1234 | _spi.write(addr & SPI_READ_CMD); |
brunnobbco | 0:561d07a737bc | 1235 | |
brunnobbco | 0:561d07a737bc | 1236 | // read buffers |
brunnobbco | 0:561d07a737bc | 1237 | for (uint8_t i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 1238 | buffer[i] = _spi.write(0); |
brunnobbco | 0:561d07a737bc | 1239 | } |
brunnobbco | 0:561d07a737bc | 1240 | |
brunnobbco | 0:561d07a737bc | 1241 | // set chip-select high |
brunnobbco | 0:561d07a737bc | 1242 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 1243 | } |
brunnobbco | 0:561d07a737bc | 1244 | |
brunnobbco | 0:561d07a737bc | 1245 | /** |
brunnobbco | 0:561d07a737bc | 1246 | * Writes to FIIO provided by the chip |
brunnobbco | 0:561d07a737bc | 1247 | */ |
brunnobbco | 0:561d07a737bc | 1248 | void SX1276_LoRaRadio::write_fifo(uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1249 | { |
brunnobbco | 0:561d07a737bc | 1250 | write_to_register(0, buffer, size); |
brunnobbco | 0:561d07a737bc | 1251 | } |
brunnobbco | 0:561d07a737bc | 1252 | |
brunnobbco | 0:561d07a737bc | 1253 | /** |
brunnobbco | 0:561d07a737bc | 1254 | * Reads from the FIFO provided by the chip |
brunnobbco | 0:561d07a737bc | 1255 | */ |
brunnobbco | 0:561d07a737bc | 1256 | void SX1276_LoRaRadio::read_fifo(uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1257 | { |
brunnobbco | 0:561d07a737bc | 1258 | read_register(0, buffer, size); |
brunnobbco | 0:561d07a737bc | 1259 | } |
brunnobbco | 0:561d07a737bc | 1260 | |
brunnobbco | 0:561d07a737bc | 1261 | /** |
brunnobbco | 0:561d07a737bc | 1262 | * Sets up operation mode |
brunnobbco | 0:561d07a737bc | 1263 | */ |
brunnobbco | 0:561d07a737bc | 1264 | void SX1276_LoRaRadio::set_operation_mode(uint8_t mode) |
brunnobbco | 0:561d07a737bc | 1265 | { |
brunnobbco | 0:561d07a737bc | 1266 | if (mode == RF_OPMODE_SLEEP) { |
brunnobbco | 0:561d07a737bc | 1267 | set_low_power_mode(); |
brunnobbco | 0:561d07a737bc | 1268 | } else { |
brunnobbco | 0:561d07a737bc | 1269 | set_low_power_mode(); |
brunnobbco | 0:561d07a737bc | 1270 | set_antenna_switch(mode); |
brunnobbco | 0:561d07a737bc | 1271 | } |
brunnobbco | 0:561d07a737bc | 1272 | |
brunnobbco | 0:561d07a737bc | 1273 | write_to_register(REG_OPMODE, (read_register(REG_OPMODE) & RF_OPMODE_MASK) | mode); |
brunnobbco | 0:561d07a737bc | 1274 | } |
brunnobbco | 0:561d07a737bc | 1275 | |
brunnobbco | 0:561d07a737bc | 1276 | /** |
brunnobbco | 0:561d07a737bc | 1277 | * Sets the modem type to use |
brunnobbco | 0:561d07a737bc | 1278 | * |
brunnobbco | 0:561d07a737bc | 1279 | * At initialization FSK is chosen. Later stack or application |
brunnobbco | 0:561d07a737bc | 1280 | * can choose to change. |
brunnobbco | 0:561d07a737bc | 1281 | */ |
brunnobbco | 0:561d07a737bc | 1282 | void SX1276_LoRaRadio::set_modem(uint8_t modem ) |
brunnobbco | 0:561d07a737bc | 1283 | { |
brunnobbco | 0:561d07a737bc | 1284 | if ((read_register(REG_OPMODE) & RFLR_OPMODE_LONGRANGEMODE_ON) != 0 ) { |
brunnobbco | 0:561d07a737bc | 1285 | _rf_settings.modem = MODEM_LORA; |
brunnobbco | 0:561d07a737bc | 1286 | } else { |
brunnobbco | 0:561d07a737bc | 1287 | _rf_settings.modem = MODEM_FSK; |
brunnobbco | 0:561d07a737bc | 1288 | } |
brunnobbco | 0:561d07a737bc | 1289 | |
brunnobbco | 0:561d07a737bc | 1290 | if(_rf_settings.modem == modem ) { |
brunnobbco | 0:561d07a737bc | 1291 | // if the modem is already set |
brunnobbco | 0:561d07a737bc | 1292 | return; |
brunnobbco | 0:561d07a737bc | 1293 | } |
brunnobbco | 0:561d07a737bc | 1294 | |
brunnobbco | 0:561d07a737bc | 1295 | _rf_settings.modem = modem; |
brunnobbco | 0:561d07a737bc | 1296 | |
brunnobbco | 0:561d07a737bc | 1297 | switch(_rf_settings.modem) |
brunnobbco | 0:561d07a737bc | 1298 | { |
brunnobbco | 0:561d07a737bc | 1299 | default: |
brunnobbco | 0:561d07a737bc | 1300 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1301 | // before changing modem mode, put the module to sleep |
brunnobbco | 0:561d07a737bc | 1302 | sleep(); |
brunnobbco | 0:561d07a737bc | 1303 | write_to_register(REG_OPMODE, (read_register(REG_OPMODE) & RFLR_OPMODE_LONGRANGEMODE_MASK) |
brunnobbco | 0:561d07a737bc | 1304 | | RFLR_OPMODE_LONGRANGEMODE_OFF); |
brunnobbco | 0:561d07a737bc | 1305 | |
brunnobbco | 0:561d07a737bc | 1306 | // Datasheet Tables 28, 29 DIO mapping |
brunnobbco | 0:561d07a737bc | 1307 | write_to_register(REG_DIOMAPPING1, 0x00); // sets DIO0-DI03 in default mode |
brunnobbco | 0:561d07a737bc | 1308 | write_to_register(REG_DIOMAPPING2, 0x30); // bits 4-5 are turned on i.e., |
brunnobbco | 0:561d07a737bc | 1309 | // DIO5 and DIO4=ModeReady |
brunnobbco | 0:561d07a737bc | 1310 | break; |
brunnobbco | 0:561d07a737bc | 1311 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1312 | sleep(); |
brunnobbco | 0:561d07a737bc | 1313 | write_to_register(REG_OPMODE, (read_register(REG_OPMODE) & RFLR_OPMODE_LONGRANGEMODE_MASK) |
brunnobbco | 0:561d07a737bc | 1314 | | RFLR_OPMODE_LONGRANGEMODE_ON); |
brunnobbco | 0:561d07a737bc | 1315 | |
brunnobbco | 0:561d07a737bc | 1316 | // Datasheet Tables 17 DIO mapping for LoRa |
brunnobbco | 0:561d07a737bc | 1317 | // set to defaults |
brunnobbco | 0:561d07a737bc | 1318 | write_to_register(REG_DIOMAPPING1, 0x00); // DIO0 - DIO3 defaults |
brunnobbco | 0:561d07a737bc | 1319 | write_to_register(REG_DIOMAPPING2, 0x00); // DIO4 - DIO5 defaults |
brunnobbco | 0:561d07a737bc | 1320 | |
brunnobbco | 0:561d07a737bc | 1321 | break; |
brunnobbco | 0:561d07a737bc | 1322 | } |
brunnobbco | 0:561d07a737bc | 1323 | } |
brunnobbco | 0:561d07a737bc | 1324 | |
brunnobbco | 0:561d07a737bc | 1325 | /** |
brunnobbco | 0:561d07a737bc | 1326 | * Set the radio module variant |
brunnobbco | 0:561d07a737bc | 1327 | */ |
brunnobbco | 0:561d07a737bc | 1328 | void SX1276_LoRaRadio::set_sx1276_variant_type() |
brunnobbco | 0:561d07a737bc | 1329 | { |
brunnobbco | 0:561d07a737bc | 1330 | if (_rf_ctrls.ant_switch != NC) { |
brunnobbco | 0:561d07a737bc | 1331 | _ant_switch.input(); |
brunnobbco | 0:561d07a737bc | 1332 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 1333 | if (_ant_switch == 1) { |
brunnobbco | 0:561d07a737bc | 1334 | radio_variant = SX1276MB1LAS; |
brunnobbco | 0:561d07a737bc | 1335 | } else { |
brunnobbco | 0:561d07a737bc | 1336 | radio_variant = SX1276MB1MAS; |
brunnobbco | 0:561d07a737bc | 1337 | } |
brunnobbco | 0:561d07a737bc | 1338 | _ant_switch.output(); |
brunnobbco | 0:561d07a737bc | 1339 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 1340 | } else { |
brunnobbco | 0:561d07a737bc | 1341 | radio_variant = MBED_CONF_SX1276_LORA_DRIVER_RADIO_VARIANT; |
brunnobbco | 0:561d07a737bc | 1342 | } |
brunnobbco | 0:561d07a737bc | 1343 | } |
brunnobbco | 0:561d07a737bc | 1344 | |
brunnobbco | 0:561d07a737bc | 1345 | /** |
brunnobbco | 0:561d07a737bc | 1346 | * Sets up frequency for SPI module |
brunnobbco | 0:561d07a737bc | 1347 | * Reference DataSheet: 4.3 SPI Interface |
brunnobbco | 0:561d07a737bc | 1348 | */ |
brunnobbco | 0:561d07a737bc | 1349 | void SX1276_LoRaRadio::setup_spi() |
brunnobbco | 0:561d07a737bc | 1350 | { |
brunnobbco | 0:561d07a737bc | 1351 | // SPI bus frequency |
brunnobbco | 0:561d07a737bc | 1352 | uint32_t spi_freq = SPI_FREQUENCY; |
brunnobbco | 0:561d07a737bc | 1353 | |
brunnobbco | 0:561d07a737bc | 1354 | // Hold chip-select high |
brunnobbco | 0:561d07a737bc | 1355 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 1356 | _spi.format(8, 0); |
brunnobbco | 0:561d07a737bc | 1357 | |
brunnobbco | 0:561d07a737bc | 1358 | #if defined (TARGET_KL25Z) |
brunnobbco | 0:561d07a737bc | 1359 | //bus-clock frequency is halved -> double the SPI frequency to compensate |
brunnobbco | 0:561d07a737bc | 1360 | _spi.frequency(spi_freq * 2); |
brunnobbco | 0:561d07a737bc | 1361 | #else |
brunnobbco | 0:561d07a737bc | 1362 | // otherwise use default SPI frequency which is 8 MHz |
brunnobbco | 0:561d07a737bc | 1363 | _spi.frequency(spi_freq); |
brunnobbco | 0:561d07a737bc | 1364 | #endif |
brunnobbco | 0:561d07a737bc | 1365 | // 100 us wait to settle down |
brunnobbco | 0:561d07a737bc | 1366 | wait(0.1); |
brunnobbco | 0:561d07a737bc | 1367 | } |
brunnobbco | 0:561d07a737bc | 1368 | |
brunnobbco | 0:561d07a737bc | 1369 | /** |
brunnobbco | 0:561d07a737bc | 1370 | * Sets the radio registers to defaults |
brunnobbco | 0:561d07a737bc | 1371 | */ |
brunnobbco | 0:561d07a737bc | 1372 | void SX1276_LoRaRadio::setup_registers() |
brunnobbco | 0:561d07a737bc | 1373 | { |
brunnobbco | 0:561d07a737bc | 1374 | for (unsigned int i = 0; i < sizeof(radio_reg_init) / sizeof(radio_registers_t); i++) { |
brunnobbco | 0:561d07a737bc | 1375 | set_modem(radio_reg_init[i].modem); |
brunnobbco | 0:561d07a737bc | 1376 | write_to_register(radio_reg_init[i].addr, radio_reg_init[i].value); |
brunnobbco | 0:561d07a737bc | 1377 | } |
brunnobbco | 0:561d07a737bc | 1378 | } |
brunnobbco | 0:561d07a737bc | 1379 | |
brunnobbco | 0:561d07a737bc | 1380 | /** |
brunnobbco | 0:561d07a737bc | 1381 | * Performs the Rx chain calibration for LF and HF bands |
brunnobbco | 0:561d07a737bc | 1382 | * |
brunnobbco | 0:561d07a737bc | 1383 | * Must be called just after the reset so all registers are at their |
brunnobbco | 0:561d07a737bc | 1384 | * default values. |
brunnobbco | 0:561d07a737bc | 1385 | */ |
brunnobbco | 0:561d07a737bc | 1386 | void SX1276_LoRaRadio::rx_chain_calibration(void) |
brunnobbco | 0:561d07a737bc | 1387 | { |
brunnobbco | 0:561d07a737bc | 1388 | uint8_t regPaConfigInitVal; |
brunnobbco | 0:561d07a737bc | 1389 | uint32_t initialFreq; |
brunnobbco | 0:561d07a737bc | 1390 | |
brunnobbco | 0:561d07a737bc | 1391 | // Save context |
brunnobbco | 0:561d07a737bc | 1392 | regPaConfigInitVal = read_register( REG_PACONFIG ); |
brunnobbco | 0:561d07a737bc | 1393 | initialFreq = (float) (((uint32_t) this->read_register(REG_FRFMSB) << 16) | |
brunnobbco | 0:561d07a737bc | 1394 | ((uint32_t) this->read_register(REG_FRFMID) << 8 ) | |
brunnobbco | 0:561d07a737bc | 1395 | ((uint32_t)this->read_register(REG_FRFLSB))) * (float) FREQ_STEP; |
brunnobbco | 0:561d07a737bc | 1396 | |
brunnobbco | 0:561d07a737bc | 1397 | // Cut the PA just in case, RFO output, power = -1 dBm |
brunnobbco | 0:561d07a737bc | 1398 | write_to_register(REG_PACONFIG, 0x00); |
brunnobbco | 0:561d07a737bc | 1399 | |
brunnobbco | 0:561d07a737bc | 1400 | // Launch Rx chain calibration for LF band |
brunnobbco | 0:561d07a737bc | 1401 | write_to_register (REG_IMAGECAL, (read_register(REG_IMAGECAL) |
brunnobbco | 0:561d07a737bc | 1402 | & RF_IMAGECAL_IMAGECAL_MASK) |
brunnobbco | 0:561d07a737bc | 1403 | | RF_IMAGECAL_IMAGECAL_START); |
brunnobbco | 0:561d07a737bc | 1404 | while((read_register(REG_IMAGECAL) & RF_IMAGECAL_IMAGECAL_RUNNING ) |
brunnobbco | 0:561d07a737bc | 1405 | == RF_IMAGECAL_IMAGECAL_RUNNING ) |
brunnobbco | 0:561d07a737bc | 1406 | { |
brunnobbco | 0:561d07a737bc | 1407 | } |
brunnobbco | 0:561d07a737bc | 1408 | |
brunnobbco | 0:561d07a737bc | 1409 | // Sets a Frequency in HF band |
brunnobbco | 0:561d07a737bc | 1410 | set_channel(868000000); |
brunnobbco | 0:561d07a737bc | 1411 | |
brunnobbco | 0:561d07a737bc | 1412 | // Launch Rx chain calibration for HF band |
brunnobbco | 0:561d07a737bc | 1413 | write_to_register (REG_IMAGECAL, (read_register(REG_IMAGECAL) |
brunnobbco | 0:561d07a737bc | 1414 | & RF_IMAGECAL_IMAGECAL_MASK ) |
brunnobbco | 0:561d07a737bc | 1415 | | RF_IMAGECAL_IMAGECAL_START ); |
brunnobbco | 0:561d07a737bc | 1416 | while((read_register(REG_IMAGECAL) & RF_IMAGECAL_IMAGECAL_RUNNING ) |
brunnobbco | 0:561d07a737bc | 1417 | == RF_IMAGECAL_IMAGECAL_RUNNING ) |
brunnobbco | 0:561d07a737bc | 1418 | { |
brunnobbco | 0:561d07a737bc | 1419 | // do nothing, just wait while rf image frequency calibration is done |
brunnobbco | 0:561d07a737bc | 1420 | } |
brunnobbco | 0:561d07a737bc | 1421 | |
brunnobbco | 0:561d07a737bc | 1422 | // Restore context |
brunnobbco | 0:561d07a737bc | 1423 | write_to_register( REG_PACONFIG, regPaConfigInitVal ); |
brunnobbco | 0:561d07a737bc | 1424 | set_channel(initialFreq); |
brunnobbco | 0:561d07a737bc | 1425 | } |
brunnobbco | 0:561d07a737bc | 1426 | |
brunnobbco | 0:561d07a737bc | 1427 | /** |
brunnobbco | 0:561d07a737bc | 1428 | * Gets FSK bandwidth values |
brunnobbco | 0:561d07a737bc | 1429 | * |
brunnobbco | 0:561d07a737bc | 1430 | * Gives either normal bandwidths or bandwidths for |
brunnobbco | 0:561d07a737bc | 1431 | * AFC (auto frequency correction) |
brunnobbco | 0:561d07a737bc | 1432 | */ |
brunnobbco | 0:561d07a737bc | 1433 | uint8_t SX1276_LoRaRadio::get_fsk_bw_reg_val(uint32_t bandwidth) |
brunnobbco | 0:561d07a737bc | 1434 | { |
brunnobbco | 0:561d07a737bc | 1435 | uint8_t i; |
brunnobbco | 0:561d07a737bc | 1436 | |
brunnobbco | 0:561d07a737bc | 1437 | for (i = 0; i < (sizeof(fsk_bandwidths) / sizeof(fsk_bw_t)) - 1; i++) { |
brunnobbco | 0:561d07a737bc | 1438 | if ((bandwidth >= fsk_bandwidths[i].bandwidth) |
brunnobbco | 0:561d07a737bc | 1439 | && (bandwidth < fsk_bandwidths[i + 1].bandwidth)) { |
brunnobbco | 0:561d07a737bc | 1440 | return fsk_bandwidths[i].register_value; |
brunnobbco | 0:561d07a737bc | 1441 | } |
brunnobbco | 0:561d07a737bc | 1442 | } |
brunnobbco | 0:561d07a737bc | 1443 | // ERROR: Value not found |
brunnobbco | 0:561d07a737bc | 1444 | // This should never happen |
brunnobbco | 0:561d07a737bc | 1445 | while (1); |
brunnobbco | 0:561d07a737bc | 1446 | } |
brunnobbco | 0:561d07a737bc | 1447 | |
brunnobbco | 0:561d07a737bc | 1448 | uint8_t SX1276_LoRaRadio::get_pa_conf_reg(uint32_t channel) |
brunnobbco | 0:561d07a737bc | 1449 | { |
brunnobbco | 0:561d07a737bc | 1450 | if (radio_variant == SX1276UNDEFINED) { |
brunnobbco | 0:561d07a737bc | 1451 | return RF_PACONFIG_PASELECT_PABOOST; |
brunnobbco | 0:561d07a737bc | 1452 | } else if (channel > RF_MID_BAND_THRESH) { |
brunnobbco | 0:561d07a737bc | 1453 | if (radio_variant == SX1276MB1LAS) { |
brunnobbco | 0:561d07a737bc | 1454 | return RF_PACONFIG_PASELECT_PABOOST; |
brunnobbco | 0:561d07a737bc | 1455 | } else { |
brunnobbco | 0:561d07a737bc | 1456 | return RF_PACONFIG_PASELECT_RFO; |
brunnobbco | 0:561d07a737bc | 1457 | } |
brunnobbco | 0:561d07a737bc | 1458 | } else { |
brunnobbco | 0:561d07a737bc | 1459 | return RF_PACONFIG_PASELECT_RFO; |
brunnobbco | 0:561d07a737bc | 1460 | } |
brunnobbco | 0:561d07a737bc | 1461 | } |
brunnobbco | 0:561d07a737bc | 1462 | |
brunnobbco | 0:561d07a737bc | 1463 | /** |
brunnobbco | 0:561d07a737bc | 1464 | * Sets the transmit power for the module |
brunnobbco | 0:561d07a737bc | 1465 | */ |
brunnobbco | 0:561d07a737bc | 1466 | void SX1276_LoRaRadio::set_rf_tx_power(int8_t power) |
brunnobbco | 0:561d07a737bc | 1467 | { |
brunnobbco | 0:561d07a737bc | 1468 | |
brunnobbco | 0:561d07a737bc | 1469 | uint8_t paConfig = 0; |
brunnobbco | 0:561d07a737bc | 1470 | uint8_t paDac = 0; |
brunnobbco | 0:561d07a737bc | 1471 | |
brunnobbco | 0:561d07a737bc | 1472 | paConfig = read_register(REG_PACONFIG); |
brunnobbco | 0:561d07a737bc | 1473 | paDac = read_register(REG_PADAC); |
brunnobbco | 0:561d07a737bc | 1474 | |
brunnobbco | 0:561d07a737bc | 1475 | paConfig = (paConfig & RF_PACONFIG_PASELECT_MASK) | get_pa_conf_reg(_rf_settings.channel); |
brunnobbco | 0:561d07a737bc | 1476 | paConfig = (paConfig & RF_PACONFIG_MAX_POWER_MASK) | 0x70; |
brunnobbco | 0:561d07a737bc | 1477 | |
brunnobbco | 0:561d07a737bc | 1478 | if ((paConfig & RF_PACONFIG_PASELECT_PABOOST) == RF_PACONFIG_PASELECT_PABOOST) { |
brunnobbco | 0:561d07a737bc | 1479 | if (power > 17) { |
brunnobbco | 0:561d07a737bc | 1480 | paDac = (paDac & RF_PADAC_20DBM_MASK) | RF_PADAC_20DBM_ON; |
brunnobbco | 0:561d07a737bc | 1481 | } else { |
brunnobbco | 0:561d07a737bc | 1482 | paDac = (paDac & RF_PADAC_20DBM_MASK) | RF_PADAC_20DBM_OFF; |
brunnobbco | 0:561d07a737bc | 1483 | } |
brunnobbco | 0:561d07a737bc | 1484 | if ((paDac & RF_PADAC_20DBM_ON) == RF_PADAC_20DBM_ON) { |
brunnobbco | 0:561d07a737bc | 1485 | if (power < 5) { |
brunnobbco | 0:561d07a737bc | 1486 | power = 5; |
brunnobbco | 0:561d07a737bc | 1487 | } |
brunnobbco | 0:561d07a737bc | 1488 | if (power > 20) { |
brunnobbco | 0:561d07a737bc | 1489 | power = 20; |
brunnobbco | 0:561d07a737bc | 1490 | } |
brunnobbco | 0:561d07a737bc | 1491 | paConfig = (paConfig & RF_PACONFIG_OUTPUTPOWER_MASK) |
brunnobbco | 0:561d07a737bc | 1492 | | (uint8_t) ((uint16_t) (power - 5) & 0x0F); |
brunnobbco | 0:561d07a737bc | 1493 | } else { |
brunnobbco | 0:561d07a737bc | 1494 | if (power < 2) { |
brunnobbco | 0:561d07a737bc | 1495 | power = 2; |
brunnobbco | 0:561d07a737bc | 1496 | } |
brunnobbco | 0:561d07a737bc | 1497 | if (power > 17) { |
brunnobbco | 0:561d07a737bc | 1498 | power = 17; |
brunnobbco | 0:561d07a737bc | 1499 | } |
brunnobbco | 0:561d07a737bc | 1500 | paConfig = (paConfig & RF_PACONFIG_OUTPUTPOWER_MASK) |
brunnobbco | 0:561d07a737bc | 1501 | | (uint8_t) ((uint16_t) (power - 2) & 0x0F); |
brunnobbco | 0:561d07a737bc | 1502 | } |
brunnobbco | 0:561d07a737bc | 1503 | } else { |
brunnobbco | 0:561d07a737bc | 1504 | if (power < -1) { |
brunnobbco | 0:561d07a737bc | 1505 | power = -1; |
brunnobbco | 0:561d07a737bc | 1506 | } |
brunnobbco | 0:561d07a737bc | 1507 | if (power > 14) { |
brunnobbco | 0:561d07a737bc | 1508 | power = 14; |
brunnobbco | 0:561d07a737bc | 1509 | } |
brunnobbco | 0:561d07a737bc | 1510 | paConfig = (paConfig & RF_PACONFIG_OUTPUTPOWER_MASK) |
brunnobbco | 0:561d07a737bc | 1511 | | (uint8_t) ((uint16_t) (power + 1) & 0x0F); |
brunnobbco | 0:561d07a737bc | 1512 | } |
brunnobbco | 0:561d07a737bc | 1513 | write_to_register( REG_PACONFIG, paConfig); |
brunnobbco | 0:561d07a737bc | 1514 | write_to_register( REG_PADAC, paDac); |
brunnobbco | 0:561d07a737bc | 1515 | } |
brunnobbco | 0:561d07a737bc | 1516 | |
brunnobbco | 0:561d07a737bc | 1517 | /** |
brunnobbco | 0:561d07a737bc | 1518 | * Actual TX - Transmit routine |
brunnobbco | 0:561d07a737bc | 1519 | * |
brunnobbco | 0:561d07a737bc | 1520 | * A DIO0 interrupt let the state machine know that a a packet is |
brunnobbco | 0:561d07a737bc | 1521 | * successfully sent, otherwise a TxTimeout is invoked. |
brunnobbco | 0:561d07a737bc | 1522 | * TxTimeout should never happen in normal circumstances as the radio should |
brunnobbco | 0:561d07a737bc | 1523 | * be able to send a packet out in the air no matter what. |
brunnobbco | 0:561d07a737bc | 1524 | */ |
brunnobbco | 0:561d07a737bc | 1525 | void SX1276_LoRaRadio::transmit(uint32_t timeout) |
brunnobbco | 0:561d07a737bc | 1526 | { |
brunnobbco | 0:561d07a737bc | 1527 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 1528 | |
brunnobbco | 0:561d07a737bc | 1529 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1530 | // DIO0=PacketSent |
brunnobbco | 0:561d07a737bc | 1531 | // DIO1=FifoEmpty |
brunnobbco | 0:561d07a737bc | 1532 | // DIO2=FifoFull |
brunnobbco | 0:561d07a737bc | 1533 | // DIO3=FifoEmpty |
brunnobbco | 0:561d07a737bc | 1534 | // DIO4=LowBat |
brunnobbco | 0:561d07a737bc | 1535 | // DIO5=ModeReady |
brunnobbco | 0:561d07a737bc | 1536 | write_to_register(REG_DIOMAPPING1,(read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 1537 | RF_DIOMAPPING1_DIO0_MASK & |
brunnobbco | 0:561d07a737bc | 1538 | RF_DIOMAPPING1_DIO1_MASK & |
brunnobbco | 0:561d07a737bc | 1539 | RF_DIOMAPPING1_DIO2_MASK) | |
brunnobbco | 0:561d07a737bc | 1540 | RF_DIOMAPPING1_DIO1_01); |
brunnobbco | 0:561d07a737bc | 1541 | |
brunnobbco | 0:561d07a737bc | 1542 | write_to_register(REG_DIOMAPPING2, (read_register(REG_DIOMAPPING2) & |
brunnobbco | 0:561d07a737bc | 1543 | RF_DIOMAPPING2_DIO4_MASK & |
brunnobbco | 0:561d07a737bc | 1544 | RF_DIOMAPPING2_MAP_MASK)); |
brunnobbco | 0:561d07a737bc | 1545 | _rf_settings.fsk_packet_handler.fifo_thresh = |
brunnobbco | 0:561d07a737bc | 1546 | read_register(REG_FIFOTHRESH) & 0x3F; |
brunnobbco | 0:561d07a737bc | 1547 | |
brunnobbco | 0:561d07a737bc | 1548 | break; |
brunnobbco | 0:561d07a737bc | 1549 | |
brunnobbco | 0:561d07a737bc | 1550 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1551 | |
brunnobbco | 0:561d07a737bc | 1552 | if (_rf_settings.lora.freq_hop_on == true) { |
brunnobbco | 0:561d07a737bc | 1553 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 1554 | RFLR_IRQFLAGS_RXTIMEOUT | |
brunnobbco | 0:561d07a737bc | 1555 | RFLR_IRQFLAGS_RXDONE | |
brunnobbco | 0:561d07a737bc | 1556 | RFLR_IRQFLAGS_PAYLOADCRCERROR | |
brunnobbco | 0:561d07a737bc | 1557 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 1558 | RFLR_IRQFLAGS_CADDONE | |
brunnobbco | 0:561d07a737bc | 1559 | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 1560 | |
brunnobbco | 0:561d07a737bc | 1561 | // DIO0=tx_done, DIO2=fhss_change_channel |
brunnobbco | 0:561d07a737bc | 1562 | |
brunnobbco | 0:561d07a737bc | 1563 | write_to_register(REG_DIOMAPPING1, (read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 1564 | RFLR_DIOMAPPING1_DIO0_MASK & |
brunnobbco | 0:561d07a737bc | 1565 | RFLR_DIOMAPPING1_DIO2_MASK) | |
brunnobbco | 0:561d07a737bc | 1566 | RFLR_DIOMAPPING1_DIO0_01 | |
brunnobbco | 0:561d07a737bc | 1567 | RFLR_DIOMAPPING1_DIO2_01); |
brunnobbco | 0:561d07a737bc | 1568 | } else { |
brunnobbco | 0:561d07a737bc | 1569 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 1570 | RFLR_IRQFLAGS_RXTIMEOUT | |
brunnobbco | 0:561d07a737bc | 1571 | RFLR_IRQFLAGS_RXDONE | |
brunnobbco | 0:561d07a737bc | 1572 | RFLR_IRQFLAGS_PAYLOADCRCERROR | |
brunnobbco | 0:561d07a737bc | 1573 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 1574 | RFLR_IRQFLAGS_CADDONE | |
brunnobbco | 0:561d07a737bc | 1575 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | |
brunnobbco | 0:561d07a737bc | 1576 | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 1577 | |
brunnobbco | 0:561d07a737bc | 1578 | // DIO0=tx_done |
brunnobbco | 0:561d07a737bc | 1579 | write_to_register(REG_DIOMAPPING1,(read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 1580 | RFLR_DIOMAPPING1_DIO0_MASK) | |
brunnobbco | 0:561d07a737bc | 1581 | RFLR_DIOMAPPING1_DIO0_01); |
brunnobbco | 0:561d07a737bc | 1582 | } |
brunnobbco | 0:561d07a737bc | 1583 | |
brunnobbco | 0:561d07a737bc | 1584 | break; |
brunnobbco | 0:561d07a737bc | 1585 | } |
brunnobbco | 0:561d07a737bc | 1586 | |
brunnobbco | 0:561d07a737bc | 1587 | _rf_settings.state = RF_TX_RUNNING; |
brunnobbco | 0:561d07a737bc | 1588 | |
brunnobbco | 0:561d07a737bc | 1589 | tx_timeout_timer.attach_us(callback(this, |
brunnobbco | 0:561d07a737bc | 1590 | &SX1276_LoRaRadio::timeout_irq_isr), timeout * 1000); |
brunnobbco | 0:561d07a737bc | 1591 | |
brunnobbco | 0:561d07a737bc | 1592 | set_operation_mode(RF_OPMODE_TRANSMITTER); |
brunnobbco | 0:561d07a737bc | 1593 | } |
brunnobbco | 0:561d07a737bc | 1594 | |
brunnobbco | 0:561d07a737bc | 1595 | /** |
brunnobbco | 0:561d07a737bc | 1596 | * Get RSSI from the module |
brunnobbco | 0:561d07a737bc | 1597 | */ |
brunnobbco | 0:561d07a737bc | 1598 | int16_t SX1276_LoRaRadio::get_rssi(radio_modems_t modem) |
brunnobbco | 0:561d07a737bc | 1599 | { |
brunnobbco | 0:561d07a737bc | 1600 | int16_t rssi = 0; |
brunnobbco | 0:561d07a737bc | 1601 | |
brunnobbco | 0:561d07a737bc | 1602 | switch (modem) { |
brunnobbco | 0:561d07a737bc | 1603 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1604 | rssi = -(read_register(REG_RSSIVALUE) >> 1); |
brunnobbco | 0:561d07a737bc | 1605 | break; |
brunnobbco | 0:561d07a737bc | 1606 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1607 | if (_rf_settings.channel > RF_MID_BAND_THRESH) { |
brunnobbco | 0:561d07a737bc | 1608 | rssi = RSSI_OFFSET_HF + read_register(REG_LR_RSSIVALUE); |
brunnobbco | 0:561d07a737bc | 1609 | } else { |
brunnobbco | 0:561d07a737bc | 1610 | rssi = RSSI_OFFSET_LF + read_register(REG_LR_RSSIVALUE); |
brunnobbco | 0:561d07a737bc | 1611 | } |
brunnobbco | 0:561d07a737bc | 1612 | break; |
brunnobbco | 0:561d07a737bc | 1613 | default: |
brunnobbco | 0:561d07a737bc | 1614 | rssi = -1; |
brunnobbco | 0:561d07a737bc | 1615 | break; |
brunnobbco | 0:561d07a737bc | 1616 | } |
brunnobbco | 0:561d07a737bc | 1617 | return rssi; |
brunnobbco | 0:561d07a737bc | 1618 | } |
brunnobbco | 0:561d07a737bc | 1619 | |
brunnobbco | 0:561d07a737bc | 1620 | /** |
brunnobbco | 0:561d07a737bc | 1621 | * Sets the module in low power mode by disconnecting |
brunnobbco | 0:561d07a737bc | 1622 | * TX and RX submodules, turning off power amplifier etc. |
brunnobbco | 0:561d07a737bc | 1623 | */ |
brunnobbco | 0:561d07a737bc | 1624 | void SX1276_LoRaRadio::set_low_power_mode() |
brunnobbco | 0:561d07a737bc | 1625 | { |
brunnobbco | 0:561d07a737bc | 1626 | |
brunnobbco | 0:561d07a737bc | 1627 | if (_rf_ctrls.rf_switch_ctl1 != NC) { |
brunnobbco | 0:561d07a737bc | 1628 | _rf_switch_ctl1 = 0; |
brunnobbco | 0:561d07a737bc | 1629 | } |
brunnobbco | 0:561d07a737bc | 1630 | |
brunnobbco | 0:561d07a737bc | 1631 | if (_rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1632 | _rf_switch_ctl2 = 0; |
brunnobbco | 0:561d07a737bc | 1633 | } |
brunnobbco | 0:561d07a737bc | 1634 | |
brunnobbco | 0:561d07a737bc | 1635 | if (_rf_ctrls.pwr_amp_ctl != NC) { |
brunnobbco | 0:561d07a737bc | 1636 | _pwr_amp_ctl = 0; |
brunnobbco | 0:561d07a737bc | 1637 | } |
brunnobbco | 0:561d07a737bc | 1638 | |
brunnobbco | 0:561d07a737bc | 1639 | if (_rf_ctrls.txctl != NC) { |
brunnobbco | 0:561d07a737bc | 1640 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1641 | } |
brunnobbco | 0:561d07a737bc | 1642 | |
brunnobbco | 0:561d07a737bc | 1643 | if (_rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1644 | _rxctl = 0; |
brunnobbco | 0:561d07a737bc | 1645 | } |
brunnobbco | 0:561d07a737bc | 1646 | |
brunnobbco | 0:561d07a737bc | 1647 | if (_rf_ctrls.ant_switch != NC) { |
brunnobbco | 0:561d07a737bc | 1648 | _ant_switch = 0; |
brunnobbco | 0:561d07a737bc | 1649 | } |
brunnobbco | 0:561d07a737bc | 1650 | } |
brunnobbco | 0:561d07a737bc | 1651 | |
brunnobbco | 0:561d07a737bc | 1652 | /** |
brunnobbco | 0:561d07a737bc | 1653 | * Attaches ISRs to interrupt pins |
brunnobbco | 0:561d07a737bc | 1654 | */ |
brunnobbco | 0:561d07a737bc | 1655 | void SX1276_LoRaRadio::setup_interrupts() |
brunnobbco | 0:561d07a737bc | 1656 | { |
brunnobbco | 0:561d07a737bc | 1657 | _dio0_ctl.rise(callback(this, &SX1276_LoRaRadio::dio0_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1658 | _dio1_ctl.rise(callback(this, &SX1276_LoRaRadio::dio1_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1659 | _dio2_ctl.rise(callback(this, &SX1276_LoRaRadio::dio2_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1660 | _dio3_ctl.rise(callback(this, &SX1276_LoRaRadio::dio3_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1661 | if (_dio4_pin != NC) { |
brunnobbco | 0:561d07a737bc | 1662 | _dio4_ctl.rise(callback(this, &SX1276_LoRaRadio::dio4_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1663 | } |
brunnobbco | 0:561d07a737bc | 1664 | if (_dio5_pin != NC) { |
brunnobbco | 0:561d07a737bc | 1665 | _dio5_ctl.rise(callback(this, &SX1276_LoRaRadio::dio5_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1666 | } |
brunnobbco | 0:561d07a737bc | 1667 | } |
brunnobbco | 0:561d07a737bc | 1668 | |
brunnobbco | 0:561d07a737bc | 1669 | /** |
brunnobbco | 0:561d07a737bc | 1670 | * Sets up radio latch position according to the |
brunnobbco | 0:561d07a737bc | 1671 | * radio mode |
brunnobbco | 0:561d07a737bc | 1672 | */ |
brunnobbco | 0:561d07a737bc | 1673 | void SX1276_LoRaRadio::set_antenna_switch(uint8_t mode) |
brunnobbco | 0:561d07a737bc | 1674 | { |
brunnobbco | 0:561d07a737bc | 1675 | // here we got to do ifdef for changing controls |
brunnobbco | 0:561d07a737bc | 1676 | // as some pins might be NC |
brunnobbco | 0:561d07a737bc | 1677 | switch (mode) { |
brunnobbco | 0:561d07a737bc | 1678 | case RFLR_OPMODE_TRANSMITTER: |
brunnobbco | 0:561d07a737bc | 1679 | if (_rf_ctrls.rf_switch_ctl1 != NC |
brunnobbco | 0:561d07a737bc | 1680 | && _rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1681 | // module is in transmit mode and RF latch switches |
brunnobbco | 0:561d07a737bc | 1682 | // are connected. Check if power amplifier boost is |
brunnobbco | 0:561d07a737bc | 1683 | // setup or not |
brunnobbco | 0:561d07a737bc | 1684 | if ((read_register(REG_PACONFIG) & RF_PACONFIG_PASELECT_PABOOST) |
brunnobbco | 0:561d07a737bc | 1685 | == RF_PACONFIG_PASELECT_PABOOST) { |
brunnobbco | 0:561d07a737bc | 1686 | _rf_switch_ctl1 = 1; |
brunnobbco | 0:561d07a737bc | 1687 | _rf_switch_ctl2 = 0; |
brunnobbco | 0:561d07a737bc | 1688 | } else { |
brunnobbco | 0:561d07a737bc | 1689 | // power amplifier not selected |
brunnobbco | 0:561d07a737bc | 1690 | _rf_switch_ctl1 = 0; |
brunnobbco | 0:561d07a737bc | 1691 | _rf_switch_ctl2 = 1; |
brunnobbco | 0:561d07a737bc | 1692 | } |
brunnobbco | 0:561d07a737bc | 1693 | } |
brunnobbco | 0:561d07a737bc | 1694 | if (_rf_ctrls.txctl != NC && _rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1695 | // module is in transmit mode and tx/rx submodule control |
brunnobbco | 0:561d07a737bc | 1696 | // pins are connected |
brunnobbco | 0:561d07a737bc | 1697 | if (_rf_ctrls.pwr_amp_ctl != NC) { |
brunnobbco | 0:561d07a737bc | 1698 | if (read_register(REG_PACONFIG) & RF_PACONFIG_PASELECT_PABOOST) { |
brunnobbco | 0:561d07a737bc | 1699 | _pwr_amp_ctl = 1; |
brunnobbco | 0:561d07a737bc | 1700 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1701 | } else { |
brunnobbco | 0:561d07a737bc | 1702 | _pwr_amp_ctl = 0; |
brunnobbco | 0:561d07a737bc | 1703 | _txctl = 1; |
brunnobbco | 0:561d07a737bc | 1704 | } |
brunnobbco | 0:561d07a737bc | 1705 | } else { |
brunnobbco | 0:561d07a737bc | 1706 | _txctl = 1; |
brunnobbco | 0:561d07a737bc | 1707 | } |
brunnobbco | 0:561d07a737bc | 1708 | _rxctl = 0; |
brunnobbco | 0:561d07a737bc | 1709 | } |
brunnobbco | 0:561d07a737bc | 1710 | if (_rf_ctrls.ant_switch != NC){ |
brunnobbco | 0:561d07a737bc | 1711 | _ant_switch = 1; |
brunnobbco | 0:561d07a737bc | 1712 | } |
brunnobbco | 0:561d07a737bc | 1713 | break; |
brunnobbco | 0:561d07a737bc | 1714 | case RFLR_OPMODE_RECEIVER: |
brunnobbco | 0:561d07a737bc | 1715 | case RFLR_OPMODE_RECEIVER_SINGLE: |
brunnobbco | 0:561d07a737bc | 1716 | case RFLR_OPMODE_CAD: |
brunnobbco | 0:561d07a737bc | 1717 | if (_rf_ctrls.rf_switch_ctl1 != NC |
brunnobbco | 0:561d07a737bc | 1718 | && _rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1719 | // radio is in reception or CAD mode and RF latch switches |
brunnobbco | 0:561d07a737bc | 1720 | // are connected |
brunnobbco | 0:561d07a737bc | 1721 | _rf_switch_ctl1 = 1; |
brunnobbco | 0:561d07a737bc | 1722 | _rf_switch_ctl2 = 1; |
brunnobbco | 0:561d07a737bc | 1723 | } |
brunnobbco | 0:561d07a737bc | 1724 | if (_rf_ctrls.txctl != NC && _rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1725 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1726 | _rxctl = 1; |
brunnobbco | 0:561d07a737bc | 1727 | } |
brunnobbco | 0:561d07a737bc | 1728 | if (_rf_ctrls.ant_switch != NC) { |
brunnobbco | 0:561d07a737bc | 1729 | _ant_switch = 0; |
brunnobbco | 0:561d07a737bc | 1730 | } |
brunnobbco | 0:561d07a737bc | 1731 | if (_rf_ctrls.pwr_amp_ctl != NC) { |
brunnobbco | 0:561d07a737bc | 1732 | _pwr_amp_ctl = 0; |
brunnobbco | 0:561d07a737bc | 1733 | } |
brunnobbco | 0:561d07a737bc | 1734 | break; |
brunnobbco | 0:561d07a737bc | 1735 | default: |
brunnobbco | 0:561d07a737bc | 1736 | // Enforce default case when any connected control pin is kept low. |
brunnobbco | 0:561d07a737bc | 1737 | if (_rf_ctrls.rf_switch_ctl1 != NC |
brunnobbco | 0:561d07a737bc | 1738 | && _rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1739 | // radio is in reception or CAD mode and RF latch switches |
brunnobbco | 0:561d07a737bc | 1740 | // are connected |
brunnobbco | 0:561d07a737bc | 1741 | _rf_switch_ctl1 = 0; |
brunnobbco | 0:561d07a737bc | 1742 | _rf_switch_ctl2 = 0; |
brunnobbco | 0:561d07a737bc | 1743 | } |
brunnobbco | 0:561d07a737bc | 1744 | if (_rf_ctrls.txctl != NC && _rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1745 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1746 | _rxctl = 0; |
brunnobbco | 0:561d07a737bc | 1747 | } |
brunnobbco | 0:561d07a737bc | 1748 | if (_rf_ctrls.ant_switch != NC) { |
brunnobbco | 0:561d07a737bc | 1749 | _ant_switch = 0; |
brunnobbco | 0:561d07a737bc | 1750 | } |
brunnobbco | 0:561d07a737bc | 1751 | if (_rf_ctrls.pwr_amp_ctl != NC) { |
brunnobbco | 0:561d07a737bc | 1752 | _pwr_amp_ctl = 0; |
brunnobbco | 0:561d07a737bc | 1753 | } |
brunnobbco | 0:561d07a737bc | 1754 | break; |
brunnobbco | 0:561d07a737bc | 1755 | } |
brunnobbco | 0:561d07a737bc | 1756 | } |
brunnobbco | 0:561d07a737bc | 1757 | |
brunnobbco | 0:561d07a737bc | 1758 | /***************************************************************************** |
brunnobbco | 0:561d07a737bc | 1759 | * Interrupt service routines (ISRs) - set signals to the irq_thread * |
brunnobbco | 0:561d07a737bc | 1760 | ****************************************************************************/ |
brunnobbco | 0:561d07a737bc | 1761 | void SX1276_LoRaRadio::dio0_irq_isr() |
brunnobbco | 0:561d07a737bc | 1762 | { |
brunnobbco | 0:561d07a737bc | 1763 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1764 | irq_thread.flags_set(SIG_DIO0); |
brunnobbco | 0:561d07a737bc | 1765 | #else |
brunnobbco | 0:561d07a737bc | 1766 | handle_dio0_irq(); |
brunnobbco | 0:561d07a737bc | 1767 | #endif |
brunnobbco | 0:561d07a737bc | 1768 | } |
brunnobbco | 0:561d07a737bc | 1769 | |
brunnobbco | 0:561d07a737bc | 1770 | void SX1276_LoRaRadio::dio1_irq_isr() |
brunnobbco | 0:561d07a737bc | 1771 | { |
brunnobbco | 0:561d07a737bc | 1772 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1773 | irq_thread.flags_set(SIG_DIO1); |
brunnobbco | 0:561d07a737bc | 1774 | #else |
brunnobbco | 0:561d07a737bc | 1775 | handle_dio1_irq(); |
brunnobbco | 0:561d07a737bc | 1776 | #endif |
brunnobbco | 0:561d07a737bc | 1777 | } |
brunnobbco | 0:561d07a737bc | 1778 | |
brunnobbco | 0:561d07a737bc | 1779 | void SX1276_LoRaRadio::dio2_irq_isr() |
brunnobbco | 0:561d07a737bc | 1780 | { |
brunnobbco | 0:561d07a737bc | 1781 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1782 | irq_thread.flags_set(SIG_DIO2); |
brunnobbco | 0:561d07a737bc | 1783 | #else |
brunnobbco | 0:561d07a737bc | 1784 | handle_dio2_irq(); |
brunnobbco | 0:561d07a737bc | 1785 | #endif |
brunnobbco | 0:561d07a737bc | 1786 | } |
brunnobbco | 0:561d07a737bc | 1787 | |
brunnobbco | 0:561d07a737bc | 1788 | void SX1276_LoRaRadio::dio3_irq_isr() |
brunnobbco | 0:561d07a737bc | 1789 | { |
brunnobbco | 0:561d07a737bc | 1790 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1791 | irq_thread.flags_set(SIG_DIO3); |
brunnobbco | 0:561d07a737bc | 1792 | #else |
brunnobbco | 0:561d07a737bc | 1793 | handle_dio3_irq(); |
brunnobbco | 0:561d07a737bc | 1794 | #endif |
brunnobbco | 0:561d07a737bc | 1795 | } |
brunnobbco | 0:561d07a737bc | 1796 | |
brunnobbco | 0:561d07a737bc | 1797 | void SX1276_LoRaRadio::dio4_irq_isr() |
brunnobbco | 0:561d07a737bc | 1798 | { |
brunnobbco | 0:561d07a737bc | 1799 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1800 | irq_thread.flags_set(SIG_DIO4); |
brunnobbco | 0:561d07a737bc | 1801 | #else |
brunnobbco | 0:561d07a737bc | 1802 | handle_dio4_irq(); |
brunnobbco | 0:561d07a737bc | 1803 | #endif |
brunnobbco | 0:561d07a737bc | 1804 | } |
brunnobbco | 0:561d07a737bc | 1805 | |
brunnobbco | 0:561d07a737bc | 1806 | void SX1276_LoRaRadio::dio5_irq_isr() |
brunnobbco | 0:561d07a737bc | 1807 | { |
brunnobbco | 0:561d07a737bc | 1808 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1809 | irq_thread.flags_set(SIG_DIO5); |
brunnobbco | 0:561d07a737bc | 1810 | #else |
brunnobbco | 0:561d07a737bc | 1811 | handle_dio5_irq(); |
brunnobbco | 0:561d07a737bc | 1812 | #endif |
brunnobbco | 0:561d07a737bc | 1813 | } |
brunnobbco | 0:561d07a737bc | 1814 | |
brunnobbco | 0:561d07a737bc | 1815 | // This is not a hardware interrupt |
brunnobbco | 0:561d07a737bc | 1816 | // we invoke it ourselves based upon |
brunnobbco | 0:561d07a737bc | 1817 | // our timers |
brunnobbco | 0:561d07a737bc | 1818 | void SX1276_LoRaRadio::timeout_irq_isr() |
brunnobbco | 0:561d07a737bc | 1819 | { |
brunnobbco | 0:561d07a737bc | 1820 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1821 | irq_thread.flags_set(SIG_TIMOUT); |
brunnobbco | 0:561d07a737bc | 1822 | #else |
brunnobbco | 0:561d07a737bc | 1823 | handle_timeout_irq(); |
brunnobbco | 0:561d07a737bc | 1824 | #endif |
brunnobbco | 0:561d07a737bc | 1825 | } |
brunnobbco | 0:561d07a737bc | 1826 | |
brunnobbco | 0:561d07a737bc | 1827 | /****************************************************************************** |
brunnobbco | 0:561d07a737bc | 1828 | * Interrupt Handlers * |
brunnobbco | 0:561d07a737bc | 1829 | *****************************************************************************/ |
brunnobbco | 0:561d07a737bc | 1830 | |
brunnobbco | 0:561d07a737bc | 1831 | void SX1276_LoRaRadio::handle_dio0_irq() |
brunnobbco | 0:561d07a737bc | 1832 | { |
brunnobbco | 0:561d07a737bc | 1833 | volatile uint8_t irqFlags = 0; |
brunnobbco | 0:561d07a737bc | 1834 | |
brunnobbco | 0:561d07a737bc | 1835 | switch (_rf_settings.state) { |
brunnobbco | 0:561d07a737bc | 1836 | case RF_RX_RUNNING: |
brunnobbco | 0:561d07a737bc | 1837 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 1838 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1839 | if (_rf_settings.fsk.crc_on == true) { |
brunnobbco | 0:561d07a737bc | 1840 | irqFlags = read_register(REG_IRQFLAGS2); |
brunnobbco | 0:561d07a737bc | 1841 | if ((irqFlags & RF_IRQFLAGS2_CRCOK) |
brunnobbco | 0:561d07a737bc | 1842 | != RF_IRQFLAGS2_CRCOK) { |
brunnobbco | 0:561d07a737bc | 1843 | // Clear Irqs |
brunnobbco | 0:561d07a737bc | 1844 | write_to_register(REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | |
brunnobbco | 0:561d07a737bc | 1845 | RF_IRQFLAGS1_PREAMBLEDETECT | |
brunnobbco | 0:561d07a737bc | 1846 | RF_IRQFLAGS1_SYNCADDRESSMATCH); |
brunnobbco | 0:561d07a737bc | 1847 | write_to_register(REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN); |
brunnobbco | 0:561d07a737bc | 1848 | |
brunnobbco | 0:561d07a737bc | 1849 | if (_rf_settings.fsk.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1850 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1851 | } else { |
brunnobbco | 0:561d07a737bc | 1852 | // Continuous mode restart Rx chain |
brunnobbco | 0:561d07a737bc | 1853 | write_to_register(REG_RXCONFIG, |
brunnobbco | 0:561d07a737bc | 1854 | read_register(REG_RXCONFIG) | |
brunnobbco | 0:561d07a737bc | 1855 | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); |
brunnobbco | 0:561d07a737bc | 1856 | } |
brunnobbco | 0:561d07a737bc | 1857 | |
brunnobbco | 0:561d07a737bc | 1858 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 1859 | && (_radio_events->rx_error)) { |
brunnobbco | 0:561d07a737bc | 1860 | _radio_events->rx_error(); |
brunnobbco | 0:561d07a737bc | 1861 | } |
brunnobbco | 0:561d07a737bc | 1862 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 1863 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 1864 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 1865 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 1866 | // break from here, a CRC error happened, RX_ERROR |
brunnobbco | 0:561d07a737bc | 1867 | // was notified. No need to go any further |
brunnobbco | 0:561d07a737bc | 1868 | break; |
brunnobbco | 0:561d07a737bc | 1869 | } |
brunnobbco | 0:561d07a737bc | 1870 | } |
brunnobbco | 0:561d07a737bc | 1871 | |
brunnobbco | 0:561d07a737bc | 1872 | // This block was moved from dio2_handler. |
brunnobbco | 0:561d07a737bc | 1873 | // We can have a snapshot of RSSI here as at this point it |
brunnobbco | 0:561d07a737bc | 1874 | // should be more smoothed out. |
brunnobbco | 0:561d07a737bc | 1875 | _rf_settings.fsk_packet_handler.rssi_value = |
brunnobbco | 0:561d07a737bc | 1876 | -(read_register(REG_RSSIVALUE) >> 1); |
brunnobbco | 0:561d07a737bc | 1877 | |
brunnobbco | 0:561d07a737bc | 1878 | _rf_settings.fsk_packet_handler.afc_value = |
brunnobbco | 0:561d07a737bc | 1879 | (int32_t) (float) (((uint16_t) read_register(REG_AFCMSB) << 8) |
brunnobbco | 0:561d07a737bc | 1880 | | (uint16_t) read_register( REG_AFCLSB)) |
brunnobbco | 0:561d07a737bc | 1881 | * (float) FREQ_STEP; |
brunnobbco | 0:561d07a737bc | 1882 | _rf_settings.fsk_packet_handler.rx_gain = |
brunnobbco | 0:561d07a737bc | 1883 | (read_register( REG_LNA) >> 5) & 0x07; |
brunnobbco | 0:561d07a737bc | 1884 | |
brunnobbco | 0:561d07a737bc | 1885 | // Read received packet size |
brunnobbco | 0:561d07a737bc | 1886 | if ((_rf_settings.fsk_packet_handler.size == 0) |
brunnobbco | 0:561d07a737bc | 1887 | && (_rf_settings.fsk_packet_handler.nb_bytes == 0)) { |
brunnobbco | 0:561d07a737bc | 1888 | if (_rf_settings.fsk.fix_len == false) { |
brunnobbco | 0:561d07a737bc | 1889 | read_fifo((uint8_t*) &_rf_settings.fsk_packet_handler.size, 1); |
brunnobbco | 0:561d07a737bc | 1890 | } else { |
brunnobbco | 0:561d07a737bc | 1891 | _rf_settings.fsk_packet_handler.size = read_register(REG_PAYLOADLENGTH); |
brunnobbco | 0:561d07a737bc | 1892 | } |
brunnobbco | 0:561d07a737bc | 1893 | read_fifo(_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes, |
brunnobbco | 0:561d07a737bc | 1894 | _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1895 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 1896 | (_rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1897 | } else { |
brunnobbco | 0:561d07a737bc | 1898 | read_fifo(_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes, |
brunnobbco | 0:561d07a737bc | 1899 | _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1900 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 1901 | (_rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1902 | } |
brunnobbco | 0:561d07a737bc | 1903 | |
brunnobbco | 0:561d07a737bc | 1904 | if (_rf_settings.fsk.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1905 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1906 | } else { |
brunnobbco | 0:561d07a737bc | 1907 | // Continuous mode restart Rx chain |
brunnobbco | 0:561d07a737bc | 1908 | write_to_register(REG_RXCONFIG, read_register(REG_RXCONFIG) |
brunnobbco | 0:561d07a737bc | 1909 | | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); |
brunnobbco | 0:561d07a737bc | 1910 | } |
brunnobbco | 0:561d07a737bc | 1911 | |
brunnobbco | 0:561d07a737bc | 1912 | if ((_radio_events != NULL) && (_radio_events->rx_done)) { |
brunnobbco | 0:561d07a737bc | 1913 | _radio_events->rx_done( |
brunnobbco | 0:561d07a737bc | 1914 | _data_buffer, |
brunnobbco | 0:561d07a737bc | 1915 | _rf_settings.fsk_packet_handler.size, |
brunnobbco | 0:561d07a737bc | 1916 | _rf_settings.fsk_packet_handler.rssi_value, 0); |
brunnobbco | 0:561d07a737bc | 1917 | } |
brunnobbco | 0:561d07a737bc | 1918 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 1919 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 1920 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 1921 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 1922 | break; |
brunnobbco | 0:561d07a737bc | 1923 | |
brunnobbco | 0:561d07a737bc | 1924 | case MODEM_LORA: { |
brunnobbco | 0:561d07a737bc | 1925 | int8_t snr = 0; |
brunnobbco | 0:561d07a737bc | 1926 | |
brunnobbco | 0:561d07a737bc | 1927 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 1928 | write_to_register(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE); |
brunnobbco | 0:561d07a737bc | 1929 | |
brunnobbco | 0:561d07a737bc | 1930 | irqFlags = read_register(REG_LR_IRQFLAGS); |
brunnobbco | 0:561d07a737bc | 1931 | if ((irqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK) |
brunnobbco | 0:561d07a737bc | 1932 | == RFLR_IRQFLAGS_PAYLOADCRCERROR) { |
brunnobbco | 0:561d07a737bc | 1933 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 1934 | write_to_register( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_PAYLOADCRCERROR); |
brunnobbco | 0:561d07a737bc | 1935 | |
brunnobbco | 0:561d07a737bc | 1936 | if (_rf_settings.lora.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1937 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1938 | } |
brunnobbco | 0:561d07a737bc | 1939 | |
brunnobbco | 0:561d07a737bc | 1940 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 1941 | && (_radio_events->rx_error)) { |
brunnobbco | 0:561d07a737bc | 1942 | _radio_events->rx_error(); |
brunnobbco | 0:561d07a737bc | 1943 | } |
brunnobbco | 0:561d07a737bc | 1944 | break; |
brunnobbco | 0:561d07a737bc | 1945 | } |
brunnobbco | 0:561d07a737bc | 1946 | |
brunnobbco | 0:561d07a737bc | 1947 | _rf_settings.lora_packet_handler.snr_value = read_register( |
brunnobbco | 0:561d07a737bc | 1948 | REG_LR_PKTSNRVALUE); |
brunnobbco | 0:561d07a737bc | 1949 | if (_rf_settings.lora_packet_handler.snr_value & 0x80) // The SNR sign bit is 1 |
brunnobbco | 0:561d07a737bc | 1950 | { |
brunnobbco | 0:561d07a737bc | 1951 | // Invert and divide by 4 |
brunnobbco | 0:561d07a737bc | 1952 | snr = ((~_rf_settings.lora_packet_handler.snr_value + 1) |
brunnobbco | 0:561d07a737bc | 1953 | & 0xFF) >> 2; |
brunnobbco | 0:561d07a737bc | 1954 | snr = -snr; |
brunnobbco | 0:561d07a737bc | 1955 | } else { |
brunnobbco | 0:561d07a737bc | 1956 | // Divide by 4 |
brunnobbco | 0:561d07a737bc | 1957 | snr = |
brunnobbco | 0:561d07a737bc | 1958 | (_rf_settings.lora_packet_handler.snr_value |
brunnobbco | 0:561d07a737bc | 1959 | & 0xFF) >> 2; |
brunnobbco | 0:561d07a737bc | 1960 | } |
brunnobbco | 0:561d07a737bc | 1961 | |
brunnobbco | 0:561d07a737bc | 1962 | int16_t rssi = read_register( REG_LR_PKTRSSIVALUE); |
brunnobbco | 0:561d07a737bc | 1963 | if (snr < 0) { |
brunnobbco | 0:561d07a737bc | 1964 | if (_rf_settings.channel > RF_MID_BAND_THRESH) { |
brunnobbco | 0:561d07a737bc | 1965 | _rf_settings.lora_packet_handler.rssi_value = |
brunnobbco | 0:561d07a737bc | 1966 | RSSI_OFFSET_HF + rssi + (rssi >> 4) + snr; |
brunnobbco | 0:561d07a737bc | 1967 | } else { |
brunnobbco | 0:561d07a737bc | 1968 | _rf_settings.lora_packet_handler.rssi_value = |
brunnobbco | 0:561d07a737bc | 1969 | RSSI_OFFSET_LF + rssi + (rssi >> 4) + snr; |
brunnobbco | 0:561d07a737bc | 1970 | } |
brunnobbco | 0:561d07a737bc | 1971 | } else { |
brunnobbco | 0:561d07a737bc | 1972 | if (_rf_settings.channel > RF_MID_BAND_THRESH) { |
brunnobbco | 0:561d07a737bc | 1973 | _rf_settings.lora_packet_handler.rssi_value = |
brunnobbco | 0:561d07a737bc | 1974 | RSSI_OFFSET_HF + rssi + (rssi >> 4); |
brunnobbco | 0:561d07a737bc | 1975 | } else { |
brunnobbco | 0:561d07a737bc | 1976 | _rf_settings.lora_packet_handler.rssi_value = |
brunnobbco | 0:561d07a737bc | 1977 | RSSI_OFFSET_LF + rssi + (rssi >> 4); |
brunnobbco | 0:561d07a737bc | 1978 | } |
brunnobbco | 0:561d07a737bc | 1979 | } |
brunnobbco | 0:561d07a737bc | 1980 | |
brunnobbco | 0:561d07a737bc | 1981 | _rf_settings.lora_packet_handler.size = read_register(REG_LR_RXNBBYTES); |
brunnobbco | 0:561d07a737bc | 1982 | read_fifo(_data_buffer, _rf_settings.lora_packet_handler.size); |
brunnobbco | 0:561d07a737bc | 1983 | |
brunnobbco | 0:561d07a737bc | 1984 | if (_rf_settings.lora.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1985 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1986 | } |
brunnobbco | 0:561d07a737bc | 1987 | |
brunnobbco | 0:561d07a737bc | 1988 | if ((_radio_events != NULL) && (_radio_events->rx_done)) { |
brunnobbco | 0:561d07a737bc | 1989 | _radio_events->rx_done(_data_buffer, |
brunnobbco | 0:561d07a737bc | 1990 | _rf_settings.lora_packet_handler.size, |
brunnobbco | 0:561d07a737bc | 1991 | _rf_settings.lora_packet_handler.rssi_value, |
brunnobbco | 0:561d07a737bc | 1992 | _rf_settings.lora_packet_handler.snr_value); |
brunnobbco | 0:561d07a737bc | 1993 | } |
brunnobbco | 0:561d07a737bc | 1994 | } |
brunnobbco | 0:561d07a737bc | 1995 | break; |
brunnobbco | 0:561d07a737bc | 1996 | default: |
brunnobbco | 0:561d07a737bc | 1997 | break; |
brunnobbco | 0:561d07a737bc | 1998 | } |
brunnobbco | 0:561d07a737bc | 1999 | break; |
brunnobbco | 0:561d07a737bc | 2000 | case RF_TX_RUNNING: |
brunnobbco | 0:561d07a737bc | 2001 | tx_timeout_timer.detach(); |
brunnobbco | 0:561d07a737bc | 2002 | // TxDone interrupt |
brunnobbco | 0:561d07a737bc | 2003 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2004 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2005 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 2006 | write_to_register(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE); |
brunnobbco | 0:561d07a737bc | 2007 | // Intentional fall through |
brunnobbco | 0:561d07a737bc | 2008 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2009 | default: |
brunnobbco | 0:561d07a737bc | 2010 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 2011 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 2012 | && (_radio_events->tx_done)) { |
brunnobbco | 0:561d07a737bc | 2013 | _radio_events->tx_done(); |
brunnobbco | 0:561d07a737bc | 2014 | } |
brunnobbco | 0:561d07a737bc | 2015 | break; |
brunnobbco | 0:561d07a737bc | 2016 | } |
brunnobbco | 0:561d07a737bc | 2017 | break; |
brunnobbco | 0:561d07a737bc | 2018 | default: |
brunnobbco | 0:561d07a737bc | 2019 | break; |
brunnobbco | 0:561d07a737bc | 2020 | } |
brunnobbco | 0:561d07a737bc | 2021 | } |
brunnobbco | 0:561d07a737bc | 2022 | |
brunnobbco | 0:561d07a737bc | 2023 | void SX1276_LoRaRadio::handle_dio1_irq() |
brunnobbco | 0:561d07a737bc | 2024 | { |
brunnobbco | 0:561d07a737bc | 2025 | switch (_rf_settings.state) { |
brunnobbco | 0:561d07a737bc | 2026 | case RF_RX_RUNNING: |
brunnobbco | 0:561d07a737bc | 2027 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2028 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2029 | // FifoLevel interrupt |
brunnobbco | 0:561d07a737bc | 2030 | // Read received packet size |
brunnobbco | 0:561d07a737bc | 2031 | if ((_rf_settings.fsk_packet_handler.size == 0) |
brunnobbco | 0:561d07a737bc | 2032 | && (_rf_settings.fsk_packet_handler.nb_bytes == 0)) { |
brunnobbco | 0:561d07a737bc | 2033 | if (_rf_settings.fsk.fix_len == false) { |
brunnobbco | 0:561d07a737bc | 2034 | read_fifo((uint8_t*) &_rf_settings.fsk_packet_handler.size, 1); |
brunnobbco | 0:561d07a737bc | 2035 | } else { |
brunnobbco | 0:561d07a737bc | 2036 | _rf_settings.fsk_packet_handler.size = |
brunnobbco | 0:561d07a737bc | 2037 | read_register(REG_PAYLOADLENGTH); |
brunnobbco | 0:561d07a737bc | 2038 | } |
brunnobbco | 0:561d07a737bc | 2039 | } |
brunnobbco | 0:561d07a737bc | 2040 | |
brunnobbco | 0:561d07a737bc | 2041 | if ((_rf_settings.fsk_packet_handler.size |
brunnobbco | 0:561d07a737bc | 2042 | - _rf_settings.fsk_packet_handler.nb_bytes) |
brunnobbco | 0:561d07a737bc | 2043 | > _rf_settings.fsk_packet_handler.fifo_thresh) { |
brunnobbco | 0:561d07a737bc | 2044 | read_fifo((_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes), |
brunnobbco | 0:561d07a737bc | 2045 | _rf_settings.fsk_packet_handler.fifo_thresh); |
brunnobbco | 0:561d07a737bc | 2046 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 2047 | _rf_settings.fsk_packet_handler.fifo_thresh; |
brunnobbco | 0:561d07a737bc | 2048 | } else { |
brunnobbco | 0:561d07a737bc | 2049 | read_fifo((_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes), |
brunnobbco | 0:561d07a737bc | 2050 | _rf_settings.fsk_packet_handler.size |
brunnobbco | 0:561d07a737bc | 2051 | - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 2052 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 2053 | (_rf_settings.fsk_packet_handler.size |
brunnobbco | 0:561d07a737bc | 2054 | - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 2055 | } |
brunnobbco | 0:561d07a737bc | 2056 | |
brunnobbco | 0:561d07a737bc | 2057 | break; |
brunnobbco | 0:561d07a737bc | 2058 | |
brunnobbco | 0:561d07a737bc | 2059 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2060 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 2061 | write_to_register(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXTIMEOUT); |
brunnobbco | 0:561d07a737bc | 2062 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 2063 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 2064 | && (_radio_events->rx_timeout)) { |
brunnobbco | 0:561d07a737bc | 2065 | _radio_events->rx_timeout(); |
brunnobbco | 0:561d07a737bc | 2066 | } |
brunnobbco | 0:561d07a737bc | 2067 | break; |
brunnobbco | 0:561d07a737bc | 2068 | default: |
brunnobbco | 0:561d07a737bc | 2069 | break; |
brunnobbco | 0:561d07a737bc | 2070 | } |
brunnobbco | 0:561d07a737bc | 2071 | |
brunnobbco | 0:561d07a737bc | 2072 | break; |
brunnobbco | 0:561d07a737bc | 2073 | |
brunnobbco | 0:561d07a737bc | 2074 | case RF_TX_RUNNING: |
brunnobbco | 0:561d07a737bc | 2075 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2076 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2077 | // FifoLevel interrupt |
brunnobbco | 0:561d07a737bc | 2078 | if ((_rf_settings.fsk_packet_handler.size |
brunnobbco | 0:561d07a737bc | 2079 | - _rf_settings.fsk_packet_handler.nb_bytes) |
brunnobbco | 0:561d07a737bc | 2080 | > _rf_settings.fsk_packet_handler.chunk_size) { |
brunnobbco | 0:561d07a737bc | 2081 | write_fifo((_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes), |
brunnobbco | 0:561d07a737bc | 2082 | _rf_settings.fsk_packet_handler.chunk_size); |
brunnobbco | 0:561d07a737bc | 2083 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 2084 | _rf_settings.fsk_packet_handler.chunk_size; |
brunnobbco | 0:561d07a737bc | 2085 | } else { |
brunnobbco | 0:561d07a737bc | 2086 | // Write the last chunk of data |
brunnobbco | 0:561d07a737bc | 2087 | write_fifo(_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes, |
brunnobbco | 0:561d07a737bc | 2088 | _rf_settings.fsk_packet_handler.size |
brunnobbco | 0:561d07a737bc | 2089 | - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 2090 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 2091 | _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes; |
brunnobbco | 0:561d07a737bc | 2092 | } |
brunnobbco | 0:561d07a737bc | 2093 | |
brunnobbco | 0:561d07a737bc | 2094 | break; |
brunnobbco | 0:561d07a737bc | 2095 | |
brunnobbco | 0:561d07a737bc | 2096 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2097 | break; |
brunnobbco | 0:561d07a737bc | 2098 | default: |
brunnobbco | 0:561d07a737bc | 2099 | break; |
brunnobbco | 0:561d07a737bc | 2100 | } |
brunnobbco | 0:561d07a737bc | 2101 | break; |
brunnobbco | 0:561d07a737bc | 2102 | default: |
brunnobbco | 0:561d07a737bc | 2103 | break; |
brunnobbco | 0:561d07a737bc | 2104 | } |
brunnobbco | 0:561d07a737bc | 2105 | } |
brunnobbco | 0:561d07a737bc | 2106 | |
brunnobbco | 0:561d07a737bc | 2107 | void SX1276_LoRaRadio::handle_dio2_irq(void) |
brunnobbco | 0:561d07a737bc | 2108 | { |
brunnobbco | 0:561d07a737bc | 2109 | switch (_rf_settings.state) { |
brunnobbco | 0:561d07a737bc | 2110 | case RF_RX_RUNNING: |
brunnobbco | 0:561d07a737bc | 2111 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2112 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2113 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 2114 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 2115 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 2116 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 2117 | |
brunnobbco | 0:561d07a737bc | 2118 | // Clear Irqs |
brunnobbco | 0:561d07a737bc | 2119 | write_to_register(REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | |
brunnobbco | 0:561d07a737bc | 2120 | RF_IRQFLAGS1_PREAMBLEDETECT | |
brunnobbco | 0:561d07a737bc | 2121 | RF_IRQFLAGS1_SYNCADDRESSMATCH | |
brunnobbco | 0:561d07a737bc | 2122 | RF_IRQFLAGS1_TIMEOUT); |
brunnobbco | 0:561d07a737bc | 2123 | |
brunnobbco | 0:561d07a737bc | 2124 | write_to_register( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN); |
brunnobbco | 0:561d07a737bc | 2125 | |
brunnobbco | 0:561d07a737bc | 2126 | if (_rf_settings.fsk.rx_continuous == true) { |
brunnobbco | 0:561d07a737bc | 2127 | // Continuous mode restart Rx chain |
brunnobbco | 0:561d07a737bc | 2128 | write_to_register( REG_RXCONFIG, |
brunnobbco | 0:561d07a737bc | 2129 | read_register(REG_RXCONFIG) | |
brunnobbco | 0:561d07a737bc | 2130 | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); |
brunnobbco | 0:561d07a737bc | 2131 | } else { |
brunnobbco | 0:561d07a737bc | 2132 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 2133 | } |
brunnobbco | 0:561d07a737bc | 2134 | |
brunnobbco | 0:561d07a737bc | 2135 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 2136 | && (_radio_events->rx_timeout)) { |
brunnobbco | 0:561d07a737bc | 2137 | _radio_events->rx_timeout(); |
brunnobbco | 0:561d07a737bc | 2138 | } |
brunnobbco | 0:561d07a737bc | 2139 | |
brunnobbco | 0:561d07a737bc | 2140 | break; |
brunnobbco | 0:561d07a737bc | 2141 | |
brunnobbco | 0:561d07a737bc | 2142 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2143 | if (_rf_settings.lora.freq_hop_on == true) { |
brunnobbco | 0:561d07a737bc | 2144 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 2145 | write_to_register(REG_LR_IRQFLAGS, |
brunnobbco | 0:561d07a737bc | 2146 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL); |
brunnobbco | 0:561d07a737bc | 2147 | |
brunnobbco | 0:561d07a737bc | 2148 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 2149 | && (_radio_events->fhss_change_channel)) { |
brunnobbco | 0:561d07a737bc | 2150 | _radio_events->fhss_change_channel( |
brunnobbco | 0:561d07a737bc | 2151 | (read_register(REG_LR_HOPCHANNEL) |
brunnobbco | 0:561d07a737bc | 2152 | & RFLR_HOPCHANNEL_CHANNEL_MASK)); |
brunnobbco | 0:561d07a737bc | 2153 | } |
brunnobbco | 0:561d07a737bc | 2154 | } |
brunnobbco | 0:561d07a737bc | 2155 | |
brunnobbco | 0:561d07a737bc | 2156 | break; |
brunnobbco | 0:561d07a737bc | 2157 | |
brunnobbco | 0:561d07a737bc | 2158 | default: |
brunnobbco | 0:561d07a737bc | 2159 | break; |
brunnobbco | 0:561d07a737bc | 2160 | } |
brunnobbco | 0:561d07a737bc | 2161 | |
brunnobbco | 0:561d07a737bc | 2162 | break; |
brunnobbco | 0:561d07a737bc | 2163 | |
brunnobbco | 0:561d07a737bc | 2164 | case RF_TX_RUNNING: |
brunnobbco | 0:561d07a737bc | 2165 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2166 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2167 | break; |
brunnobbco | 0:561d07a737bc | 2168 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2169 | if (_rf_settings.lora.freq_hop_on == true) { |
brunnobbco | 0:561d07a737bc | 2170 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 2171 | write_to_register(REG_LR_IRQFLAGS, |
brunnobbco | 0:561d07a737bc | 2172 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL); |
brunnobbco | 0:561d07a737bc | 2173 | |
brunnobbco | 0:561d07a737bc | 2174 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 2175 | && (_radio_events->fhss_change_channel)) { |
brunnobbco | 0:561d07a737bc | 2176 | _radio_events->fhss_change_channel( |
brunnobbco | 0:561d07a737bc | 2177 | (read_register(REG_LR_HOPCHANNEL) |
brunnobbco | 0:561d07a737bc | 2178 | & RFLR_HOPCHANNEL_CHANNEL_MASK)); |
brunnobbco | 0:561d07a737bc | 2179 | } |
brunnobbco | 0:561d07a737bc | 2180 | } |
brunnobbco | 0:561d07a737bc | 2181 | break; |
brunnobbco | 0:561d07a737bc | 2182 | default: |
brunnobbco | 0:561d07a737bc | 2183 | break; |
brunnobbco | 0:561d07a737bc | 2184 | } |
brunnobbco | 0:561d07a737bc | 2185 | break; |
brunnobbco | 0:561d07a737bc | 2186 | default: |
brunnobbco | 0:561d07a737bc | 2187 | break; |
brunnobbco | 0:561d07a737bc | 2188 | } |
brunnobbco | 0:561d07a737bc | 2189 | } |
brunnobbco | 0:561d07a737bc | 2190 | |
brunnobbco | 0:561d07a737bc | 2191 | void SX1276_LoRaRadio::handle_dio3_irq(void) |
brunnobbco | 0:561d07a737bc | 2192 | { |
brunnobbco | 0:561d07a737bc | 2193 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2194 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2195 | break; |
brunnobbco | 0:561d07a737bc | 2196 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2197 | if ((read_register(REG_LR_IRQFLAGS) & RFLR_IRQFLAGS_CADDETECTED) |
brunnobbco | 0:561d07a737bc | 2198 | == RFLR_IRQFLAGS_CADDETECTED) { |
brunnobbco | 0:561d07a737bc | 2199 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 2200 | write_to_register(REG_LR_IRQFLAGS, |
brunnobbco | 0:561d07a737bc | 2201 | RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE); |
brunnobbco | 0:561d07a737bc | 2202 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 2203 | && (_radio_events->cad_done)) { |
brunnobbco | 0:561d07a737bc | 2204 | _radio_events->cad_done(true); |
brunnobbco | 0:561d07a737bc | 2205 | } |
brunnobbco | 0:561d07a737bc | 2206 | } else { |
brunnobbco | 0:561d07a737bc | 2207 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 2208 | write_to_register(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE); |
brunnobbco | 0:561d07a737bc | 2209 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 2210 | && (_radio_events->cad_done)) { |
brunnobbco | 0:561d07a737bc | 2211 | _radio_events->cad_done(false); |
brunnobbco | 0:561d07a737bc | 2212 | } |
brunnobbco | 0:561d07a737bc | 2213 | } |
brunnobbco | 0:561d07a737bc | 2214 | break; |
brunnobbco | 0:561d07a737bc | 2215 | default: |
brunnobbco | 0:561d07a737bc | 2216 | break; |
brunnobbco | 0:561d07a737bc | 2217 | } |
brunnobbco | 0:561d07a737bc | 2218 | } |
brunnobbco | 0:561d07a737bc | 2219 | |
brunnobbco | 0:561d07a737bc | 2220 | void SX1276_LoRaRadio::handle_dio4_irq(void) |
brunnobbco | 0:561d07a737bc | 2221 | { |
brunnobbco | 0:561d07a737bc | 2222 | // is asserted when a preamble is detected (FSK modem only) |
brunnobbco | 0:561d07a737bc | 2223 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2224 | case MODEM_FSK: { |
brunnobbco | 0:561d07a737bc | 2225 | if (_rf_settings.fsk_packet_handler.preamble_detected == 0) { |
brunnobbco | 0:561d07a737bc | 2226 | _rf_settings.fsk_packet_handler.preamble_detected = 1; |
brunnobbco | 0:561d07a737bc | 2227 | } |
brunnobbco | 0:561d07a737bc | 2228 | } |
brunnobbco | 0:561d07a737bc | 2229 | break; |
brunnobbco | 0:561d07a737bc | 2230 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2231 | break; |
brunnobbco | 0:561d07a737bc | 2232 | default: |
brunnobbco | 0:561d07a737bc | 2233 | break; |
brunnobbco | 0:561d07a737bc | 2234 | } |
brunnobbco | 0:561d07a737bc | 2235 | } |
brunnobbco | 0:561d07a737bc | 2236 | |
brunnobbco | 0:561d07a737bc | 2237 | void SX1276_LoRaRadio::handle_dio5_irq() |
brunnobbco | 0:561d07a737bc | 2238 | { |
brunnobbco | 0:561d07a737bc | 2239 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 2240 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2241 | break; |
brunnobbco | 0:561d07a737bc | 2242 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2243 | break; |
brunnobbco | 0:561d07a737bc | 2244 | default: |
brunnobbco | 0:561d07a737bc | 2245 | break; |
brunnobbco | 0:561d07a737bc | 2246 | } |
brunnobbco | 0:561d07a737bc | 2247 | } |
brunnobbco | 0:561d07a737bc | 2248 | |
brunnobbco | 0:561d07a737bc | 2249 | void SX1276_LoRaRadio::handle_timeout_irq() |
brunnobbco | 0:561d07a737bc | 2250 | { |
brunnobbco | 0:561d07a737bc | 2251 | tx_timeout_timer.detach(); |
brunnobbco | 0:561d07a737bc | 2252 | |
brunnobbco | 0:561d07a737bc | 2253 | if (_rf_settings.state == RF_TX_RUNNING) { |
brunnobbco | 0:561d07a737bc | 2254 | // Tx timeout shouldn't happen. |
brunnobbco | 0:561d07a737bc | 2255 | // But it has been observed that when it happens it is a result of a |
brunnobbco | 0:561d07a737bc | 2256 | // corrupted SPI transfer |
brunnobbco | 0:561d07a737bc | 2257 | // The workaround is to put the radio in a known state. |
brunnobbco | 0:561d07a737bc | 2258 | // Thus, we re-initialize it. |
brunnobbco | 0:561d07a737bc | 2259 | |
brunnobbco | 0:561d07a737bc | 2260 | // Initialize radio default values |
brunnobbco | 0:561d07a737bc | 2261 | set_operation_mode(RF_OPMODE_SLEEP); |
brunnobbco | 0:561d07a737bc | 2262 | |
brunnobbco | 0:561d07a737bc | 2263 | setup_registers(); |
brunnobbco | 0:561d07a737bc | 2264 | |
brunnobbco | 0:561d07a737bc | 2265 | set_modem(MODEM_FSK); |
brunnobbco | 0:561d07a737bc | 2266 | |
brunnobbco | 0:561d07a737bc | 2267 | // Restore previous network type setting. |
brunnobbco | 0:561d07a737bc | 2268 | set_public_network(_rf_settings.lora.public_network); |
brunnobbco | 0:561d07a737bc | 2269 | |
brunnobbco | 0:561d07a737bc | 2270 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 2271 | |
brunnobbco | 0:561d07a737bc | 2272 | if ((_radio_events != NULL) && (_radio_events->tx_timeout)) { |
brunnobbco | 0:561d07a737bc | 2273 | _radio_events->tx_timeout(); |
brunnobbco | 0:561d07a737bc | 2274 | } |
brunnobbco | 0:561d07a737bc | 2275 | } |
brunnobbco | 0:561d07a737bc | 2276 | } |
brunnobbco | 0:561d07a737bc | 2277 | // EOF |