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

Committer:
brunnobbco
Date:
Thu Nov 12 22:09:59 2020 +0000
Revision:
2:6c5853c2fd72
Parent:
0:561d07a737bc
Removed debug related code.

Who changed what in which revision?

UserRevisionLine numberNew 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