testing hex for lorawan communication
SX126X/SX126X_LoRaRadio.cpp@0:561d07a737bc, 2020-11-12 (annotated)
- Committer:
- brunnobbco
- Date:
- Thu Nov 12 19:26:24 2020 +0000
- Revision:
- 0:561d07a737bc
- Child:
- 3:9e7d20163e7a
SX1272 driver using only DIO0 and polling.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
brunnobbco | 0:561d07a737bc | 1 | /** |
brunnobbco | 0:561d07a737bc | 2 | / _____) _ | | |
brunnobbco | 0:561d07a737bc | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ |
brunnobbco | 0:561d07a737bc | 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ |
brunnobbco | 0:561d07a737bc | 5 | _____) ) ____| | | || |_| ____( (___| | | | |
brunnobbco | 0:561d07a737bc | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| |
brunnobbco | 0:561d07a737bc | 7 | (C)2015 Semtech |
brunnobbco | 0:561d07a737bc | 8 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ |
brunnobbco | 0:561d07a737bc | 9 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| |
brunnobbco | 0:561d07a737bc | 10 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| |
brunnobbco | 0:561d07a737bc | 11 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| |
brunnobbco | 0:561d07a737bc | 12 | embedded.connectivity.solutions=============== |
brunnobbco | 0:561d07a737bc | 13 | |
brunnobbco | 0:561d07a737bc | 14 | Description: LoRaWAN stack layer that controls both MAC and PHY underneath |
brunnobbco | 0:561d07a737bc | 15 | |
brunnobbco | 0:561d07a737bc | 16 | License: Revised BSD License, see LICENSE.TXT file include in the project |
brunnobbco | 0:561d07a737bc | 17 | |
brunnobbco | 0:561d07a737bc | 18 | Maintainer: Miguel Luis, Gregory Cristian & Gilbert Menth |
brunnobbco | 0:561d07a737bc | 19 | |
brunnobbco | 0:561d07a737bc | 20 | Copyright (c) 2019, Arm Limited and affiliates. |
brunnobbco | 0:561d07a737bc | 21 | |
brunnobbco | 0:561d07a737bc | 22 | SPDX-License-Identifier: BSD-3-Clause |
brunnobbco | 0:561d07a737bc | 23 | */ |
brunnobbco | 0:561d07a737bc | 24 | |
brunnobbco | 0:561d07a737bc | 25 | #include <math.h> |
brunnobbco | 0:561d07a737bc | 26 | #include "mbed_wait_api.h" |
brunnobbco | 0:561d07a737bc | 27 | #include "Timer.h" |
brunnobbco | 0:561d07a737bc | 28 | #include "SX126X_LoRaRadio.h" |
brunnobbco | 0:561d07a737bc | 29 | |
brunnobbco | 0:561d07a737bc | 30 | #ifdef MBED_CONF_SX126X_LORA_DRIVER_SPI_FREQUENCY |
brunnobbco | 0:561d07a737bc | 31 | #define SPI_FREQUENCY MBED_CONF_SX126X_LORA_DRIVER_SPI_FREQUENCY |
brunnobbco | 0:561d07a737bc | 32 | #else |
brunnobbco | 0:561d07a737bc | 33 | #define SPI_FREQUENCY 16000000 |
brunnobbco | 0:561d07a737bc | 34 | #endif |
brunnobbco | 0:561d07a737bc | 35 | |
brunnobbco | 0:561d07a737bc | 36 | using namespace mbed; |
brunnobbco | 0:561d07a737bc | 37 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 38 | using namespace rtos; |
brunnobbco | 0:561d07a737bc | 39 | /** |
brunnobbco | 0:561d07a737bc | 40 | * Signals |
brunnobbco | 0:561d07a737bc | 41 | */ |
brunnobbco | 0:561d07a737bc | 42 | #define SIG_INTERRUPT 0x02 |
brunnobbco | 0:561d07a737bc | 43 | #endif |
brunnobbco | 0:561d07a737bc | 44 | |
brunnobbco | 0:561d07a737bc | 45 | /*! |
brunnobbco | 0:561d07a737bc | 46 | * FSK bandwidth definition |
brunnobbco | 0:561d07a737bc | 47 | */ |
brunnobbco | 0:561d07a737bc | 48 | typedef struct |
brunnobbco | 0:561d07a737bc | 49 | { |
brunnobbco | 0:561d07a737bc | 50 | uint32_t bandwidth; |
brunnobbco | 0:561d07a737bc | 51 | uint8_t register_value; |
brunnobbco | 0:561d07a737bc | 52 | } fsk_bw_t; |
brunnobbco | 0:561d07a737bc | 53 | |
brunnobbco | 0:561d07a737bc | 54 | static const fsk_bw_t fsk_bandwidths[] = |
brunnobbco | 0:561d07a737bc | 55 | { |
brunnobbco | 0:561d07a737bc | 56 | { 4800 , 0x1F }, |
brunnobbco | 0:561d07a737bc | 57 | { 5800 , 0x17 }, |
brunnobbco | 0:561d07a737bc | 58 | { 7300 , 0x0F }, |
brunnobbco | 0:561d07a737bc | 59 | { 9700 , 0x1E }, |
brunnobbco | 0:561d07a737bc | 60 | { 11700 , 0x16 }, |
brunnobbco | 0:561d07a737bc | 61 | { 14600 , 0x0E }, |
brunnobbco | 0:561d07a737bc | 62 | { 19500 , 0x1D }, |
brunnobbco | 0:561d07a737bc | 63 | { 23400 , 0x15 }, |
brunnobbco | 0:561d07a737bc | 64 | { 29300 , 0x0D }, |
brunnobbco | 0:561d07a737bc | 65 | { 39000 , 0x1C }, |
brunnobbco | 0:561d07a737bc | 66 | { 46900 , 0x14 }, |
brunnobbco | 0:561d07a737bc | 67 | { 58600 , 0x0C }, |
brunnobbco | 0:561d07a737bc | 68 | { 78200 , 0x1B }, |
brunnobbco | 0:561d07a737bc | 69 | { 93800 , 0x13 }, |
brunnobbco | 0:561d07a737bc | 70 | { 117300, 0x0B }, |
brunnobbco | 0:561d07a737bc | 71 | { 156200, 0x1A }, |
brunnobbco | 0:561d07a737bc | 72 | { 187200, 0x12 }, |
brunnobbco | 0:561d07a737bc | 73 | { 234300, 0x0A }, |
brunnobbco | 0:561d07a737bc | 74 | { 312000, 0x19 }, |
brunnobbco | 0:561d07a737bc | 75 | { 373600, 0x11 }, |
brunnobbco | 0:561d07a737bc | 76 | { 467000, 0x09 }, |
brunnobbco | 0:561d07a737bc | 77 | { 500000, 0x00 }, // Invalid Bandwidth |
brunnobbco | 0:561d07a737bc | 78 | }; |
brunnobbco | 0:561d07a737bc | 79 | |
brunnobbco | 0:561d07a737bc | 80 | const uint8_t sync_word[] = {0xC1, 0x94, 0xC1, 0x00, 0x00, 0x00, 0x00,0x00}; |
brunnobbco | 0:561d07a737bc | 81 | |
brunnobbco | 0:561d07a737bc | 82 | // in ms SF12 SF11 SF10 SF9 SF8 SF7 |
brunnobbco | 0:561d07a737bc | 83 | const float lora_symbol_time[3][6] = {{ 32.768, 16.384, 8.192, 4.096, 2.048, 1.024 }, // 125 KHz |
brunnobbco | 0:561d07a737bc | 84 | { 16.384, 8.192, 4.096, 2.048, 1.024, 0.512 }, // 250 KHz |
brunnobbco | 0:561d07a737bc | 85 | { 8.192, 4.096, 2.048, 1.024, 0.512, 0.256 }}; // 500 KHz |
brunnobbco | 0:561d07a737bc | 86 | |
brunnobbco | 0:561d07a737bc | 87 | SX126X_LoRaRadio::SX126X_LoRaRadio(PinName mosi, |
brunnobbco | 0:561d07a737bc | 88 | PinName miso, |
brunnobbco | 0:561d07a737bc | 89 | PinName sclk, |
brunnobbco | 0:561d07a737bc | 90 | PinName nss, |
brunnobbco | 0:561d07a737bc | 91 | PinName reset, |
brunnobbco | 0:561d07a737bc | 92 | PinName dio1, |
brunnobbco | 0:561d07a737bc | 93 | PinName busy, |
brunnobbco | 0:561d07a737bc | 94 | PinName freq_select, |
brunnobbco | 0:561d07a737bc | 95 | PinName device_select, |
brunnobbco | 0:561d07a737bc | 96 | PinName crystal_select, |
brunnobbco | 0:561d07a737bc | 97 | PinName ant_switch) |
brunnobbco | 0:561d07a737bc | 98 | : _spi(mosi, miso, sclk), |
brunnobbco | 0:561d07a737bc | 99 | _chip_select(nss, 1), |
brunnobbco | 0:561d07a737bc | 100 | _reset_ctl(reset), |
brunnobbco | 0:561d07a737bc | 101 | _dio1_ctl(dio1, PullNone), |
brunnobbco | 0:561d07a737bc | 102 | _busy(busy, PullNone), |
brunnobbco | 0:561d07a737bc | 103 | _freq_select(freq_select), |
brunnobbco | 0:561d07a737bc | 104 | _dev_select(device_select), |
brunnobbco | 0:561d07a737bc | 105 | _crystal_select(crystal_select, PullDown), |
brunnobbco | 0:561d07a737bc | 106 | _ant_switch(ant_switch, PIN_INPUT, PullUp, 0) |
brunnobbco | 0:561d07a737bc | 107 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 108 | , irq_thread(osPriorityRealtime, 1024, NULL, "LR-SX126X") |
brunnobbco | 0:561d07a737bc | 109 | #endif |
brunnobbco | 0:561d07a737bc | 110 | { |
brunnobbco | 0:561d07a737bc | 111 | _radio_events = NULL; |
brunnobbco | 0:561d07a737bc | 112 | _reset_ctl = 1; |
brunnobbco | 0:561d07a737bc | 113 | _image_calibrated = false; |
brunnobbco | 0:561d07a737bc | 114 | _force_image_calibration = false; |
brunnobbco | 0:561d07a737bc | 115 | _active_modem = MODEM_LORA; |
brunnobbco | 0:561d07a737bc | 116 | |
brunnobbco | 0:561d07a737bc | 117 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 118 | irq_thread.start(callback(this, &SX126X_LoRaRadio::rf_irq_task)); |
brunnobbco | 0:561d07a737bc | 119 | #endif |
brunnobbco | 0:561d07a737bc | 120 | } |
brunnobbco | 0:561d07a737bc | 121 | |
brunnobbco | 0:561d07a737bc | 122 | SX126X_LoRaRadio::~SX126X_LoRaRadio() |
brunnobbco | 0:561d07a737bc | 123 | { |
brunnobbco | 0:561d07a737bc | 124 | |
brunnobbco | 0:561d07a737bc | 125 | } |
brunnobbco | 0:561d07a737bc | 126 | |
brunnobbco | 0:561d07a737bc | 127 | /** |
brunnobbco | 0:561d07a737bc | 128 | * Acquire lock |
brunnobbco | 0:561d07a737bc | 129 | */ |
brunnobbco | 0:561d07a737bc | 130 | void SX126X_LoRaRadio::lock(void) |
brunnobbco | 0:561d07a737bc | 131 | { |
brunnobbco | 0:561d07a737bc | 132 | mutex.lock(); |
brunnobbco | 0:561d07a737bc | 133 | } |
brunnobbco | 0:561d07a737bc | 134 | |
brunnobbco | 0:561d07a737bc | 135 | /** |
brunnobbco | 0:561d07a737bc | 136 | * Release lock |
brunnobbco | 0:561d07a737bc | 137 | */ |
brunnobbco | 0:561d07a737bc | 138 | void SX126X_LoRaRadio::unlock(void) |
brunnobbco | 0:561d07a737bc | 139 | { |
brunnobbco | 0:561d07a737bc | 140 | mutex.unlock(); |
brunnobbco | 0:561d07a737bc | 141 | } |
brunnobbco | 0:561d07a737bc | 142 | |
brunnobbco | 0:561d07a737bc | 143 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 144 | /** |
brunnobbco | 0:561d07a737bc | 145 | * Thread task handling IRQs |
brunnobbco | 0:561d07a737bc | 146 | */ |
brunnobbco | 0:561d07a737bc | 147 | void SX126X_LoRaRadio::rf_irq_task(void) |
brunnobbco | 0:561d07a737bc | 148 | { |
brunnobbco | 0:561d07a737bc | 149 | for (;;) { |
brunnobbco | 0:561d07a737bc | 150 | uint32_t flags = ThisThread::flags_wait_any(0x7FFFFFFF); |
brunnobbco | 0:561d07a737bc | 151 | |
brunnobbco | 0:561d07a737bc | 152 | lock(); |
brunnobbco | 0:561d07a737bc | 153 | if (flags & SIG_INTERRUPT) { |
brunnobbco | 0:561d07a737bc | 154 | handle_dio1_irq(); |
brunnobbco | 0:561d07a737bc | 155 | } |
brunnobbco | 0:561d07a737bc | 156 | unlock(); |
brunnobbco | 0:561d07a737bc | 157 | } |
brunnobbco | 0:561d07a737bc | 158 | } |
brunnobbco | 0:561d07a737bc | 159 | #endif |
brunnobbco | 0:561d07a737bc | 160 | |
brunnobbco | 0:561d07a737bc | 161 | void SX126X_LoRaRadio::dio1_irq_isr() |
brunnobbco | 0:561d07a737bc | 162 | { |
brunnobbco | 0:561d07a737bc | 163 | #ifdef MBED_CONF_RTOS_PRESENT |
brunnobbco | 0:561d07a737bc | 164 | irq_thread.flags_set(SIG_INTERRUPT); |
brunnobbco | 0:561d07a737bc | 165 | #else |
brunnobbco | 0:561d07a737bc | 166 | handle_dio1_irq(); |
brunnobbco | 0:561d07a737bc | 167 | #endif |
brunnobbco | 0:561d07a737bc | 168 | } |
brunnobbco | 0:561d07a737bc | 169 | |
brunnobbco | 0:561d07a737bc | 170 | uint16_t SX126X_LoRaRadio::get_irq_status(void) |
brunnobbco | 0:561d07a737bc | 171 | { |
brunnobbco | 0:561d07a737bc | 172 | uint8_t status[2]; |
brunnobbco | 0:561d07a737bc | 173 | |
brunnobbco | 0:561d07a737bc | 174 | read_opmode_command((uint8_t) RADIO_GET_IRQSTATUS, status, 2); |
brunnobbco | 0:561d07a737bc | 175 | return (status[0] << 8) | status[1]; |
brunnobbco | 0:561d07a737bc | 176 | } |
brunnobbco | 0:561d07a737bc | 177 | |
brunnobbco | 0:561d07a737bc | 178 | void SX126X_LoRaRadio::clear_irq_status(uint16_t irq) |
brunnobbco | 0:561d07a737bc | 179 | { |
brunnobbco | 0:561d07a737bc | 180 | uint8_t buf[2]; |
brunnobbco | 0:561d07a737bc | 181 | |
brunnobbco | 0:561d07a737bc | 182 | buf[0] = (uint8_t) (((uint16_t) irq >> 8) & 0x00FF); |
brunnobbco | 0:561d07a737bc | 183 | buf[1] = (uint8_t) ((uint16_t) irq & 0x00FF); |
brunnobbco | 0:561d07a737bc | 184 | write_opmode_command((uint8_t) RADIO_CLR_IRQSTATUS, buf, 2); |
brunnobbco | 0:561d07a737bc | 185 | } |
brunnobbco | 0:561d07a737bc | 186 | |
brunnobbco | 0:561d07a737bc | 187 | //TODO - Better do CAD here. CAD code is already part of the driver |
brunnobbco | 0:561d07a737bc | 188 | // It needs to be hooked up to the stack (this API will need change |
brunnobbco | 0:561d07a737bc | 189 | // and the stack will need changes too) |
brunnobbco | 0:561d07a737bc | 190 | bool SX126X_LoRaRadio::perform_carrier_sense(radio_modems_t modem, |
brunnobbco | 0:561d07a737bc | 191 | uint32_t freq, |
brunnobbco | 0:561d07a737bc | 192 | int16_t rssi_threshold, |
brunnobbco | 0:561d07a737bc | 193 | uint32_t max_carrier_sense_time) |
brunnobbco | 0:561d07a737bc | 194 | { |
brunnobbco | 0:561d07a737bc | 195 | bool status = true; |
brunnobbco | 0:561d07a737bc | 196 | int16_t rssi = 0; |
brunnobbco | 0:561d07a737bc | 197 | |
brunnobbco | 0:561d07a737bc | 198 | set_modem(modem); |
brunnobbco | 0:561d07a737bc | 199 | set_channel(freq); |
brunnobbco | 0:561d07a737bc | 200 | _reception_mode = RECEPTION_MODE_OTHER; |
brunnobbco | 0:561d07a737bc | 201 | _rx_timeout = 0x00000000; |
brunnobbco | 0:561d07a737bc | 202 | receive(); |
brunnobbco | 0:561d07a737bc | 203 | |
brunnobbco | 0:561d07a737bc | 204 | // hold on a bit, radio turn-around time |
brunnobbco | 0:561d07a737bc | 205 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 206 | |
brunnobbco | 0:561d07a737bc | 207 | Timer elapsed_time; |
brunnobbco | 0:561d07a737bc | 208 | elapsed_time.start(); |
brunnobbco | 0:561d07a737bc | 209 | |
brunnobbco | 0:561d07a737bc | 210 | // Perform carrier sense for maxCarrierSenseTime |
brunnobbco | 0:561d07a737bc | 211 | while (elapsed_time.read_ms() < (int) max_carrier_sense_time) { |
brunnobbco | 0:561d07a737bc | 212 | rssi = get_rssi(); |
brunnobbco | 0:561d07a737bc | 213 | |
brunnobbco | 0:561d07a737bc | 214 | if (rssi > rssi_threshold) { |
brunnobbco | 0:561d07a737bc | 215 | status = false; |
brunnobbco | 0:561d07a737bc | 216 | break; |
brunnobbco | 0:561d07a737bc | 217 | } |
brunnobbco | 0:561d07a737bc | 218 | } |
brunnobbco | 0:561d07a737bc | 219 | |
brunnobbco | 0:561d07a737bc | 220 | sleep(); |
brunnobbco | 0:561d07a737bc | 221 | return status; |
brunnobbco | 0:561d07a737bc | 222 | } |
brunnobbco | 0:561d07a737bc | 223 | |
brunnobbco | 0:561d07a737bc | 224 | void SX126X_LoRaRadio::start_cad(void) |
brunnobbco | 0:561d07a737bc | 225 | { |
brunnobbco | 0:561d07a737bc | 226 | // TODO: CAD is more advanced in SX126X. We will need API change in LoRaRadio |
brunnobbco | 0:561d07a737bc | 227 | // for this to act properly |
brunnobbco | 0:561d07a737bc | 228 | } |
brunnobbco | 0:561d07a737bc | 229 | |
brunnobbco | 0:561d07a737bc | 230 | /** |
brunnobbco | 0:561d07a737bc | 231 | * TODO: The purpose of this API is unclear. |
brunnobbco | 0:561d07a737bc | 232 | * Need to start an internal discussion. |
brunnobbco | 0:561d07a737bc | 233 | */ |
brunnobbco | 0:561d07a737bc | 234 | bool SX126X_LoRaRadio::check_rf_frequency(uint32_t frequency) |
brunnobbco | 0:561d07a737bc | 235 | { |
brunnobbco | 0:561d07a737bc | 236 | // Implement check. Currently all frequencies are supported ? What band ? |
brunnobbco | 0:561d07a737bc | 237 | return true; |
brunnobbco | 0:561d07a737bc | 238 | } |
brunnobbco | 0:561d07a737bc | 239 | |
brunnobbco | 0:561d07a737bc | 240 | void SX126X_LoRaRadio::set_tx_continuous_wave(uint32_t freq, int8_t power, |
brunnobbco | 0:561d07a737bc | 241 | uint16_t time) |
brunnobbco | 0:561d07a737bc | 242 | { |
brunnobbco | 0:561d07a737bc | 243 | // This is useless. We even removed the support from our MAC layer. |
brunnobbco | 0:561d07a737bc | 244 | } |
brunnobbco | 0:561d07a737bc | 245 | |
brunnobbco | 0:561d07a737bc | 246 | void SX126X_LoRaRadio::handle_dio1_irq() |
brunnobbco | 0:561d07a737bc | 247 | { |
brunnobbco | 0:561d07a737bc | 248 | uint16_t irq_status = get_irq_status(); |
brunnobbco | 0:561d07a737bc | 249 | clear_irq_status(IRQ_RADIO_ALL); |
brunnobbco | 0:561d07a737bc | 250 | |
brunnobbco | 0:561d07a737bc | 251 | if ((irq_status & IRQ_TX_DONE) == IRQ_TX_DONE) { |
brunnobbco | 0:561d07a737bc | 252 | if (_radio_events->tx_done) { |
brunnobbco | 0:561d07a737bc | 253 | _radio_events->tx_done(); |
brunnobbco | 0:561d07a737bc | 254 | } |
brunnobbco | 0:561d07a737bc | 255 | } |
brunnobbco | 0:561d07a737bc | 256 | |
brunnobbco | 0:561d07a737bc | 257 | if ((irq_status & IRQ_RX_DONE) == IRQ_RX_DONE) { |
brunnobbco | 0:561d07a737bc | 258 | if ((irq_status & IRQ_CRC_ERROR) == IRQ_CRC_ERROR) { |
brunnobbco | 0:561d07a737bc | 259 | if (_radio_events && _radio_events->rx_error) { |
brunnobbco | 0:561d07a737bc | 260 | _radio_events->rx_error(); |
brunnobbco | 0:561d07a737bc | 261 | } |
brunnobbco | 0:561d07a737bc | 262 | } else { |
brunnobbco | 0:561d07a737bc | 263 | if (_radio_events->rx_done) { |
brunnobbco | 0:561d07a737bc | 264 | uint8_t offset = 0; |
brunnobbco | 0:561d07a737bc | 265 | uint8_t payload_len = 0; |
brunnobbco | 0:561d07a737bc | 266 | int16_t rssi = 0; |
brunnobbco | 0:561d07a737bc | 267 | int8_t snr = 0; |
brunnobbco | 0:561d07a737bc | 268 | packet_status_t pkt_status; |
brunnobbco | 0:561d07a737bc | 269 | |
brunnobbco | 0:561d07a737bc | 270 | get_rx_buffer_status(&payload_len, &offset); |
brunnobbco | 0:561d07a737bc | 271 | read_fifo(_data_buffer, payload_len, offset); |
brunnobbco | 0:561d07a737bc | 272 | get_packet_status(&pkt_status); |
brunnobbco | 0:561d07a737bc | 273 | if (pkt_status.modem_type == MODEM_FSK) { |
brunnobbco | 0:561d07a737bc | 274 | rssi = pkt_status.params.gfsk.rssi_sync; |
brunnobbco | 0:561d07a737bc | 275 | } else { |
brunnobbco | 0:561d07a737bc | 276 | rssi = pkt_status.params.lora.rssi_pkt; |
brunnobbco | 0:561d07a737bc | 277 | snr = pkt_status.params.lora.snr_pkt; |
brunnobbco | 0:561d07a737bc | 278 | } |
brunnobbco | 0:561d07a737bc | 279 | |
brunnobbco | 0:561d07a737bc | 280 | _radio_events->rx_done(_data_buffer, payload_len, rssi, snr); |
brunnobbco | 0:561d07a737bc | 281 | } |
brunnobbco | 0:561d07a737bc | 282 | } |
brunnobbco | 0:561d07a737bc | 283 | } |
brunnobbco | 0:561d07a737bc | 284 | |
brunnobbco | 0:561d07a737bc | 285 | if ((irq_status & IRQ_CAD_DONE) == IRQ_CAD_DONE) { |
brunnobbco | 0:561d07a737bc | 286 | if (_radio_events->cad_done) { |
brunnobbco | 0:561d07a737bc | 287 | _radio_events->cad_done((irq_status & IRQ_CAD_ACTIVITY_DETECTED) |
brunnobbco | 0:561d07a737bc | 288 | == IRQ_CAD_ACTIVITY_DETECTED); |
brunnobbco | 0:561d07a737bc | 289 | } |
brunnobbco | 0:561d07a737bc | 290 | } |
brunnobbco | 0:561d07a737bc | 291 | |
brunnobbco | 0:561d07a737bc | 292 | if ((irq_status & IRQ_RX_TX_TIMEOUT) == IRQ_RX_TX_TIMEOUT) { |
brunnobbco | 0:561d07a737bc | 293 | if ((_radio_events->tx_timeout) && (_operation_mode == MODE_TX)) { |
brunnobbco | 0:561d07a737bc | 294 | _radio_events->tx_timeout(); |
brunnobbco | 0:561d07a737bc | 295 | } else if ((_radio_events && _radio_events->rx_timeout) && (_operation_mode == MODE_RX)) { |
brunnobbco | 0:561d07a737bc | 296 | _radio_events->rx_timeout(); |
brunnobbco | 0:561d07a737bc | 297 | } |
brunnobbco | 0:561d07a737bc | 298 | } |
brunnobbco | 0:561d07a737bc | 299 | } |
brunnobbco | 0:561d07a737bc | 300 | |
brunnobbco | 0:561d07a737bc | 301 | void SX126X_LoRaRadio::set_device_ready(void) |
brunnobbco | 0:561d07a737bc | 302 | { |
brunnobbco | 0:561d07a737bc | 303 | if (_operation_mode == MODE_SLEEP) { |
brunnobbco | 0:561d07a737bc | 304 | wakeup(); |
brunnobbco | 0:561d07a737bc | 305 | } |
brunnobbco | 0:561d07a737bc | 306 | } |
brunnobbco | 0:561d07a737bc | 307 | |
brunnobbco | 0:561d07a737bc | 308 | void SX126X_LoRaRadio::calibrate_image(uint32_t freq) |
brunnobbco | 0:561d07a737bc | 309 | { |
brunnobbco | 0:561d07a737bc | 310 | uint8_t cal_freq[2]; |
brunnobbco | 0:561d07a737bc | 311 | |
brunnobbco | 0:561d07a737bc | 312 | if (freq > 900000000) { |
brunnobbco | 0:561d07a737bc | 313 | cal_freq[0] = 0xE1; |
brunnobbco | 0:561d07a737bc | 314 | cal_freq[1] = 0xE9; |
brunnobbco | 0:561d07a737bc | 315 | } else if (freq > 850000000) { |
brunnobbco | 0:561d07a737bc | 316 | cal_freq[0] = 0xD7; |
brunnobbco | 0:561d07a737bc | 317 | cal_freq[1] = 0xD8; |
brunnobbco | 0:561d07a737bc | 318 | } else if (freq > 770000000) { |
brunnobbco | 0:561d07a737bc | 319 | cal_freq[0] = 0xC1; |
brunnobbco | 0:561d07a737bc | 320 | cal_freq[1] = 0xC5; |
brunnobbco | 0:561d07a737bc | 321 | } else if (freq > 460000000) { |
brunnobbco | 0:561d07a737bc | 322 | cal_freq[0] = 0x75; |
brunnobbco | 0:561d07a737bc | 323 | cal_freq[1] = 0x81; |
brunnobbco | 0:561d07a737bc | 324 | } else if (freq > 425000000) { |
brunnobbco | 0:561d07a737bc | 325 | cal_freq[0] = 0x6B; |
brunnobbco | 0:561d07a737bc | 326 | cal_freq[1] = 0x6F; |
brunnobbco | 0:561d07a737bc | 327 | } |
brunnobbco | 0:561d07a737bc | 328 | |
brunnobbco | 0:561d07a737bc | 329 | write_opmode_command((uint8_t) RADIO_CALIBRATEIMAGE, cal_freq, 2); |
brunnobbco | 0:561d07a737bc | 330 | |
brunnobbco | 0:561d07a737bc | 331 | _image_calibrated = true; |
brunnobbco | 0:561d07a737bc | 332 | } |
brunnobbco | 0:561d07a737bc | 333 | |
brunnobbco | 0:561d07a737bc | 334 | void SX126X_LoRaRadio::set_channel(uint32_t frequency) |
brunnobbco | 0:561d07a737bc | 335 | { |
brunnobbco | 0:561d07a737bc | 336 | #if MBED_CONF_SX126X_LORA_DRIVER_SLEEP_MODE == 1 |
brunnobbco | 0:561d07a737bc | 337 | // At this point, we are not sure what is the Modem type, set both |
brunnobbco | 0:561d07a737bc | 338 | _mod_params.params.lora.operational_frequency = frequency; |
brunnobbco | 0:561d07a737bc | 339 | _mod_params.params.gfsk.operational_frequency = frequency; |
brunnobbco | 0:561d07a737bc | 340 | #endif |
brunnobbco | 0:561d07a737bc | 341 | |
brunnobbco | 0:561d07a737bc | 342 | uint8_t buf[4]; |
brunnobbco | 0:561d07a737bc | 343 | uint32_t freq = 0; |
brunnobbco | 0:561d07a737bc | 344 | |
brunnobbco | 0:561d07a737bc | 345 | if ( _force_image_calibration || !_image_calibrated) { |
brunnobbco | 0:561d07a737bc | 346 | calibrate_image(frequency); |
brunnobbco | 0:561d07a737bc | 347 | _image_calibrated = true; |
brunnobbco | 0:561d07a737bc | 348 | } |
brunnobbco | 0:561d07a737bc | 349 | |
brunnobbco | 0:561d07a737bc | 350 | freq = (uint32_t) ceil(((float) frequency / (float) FREQ_STEP)); |
brunnobbco | 0:561d07a737bc | 351 | buf[0] = (uint8_t) ((freq >> 24) & 0xFF); |
brunnobbco | 0:561d07a737bc | 352 | buf[1] = (uint8_t) ((freq >> 16) & 0xFF); |
brunnobbco | 0:561d07a737bc | 353 | buf[2] = (uint8_t) ((freq >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 354 | buf[3] = (uint8_t) (freq & 0xFF); |
brunnobbco | 0:561d07a737bc | 355 | |
brunnobbco | 0:561d07a737bc | 356 | write_opmode_command((uint8_t) RADIO_SET_RFFREQUENCY, buf, 4); |
brunnobbco | 0:561d07a737bc | 357 | } |
brunnobbco | 0:561d07a737bc | 358 | |
brunnobbco | 0:561d07a737bc | 359 | /** |
brunnobbco | 0:561d07a737bc | 360 | * Put radio in Standby mode |
brunnobbco | 0:561d07a737bc | 361 | */ |
brunnobbco | 0:561d07a737bc | 362 | void SX126X_LoRaRadio::standby(void) |
brunnobbco | 0:561d07a737bc | 363 | { |
brunnobbco | 0:561d07a737bc | 364 | if (_operation_mode == MODE_STDBY_RC) { |
brunnobbco | 0:561d07a737bc | 365 | return; |
brunnobbco | 0:561d07a737bc | 366 | } |
brunnobbco | 0:561d07a737bc | 367 | |
brunnobbco | 0:561d07a737bc | 368 | set_device_ready(); |
brunnobbco | 0:561d07a737bc | 369 | uint8_t standby_mode = MBED_CONF_SX126X_LORA_DRIVER_STANDBY_MODE; |
brunnobbco | 0:561d07a737bc | 370 | write_opmode_command((uint8_t) RADIO_SET_STANDBY, &standby_mode, 1); |
brunnobbco | 0:561d07a737bc | 371 | |
brunnobbco | 0:561d07a737bc | 372 | if (standby_mode == STDBY_RC) { |
brunnobbco | 0:561d07a737bc | 373 | _operation_mode = MODE_STDBY_RC; |
brunnobbco | 0:561d07a737bc | 374 | } else { |
brunnobbco | 0:561d07a737bc | 375 | _operation_mode = MODE_STDBY_XOSC; |
brunnobbco | 0:561d07a737bc | 376 | } |
brunnobbco | 0:561d07a737bc | 377 | } |
brunnobbco | 0:561d07a737bc | 378 | |
brunnobbco | 0:561d07a737bc | 379 | void SX126X_LoRaRadio::set_dio2_as_rfswitch_ctrl(uint8_t enable) |
brunnobbco | 0:561d07a737bc | 380 | { |
brunnobbco | 0:561d07a737bc | 381 | write_opmode_command(RADIO_SET_RFSWITCHMODE, &enable, 1); |
brunnobbco | 0:561d07a737bc | 382 | } |
brunnobbco | 0:561d07a737bc | 383 | |
brunnobbco | 0:561d07a737bc | 384 | void SX126X_LoRaRadio::set_dio3_as_tcxo_ctrl(radio_TCXO_ctrl_voltage_t voltage, |
brunnobbco | 0:561d07a737bc | 385 | uint32_t timeout) |
brunnobbco | 0:561d07a737bc | 386 | { |
brunnobbco | 0:561d07a737bc | 387 | uint8_t buf[4]; |
brunnobbco | 0:561d07a737bc | 388 | |
brunnobbco | 0:561d07a737bc | 389 | buf[0] = voltage & 0x07; |
brunnobbco | 0:561d07a737bc | 390 | buf[1] = (uint8_t) ((timeout >> 16) & 0xFF); |
brunnobbco | 0:561d07a737bc | 391 | buf[2] = (uint8_t) ((timeout >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 392 | buf[3] = (uint8_t) (timeout & 0xFF); |
brunnobbco | 0:561d07a737bc | 393 | |
brunnobbco | 0:561d07a737bc | 394 | write_opmode_command(RADIO_SET_TCXOMODE, buf, 4); |
brunnobbco | 0:561d07a737bc | 395 | } |
brunnobbco | 0:561d07a737bc | 396 | |
brunnobbco | 0:561d07a737bc | 397 | void SX126X_LoRaRadio::init_radio(radio_events_t *events) |
brunnobbco | 0:561d07a737bc | 398 | { |
brunnobbco | 0:561d07a737bc | 399 | _radio_events = events; |
brunnobbco | 0:561d07a737bc | 400 | |
brunnobbco | 0:561d07a737bc | 401 | // attach DIO1 interrupt line to its respective ISR |
brunnobbco | 0:561d07a737bc | 402 | _dio1_ctl.rise(callback(this, &SX126X_LoRaRadio::dio1_irq_isr)); |
brunnobbco | 0:561d07a737bc | 403 | |
brunnobbco | 0:561d07a737bc | 404 | uint8_t freq_support = get_frequency_support(); |
brunnobbco | 0:561d07a737bc | 405 | |
brunnobbco | 0:561d07a737bc | 406 | // Hold chip-select high |
brunnobbco | 0:561d07a737bc | 407 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 408 | _spi.format(8, 0); |
brunnobbco | 0:561d07a737bc | 409 | _spi.frequency(SPI_FREQUENCY); |
brunnobbco | 0:561d07a737bc | 410 | // 100 us wait to settle down |
brunnobbco | 0:561d07a737bc | 411 | wait_us(100); |
brunnobbco | 0:561d07a737bc | 412 | |
brunnobbco | 0:561d07a737bc | 413 | radio_reset(); |
brunnobbco | 0:561d07a737bc | 414 | |
brunnobbco | 0:561d07a737bc | 415 | #if MBED_CONF_LORA_PUBLIC_NETWORK |
brunnobbco | 0:561d07a737bc | 416 | _network_mode_public = true; |
brunnobbco | 0:561d07a737bc | 417 | #else |
brunnobbco | 0:561d07a737bc | 418 | _network_mode_public = false; |
brunnobbco | 0:561d07a737bc | 419 | #endif |
brunnobbco | 0:561d07a737bc | 420 | |
brunnobbco | 0:561d07a737bc | 421 | // this is a POR sequence |
brunnobbco | 0:561d07a737bc | 422 | cold_start_wakeup(); |
brunnobbco | 0:561d07a737bc | 423 | } |
brunnobbco | 0:561d07a737bc | 424 | |
brunnobbco | 0:561d07a737bc | 425 | void SX126X_LoRaRadio::cold_start_wakeup() |
brunnobbco | 0:561d07a737bc | 426 | { |
brunnobbco | 0:561d07a737bc | 427 | uint8_t regulator_mode = MBED_CONF_SX126X_LORA_DRIVER_REGULATOR_MODE; |
brunnobbco | 0:561d07a737bc | 428 | write_opmode_command(RADIO_SET_REGULATORMODE, ®ulator_mode, 1); |
brunnobbco | 0:561d07a737bc | 429 | set_buffer_base_addr(0x00, 0x00); |
brunnobbco | 0:561d07a737bc | 430 | |
brunnobbco | 0:561d07a737bc | 431 | if (_crystal_select.is_connected() && _crystal_select == 0) { |
brunnobbco | 0:561d07a737bc | 432 | caliberation_params_t calib_param; |
brunnobbco | 0:561d07a737bc | 433 | set_dio3_as_tcxo_ctrl(TCXO_CTRL_1_7V, 320); //5 ms |
brunnobbco | 0:561d07a737bc | 434 | calib_param.value = 0x7F; |
brunnobbco | 0:561d07a737bc | 435 | write_opmode_command(RADIO_CALIBRATE, &calib_param.value, 1); |
brunnobbco | 0:561d07a737bc | 436 | } |
brunnobbco | 0:561d07a737bc | 437 | |
brunnobbco | 0:561d07a737bc | 438 | set_dio2_as_rfswitch_ctrl(true); |
brunnobbco | 0:561d07a737bc | 439 | |
brunnobbco | 0:561d07a737bc | 440 | _operation_mode = MODE_STDBY_RC; |
brunnobbco | 0:561d07a737bc | 441 | |
brunnobbco | 0:561d07a737bc | 442 | set_modem(_active_modem); |
brunnobbco | 0:561d07a737bc | 443 | |
brunnobbco | 0:561d07a737bc | 444 | if (_active_modem == MODEM_LORA) { |
brunnobbco | 0:561d07a737bc | 445 | set_public_network(_network_mode_public); |
brunnobbco | 0:561d07a737bc | 446 | } |
brunnobbco | 0:561d07a737bc | 447 | } |
brunnobbco | 0:561d07a737bc | 448 | |
brunnobbco | 0:561d07a737bc | 449 | void SX126X_LoRaRadio::set_public_network(bool enable) |
brunnobbco | 0:561d07a737bc | 450 | { |
brunnobbco | 0:561d07a737bc | 451 | if (enable) { |
brunnobbco | 0:561d07a737bc | 452 | // Change LoRa modem SyncWord |
brunnobbco | 0:561d07a737bc | 453 | write_to_register(REG_LR_SYNCWORD, (LORA_MAC_PUBLIC_SYNCWORD >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 454 | write_to_register(REG_LR_SYNCWORD + 1, LORA_MAC_PUBLIC_SYNCWORD & 0xFF); |
brunnobbco | 0:561d07a737bc | 455 | } else { |
brunnobbco | 0:561d07a737bc | 456 | // Change LoRa modem SyncWord |
brunnobbco | 0:561d07a737bc | 457 | write_to_register(REG_LR_SYNCWORD, (LORA_MAC_PRIVATE_SYNCWORD >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 458 | write_to_register(REG_LR_SYNCWORD + 1, LORA_MAC_PRIVATE_SYNCWORD & 0xFF); |
brunnobbco | 0:561d07a737bc | 459 | } |
brunnobbco | 0:561d07a737bc | 460 | } |
brunnobbco | 0:561d07a737bc | 461 | |
brunnobbco | 0:561d07a737bc | 462 | uint32_t SX126X_LoRaRadio::time_on_air(radio_modems_t modem, uint8_t pkt_len) |
brunnobbco | 0:561d07a737bc | 463 | { |
brunnobbco | 0:561d07a737bc | 464 | uint32_t air_time = 0; |
brunnobbco | 0:561d07a737bc | 465 | |
brunnobbco | 0:561d07a737bc | 466 | switch (modem) { |
brunnobbco | 0:561d07a737bc | 467 | case MODEM_FSK: { |
brunnobbco | 0:561d07a737bc | 468 | air_time = rint((8 * (_packet_params.params.gfsk.preamble_length |
brunnobbco | 0:561d07a737bc | 469 | + (_packet_params.params.gfsk.syncword_length >> 3) |
brunnobbco | 0:561d07a737bc | 470 | + ((_packet_params.params.gfsk.header_type |
brunnobbco | 0:561d07a737bc | 471 | == RADIO_PACKET_FIXED_LENGTH) ? 0.0f : 1.0f) + pkt_len |
brunnobbco | 0:561d07a737bc | 472 | + ((_packet_params.params.gfsk.crc_length == RADIO_CRC_2_BYTES) ? 2.0f : 0.0f)) |
brunnobbco | 0:561d07a737bc | 473 | / _mod_params.params.gfsk.bit_rate) * 1000); |
brunnobbco | 0:561d07a737bc | 474 | } |
brunnobbco | 0:561d07a737bc | 475 | break; |
brunnobbco | 0:561d07a737bc | 476 | case MODEM_LORA: { |
brunnobbco | 0:561d07a737bc | 477 | float ts = lora_symbol_time[_mod_params.params.lora.bandwidth - 4][12 |
brunnobbco | 0:561d07a737bc | 478 | - _mod_params.params.lora.spreading_factor]; |
brunnobbco | 0:561d07a737bc | 479 | // time of preamble |
brunnobbco | 0:561d07a737bc | 480 | float t_preamble = (_packet_params.params.lora.preamble_length + 4.25f) * ts; |
brunnobbco | 0:561d07a737bc | 481 | // Symbol length of payload and time |
brunnobbco | 0:561d07a737bc | 482 | float tmp = ceil((8 * pkt_len - 4 * _mod_params.params.lora.spreading_factor |
brunnobbco | 0:561d07a737bc | 483 | + 28 + 16 * _packet_params.params.lora.crc_mode |
brunnobbco | 0:561d07a737bc | 484 | - ((_packet_params.params.lora.header_type == LORA_PACKET_FIXED_LENGTH) ? 20 : 0)) |
brunnobbco | 0:561d07a737bc | 485 | / (float) (4 * (_mod_params.params.lora.spreading_factor |
brunnobbco | 0:561d07a737bc | 486 | - ((_mod_params.params.lora.low_datarate_optimization > 0) ? 2 : 0)))) |
brunnobbco | 0:561d07a737bc | 487 | * ((_mod_params.params.lora.coding_rate % 4) + 4); |
brunnobbco | 0:561d07a737bc | 488 | float n_payload = 8 + ((tmp > 0) ? tmp : 0); |
brunnobbco | 0:561d07a737bc | 489 | float t_payload = n_payload * ts; |
brunnobbco | 0:561d07a737bc | 490 | // Time on air |
brunnobbco | 0:561d07a737bc | 491 | float tOnAir = t_preamble + t_payload; |
brunnobbco | 0:561d07a737bc | 492 | // return milliseconds (as ts is in milliseconds) |
brunnobbco | 0:561d07a737bc | 493 | air_time = floor(tOnAir + 0.999); |
brunnobbco | 0:561d07a737bc | 494 | } |
brunnobbco | 0:561d07a737bc | 495 | break; |
brunnobbco | 0:561d07a737bc | 496 | } |
brunnobbco | 0:561d07a737bc | 497 | |
brunnobbco | 0:561d07a737bc | 498 | return air_time; |
brunnobbco | 0:561d07a737bc | 499 | } |
brunnobbco | 0:561d07a737bc | 500 | |
brunnobbco | 0:561d07a737bc | 501 | void SX126X_LoRaRadio::radio_reset() |
brunnobbco | 0:561d07a737bc | 502 | { |
brunnobbco | 0:561d07a737bc | 503 | _reset_ctl.output(); |
brunnobbco | 0:561d07a737bc | 504 | _reset_ctl = 0; |
brunnobbco | 0:561d07a737bc | 505 | // should be enough, required is 50-100 us |
brunnobbco | 0:561d07a737bc | 506 | wait_ms(2); |
brunnobbco | 0:561d07a737bc | 507 | _reset_ctl.input(); |
brunnobbco | 0:561d07a737bc | 508 | // give some time for automatic image calibration |
brunnobbco | 0:561d07a737bc | 509 | wait_ms(6); |
brunnobbco | 0:561d07a737bc | 510 | } |
brunnobbco | 0:561d07a737bc | 511 | |
brunnobbco | 0:561d07a737bc | 512 | void SX126X_LoRaRadio::wakeup() |
brunnobbco | 0:561d07a737bc | 513 | { |
brunnobbco | 0:561d07a737bc | 514 | // hold the NSS low, this should wakeup the chip. |
brunnobbco | 0:561d07a737bc | 515 | // now we should wait for the _busy line to go low |
brunnobbco | 0:561d07a737bc | 516 | if (_operation_mode == MODE_SLEEP) { |
brunnobbco | 0:561d07a737bc | 517 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 518 | wait_us(100); |
brunnobbco | 0:561d07a737bc | 519 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 520 | //wait_us(100); |
brunnobbco | 0:561d07a737bc | 521 | #if MBED_CONF_SX126X_LORA_DRIVER_SLEEP_MODE == 1 |
brunnobbco | 0:561d07a737bc | 522 | wait_us(3500); |
brunnobbco | 0:561d07a737bc | 523 | // whenever we wakeup from Cold sleep state, we need to perform |
brunnobbco | 0:561d07a737bc | 524 | // image calibration |
brunnobbco | 0:561d07a737bc | 525 | _force_image_calibration = true; |
brunnobbco | 0:561d07a737bc | 526 | cold_start_wakeup(); |
brunnobbco | 0:561d07a737bc | 527 | #endif |
brunnobbco | 0:561d07a737bc | 528 | } |
brunnobbco | 0:561d07a737bc | 529 | } |
brunnobbco | 0:561d07a737bc | 530 | |
brunnobbco | 0:561d07a737bc | 531 | void SX126X_LoRaRadio::sleep(void) |
brunnobbco | 0:561d07a737bc | 532 | { |
brunnobbco | 0:561d07a737bc | 533 | // warm start, power consumption 600 nA |
brunnobbco | 0:561d07a737bc | 534 | uint8_t sleep_state = 0x04; |
brunnobbco | 0:561d07a737bc | 535 | _operation_mode = MODE_SLEEP; |
brunnobbco | 0:561d07a737bc | 536 | |
brunnobbco | 0:561d07a737bc | 537 | #if MBED_CONF_SX126X_LORA_DRIVER_SLEEP_MODE == 1 |
brunnobbco | 0:561d07a737bc | 538 | // cold start, power consumption 160 nA |
brunnobbco | 0:561d07a737bc | 539 | sleep_state = 0x00; |
brunnobbco | 0:561d07a737bc | 540 | #endif |
brunnobbco | 0:561d07a737bc | 541 | |
brunnobbco | 0:561d07a737bc | 542 | write_opmode_command(RADIO_SET_SLEEP, &sleep_state, 1); |
brunnobbco | 0:561d07a737bc | 543 | wait_ms(2); |
brunnobbco | 0:561d07a737bc | 544 | } |
brunnobbco | 0:561d07a737bc | 545 | |
brunnobbco | 0:561d07a737bc | 546 | uint32_t SX126X_LoRaRadio::random(void) |
brunnobbco | 0:561d07a737bc | 547 | { |
brunnobbco | 0:561d07a737bc | 548 | set_modem(MODEM_LORA); |
brunnobbco | 0:561d07a737bc | 549 | uint8_t buf[] = {0, 0, 0, 0}; |
brunnobbco | 0:561d07a737bc | 550 | |
brunnobbco | 0:561d07a737bc | 551 | // Set radio in continuous reception |
brunnobbco | 0:561d07a737bc | 552 | _reception_mode = RECEPTION_MODE_OTHER; |
brunnobbco | 0:561d07a737bc | 553 | _rx_timeout = 0xFFFFFFFF; |
brunnobbco | 0:561d07a737bc | 554 | receive(); |
brunnobbco | 0:561d07a737bc | 555 | wait_ms(1); |
brunnobbco | 0:561d07a737bc | 556 | read_register(RANDOM_NUMBER_GENERATORBASEADDR, buf, 4); |
brunnobbco | 0:561d07a737bc | 557 | standby(); |
brunnobbco | 0:561d07a737bc | 558 | |
brunnobbco | 0:561d07a737bc | 559 | return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; |
brunnobbco | 0:561d07a737bc | 560 | } |
brunnobbco | 0:561d07a737bc | 561 | |
brunnobbco | 0:561d07a737bc | 562 | void SX126X_LoRaRadio::write_opmode_command(uint8_t cmd, uint8_t *buffer, uint16_t size) |
brunnobbco | 0:561d07a737bc | 563 | { |
brunnobbco | 0:561d07a737bc | 564 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 565 | |
brunnobbco | 0:561d07a737bc | 566 | while (_busy) { |
brunnobbco | 0:561d07a737bc | 567 | // do nothing |
brunnobbco | 0:561d07a737bc | 568 | } |
brunnobbco | 0:561d07a737bc | 569 | |
brunnobbco | 0:561d07a737bc | 570 | _spi.write(cmd); |
brunnobbco | 0:561d07a737bc | 571 | |
brunnobbco | 0:561d07a737bc | 572 | for (int i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 573 | _spi.write(buffer[i]); |
brunnobbco | 0:561d07a737bc | 574 | } |
brunnobbco | 0:561d07a737bc | 575 | |
brunnobbco | 0:561d07a737bc | 576 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 577 | } |
brunnobbco | 0:561d07a737bc | 578 | |
brunnobbco | 0:561d07a737bc | 579 | void SX126X_LoRaRadio::read_opmode_command(uint8_t cmd, |
brunnobbco | 0:561d07a737bc | 580 | uint8_t *buffer, uint16_t size) |
brunnobbco | 0:561d07a737bc | 581 | { |
brunnobbco | 0:561d07a737bc | 582 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 583 | |
brunnobbco | 0:561d07a737bc | 584 | while (_busy) { |
brunnobbco | 0:561d07a737bc | 585 | // do nothing |
brunnobbco | 0:561d07a737bc | 586 | } |
brunnobbco | 0:561d07a737bc | 587 | |
brunnobbco | 0:561d07a737bc | 588 | _spi.write(cmd); |
brunnobbco | 0:561d07a737bc | 589 | _spi.write(0); |
brunnobbco | 0:561d07a737bc | 590 | |
brunnobbco | 0:561d07a737bc | 591 | for (int i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 592 | buffer[i] = _spi.write(0); |
brunnobbco | 0:561d07a737bc | 593 | } |
brunnobbco | 0:561d07a737bc | 594 | |
brunnobbco | 0:561d07a737bc | 595 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 596 | } |
brunnobbco | 0:561d07a737bc | 597 | |
brunnobbco | 0:561d07a737bc | 598 | void SX126X_LoRaRadio::write_to_register(uint16_t addr, uint8_t data) |
brunnobbco | 0:561d07a737bc | 599 | { |
brunnobbco | 0:561d07a737bc | 600 | write_to_register(addr, &data, 1); |
brunnobbco | 0:561d07a737bc | 601 | } |
brunnobbco | 0:561d07a737bc | 602 | |
brunnobbco | 0:561d07a737bc | 603 | void SX126X_LoRaRadio::write_to_register(uint16_t addr, uint8_t *data, |
brunnobbco | 0:561d07a737bc | 604 | uint8_t size) |
brunnobbco | 0:561d07a737bc | 605 | { |
brunnobbco | 0:561d07a737bc | 606 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 607 | |
brunnobbco | 0:561d07a737bc | 608 | _spi.write(RADIO_WRITE_REGISTER); |
brunnobbco | 0:561d07a737bc | 609 | _spi.write((addr & 0xFF00) >> 8); |
brunnobbco | 0:561d07a737bc | 610 | _spi.write(addr & 0x00FF); |
brunnobbco | 0:561d07a737bc | 611 | |
brunnobbco | 0:561d07a737bc | 612 | for (int i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 613 | _spi.write(data[i]); |
brunnobbco | 0:561d07a737bc | 614 | } |
brunnobbco | 0:561d07a737bc | 615 | |
brunnobbco | 0:561d07a737bc | 616 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 617 | } |
brunnobbco | 0:561d07a737bc | 618 | |
brunnobbco | 0:561d07a737bc | 619 | uint8_t SX126X_LoRaRadio::read_register(uint16_t addr) |
brunnobbco | 0:561d07a737bc | 620 | { |
brunnobbco | 0:561d07a737bc | 621 | uint8_t data; |
brunnobbco | 0:561d07a737bc | 622 | read_register(addr, &data, 1); |
brunnobbco | 0:561d07a737bc | 623 | return data; |
brunnobbco | 0:561d07a737bc | 624 | |
brunnobbco | 0:561d07a737bc | 625 | } |
brunnobbco | 0:561d07a737bc | 626 | |
brunnobbco | 0:561d07a737bc | 627 | void SX126X_LoRaRadio::read_register(uint16_t addr, uint8_t *buffer, |
brunnobbco | 0:561d07a737bc | 628 | uint8_t size) |
brunnobbco | 0:561d07a737bc | 629 | { |
brunnobbco | 0:561d07a737bc | 630 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 631 | |
brunnobbco | 0:561d07a737bc | 632 | _spi.write(RADIO_READ_REGISTER); |
brunnobbco | 0:561d07a737bc | 633 | _spi.write((addr & 0xFF00) >> 8); |
brunnobbco | 0:561d07a737bc | 634 | _spi.write(addr & 0x00FF); |
brunnobbco | 0:561d07a737bc | 635 | _spi.write(0); |
brunnobbco | 0:561d07a737bc | 636 | |
brunnobbco | 0:561d07a737bc | 637 | for (int i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 638 | buffer[i] = _spi.write(0); |
brunnobbco | 0:561d07a737bc | 639 | } |
brunnobbco | 0:561d07a737bc | 640 | |
brunnobbco | 0:561d07a737bc | 641 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 642 | } |
brunnobbco | 0:561d07a737bc | 643 | |
brunnobbco | 0:561d07a737bc | 644 | void SX126X_LoRaRadio::write_fifo(uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 645 | { |
brunnobbco | 0:561d07a737bc | 646 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 647 | |
brunnobbco | 0:561d07a737bc | 648 | _spi.write(RADIO_WRITE_BUFFER); |
brunnobbco | 0:561d07a737bc | 649 | _spi.write(0); |
brunnobbco | 0:561d07a737bc | 650 | |
brunnobbco | 0:561d07a737bc | 651 | for (int i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 652 | _spi.write(buffer[i]); |
brunnobbco | 0:561d07a737bc | 653 | } |
brunnobbco | 0:561d07a737bc | 654 | |
brunnobbco | 0:561d07a737bc | 655 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 656 | } |
brunnobbco | 0:561d07a737bc | 657 | |
brunnobbco | 0:561d07a737bc | 658 | void SX126X_LoRaRadio::set_modem(uint8_t modem) |
brunnobbco | 0:561d07a737bc | 659 | { |
brunnobbco | 0:561d07a737bc | 660 | _active_modem = modem; |
brunnobbco | 0:561d07a737bc | 661 | |
brunnobbco | 0:561d07a737bc | 662 | // setting modem type must happen in stnadby mode |
brunnobbco | 0:561d07a737bc | 663 | if (_operation_mode != MODE_STDBY_RC) { |
brunnobbco | 0:561d07a737bc | 664 | standby(); |
brunnobbco | 0:561d07a737bc | 665 | } |
brunnobbco | 0:561d07a737bc | 666 | |
brunnobbco | 0:561d07a737bc | 667 | write_opmode_command(RADIO_SET_PACKETTYPE, &_active_modem, 1); |
brunnobbco | 0:561d07a737bc | 668 | } |
brunnobbco | 0:561d07a737bc | 669 | |
brunnobbco | 0:561d07a737bc | 670 | uint8_t SX126X_LoRaRadio::get_modem() |
brunnobbco | 0:561d07a737bc | 671 | { |
brunnobbco | 0:561d07a737bc | 672 | return _active_modem; |
brunnobbco | 0:561d07a737bc | 673 | } |
brunnobbco | 0:561d07a737bc | 674 | |
brunnobbco | 0:561d07a737bc | 675 | void SX126X_LoRaRadio::read_fifo(uint8_t *buffer, uint8_t size, uint8_t offset) |
brunnobbco | 0:561d07a737bc | 676 | { |
brunnobbco | 0:561d07a737bc | 677 | _chip_select = 0; |
brunnobbco | 0:561d07a737bc | 678 | |
brunnobbco | 0:561d07a737bc | 679 | _spi.write(RADIO_READ_BUFFER); |
brunnobbco | 0:561d07a737bc | 680 | _spi.write(offset); |
brunnobbco | 0:561d07a737bc | 681 | _spi.write(0); |
brunnobbco | 0:561d07a737bc | 682 | |
brunnobbco | 0:561d07a737bc | 683 | for (int i = 0; i < size; i++) { |
brunnobbco | 0:561d07a737bc | 684 | buffer[i] = _spi.write(0); |
brunnobbco | 0:561d07a737bc | 685 | } |
brunnobbco | 0:561d07a737bc | 686 | |
brunnobbco | 0:561d07a737bc | 687 | _chip_select = 1; |
brunnobbco | 0:561d07a737bc | 688 | } |
brunnobbco | 0:561d07a737bc | 689 | |
brunnobbco | 0:561d07a737bc | 690 | uint8_t SX126X_LoRaRadio::get_device_variant(void) |
brunnobbco | 0:561d07a737bc | 691 | { |
brunnobbco | 0:561d07a737bc | 692 | uint16_t val = 0; |
brunnobbco | 0:561d07a737bc | 693 | val = _dev_select.read_u16(); |
brunnobbco | 0:561d07a737bc | 694 | |
brunnobbco | 0:561d07a737bc | 695 | if (val <= 0x2000) { |
brunnobbco | 0:561d07a737bc | 696 | return SX1262; |
brunnobbco | 0:561d07a737bc | 697 | } else if (val <= 0xA000) { |
brunnobbco | 0:561d07a737bc | 698 | return SX1268; |
brunnobbco | 0:561d07a737bc | 699 | } else { |
brunnobbco | 0:561d07a737bc | 700 | return SX1261; |
brunnobbco | 0:561d07a737bc | 701 | } |
brunnobbco | 0:561d07a737bc | 702 | } |
brunnobbco | 0:561d07a737bc | 703 | |
brunnobbco | 0:561d07a737bc | 704 | uint8_t SX126X_LoRaRadio::get_frequency_support(void) |
brunnobbco | 0:561d07a737bc | 705 | { |
brunnobbco | 0:561d07a737bc | 706 | uint16_t val = 0; |
brunnobbco | 0:561d07a737bc | 707 | val = _freq_select.read_u16(); |
brunnobbco | 0:561d07a737bc | 708 | |
brunnobbco | 0:561d07a737bc | 709 | if (val < 100) { |
brunnobbco | 0:561d07a737bc | 710 | return ( MATCHING_FREQ_915); |
brunnobbco | 0:561d07a737bc | 711 | } else if (val <= 0x3000) { |
brunnobbco | 0:561d07a737bc | 712 | return ( MATCHING_FREQ_780); |
brunnobbco | 0:561d07a737bc | 713 | } else if (val <= 0x4900) { // 0x4724 |
brunnobbco | 0:561d07a737bc | 714 | return ( MATCHING_FREQ_490); |
brunnobbco | 0:561d07a737bc | 715 | } else if (val <= 1) { |
brunnobbco | 0:561d07a737bc | 716 | return ( MATCHING_FREQ_434); |
brunnobbco | 0:561d07a737bc | 717 | } else if (val <= 1) { |
brunnobbco | 0:561d07a737bc | 718 | return ( MATCHING_FREQ_280); |
brunnobbco | 0:561d07a737bc | 719 | } else if (val <= 0xF000) { |
brunnobbco | 0:561d07a737bc | 720 | return ( MATCHING_FREQ_169); |
brunnobbco | 0:561d07a737bc | 721 | } else { |
brunnobbco | 0:561d07a737bc | 722 | return ( MATCHING_FREQ_868); |
brunnobbco | 0:561d07a737bc | 723 | } |
brunnobbco | 0:561d07a737bc | 724 | } |
brunnobbco | 0:561d07a737bc | 725 | |
brunnobbco | 0:561d07a737bc | 726 | uint8_t SX126X_LoRaRadio::get_fsk_bw_reg_val(uint32_t bandwidth) |
brunnobbco | 0:561d07a737bc | 727 | { |
brunnobbco | 0:561d07a737bc | 728 | uint8_t i; |
brunnobbco | 0:561d07a737bc | 729 | |
brunnobbco | 0:561d07a737bc | 730 | for (i = 0; i < (sizeof(fsk_bandwidths) / sizeof(fsk_bw_t)) - 1; i++) { |
brunnobbco | 0:561d07a737bc | 731 | if ((bandwidth >= fsk_bandwidths[i].bandwidth) |
brunnobbco | 0:561d07a737bc | 732 | && (bandwidth < fsk_bandwidths[i + 1].bandwidth)) { |
brunnobbco | 0:561d07a737bc | 733 | return fsk_bandwidths[i].register_value; |
brunnobbco | 0:561d07a737bc | 734 | } |
brunnobbco | 0:561d07a737bc | 735 | } |
brunnobbco | 0:561d07a737bc | 736 | // ERROR: Value not found |
brunnobbco | 0:561d07a737bc | 737 | // This should never happen |
brunnobbco | 0:561d07a737bc | 738 | while (1); |
brunnobbco | 0:561d07a737bc | 739 | } |
brunnobbco | 0:561d07a737bc | 740 | |
brunnobbco | 0:561d07a737bc | 741 | void SX126X_LoRaRadio::set_max_payload_length(radio_modems_t modem, uint8_t max) |
brunnobbco | 0:561d07a737bc | 742 | { |
brunnobbco | 0:561d07a737bc | 743 | if (modem == MODEM_LORA) { |
brunnobbco | 0:561d07a737bc | 744 | _packet_params.params.lora.payload_length = max; |
brunnobbco | 0:561d07a737bc | 745 | } else { |
brunnobbco | 0:561d07a737bc | 746 | _packet_params.params.gfsk.payload_length = max; |
brunnobbco | 0:561d07a737bc | 747 | } |
brunnobbco | 0:561d07a737bc | 748 | } |
brunnobbco | 0:561d07a737bc | 749 | |
brunnobbco | 0:561d07a737bc | 750 | void SX126X_LoRaRadio::set_tx_config(radio_modems_t modem, |
brunnobbco | 0:561d07a737bc | 751 | int8_t power, |
brunnobbco | 0:561d07a737bc | 752 | uint32_t fdev, |
brunnobbco | 0:561d07a737bc | 753 | uint32_t bandwidth, |
brunnobbco | 0:561d07a737bc | 754 | uint32_t datarate, |
brunnobbco | 0:561d07a737bc | 755 | uint8_t coderate, |
brunnobbco | 0:561d07a737bc | 756 | uint16_t preamble_len, |
brunnobbco | 0:561d07a737bc | 757 | bool fix_len, |
brunnobbco | 0:561d07a737bc | 758 | bool crc_on, |
brunnobbco | 0:561d07a737bc | 759 | bool freq_hop_on, |
brunnobbco | 0:561d07a737bc | 760 | uint8_t hop_period, |
brunnobbco | 0:561d07a737bc | 761 | bool iq_inverted, |
brunnobbco | 0:561d07a737bc | 762 | uint32_t timeout) |
brunnobbco | 0:561d07a737bc | 763 | { |
brunnobbco | 0:561d07a737bc | 764 | |
brunnobbco | 0:561d07a737bc | 765 | uint8_t modem_type = (uint8_t) modem; |
brunnobbco | 0:561d07a737bc | 766 | switch (modem_type) { |
brunnobbco | 0:561d07a737bc | 767 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 768 | _mod_params.modem_type = MODEM_FSK; |
brunnobbco | 0:561d07a737bc | 769 | _mod_params.params.gfsk.bit_rate = datarate; |
brunnobbco | 0:561d07a737bc | 770 | |
brunnobbco | 0:561d07a737bc | 771 | _mod_params.params.gfsk.modulation_shaping = MOD_SHAPING_G_BT_1; |
brunnobbco | 0:561d07a737bc | 772 | _mod_params.params.gfsk.bandwidth = get_fsk_bw_reg_val(bandwidth); |
brunnobbco | 0:561d07a737bc | 773 | _mod_params.params.gfsk.fdev = fdev; |
brunnobbco | 0:561d07a737bc | 774 | |
brunnobbco | 0:561d07a737bc | 775 | _packet_params.modem_type = MODEM_FSK; |
brunnobbco | 0:561d07a737bc | 776 | _packet_params.params.gfsk.preamble_length = (preamble_len << 3); // convert byte into bit |
brunnobbco | 0:561d07a737bc | 777 | _packet_params.params.gfsk.preamble_min_detect = RADIO_PREAMBLE_DETECTOR_08_BITS; |
brunnobbco | 0:561d07a737bc | 778 | _packet_params.params.gfsk.syncword_length = 3 << 3; // convert byte into bit |
brunnobbco | 0:561d07a737bc | 779 | _packet_params.params.gfsk.addr_comp = RADIO_ADDRESSCOMP_FILT_OFF; |
brunnobbco | 0:561d07a737bc | 780 | _packet_params.params.gfsk.header_type = (fix_len == true) ? |
brunnobbco | 0:561d07a737bc | 781 | RADIO_PACKET_FIXED_LENGTH : |
brunnobbco | 0:561d07a737bc | 782 | RADIO_PACKET_VARIABLE_LENGTH; |
brunnobbco | 0:561d07a737bc | 783 | |
brunnobbco | 0:561d07a737bc | 784 | if (crc_on) { |
brunnobbco | 0:561d07a737bc | 785 | _packet_params.params.gfsk.crc_length = RADIO_CRC_2_BYTES_CCIT; |
brunnobbco | 0:561d07a737bc | 786 | } else { |
brunnobbco | 0:561d07a737bc | 787 | _packet_params.params.gfsk.crc_length = RADIO_CRC_OFF; |
brunnobbco | 0:561d07a737bc | 788 | } |
brunnobbco | 0:561d07a737bc | 789 | _packet_params.params.gfsk.whitening_mode = RADIO_DC_FREEWHITENING; |
brunnobbco | 0:561d07a737bc | 790 | |
brunnobbco | 0:561d07a737bc | 791 | set_modem(MODEM_FSK); |
brunnobbco | 0:561d07a737bc | 792 | |
brunnobbco | 0:561d07a737bc | 793 | write_to_register(REG_LR_SYNCWORDBASEADDRESS, (uint8_t *) sync_word, 8); |
brunnobbco | 0:561d07a737bc | 794 | set_whitening_seed(0x01FF); |
brunnobbco | 0:561d07a737bc | 795 | break; |
brunnobbco | 0:561d07a737bc | 796 | |
brunnobbco | 0:561d07a737bc | 797 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 798 | _mod_params.modem_type = MODEM_LORA; |
brunnobbco | 0:561d07a737bc | 799 | _mod_params.params.lora.spreading_factor = (lora_spread_factors_t) datarate; |
brunnobbco | 0:561d07a737bc | 800 | _mod_params.params.lora.bandwidth = (lora_bandwidths_t) lora_bandwidhts[bandwidth]; |
brunnobbco | 0:561d07a737bc | 801 | _mod_params.params.lora.coding_rate = (lora_coding_tates_t) coderate; |
brunnobbco | 0:561d07a737bc | 802 | |
brunnobbco | 0:561d07a737bc | 803 | if (((bandwidth == 0) && ((datarate == 11) || (datarate == 12))) |
brunnobbco | 0:561d07a737bc | 804 | || ((bandwidth == 1) && (datarate == 12))) { |
brunnobbco | 0:561d07a737bc | 805 | _mod_params.params.lora.low_datarate_optimization = 0x01; |
brunnobbco | 0:561d07a737bc | 806 | } else { |
brunnobbco | 0:561d07a737bc | 807 | _mod_params.params.lora.low_datarate_optimization = 0x00; |
brunnobbco | 0:561d07a737bc | 808 | } |
brunnobbco | 0:561d07a737bc | 809 | |
brunnobbco | 0:561d07a737bc | 810 | _packet_params.modem_type = MODEM_LORA; |
brunnobbco | 0:561d07a737bc | 811 | |
brunnobbco | 0:561d07a737bc | 812 | if ((_mod_params.params.lora.spreading_factor == LORA_SF5) |
brunnobbco | 0:561d07a737bc | 813 | || (_mod_params.params.lora.spreading_factor == LORA_SF6)) { |
brunnobbco | 0:561d07a737bc | 814 | if (preamble_len < 12) { |
brunnobbco | 0:561d07a737bc | 815 | _packet_params.params.lora.preamble_length = 12; |
brunnobbco | 0:561d07a737bc | 816 | } else { |
brunnobbco | 0:561d07a737bc | 817 | _packet_params.params.lora.preamble_length = preamble_len; |
brunnobbco | 0:561d07a737bc | 818 | } |
brunnobbco | 0:561d07a737bc | 819 | } else { |
brunnobbco | 0:561d07a737bc | 820 | _packet_params.params.lora.preamble_length = preamble_len; |
brunnobbco | 0:561d07a737bc | 821 | } |
brunnobbco | 0:561d07a737bc | 822 | |
brunnobbco | 0:561d07a737bc | 823 | _packet_params.params.lora.header_type = (lora_pkt_length_t) fix_len; |
brunnobbco | 0:561d07a737bc | 824 | _packet_params.params.lora.crc_mode = (lora_crc_mode_t) crc_on; |
brunnobbco | 0:561d07a737bc | 825 | _packet_params.params.lora.invert_IQ = (lora_IQ_mode_t) iq_inverted; |
brunnobbco | 0:561d07a737bc | 826 | |
brunnobbco | 0:561d07a737bc | 827 | set_modem(MODEM_LORA); |
brunnobbco | 0:561d07a737bc | 828 | |
brunnobbco | 0:561d07a737bc | 829 | break; |
brunnobbco | 0:561d07a737bc | 830 | } |
brunnobbco | 0:561d07a737bc | 831 | |
brunnobbco | 0:561d07a737bc | 832 | _tx_power = power; |
brunnobbco | 0:561d07a737bc | 833 | _tx_timeout = timeout; |
brunnobbco | 0:561d07a737bc | 834 | } |
brunnobbco | 0:561d07a737bc | 835 | |
brunnobbco | 0:561d07a737bc | 836 | void SX126X_LoRaRadio::set_rx_config(radio_modems_t modem, |
brunnobbco | 0:561d07a737bc | 837 | uint32_t bandwidth, |
brunnobbco | 0:561d07a737bc | 838 | uint32_t datarate, |
brunnobbco | 0:561d07a737bc | 839 | uint8_t coderate, |
brunnobbco | 0:561d07a737bc | 840 | uint32_t bandwidthAfc, |
brunnobbco | 0:561d07a737bc | 841 | uint16_t preamble_len, |
brunnobbco | 0:561d07a737bc | 842 | uint16_t symb_timeout, |
brunnobbco | 0:561d07a737bc | 843 | bool fix_len, |
brunnobbco | 0:561d07a737bc | 844 | uint8_t payload_len, |
brunnobbco | 0:561d07a737bc | 845 | bool crc_on, |
brunnobbco | 0:561d07a737bc | 846 | bool freq_hop_on, |
brunnobbco | 0:561d07a737bc | 847 | uint8_t hop_period, |
brunnobbco | 0:561d07a737bc | 848 | bool iq_inverted, |
brunnobbco | 0:561d07a737bc | 849 | bool rx_continuous) |
brunnobbco | 0:561d07a737bc | 850 | { |
brunnobbco | 0:561d07a737bc | 851 | uint8_t max_payload_len; |
brunnobbco | 0:561d07a737bc | 852 | (void) freq_hop_on; |
brunnobbco | 0:561d07a737bc | 853 | (void) hop_period; |
brunnobbco | 0:561d07a737bc | 854 | |
brunnobbco | 0:561d07a737bc | 855 | if (rx_continuous) { |
brunnobbco | 0:561d07a737bc | 856 | _reception_mode = RECEPTION_MODE_CONTINUOUS; |
brunnobbco | 0:561d07a737bc | 857 | } else { |
brunnobbco | 0:561d07a737bc | 858 | _reception_mode = RECEPTION_MODE_SINGLE; |
brunnobbco | 0:561d07a737bc | 859 | } |
brunnobbco | 0:561d07a737bc | 860 | |
brunnobbco | 0:561d07a737bc | 861 | if (fix_len == true) { |
brunnobbco | 0:561d07a737bc | 862 | max_payload_len = payload_len; |
brunnobbco | 0:561d07a737bc | 863 | } else { |
brunnobbco | 0:561d07a737bc | 864 | max_payload_len = 0xFF; |
brunnobbco | 0:561d07a737bc | 865 | } |
brunnobbco | 0:561d07a737bc | 866 | |
brunnobbco | 0:561d07a737bc | 867 | uint8_t modem_type = (uint8_t) modem; |
brunnobbco | 0:561d07a737bc | 868 | |
brunnobbco | 0:561d07a737bc | 869 | switch (modem_type) { |
brunnobbco | 0:561d07a737bc | 870 | case MODEM_FSK: { |
brunnobbco | 0:561d07a737bc | 871 | _mod_params.modem_type = MODEM_FSK; |
brunnobbco | 0:561d07a737bc | 872 | _mod_params.params.gfsk.bit_rate = datarate; |
brunnobbco | 0:561d07a737bc | 873 | _mod_params.params.gfsk.modulation_shaping = MOD_SHAPING_G_BT_1; |
brunnobbco | 0:561d07a737bc | 874 | _mod_params.params.gfsk.bandwidth = get_fsk_bw_reg_val(bandwidth); |
brunnobbco | 0:561d07a737bc | 875 | |
brunnobbco | 0:561d07a737bc | 876 | _packet_params.modem_type = MODEM_FSK; |
brunnobbco | 0:561d07a737bc | 877 | _packet_params.params.gfsk.preamble_length = (preamble_len << 3); // convert byte into bit |
brunnobbco | 0:561d07a737bc | 878 | _packet_params.params.gfsk.preamble_min_detect = |
brunnobbco | 0:561d07a737bc | 879 | RADIO_PREAMBLE_DETECTOR_08_BITS; |
brunnobbco | 0:561d07a737bc | 880 | _packet_params.params.gfsk.syncword_length = 3 << 3; // convert byte into bit |
brunnobbco | 0:561d07a737bc | 881 | _packet_params.params.gfsk.addr_comp = RADIO_ADDRESSCOMP_FILT_OFF; |
brunnobbco | 0:561d07a737bc | 882 | _packet_params.params.gfsk.header_type = |
brunnobbco | 0:561d07a737bc | 883 | (fix_len == true) ? |
brunnobbco | 0:561d07a737bc | 884 | RADIO_PACKET_FIXED_LENGTH : |
brunnobbco | 0:561d07a737bc | 885 | RADIO_PACKET_VARIABLE_LENGTH; |
brunnobbco | 0:561d07a737bc | 886 | _packet_params.params.gfsk.payload_length = max_payload_len; |
brunnobbco | 0:561d07a737bc | 887 | |
brunnobbco | 0:561d07a737bc | 888 | if (crc_on) { |
brunnobbco | 0:561d07a737bc | 889 | _packet_params.params.gfsk.crc_length = RADIO_CRC_2_BYTES_CCIT; |
brunnobbco | 0:561d07a737bc | 890 | } else { |
brunnobbco | 0:561d07a737bc | 891 | _packet_params.params.gfsk.crc_length = RADIO_CRC_OFF; |
brunnobbco | 0:561d07a737bc | 892 | } |
brunnobbco | 0:561d07a737bc | 893 | |
brunnobbco | 0:561d07a737bc | 894 | _packet_params.params.gfsk.whitening_mode = RADIO_DC_FREEWHITENING; |
brunnobbco | 0:561d07a737bc | 895 | |
brunnobbco | 0:561d07a737bc | 896 | set_modem(MODEM_FSK); |
brunnobbco | 0:561d07a737bc | 897 | |
brunnobbco | 0:561d07a737bc | 898 | write_to_register(REG_LR_SYNCWORDBASEADDRESS, (uint8_t *) sync_word, 8); |
brunnobbco | 0:561d07a737bc | 899 | set_whitening_seed(0x01FF); |
brunnobbco | 0:561d07a737bc | 900 | |
brunnobbco | 0:561d07a737bc | 901 | _rx_timeout = (uint32_t) (symb_timeout |
brunnobbco | 0:561d07a737bc | 902 | * ((1.0 / (float) datarate) * 8.0) * 1000); |
brunnobbco | 0:561d07a737bc | 903 | |
brunnobbco | 0:561d07a737bc | 904 | break; |
brunnobbco | 0:561d07a737bc | 905 | } |
brunnobbco | 0:561d07a737bc | 906 | |
brunnobbco | 0:561d07a737bc | 907 | case MODEM_LORA: { |
brunnobbco | 0:561d07a737bc | 908 | _rx_timeout_in_symbols = symb_timeout; |
brunnobbco | 0:561d07a737bc | 909 | _mod_params.modem_type = MODEM_LORA; |
brunnobbco | 0:561d07a737bc | 910 | _mod_params.params.lora.spreading_factor = |
brunnobbco | 0:561d07a737bc | 911 | (lora_spread_factors_t) datarate; |
brunnobbco | 0:561d07a737bc | 912 | _mod_params.params.lora.bandwidth = (lora_bandwidths_t) lora_bandwidhts[bandwidth]; |
brunnobbco | 0:561d07a737bc | 913 | _mod_params.params.lora.coding_rate = |
brunnobbco | 0:561d07a737bc | 914 | (lora_coding_tates_t) coderate; |
brunnobbco | 0:561d07a737bc | 915 | |
brunnobbco | 0:561d07a737bc | 916 | if (((bandwidth == 0) && ((datarate == 11) || (datarate == 12))) |
brunnobbco | 0:561d07a737bc | 917 | || ((bandwidth == 1) && (datarate == 12))) { |
brunnobbco | 0:561d07a737bc | 918 | _mod_params.params.lora.low_datarate_optimization = 0x01; |
brunnobbco | 0:561d07a737bc | 919 | } else { |
brunnobbco | 0:561d07a737bc | 920 | _mod_params.params.lora.low_datarate_optimization = 0x00; |
brunnobbco | 0:561d07a737bc | 921 | } |
brunnobbco | 0:561d07a737bc | 922 | |
brunnobbco | 0:561d07a737bc | 923 | _packet_params.modem_type = MODEM_LORA; |
brunnobbco | 0:561d07a737bc | 924 | |
brunnobbco | 0:561d07a737bc | 925 | if ((_mod_params.params.lora.spreading_factor == LORA_SF5) |
brunnobbco | 0:561d07a737bc | 926 | || (_mod_params.params.lora.spreading_factor == LORA_SF6)) { |
brunnobbco | 0:561d07a737bc | 927 | if (preamble_len < 12) { |
brunnobbco | 0:561d07a737bc | 928 | _packet_params.params.lora.preamble_length = 12; |
brunnobbco | 0:561d07a737bc | 929 | } else { |
brunnobbco | 0:561d07a737bc | 930 | _packet_params.params.lora.preamble_length = preamble_len; |
brunnobbco | 0:561d07a737bc | 931 | } |
brunnobbco | 0:561d07a737bc | 932 | } else { |
brunnobbco | 0:561d07a737bc | 933 | _packet_params.params.lora.preamble_length = preamble_len; |
brunnobbco | 0:561d07a737bc | 934 | } |
brunnobbco | 0:561d07a737bc | 935 | |
brunnobbco | 0:561d07a737bc | 936 | _packet_params.params.lora.header_type = (lora_pkt_length_t) fix_len; |
brunnobbco | 0:561d07a737bc | 937 | _packet_params.params.lora.payload_length = max_payload_len; |
brunnobbco | 0:561d07a737bc | 938 | _packet_params.params.lora.crc_mode = (lora_crc_mode_t) crc_on; |
brunnobbco | 0:561d07a737bc | 939 | _packet_params.params.lora.invert_IQ = (lora_IQ_mode_t) iq_inverted; |
brunnobbco | 0:561d07a737bc | 940 | |
brunnobbco | 0:561d07a737bc | 941 | set_modem(MODEM_LORA); |
brunnobbco | 0:561d07a737bc | 942 | |
brunnobbco | 0:561d07a737bc | 943 | if (_reception_mode == RECEPTION_MODE_CONTINUOUS) { |
brunnobbco | 0:561d07a737bc | 944 | _rx_timeout = 0xFFFFFFFF; |
brunnobbco | 0:561d07a737bc | 945 | } else { |
brunnobbco | 0:561d07a737bc | 946 | _rx_timeout = 0x00000000; |
brunnobbco | 0:561d07a737bc | 947 | } |
brunnobbco | 0:561d07a737bc | 948 | |
brunnobbco | 0:561d07a737bc | 949 | break; |
brunnobbco | 0:561d07a737bc | 950 | } |
brunnobbco | 0:561d07a737bc | 951 | |
brunnobbco | 0:561d07a737bc | 952 | default: |
brunnobbco | 0:561d07a737bc | 953 | break; |
brunnobbco | 0:561d07a737bc | 954 | } |
brunnobbco | 0:561d07a737bc | 955 | } |
brunnobbco | 0:561d07a737bc | 956 | |
brunnobbco | 0:561d07a737bc | 957 | void SX126X_LoRaRadio::configure_dio_irq(uint16_t irq_mask, uint16_t dio1_mask, |
brunnobbco | 0:561d07a737bc | 958 | uint16_t dio2_mask, uint16_t dio3_mask) |
brunnobbco | 0:561d07a737bc | 959 | { |
brunnobbco | 0:561d07a737bc | 960 | uint8_t buf[8]; |
brunnobbco | 0:561d07a737bc | 961 | |
brunnobbco | 0:561d07a737bc | 962 | buf[0] = (uint8_t) ((irq_mask >> 8) & 0x00FF); |
brunnobbco | 0:561d07a737bc | 963 | buf[1] = (uint8_t) (irq_mask & 0x00FF); |
brunnobbco | 0:561d07a737bc | 964 | buf[2] = (uint8_t) ((dio1_mask >> 8) & 0x00FF); |
brunnobbco | 0:561d07a737bc | 965 | buf[3] = (uint8_t) (dio1_mask & 0x00FF); |
brunnobbco | 0:561d07a737bc | 966 | buf[4] = (uint8_t) ((dio2_mask >> 8) & 0x00FF); |
brunnobbco | 0:561d07a737bc | 967 | buf[5] = (uint8_t) (dio2_mask & 0x00FF); |
brunnobbco | 0:561d07a737bc | 968 | buf[6] = (uint8_t) ((dio3_mask >> 8) & 0x00FF); |
brunnobbco | 0:561d07a737bc | 969 | buf[7] = (uint8_t) (dio3_mask & 0x00FF); |
brunnobbco | 0:561d07a737bc | 970 | |
brunnobbco | 0:561d07a737bc | 971 | write_opmode_command((uint8_t) RADIO_CFG_DIOIRQ, buf, 8); |
brunnobbco | 0:561d07a737bc | 972 | } |
brunnobbco | 0:561d07a737bc | 973 | |
brunnobbco | 0:561d07a737bc | 974 | void SX126X_LoRaRadio::send(uint8_t *buffer, uint8_t size) |
brunnobbco | 0:561d07a737bc | 975 | { |
brunnobbco | 0:561d07a737bc | 976 | set_tx_power(_tx_power); |
brunnobbco | 0:561d07a737bc | 977 | configure_dio_irq(IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT, |
brunnobbco | 0:561d07a737bc | 978 | IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT, |
brunnobbco | 0:561d07a737bc | 979 | IRQ_RADIO_NONE, |
brunnobbco | 0:561d07a737bc | 980 | IRQ_RADIO_NONE ); |
brunnobbco | 0:561d07a737bc | 981 | |
brunnobbco | 0:561d07a737bc | 982 | set_modulation_params(&_mod_params); |
brunnobbco | 0:561d07a737bc | 983 | set_packet_params(&_packet_params); |
brunnobbco | 0:561d07a737bc | 984 | |
brunnobbco | 0:561d07a737bc | 985 | write_fifo(buffer, size); |
brunnobbco | 0:561d07a737bc | 986 | uint8_t buf[3]; |
brunnobbco | 0:561d07a737bc | 987 | |
brunnobbco | 0:561d07a737bc | 988 | // _tx_timeout in ms should be converted to us and then divided by |
brunnobbco | 0:561d07a737bc | 989 | // 15.625 us. Check data-sheet 13.1.4 SetTX() section. |
brunnobbco | 0:561d07a737bc | 990 | uint32_t timeout_scalled = ceil((_tx_timeout * 1000) / 15.625); |
brunnobbco | 0:561d07a737bc | 991 | |
brunnobbco | 0:561d07a737bc | 992 | buf[0] = (uint8_t) ((timeout_scalled >> 16) & 0xFF); |
brunnobbco | 0:561d07a737bc | 993 | buf[1] = (uint8_t) ((timeout_scalled >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 994 | buf[2] = (uint8_t) (timeout_scalled & 0xFF); |
brunnobbco | 0:561d07a737bc | 995 | |
brunnobbco | 0:561d07a737bc | 996 | write_opmode_command(RADIO_SET_TX, buf, 3); |
brunnobbco | 0:561d07a737bc | 997 | |
brunnobbco | 0:561d07a737bc | 998 | _operation_mode = MODE_TX; |
brunnobbco | 0:561d07a737bc | 999 | } |
brunnobbco | 0:561d07a737bc | 1000 | |
brunnobbco | 0:561d07a737bc | 1001 | |
brunnobbco | 0:561d07a737bc | 1002 | void SX126X_LoRaRadio::receive(void) |
brunnobbco | 0:561d07a737bc | 1003 | { |
brunnobbco | 0:561d07a737bc | 1004 | if (get_modem() == MODEM_LORA && _reception_mode != RECEPTION_MODE_CONTINUOUS) { |
brunnobbco | 0:561d07a737bc | 1005 | // Data-sheet Table 13-11: StopOnPreambParam |
brunnobbco | 0:561d07a737bc | 1006 | // We will use radio's internal timer to mark no reception. This behaviour |
brunnobbco | 0:561d07a737bc | 1007 | // is different from SX1272/SX1276 where we are relying on radio to stop |
brunnobbco | 0:561d07a737bc | 1008 | // at preamble detection. |
brunnobbco | 0:561d07a737bc | 1009 | // 0x00 means Timer will be stopped on SyncWord(FSK) or Header (LoRa) detection |
brunnobbco | 0:561d07a737bc | 1010 | // 0x01 means Timer is stopped on preamble detection |
brunnobbco | 0:561d07a737bc | 1011 | uint8_t stop_at_preamble = 0x01; |
brunnobbco | 0:561d07a737bc | 1012 | write_opmode_command(RADIO_SET_STOPRXTIMERONPREAMBLE, &stop_at_preamble, 1); |
brunnobbco | 0:561d07a737bc | 1013 | // Data-sheet 13.4.9 SetLoRaSymbNumTimeout |
brunnobbco | 0:561d07a737bc | 1014 | write_opmode_command(RADIO_SET_LORASYMBTIMEOUT, &_rx_timeout_in_symbols, 1); |
brunnobbco | 0:561d07a737bc | 1015 | } |
brunnobbco | 0:561d07a737bc | 1016 | |
brunnobbco | 0:561d07a737bc | 1017 | if (_reception_mode != RECEPTION_MODE_OTHER) { |
brunnobbco | 0:561d07a737bc | 1018 | configure_dio_irq(IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT | IRQ_CRC_ERROR , |
brunnobbco | 0:561d07a737bc | 1019 | IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT | IRQ_CRC_ERROR , |
brunnobbco | 0:561d07a737bc | 1020 | IRQ_RADIO_NONE, |
brunnobbco | 0:561d07a737bc | 1021 | IRQ_RADIO_NONE); |
brunnobbco | 0:561d07a737bc | 1022 | set_modulation_params(&_mod_params); |
brunnobbco | 0:561d07a737bc | 1023 | set_packet_params(&_packet_params); |
brunnobbco | 0:561d07a737bc | 1024 | } |
brunnobbco | 0:561d07a737bc | 1025 | |
brunnobbco | 0:561d07a737bc | 1026 | uint8_t buf[3]; |
brunnobbco | 0:561d07a737bc | 1027 | |
brunnobbco | 0:561d07a737bc | 1028 | #if MBED_CONF_SX126X_LORA_DRIVER_BOOST_RX |
brunnobbco | 0:561d07a737bc | 1029 | write_to_register(REG_RX_GAIN, 0x96); |
brunnobbco | 0:561d07a737bc | 1030 | #endif |
brunnobbco | 0:561d07a737bc | 1031 | |
brunnobbco | 0:561d07a737bc | 1032 | buf[0] = (uint8_t) ((_rx_timeout >> 16) & 0xFF); |
brunnobbco | 0:561d07a737bc | 1033 | buf[1] = (uint8_t) ((_rx_timeout >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 1034 | buf[2] = (uint8_t) (_rx_timeout & 0xFF); |
brunnobbco | 0:561d07a737bc | 1035 | |
brunnobbco | 0:561d07a737bc | 1036 | write_opmode_command(RADIO_SET_RX, buf, 3); |
brunnobbco | 0:561d07a737bc | 1037 | |
brunnobbco | 0:561d07a737bc | 1038 | _operation_mode = MODE_RX; |
brunnobbco | 0:561d07a737bc | 1039 | } |
brunnobbco | 0:561d07a737bc | 1040 | |
brunnobbco | 0:561d07a737bc | 1041 | // check data-sheet 13.1.14.1 PA optimal settings |
brunnobbco | 0:561d07a737bc | 1042 | void SX126X_LoRaRadio::set_tx_power(int8_t power) |
brunnobbco | 0:561d07a737bc | 1043 | { |
brunnobbco | 0:561d07a737bc | 1044 | uint8_t buf[2]; |
brunnobbco | 0:561d07a737bc | 1045 | |
brunnobbco | 0:561d07a737bc | 1046 | if (get_device_variant() == SX1261) { |
brunnobbco | 0:561d07a737bc | 1047 | if (power >= 14) { |
brunnobbco | 0:561d07a737bc | 1048 | set_pa_config(0x04, 0x00, 0x01, 0x01); |
brunnobbco | 0:561d07a737bc | 1049 | power = 14; |
brunnobbco | 0:561d07a737bc | 1050 | } else if (power < 14){ |
brunnobbco | 0:561d07a737bc | 1051 | set_pa_config(0x01, 0x00, 0x01, 0x01); |
brunnobbco | 0:561d07a737bc | 1052 | } |
brunnobbco | 0:561d07a737bc | 1053 | |
brunnobbco | 0:561d07a737bc | 1054 | if (power < -3) { |
brunnobbco | 0:561d07a737bc | 1055 | power = -3; |
brunnobbco | 0:561d07a737bc | 1056 | } |
brunnobbco | 0:561d07a737bc | 1057 | write_to_register(REG_OCP, 0x18); // current max is 80 mA for the whole device |
brunnobbco | 0:561d07a737bc | 1058 | } else { |
brunnobbco | 0:561d07a737bc | 1059 | // sx1262 or sx1268 |
brunnobbco | 0:561d07a737bc | 1060 | if (power > 22) { |
brunnobbco | 0:561d07a737bc | 1061 | power = 22; |
brunnobbco | 0:561d07a737bc | 1062 | } else if (power < -3) { |
brunnobbco | 0:561d07a737bc | 1063 | power = -3; |
brunnobbco | 0:561d07a737bc | 1064 | } |
brunnobbco | 0:561d07a737bc | 1065 | |
brunnobbco | 0:561d07a737bc | 1066 | if (power <= 14) { |
brunnobbco | 0:561d07a737bc | 1067 | set_pa_config(0x02, 0x02, 0x00, 0x01); |
brunnobbco | 0:561d07a737bc | 1068 | } else { |
brunnobbco | 0:561d07a737bc | 1069 | set_pa_config(0x04, 0x07, 0x00, 0x01); |
brunnobbco | 0:561d07a737bc | 1070 | } |
brunnobbco | 0:561d07a737bc | 1071 | |
brunnobbco | 0:561d07a737bc | 1072 | write_to_register(REG_OCP, 0x38); // current max 160mA for the whole device |
brunnobbco | 0:561d07a737bc | 1073 | } |
brunnobbco | 0:561d07a737bc | 1074 | |
brunnobbco | 0:561d07a737bc | 1075 | buf[0] = power; |
brunnobbco | 0:561d07a737bc | 1076 | |
brunnobbco | 0:561d07a737bc | 1077 | if (_crystal_select.is_connected() && _crystal_select == 0) { |
brunnobbco | 0:561d07a737bc | 1078 | // TCXO |
brunnobbco | 0:561d07a737bc | 1079 | buf[1] = RADIO_RAMP_200_US; |
brunnobbco | 0:561d07a737bc | 1080 | } else { |
brunnobbco | 0:561d07a737bc | 1081 | // XTAL |
brunnobbco | 0:561d07a737bc | 1082 | buf[1] = RADIO_RAMP_20_US; |
brunnobbco | 0:561d07a737bc | 1083 | } |
brunnobbco | 0:561d07a737bc | 1084 | |
brunnobbco | 0:561d07a737bc | 1085 | write_opmode_command(RADIO_SET_TXPARAMS, buf, 2); |
brunnobbco | 0:561d07a737bc | 1086 | } |
brunnobbco | 0:561d07a737bc | 1087 | |
brunnobbco | 0:561d07a737bc | 1088 | void SX126X_LoRaRadio::set_modulation_params(modulation_params_t *params) |
brunnobbco | 0:561d07a737bc | 1089 | { |
brunnobbco | 0:561d07a737bc | 1090 | uint8_t n; |
brunnobbco | 0:561d07a737bc | 1091 | uint32_t temp = 0; |
brunnobbco | 0:561d07a737bc | 1092 | uint8_t buf[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
brunnobbco | 0:561d07a737bc | 1093 | |
brunnobbco | 0:561d07a737bc | 1094 | // Check if required configuration corresponds to the stored packet type |
brunnobbco | 0:561d07a737bc | 1095 | // If not, silently update radio packet type |
brunnobbco | 0:561d07a737bc | 1096 | if (_active_modem != params->modem_type) { |
brunnobbco | 0:561d07a737bc | 1097 | set_modem(params->modem_type); |
brunnobbco | 0:561d07a737bc | 1098 | } |
brunnobbco | 0:561d07a737bc | 1099 | |
brunnobbco | 0:561d07a737bc | 1100 | switch (params->modem_type) { |
brunnobbco | 0:561d07a737bc | 1101 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1102 | n = 8; |
brunnobbco | 0:561d07a737bc | 1103 | temp = (uint32_t) (32 * ((float) XTAL_FREQ / (float) params->params.gfsk.bit_rate)); |
brunnobbco | 0:561d07a737bc | 1104 | buf[0] = (temp >> 16) & 0xFF; |
brunnobbco | 0:561d07a737bc | 1105 | buf[1] = (temp >> 8) & 0xFF; |
brunnobbco | 0:561d07a737bc | 1106 | buf[2] = temp & 0xFF; |
brunnobbco | 0:561d07a737bc | 1107 | buf[3] = params->params.gfsk.modulation_shaping; |
brunnobbco | 0:561d07a737bc | 1108 | buf[4] = params->params.gfsk.bandwidth; |
brunnobbco | 0:561d07a737bc | 1109 | temp = (uint32_t) ((float) params->params.gfsk.fdev / (float) FREQ_STEP); |
brunnobbco | 0:561d07a737bc | 1110 | buf[5] = (temp >> 16) & 0xFF; |
brunnobbco | 0:561d07a737bc | 1111 | buf[6] = (temp >> 8) & 0xFF; |
brunnobbco | 0:561d07a737bc | 1112 | buf[7] = (temp & 0xFF); |
brunnobbco | 0:561d07a737bc | 1113 | write_opmode_command(RADIO_SET_MODULATIONPARAMS, buf, n); |
brunnobbco | 0:561d07a737bc | 1114 | break; |
brunnobbco | 0:561d07a737bc | 1115 | |
brunnobbco | 0:561d07a737bc | 1116 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1117 | n = 4; |
brunnobbco | 0:561d07a737bc | 1118 | buf[0] = params->params.lora.spreading_factor; |
brunnobbco | 0:561d07a737bc | 1119 | buf[1] = params->params.lora.bandwidth; |
brunnobbco | 0:561d07a737bc | 1120 | buf[2] = params->params.lora.coding_rate; |
brunnobbco | 0:561d07a737bc | 1121 | buf[3] = params->params.lora.low_datarate_optimization; |
brunnobbco | 0:561d07a737bc | 1122 | |
brunnobbco | 0:561d07a737bc | 1123 | write_opmode_command(RADIO_SET_MODULATIONPARAMS, buf, n); |
brunnobbco | 0:561d07a737bc | 1124 | break; |
brunnobbco | 0:561d07a737bc | 1125 | |
brunnobbco | 0:561d07a737bc | 1126 | default: |
brunnobbco | 0:561d07a737bc | 1127 | return; |
brunnobbco | 0:561d07a737bc | 1128 | } |
brunnobbco | 0:561d07a737bc | 1129 | } |
brunnobbco | 0:561d07a737bc | 1130 | |
brunnobbco | 0:561d07a737bc | 1131 | void SX126X_LoRaRadio::set_pa_config(uint8_t pa_DC, uint8_t hp_max, |
brunnobbco | 0:561d07a737bc | 1132 | uint8_t device_type, uint8_t pa_LUT ) |
brunnobbco | 0:561d07a737bc | 1133 | { |
brunnobbco | 0:561d07a737bc | 1134 | uint8_t buf[4]; |
brunnobbco | 0:561d07a737bc | 1135 | |
brunnobbco | 0:561d07a737bc | 1136 | buf[0] = pa_DC; |
brunnobbco | 0:561d07a737bc | 1137 | buf[1] = hp_max; |
brunnobbco | 0:561d07a737bc | 1138 | buf[2] = device_type; |
brunnobbco | 0:561d07a737bc | 1139 | buf[3] = pa_LUT; |
brunnobbco | 0:561d07a737bc | 1140 | write_opmode_command(RADIO_SET_PACONFIG, buf, 4); |
brunnobbco | 0:561d07a737bc | 1141 | } |
brunnobbco | 0:561d07a737bc | 1142 | |
brunnobbco | 0:561d07a737bc | 1143 | void SX126X_LoRaRadio::set_crc_seed(uint16_t seed) |
brunnobbco | 0:561d07a737bc | 1144 | { |
brunnobbco | 0:561d07a737bc | 1145 | if (_active_modem == MODEM_FSK) { |
brunnobbco | 0:561d07a737bc | 1146 | uint8_t buf[2]; |
brunnobbco | 0:561d07a737bc | 1147 | buf[0] = (uint8_t) ((seed >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 1148 | buf[1] = (uint8_t) (seed & 0xFF); |
brunnobbco | 0:561d07a737bc | 1149 | write_to_register(REG_LR_CRCSEEDBASEADDR, buf, 2); |
brunnobbco | 0:561d07a737bc | 1150 | } |
brunnobbco | 0:561d07a737bc | 1151 | } |
brunnobbco | 0:561d07a737bc | 1152 | |
brunnobbco | 0:561d07a737bc | 1153 | void SX126X_LoRaRadio::set_crc_polynomial(uint16_t polynomial) |
brunnobbco | 0:561d07a737bc | 1154 | { |
brunnobbco | 0:561d07a737bc | 1155 | if (_active_modem == MODEM_FSK) { |
brunnobbco | 0:561d07a737bc | 1156 | uint8_t buf[2]; |
brunnobbco | 0:561d07a737bc | 1157 | buf[0] = (uint8_t) ((polynomial >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 1158 | buf[1] = (uint8_t) (polynomial & 0xFF); |
brunnobbco | 0:561d07a737bc | 1159 | write_to_register(REG_LR_CRCPOLYBASEADDR, buf, 2); |
brunnobbco | 0:561d07a737bc | 1160 | } |
brunnobbco | 0:561d07a737bc | 1161 | } |
brunnobbco | 0:561d07a737bc | 1162 | |
brunnobbco | 0:561d07a737bc | 1163 | void SX126X_LoRaRadio::set_whitening_seed(uint16_t seed) |
brunnobbco | 0:561d07a737bc | 1164 | { |
brunnobbco | 0:561d07a737bc | 1165 | if (_active_modem == MODEM_FSK) { |
brunnobbco | 0:561d07a737bc | 1166 | uint8_t reg_value = read_register(REG_LR_WHITSEEDBASEADDR_MSB) & 0xFE; |
brunnobbco | 0:561d07a737bc | 1167 | reg_value = ((seed >> 8) & 0x01) | reg_value; |
brunnobbco | 0:561d07a737bc | 1168 | write_to_register(REG_LR_WHITSEEDBASEADDR_MSB, reg_value); // only 1 bit. |
brunnobbco | 0:561d07a737bc | 1169 | write_to_register(REG_LR_WHITSEEDBASEADDR_LSB, (uint8_t) seed); |
brunnobbco | 0:561d07a737bc | 1170 | } |
brunnobbco | 0:561d07a737bc | 1171 | } |
brunnobbco | 0:561d07a737bc | 1172 | |
brunnobbco | 0:561d07a737bc | 1173 | void SX126X_LoRaRadio::set_packet_params(packet_params_t *packet_params) |
brunnobbco | 0:561d07a737bc | 1174 | { |
brunnobbco | 0:561d07a737bc | 1175 | uint8_t n; |
brunnobbco | 0:561d07a737bc | 1176 | uint8_t crc_val = 0; |
brunnobbco | 0:561d07a737bc | 1177 | uint8_t buf[9] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
brunnobbco | 0:561d07a737bc | 1178 | |
brunnobbco | 0:561d07a737bc | 1179 | // Check if required configuration corresponds to the stored packet type |
brunnobbco | 0:561d07a737bc | 1180 | // If not, silently update radio packet type |
brunnobbco | 0:561d07a737bc | 1181 | if (_active_modem != packet_params->modem_type) { |
brunnobbco | 0:561d07a737bc | 1182 | set_modem(packet_params->modem_type); |
brunnobbco | 0:561d07a737bc | 1183 | } |
brunnobbco | 0:561d07a737bc | 1184 | |
brunnobbco | 0:561d07a737bc | 1185 | switch (packet_params->modem_type) { |
brunnobbco | 0:561d07a737bc | 1186 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1187 | if (packet_params->params.gfsk.crc_length == RADIO_CRC_2_BYTES_IBM) { |
brunnobbco | 0:561d07a737bc | 1188 | set_crc_seed(CRC_IBM_SEED); |
brunnobbco | 0:561d07a737bc | 1189 | set_crc_polynomial(CRC_POLYNOMIAL_IBM); |
brunnobbco | 0:561d07a737bc | 1190 | crc_val = RADIO_CRC_2_BYTES; |
brunnobbco | 0:561d07a737bc | 1191 | } else if (packet_params->params.gfsk.crc_length == RADIO_CRC_2_BYTES_CCIT) { |
brunnobbco | 0:561d07a737bc | 1192 | set_crc_seed(CRC_CCITT_SEED); |
brunnobbco | 0:561d07a737bc | 1193 | set_crc_polynomial(CRC_POLYNOMIAL_CCITT); |
brunnobbco | 0:561d07a737bc | 1194 | crc_val = RADIO_CRC_2_BYTES_INV; |
brunnobbco | 0:561d07a737bc | 1195 | } else { |
brunnobbco | 0:561d07a737bc | 1196 | crc_val = packet_params->params.gfsk.crc_length; |
brunnobbco | 0:561d07a737bc | 1197 | } |
brunnobbco | 0:561d07a737bc | 1198 | n = 9; |
brunnobbco | 0:561d07a737bc | 1199 | buf[0] = (packet_params->params.gfsk.preamble_length >> 8) & 0xFF; |
brunnobbco | 0:561d07a737bc | 1200 | buf[1] = packet_params->params.gfsk.preamble_length; |
brunnobbco | 0:561d07a737bc | 1201 | buf[2] = packet_params->params.gfsk.preamble_min_detect; |
brunnobbco | 0:561d07a737bc | 1202 | buf[3] = (packet_params->params.gfsk.syncword_length /*<< 3*/); // convert from byte to bit |
brunnobbco | 0:561d07a737bc | 1203 | buf[4] = packet_params->params.gfsk.addr_comp; |
brunnobbco | 0:561d07a737bc | 1204 | buf[5] = packet_params->params.gfsk.header_type; |
brunnobbco | 0:561d07a737bc | 1205 | buf[6] = packet_params->params.gfsk.payload_length; |
brunnobbco | 0:561d07a737bc | 1206 | buf[7] = crc_val; |
brunnobbco | 0:561d07a737bc | 1207 | buf[8] = packet_params->params.gfsk.whitening_mode; |
brunnobbco | 0:561d07a737bc | 1208 | break; |
brunnobbco | 0:561d07a737bc | 1209 | |
brunnobbco | 0:561d07a737bc | 1210 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1211 | n = 6; |
brunnobbco | 0:561d07a737bc | 1212 | buf[0] = (packet_params->params.lora.preamble_length >> 8) & 0xFF; |
brunnobbco | 0:561d07a737bc | 1213 | buf[1] = packet_params->params.lora.preamble_length; |
brunnobbco | 0:561d07a737bc | 1214 | buf[2] = packet_params->params.lora.header_type; |
brunnobbco | 0:561d07a737bc | 1215 | buf[3] = packet_params->params.lora.payload_length; |
brunnobbco | 0:561d07a737bc | 1216 | buf[4] = packet_params->params.lora.crc_mode; |
brunnobbco | 0:561d07a737bc | 1217 | buf[5] = packet_params->params.lora.invert_IQ; |
brunnobbco | 0:561d07a737bc | 1218 | break; |
brunnobbco | 0:561d07a737bc | 1219 | default: |
brunnobbco | 0:561d07a737bc | 1220 | return; |
brunnobbco | 0:561d07a737bc | 1221 | } |
brunnobbco | 0:561d07a737bc | 1222 | write_opmode_command(RADIO_SET_PACKETPARAMS, buf, n); |
brunnobbco | 0:561d07a737bc | 1223 | } |
brunnobbco | 0:561d07a737bc | 1224 | |
brunnobbco | 0:561d07a737bc | 1225 | void SX126X_LoRaRadio::set_cad_params(lora_cad_symbols_t nb_symbols, |
brunnobbco | 0:561d07a737bc | 1226 | uint8_t det_peak, uint8_t det_min, |
brunnobbco | 0:561d07a737bc | 1227 | cad_exit_modes_t exit_mode, |
brunnobbco | 0:561d07a737bc | 1228 | uint32_t timeout) |
brunnobbco | 0:561d07a737bc | 1229 | { |
brunnobbco | 0:561d07a737bc | 1230 | uint8_t buf[7]; |
brunnobbco | 0:561d07a737bc | 1231 | |
brunnobbco | 0:561d07a737bc | 1232 | buf[0] = (uint8_t) nb_symbols; |
brunnobbco | 0:561d07a737bc | 1233 | buf[1] = det_peak; |
brunnobbco | 0:561d07a737bc | 1234 | buf[2] = det_min; |
brunnobbco | 0:561d07a737bc | 1235 | buf[3] = (uint8_t) exit_mode; |
brunnobbco | 0:561d07a737bc | 1236 | buf[4] = (uint8_t) ((timeout >> 16) & 0xFF); |
brunnobbco | 0:561d07a737bc | 1237 | buf[5] = (uint8_t) ((timeout >> 8) & 0xFF); |
brunnobbco | 0:561d07a737bc | 1238 | buf[6] = (uint8_t) (timeout & 0xFF); |
brunnobbco | 0:561d07a737bc | 1239 | write_opmode_command((uint8_t) RADIO_SET_CADPARAMS, buf, 7); |
brunnobbco | 0:561d07a737bc | 1240 | |
brunnobbco | 0:561d07a737bc | 1241 | _operation_mode = MODE_CAD; |
brunnobbco | 0:561d07a737bc | 1242 | } |
brunnobbco | 0:561d07a737bc | 1243 | |
brunnobbco | 0:561d07a737bc | 1244 | void SX126X_LoRaRadio::set_buffer_base_addr(uint8_t tx_base_addr, uint8_t rx_base_addr) |
brunnobbco | 0:561d07a737bc | 1245 | { |
brunnobbco | 0:561d07a737bc | 1246 | uint8_t buf[2]; |
brunnobbco | 0:561d07a737bc | 1247 | |
brunnobbco | 0:561d07a737bc | 1248 | buf[0] = tx_base_addr; |
brunnobbco | 0:561d07a737bc | 1249 | buf[1] = rx_base_addr; |
brunnobbco | 0:561d07a737bc | 1250 | write_opmode_command((uint8_t) RADIO_SET_BUFFERBASEADDRESS, buf, 2); |
brunnobbco | 0:561d07a737bc | 1251 | } |
brunnobbco | 0:561d07a737bc | 1252 | |
brunnobbco | 0:561d07a737bc | 1253 | uint8_t SX126X_LoRaRadio::get_status(void) |
brunnobbco | 0:561d07a737bc | 1254 | { |
brunnobbco | 0:561d07a737bc | 1255 | if (_operation_mode != MODE_STDBY_RC || _operation_mode != MODE_SLEEP) { |
brunnobbco | 0:561d07a737bc | 1256 | return 0; |
brunnobbco | 0:561d07a737bc | 1257 | } |
brunnobbco | 0:561d07a737bc | 1258 | |
brunnobbco | 0:561d07a737bc | 1259 | return 0xFF; |
brunnobbco | 0:561d07a737bc | 1260 | } |
brunnobbco | 0:561d07a737bc | 1261 | |
brunnobbco | 0:561d07a737bc | 1262 | int8_t SX126X_LoRaRadio::get_rssi() |
brunnobbco | 0:561d07a737bc | 1263 | { |
brunnobbco | 0:561d07a737bc | 1264 | uint8_t buf[1]; |
brunnobbco | 0:561d07a737bc | 1265 | int8_t rssi = 0; |
brunnobbco | 0:561d07a737bc | 1266 | |
brunnobbco | 0:561d07a737bc | 1267 | read_opmode_command((uint8_t) RADIO_GET_RSSIINST, buf, 1); |
brunnobbco | 0:561d07a737bc | 1268 | rssi = -buf[0] >> 1; |
brunnobbco | 0:561d07a737bc | 1269 | return rssi; |
brunnobbco | 0:561d07a737bc | 1270 | } |
brunnobbco | 0:561d07a737bc | 1271 | |
brunnobbco | 0:561d07a737bc | 1272 | void SX126X_LoRaRadio::get_rx_buffer_status(uint8_t *payload_len, |
brunnobbco | 0:561d07a737bc | 1273 | uint8_t *start_ptr) |
brunnobbco | 0:561d07a737bc | 1274 | { |
brunnobbco | 0:561d07a737bc | 1275 | uint8_t status[2]; |
brunnobbco | 0:561d07a737bc | 1276 | |
brunnobbco | 0:561d07a737bc | 1277 | read_opmode_command((uint8_t) RADIO_GET_RXBUFFERSTATUS, status, 2); |
brunnobbco | 0:561d07a737bc | 1278 | |
brunnobbco | 0:561d07a737bc | 1279 | // In case of LORA fixed header, the payloadLength is obtained by reading |
brunnobbco | 0:561d07a737bc | 1280 | // the register REG_LR_PAYLOADLENGTH |
brunnobbco | 0:561d07a737bc | 1281 | if ((get_modem() == MODEM_LORA) && |
brunnobbco | 0:561d07a737bc | 1282 | (read_register(REG_LR_PACKETPARAMS) >> 7 == 1)) { |
brunnobbco | 0:561d07a737bc | 1283 | *payload_len = read_register(REG_LR_PAYLOADLENGTH); |
brunnobbco | 0:561d07a737bc | 1284 | } else { |
brunnobbco | 0:561d07a737bc | 1285 | *payload_len = status[0]; |
brunnobbco | 0:561d07a737bc | 1286 | } |
brunnobbco | 0:561d07a737bc | 1287 | |
brunnobbco | 0:561d07a737bc | 1288 | *start_ptr = status[1]; |
brunnobbco | 0:561d07a737bc | 1289 | } |
brunnobbco | 0:561d07a737bc | 1290 | |
brunnobbco | 0:561d07a737bc | 1291 | void SX126X_LoRaRadio::get_packet_status(packet_status_t *pkt_status) |
brunnobbco | 0:561d07a737bc | 1292 | { |
brunnobbco | 0:561d07a737bc | 1293 | uint8_t status[3]; |
brunnobbco | 0:561d07a737bc | 1294 | |
brunnobbco | 0:561d07a737bc | 1295 | read_opmode_command((uint8_t) RADIO_GET_PACKETSTATUS, status, 3); |
brunnobbco | 0:561d07a737bc | 1296 | |
brunnobbco | 0:561d07a737bc | 1297 | pkt_status->modem_type = (radio_modems_t) get_modem(); |
brunnobbco | 0:561d07a737bc | 1298 | switch (pkt_status->modem_type) { |
brunnobbco | 0:561d07a737bc | 1299 | case MODEM_FSK: |
brunnobbco | 0:561d07a737bc | 1300 | pkt_status->params.gfsk.rx_status = status[0]; |
brunnobbco | 0:561d07a737bc | 1301 | pkt_status->params.gfsk.rssi_sync = -status[1] >> 1; |
brunnobbco | 0:561d07a737bc | 1302 | pkt_status->params.gfsk.rssi_avg = -status[2] >> 1; |
brunnobbco | 0:561d07a737bc | 1303 | pkt_status->params.gfsk.freq_error = 0; |
brunnobbco | 0:561d07a737bc | 1304 | break; |
brunnobbco | 0:561d07a737bc | 1305 | |
brunnobbco | 0:561d07a737bc | 1306 | case MODEM_LORA: |
brunnobbco | 0:561d07a737bc | 1307 | pkt_status->params.lora.rssi_pkt = -status[0] >> 1; |
brunnobbco | 0:561d07a737bc | 1308 | // Returns SNR value [dB] rounded to the nearest integer value |
brunnobbco | 0:561d07a737bc | 1309 | pkt_status->params.lora.snr_pkt = (((int8_t) status[1]) + 2) >> 2; |
brunnobbco | 0:561d07a737bc | 1310 | pkt_status->params.lora.signal_rssi_pkt = -status[2] >> 1; |
brunnobbco | 0:561d07a737bc | 1311 | break; |
brunnobbco | 0:561d07a737bc | 1312 | |
brunnobbco | 0:561d07a737bc | 1313 | default: |
brunnobbco | 0:561d07a737bc | 1314 | // In that specific case, we set everything in the pkt_status to zeros |
brunnobbco | 0:561d07a737bc | 1315 | // and reset the packet type accordingly |
brunnobbco | 0:561d07a737bc | 1316 | memset(pkt_status, 0, sizeof(packet_status_t)); |
brunnobbco | 0:561d07a737bc | 1317 | break; |
brunnobbco | 0:561d07a737bc | 1318 | } |
brunnobbco | 0:561d07a737bc | 1319 | } |
brunnobbco | 0:561d07a737bc | 1320 | |
brunnobbco | 0:561d07a737bc | 1321 | radio_error_t SX126X_LoRaRadio::get_device_errors(void) |
brunnobbco | 0:561d07a737bc | 1322 | { |
brunnobbco | 0:561d07a737bc | 1323 | radio_error_t error; |
brunnobbco | 0:561d07a737bc | 1324 | |
brunnobbco | 0:561d07a737bc | 1325 | read_opmode_command((uint8_t) RADIO_GET_ERROR, (uint8_t *)&error, 2); |
brunnobbco | 0:561d07a737bc | 1326 | return error; |
brunnobbco | 0:561d07a737bc | 1327 | } |
brunnobbco | 0:561d07a737bc | 1328 | |
brunnobbco | 0:561d07a737bc | 1329 | void SX126X_LoRaRadio::clear_device_errors(void) |
brunnobbco | 0:561d07a737bc | 1330 | { |
brunnobbco | 0:561d07a737bc | 1331 | uint8_t buf[2] = {0x00, 0x00}; |
brunnobbco | 0:561d07a737bc | 1332 | write_opmode_command((uint8_t) RADIO_CLR_ERROR, buf, 2); |
brunnobbco | 0:561d07a737bc | 1333 | } |
brunnobbco | 0:561d07a737bc | 1334 |