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
- SX1272 shield.
- SX1276 shield.
- SX126x kit with color touch screen, or sx126x radio-only shield.
- Exceptions with their own pin assignments: NAMote-72 and Murata discovery board.
- TODO: pin assign XDOT.
radio_sx128x.cpp@17:5f34cbe2ac53, 2020-06-01 (annotated)
- 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?
User | Revision | Line number | New 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 */ |