Brunno Oliveira / pulga-lorawan-drv

Dependents:   pulga-mbed-lorawan-gps mbed-lorawan-pulga mbed-lorawan-pulga-testing-channel mbed-lorawan-pulga-serial_rx ... more

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