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:
Mon Jun 01 15:59:56 2020 -0700
Revision:
17:5f34cbe2ac53
Parent:
16:34de2ab7eb32
Child:
20:75635d50262e
support platforms without LowPowerTimer, add LR1110

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