Hardware Abstraction Layer, permitting any LoRa application to use any LoRa radio chip

Dependents:   alarm_slave alarm_master lora_p2p lorawan1v1 ... more

radio chip selection

Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
if you're using LR1110, then import LR1110 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.
If you're using Type1SJ select target DISCO_L072CZ_LRWAN1 and import sx126x driver into your program.

Pin assigned to arduino LoRa radio shield form-factor

Committer:
Wayne Roberts
Date:
Fri Feb 05 16:35:05 2021 -0800
Revision:
21:96db08266089
Parent:
20:75635d50262e
lr1110: handle tcxo when hf-xosc fails to start

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 0:9c052ff8dd6a 1 #include "radio.h"
Wayne Roberts 0:9c052ff8dd6a 2 #ifdef SX128x_H
Wayne Roberts 0:9c052ff8dd6a 3 #include "SPIu.h"
Wayne Roberts 0:9c052ff8dd6a 4 #include <float.h>
Wayne Roberts 0:9c052ff8dd6a 5
Wayne Roberts 20:75635d50262e 6 #ifdef DEVICE_LPTICKER
Wayne Roberts 20:75635d50262e 7 LowPowerTimer Radio::lpt;
Wayne Roberts 20:75635d50262e 8 #else
Wayne Roberts 20:75635d50262e 9 Timer Radio::lpt;
Wayne Roberts 20:75635d50262e 10 #endif
Wayne Roberts 20:75635d50262e 11
Wayne Roberts 20:75635d50262e 12 #if (MBED_MAJOR_VERSION < 6)
Wayne Roberts 20:75635d50262e 13 volatile us_timestamp_t Radio::irqAt;
Wayne Roberts 20:75635d50262e 14 #else
Wayne Roberts 20:75635d50262e 15 LowPowerClock::time_point Radio::irqAt;
Wayne Roberts 20:75635d50262e 16 #endif
Wayne Roberts 20:75635d50262e 17
Wayne Roberts 0:9c052ff8dd6a 18 #ifdef TARGET_FF_ARDUINO /* pins of SX126xDVK1xAS board */
Wayne Roberts 1:e79b0a55135f 19 #define NRST_PIN A0
Wayne Roberts 0:9c052ff8dd6a 20 SPIu spi(D11, D12, D13); // mosi, miso, sclk
Wayne Roberts 0:9c052ff8dd6a 21 // spi, nss, busy, dio1
Wayne Roberts 1:e79b0a55135f 22 SX128x Radio::radio(spi, D7, D3, D5, NRST_PIN);
Wayne Roberts 0:9c052ff8dd6a 23
Wayne Roberts 0:9c052ff8dd6a 24 #define LED_ON 1
Wayne Roberts 0:9c052ff8dd6a 25 #define LED_OFF 0
Wayne Roberts 0:9c052ff8dd6a 26 DigitalOut tx_led(A4);
Wayne Roberts 0:9c052ff8dd6a 27 DigitalOut rx_led(A5);
Wayne Roberts 0:9c052ff8dd6a 28
Wayne Roberts 0:9c052ff8dd6a 29
Wayne Roberts 0:9c052ff8dd6a 30 DigitalOut ant_sw(A3);
Wayne Roberts 0:9c052ff8dd6a 31 DigitalOut cps(D6); // SE2436L
Wayne Roberts 0:9c052ff8dd6a 32
Wayne Roberts 0:9c052ff8dd6a 33 bool fe_enable; // SE2436L
Wayne Roberts 0:9c052ff8dd6a 34
Wayne Roberts 0:9c052ff8dd6a 35 void Radio::chipModeChange()
Wayne Roberts 0:9c052ff8dd6a 36 {
Wayne Roberts 0:9c052ff8dd6a 37 if (radio.chipMode == CHIPMODE_NONE) {
Wayne Roberts 0:9c052ff8dd6a 38 cps = 0;
Wayne Roberts 0:9c052ff8dd6a 39 tx_led = LED_OFF;
Wayne Roberts 0:9c052ff8dd6a 40 rx_led = LED_OFF;
Wayne Roberts 0:9c052ff8dd6a 41 } else if (radio.chipMode == CHIPMODE_TX) {
Wayne Roberts 0:9c052ff8dd6a 42 cps = fe_enable;
Wayne Roberts 0:9c052ff8dd6a 43 tx_led = LED_ON;
Wayne Roberts 0:9c052ff8dd6a 44 rx_led = LED_OFF;
Wayne Roberts 0:9c052ff8dd6a 45 } else if (radio.chipMode == CHIPMODE_RX) {
Wayne Roberts 0:9c052ff8dd6a 46 cps = fe_enable;
Wayne Roberts 0:9c052ff8dd6a 47 tx_led = LED_OFF;
Wayne Roberts 0:9c052ff8dd6a 48 rx_led = LED_ON;
Wayne Roberts 0:9c052ff8dd6a 49 }
Wayne Roberts 0:9c052ff8dd6a 50 }
Wayne Roberts 0:9c052ff8dd6a 51 #endif /* TARGET_FF_ARDUINO */
Wayne Roberts 0:9c052ff8dd6a 52
Wayne Roberts 0:9c052ff8dd6a 53 #ifdef TARGET_FF_MORPHO
Wayne Roberts 0:9c052ff8dd6a 54 DigitalOut pc3(PC_3); // debug RX indication, for nucleo boards
Wayne Roberts 7:ba81f66e56d1 55 #define RX_INDICATION pc3
Wayne Roberts 0:9c052ff8dd6a 56 #endif /* TARGET_FF_MORPHO */
Wayne Roberts 0:9c052ff8dd6a 57
Wayne Roberts 0:9c052ff8dd6a 58
Wayne Roberts 0:9c052ff8dd6a 59 PacketParams_t Radio::ppGFSK;
Wayne Roberts 0:9c052ff8dd6a 60 PacketParams_t Radio::ppLORA;
Wayne Roberts 0:9c052ff8dd6a 61 PacketParams_t Radio::ppFLRC;
Wayne Roberts 0:9c052ff8dd6a 62
Wayne Roberts 0:9c052ff8dd6a 63 ModulationParams_t Radio::mpBLE_GFSK;
Wayne Roberts 0:9c052ff8dd6a 64 ModulationParams_t Radio::mpFLRC;
Wayne Roberts 0:9c052ff8dd6a 65 ModulationParams_t Radio::mpLORA;
Wayne Roberts 0:9c052ff8dd6a 66
Wayne Roberts 0:9c052ff8dd6a 67 const RadioEvents_t* RadioEvents;
Wayne Roberts 0:9c052ff8dd6a 68
Wayne Roberts 9:97a6de3dbc86 69 unsigned Radio::symbolPeriodUs;
Wayne Roberts 9:97a6de3dbc86 70 unsigned Radio::nSymbs;
Wayne Roberts 9:97a6de3dbc86 71 unsigned Radio::rxTimeoutMs;
Wayne Roberts 9:97a6de3dbc86 72
Wayne Roberts 0:9c052ff8dd6a 73 void Radio::readChip()
Wayne Roberts 0:9c052ff8dd6a 74 {
Wayne Roberts 0:9c052ff8dd6a 75 uint8_t reg8;
Wayne Roberts 0:9c052ff8dd6a 76
Wayne Roberts 0:9c052ff8dd6a 77 reg8 = radio.readReg(REG_ADDR_PKTCTRL0, 1);
Wayne Roberts 0:9c052ff8dd6a 78 ppGFSK.gfskFLRC.HeaderType = reg8 & 0x20;
Wayne Roberts 0:9c052ff8dd6a 79 ppFLRC.gfskFLRC.HeaderType = reg8 & 0x20;
Wayne Roberts 0:9c052ff8dd6a 80
Wayne Roberts 0:9c052ff8dd6a 81 reg8 = radio.readReg(REG_ADDR_PKTCTRL1, 1);
Wayne Roberts 0:9c052ff8dd6a 82 ppGFSK.gfskFLRC.PreambleLength = reg8 & 0x70;
Wayne Roberts 0:9c052ff8dd6a 83 ppFLRC.gfskFLRC.PreambleLength = reg8 & 0x70;
Wayne Roberts 0:9c052ff8dd6a 84 ppGFSK.gfskFLRC.SyncWordLength = reg8 & 0x0e;
Wayne Roberts 0:9c052ff8dd6a 85 ppFLRC.gfskFLRC.SyncWordLength = reg8 & 0x06;
Wayne Roberts 0:9c052ff8dd6a 86 if (ppFLRC.gfskFLRC.SyncWordLength == 0x06)
Wayne Roberts 0:9c052ff8dd6a 87 ppFLRC.gfskFLRC.SyncWordLength = FLRC_SYNC_WORD_LEN_P32S;
Wayne Roberts 0:9c052ff8dd6a 88
Wayne Roberts 0:9c052ff8dd6a 89 reg8 = radio.readReg(REG_ADDR_PKT_SYNC_ADRS_CTRL, 1);
Wayne Roberts 0:9c052ff8dd6a 90 ppGFSK.gfskFLRC.SyncWordMatch = reg8 & 0x70;
Wayne Roberts 0:9c052ff8dd6a 91 ppFLRC.gfskFLRC.SyncWordMatch = reg8 & 0x70;
Wayne Roberts 0:9c052ff8dd6a 92
Wayne Roberts 0:9c052ff8dd6a 93 reg8 = radio.readReg(REG_ADDR_PAYLOAD_LEN, 1);
Wayne Roberts 0:9c052ff8dd6a 94 ppGFSK.gfskFLRC.PayloadLength = reg8;
Wayne Roberts 0:9c052ff8dd6a 95 ppFLRC.gfskFLRC.PayloadLength = reg8;
Wayne Roberts 0:9c052ff8dd6a 96
Wayne Roberts 0:9c052ff8dd6a 97 reg8 = radio.readReg(REG_ADDR_PKT_TX_HEADER, 1); // TODO hi bit of payload length
Wayne Roberts 0:9c052ff8dd6a 98 //ppBLE.ble.ConnectionState = reg8 & 0xe0;
Wayne Roberts 0:9c052ff8dd6a 99 //ppBLE.ble.BleTestPayload = reg8 & 0x1c;
Wayne Roberts 0:9c052ff8dd6a 100
Wayne Roberts 0:9c052ff8dd6a 101 reg8 = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
Wayne Roberts 0:9c052ff8dd6a 102 //ppBLE.ble.CrcLength = reg8 & 0x30;
Wayne Roberts 0:9c052ff8dd6a 103 //ppBLE.ble.Whitening = reg8 & 0x08;
Wayne Roberts 0:9c052ff8dd6a 104 ppGFSK.gfskFLRC.CRCLength = reg8 & 0x30;
Wayne Roberts 0:9c052ff8dd6a 105 ppFLRC.gfskFLRC.CRCLength = reg8 & 0x30;
Wayne Roberts 0:9c052ff8dd6a 106 ppGFSK.gfskFLRC.Whitening = reg8 & 0x08;
Wayne Roberts 0:9c052ff8dd6a 107 ppFLRC.gfskFLRC.Whitening = reg8 & 0x08;
Wayne Roberts 0:9c052ff8dd6a 108
Wayne Roberts 0:9c052ff8dd6a 109 {
Wayne Roberts 0:9c052ff8dd6a 110 LoRaPktPar0_t LoRaPktPar0;
Wayne Roberts 0:9c052ff8dd6a 111 LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
Wayne Roberts 0:9c052ff8dd6a 112 switch (LoRaPktPar0.bits.modem_bw) {
Wayne Roberts 0:9c052ff8dd6a 113 case 2: mpLORA.lora.bandwidth = LORA_BW_200; break;
Wayne Roberts 0:9c052ff8dd6a 114 case 3: mpLORA.lora.bandwidth = LORA_BW_400; break;
Wayne Roberts 0:9c052ff8dd6a 115 case 4: mpLORA.lora.bandwidth = LORA_BW_800; break;
Wayne Roberts 0:9c052ff8dd6a 116 case 5: mpLORA.lora.bandwidth = LORA_BW_1600; break;
Wayne Roberts 0:9c052ff8dd6a 117 }
Wayne Roberts 0:9c052ff8dd6a 118 mpLORA.lora.spreadingFactor = LoRaPktPar0.bits.modem_sf << 4;
Wayne Roberts 0:9c052ff8dd6a 119 }
Wayne Roberts 0:9c052ff8dd6a 120
Wayne Roberts 0:9c052ff8dd6a 121 {
Wayne Roberts 0:9c052ff8dd6a 122 LoRaPktPar1_t LoRaPktPar1;
Wayne Roberts 0:9c052ff8dd6a 123 LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
Wayne Roberts 0:9c052ff8dd6a 124 mpLORA.lora.codingRate = LoRaPktPar1.bits.coding_rate;
Wayne Roberts 1:e79b0a55135f 125 ppLORA.lora.InvertIQ = LoRaPktPar1.octet & LORA_IQ_STD; // LoRaPktPar1.bits.rxinvert_iq
Wayne Roberts 1:e79b0a55135f 126 ppLORA.lora.HeaderType = LoRaPktPar1.bits.implicit_header ? IMPLICIT_HEADER : EXPLICIT_HEADER;
Wayne Roberts 0:9c052ff8dd6a 127 // LoRaPktPar1.bits.ppm_offset
Wayne Roberts 0:9c052ff8dd6a 128 }
Wayne Roberts 0:9c052ff8dd6a 129
Wayne Roberts 0:9c052ff8dd6a 130 {
Wayne Roberts 0:9c052ff8dd6a 131 LoRaPreambleReg_t LoRaPreambleReg;
Wayne Roberts 0:9c052ff8dd6a 132 LoRaPreambleReg.octet = radio.readReg(REG_ADDR_LORA_PREAMBLE, 1);
Wayne Roberts 0:9c052ff8dd6a 133 ppLORA.lora.PreambleLength = LoRaPreambleReg.bits.preamble_symb1_nb * (1 << LoRaPreambleReg.bits.preamble_symb_nb_exp);
Wayne Roberts 0:9c052ff8dd6a 134 }
Wayne Roberts 0:9c052ff8dd6a 135 ppLORA.lora.PayloadLength = radio.readReg(REG_ADDR_LORA_TX_PAYLOAD_LENGTH, 1);
Wayne Roberts 0:9c052ff8dd6a 136
Wayne Roberts 0:9c052ff8dd6a 137 {
Wayne Roberts 0:9c052ff8dd6a 138 LoRaLrCtl_t LoRaLrCtl;
Wayne Roberts 0:9c052ff8dd6a 139 LoRaLrCtl.octet = radio.readReg(REG_ADDR_LORA_LRCTL, 1);
Wayne Roberts 0:9c052ff8dd6a 140 ppLORA.lora.crc = LoRaLrCtl.octet & 0x20; // LoRaLrCtl.bits.crc_en
Wayne Roberts 0:9c052ff8dd6a 141 }
Wayne Roberts 0:9c052ff8dd6a 142
Wayne Roberts 0:9c052ff8dd6a 143 {
Wayne Roberts 0:9c052ff8dd6a 144 RegRxBw_t RegRxBw;
Wayne Roberts 0:9c052ff8dd6a 145 unsigned bps;
Wayne Roberts 0:9c052ff8dd6a 146 FloraPreambleHi_t FloraPreambleHi;
Wayne Roberts 0:9c052ff8dd6a 147 float mi, fdev_hz;
Wayne Roberts 0:9c052ff8dd6a 148 unsigned freqDev;
Wayne Roberts 0:9c052ff8dd6a 149 FskModDfH_t FskModDfH;
Wayne Roberts 0:9c052ff8dd6a 150 FskModDfH.octet = radio.readReg(REG_ADDR_FSK_MODDFH, 1);
Wayne Roberts 0:9c052ff8dd6a 151 freqDev = FskModDfH.bits.freqDev;
Wayne Roberts 0:9c052ff8dd6a 152 freqDev <<= 8;
Wayne Roberts 0:9c052ff8dd6a 153 freqDev |= radio.readReg(REG_ADDR_FSK_MODDFL, 1);
Wayne Roberts 0:9c052ff8dd6a 154 fdev_hz = freqDev * PLL_STEP_HZ;
Wayne Roberts 0:9c052ff8dd6a 155
Wayne Roberts 0:9c052ff8dd6a 156 FloraPreambleHi.octet = radio.readReg(REG_ADDR_FLORA_PREAMBLE_HI, 1);
Wayne Roberts 0:9c052ff8dd6a 157 switch (FloraPreambleHi.bits.data_rate) {
Wayne Roberts 0:9c052ff8dd6a 158 case 0:
Wayne Roberts 0:9c052ff8dd6a 159 bps = 2.0e6;
Wayne Roberts 0:9c052ff8dd6a 160 //mpFLRC.flrc.bitrateBandwidth = ??; // 2.6
Wayne Roberts 0:9c052ff8dd6a 161 break;
Wayne Roberts 0:9c052ff8dd6a 162 case 1:
Wayne Roberts 0:9c052ff8dd6a 163 bps = 1.6e6;
Wayne Roberts 0:9c052ff8dd6a 164 //mpFLRC.flrc.bitrateBandwidth = ??; // 2.08
Wayne Roberts 0:9c052ff8dd6a 165 break;
Wayne Roberts 0:9c052ff8dd6a 166 case 2:
Wayne Roberts 0:9c052ff8dd6a 167 bps = 1.0e6;
Wayne Roberts 0:9c052ff8dd6a 168 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_300_BW_1_2; // 1.3
Wayne Roberts 0:9c052ff8dd6a 169 break;
Wayne Roberts 0:9c052ff8dd6a 170 case 3:
Wayne Roberts 0:9c052ff8dd6a 171 bps = 0.8e6;
Wayne Roberts 0:9c052ff8dd6a 172 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_1_000_BW_1_2; // 1.04
Wayne Roberts 0:9c052ff8dd6a 173 break;
Wayne Roberts 0:9c052ff8dd6a 174 case 4:
Wayne Roberts 0:9c052ff8dd6a 175 bps = 0.5e6;
Wayne Roberts 0:9c052ff8dd6a 176 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_650_BW_0_6; // 0.65
Wayne Roberts 0:9c052ff8dd6a 177 break;
Wayne Roberts 0:9c052ff8dd6a 178 case 5:
Wayne Roberts 0:9c052ff8dd6a 179 bps = 0.4e6;
Wayne Roberts 0:9c052ff8dd6a 180 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_520_BW_0_6; // 0.52
Wayne Roberts 0:9c052ff8dd6a 181 break;
Wayne Roberts 0:9c052ff8dd6a 182 case 6:
Wayne Roberts 0:9c052ff8dd6a 183 bps = 0.25e6;
Wayne Roberts 0:9c052ff8dd6a 184 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_325_BW_0_3; // 0.325
Wayne Roberts 0:9c052ff8dd6a 185 break;
Wayne Roberts 0:9c052ff8dd6a 186 case 7:
Wayne Roberts 0:9c052ff8dd6a 187 bps = 0.125e6;
Wayne Roberts 0:9c052ff8dd6a 188 mpFLRC.flrc.bitrateBandwidth = FLRC_BR_0_260_BW_0_3; // 0.26
Wayne Roberts 0:9c052ff8dd6a 189 break;
Wayne Roberts 0:9c052ff8dd6a 190 }
Wayne Roberts 0:9c052ff8dd6a 191
Wayne Roberts 0:9c052ff8dd6a 192 mi = (fdev_hz * 2.0) / bps;
Wayne Roberts 0:9c052ff8dd6a 193 if (mi > 0.35) {
Wayne Roberts 0:9c052ff8dd6a 194 mi -= 0.5;
Wayne Roberts 0:9c052ff8dd6a 195 mi /= 0.25;
Wayne Roberts 0:9c052ff8dd6a 196 mpBLE_GFSK.gfskBle.ModulationIndex = ((uint8_t)mi) + 1;
Wayne Roberts 0:9c052ff8dd6a 197 } else
Wayne Roberts 0:9c052ff8dd6a 198 mpBLE_GFSK.gfskBle.ModulationIndex = 0;
Wayne Roberts 0:9c052ff8dd6a 199
Wayne Roberts 0:9c052ff8dd6a 200 RegRxBw.octet = radio.readReg(REG_ADDR_RXBW, 1);
Wayne Roberts 0:9c052ff8dd6a 201
Wayne Roberts 0:9c052ff8dd6a 202 switch (RegRxBw.bits.bw) {
Wayne Roberts 0:9c052ff8dd6a 203 case 0:
Wayne Roberts 0:9c052ff8dd6a 204 if (FloraPreambleHi.bits.data_rate == 0)
Wayne Roberts 0:9c052ff8dd6a 205 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_2_000_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 206 if (FloraPreambleHi.bits.data_rate == 1)
Wayne Roberts 0:9c052ff8dd6a 207 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_600_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 208 if (FloraPreambleHi.bits.data_rate == 2)
Wayne Roberts 0:9c052ff8dd6a 209 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 210 if (FloraPreambleHi.bits.data_rate == 3)
Wayne Roberts 0:9c052ff8dd6a 211 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 212 break;
Wayne Roberts 0:9c052ff8dd6a 213 case 1:
Wayne Roberts 0:9c052ff8dd6a 214 if (FloraPreambleHi.bits.data_rate == 2)
Wayne Roberts 0:9c052ff8dd6a 215 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_1_000_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 216 if (FloraPreambleHi.bits.data_rate == 3)
Wayne Roberts 0:9c052ff8dd6a 217 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_800_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 218 if (FloraPreambleHi.bits.data_rate == 4)
Wayne Roberts 0:9c052ff8dd6a 219 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 220 if (FloraPreambleHi.bits.data_rate == 5)
Wayne Roberts 0:9c052ff8dd6a 221 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 222 break;
Wayne Roberts 0:9c052ff8dd6a 223 case 2:
Wayne Roberts 0:9c052ff8dd6a 224 if (FloraPreambleHi.bits.data_rate == 4)
Wayne Roberts 0:9c052ff8dd6a 225 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_500_BW_0_6;
Wayne Roberts 0:9c052ff8dd6a 226 if (FloraPreambleHi.bits.data_rate == 5)
Wayne Roberts 0:9c052ff8dd6a 227 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_400_BW_0_6;
Wayne Roberts 0:9c052ff8dd6a 228 if (FloraPreambleHi.bits.data_rate == 6)
Wayne Roberts 0:9c052ff8dd6a 229 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_6;
Wayne Roberts 0:9c052ff8dd6a 230 break;
Wayne Roberts 0:9c052ff8dd6a 231 case 3:
Wayne Roberts 0:9c052ff8dd6a 232 if (FloraPreambleHi.bits.data_rate == 6)
Wayne Roberts 0:9c052ff8dd6a 233 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_250_BW_0_3;
Wayne Roberts 0:9c052ff8dd6a 234 if (FloraPreambleHi.bits.data_rate == 7)
Wayne Roberts 0:9c052ff8dd6a 235 mpBLE_GFSK.gfskBle.bitrateBandwidth = GFSK_BLE_BR_0_125_BW_0_3;
Wayne Roberts 0:9c052ff8dd6a 236 break;
Wayne Roberts 0:9c052ff8dd6a 237 }
Wayne Roberts 0:9c052ff8dd6a 238 mpBLE_GFSK.gfskBle.bitrateBandwidth = reg8;
Wayne Roberts 0:9c052ff8dd6a 239 }
Wayne Roberts 0:9c052ff8dd6a 240
Wayne Roberts 0:9c052ff8dd6a 241 {
Wayne Roberts 0:9c052ff8dd6a 242 FskCfg_t FskCfg;
Wayne Roberts 0:9c052ff8dd6a 243 FskCfg.octet = radio.readReg(REG_ADDR_FSK_CFG, 1);
Wayne Roberts 0:9c052ff8dd6a 244 mpBLE_GFSK.gfskBle.ModulationShaping = FskCfg.bits.gf_bt << 4;
Wayne Roberts 0:9c052ff8dd6a 245 mpFLRC.flrc.ModulationShaping = mpBLE_GFSK.gfskBle.ModulationShaping;
Wayne Roberts 0:9c052ff8dd6a 246 }
Wayne Roberts 0:9c052ff8dd6a 247
Wayne Roberts 0:9c052ff8dd6a 248 {
Wayne Roberts 0:9c052ff8dd6a 249 PktBitStreamCtrl_t PktBitStreamCtrl;
Wayne Roberts 0:9c052ff8dd6a 250 PktBitStreamCtrl.octet = radio.readReg(REG_ADDR_PKT_BITSTREAM_CTRL, 1);
Wayne Roberts 0:9c052ff8dd6a 251 mpFLRC.flrc.CodingRate = PktBitStreamCtrl.octet & 0x06; // PktBitStreamCtrl.bits.flora_coding_rate
Wayne Roberts 0:9c052ff8dd6a 252 }
Wayne Roberts 0:9c052ff8dd6a 253
Wayne Roberts 0:9c052ff8dd6a 254 }
Wayne Roberts 0:9c052ff8dd6a 255
Wayne Roberts 0:9c052ff8dd6a 256 void Radio:: diox_top_half()
Wayne Roberts 0:9c052ff8dd6a 257 {
Wayne Roberts 20:75635d50262e 258 #if (MBED_MAJOR_VERSION < 6)
Wayne Roberts 0:9c052ff8dd6a 259 irqAt = lpt.read_us();
Wayne Roberts 20:75635d50262e 260 #else
Wayne Roberts 20:75635d50262e 261 irqAt = LowPowerClock::now();
Wayne Roberts 20:75635d50262e 262 #endif
Wayne Roberts 0:9c052ff8dd6a 263
Wayne Roberts 14:94993ae5b164 264 if (RadioEvents->DioPin_top_half)
Wayne Roberts 14:94993ae5b164 265 RadioEvents->DioPin_top_half();
Wayne Roberts 14:94993ae5b164 266
Wayne Roberts 0:9c052ff8dd6a 267 if (radio.chipMode == CHIPMODE_TX) {
Wayne Roberts 0:9c052ff8dd6a 268 /* TxDone handling requires low latency */
Wayne Roberts 0:9c052ff8dd6a 269 if (RadioEvents->TxDone_topHalf) {
Wayne Roberts 0:9c052ff8dd6a 270 RadioEvents->TxDone_topHalf();
Wayne Roberts 0:9c052ff8dd6a 271 }
Wayne Roberts 7:ba81f66e56d1 272 } else {
Wayne Roberts 7:ba81f66e56d1 273 #ifdef RX_INDICATION
Wayne Roberts 7:ba81f66e56d1 274 RX_INDICATION = 0;
Wayne Roberts 7:ba81f66e56d1 275 #endif
Wayne Roberts 0:9c052ff8dd6a 276 }
Wayne Roberts 0:9c052ff8dd6a 277 }
Wayne Roberts 0:9c052ff8dd6a 278
Wayne Roberts 0:9c052ff8dd6a 279 void Radio::rxDone(uint8_t size, const pktStatus_t* pktStatus)
Wayne Roberts 0:9c052ff8dd6a 280 {
Wayne Roberts 0:9c052ff8dd6a 281 float rssi, snr;
Wayne Roberts 0:9c052ff8dd6a 282
Wayne Roberts 0:9c052ff8dd6a 283 if (pktStatus->ble_gfsk_flrc.sync.syncAddrsCode == 0) {
Wayne Roberts 0:9c052ff8dd6a 284 int8_t s = pktStatus->lora.snr;
Wayne Roberts 0:9c052ff8dd6a 285 rssi = -pktStatus->lora.rssiSync / 2.0;
Wayne Roberts 0:9c052ff8dd6a 286 snr = s / 4.0;
Wayne Roberts 0:9c052ff8dd6a 287 } else {
Wayne Roberts 0:9c052ff8dd6a 288 rssi = -pktStatus->ble_gfsk_flrc.rssiSync / 2.0;
Wayne Roberts 0:9c052ff8dd6a 289 snr = FLT_MIN;
Wayne Roberts 0:9c052ff8dd6a 290 }
Wayne Roberts 0:9c052ff8dd6a 291
Wayne Roberts 0:9c052ff8dd6a 292 RadioEvents->RxDone(size, rssi, snr);
Wayne Roberts 0:9c052ff8dd6a 293 }
Wayne Roberts 0:9c052ff8dd6a 294
Wayne Roberts 0:9c052ff8dd6a 295 void Radio::timeout_callback(bool tx)
Wayne Roberts 0:9c052ff8dd6a 296 {
Wayne Roberts 0:9c052ff8dd6a 297 if (!tx) {
Wayne Roberts 0:9c052ff8dd6a 298 if (RadioEvents->RxTimeout)
Wayne Roberts 0:9c052ff8dd6a 299 RadioEvents->RxTimeout();
Wayne Roberts 7:ba81f66e56d1 300 #ifdef RX_INDICATION
Wayne Roberts 7:ba81f66e56d1 301 RX_INDICATION = 0;
Wayne Roberts 7:ba81f66e56d1 302 #endif
Wayne Roberts 17:5f34cbe2ac53 303 } // else TODO tx timeout
Wayne Roberts 0:9c052ff8dd6a 304 }
Wayne Roberts 0:9c052ff8dd6a 305
Wayne Roberts 0:9c052ff8dd6a 306 void Radio::txDoneBottom()
Wayne Roberts 0:9c052ff8dd6a 307 {
Wayne Roberts 0:9c052ff8dd6a 308 if (RadioEvents->TxDone_botHalf)
Wayne Roberts 0:9c052ff8dd6a 309 RadioEvents->TxDone_botHalf();
Wayne Roberts 0:9c052ff8dd6a 310 }
Wayne Roberts 0:9c052ff8dd6a 311
Wayne Roberts 13:a354f82d12d9 312 void Radio::Init(const RadioEvents_t* e, unsigned spi_hz)
Wayne Roberts 0:9c052ff8dd6a 313 {
Wayne Roberts 0:9c052ff8dd6a 314 uint64_t sa;
Wayne Roberts 0:9c052ff8dd6a 315
Wayne Roberts 0:9c052ff8dd6a 316 radio.txDone = txDoneBottom;
Wayne Roberts 0:9c052ff8dd6a 317 radio.rxDone = rxDone;
Wayne Roberts 0:9c052ff8dd6a 318 radio.timeout = timeout_callback;
Wayne Roberts 0:9c052ff8dd6a 319 radio.chipModeChange = chipModeChange;
Wayne Roberts 0:9c052ff8dd6a 320 radio.diox_topHalf = diox_top_half;
Wayne Roberts 0:9c052ff8dd6a 321
Wayne Roberts 13:a354f82d12d9 322 spi.frequency(spi_hz);
Wayne Roberts 0:9c052ff8dd6a 323 readChip();
Wayne Roberts 0:9c052ff8dd6a 324
Wayne Roberts 0:9c052ff8dd6a 325 radio.setRegulator(0); // default to LDO
Wayne Roberts 0:9c052ff8dd6a 326
Wayne Roberts 0:9c052ff8dd6a 327 sa = 0xc194c1;
Wayne Roberts 0:9c052ff8dd6a 328 radio.setSyncAddr(1, sa);
Wayne Roberts 0:9c052ff8dd6a 329
Wayne Roberts 0:9c052ff8dd6a 330 RadioEvents = e;
Wayne Roberts 0:9c052ff8dd6a 331 lpt.start();
Wayne Roberts 0:9c052ff8dd6a 332
Wayne Roberts 0:9c052ff8dd6a 333 fe_enable = true;
Wayne Roberts 0:9c052ff8dd6a 334
Wayne Roberts 0:9c052ff8dd6a 335 radio.periodBase = 2; // 1ms resolution
Wayne Roberts 9:97a6de3dbc86 336 nSymbs = 8;
Wayne Roberts 0:9c052ff8dd6a 337 }
Wayne Roberts 0:9c052ff8dd6a 338
Wayne Roberts 7:ba81f66e56d1 339 float Radio::GetRssiInst()
Wayne Roberts 7:ba81f66e56d1 340 {
Wayne Roberts 7:ba81f66e56d1 341 uint8_t buf[2];
Wayne Roberts 7:ba81f66e56d1 342 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf);
Wayne Roberts 7:ba81f66e56d1 343 return buf[1] / -2.0;
Wayne Roberts 7:ba81f66e56d1 344 }
Wayne Roberts 7:ba81f66e56d1 345
Wayne Roberts 0:9c052ff8dd6a 346 int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh)
Wayne Roberts 0:9c052ff8dd6a 347 {
Wayne Roberts 0:9c052ff8dd6a 348 uint8_t buf[8];
Wayne Roberts 1:e79b0a55135f 349 uint8_t pktType = radio.getPacketType();
Wayne Roberts 0:9c052ff8dd6a 350
Wayne Roberts 1:e79b0a55135f 351 if (pktType == PACKET_TYPE_LORA) {
Wayne Roberts 1:e79b0a55135f 352 ppLORA.lora.PayloadLength = size;
Wayne Roberts 1:e79b0a55135f 353 radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf);
Wayne Roberts 1:e79b0a55135f 354 } else if (pktType == PACKET_TYPE_GFSK) {
Wayne Roberts 0:9c052ff8dd6a 355 ppGFSK.gfskFLRC.PayloadLength = size;
Wayne Roberts 0:9c052ff8dd6a 356 radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
Wayne Roberts 0:9c052ff8dd6a 357 }
Wayne Roberts 0:9c052ff8dd6a 358
Wayne Roberts 0:9c052ff8dd6a 359 if (maxListenTime > 0) {
Wayne Roberts 0:9c052ff8dd6a 360 int rssi;
Wayne Roberts 0:9c052ff8dd6a 361 us_timestamp_t startAt, chFreeAt, now;
Wayne Roberts 0:9c052ff8dd6a 362 radio.start_rx(-1);
Wayne Roberts 20:75635d50262e 363 #if (MBED_MAJOR_VERSION < 6)
Wayne Roberts 0:9c052ff8dd6a 364 startAt = lpt.read_us();
Wayne Roberts 20:75635d50262e 365 #else
Wayne Roberts 20:75635d50262e 366 startAt = LowPowerClock::now().time_since_epoch().count();
Wayne Roberts 20:75635d50262e 367 #endif
Wayne Roberts 0:9c052ff8dd6a 368 Lstart:
Wayne Roberts 0:9c052ff8dd6a 369 do {
Wayne Roberts 20:75635d50262e 370 #if (MBED_MAJOR_VERSION < 6)
Wayne Roberts 0:9c052ff8dd6a 371 now = lpt.read_us();
Wayne Roberts 20:75635d50262e 372 #else
Wayne Roberts 20:75635d50262e 373 now = LowPowerClock::now().time_since_epoch().count();
Wayne Roberts 20:75635d50262e 374 #endif
Wayne Roberts 0:9c052ff8dd6a 375 if ((now - startAt) > maxListenTime) {
Wayne Roberts 0:9c052ff8dd6a 376 return -1;
Wayne Roberts 0:9c052ff8dd6a 377 }
Wayne Roberts 0:9c052ff8dd6a 378 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf);
Wayne Roberts 0:9c052ff8dd6a 379 rssi = buf[1] / -2;
Wayne Roberts 0:9c052ff8dd6a 380 } while (rssi > rssiThresh);
Wayne Roberts 20:75635d50262e 381 #if (MBED_MAJOR_VERSION < 6)
Wayne Roberts 0:9c052ff8dd6a 382 chFreeAt = lpt.read_us();
Wayne Roberts 20:75635d50262e 383 #else
Wayne Roberts 20:75635d50262e 384 chFreeAt = LowPowerClock::now().time_since_epoch().count();
Wayne Roberts 20:75635d50262e 385 #endif
Wayne Roberts 0:9c052ff8dd6a 386 do {
Wayne Roberts 20:75635d50262e 387 #if (MBED_MAJOR_VERSION < 6)
Wayne Roberts 0:9c052ff8dd6a 388 now = lpt.read_us();
Wayne Roberts 20:75635d50262e 389 #else
Wayne Roberts 20:75635d50262e 390 now = LowPowerClock::now().time_since_epoch().count();
Wayne Roberts 20:75635d50262e 391 #endif
Wayne Roberts 0:9c052ff8dd6a 392 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf);
Wayne Roberts 0:9c052ff8dd6a 393 rssi = buf[1] / -2;
Wayne Roberts 0:9c052ff8dd6a 394 if (rssi > rssiThresh) {
Wayne Roberts 0:9c052ff8dd6a 395 goto Lstart;
Wayne Roberts 0:9c052ff8dd6a 396 }
Wayne Roberts 0:9c052ff8dd6a 397 } while ((now - chFreeAt) < channelFreeTime);
Wayne Roberts 0:9c052ff8dd6a 398 }
Wayne Roberts 0:9c052ff8dd6a 399
Wayne Roberts 0:9c052ff8dd6a 400 radio.start_tx(size, 4000);
Wayne Roberts 0:9c052ff8dd6a 401
Wayne Roberts 0:9c052ff8dd6a 402 return 0;
Wayne Roberts 0:9c052ff8dd6a 403 }
Wayne Roberts 0:9c052ff8dd6a 404
Wayne Roberts 0:9c052ff8dd6a 405 void Radio::service()
Wayne Roberts 0:9c052ff8dd6a 406 {
Wayne Roberts 0:9c052ff8dd6a 407 radio.service();
Wayne Roberts 0:9c052ff8dd6a 408 }
Wayne Roberts 0:9c052ff8dd6a 409
Wayne Roberts 0:9c052ff8dd6a 410 bool Radio::CheckRfFrequency(unsigned hz)
Wayne Roberts 0:9c052ff8dd6a 411 {
Wayne Roberts 0:9c052ff8dd6a 412 return true;
Wayne Roberts 0:9c052ff8dd6a 413 }
Wayne Roberts 0:9c052ff8dd6a 414
Wayne Roberts 0:9c052ff8dd6a 415 void Radio::Sleep()
Wayne Roberts 0:9c052ff8dd6a 416 {
Wayne Roberts 0:9c052ff8dd6a 417 radio.setSleep(true);
Wayne Roberts 0:9c052ff8dd6a 418 }
Wayne Roberts 0:9c052ff8dd6a 419
Wayne Roberts 0:9c052ff8dd6a 420 void Radio::SetPublicNetwork(bool en)
Wayne Roberts 0:9c052ff8dd6a 421 {
Wayne Roberts 8:0518c6e68b79 422 /* uint16_t ppg;
Wayne Roberts 0:9c052ff8dd6a 423
Wayne Roberts 0:9c052ff8dd6a 424 if (en)
Wayne Roberts 0:9c052ff8dd6a 425 ppg = 0x3444;
Wayne Roberts 0:9c052ff8dd6a 426 else
Wayne Roberts 0:9c052ff8dd6a 427 ppg = 0x1424;
Wayne Roberts 0:9c052ff8dd6a 428
Wayne Roberts 0:9c052ff8dd6a 429 radio.writeReg(REG_ADDR_LORA_SYNC, ppg, 2);
Wayne Roberts 8:0518c6e68b79 430 */
Wayne Roberts 0:9c052ff8dd6a 431 }
Wayne Roberts 0:9c052ff8dd6a 432
Wayne Roberts 0:9c052ff8dd6a 433 uint32_t Radio::lora_toa_us( uint8_t pktLen )
Wayne Roberts 0:9c052ff8dd6a 434 {
Wayne Roberts 0:9c052ff8dd6a 435 double bwKHz;
Wayne Roberts 0:9c052ff8dd6a 436 LoRaPktPar0_t LoRaPktPar0;
Wayne Roberts 0:9c052ff8dd6a 437 LoRaLrCtl_t LoRaLrCtl;
Wayne Roberts 0:9c052ff8dd6a 438 LoRaPktPar1_t LoRaPktPar1;
Wayne Roberts 0:9c052ff8dd6a 439 uint8_t LowDatarateOptimize;
Wayne Roberts 0:9c052ff8dd6a 440
Wayne Roberts 0:9c052ff8dd6a 441 {
Wayne Roberts 0:9c052ff8dd6a 442 LoRaPktPar1.octet = radio.readReg(REG_ADDR_LORA_PKTPAR1, 1);
Wayne Roberts 0:9c052ff8dd6a 443 LowDatarateOptimize = LoRaPktPar1.bits.ppm_offset ? 1 : 0;
Wayne Roberts 1:e79b0a55135f 444 ppLORA.lora.HeaderType = LoRaPktPar1.bits.implicit_header ? IMPLICIT_HEADER : EXPLICIT_HEADER;
Wayne Roberts 1:e79b0a55135f 445 ppLORA.lora.InvertIQ = LoRaPktPar1.octet & LORA_IQ_STD; // LoRaPktPar1.bits.rxinvert_iq
Wayne Roberts 0:9c052ff8dd6a 446 mpLORA.lora.codingRate = LoRaPktPar1.bits.coding_rate;
Wayne Roberts 0:9c052ff8dd6a 447 }
Wayne Roberts 0:9c052ff8dd6a 448
Wayne Roberts 0:9c052ff8dd6a 449 {
Wayne Roberts 0:9c052ff8dd6a 450 LoRaLrCtl.octet = radio.readReg(REG_ADDR_LORA_LRCTL, 1);
Wayne Roberts 0:9c052ff8dd6a 451 ppLORA.lora.crc = LoRaLrCtl.octet & 0x20; // LoRaLrCtl.bits.crc_en
Wayne Roberts 0:9c052ff8dd6a 452 }
Wayne Roberts 0:9c052ff8dd6a 453
Wayne Roberts 0:9c052ff8dd6a 454 {
Wayne Roberts 0:9c052ff8dd6a 455 LoRaPreambleReg_t LoRaPreambleReg;
Wayne Roberts 0:9c052ff8dd6a 456 LoRaPreambleReg.octet = radio.readReg(REG_ADDR_LORA_PREAMBLE, 1);
Wayne Roberts 0:9c052ff8dd6a 457 ppLORA.lora.PreambleLength = LoRaPreambleReg.bits.preamble_symb1_nb * (1 << LoRaPreambleReg.bits.preamble_symb_nb_exp);
Wayne Roberts 0:9c052ff8dd6a 458 }
Wayne Roberts 0:9c052ff8dd6a 459
Wayne Roberts 0:9c052ff8dd6a 460 {
Wayne Roberts 0:9c052ff8dd6a 461 LoRaPktPar0.octet = radio.readReg(REG_ADDR_LORA_PKTPAR0, 1);
Wayne Roberts 0:9c052ff8dd6a 462 switch (LoRaPktPar0.bits.modem_bw) {
Wayne Roberts 0:9c052ff8dd6a 463 case 0: bwKHz = 50; break;
Wayne Roberts 0:9c052ff8dd6a 464 case 1: bwKHz = 100; break;
Wayne Roberts 0:9c052ff8dd6a 465 case 2: mpLORA.lora.bandwidth = LORA_BW_200; bwKHz = 200; break;
Wayne Roberts 0:9c052ff8dd6a 466 case 3: mpLORA.lora.bandwidth = LORA_BW_400; bwKHz = 400; break;
Wayne Roberts 0:9c052ff8dd6a 467 case 4: mpLORA.lora.bandwidth = LORA_BW_800; bwKHz = 800; break;
Wayne Roberts 0:9c052ff8dd6a 468 case 5: mpLORA.lora.bandwidth = LORA_BW_1600; bwKHz = 1600; break;
Wayne Roberts 0:9c052ff8dd6a 469 default: bwKHz = 0; break;
Wayne Roberts 0:9c052ff8dd6a 470 }
Wayne Roberts 0:9c052ff8dd6a 471 mpLORA.lora.spreadingFactor = LoRaPktPar0.bits.modem_sf << 4;
Wayne Roberts 0:9c052ff8dd6a 472 }
Wayne Roberts 0:9c052ff8dd6a 473
Wayne Roberts 0:9c052ff8dd6a 474 // Symbol rate : time for one symbol (secs)
Wayne Roberts 0:9c052ff8dd6a 475 double rs = bwKHz / (1 << LoRaPktPar0.bits.modem_sf);
Wayne Roberts 0:9c052ff8dd6a 476 double ts = 1 / rs;
Wayne Roberts 0:9c052ff8dd6a 477 // time of preamble
Wayne Roberts 0:9c052ff8dd6a 478 //
Wayne Roberts 0:9c052ff8dd6a 479 double tPreamble = ( ppLORA.lora.PreambleLength + 4.25 ) * ts;
Wayne Roberts 0:9c052ff8dd6a 480 // Symbol length of payload and time
Wayne Roberts 0:9c052ff8dd6a 481
Wayne Roberts 0:9c052ff8dd6a 482 double tmp = ceil( ( 8 * pktLen - 4 * LoRaPktPar0.bits.modem_sf +
Wayne Roberts 0:9c052ff8dd6a 483 28 + 16 * LoRaLrCtl.bits.crc_en -
Wayne Roberts 0:9c052ff8dd6a 484 ( LoRaPktPar1.bits.implicit_header ? 20 : 0 ) ) /
Wayne Roberts 0:9c052ff8dd6a 485 ( double )( 4 * ( LoRaPktPar0.bits.modem_sf -
Wayne Roberts 0:9c052ff8dd6a 486 ( ( LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) *
Wayne Roberts 0:9c052ff8dd6a 487 ( LoRaPktPar1.bits.coding_rate + 4 );
Wayne Roberts 0:9c052ff8dd6a 488
Wayne Roberts 0:9c052ff8dd6a 489 double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 );
Wayne Roberts 0:9c052ff8dd6a 490 double tPayload = nPayload * ts;
Wayne Roberts 0:9c052ff8dd6a 491 // Time on air
Wayne Roberts 0:9c052ff8dd6a 492 double tOnAir = tPreamble + tPayload;
Wayne Roberts 0:9c052ff8dd6a 493 // return microseconds
Wayne Roberts 0:9c052ff8dd6a 494 return floor( tOnAir * 1000 + 0.999 );
Wayne Roberts 0:9c052ff8dd6a 495 }
Wayne Roberts 0:9c052ff8dd6a 496
Wayne Roberts 0:9c052ff8dd6a 497 void Radio::GFSKModemConfig(unsigned bps, unsigned bw_hz, unsigned fdev_hz)
Wayne Roberts 0:9c052ff8dd6a 498 {
Wayne Roberts 0:9c052ff8dd6a 499 uint8_t u8;
Wayne Roberts 0:9c052ff8dd6a 500 float mi, Mbps = bps / 1000000.0;
Wayne Roberts 0:9c052ff8dd6a 501
Wayne Roberts 0:9c052ff8dd6a 502 if (Mbps > 1.6) {
Wayne Roberts 0:9c052ff8dd6a 503 /* 2.0Mbps */
Wayne Roberts 0:9c052ff8dd6a 504 u8 = GFSK_BLE_BR_2_000_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 505 } else if (Mbps > 1.0) {
Wayne Roberts 0:9c052ff8dd6a 506 /* 1.6Mbps */
Wayne Roberts 0:9c052ff8dd6a 507 u8 = GFSK_BLE_BR_1_600_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 508 } else if (Mbps > 0.8) {
Wayne Roberts 0:9c052ff8dd6a 509 /* 1.0Mbps */
Wayne Roberts 0:9c052ff8dd6a 510 /*if (bwMHz > 1.2)
Wayne Roberts 0:9c052ff8dd6a 511 u8 = GFSK_BLE_BR_1_000_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 512 else*/
Wayne Roberts 0:9c052ff8dd6a 513 u8 = GFSK_BLE_BR_1_000_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 514 } else if (Mbps > 0.5) {
Wayne Roberts 0:9c052ff8dd6a 515 /* 0.8Mbps */
Wayne Roberts 0:9c052ff8dd6a 516 /*if (bwMHz > 1.2)
Wayne Roberts 0:9c052ff8dd6a 517 u8 = GFSK_BLE_BR_0_800_BW_2_4;
Wayne Roberts 0:9c052ff8dd6a 518 else*/
Wayne Roberts 0:9c052ff8dd6a 519 u8 = GFSK_BLE_BR_0_800_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 520 } else if (Mbps > 0.4) {
Wayne Roberts 0:9c052ff8dd6a 521 /* 0.5Mbps */
Wayne Roberts 0:9c052ff8dd6a 522 /*if (bwMHz > 0.6)
Wayne Roberts 0:9c052ff8dd6a 523 u8 = GFSK_BLE_BR_0_500_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 524 else*/
Wayne Roberts 0:9c052ff8dd6a 525 u8 = GFSK_BLE_BR_0_500_BW_0_6;
Wayne Roberts 0:9c052ff8dd6a 526 } else if (Mbps > 0.25) {
Wayne Roberts 0:9c052ff8dd6a 527 /* 0.4Mbps */
Wayne Roberts 0:9c052ff8dd6a 528 /*if (bwMHz > 0.6)
Wayne Roberts 0:9c052ff8dd6a 529 u8 = GFSK_BLE_BR_0_400_BW_1_2;
Wayne Roberts 0:9c052ff8dd6a 530 else*/
Wayne Roberts 0:9c052ff8dd6a 531 u8 = GFSK_BLE_BR_0_400_BW_0_6;
Wayne Roberts 0:9c052ff8dd6a 532 } else if (Mbps > 0.125) {
Wayne Roberts 0:9c052ff8dd6a 533 /* 0.25Mbps */
Wayne Roberts 0:9c052ff8dd6a 534 /*if (bwMHz > 0.3)
Wayne Roberts 0:9c052ff8dd6a 535 u8 = GFSK_BLE_BR_0_250_BW_0_6;
Wayne Roberts 0:9c052ff8dd6a 536 else*/
Wayne Roberts 0:9c052ff8dd6a 537 u8 = GFSK_BLE_BR_0_250_BW_0_3;
Wayne Roberts 0:9c052ff8dd6a 538 } else {
Wayne Roberts 0:9c052ff8dd6a 539 /* 0.125Mbps */
Wayne Roberts 0:9c052ff8dd6a 540 u8 = GFSK_BLE_BR_0_125_BW_0_3;
Wayne Roberts 0:9c052ff8dd6a 541 }
Wayne Roberts 0:9c052ff8dd6a 542
Wayne Roberts 0:9c052ff8dd6a 543 mpBLE_GFSK.gfskBle.bitrateBandwidth = u8;
Wayne Roberts 0:9c052ff8dd6a 544
Wayne Roberts 0:9c052ff8dd6a 545 mpBLE_GFSK.gfskBle.ModulationShaping = BT_OFF;
Wayne Roberts 0:9c052ff8dd6a 546
Wayne Roberts 0:9c052ff8dd6a 547 mi = (fdev_hz * 2.0) / bps;
Wayne Roberts 0:9c052ff8dd6a 548 if (mi > 0.35) {
Wayne Roberts 0:9c052ff8dd6a 549 mi -= 0.5;
Wayne Roberts 0:9c052ff8dd6a 550 mi /= 0.25;
Wayne Roberts 0:9c052ff8dd6a 551 mpBLE_GFSK.gfskBle.ModulationIndex = ((uint8_t)mi) + 1;
Wayne Roberts 0:9c052ff8dd6a 552 } else
Wayne Roberts 0:9c052ff8dd6a 553 mpBLE_GFSK.gfskBle.ModulationIndex = 0;
Wayne Roberts 0:9c052ff8dd6a 554
Wayne Roberts 0:9c052ff8dd6a 555 radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpBLE_GFSK.buf);
Wayne Roberts 0:9c052ff8dd6a 556 }
Wayne Roberts 0:9c052ff8dd6a 557
Wayne Roberts 0:9c052ff8dd6a 558 void Radio::GFSKPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn)
Wayne Roberts 0:9c052ff8dd6a 559 {
Wayne Roberts 0:9c052ff8dd6a 560 ppGFSK.gfskFLRC.PreambleLength = (preambleLen - 4) / 4;
Wayne Roberts 0:9c052ff8dd6a 561 ppGFSK.gfskFLRC.PreambleLength <<= 4;
Wayne Roberts 0:9c052ff8dd6a 562 ppGFSK.gfskFLRC.SyncWordLength = (3 - 1) << 1; // 3 byte 0xc194c1
Wayne Roberts 0:9c052ff8dd6a 563 ppGFSK.gfskFLRC.HeaderType = fixLen ? RADIO_PACKET_FIXED_LENGTH : RADIO_PACKET_VARIABLE_LENGTH;
Wayne Roberts 0:9c052ff8dd6a 564 ppGFSK.gfskFLRC.CRCLength = crcOn ? RADIO_CRC_2_BYTES : RADIO_CRC_OFF;
Wayne Roberts 0:9c052ff8dd6a 565
Wayne Roberts 0:9c052ff8dd6a 566 // TODO ppGFSK.gfskFLRC.PayloadLength = ;
Wayne Roberts 0:9c052ff8dd6a 567
Wayne Roberts 0:9c052ff8dd6a 568 radio.xfer(OPCODE_SET_PACKET_PARAMS, 7, 0, ppGFSK.buf);
Wayne Roberts 0:9c052ff8dd6a 569 }
Wayne Roberts 0:9c052ff8dd6a 570
Wayne Roberts 13:a354f82d12d9 571 void Radio::SetLoRaSymbolTimeout(uint16_t symbs)
Wayne Roberts 0:9c052ff8dd6a 572 {
Wayne Roberts 9:97a6de3dbc86 573 nSymbs = symbs;
Wayne Roberts 9:97a6de3dbc86 574 rxTimeoutMs = nSymbs * (symbolPeriodUs / 1000.0);
Wayne Roberts 0:9c052ff8dd6a 575 }
Wayne Roberts 0:9c052ff8dd6a 576
Wayne Roberts 0:9c052ff8dd6a 577 void Radio::LoRaModemConfig(unsigned bwKHz, uint8_t sf, uint8_t cr)
Wayne Roberts 0:9c052ff8dd6a 578 {
Wayne Roberts 1:e79b0a55135f 579 if (radio.getPacketType() != PACKET_TYPE_LORA)
Wayne Roberts 1:e79b0a55135f 580 radio.setPacketType(PACKET_TYPE_LORA);
Wayne Roberts 1:e79b0a55135f 581
Wayne Roberts 12:fcfafd17ae1b 582 if (bwKHz > 800)
Wayne Roberts 0:9c052ff8dd6a 583 mpLORA.lora.bandwidth = LORA_BW_1600;
Wayne Roberts 12:fcfafd17ae1b 584 else if (bwKHz > 400)
Wayne Roberts 0:9c052ff8dd6a 585 mpLORA.lora.bandwidth = LORA_BW_800;
Wayne Roberts 12:fcfafd17ae1b 586 else if (bwKHz > 200)
Wayne Roberts 0:9c052ff8dd6a 587 mpLORA.lora.bandwidth = LORA_BW_400;
Wayne Roberts 12:fcfafd17ae1b 588 else if (bwKHz > 100)
Wayne Roberts 0:9c052ff8dd6a 589 mpLORA.lora.bandwidth = LORA_BW_200;
Wayne Roberts 12:fcfafd17ae1b 590 else if (bwKHz > 50)
Wayne Roberts 12:fcfafd17ae1b 591 mpLORA.lora.bandwidth = LORA_BW_100;
Wayne Roberts 12:fcfafd17ae1b 592 else
Wayne Roberts 12:fcfafd17ae1b 593 mpLORA.lora.bandwidth = LORA_BW_50;
Wayne Roberts 0:9c052ff8dd6a 594
Wayne Roberts 0:9c052ff8dd6a 595 mpLORA.lora.codingRate = cr;
Wayne Roberts 0:9c052ff8dd6a 596
Wayne Roberts 0:9c052ff8dd6a 597 mpLORA.lora.spreadingFactor = sf << 4;
Wayne Roberts 0:9c052ff8dd6a 598
Wayne Roberts 0:9c052ff8dd6a 599 radio.xfer(OPCODE_SET_MODULATION_PARAMS, 3, 0, mpLORA.buf);
Wayne Roberts 9:97a6de3dbc86 600
Wayne Roberts 9:97a6de3dbc86 601 symbolPeriodUs = (1 << sf) / (bwKHz / 1000.0); // bw in MHz gives microseconds
Wayne Roberts 9:97a6de3dbc86 602 rxTimeoutMs = nSymbs * (symbolPeriodUs / 1000.0);
Wayne Roberts 0:9c052ff8dd6a 603 }
Wayne Roberts 0:9c052ff8dd6a 604
Wayne Roberts 0:9c052ff8dd6a 605 void Radio::LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ)
Wayne Roberts 0:9c052ff8dd6a 606 {
Wayne Roberts 1:e79b0a55135f 607 if (radio.getPacketType() != PACKET_TYPE_LORA)
Wayne Roberts 1:e79b0a55135f 608 radio.setPacketType(PACKET_TYPE_LORA);
Wayne Roberts 1:e79b0a55135f 609
Wayne Roberts 0:9c052ff8dd6a 610 ppLORA.lora.PreambleLength = preambleLen;
Wayne Roberts 0:9c052ff8dd6a 611 ppLORA.lora.HeaderType = fixLen ? IMPLICIT_HEADER : EXPLICIT_HEADER;
Wayne Roberts 0:9c052ff8dd6a 612 ppLORA.lora.crc = crcOn ? LORA_CRC_ENABLE : LORA_CRC_DISABLE;
Wayne Roberts 0:9c052ff8dd6a 613 ppLORA.lora.InvertIQ = invIQ ? LORA_IQ_INVERTED : LORA_IQ_STD;
Wayne Roberts 0:9c052ff8dd6a 614
Wayne Roberts 0:9c052ff8dd6a 615 radio.xfer(OPCODE_SET_PACKET_PARAMS, 5, 0, ppLORA.buf);
Wayne Roberts 0:9c052ff8dd6a 616 }
Wayne Roberts 0:9c052ff8dd6a 617
Wayne Roberts 0:9c052ff8dd6a 618 void Radio::SetChannel(unsigned hz)
Wayne Roberts 0:9c052ff8dd6a 619 {
Wayne Roberts 0:9c052ff8dd6a 620 radio.setMHz(hz / 1000000.0);
Wayne Roberts 0:9c052ff8dd6a 621 }
Wayne Roberts 0:9c052ff8dd6a 622
Wayne Roberts 0:9c052ff8dd6a 623 uint32_t Radio::Random(void)
Wayne Roberts 0:9c052ff8dd6a 624 {
Wayne Roberts 0:9c052ff8dd6a 625 uint8_t buf[2];
Wayne Roberts 0:9c052ff8dd6a 626 uint32_t ret = 0;
Wayne Roberts 0:9c052ff8dd6a 627 unsigned n;
Wayne Roberts 0:9c052ff8dd6a 628
Wayne Roberts 0:9c052ff8dd6a 629 radio.start_rx(-1);
Wayne Roberts 0:9c052ff8dd6a 630
Wayne Roberts 0:9c052ff8dd6a 631 for (n = 0; n < 8; n++) {
Wayne Roberts 0:9c052ff8dd6a 632 uint32_t r, s;
Wayne Roberts 0:9c052ff8dd6a 633 wait_us(5000);
Wayne Roberts 0:9c052ff8dd6a 634 radio.xfer(OPCODE_GET_RSSIINST, 0, 2, buf);
Wayne Roberts 0:9c052ff8dd6a 635 r = buf[1];
Wayne Roberts 0:9c052ff8dd6a 636 s = n * 4;
Wayne Roberts 0:9c052ff8dd6a 637 r <<= s;
Wayne Roberts 0:9c052ff8dd6a 638 ret ^= r;
Wayne Roberts 0:9c052ff8dd6a 639 }
Wayne Roberts 0:9c052ff8dd6a 640
Wayne Roberts 0:9c052ff8dd6a 641 radio.setStandby(STDBY_RC);
Wayne Roberts 0:9c052ff8dd6a 642
Wayne Roberts 0:9c052ff8dd6a 643 return ret;
Wayne Roberts 0:9c052ff8dd6a 644 }
Wayne Roberts 0:9c052ff8dd6a 645
Wayne Roberts 0:9c052ff8dd6a 646 void Radio::Rx(unsigned timeout)
Wayne Roberts 0:9c052ff8dd6a 647 {
Wayne Roberts 7:ba81f66e56d1 648 #ifdef RX_INDICATION
Wayne Roberts 7:ba81f66e56d1 649 RX_INDICATION = 1;
Wayne Roberts 7:ba81f66e56d1 650 #endif
Wayne Roberts 9:97a6de3dbc86 651 if (timeout == 0)
Wayne Roberts 9:97a6de3dbc86 652 radio.start_rx(0); // continuous rx
Wayne Roberts 9:97a6de3dbc86 653 else {
Wayne Roberts 9:97a6de3dbc86 654 radio.start_rx(rxTimeoutMs);
Wayne Roberts 9:97a6de3dbc86 655 }
Wayne Roberts 0:9c052ff8dd6a 656 }
Wayne Roberts 0:9c052ff8dd6a 657
Wayne Roberts 0:9c052ff8dd6a 658 void Radio::Standby()
Wayne Roberts 0:9c052ff8dd6a 659 {
Wayne Roberts 0:9c052ff8dd6a 660 radio.setStandby(STDBY_RC);
Wayne Roberts 0:9c052ff8dd6a 661 }
Wayne Roberts 0:9c052ff8dd6a 662
Wayne Roberts 13:a354f82d12d9 663 #define TX_PWR_OFFSET 18
Wayne Roberts 0:9c052ff8dd6a 664 void Radio::set_tx_dbm(int8_t dbm)
Wayne Roberts 0:9c052ff8dd6a 665 {
Wayne Roberts 5:ab124d3842a8 666 if (dbm == PA_OFF_DBM) {
Wayne Roberts 5:ab124d3842a8 667 /* TODO: shut off PA */
Wayne Roberts 13:a354f82d12d9 668 radio.set_tx_dbm(0);
Wayne Roberts 5:ab124d3842a8 669 } else {
Wayne Roberts 13:a354f82d12d9 670 /* power range -18dBm to +13dBm */
Wayne Roberts 13:a354f82d12d9 671 radio.set_tx_dbm(dbm + TX_PWR_OFFSET);
Wayne Roberts 5:ab124d3842a8 672 }
Wayne Roberts 0:9c052ff8dd6a 673 }
Wayne Roberts 0:9c052ff8dd6a 674
Wayne Roberts 0:9c052ff8dd6a 675 void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us)
Wayne Roberts 0:9c052ff8dd6a 676 {
Wayne Roberts 0:9c052ff8dd6a 677 SetChannel(hz);
Wayne Roberts 0:9c052ff8dd6a 678 radio.set_tx_dbm(dbm);
Wayne Roberts 0:9c052ff8dd6a 679 radio.xfer(OPCODE_SET_TX_CARRIER, 0, 0, NULL);
Wayne Roberts 0:9c052ff8dd6a 680 }
Wayne Roberts 0:9c052ff8dd6a 681
Wayne Roberts 1:e79b0a55135f 682 void Radio::SetRxMaxPayloadLength(uint8_t max)
Wayne Roberts 0:9c052ff8dd6a 683 {
Wayne Roberts 1:e79b0a55135f 684 uint8_t pktType = radio.getPacketType();
Wayne Roberts 1:e79b0a55135f 685
Wayne Roberts 1:e79b0a55135f 686 if (pktType == PACKET_TYPE_GFSK)
Wayne Roberts 0:9c052ff8dd6a 687 ppGFSK.gfskFLRC.PayloadLength = max;
Wayne Roberts 1:e79b0a55135f 688 else if (pktType == PACKET_TYPE_LORA)
Wayne Roberts 0:9c052ff8dd6a 689 ppLORA.lora.PayloadLength = max;
Wayne Roberts 0:9c052ff8dd6a 690 }
Wayne Roberts 0:9c052ff8dd6a 691
Wayne Roberts 0:9c052ff8dd6a 692 #endif /* ..SX126x_H */