testing hex for lorawan communication
SX1272/SX1272_LoRaRadio.cpp@2:6c5853c2fd72, 2020-11-12 (annotated)
- Committer:
- brunnobbco
- Date:
- Thu Nov 12 22:09:59 2020 +0000
- Revision:
- 2:6c5853c2fd72
- Parent:
- 1:3bdd6f917bf5
Removed debug related code.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
brunnobbco | 0:561d07a737bc | 1 | /** |
brunnobbco | 0:561d07a737bc | 2 | / _____) _ | | |
brunnobbco | 0:561d07a737bc | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ |
brunnobbco | 0:561d07a737bc | 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ |
brunnobbco | 0:561d07a737bc | 5 | _____) ) ____| | | || |_| ____( (___| | | | |
brunnobbco | 0:561d07a737bc | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| |
brunnobbco | 0:561d07a737bc | 7 | (C)2013 Semtech |
brunnobbco | 0:561d07a737bc | 8 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ |
brunnobbco | 0:561d07a737bc | 9 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| |
brunnobbco | 0:561d07a737bc | 10 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| |
brunnobbco | 0:561d07a737bc | 11 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| |
brunnobbco | 0:561d07a737bc | 12 | embedded.connectivity.solutions=============== |
brunnobbco | 0:561d07a737bc | 13 | |
brunnobbco | 0:561d07a737bc | 14 | Description: 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 | 0:561d07a737bc | 52 | SX1272MB2XAS, |
brunnobbco | 0:561d07a737bc | 53 | SX1272MB1DCS |
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 | 0:561d07a737bc | 177 | _ant_switch(antswitch, PIN_INPUT, PullUp, 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 | printf("transmit fsk!\n"); |
brunnobbco | 0:561d07a737bc | 820 | |
brunnobbco | 0:561d07a737bc | 821 | break; |
brunnobbco | 0:561d07a737bc | 822 | |
brunnobbco | 0:561d07a737bc | 823 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 824 | |
brunnobbco | 1:3bdd6f917bf5 | 825 | if (_rf_settings.lora.freq_hop_on == true) |
brunnobbco | 1:3bdd6f917bf5 | 826 | { |
brunnobbco | 0:561d07a737bc | 827 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 828 | RFLR_IRQFLAGS_RXTIMEOUT | |
brunnobbco | 0:561d07a737bc | 829 | RFLR_IRQFLAGS_RXDONE | |
brunnobbco | 0:561d07a737bc | 830 | RFLR_IRQFLAGS_PAYLOADCRCERROR | |
brunnobbco | 0:561d07a737bc | 831 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 832 | RFLR_IRQFLAGS_CADDONE | |
brunnobbco | 0:561d07a737bc | 833 | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 834 | |
brunnobbco | 0:561d07a737bc | 835 | // DIO0=tx_done, DIO2=fhss_change_channel |
brunnobbco | 0:561d07a737bc | 836 | |
brunnobbco | 0:561d07a737bc | 837 | write_to_register(REG_DIOMAPPING1, (read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 838 | RFLR_DIOMAPPING1_DIO0_MASK & |
brunnobbco | 0:561d07a737bc | 839 | RFLR_DIOMAPPING1_DIO2_MASK) | |
brunnobbco | 0:561d07a737bc | 840 | RFLR_DIOMAPPING1_DIO0_01 | |
brunnobbco | 0:561d07a737bc | 841 | RFLR_DIOMAPPING1_DIO2_01); |
brunnobbco | 1:3bdd6f917bf5 | 842 | } |
brunnobbco | 1:3bdd6f917bf5 | 843 | else |
brunnobbco | 1:3bdd6f917bf5 | 844 | { |
brunnobbco | 0:561d07a737bc | 845 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 846 | RFLR_IRQFLAGS_RXTIMEOUT | |
brunnobbco | 0:561d07a737bc | 847 | RFLR_IRQFLAGS_RXDONE | |
brunnobbco | 0:561d07a737bc | 848 | RFLR_IRQFLAGS_PAYLOADCRCERROR | |
brunnobbco | 0:561d07a737bc | 849 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 850 | RFLR_IRQFLAGS_CADDONE | |
brunnobbco | 0:561d07a737bc | 851 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | |
brunnobbco | 0:561d07a737bc | 852 | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 853 | |
brunnobbco | 0:561d07a737bc | 854 | // DIO0=tx_done |
brunnobbco | 0:561d07a737bc | 855 | write_to_register(REG_DIOMAPPING1,(read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 856 | RFLR_DIOMAPPING1_DIO0_MASK) | |
brunnobbco | 0:561d07a737bc | 857 | RFLR_DIOMAPPING1_DIO0_01); |
brunnobbco | 0:561d07a737bc | 858 | } |
brunnobbco | 0:561d07a737bc | 859 | |
brunnobbco | 0:561d07a737bc | 860 | break; |
brunnobbco | 0:561d07a737bc | 861 | } |
brunnobbco | 0:561d07a737bc | 862 | |
brunnobbco | 0:561d07a737bc | 863 | _rf_settings.state = RF_TX_RUNNING; |
brunnobbco | 1:3bdd6f917bf5 | 864 | |
brunnobbco | 0:561d07a737bc | 865 | tx_timeout_timer.attach_us(callback(this, &SX1272_LoRaRadio::timeout_irq_isr), |
brunnobbco | 0:561d07a737bc | 866 | timeout * 1000); |
brunnobbco | 1:3bdd6f917bf5 | 867 | |
brunnobbco | 1:3bdd6f917bf5 | 868 | if ((_rf_settings.modem == MODEM_LORA) && (_rf_settings.lora.freq_hop_on == true)) |
brunnobbco | 1:3bdd6f917bf5 | 869 | { |
brunnobbco | 1:3bdd6f917bf5 | 870 | lora_hop_timer.attach_us(callback(this, &SX1272_LoRaRadio::lrhop_irq_isr), 1000); |
brunnobbco | 1:3bdd6f917bf5 | 871 | } |
brunnobbco | 1:3bdd6f917bf5 | 872 | |
brunnobbco | 0:561d07a737bc | 873 | set_operation_mode(RF_OPMODE_TRANSMITTER); |
brunnobbco | 0:561d07a737bc | 874 | } |
brunnobbco | 0:561d07a737bc | 875 | |
brunnobbco | 0:561d07a737bc | 876 | /** |
brunnobbco | 0:561d07a737bc | 877 | * Sets the radio module in receive mode |
brunnobbco | 0:561d07a737bc | 878 | * |
brunnobbco | 0:561d07a737bc | 879 | * A DIO4 interrupt let's the state machine know that a preamble is detected |
brunnobbco | 0:561d07a737bc | 880 | * and finally a DIO0 interrupt let's the state machine know that a packet is |
brunnobbco | 0:561d07a737bc | 881 | * ready to be read from the FIFO |
brunnobbco | 0:561d07a737bc | 882 | */ |
brunnobbco | 0:561d07a737bc | 883 | void SX1272_LoRaRadio::receive(void) |
brunnobbco | 0:561d07a737bc | 884 | { |
brunnobbco | 0:561d07a737bc | 885 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 886 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 887 | // DIO0=PayloadReady |
brunnobbco | 0:561d07a737bc | 888 | // DIO1=FifoLevel |
brunnobbco | 0:561d07a737bc | 889 | // DIO2=RxTimeout |
brunnobbco | 0:561d07a737bc | 890 | // DIO3=FifoEmpty |
brunnobbco | 0:561d07a737bc | 891 | // DIO4=Preamble |
brunnobbco | 0:561d07a737bc | 892 | // DIO5=ModeReady |
brunnobbco | 0:561d07a737bc | 893 | write_to_register(REG_DIOMAPPING1, (read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 894 | RF_DIOMAPPING1_DIO0_MASK & |
brunnobbco | 0:561d07a737bc | 895 | RF_DIOMAPPING1_DIO1_MASK & |
brunnobbco | 0:561d07a737bc | 896 | RF_DIOMAPPING1_DIO2_MASK) | |
brunnobbco | 0:561d07a737bc | 897 | RF_DIOMAPPING1_DIO0_00 | |
brunnobbco | 0:561d07a737bc | 898 | RF_DIOMAPPING1_DIO1_00 | |
brunnobbco | 0:561d07a737bc | 899 | RF_DIOMAPPING1_DIO2_10); |
brunnobbco | 0:561d07a737bc | 900 | |
brunnobbco | 0:561d07a737bc | 901 | write_to_register(REG_DIOMAPPING2, (read_register(REG_DIOMAPPING2) & |
brunnobbco | 0:561d07a737bc | 902 | RF_DIOMAPPING2_DIO4_MASK & |
brunnobbco | 0:561d07a737bc | 903 | RF_DIOMAPPING2_MAP_MASK) | |
brunnobbco | 0:561d07a737bc | 904 | RF_DIOMAPPING2_DIO4_11 | |
brunnobbco | 0:561d07a737bc | 905 | RF_DIOMAPPING2_MAP_PREAMBLEDETECT); |
brunnobbco | 0:561d07a737bc | 906 | |
brunnobbco | 0:561d07a737bc | 907 | _rf_settings.fsk_packet_handler.fifo_thresh = |
brunnobbco | 0:561d07a737bc | 908 | read_register(REG_FIFOTHRESH) & 0x3F; |
brunnobbco | 0:561d07a737bc | 909 | |
brunnobbco | 0:561d07a737bc | 910 | write_to_register(REG_RXCONFIG, RF_RXCONFIG_AFCAUTO_ON | |
brunnobbco | 0:561d07a737bc | 911 | RF_RXCONFIG_AGCAUTO_ON | |
brunnobbco | 0:561d07a737bc | 912 | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT); |
brunnobbco | 0:561d07a737bc | 913 | |
brunnobbco | 0:561d07a737bc | 914 | if (!_rf_settings.fsk.rx_continuous) { |
brunnobbco | 0:561d07a737bc | 915 | // the value for rx timeout in symbols cannot be more than 255 |
brunnobbco | 0:561d07a737bc | 916 | // as the preamble length is fixed. We assert here for quick |
brunnobbco | 0:561d07a737bc | 917 | // diagnostics |
brunnobbco | 0:561d07a737bc | 918 | MBED_ASSERT(_rf_settings.fsk.rx_single_timeout <= 255); |
brunnobbco | 0:561d07a737bc | 919 | write_to_register(REG_RXTIMEOUT2, _rf_settings.fsk.rx_single_timeout); |
brunnobbco | 0:561d07a737bc | 920 | write_to_register(REG_RXTIMEOUT3, 0x00); |
brunnobbco | 0:561d07a737bc | 921 | write_to_register(REG_RXTIMEOUT1, 0x00); |
brunnobbco | 0:561d07a737bc | 922 | } |
brunnobbco | 0:561d07a737bc | 923 | |
brunnobbco | 0:561d07a737bc | 924 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 925 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 926 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 927 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 928 | |
brunnobbco | 0:561d07a737bc | 929 | printf("receive fsk!\n"); |
brunnobbco | 0:561d07a737bc | 930 | |
brunnobbco | 0:561d07a737bc | 931 | break; |
brunnobbco | 0:561d07a737bc | 932 | |
brunnobbco | 0:561d07a737bc | 933 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 934 | |
brunnobbco | 0:561d07a737bc | 935 | if (_rf_settings.lora.iq_inverted == true) { |
brunnobbco | 0:561d07a737bc | 936 | write_to_register(REG_LR_INVERTIQ, ((read_register(REG_LR_INVERTIQ) & |
brunnobbco | 0:561d07a737bc | 937 | RFLR_INVERTIQ_TX_MASK & |
brunnobbco | 0:561d07a737bc | 938 | RFLR_INVERTIQ_RX_MASK) | |
brunnobbco | 0:561d07a737bc | 939 | RFLR_INVERTIQ_RX_ON | |
brunnobbco | 0:561d07a737bc | 940 | RFLR_INVERTIQ_TX_OFF)); |
brunnobbco | 0:561d07a737bc | 941 | write_to_register(REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON); |
brunnobbco | 0:561d07a737bc | 942 | } else { |
brunnobbco | 0:561d07a737bc | 943 | write_to_register(REG_LR_INVERTIQ, ((read_register(REG_LR_INVERTIQ) & |
brunnobbco | 0:561d07a737bc | 944 | RFLR_INVERTIQ_TX_MASK & |
brunnobbco | 0:561d07a737bc | 945 | RFLR_INVERTIQ_RX_MASK) | |
brunnobbco | 0:561d07a737bc | 946 | RFLR_INVERTIQ_RX_OFF | |
brunnobbco | 0:561d07a737bc | 947 | RFLR_INVERTIQ_TX_OFF)); |
brunnobbco | 0:561d07a737bc | 948 | write_to_register( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF); |
brunnobbco | 0:561d07a737bc | 949 | } |
brunnobbco | 0:561d07a737bc | 950 | |
brunnobbco | 0:561d07a737bc | 951 | if (_rf_settings.lora.freq_hop_on == true) { |
brunnobbco | 0:561d07a737bc | 952 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 953 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 954 | RFLR_IRQFLAGS_TXDONE | |
brunnobbco | 0:561d07a737bc | 955 | RFLR_IRQFLAGS_CADDONE | |
brunnobbco | 0:561d07a737bc | 956 | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 957 | |
brunnobbco | 0:561d07a737bc | 958 | // DIO0=rx_done, DIO2=fhss_change_channel |
brunnobbco | 0:561d07a737bc | 959 | write_to_register(REG_DIOMAPPING1, (read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 960 | RFLR_DIOMAPPING1_DIO0_MASK & |
brunnobbco | 0:561d07a737bc | 961 | RFLR_DIOMAPPING1_DIO2_MASK) | |
brunnobbco | 0:561d07a737bc | 962 | RFLR_DIOMAPPING1_DIO0_00 | |
brunnobbco | 0:561d07a737bc | 963 | RFLR_DIOMAPPING1_DIO2_00); |
brunnobbco | 0:561d07a737bc | 964 | } else { |
brunnobbco | 0:561d07a737bc | 965 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 966 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 967 | RFLR_IRQFLAGS_TXDONE | |
brunnobbco | 0:561d07a737bc | 968 | RFLR_IRQFLAGS_CADDONE | |
brunnobbco | 0:561d07a737bc | 969 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | |
brunnobbco | 0:561d07a737bc | 970 | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 971 | |
brunnobbco | 0:561d07a737bc | 972 | // DIO0=rx_done |
brunnobbco | 0:561d07a737bc | 973 | write_to_register(REG_DIOMAPPING1, (read_register(REG_DIOMAPPING1) & |
brunnobbco | 0:561d07a737bc | 974 | RFLR_DIOMAPPING1_DIO0_MASK) | |
brunnobbco | 0:561d07a737bc | 975 | RFLR_DIOMAPPING1_DIO0_00); |
brunnobbco | 0:561d07a737bc | 976 | } |
brunnobbco | 0:561d07a737bc | 977 | |
brunnobbco | 0:561d07a737bc | 978 | write_to_register(REG_LR_FIFORXBASEADDR, 0); |
brunnobbco | 0:561d07a737bc | 979 | write_to_register(REG_LR_FIFOADDRPTR, 0); |
brunnobbco | 0:561d07a737bc | 980 | |
brunnobbco | 0:561d07a737bc | 981 | break; |
brunnobbco | 0:561d07a737bc | 982 | } |
brunnobbco | 0:561d07a737bc | 983 | |
brunnobbco | 0:561d07a737bc | 984 | memset(_data_buffer, 0, (size_t) MAX_DATA_BUFFER_SIZE_SX172); |
brunnobbco | 0:561d07a737bc | 985 | |
brunnobbco | 0:561d07a737bc | 986 | _rf_settings.state = RF_RX_RUNNING; |
brunnobbco | 0:561d07a737bc | 987 | |
brunnobbco | 0:561d07a737bc | 988 | if (_rf_settings.modem == MODEM_FSK) { |
brunnobbco | 0:561d07a737bc | 989 | set_operation_mode(RF_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 990 | return; |
brunnobbco | 0:561d07a737bc | 991 | } |
brunnobbco | 0:561d07a737bc | 992 | |
brunnobbco | 0:561d07a737bc | 993 | // If mode is LoRa set mode |
brunnobbco | 0:561d07a737bc | 994 | if (_rf_settings.lora.rx_continuous == true) { |
brunnobbco | 0:561d07a737bc | 995 | set_operation_mode(RFLR_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 996 | } |
brunnobbco | 0:561d07a737bc | 997 | else |
brunnobbco | 0:561d07a737bc | 998 | { |
brunnobbco | 1:3bdd6f917bf5 | 999 | set_operation_mode(RFLR_OPMODE_RECEIVER_SINGLE); |
brunnobbco | 0:561d07a737bc | 1000 | rx_sync_timer.attach_us(callback(this, &SX1272_LoRaRadio::rxsync_irq_isr), 1000); |
brunnobbco | 1:3bdd6f917bf5 | 1001 | } |
brunnobbco | 1:3bdd6f917bf5 | 1002 | |
brunnobbco | 1:3bdd6f917bf5 | 1003 | if (_rf_settings.lora.freq_hop_on == true) |
brunnobbco | 1:3bdd6f917bf5 | 1004 | { |
brunnobbco | 1:3bdd6f917bf5 | 1005 | lora_hop_timer.attach_us(callback(this, &SX1272_LoRaRadio::lrhop_irq_isr), 1000); |
brunnobbco | 0:561d07a737bc | 1006 | } |
brunnobbco | 0:561d07a737bc | 1007 | } |
brunnobbco | 0:561d07a737bc | 1008 | |
brunnobbco | 0:561d07a737bc | 1009 | /** |
brunnobbco | 0:561d07a737bc | 1010 | * Puts a limit on the size of payload the module can handle |
brunnobbco | 0:561d07a737bc | 1011 | * By default it is MAX, i.e., 256 bytes |
brunnobbco | 0:561d07a737bc | 1012 | */ |
brunnobbco | 0:561d07a737bc | 1013 | void SX1272_LoRaRadio::set_max_payload_length(radio_modems_t modem, uint8_t max) |
brunnobbco | 0:561d07a737bc | 1014 | { |
brunnobbco | 0:561d07a737bc | 1015 | set_modem(modem); |
brunnobbco | 0:561d07a737bc | 1016 | |
brunnobbco | 0:561d07a737bc | 1017 | switch (modem) { |
brunnobbco | 0:561d07a737bc | 1018 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1019 | if (_rf_settings.fsk.fix_len == false) { |
brunnobbco | 0:561d07a737bc | 1020 | write_to_register(REG_PAYLOADLENGTH, max); |
brunnobbco | 0:561d07a737bc | 1021 | } |
brunnobbco | 0:561d07a737bc | 1022 | break; |
brunnobbco | 0:561d07a737bc | 1023 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1024 | write_to_register(REG_LR_PAYLOADMAXLENGTH, max); |
brunnobbco | 0:561d07a737bc | 1025 | break; |
brunnobbco | 0:561d07a737bc | 1026 | } |
brunnobbco | 0:561d07a737bc | 1027 | } |
brunnobbco | 0:561d07a737bc | 1028 | |
brunnobbco | 0:561d07a737bc | 1029 | /** |
brunnobbco | 0:561d07a737bc | 1030 | * TODO: Making sure if this API is valid only for LoRa modulation ? |
brunnobbco | 0:561d07a737bc | 1031 | * |
brunnobbco | 0:561d07a737bc | 1032 | * Indicates if the node is part of a private or public network |
brunnobbco | 0:561d07a737bc | 1033 | */ |
brunnobbco | 0:561d07a737bc | 1034 | void SX1272_LoRaRadio::set_public_network(bool enable) |
brunnobbco | 0:561d07a737bc | 1035 | { |
brunnobbco | 0:561d07a737bc | 1036 | set_modem(MODEM_LORA); |
brunnobbco | 0:561d07a737bc | 1037 | |
brunnobbco | 0:561d07a737bc | 1038 | _rf_settings.lora.public_network = enable; |
brunnobbco | 0:561d07a737bc | 1039 | if (enable == true) { |
brunnobbco | 0:561d07a737bc | 1040 | // Change lora modem SyncWord |
brunnobbco | 0:561d07a737bc | 1041 | write_to_register(REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD); |
brunnobbco | 0:561d07a737bc | 1042 | } else { |
brunnobbco | 0:561d07a737bc | 1043 | // Change lora modem SyncWord |
brunnobbco | 0:561d07a737bc | 1044 | write_to_register(REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD); |
brunnobbco | 0:561d07a737bc | 1045 | } |
brunnobbco | 0:561d07a737bc | 1046 | |
brunnobbco | 0:561d07a737bc | 1047 | } |
brunnobbco | 0:561d07a737bc | 1048 | |
brunnobbco | 0:561d07a737bc | 1049 | /** |
brunnobbco | 0:561d07a737bc | 1050 | * Perform carrier sensing |
brunnobbco | 0:561d07a737bc | 1051 | * |
brunnobbco | 0:561d07a737bc | 1052 | * Checks for a certain time if the RSSI is above a given threshold. |
brunnobbco | 0:561d07a737bc | 1053 | * This threshold determines if there is already a transmission going on |
brunnobbco | 0:561d07a737bc | 1054 | * in the channel or not. |
brunnobbco | 0:561d07a737bc | 1055 | * |
brunnobbco | 0:561d07a737bc | 1056 | */ |
brunnobbco | 0:561d07a737bc | 1057 | bool SX1272_LoRaRadio::perform_carrier_sense(radio_modems_t modem, |
brunnobbco | 0:561d07a737bc | 1058 | uint32_t freq, |
brunnobbco | 0:561d07a737bc | 1059 | int16_t rssi_threshold, |
brunnobbco | 0:561d07a737bc | 1060 | uint32_t max_carrier_sense_time) |
brunnobbco | 0:561d07a737bc | 1061 | { |
brunnobbco | 0:561d07a737bc | 1062 | bool status = true; |
brunnobbco | 0:561d07a737bc | 1063 | int16_t rssi = 0; |
brunnobbco | 0:561d07a737bc | 1064 | |
brunnobbco | 0:561d07a737bc | 1065 | set_modem(modem); |
brunnobbco | 0:561d07a737bc | 1066 | set_channel(freq); |
brunnobbco | 0:561d07a737bc | 1067 | set_operation_mode(RF_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 1068 | |
brunnobbco | 0:561d07a737bc | 1069 | // hold on a bit, radio turn-around time |
brunnobbco | 0:561d07a737bc | 1070 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 1071 | |
brunnobbco | 0:561d07a737bc | 1072 | Timer elapsed_time; |
brunnobbco | 0:561d07a737bc | 1073 | elapsed_time.start(); |
brunnobbco | 0:561d07a737bc | 1074 | |
brunnobbco | 0:561d07a737bc | 1075 | // Perform carrier sense for maxCarrierSenseTime |
brunnobbco | 0:561d07a737bc | 1076 | while (elapsed_time.read_ms() < (int)max_carrier_sense_time) { |
brunnobbco | 0:561d07a737bc | 1077 | rssi = get_rssi(modem); |
brunnobbco | 0:561d07a737bc | 1078 | |
brunnobbco | 0:561d07a737bc | 1079 | if (rssi > rssi_threshold) { |
brunnobbco | 0:561d07a737bc | 1080 | status = false; |
brunnobbco | 0:561d07a737bc | 1081 | break; |
brunnobbco | 0:561d07a737bc | 1082 | } |
brunnobbco | 0:561d07a737bc | 1083 | } |
brunnobbco | 0:561d07a737bc | 1084 | |
brunnobbco | 0:561d07a737bc | 1085 | sleep(); |
brunnobbco | 0:561d07a737bc | 1086 | return status; |
brunnobbco | 0:561d07a737bc | 1087 | } |
brunnobbco | 0:561d07a737bc | 1088 | |
brunnobbco | 0:561d07a737bc | 1089 | /** |
brunnobbco | 0:561d07a737bc | 1090 | * Channel Activity detection (can be done only in LoRa mode) |
brunnobbco | 0:561d07a737bc | 1091 | * |
brunnobbco | 0:561d07a737bc | 1092 | * If any activity on the channel is detected, an interrupt is asserted on |
brunnobbco | 0:561d07a737bc | 1093 | * DIO3. A callback will be generated to the stack/application upon the |
brunnobbco | 0:561d07a737bc | 1094 | * assertion of DIO3. |
brunnobbco | 0:561d07a737bc | 1095 | */ |
brunnobbco | 0:561d07a737bc | 1096 | void SX1272_LoRaRadio::start_cad() |
brunnobbco | 0:561d07a737bc | 1097 | { |
brunnobbco | 0:561d07a737bc | 1098 | uint8_t reg_val; |
brunnobbco | 0:561d07a737bc | 1099 | |
brunnobbco | 0:561d07a737bc | 1100 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 1101 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1102 | break; |
brunnobbco | 0:561d07a737bc | 1103 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1104 | write_to_register(REG_LR_IRQFLAGSMASK, |
brunnobbco | 0:561d07a737bc | 1105 | RFLR_IRQFLAGS_RXTIMEOUT | |
brunnobbco | 0:561d07a737bc | 1106 | RFLR_IRQFLAGS_RXDONE | |
brunnobbco | 0:561d07a737bc | 1107 | RFLR_IRQFLAGS_PAYLOADCRCERROR | |
brunnobbco | 0:561d07a737bc | 1108 | RFLR_IRQFLAGS_VALIDHEADER | |
brunnobbco | 0:561d07a737bc | 1109 | RFLR_IRQFLAGS_TXDONE | |
brunnobbco | 0:561d07a737bc | 1110 | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL); |
brunnobbco | 0:561d07a737bc | 1111 | |
brunnobbco | 0:561d07a737bc | 1112 | // DIO3=CADDone |
brunnobbco | 0:561d07a737bc | 1113 | reg_val = read_register(REG_DIOMAPPING1); |
brunnobbco | 0:561d07a737bc | 1114 | write_to_register(REG_DIOMAPPING1, (reg_val & |
brunnobbco | 0:561d07a737bc | 1115 | RFLR_DIOMAPPING1_DIO3_MASK) | |
brunnobbco | 0:561d07a737bc | 1116 | RFLR_DIOMAPPING1_DIO3_00); |
brunnobbco | 0:561d07a737bc | 1117 | |
brunnobbco | 0:561d07a737bc | 1118 | set_operation_mode(RFLR_OPMODE_CAD); |
brunnobbco | 0:561d07a737bc | 1119 | _rf_settings.state = RF_CAD; |
brunnobbco | 1:3bdd6f917bf5 | 1120 | lora_cad_timer.attach_us(callback(this, &SX1272_LoRaRadio::lrcad_irq_isr), 1000); |
brunnobbco | 0:561d07a737bc | 1121 | break; |
brunnobbco | 0:561d07a737bc | 1122 | default: |
brunnobbco | 0:561d07a737bc | 1123 | break; |
brunnobbco | 0:561d07a737bc | 1124 | } |
brunnobbco | 0:561d07a737bc | 1125 | } |
brunnobbco | 0:561d07a737bc | 1126 | |
brunnobbco | 0:561d07a737bc | 1127 | /** |
brunnobbco | 0:561d07a737bc | 1128 | * Set transmission in continuous wave mode |
brunnobbco | 0:561d07a737bc | 1129 | */ |
brunnobbco | 0:561d07a737bc | 1130 | void SX1272_LoRaRadio::set_tx_continuous_wave(uint32_t freq, int8_t power, |
brunnobbco | 0:561d07a737bc | 1131 | uint16_t time) |
brunnobbco | 0:561d07a737bc | 1132 | { |
brunnobbco | 0:561d07a737bc | 1133 | uint8_t reg_val; |
brunnobbco | 0:561d07a737bc | 1134 | |
brunnobbco | 0:561d07a737bc | 1135 | set_channel(freq); |
brunnobbco | 0:561d07a737bc | 1136 | set_tx_config(MODEM_FSK, power, 0, 0, 4800, 0, 5, false, false, 0, 0, 0, time * 1000); |
brunnobbco | 0:561d07a737bc | 1137 | reg_val = read_register(REG_PACKETCONFIG2); |
brunnobbco | 0:561d07a737bc | 1138 | |
brunnobbco | 0:561d07a737bc | 1139 | write_to_register( REG_PACKETCONFIG2, (reg_val & RF_PACKETCONFIG2_DATAMODE_MASK ) ); |
brunnobbco | 0:561d07a737bc | 1140 | // Disable radio interrupts |
brunnobbco | 0:561d07a737bc | 1141 | write_to_register( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 | RF_DIOMAPPING1_DIO1_11 ); |
brunnobbco | 0:561d07a737bc | 1142 | write_to_register( REG_DIOMAPPING2, RF_DIOMAPPING2_DIO4_10 | RF_DIOMAPPING2_DIO5_10 ); |
brunnobbco | 0:561d07a737bc | 1143 | |
brunnobbco | 0:561d07a737bc | 1144 | _rf_settings.state = RF_TX_RUNNING; |
brunnobbco | 0:561d07a737bc | 1145 | tx_timeout_timer.attach_us(callback(this, &SX1272_LoRaRadio::timeout_irq_isr), time * 1000000); |
brunnobbco | 0:561d07a737bc | 1146 | set_operation_mode(RF_OPMODE_TRANSMITTER); |
brunnobbco | 0:561d07a737bc | 1147 | } |
brunnobbco | 0:561d07a737bc | 1148 | |
brunnobbco | 0:561d07a737bc | 1149 | /** |
brunnobbco | 0:561d07a737bc | 1150 | * Put radio in Standby mode |
brunnobbco | 0:561d07a737bc | 1151 | */ |
brunnobbco | 0:561d07a737bc | 1152 | void SX1272_LoRaRadio::standby( void ) |
brunnobbco | 0:561d07a737bc | 1153 | { |
brunnobbco | 0:561d07a737bc | 1154 | tx_timeout_timer.detach(); |
brunnobbco | 0:561d07a737bc | 1155 | rx_sync_timer.detach(); |
brunnobbco | 1:3bdd6f917bf5 | 1156 | lora_cad_timer.detach(); |
brunnobbco | 1:3bdd6f917bf5 | 1157 | lora_hop_timer.detach(); |
brunnobbco | 0:561d07a737bc | 1158 | set_operation_mode(RF_OPMODE_STANDBY); |
brunnobbco | 0:561d07a737bc | 1159 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1160 | } |
brunnobbco | 0:561d07a737bc | 1161 | |
brunnobbco | 0:561d07a737bc | 1162 | /** |
brunnobbco | 0:561d07a737bc | 1163 | * Generates 32 bit random number based upon RSSI monitoring |
brunnobbco | 0:561d07a737bc | 1164 | * Used for various calculation by the stack for example dev nonce |
brunnobbco | 0:561d07a737bc | 1165 | * |
brunnobbco | 0:561d07a737bc | 1166 | * When this API is used modem is set in LoRa mode and all interrupts are |
brunnobbco | 0:561d07a737bc | 1167 | * masked. If the user had been using FSK mode, it should be noted that a |
brunnobbco | 0:561d07a737bc | 1168 | * change of mode is required again because the registers have changed. |
brunnobbco | 0:561d07a737bc | 1169 | * In addition to that RX and TX configuration APIs should be called again in |
brunnobbco | 0:561d07a737bc | 1170 | * order to have correct desires setup. |
brunnobbco | 0:561d07a737bc | 1171 | */ |
brunnobbco | 0:561d07a737bc | 1172 | uint32_t SX1272_LoRaRadio::random() |
brunnobbco | 0:561d07a737bc | 1173 | { |
brunnobbco | 0:561d07a737bc | 1174 | uint8_t i; |
brunnobbco | 0:561d07a737bc | 1175 | uint32_t rnd = 0; |
brunnobbco | 0:561d07a737bc | 1176 | |
brunnobbco | 0:561d07a737bc | 1177 | // Set LoRa modem ON |
brunnobbco | 0:561d07a737bc | 1178 | set_modem(MODEM_LORA); |
brunnobbco | 0:561d07a737bc | 1179 | |
brunnobbco | 0:561d07a737bc | 1180 | // Disable LoRa modem interrupts, i.e., mask all interrupts |
brunnobbco | 0:561d07a737bc | 1181 | write_to_register(REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | RFLR_IRQFLAGS_RXDONE |
brunnobbco | 0:561d07a737bc | 1182 | | RFLR_IRQFLAGS_PAYLOADCRCERROR | RFLR_IRQFLAGS_VALIDHEADER |
brunnobbco | 0:561d07a737bc | 1183 | | RFLR_IRQFLAGS_TXDONE | RFLR_IRQFLAGS_CADDONE |
brunnobbco | 0:561d07a737bc | 1184 | | RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | RFLR_IRQFLAGS_CADDETECTED); |
brunnobbco | 0:561d07a737bc | 1185 | |
brunnobbco | 0:561d07a737bc | 1186 | // Set radio in continuous reception |
brunnobbco | 0:561d07a737bc | 1187 | set_operation_mode(RF_OPMODE_RECEIVER); |
brunnobbco | 0:561d07a737bc | 1188 | |
brunnobbco | 0:561d07a737bc | 1189 | for (i = 0; i < 32; i++) { |
brunnobbco | 0:561d07a737bc | 1190 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 1191 | // Unfiltered RSSI value reading. Only takes the LSB value |
brunnobbco | 0:561d07a737bc | 1192 | rnd |= ((uint32_t) read_register(REG_LR_RSSIWIDEBAND) & 0x01) << i; |
brunnobbco | 0:561d07a737bc | 1193 | } |
brunnobbco | 0:561d07a737bc | 1194 | |
brunnobbco | 0:561d07a737bc | 1195 | sleep(); |
brunnobbco | 0:561d07a737bc | 1196 | |
brunnobbco | 0:561d07a737bc | 1197 | return rnd; |
brunnobbco | 0:561d07a737bc | 1198 | } |
brunnobbco | 0:561d07a737bc | 1199 | |
brunnobbco | 0:561d07a737bc | 1200 | |
brunnobbco | 0:561d07a737bc | 1201 | /***************************************************************************** |
brunnobbco | 0:561d07a737bc | 1202 | * Private APIs * |
brunnobbco | 0:561d07a737bc | 1203 | ****************************************************************************/ |
brunnobbco | 0:561d07a737bc | 1204 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1205 | /** |
brunnobbco | 0:561d07a737bc | 1206 | * Thread task handling IRQs |
brunnobbco | 0:561d07a737bc | 1207 | */ |
brunnobbco | 0:561d07a737bc | 1208 | void SX1272_LoRaRadio::rf_irq_task(void) |
brunnobbco | 0:561d07a737bc | 1209 | { |
brunnobbco | 0:561d07a737bc | 1210 | for (;;) { |
brunnobbco | 0:561d07a737bc | 1211 | uint32_t flags = ThisThread::flags_wait_any(0x7FFFFFFF); |
brunnobbco | 0:561d07a737bc | 1212 | |
brunnobbco | 0:561d07a737bc | 1213 | lock(); |
brunnobbco | 0:561d07a737bc | 1214 | if (flags & SIG_DIO0) { |
brunnobbco | 0:561d07a737bc | 1215 | handle_dio0_irq(); |
brunnobbco | 0:561d07a737bc | 1216 | } |
brunnobbco | 0:561d07a737bc | 1217 | if (flags & SIG_DIO1) { |
brunnobbco | 0:561d07a737bc | 1218 | handle_dio1_irq(); |
brunnobbco | 0:561d07a737bc | 1219 | } |
brunnobbco | 0:561d07a737bc | 1220 | if (flags & SIG_DIO2) { |
brunnobbco | 0:561d07a737bc | 1221 | handle_dio2_irq(); |
brunnobbco | 0:561d07a737bc | 1222 | } |
brunnobbco | 1:3bdd6f917bf5 | 1223 | if (flags & SIG_LRHOP) { |
brunnobbco | 1:3bdd6f917bf5 | 1224 | handle_lrhop_irq(); |
brunnobbco | 0:561d07a737bc | 1225 | } |
brunnobbco | 1:3bdd6f917bf5 | 1226 | if (flags & SIG_LRCAD) { |
brunnobbco | 1:3bdd6f917bf5 | 1227 | handle_lrcad_irq(); |
brunnobbco | 0:561d07a737bc | 1228 | } |
brunnobbco | 0:561d07a737bc | 1229 | if (flags & SIG_TIMOUT) { |
brunnobbco | 0:561d07a737bc | 1230 | handle_timeout_irq(); |
brunnobbco | 0:561d07a737bc | 1231 | } |
brunnobbco | 0:561d07a737bc | 1232 | if (flags & SIG_RXSYNC) { |
brunnobbco | 0:561d07a737bc | 1233 | handle_rxsync_irq(); |
brunnobbco | 0:561d07a737bc | 1234 | } |
brunnobbco | 0:561d07a737bc | 1235 | unlock(); |
brunnobbco | 0:561d07a737bc | 1236 | } |
brunnobbco | 0:561d07a737bc | 1237 | } |
brunnobbco | 0:561d07a737bc | 1238 | #endif |
brunnobbco | 0:561d07a737bc | 1239 | |
brunnobbco | 0:561d07a737bc | 1240 | /** |
brunnobbco | 0:561d07a737bc | 1241 | * Writes a single byte to a given register |
brunnobbco | 0:561d07a737bc | 1242 | */ |
brunnobbco | 0:561d07a737bc | 1243 | void SX1272_LoRaRadio::write_to_register(uint8_t addr, uint8_t data) |
brunnobbco | 0:561d07a737bc | 1244 | { |
brunnobbco | 0:561d07a737bc | 1245 | write_to_register(addr, &data, 1); |
brunnobbco | 0:561d07a737bc | 1246 | } |
brunnobbco | 0:561d07a737bc | 1247 | |
brunnobbco | 0:561d07a737bc | 1248 | /** |
brunnobbco | 0:561d07a737bc | 1249 | * Writes multiple bytes to a given register |
brunnobbco | 0:561d07a737bc | 1250 | */ |
brunnobbco | 0:561d07a737bc | 1251 | void SX1272_LoRaRadio::write_to_register(uint8_t addr, uint8_t *data, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1252 | { |
brunnobbco | 0:561d07a737bc | 1253 | // set chip-select low |
brunnobbco | 0:561d07a737bc | 1254 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 1255 | |
brunnobbco | 0:561d07a737bc | 1256 | // set write command |
brunnobbco | 0:561d07a737bc | 1257 | _spi.write(addr | SPI_WRITE_CMD); |
brunnobbco | 0:561d07a737bc | 1258 | |
brunnobbco | 0:561d07a737bc | 1259 | // write data |
brunnobbco | 0:561d07a737bc | 1260 | for (uint8_t i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 1261 | _spi.write(data[i]); |
brunnobbco | 0:561d07a737bc | 1262 | } |
brunnobbco | 0:561d07a737bc | 1263 | |
brunnobbco | 0:561d07a737bc | 1264 | // set chip-select high |
brunnobbco | 0:561d07a737bc | 1265 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 1266 | } |
brunnobbco | 0:561d07a737bc | 1267 | |
brunnobbco | 0:561d07a737bc | 1268 | /** |
brunnobbco | 0:561d07a737bc | 1269 | * Reads the value of a single register |
brunnobbco | 0:561d07a737bc | 1270 | */ |
brunnobbco | 0:561d07a737bc | 1271 | uint8_t SX1272_LoRaRadio::read_register(uint8_t addr) |
brunnobbco | 0:561d07a737bc | 1272 | { |
brunnobbco | 0:561d07a737bc | 1273 | uint8_t data; |
brunnobbco | 0:561d07a737bc | 1274 | read_register(addr, &data, 1); |
brunnobbco | 0:561d07a737bc | 1275 | return data; |
brunnobbco | 0:561d07a737bc | 1276 | } |
brunnobbco | 0:561d07a737bc | 1277 | |
brunnobbco | 0:561d07a737bc | 1278 | /** |
brunnobbco | 0:561d07a737bc | 1279 | * Reads multiple values from a given register |
brunnobbco | 0:561d07a737bc | 1280 | */ |
brunnobbco | 0:561d07a737bc | 1281 | void SX1272_LoRaRadio::read_register(uint8_t addr, uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1282 | { |
brunnobbco | 0:561d07a737bc | 1283 | // set chip-select low |
brunnobbco | 0:561d07a737bc | 1284 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 1285 | |
brunnobbco | 0:561d07a737bc | 1286 | // set read command |
brunnobbco | 0:561d07a737bc | 1287 | _spi.write(addr & SPI_READ_CMD); |
brunnobbco | 0:561d07a737bc | 1288 | |
brunnobbco | 0:561d07a737bc | 1289 | // read buffers |
brunnobbco | 0:561d07a737bc | 1290 | for (uint8_t i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 1291 | buffer[i] = _spi.write(0); |
brunnobbco | 0:561d07a737bc | 1292 | } |
brunnobbco | 0:561d07a737bc | 1293 | |
brunnobbco | 0:561d07a737bc | 1294 | // set chip-select high |
brunnobbco | 0:561d07a737bc | 1295 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 1296 | } |
brunnobbco | 0:561d07a737bc | 1297 | |
brunnobbco | 0:561d07a737bc | 1298 | /** |
brunnobbco | 0:561d07a737bc | 1299 | * Writes to FIIO provided by the chip |
brunnobbco | 0:561d07a737bc | 1300 | */ |
brunnobbco | 0:561d07a737bc | 1301 | void SX1272_LoRaRadio::write_fifo(uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1302 | { |
brunnobbco | 0:561d07a737bc | 1303 | write_to_register(0, buffer, size); |
brunnobbco | 0:561d07a737bc | 1304 | } |
brunnobbco | 0:561d07a737bc | 1305 | |
brunnobbco | 0:561d07a737bc | 1306 | /** |
brunnobbco | 0:561d07a737bc | 1307 | * Reads from the FIFO provided by the chip |
brunnobbco | 0:561d07a737bc | 1308 | */ |
brunnobbco | 0:561d07a737bc | 1309 | void SX1272_LoRaRadio::read_fifo(uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 1310 | { |
brunnobbco | 0:561d07a737bc | 1311 | read_register(0, buffer, size); |
brunnobbco | 0:561d07a737bc | 1312 | } |
brunnobbco | 0:561d07a737bc | 1313 | |
brunnobbco | 0:561d07a737bc | 1314 | /** |
brunnobbco | 0:561d07a737bc | 1315 | * Gets FSK bandwidth values |
brunnobbco | 0:561d07a737bc | 1316 | * |
brunnobbco | 0:561d07a737bc | 1317 | * Gives either normal bandwidths or bandwidths for |
brunnobbco | 0:561d07a737bc | 1318 | * AFC (auto frequency correction) |
brunnobbco | 0:561d07a737bc | 1319 | */ |
brunnobbco | 0:561d07a737bc | 1320 | uint8_t SX1272_LoRaRadio::get_fsk_bw_reg_val(uint32_t bandwidth) |
brunnobbco | 0:561d07a737bc | 1321 | { |
brunnobbco | 0:561d07a737bc | 1322 | uint8_t i; |
brunnobbco | 0:561d07a737bc | 1323 | |
brunnobbco | 0:561d07a737bc | 1324 | for (i = 0; i < (sizeof(fsk_bandwidths) / sizeof(fsk_bw_t)) - 1; i++) { |
brunnobbco | 0:561d07a737bc | 1325 | if ((bandwidth >= fsk_bandwidths[i].bandwidth) |
brunnobbco | 0:561d07a737bc | 1326 | && (bandwidth < fsk_bandwidths[i + 1].bandwidth)) { |
brunnobbco | 0:561d07a737bc | 1327 | return fsk_bandwidths[i].register_value; |
brunnobbco | 0:561d07a737bc | 1328 | } |
brunnobbco | 0:561d07a737bc | 1329 | } |
brunnobbco | 0:561d07a737bc | 1330 | // ERROR: Value not found |
brunnobbco | 0:561d07a737bc | 1331 | // This should never happen |
brunnobbco | 0:561d07a737bc | 1332 | while (1); |
brunnobbco | 0:561d07a737bc | 1333 | } |
brunnobbco | 0:561d07a737bc | 1334 | |
brunnobbco | 0:561d07a737bc | 1335 | /** |
brunnobbco | 0:561d07a737bc | 1336 | * Sets the radio modules to default position (off) |
brunnobbco | 0:561d07a737bc | 1337 | * |
brunnobbco | 0:561d07a737bc | 1338 | * Historically they were being called as Antenna switches, so we kept the name. |
brunnobbco | 0:561d07a737bc | 1339 | * In essence these are control latches over duplexer which either let |
brunnobbco | 0:561d07a737bc | 1340 | * TX submodule or RX submodule circuitry enabled at a time. |
brunnobbco | 0:561d07a737bc | 1341 | */ |
brunnobbco | 0:561d07a737bc | 1342 | void SX1272_LoRaRadio::default_antenna_switch_ctrls() |
brunnobbco | 0:561d07a737bc | 1343 | { |
brunnobbco | 0:561d07a737bc | 1344 | if (_rf_ctrls.pwr_amp_ctl != NC) { |
brunnobbco | 0:561d07a737bc | 1345 | _pwr_amp_ctl = 0; |
brunnobbco | 0:561d07a737bc | 1346 | } |
brunnobbco | 0:561d07a737bc | 1347 | |
brunnobbco | 0:561d07a737bc | 1348 | if (_rf_ctrls.rf_switch_ctl1 != NC && _rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1349 | _rf_switch_ctl1 = 0; |
brunnobbco | 0:561d07a737bc | 1350 | _rf_switch_ctl2 = 0; |
brunnobbco | 0:561d07a737bc | 1351 | } |
brunnobbco | 0:561d07a737bc | 1352 | |
brunnobbco | 0:561d07a737bc | 1353 | if (_rf_ctrls.txctl != NC && _rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1354 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1355 | _rxctl = 0; |
brunnobbco | 0:561d07a737bc | 1356 | } |
brunnobbco | 0:561d07a737bc | 1357 | } |
brunnobbco | 0:561d07a737bc | 1358 | |
brunnobbco | 0:561d07a737bc | 1359 | /** |
brunnobbco | 0:561d07a737bc | 1360 | * Gets the power amplifier configuration register |
brunnobbco | 0:561d07a737bc | 1361 | */ |
brunnobbco | 0:561d07a737bc | 1362 | uint8_t SX1272_LoRaRadio::get_pa_conf_reg() |
brunnobbco | 0:561d07a737bc | 1363 | { |
brunnobbco | 0:561d07a737bc | 1364 | if (radio_variant == SX1272UNDEFINED) { |
brunnobbco | 0:561d07a737bc | 1365 | return RF_PACONFIG_PASELECT_PABOOST; |
brunnobbco | 0:561d07a737bc | 1366 | } else if (radio_variant == SX1272MB1DCS) { |
brunnobbco | 0:561d07a737bc | 1367 | return RF_PACONFIG_PASELECT_PABOOST; |
brunnobbco | 0:561d07a737bc | 1368 | } else { |
brunnobbco | 0:561d07a737bc | 1369 | return RF_PACONFIG_PASELECT_RFO; |
brunnobbco | 0:561d07a737bc | 1370 | } |
brunnobbco | 0:561d07a737bc | 1371 | } |
brunnobbco | 0:561d07a737bc | 1372 | |
brunnobbco | 0:561d07a737bc | 1373 | /** |
brunnobbco | 0:561d07a737bc | 1374 | * Get RSSI from the module |
brunnobbco | 0:561d07a737bc | 1375 | */ |
brunnobbco | 0:561d07a737bc | 1376 | int16_t SX1272_LoRaRadio::get_rssi(radio_modems_t modem) |
brunnobbco | 0:561d07a737bc | 1377 | { |
brunnobbco | 0:561d07a737bc | 1378 | int16_t rssi = 0; |
brunnobbco | 0:561d07a737bc | 1379 | |
brunnobbco | 0:561d07a737bc | 1380 | switch( modem ) |
brunnobbco | 0:561d07a737bc | 1381 | { |
brunnobbco | 0:561d07a737bc | 1382 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1383 | rssi = -(read_register(REG_RSSIVALUE) >> 1 ); |
brunnobbco | 0:561d07a737bc | 1384 | break; |
brunnobbco | 0:561d07a737bc | 1385 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1386 | rssi = RSSI_OFFSET + read_register(REG_LR_RSSIVALUE); |
brunnobbco | 0:561d07a737bc | 1387 | break; |
brunnobbco | 0:561d07a737bc | 1388 | default: |
brunnobbco | 0:561d07a737bc | 1389 | rssi = -1; |
brunnobbco | 0:561d07a737bc | 1390 | break; |
brunnobbco | 0:561d07a737bc | 1391 | } |
brunnobbco | 0:561d07a737bc | 1392 | return rssi; |
brunnobbco | 0:561d07a737bc | 1393 | } |
brunnobbco | 0:561d07a737bc | 1394 | |
brunnobbco | 0:561d07a737bc | 1395 | /** |
brunnobbco | 0:561d07a737bc | 1396 | * Sets the transmit power for the module |
brunnobbco | 0:561d07a737bc | 1397 | */ |
brunnobbco | 0:561d07a737bc | 1398 | #if defined ( TARGET_MOTE_L152RC ) |
brunnobbco | 0:561d07a737bc | 1399 | static const uint8_t pa_boost_table[20] = {0, 0, 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15}; |
brunnobbco | 0:561d07a737bc | 1400 | static const uint8_t RFO_table[11] = {1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9}; |
brunnobbco | 0:561d07a737bc | 1401 | #endif |
brunnobbco | 0:561d07a737bc | 1402 | |
brunnobbco | 0:561d07a737bc | 1403 | void SX1272_LoRaRadio::set_rf_tx_power(int8_t power) |
brunnobbco | 0:561d07a737bc | 1404 | { |
brunnobbco | 0:561d07a737bc | 1405 | uint8_t pa_config = 0; |
brunnobbco | 0:561d07a737bc | 1406 | uint8_t pa_dac = 0; |
brunnobbco | 0:561d07a737bc | 1407 | |
brunnobbco | 0:561d07a737bc | 1408 | pa_config = read_register(REG_PACONFIG); |
brunnobbco | 0:561d07a737bc | 1409 | pa_dac = read_register(REG_PADAC); |
brunnobbco | 0:561d07a737bc | 1410 | |
brunnobbco | 0:561d07a737bc | 1411 | #if defined ( TARGET_MOTE_L152RC ) |
brunnobbco | 0:561d07a737bc | 1412 | if(power > 19) { |
brunnobbco | 0:561d07a737bc | 1413 | pa_config = (pa_config & RF_PACONFIG_PASELECT_MASK) | RF_PACONFIG_PASELECT_RFO; |
brunnobbco | 0:561d07a737bc | 1414 | pa_config = (pa_config & RFLR_PACONFIG_OUTPUTPOWER_MASK) | RFO_table[power - 20]; |
brunnobbco | 0:561d07a737bc | 1415 | } |
brunnobbco | 0:561d07a737bc | 1416 | else |
brunnobbco | 0:561d07a737bc | 1417 | { |
brunnobbco | 0:561d07a737bc | 1418 | pa_config = (pa_config & RF_PACONFIG_PASELECT_MASK) | RF_PACONFIG_PASELECT_PABOOST; |
brunnobbco | 0:561d07a737bc | 1419 | pa_config = (pa_config & RFLR_PACONFIG_OUTPUTPOWER_MASK) | pa_boost_table[power]; |
brunnobbco | 0:561d07a737bc | 1420 | } |
brunnobbco | 0:561d07a737bc | 1421 | #else |
brunnobbco | 0:561d07a737bc | 1422 | pa_config = (pa_config & RF_PACONFIG_PASELECT_MASK) | get_pa_conf_reg(); |
brunnobbco | 0:561d07a737bc | 1423 | |
brunnobbco | 0:561d07a737bc | 1424 | if ((pa_config & RF_PACONFIG_PASELECT_PABOOST) |
brunnobbco | 0:561d07a737bc | 1425 | == RF_PACONFIG_PASELECT_PABOOST) { |
brunnobbco | 0:561d07a737bc | 1426 | if (power > 17) { |
brunnobbco | 0:561d07a737bc | 1427 | pa_dac = (pa_dac & RF_PADAC_20DBM_MASK) | RF_PADAC_20DBM_ON; |
brunnobbco | 0:561d07a737bc | 1428 | } else { |
brunnobbco | 0:561d07a737bc | 1429 | pa_dac = (pa_dac & RF_PADAC_20DBM_MASK) | RF_PADAC_20DBM_OFF; |
brunnobbco | 0:561d07a737bc | 1430 | } |
brunnobbco | 0:561d07a737bc | 1431 | if ((pa_dac & RF_PADAC_20DBM_ON) == RF_PADAC_20DBM_ON) { |
brunnobbco | 0:561d07a737bc | 1432 | if (power < 5) { |
brunnobbco | 0:561d07a737bc | 1433 | power = 5; |
brunnobbco | 0:561d07a737bc | 1434 | } |
brunnobbco | 0:561d07a737bc | 1435 | if (power > 20) { |
brunnobbco | 0:561d07a737bc | 1436 | power = 20; |
brunnobbco | 0:561d07a737bc | 1437 | } |
brunnobbco | 0:561d07a737bc | 1438 | pa_config = (pa_config & RFLR_PACONFIG_OUTPUTPOWER_MASK) |
brunnobbco | 0:561d07a737bc | 1439 | | (uint8_t) ((uint16_t) (power - 5) & 0x0F); |
brunnobbco | 0:561d07a737bc | 1440 | } else { |
brunnobbco | 0:561d07a737bc | 1441 | if (power < 2) { |
brunnobbco | 0:561d07a737bc | 1442 | power = 2; |
brunnobbco | 0:561d07a737bc | 1443 | } |
brunnobbco | 0:561d07a737bc | 1444 | if (power > 17) { |
brunnobbco | 0:561d07a737bc | 1445 | power = 17; |
brunnobbco | 0:561d07a737bc | 1446 | } |
brunnobbco | 0:561d07a737bc | 1447 | pa_config = (pa_config & RFLR_PACONFIG_OUTPUTPOWER_MASK) |
brunnobbco | 0:561d07a737bc | 1448 | | (uint8_t) ((uint16_t) (power - 2) & 0x0F); |
brunnobbco | 0:561d07a737bc | 1449 | } |
brunnobbco | 0:561d07a737bc | 1450 | } else { |
brunnobbco | 0:561d07a737bc | 1451 | if (power < -1) { |
brunnobbco | 0:561d07a737bc | 1452 | power = -1; |
brunnobbco | 0:561d07a737bc | 1453 | } |
brunnobbco | 0:561d07a737bc | 1454 | if (power > 14) { |
brunnobbco | 0:561d07a737bc | 1455 | power = 14; |
brunnobbco | 0:561d07a737bc | 1456 | } |
brunnobbco | 0:561d07a737bc | 1457 | pa_config = (pa_config & RFLR_PACONFIG_OUTPUTPOWER_MASK) |
brunnobbco | 0:561d07a737bc | 1458 | | (uint8_t) ((uint16_t) (power + 1) & 0x0F); |
brunnobbco | 0:561d07a737bc | 1459 | } |
brunnobbco | 0:561d07a737bc | 1460 | #endif |
brunnobbco | 0:561d07a737bc | 1461 | write_to_register(REG_PACONFIG, pa_config); |
brunnobbco | 0:561d07a737bc | 1462 | write_to_register(REG_PADAC, pa_dac); |
brunnobbco | 0:561d07a737bc | 1463 | } |
brunnobbco | 0:561d07a737bc | 1464 | |
brunnobbco | 0:561d07a737bc | 1465 | /** |
brunnobbco | 0:561d07a737bc | 1466 | * Sets the radio registers to defaults |
brunnobbco | 0:561d07a737bc | 1467 | */ |
brunnobbco | 0:561d07a737bc | 1468 | void SX1272_LoRaRadio::setup_registers() |
brunnobbco | 0:561d07a737bc | 1469 | { |
brunnobbco | 0:561d07a737bc | 1470 | for (unsigned int i = 0; i < sizeof(radio_reg_init) / sizeof(radio_registers_t); i++) { |
brunnobbco | 0:561d07a737bc | 1471 | set_modem(radio_reg_init[i].modem); |
brunnobbco | 0:561d07a737bc | 1472 | write_to_register(radio_reg_init[i].addr, radio_reg_init[i].value); |
brunnobbco | 0:561d07a737bc | 1473 | } |
brunnobbco | 0:561d07a737bc | 1474 | } |
brunnobbco | 0:561d07a737bc | 1475 | |
brunnobbco | 0:561d07a737bc | 1476 | /** |
brunnobbco | 0:561d07a737bc | 1477 | * Set the radio module variant |
brunnobbco | 0:561d07a737bc | 1478 | */ |
brunnobbco | 0:561d07a737bc | 1479 | void SX1272_LoRaRadio::set_sx1272_variant_type() |
brunnobbco | 0:561d07a737bc | 1480 | { |
brunnobbco | 0:561d07a737bc | 1481 | if (_rf_ctrls.ant_switch != NC){ |
brunnobbco | 0:561d07a737bc | 1482 | _ant_switch.input(); |
brunnobbco | 0:561d07a737bc | 1483 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 1484 | if (_ant_switch == 1) { |
brunnobbco | 0:561d07a737bc | 1485 | radio_variant = SX1272MB1DCS; |
brunnobbco | 0:561d07a737bc | 1486 | } else { |
brunnobbco | 0:561d07a737bc | 1487 | radio_variant = SX1272MB2XAS; |
brunnobbco | 0:561d07a737bc | 1488 | } |
brunnobbco | 0:561d07a737bc | 1489 | _ant_switch.output(); |
brunnobbco | 0:561d07a737bc | 1490 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 1491 | } else { |
brunnobbco | 0:561d07a737bc | 1492 | radio_variant = MBED_CONF_SX1272_LORA_DRIVER_RADIO_VARIANT; |
brunnobbco | 0:561d07a737bc | 1493 | } |
brunnobbco | 0:561d07a737bc | 1494 | } |
brunnobbco | 0:561d07a737bc | 1495 | |
brunnobbco | 0:561d07a737bc | 1496 | /** |
brunnobbco | 0:561d07a737bc | 1497 | * Sets up radio latch position according to the |
brunnobbco | 0:561d07a737bc | 1498 | * radio mode |
brunnobbco | 0:561d07a737bc | 1499 | */ |
brunnobbco | 0:561d07a737bc | 1500 | void SX1272_LoRaRadio::set_antenna_switch(uint8_t mode) |
brunnobbco | 0:561d07a737bc | 1501 | { |
brunnobbco | 0:561d07a737bc | 1502 | // here we got to do ifdef for changing controls |
brunnobbco | 0:561d07a737bc | 1503 | // as some pins might be NC |
brunnobbco | 0:561d07a737bc | 1504 | switch (mode) { |
brunnobbco | 0:561d07a737bc | 1505 | case RFLR_OPMODE_TRANSMITTER: |
brunnobbco | 0:561d07a737bc | 1506 | if (_rf_ctrls.rf_switch_ctl1 != NC |
brunnobbco | 0:561d07a737bc | 1507 | && _rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1508 | // module is in transmit mode and RF latch switches |
brunnobbco | 0:561d07a737bc | 1509 | // are connected. Check if power amplifier boost is |
brunnobbco | 0:561d07a737bc | 1510 | // setup or not |
brunnobbco | 0:561d07a737bc | 1511 | if ((read_register(REG_PACONFIG) & RF_PACONFIG_PASELECT_PABOOST) |
brunnobbco | 0:561d07a737bc | 1512 | == RF_PACONFIG_PASELECT_PABOOST) { |
brunnobbco | 0:561d07a737bc | 1513 | _rf_switch_ctl1 = 1; |
brunnobbco | 0:561d07a737bc | 1514 | _rf_switch_ctl2 = 0; |
brunnobbco | 0:561d07a737bc | 1515 | } else { |
brunnobbco | 0:561d07a737bc | 1516 | // power amplifier not selected |
brunnobbco | 0:561d07a737bc | 1517 | _rf_switch_ctl1 = 0; |
brunnobbco | 0:561d07a737bc | 1518 | _rf_switch_ctl2 = 1; |
brunnobbco | 0:561d07a737bc | 1519 | } |
brunnobbco | 0:561d07a737bc | 1520 | } else if (_rf_ctrls.txctl != NC && _rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1521 | // module is in transmit mode and tx/rx submodule control |
brunnobbco | 0:561d07a737bc | 1522 | // pins are connected |
brunnobbco | 0:561d07a737bc | 1523 | _txctl = 1; |
brunnobbco | 0:561d07a737bc | 1524 | _rxctl = 0; |
brunnobbco | 0:561d07a737bc | 1525 | } else if (_rf_ctrls.ant_switch != NC){ |
brunnobbco | 0:561d07a737bc | 1526 | _ant_switch = 1; |
brunnobbco | 0:561d07a737bc | 1527 | } else { |
brunnobbco | 0:561d07a737bc | 1528 | // None of the control pins are connected. |
brunnobbco | 0:561d07a737bc | 1529 | } |
brunnobbco | 0:561d07a737bc | 1530 | break; |
brunnobbco | 0:561d07a737bc | 1531 | case RFLR_OPMODE_RECEIVER: |
brunnobbco | 0:561d07a737bc | 1532 | case RFLR_OPMODE_RECEIVER_SINGLE: |
brunnobbco | 0:561d07a737bc | 1533 | case RFLR_OPMODE_CAD: |
brunnobbco | 0:561d07a737bc | 1534 | if (_rf_ctrls.rf_switch_ctl1 != NC |
brunnobbco | 0:561d07a737bc | 1535 | && _rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1536 | // radio is in reception or CAD mode and RF latch switches |
brunnobbco | 0:561d07a737bc | 1537 | // are connected |
brunnobbco | 0:561d07a737bc | 1538 | _rf_switch_ctl1 = 1; |
brunnobbco | 0:561d07a737bc | 1539 | _rf_switch_ctl2 = 1; |
brunnobbco | 0:561d07a737bc | 1540 | } else if (_rf_ctrls.txctl != NC && _rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1541 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1542 | _rxctl = 1; |
brunnobbco | 0:561d07a737bc | 1543 | } else if (_rf_ctrls.ant_switch != NC) { |
brunnobbco | 0:561d07a737bc | 1544 | _ant_switch = 0; |
brunnobbco | 0:561d07a737bc | 1545 | } else { |
brunnobbco | 0:561d07a737bc | 1546 | // None of the control pins are connected. |
brunnobbco | 0:561d07a737bc | 1547 | } |
brunnobbco | 0:561d07a737bc | 1548 | break; |
brunnobbco | 0:561d07a737bc | 1549 | default: |
brunnobbco | 0:561d07a737bc | 1550 | // Enforce default case when any connected control pin is kept low. |
brunnobbco | 0:561d07a737bc | 1551 | if (_rf_ctrls.rf_switch_ctl1 != NC |
brunnobbco | 0:561d07a737bc | 1552 | && _rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1553 | // radio is in reception or CAD mode and RF latch switches |
brunnobbco | 0:561d07a737bc | 1554 | // are connected |
brunnobbco | 0:561d07a737bc | 1555 | _rf_switch_ctl1 = 0; |
brunnobbco | 0:561d07a737bc | 1556 | _rf_switch_ctl2 = 0; |
brunnobbco | 0:561d07a737bc | 1557 | } else if (_rf_ctrls.txctl != NC && _rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1558 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1559 | _rxctl = 0; |
brunnobbco | 0:561d07a737bc | 1560 | } else if (_rf_ctrls.ant_switch != NC) { |
brunnobbco | 0:561d07a737bc | 1561 | _ant_switch = 0; |
brunnobbco | 0:561d07a737bc | 1562 | } else { |
brunnobbco | 0:561d07a737bc | 1563 | // None of the control pins are connected. |
brunnobbco | 0:561d07a737bc | 1564 | } |
brunnobbco | 0:561d07a737bc | 1565 | break; |
brunnobbco | 0:561d07a737bc | 1566 | } |
brunnobbco | 0:561d07a737bc | 1567 | } |
brunnobbco | 0:561d07a737bc | 1568 | |
brunnobbco | 0:561d07a737bc | 1569 | /** |
brunnobbco | 0:561d07a737bc | 1570 | * Sets up frequency for SPI module |
brunnobbco | 0:561d07a737bc | 1571 | * Reference DataSheet: 4.3 SPI Interface |
brunnobbco | 0:561d07a737bc | 1572 | */ |
brunnobbco | 0:561d07a737bc | 1573 | void SX1272_LoRaRadio::setup_spi() |
brunnobbco | 0:561d07a737bc | 1574 | { |
brunnobbco | 0:561d07a737bc | 1575 | // SPI bus frequency |
brunnobbco | 0:561d07a737bc | 1576 | uint32_t spi_freq = SPI_FREQUENCY; |
brunnobbco | 0:561d07a737bc | 1577 | |
brunnobbco | 0:561d07a737bc | 1578 | // Hold chip-select high |
brunnobbco | 0:561d07a737bc | 1579 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 1580 | _spi.format(8, 0); |
brunnobbco | 0:561d07a737bc | 1581 | |
brunnobbco | 0:561d07a737bc | 1582 | #if defined (TARGET_KL25Z) |
brunnobbco | 0:561d07a737bc | 1583 | //bus-clock frequency is halved -> double the SPI frequency to compensate |
brunnobbco | 0:561d07a737bc | 1584 | _spi.frequency(spi_freq * 2); |
brunnobbco | 0:561d07a737bc | 1585 | #else |
brunnobbco | 0:561d07a737bc | 1586 | // otherwise use default SPI frequency which is 8 MHz |
brunnobbco | 0:561d07a737bc | 1587 | _spi.frequency(spi_freq); |
brunnobbco | 0:561d07a737bc | 1588 | #endif |
brunnobbco | 0:561d07a737bc | 1589 | // 100 us wait to settle down |
brunnobbco | 0:561d07a737bc | 1590 | wait(0.1); |
brunnobbco | 0:561d07a737bc | 1591 | } |
brunnobbco | 0:561d07a737bc | 1592 | |
brunnobbco | 0:561d07a737bc | 1593 | /** |
brunnobbco | 0:561d07a737bc | 1594 | * Attaches ISRs to interrupt pins |
brunnobbco | 0:561d07a737bc | 1595 | */ |
brunnobbco | 0:561d07a737bc | 1596 | void SX1272_LoRaRadio::setup_interrupts() |
brunnobbco | 0:561d07a737bc | 1597 | { |
brunnobbco | 0:561d07a737bc | 1598 | _dio0_ctl.rise(callback(this, &SX1272_LoRaRadio::dio0_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1599 | |
brunnobbco | 0:561d07a737bc | 1600 | if (_dio1_pin != NC) { |
brunnobbco | 0:561d07a737bc | 1601 | _dio1_ctl.rise(callback(this, &SX1272_LoRaRadio::dio1_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1602 | } |
brunnobbco | 0:561d07a737bc | 1603 | |
brunnobbco | 1:3bdd6f917bf5 | 1604 | if (_dio2_pin != NC) { |
brunnobbco | 1:3bdd6f917bf5 | 1605 | _dio2_ctl.rise(callback(this, &SX1272_LoRaRadio::dio2_irq_isr)); |
brunnobbco | 0:561d07a737bc | 1606 | } |
brunnobbco | 0:561d07a737bc | 1607 | } |
brunnobbco | 0:561d07a737bc | 1608 | |
brunnobbco | 0:561d07a737bc | 1609 | /** |
brunnobbco | 0:561d07a737bc | 1610 | * Sets the module in low power mode by disconnecting |
brunnobbco | 0:561d07a737bc | 1611 | * TX and RX submodules, turning off power amplifier etc. |
brunnobbco | 0:561d07a737bc | 1612 | */ |
brunnobbco | 0:561d07a737bc | 1613 | void SX1272_LoRaRadio::set_low_power_mode(bool status) |
brunnobbco | 0:561d07a737bc | 1614 | { |
brunnobbco | 0:561d07a737bc | 1615 | if (radio_is_active != status) { |
brunnobbco | 0:561d07a737bc | 1616 | radio_is_active = status; |
brunnobbco | 0:561d07a737bc | 1617 | |
brunnobbco | 0:561d07a737bc | 1618 | if (status == false) { |
brunnobbco | 0:561d07a737bc | 1619 | if (_rf_ctrls.rf_switch_ctl1 != NC) { |
brunnobbco | 0:561d07a737bc | 1620 | _rf_switch_ctl1 = 0; |
brunnobbco | 0:561d07a737bc | 1621 | } |
brunnobbco | 0:561d07a737bc | 1622 | if (_rf_ctrls.rf_switch_ctl2 != NC) { |
brunnobbco | 0:561d07a737bc | 1623 | _rf_switch_ctl2 = 0; |
brunnobbco | 0:561d07a737bc | 1624 | } |
brunnobbco | 0:561d07a737bc | 1625 | |
brunnobbco | 0:561d07a737bc | 1626 | if (_rf_ctrls.pwr_amp_ctl != NC) { |
brunnobbco | 0:561d07a737bc | 1627 | _pwr_amp_ctl = 0; |
brunnobbco | 0:561d07a737bc | 1628 | } |
brunnobbco | 0:561d07a737bc | 1629 | |
brunnobbco | 0:561d07a737bc | 1630 | if (_rf_ctrls.txctl != NC) { |
brunnobbco | 0:561d07a737bc | 1631 | _txctl = 0; |
brunnobbco | 0:561d07a737bc | 1632 | } |
brunnobbco | 0:561d07a737bc | 1633 | |
brunnobbco | 0:561d07a737bc | 1634 | if (_rf_ctrls.rxctl != NC) { |
brunnobbco | 0:561d07a737bc | 1635 | _rxctl = 0; |
brunnobbco | 0:561d07a737bc | 1636 | } |
brunnobbco | 0:561d07a737bc | 1637 | |
brunnobbco | 0:561d07a737bc | 1638 | if (_rf_ctrls.ant_switch != NC) { |
brunnobbco | 0:561d07a737bc | 1639 | _ant_switch = 0; |
brunnobbco | 0:561d07a737bc | 1640 | } |
brunnobbco | 0:561d07a737bc | 1641 | } else { |
brunnobbco | 0:561d07a737bc | 1642 | default_antenna_switch_ctrls(); |
brunnobbco | 0:561d07a737bc | 1643 | } |
brunnobbco | 0:561d07a737bc | 1644 | } |
brunnobbco | 0:561d07a737bc | 1645 | } |
brunnobbco | 0:561d07a737bc | 1646 | |
brunnobbco | 0:561d07a737bc | 1647 | /***************************************************************************** |
brunnobbco | 0:561d07a737bc | 1648 | * Interrupt service routines (ISRs) - set signals to the irq_thread * |
brunnobbco | 0:561d07a737bc | 1649 | ****************************************************************************/ |
brunnobbco | 0:561d07a737bc | 1650 | void SX1272_LoRaRadio::dio0_irq_isr() |
brunnobbco | 0:561d07a737bc | 1651 | { |
brunnobbco | 0:561d07a737bc | 1652 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1653 | irq_thread.flags_set(SIG_DIO0); |
brunnobbco | 0:561d07a737bc | 1654 | #else |
brunnobbco | 0:561d07a737bc | 1655 | handle_dio0_irq(); |
brunnobbco | 0:561d07a737bc | 1656 | #endif |
brunnobbco | 0:561d07a737bc | 1657 | } |
brunnobbco | 0:561d07a737bc | 1658 | |
brunnobbco | 0:561d07a737bc | 1659 | void SX1272_LoRaRadio::dio1_irq_isr() |
brunnobbco | 0:561d07a737bc | 1660 | { |
brunnobbco | 0:561d07a737bc | 1661 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1662 | irq_thread.flags_set(SIG_DIO1); |
brunnobbco | 0:561d07a737bc | 1663 | #else |
brunnobbco | 0:561d07a737bc | 1664 | handle_dio1_irq(); |
brunnobbco | 0:561d07a737bc | 1665 | #endif |
brunnobbco | 0:561d07a737bc | 1666 | } |
brunnobbco | 0:561d07a737bc | 1667 | |
brunnobbco | 0:561d07a737bc | 1668 | void SX1272_LoRaRadio::dio2_irq_isr() |
brunnobbco | 0:561d07a737bc | 1669 | { |
brunnobbco | 0:561d07a737bc | 1670 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1671 | irq_thread.flags_set(SIG_DIO2); |
brunnobbco | 0:561d07a737bc | 1672 | #else |
brunnobbco | 0:561d07a737bc | 1673 | handle_dio2_irq(); |
brunnobbco | 0:561d07a737bc | 1674 | #endif |
brunnobbco | 0:561d07a737bc | 1675 | } |
brunnobbco | 0:561d07a737bc | 1676 | |
brunnobbco | 0:561d07a737bc | 1677 | // This is not a hardware interrupt |
brunnobbco | 0:561d07a737bc | 1678 | // we invoke it ourselves based upon |
brunnobbco | 0:561d07a737bc | 1679 | // our timers |
brunnobbco | 0:561d07a737bc | 1680 | void SX1272_LoRaRadio::timeout_irq_isr() |
brunnobbco | 0:561d07a737bc | 1681 | { |
brunnobbco | 0:561d07a737bc | 1682 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1683 | irq_thread.flags_set(SIG_TIMOUT); |
brunnobbco | 0:561d07a737bc | 1684 | #else |
brunnobbco | 0:561d07a737bc | 1685 | handle_timeout_irq(); |
brunnobbco | 0:561d07a737bc | 1686 | #endif |
brunnobbco | 0:561d07a737bc | 1687 | } |
brunnobbco | 0:561d07a737bc | 1688 | |
brunnobbco | 0:561d07a737bc | 1689 | void SX1272_LoRaRadio::rxsync_irq_isr() |
brunnobbco | 0:561d07a737bc | 1690 | { |
brunnobbco | 0:561d07a737bc | 1691 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 1692 | irq_thread.flags_set(SIG_RXSYNC); |
brunnobbco | 0:561d07a737bc | 1693 | #else |
brunnobbco | 0:561d07a737bc | 1694 | handle_rxsync_irq(); |
brunnobbco | 0:561d07a737bc | 1695 | #endif |
brunnobbco | 0:561d07a737bc | 1696 | } |
brunnobbco | 0:561d07a737bc | 1697 | |
brunnobbco | 1:3bdd6f917bf5 | 1698 | void SX1272_LoRaRadio::lrcad_irq_isr() |
brunnobbco | 1:3bdd6f917bf5 | 1699 | { |
brunnobbco | 1:3bdd6f917bf5 | 1700 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 1:3bdd6f917bf5 | 1701 | irq_thread.flags_set(SIG_LRCAD); |
brunnobbco | 1:3bdd6f917bf5 | 1702 | #else |
brunnobbco | 1:3bdd6f917bf5 | 1703 | handle_lrcad_irq(); |
brunnobbco | 1:3bdd6f917bf5 | 1704 | #endif |
brunnobbco | 1:3bdd6f917bf5 | 1705 | } |
brunnobbco | 1:3bdd6f917bf5 | 1706 | |
brunnobbco | 1:3bdd6f917bf5 | 1707 | void SX1272_LoRaRadio::lrhop_irq_isr() |
brunnobbco | 1:3bdd6f917bf5 | 1708 | { |
brunnobbco | 1:3bdd6f917bf5 | 1709 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 1:3bdd6f917bf5 | 1710 | irq_thread.flags_set(SIG_LRHOP); |
brunnobbco | 1:3bdd6f917bf5 | 1711 | #else |
brunnobbco | 1:3bdd6f917bf5 | 1712 | handle_lrhop_irq(); |
brunnobbco | 1:3bdd6f917bf5 | 1713 | #endif |
brunnobbco | 1:3bdd6f917bf5 | 1714 | } |
brunnobbco | 1:3bdd6f917bf5 | 1715 | |
brunnobbco | 0:561d07a737bc | 1716 | /****************************************************************************** |
brunnobbco | 0:561d07a737bc | 1717 | * Interrupt Handlers * |
brunnobbco | 0:561d07a737bc | 1718 | *****************************************************************************/ |
brunnobbco | 0:561d07a737bc | 1719 | |
brunnobbco | 0:561d07a737bc | 1720 | void SX1272_LoRaRadio::handle_dio0_irq() |
brunnobbco | 0:561d07a737bc | 1721 | { |
brunnobbco | 0:561d07a737bc | 1722 | volatile uint8_t irqFlags = 0; |
brunnobbco | 0:561d07a737bc | 1723 | |
brunnobbco | 0:561d07a737bc | 1724 | switch (_rf_settings.state) { |
brunnobbco | 0:561d07a737bc | 1725 | case RF_RX_RUNNING: |
brunnobbco | 0:561d07a737bc | 1726 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 1727 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1728 | if (_rf_settings.fsk.crc_on == true) { |
brunnobbco | 0:561d07a737bc | 1729 | irqFlags = read_register(REG_IRQFLAGS2); |
brunnobbco | 0:561d07a737bc | 1730 | if ((irqFlags & RF_IRQFLAGS2_CRCOK) |
brunnobbco | 0:561d07a737bc | 1731 | != RF_IRQFLAGS2_CRCOK) { |
brunnobbco | 0:561d07a737bc | 1732 | // Clear Irqs |
brunnobbco | 0:561d07a737bc | 1733 | write_to_register(REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | |
brunnobbco | 0:561d07a737bc | 1734 | RF_IRQFLAGS1_PREAMBLEDETECT | |
brunnobbco | 0:561d07a737bc | 1735 | RF_IRQFLAGS1_SYNCADDRESSMATCH); |
brunnobbco | 0:561d07a737bc | 1736 | write_to_register(REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN); |
brunnobbco | 0:561d07a737bc | 1737 | |
brunnobbco | 0:561d07a737bc | 1738 | |
brunnobbco | 0:561d07a737bc | 1739 | if (_rf_settings.fsk.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1740 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1741 | } else { |
brunnobbco | 0:561d07a737bc | 1742 | // Continuous mode restart Rx chain |
brunnobbco | 0:561d07a737bc | 1743 | write_to_register(REG_RXCONFIG, |
brunnobbco | 0:561d07a737bc | 1744 | read_register(REG_RXCONFIG) | |
brunnobbco | 0:561d07a737bc | 1745 | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); |
brunnobbco | 0:561d07a737bc | 1746 | } |
brunnobbco | 0:561d07a737bc | 1747 | |
brunnobbco | 0:561d07a737bc | 1748 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 1749 | && (_radio_events->rx_error)) { |
brunnobbco | 0:561d07a737bc | 1750 | _radio_events->rx_error(); |
brunnobbco | 0:561d07a737bc | 1751 | } |
brunnobbco | 0:561d07a737bc | 1752 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 1753 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 1754 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 1755 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 1756 | // break from here, a CRC error happened, RX_ERROR |
brunnobbco | 0:561d07a737bc | 1757 | // was notified. No need to go any further |
brunnobbco | 0:561d07a737bc | 1758 | break; |
brunnobbco | 0:561d07a737bc | 1759 | } |
brunnobbco | 0:561d07a737bc | 1760 | } |
brunnobbco | 0:561d07a737bc | 1761 | |
brunnobbco | 0:561d07a737bc | 1762 | // This block was moved from dio2_handler. |
brunnobbco | 0:561d07a737bc | 1763 | // We can have a snapshot of RSSI here as at this point it |
brunnobbco | 0:561d07a737bc | 1764 | // should be more smoothed out. |
brunnobbco | 0:561d07a737bc | 1765 | _rf_settings.fsk_packet_handler.rssi_value = -(read_register(REG_RSSIVALUE) >> 1); |
brunnobbco | 0:561d07a737bc | 1766 | _rf_settings.fsk_packet_handler.afc_value = (int32_t)(float)(((uint16_t)read_register(REG_AFCMSB) << 8) | |
brunnobbco | 0:561d07a737bc | 1767 | (uint16_t)read_register(REG_AFCLSB)) * |
brunnobbco | 0:561d07a737bc | 1768 | (float)FREQ_STEP; |
brunnobbco | 0:561d07a737bc | 1769 | _rf_settings.fsk_packet_handler.rx_gain = (read_register(REG_LNA) >> 5) & 0x07; |
brunnobbco | 0:561d07a737bc | 1770 | |
brunnobbco | 0:561d07a737bc | 1771 | // Read received packet size |
brunnobbco | 0:561d07a737bc | 1772 | if ((_rf_settings.fsk_packet_handler.size == 0) |
brunnobbco | 0:561d07a737bc | 1773 | && (_rf_settings.fsk_packet_handler.nb_bytes == 0)) { |
brunnobbco | 0:561d07a737bc | 1774 | if (_rf_settings.fsk.fix_len == false) { |
brunnobbco | 0:561d07a737bc | 1775 | read_fifo((uint8_t*) &_rf_settings.fsk_packet_handler.size, 1); |
brunnobbco | 0:561d07a737bc | 1776 | } else { |
brunnobbco | 0:561d07a737bc | 1777 | _rf_settings.fsk_packet_handler.size = read_register(REG_PAYLOADLENGTH); |
brunnobbco | 0:561d07a737bc | 1778 | } |
brunnobbco | 0:561d07a737bc | 1779 | read_fifo(_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes, |
brunnobbco | 0:561d07a737bc | 1780 | _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1781 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 1782 | (_rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1783 | } else { |
brunnobbco | 0:561d07a737bc | 1784 | read_fifo(_data_buffer + _rf_settings.fsk_packet_handler.nb_bytes, |
brunnobbco | 0:561d07a737bc | 1785 | _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1786 | _rf_settings.fsk_packet_handler.nb_bytes += |
brunnobbco | 0:561d07a737bc | 1787 | (_rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes); |
brunnobbco | 0:561d07a737bc | 1788 | } |
brunnobbco | 0:561d07a737bc | 1789 | |
brunnobbco | 0:561d07a737bc | 1790 | if (_rf_settings.fsk.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1791 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1792 | } else { |
brunnobbco | 0:561d07a737bc | 1793 | // Continuous mode restart Rx chain |
brunnobbco | 0:561d07a737bc | 1794 | write_to_register(REG_RXCONFIG, read_register(REG_RXCONFIG) |
brunnobbco | 0:561d07a737bc | 1795 | | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); |
brunnobbco | 0:561d07a737bc | 1796 | } |
brunnobbco | 0:561d07a737bc | 1797 | |
brunnobbco | 0:561d07a737bc | 1798 | if ((_radio_events != NULL) && (_radio_events->rx_done)) { |
brunnobbco | 0:561d07a737bc | 1799 | _radio_events->rx_done( |
brunnobbco | 0:561d07a737bc | 1800 | _data_buffer, |
brunnobbco | 0:561d07a737bc | 1801 | _rf_settings.fsk_packet_handler.size, |
brunnobbco | 0:561d07a737bc | 1802 | _rf_settings.fsk_packet_handler.rssi_value, 0); |
brunnobbco | 0:561d07a737bc | 1803 | } |
brunnobbco | 0:561d07a737bc | 1804 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 1805 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 1806 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 1807 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 1808 | break; |
brunnobbco | 0:561d07a737bc | 1809 | case MODEM_LORA: { |
brunnobbco | 0:561d07a737bc | 1810 | int8_t snr = 0; |
brunnobbco | 0:561d07a737bc | 1811 | |
brunnobbco | 0:561d07a737bc | 1812 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 1813 | write_to_register(REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE); |
brunnobbco | 0:561d07a737bc | 1814 | |
brunnobbco | 0:561d07a737bc | 1815 | irqFlags = read_register(REG_LR_IRQFLAGS); |
brunnobbco | 0:561d07a737bc | 1816 | if ((irqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK) |
brunnobbco | 0:561d07a737bc | 1817 | == RFLR_IRQFLAGS_PAYLOADCRCERROR) { |
brunnobbco | 0:561d07a737bc | 1818 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 1819 | write_to_register(REG_LR_IRQFLAGS, |
brunnobbco | 0:561d07a737bc | 1820 | RFLR_IRQFLAGS_PAYLOADCRCERROR); |
brunnobbco | 0:561d07a737bc | 1821 | |
brunnobbco | 0:561d07a737bc | 1822 | if (_rf_settings.lora.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1823 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1824 | } |
brunnobbco | 0:561d07a737bc | 1825 | |
brunnobbco | 0:561d07a737bc | 1826 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 1827 | && (_radio_events->rx_error)) { |
brunnobbco | 0:561d07a737bc | 1828 | _radio_events->rx_error(); |
brunnobbco | 0:561d07a737bc | 1829 | } |
brunnobbco | 0:561d07a737bc | 1830 | break; |
brunnobbco | 0:561d07a737bc | 1831 | } |
brunnobbco | 0:561d07a737bc | 1832 | |
brunnobbco | 0:561d07a737bc | 1833 | _rf_settings.lora_packet_handler.snr_value = read_register(REG_LR_PKTSNRVALUE); |
brunnobbco | 0:561d07a737bc | 1834 | if (_rf_settings.lora_packet_handler.snr_value & 0x80) // The SNR sign bit is 1 |
brunnobbco | 0:561d07a737bc | 1835 | { |
brunnobbco | 0:561d07a737bc | 1836 | // Invert and divide by 4 |
brunnobbco | 0:561d07a737bc | 1837 | snr = ((~_rf_settings.lora_packet_handler.snr_value + 1) & 0xFF) >> 2; |
brunnobbco | 0:561d07a737bc | 1838 | snr = -snr; |
brunnobbco | 0:561d07a737bc | 1839 | } else { |
brunnobbco | 0:561d07a737bc | 1840 | // Divide by 4 |
brunnobbco | 0:561d07a737bc | 1841 | snr =(_rf_settings.lora_packet_handler.snr_value & 0xFF) >> 2; |
brunnobbco | 0:561d07a737bc | 1842 | } |
brunnobbco | 0:561d07a737bc | 1843 | |
brunnobbco | 0:561d07a737bc | 1844 | int16_t rssi = read_register(REG_LR_PKTRSSIVALUE); |
brunnobbco | 0:561d07a737bc | 1845 | if (snr < 0) { |
brunnobbco | 0:561d07a737bc | 1846 | _rf_settings.lora_packet_handler.rssi_value = |
brunnobbco | 0:561d07a737bc | 1847 | RSSI_OFFSET + rssi + (rssi >> 4) + snr; |
brunnobbco | 0:561d07a737bc | 1848 | } else { |
brunnobbco | 0:561d07a737bc | 1849 | _rf_settings.lora_packet_handler.rssi_value = |
brunnobbco | 0:561d07a737bc | 1850 | RSSI_OFFSET + rssi + (rssi >> 4); |
brunnobbco | 0:561d07a737bc | 1851 | } |
brunnobbco | 0:561d07a737bc | 1852 | |
brunnobbco | 0:561d07a737bc | 1853 | _rf_settings.lora_packet_handler.size = read_register(REG_LR_RXNBBYTES); |
brunnobbco | 0:561d07a737bc | 1854 | read_fifo(_data_buffer, _rf_settings.lora_packet_handler.size); |
brunnobbco | 0:561d07a737bc | 1855 | |
brunnobbco | 0:561d07a737bc | 1856 | if (_rf_settings.lora.rx_continuous == false) { |
brunnobbco | 0:561d07a737bc | 1857 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1858 | } |
brunnobbco | 0:561d07a737bc | 1859 | |
brunnobbco | 0:561d07a737bc | 1860 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 1861 | && (_radio_events->rx_done)) { |
brunnobbco | 0:561d07a737bc | 1862 | _radio_events->rx_done( |
brunnobbco | 0:561d07a737bc | 1863 | _data_buffer, |
brunnobbco | 0:561d07a737bc | 1864 | _rf_settings.lora_packet_handler.size, |
brunnobbco | 0:561d07a737bc | 1865 | _rf_settings.lora_packet_handler.rssi_value, |
brunnobbco | 0:561d07a737bc | 1866 | _rf_settings.lora_packet_handler.snr_value); |
brunnobbco | 0:561d07a737bc | 1867 | } |
brunnobbco | 0:561d07a737bc | 1868 | } |
brunnobbco | 0:561d07a737bc | 1869 | break; |
brunnobbco | 0:561d07a737bc | 1870 | default: |
brunnobbco | 0:561d07a737bc | 1871 | break; |
brunnobbco | 0:561d07a737bc | 1872 | } |
brunnobbco | 0:561d07a737bc | 1873 | break; |
brunnobbco | 0:561d07a737bc | 1874 | case RF_TX_RUNNING: |
brunnobbco | 0:561d07a737bc | 1875 | tx_timeout_timer.detach(); |
brunnobbco | 0:561d07a737bc | 1876 | // TxDone interrupt |
brunnobbco | 0:561d07a737bc | 1877 | switch (_rf_settings.modem) { |
brunnobbco | 0:561d07a737bc | 1878 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1879 | // Clear Irq |
brunnobbco | 0:561d07a737bc | 1880 | write_to_register( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE); |
brunnobbco | 0:561d07a737bc | 1881 | // Intentional fall through |
brunnobbco | 0:561d07a737bc | 1882 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1883 | default: |
brunnobbco | 0:561d07a737bc | 1884 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1885 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 1886 | && (_radio_events->tx_done)) { |
brunnobbco | 0:561d07a737bc | 1887 | _radio_events->tx_done(); |
brunnobbco | 0:561d07a737bc | 1888 | } |
brunnobbco | 0:561d07a737bc | 1889 | break; |
brunnobbco | 0:561d07a737bc | 1890 | } |
brunnobbco | 0:561d07a737bc | 1891 | break; |
brunnobbco | 0:561d07a737bc | 1892 | default: |
brunnobbco | 0:561d07a737bc | 1893 | break; |
brunnobbco | 0:561d07a737bc | 1894 | } |
brunnobbco | 0:561d07a737bc | 1895 | } |
brunnobbco | 0:561d07a737bc | 1896 | |
brunnobbco | 0:561d07a737bc | 1897 | void SX1272_LoRaRadio::handle_dio1_irq() |
brunnobbco | 0:561d07a737bc | 1898 | { |
brunnobbco | 0:561d07a737bc | 1899 | switch(_rf_settings.state ) |
brunnobbco | 0:561d07a737bc | 1900 | { |
brunnobbco | 0:561d07a737bc | 1901 | case RF_RX_RUNNING: |
brunnobbco | 0:561d07a737bc | 1902 | switch(_rf_settings.modem ) { |
brunnobbco | 0:561d07a737bc | 1903 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1904 | // FifoLevel interrupt |
brunnobbco | 0:561d07a737bc | 1905 | // Read received packet size |
brunnobbco | 0:561d07a737bc | 1906 | if( ( _rf_settings.fsk_packet_handler.size == 0 ) && ( _rf_settings.fsk_packet_handler.nb_bytes == 0 ) ) |
brunnobbco | 0:561d07a737bc | 1907 | { |
brunnobbco | 0:561d07a737bc | 1908 | if( _rf_settings.fsk.fix_len == false ) |
brunnobbco | 0:561d07a737bc | 1909 | { |
brunnobbco | 0:561d07a737bc | 1910 | read_fifo( ( uint8_t* )&_rf_settings.fsk_packet_handler.size, 1 ); |
brunnobbco | 0:561d07a737bc | 1911 | } |
brunnobbco | 0:561d07a737bc | 1912 | else |
brunnobbco | 0:561d07a737bc | 1913 | { |
brunnobbco | 0:561d07a737bc | 1914 | _rf_settings.fsk_packet_handler.size = read_register(REG_PAYLOADLENGTH); |
brunnobbco | 0:561d07a737bc | 1915 | } |
brunnobbco | 0:561d07a737bc | 1916 | } |
brunnobbco | 0:561d07a737bc | 1917 | |
brunnobbco | 0:561d07a737bc | 1918 | if( ( _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes ) > _rf_settings.fsk_packet_handler.fifo_thresh ) |
brunnobbco | 0:561d07a737bc | 1919 | { |
brunnobbco | 0:561d07a737bc | 1920 | read_fifo( ( _data_buffer + _rf_settings.fsk_packet_handler.nb_bytes ), _rf_settings.fsk_packet_handler.fifo_thresh ); |
brunnobbco | 0:561d07a737bc | 1921 | _rf_settings.fsk_packet_handler.nb_bytes += _rf_settings.fsk_packet_handler.fifo_thresh; |
brunnobbco | 0:561d07a737bc | 1922 | } |
brunnobbco | 0:561d07a737bc | 1923 | else |
brunnobbco | 0:561d07a737bc | 1924 | { |
brunnobbco | 0:561d07a737bc | 1925 | 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 | 1926 | _rf_settings.fsk_packet_handler.nb_bytes += ( _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes ); |
brunnobbco | 0:561d07a737bc | 1927 | } |
brunnobbco | 0:561d07a737bc | 1928 | break; |
brunnobbco | 0:561d07a737bc | 1929 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1930 | break; |
brunnobbco | 0:561d07a737bc | 1931 | default: |
brunnobbco | 0:561d07a737bc | 1932 | break; |
brunnobbco | 0:561d07a737bc | 1933 | } |
brunnobbco | 0:561d07a737bc | 1934 | break; |
brunnobbco | 0:561d07a737bc | 1935 | case RF_TX_RUNNING: |
brunnobbco | 0:561d07a737bc | 1936 | switch( _rf_settings.modem ) |
brunnobbco | 0:561d07a737bc | 1937 | { |
brunnobbco | 0:561d07a737bc | 1938 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1939 | // FifoLevel interrupt |
brunnobbco | 0:561d07a737bc | 1940 | if( ( _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes ) > _rf_settings.fsk_packet_handler.chunk_size ) |
brunnobbco | 0:561d07a737bc | 1941 | { |
brunnobbco | 0:561d07a737bc | 1942 | write_fifo(( _data_buffer + _rf_settings.fsk_packet_handler.nb_bytes ), _rf_settings.fsk_packet_handler.chunk_size ); |
brunnobbco | 0:561d07a737bc | 1943 | _rf_settings.fsk_packet_handler.nb_bytes += _rf_settings.fsk_packet_handler.chunk_size; |
brunnobbco | 0:561d07a737bc | 1944 | } |
brunnobbco | 0:561d07a737bc | 1945 | else |
brunnobbco | 0:561d07a737bc | 1946 | { |
brunnobbco | 0:561d07a737bc | 1947 | // Write the last chunk of data |
brunnobbco | 0:561d07a737bc | 1948 | 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 | 1949 | _rf_settings.fsk_packet_handler.nb_bytes += _rf_settings.fsk_packet_handler.size - _rf_settings.fsk_packet_handler.nb_bytes; |
brunnobbco | 0:561d07a737bc | 1950 | } |
brunnobbco | 0:561d07a737bc | 1951 | break; |
brunnobbco | 0:561d07a737bc | 1952 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1953 | break; |
brunnobbco | 0:561d07a737bc | 1954 | default: |
brunnobbco | 0:561d07a737bc | 1955 | break; |
brunnobbco | 0:561d07a737bc | 1956 | } |
brunnobbco | 0:561d07a737bc | 1957 | break; |
brunnobbco | 0:561d07a737bc | 1958 | default: |
brunnobbco | 0:561d07a737bc | 1959 | break; |
brunnobbco | 0:561d07a737bc | 1960 | } |
brunnobbco | 0:561d07a737bc | 1961 | } |
brunnobbco | 0:561d07a737bc | 1962 | |
brunnobbco | 0:561d07a737bc | 1963 | void SX1272_LoRaRadio::handle_dio2_irq(void) |
brunnobbco | 0:561d07a737bc | 1964 | { |
brunnobbco | 0:561d07a737bc | 1965 | switch(_rf_settings.state ) |
brunnobbco | 0:561d07a737bc | 1966 | { |
brunnobbco | 0:561d07a737bc | 1967 | case RF_RX_RUNNING: |
brunnobbco | 0:561d07a737bc | 1968 | switch( _rf_settings.modem ) |
brunnobbco | 0:561d07a737bc | 1969 | { |
brunnobbco | 0:561d07a737bc | 1970 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1971 | _rf_settings.fsk_packet_handler.preamble_detected = 0; |
brunnobbco | 0:561d07a737bc | 1972 | _rf_settings.fsk_packet_handler.sync_word_detected = 0; |
brunnobbco | 0:561d07a737bc | 1973 | _rf_settings.fsk_packet_handler.nb_bytes = 0; |
brunnobbco | 0:561d07a737bc | 1974 | _rf_settings.fsk_packet_handler.size = 0; |
brunnobbco | 0:561d07a737bc | 1975 | |
brunnobbco | 0:561d07a737bc | 1976 | // Clear Irqs |
brunnobbco | 0:561d07a737bc | 1977 | write_to_register(REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | |
brunnobbco | 0:561d07a737bc | 1978 | RF_IRQFLAGS1_PREAMBLEDETECT | |
brunnobbco | 0:561d07a737bc | 1979 | RF_IRQFLAGS1_SYNCADDRESSMATCH | |
brunnobbco | 0:561d07a737bc | 1980 | RF_IRQFLAGS1_TIMEOUT); |
brunnobbco | 0:561d07a737bc | 1981 | |
brunnobbco | 0:561d07a737bc | 1982 | write_to_register( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN); |
brunnobbco | 0:561d07a737bc | 1983 | |
brunnobbco | 0:561d07a737bc | 1984 | if (_rf_settings.fsk.rx_continuous == true) { |
brunnobbco | 0:561d07a737bc | 1985 | // Continuous mode restart Rx chain |
brunnobbco | 0:561d07a737bc | 1986 | write_to_register( REG_RXCONFIG, |
brunnobbco | 0:561d07a737bc | 1987 | read_register(REG_RXCONFIG) | |
brunnobbco | 0:561d07a737bc | 1988 | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK); |
brunnobbco | 0:561d07a737bc | 1989 | } else { |
brunnobbco | 0:561d07a737bc | 1990 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 1991 | } |
brunnobbco | 0:561d07a737bc | 1992 | |
brunnobbco | 0:561d07a737bc | 1993 | if ((_radio_events != NULL) |
brunnobbco | 0:561d07a737bc | 1994 | && (_radio_events->rx_timeout)) { |
brunnobbco | 0:561d07a737bc | 1995 | _radio_events->rx_timeout(); |
brunnobbco | 0:561d07a737bc | 1996 | } |
brunnobbco | 0:561d07a737bc | 1997 | |
brunnobbco | 0:561d07a737bc | 1998 | break; |
brunnobbco | 0:561d07a737bc | 1999 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2000 | break; |
brunnobbco | 0:561d07a737bc | 2001 | default: |
brunnobbco | 0:561d07a737bc | 2002 | break; |
brunnobbco | 0:561d07a737bc | 2003 | } |
brunnobbco | 0:561d07a737bc | 2004 | break; |
brunnobbco | 0:561d07a737bc | 2005 | case RF_TX_RUNNING: |
brunnobbco | 0:561d07a737bc | 2006 | switch( _rf_settings.modem ) |
brunnobbco | 0:561d07a737bc | 2007 | { |
brunnobbco | 0:561d07a737bc | 2008 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 2009 | break; |
brunnobbco | 0:561d07a737bc | 2010 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 2011 | break; |
brunnobbco | 0:561d07a737bc | 2012 | default: |
brunnobbco | 0:561d07a737bc | 2013 | break; |
brunnobbco | 0:561d07a737bc | 2014 | } |
brunnobbco | 0:561d07a737bc | 2015 | break; |
brunnobbco | 0:561d07a737bc | 2016 | default: |
brunnobbco | 0:561d07a737bc | 2017 | break; |
brunnobbco | 0:561d07a737bc | 2018 | } |
brunnobbco | 0:561d07a737bc | 2019 | } |
brunnobbco | 0:561d07a737bc | 2020 | |
brunnobbco | 0:561d07a737bc | 2021 | void SX1272_LoRaRadio::handle_timeout_irq() |
brunnobbco | 0:561d07a737bc | 2022 | { |
brunnobbco | 0:561d07a737bc | 2023 | tx_timeout_timer.detach(); |
brunnobbco | 0:561d07a737bc | 2024 | |
brunnobbco | 0:561d07a737bc | 2025 | if (_rf_settings.state == RF_TX_RUNNING) { |
brunnobbco | 0:561d07a737bc | 2026 | // Tx timeout shouldn't happen. |
brunnobbco | 0:561d07a737bc | 2027 | // But it has been observed that when it happens it is a result of a |
brunnobbco | 0:561d07a737bc | 2028 | // corrupted SPI transfer |
brunnobbco | 0:561d07a737bc | 2029 | // The workaround is to put the radio in a known state. |
brunnobbco | 0:561d07a737bc | 2030 | // Thus, we re-initialize it. |
brunnobbco | 0:561d07a737bc | 2031 | |
brunnobbco | 0:561d07a737bc | 2032 | // Initialize radio default values |
brunnobbco | 0:561d07a737bc | 2033 | set_operation_mode(RF_OPMODE_SLEEP); |
brunnobbco | 0:561d07a737bc | 2034 | |
brunnobbco | 0:561d07a737bc | 2035 | setup_registers(); |
brunnobbco | 0:561d07a737bc | 2036 | |
brunnobbco | 0:561d07a737bc | 2037 | set_modem(MODEM_FSK); |
brunnobbco | 0:561d07a737bc | 2038 | |
brunnobbco | 0:561d07a737bc | 2039 | // Restore previous network type setting. |
brunnobbco | 0:561d07a737bc | 2040 | set_public_network(_rf_settings.lora.public_network); |
brunnobbco | 0:561d07a737bc | 2041 | |
brunnobbco | 0:561d07a737bc | 2042 | _rf_settings.state = RF_IDLE; |
brunnobbco | 0:561d07a737bc | 2043 | |
brunnobbco | 0:561d07a737bc | 2044 | if ((_radio_events != NULL) && (_radio_events->tx_timeout)) { |
brunnobbco | 0:561d07a737bc | 2045 | _radio_events->tx_timeout(); |
brunnobbco | 0:561d07a737bc | 2046 | } |
brunnobbco | 0:561d07a737bc | 2047 | } |
brunnobbco | 0:561d07a737bc | 2048 | } |
brunnobbco | 0:561d07a737bc | 2049 | |
brunnobbco | 0:561d07a737bc | 2050 | void SX1272_LoRaRadio::handle_rxsync_irq() |
brunnobbco | 0:561d07a737bc | 2051 | { |
brunnobbco | 0:561d07a737bc | 2052 | rx_sync_timer.detach(); |
brunnobbco | 0:561d07a737bc | 2053 | |
brunnobbco | 1:3bdd6f917bf5 | 2054 | if (_rf_settings.modem != MODEM_LORA) { |
brunnobbco | 1:3bdd6f917bf5 | 2055 | return; |
brunnobbco | 1:3bdd6f917bf5 | 2056 | } |
brunnobbco | 1:3bdd6f917bf5 | 2057 | if (_rf_settings.state != RF_RX_RUNNING) { |
brunnobbco | 1:3bdd6f917bf5 | 2058 | return; |
brunnobbco | 1:3bdd6f917bf5 | 2059 | } |
brunnobbco | 1:3bdd6f917bf5 | 2060 | |
brunnobbco | 1:3bdd6f917bf5 | 2061 | if((read_register(REG_OPMODE) & 0x7) == RFLR_OPMODE_RECEIVER_SINGLE) |
brunnobbco | 1:3bdd6f917bf5 | 2062 | { |
brunnobbco | 1:3bdd6f917bf5 | 2063 | rx_sync_timer.attach_us(callback(this, &SX1272_LoRaRadio::rxsync_irq_isr), 1000); |
brunnobbco | 1:3bdd6f917bf5 | 2064 | } |
brunnobbco | 1:3bdd6f917bf5 | 2065 | else |
brunnobbco | 0:561d07a737bc | 2066 | { |
brunnobbco | 1:3bdd6f917bf5 | 2067 | // Sync time out |
brunnobbco | 1:3bdd6f917bf5 | 2068 | _rf_settings.state = RF_IDLE; |
brunnobbco | 1:3bdd6f917bf5 | 2069 | |
brunnobbco | 1:3bdd6f917bf5 | 2070 | if ((_radio_events != NULL) && (_radio_events->rx_timeout)) { |
brunnobbco | 1:3bdd6f917bf5 | 2071 | _radio_events->rx_timeout(); |
brunnobbco | 1:3bdd6f917bf5 | 2072 | } |
brunnobbco | 1:3bdd6f917bf5 | 2073 | } |
brunnobbco | 1:3bdd6f917bf5 | 2074 | } |
brunnobbco | 1:3bdd6f917bf5 | 2075 | |
brunnobbco | 1:3bdd6f917bf5 | 2076 | void SX1272_LoRaRadio::handle_lrcad_irq() |
brunnobbco | 1:3bdd6f917bf5 | 2077 | { |
brunnobbco | 1:3bdd6f917bf5 | 2078 | lora_cad_timer.detach(); |
brunnobbco | 1:3bdd6f917bf5 | 2079 | |
brunnobbco | 1:3bdd6f917bf5 | 2080 | if (_rf_settings.modem != MODEM_LORA) { |
brunnobbco | 1:3bdd6f917bf5 | 2081 | return; |
brunnobbco | 1:3bdd6f917bf5 | 2082 | } |
brunnobbco | 1:3bdd6f917bf5 | 2083 | if (_rf_settings.state != RF_CAD) { |
brunnobbco | 1:3bdd6f917bf5 | 2084 | return; |
brunnobbco | 1:3bdd6f917bf5 | 2085 | } |
brunnobbco | 1:3bdd6f917bf5 | 2086 | |
brunnobbco | 1:3bdd6f917bf5 | 2087 | if((read_register(REG_OPMODE) & 0x7) == RFLR_OPMODE_CAD) |
brunnobbco | 1:3bdd6f917bf5 | 2088 | { |
brunnobbco | 1:3bdd6f917bf5 | 2089 | lora_cad_timer.attach_us(callback(this, &SX1272_LoRaRadio::lrcad_irq_isr), 1000); |
brunnobbco | 1:3bdd6f917bf5 | 2090 | } |
brunnobbco | 1:3bdd6f917bf5 | 2091 | else |
brunnobbco | 1:3bdd6f917bf5 | 2092 | { |
brunnobbco | 1:3bdd6f917bf5 | 2093 | _rf_settings.state = RF_IDLE; |
brunnobbco | 1:3bdd6f917bf5 | 2094 | |
brunnobbco | 1:3bdd6f917bf5 | 2095 | if( ( read_register( REG_LR_IRQFLAGS ) & RFLR_IRQFLAGS_CADDETECTED ) == RFLR_IRQFLAGS_CADDETECTED ) |
brunnobbco | 0:561d07a737bc | 2096 | { |
brunnobbco | 1:3bdd6f917bf5 | 2097 | // Clear Irq |
brunnobbco | 1:3bdd6f917bf5 | 2098 | write_to_register( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE ); |
brunnobbco | 1:3bdd6f917bf5 | 2099 | |
brunnobbco | 1:3bdd6f917bf5 | 2100 | if( ( _radio_events != NULL ) && ( _radio_events->cad_done ) ) |
brunnobbco | 1:3bdd6f917bf5 | 2101 | { |
brunnobbco | 1:3bdd6f917bf5 | 2102 | _radio_events->cad_done( true ); |
brunnobbco | 1:3bdd6f917bf5 | 2103 | } |
brunnobbco | 0:561d07a737bc | 2104 | } |
brunnobbco | 0:561d07a737bc | 2105 | else |
brunnobbco | 0:561d07a737bc | 2106 | { |
brunnobbco | 1:3bdd6f917bf5 | 2107 | // Clear Irq |
brunnobbco | 1:3bdd6f917bf5 | 2108 | write_to_register( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE ); |
brunnobbco | 1:3bdd6f917bf5 | 2109 | if( ( _radio_events != NULL ) && ( _radio_events->cad_done ) ) |
brunnobbco | 1:3bdd6f917bf5 | 2110 | { |
brunnobbco | 1:3bdd6f917bf5 | 2111 | _radio_events->cad_done( false ); |
brunnobbco | 0:561d07a737bc | 2112 | } |
brunnobbco | 0:561d07a737bc | 2113 | } |
brunnobbco | 0:561d07a737bc | 2114 | } |
brunnobbco | 0:561d07a737bc | 2115 | } |
brunnobbco | 0:561d07a737bc | 2116 | |
brunnobbco | 1:3bdd6f917bf5 | 2117 | void SX1272_LoRaRadio::handle_lrhop_irq() |
brunnobbco | 1:3bdd6f917bf5 | 2118 | { |
brunnobbco | 1:3bdd6f917bf5 | 2119 | lora_hop_timer.detach(); |
brunnobbco | 1:3bdd6f917bf5 | 2120 | |
brunnobbco | 1:3bdd6f917bf5 | 2121 | if ((_rf_settings.state != RF_TX_RUNNING) && (_rf_settings.state != RF_RX_RUNNING)) { |
brunnobbco | 1:3bdd6f917bf5 | 2122 | return; |
brunnobbco | 1:3bdd6f917bf5 | 2123 | } |
brunnobbco | 1:3bdd6f917bf5 | 2124 | if ((_rf_settings.modem != MODEM_LORA) || (_rf_settings.lora.freq_hop_on == false)) { |
brunnobbco | 1:3bdd6f917bf5 | 2125 | return; |
brunnobbco | 1:3bdd6f917bf5 | 2126 | } |
brunnobbco | 1:3bdd6f917bf5 | 2127 | |
brunnobbco | 1:3bdd6f917bf5 | 2128 | lora_hop_timer.attach_us(callback(this, &SX1272_LoRaRadio::lrhop_irq_isr), 1000); |
brunnobbco | 1:3bdd6f917bf5 | 2129 | |
brunnobbco | 1:3bdd6f917bf5 | 2130 | if((read_register(REG_LR_IRQFLAGS) & RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL) == RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL) |
brunnobbco | 1:3bdd6f917bf5 | 2131 | { |
brunnobbco | 1:3bdd6f917bf5 | 2132 | write_to_register( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); |
brunnobbco | 1:3bdd6f917bf5 | 2133 | |
brunnobbco | 1:3bdd6f917bf5 | 2134 | if((_radio_events != NULL) && (_radio_events->fhss_change_channel)) |
brunnobbco | 1:3bdd6f917bf5 | 2135 | { |
brunnobbco | 1:3bdd6f917bf5 | 2136 | _radio_events->fhss_change_channel((read_register( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK)); |
brunnobbco | 1:3bdd6f917bf5 | 2137 | } |
brunnobbco | 1:3bdd6f917bf5 | 2138 | } |
brunnobbco | 1:3bdd6f917bf5 | 2139 | } |