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_sx127x.cpp@20:75635d50262e, 2020-07-10 (annotated)
- Committer:
- Wayne Roberts
- Date:
- Fri Jul 10 10:52:39 2020 -0700
- Revision:
- 20:75635d50262e
- Parent:
- 19:94b5382d3fc6
support mbed-6
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 SX127x_H |
Wayne Roberts |
0:9c052ff8dd6a | 3 | |
Wayne Roberts |
17:5f34cbe2ac53 | 4 | #ifdef DEVICE_LPTICKER |
Wayne Roberts |
0:9c052ff8dd6a | 5 | LowPowerTimer Radio::lpt; |
Wayne Roberts |
17:5f34cbe2ac53 | 6 | LowPowerTimeout TxTimeoutEvent; |
Wayne Roberts |
17:5f34cbe2ac53 | 7 | #else |
Wayne Roberts |
17:5f34cbe2ac53 | 8 | Timer Radio::lpt; |
Wayne Roberts |
17:5f34cbe2ac53 | 9 | Timeout TxTimeoutEvent; |
Wayne Roberts |
17:5f34cbe2ac53 | 10 | #endif |
Wayne Roberts |
0:9c052ff8dd6a | 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 | using namespace std::chrono; |
Wayne Roberts |
20:75635d50262e | 16 | LowPowerClock::time_point Radio::irqAt; |
Wayne Roberts |
20:75635d50262e | 17 | #endif |
Wayne Roberts |
20:75635d50262e | 18 | |
Wayne Roberts |
0:9c052ff8dd6a | 19 | void Radio::Sleep() |
Wayne Roberts |
0:9c052ff8dd6a | 20 | { |
Wayne Roberts |
0:9c052ff8dd6a | 21 | radio.set_opmode(RF_OPMODE_SLEEP); |
Wayne Roberts |
0:9c052ff8dd6a | 22 | } |
Wayne Roberts |
0:9c052ff8dd6a | 23 | |
Wayne Roberts |
0:9c052ff8dd6a | 24 | void Radio::Standby() |
Wayne Roberts |
0:9c052ff8dd6a | 25 | { |
Wayne Roberts |
0:9c052ff8dd6a | 26 | radio.set_opmode(RF_OPMODE_STANDBY); |
Wayne Roberts |
0:9c052ff8dd6a | 27 | } |
Wayne Roberts |
0:9c052ff8dd6a | 28 | |
Wayne Roberts |
0:9c052ff8dd6a | 29 | bool Radio::CheckRfFrequency(unsigned hz) |
Wayne Roberts |
0:9c052ff8dd6a | 30 | { |
Wayne Roberts |
0:9c052ff8dd6a | 31 | return true; |
Wayne Roberts |
0:9c052ff8dd6a | 32 | } |
Wayne Roberts |
0:9c052ff8dd6a | 33 | |
Wayne Roberts |
0:9c052ff8dd6a | 34 | void Radio::SetChannel(unsigned hz) |
Wayne Roberts |
0:9c052ff8dd6a | 35 | { |
Wayne Roberts |
0:9c052ff8dd6a | 36 | radio.set_frf_MHz(hz / 1000000.0); |
Wayne Roberts |
0:9c052ff8dd6a | 37 | } |
Wayne Roberts |
0:9c052ff8dd6a | 38 | |
Wayne Roberts |
0:9c052ff8dd6a | 39 | float Radio::getFrfMHz() |
Wayne Roberts |
0:9c052ff8dd6a | 40 | { |
Wayne Roberts |
0:9c052ff8dd6a | 41 | return radio.get_frf_MHz(); |
Wayne Roberts |
0:9c052ff8dd6a | 42 | } |
Wayne Roberts |
0:9c052ff8dd6a | 43 | |
Wayne Roberts |
0:9c052ff8dd6a | 44 | void SX1272OnTimeoutIrq( void ) |
Wayne Roberts |
0:9c052ff8dd6a | 45 | { |
Wayne Roberts |
0:9c052ff8dd6a | 46 | Radio::radio.set_opmode(RF_OPMODE_STANDBY); |
Wayne Roberts |
0:9c052ff8dd6a | 47 | } |
Wayne Roberts |
0:9c052ff8dd6a | 48 | |
Wayne Roberts |
0:9c052ff8dd6a | 49 | void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us) |
Wayne Roberts |
0:9c052ff8dd6a | 50 | { |
Wayne Roberts |
19:94b5382d3fc6 | 51 | fsk.enable(true); |
Wayne Roberts |
19:94b5382d3fc6 | 52 | fsk.RegPktConfig2.word = radio.read_u16(REG_FSK_PACKETCONFIG2); |
Wayne Roberts |
19:94b5382d3fc6 | 53 | fsk.RegPktConfig2.bits.DataModePacket = 0; // continuous mode |
Wayne Roberts |
19:94b5382d3fc6 | 54 | radio.write_u16(REG_FSK_PACKETCONFIG2, fsk.RegPktConfig2.word); |
Wayne Roberts |
19:94b5382d3fc6 | 55 | fsk.set_tx_fdev_hz(0); // unmodulated carrier, aka dead carrier |
Wayne Roberts |
19:94b5382d3fc6 | 56 | SetChannel(hz); |
Wayne Roberts |
0:9c052ff8dd6a | 57 | set_tx_dbm(dbm); |
Wayne Roberts |
19:94b5382d3fc6 | 58 | |
Wayne Roberts |
20:75635d50262e | 59 | if (timeout_us != 0) { |
Wayne Roberts |
20:75635d50262e | 60 | #if (MBED_MAJOR_VERSION < 6) |
Wayne Roberts |
19:94b5382d3fc6 | 61 | TxTimeoutEvent.attach_us(SX1272OnTimeoutIrq, timeout_us); |
Wayne Roberts |
20:75635d50262e | 62 | #else |
Wayne Roberts |
20:75635d50262e | 63 | TxTimeoutEvent.attach(SX1272OnTimeoutIrq, microseconds(timeout_us)); |
Wayne Roberts |
20:75635d50262e | 64 | #endif |
Wayne Roberts |
20:75635d50262e | 65 | } |
Wayne Roberts |
19:94b5382d3fc6 | 66 | |
Wayne Roberts |
0:9c052ff8dd6a | 67 | radio.set_opmode(RF_OPMODE_TRANSMITTER); |
Wayne Roberts |
0:9c052ff8dd6a | 68 | } |
Wayne Roberts |
0:9c052ff8dd6a | 69 | |
Wayne Roberts |
0:9c052ff8dd6a | 70 | #define LORA_MAC_PRIVATE_SYNCWORD 0x12 |
Wayne Roberts |
0:9c052ff8dd6a | 71 | #define LORA_MAC_PUBLIC_SYNCWORD 0x34 |
Wayne Roberts |
0:9c052ff8dd6a | 72 | void Radio::SetPublicNetwork(bool en) |
Wayne Roberts |
0:9c052ff8dd6a | 73 | { |
Wayne Roberts |
0:9c052ff8dd6a | 74 | radio.write_reg(REG_LR_SYNC_BYTE, en ? LORA_MAC_PUBLIC_SYNCWORD : LORA_MAC_PRIVATE_SYNCWORD); |
Wayne Roberts |
0:9c052ff8dd6a | 75 | } |
Wayne Roberts |
0:9c052ff8dd6a | 76 | |
Wayne Roberts |
0:9c052ff8dd6a | 77 | uint32_t Radio::Random(void) |
Wayne Roberts |
0:9c052ff8dd6a | 78 | { |
Wayne Roberts |
0:9c052ff8dd6a | 79 | uint32_t ret = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 80 | unsigned i; |
Wayne Roberts |
0:9c052ff8dd6a | 81 | |
Wayne Roberts |
0:9c052ff8dd6a | 82 | radio.set_opmode(RF_OPMODE_RECEIVER); |
Wayne Roberts |
0:9c052ff8dd6a | 83 | for (i = 0; i < 32; i++) { |
Wayne Roberts |
0:9c052ff8dd6a | 84 | uint32_t r; |
Wayne Roberts |
0:9c052ff8dd6a | 85 | wait_us(3000); |
Wayne Roberts |
0:9c052ff8dd6a | 86 | r = radio.read_reg(REG_LR_WIDEBAND_RSSI); |
Wayne Roberts |
0:9c052ff8dd6a | 87 | r <<= ((i & 7) << 2); |
Wayne Roberts |
0:9c052ff8dd6a | 88 | ret ^= r; |
Wayne Roberts |
0:9c052ff8dd6a | 89 | } |
Wayne Roberts |
0:9c052ff8dd6a | 90 | |
Wayne Roberts |
0:9c052ff8dd6a | 91 | return ret; |
Wayne Roberts |
0:9c052ff8dd6a | 92 | } |
Wayne Roberts |
0:9c052ff8dd6a | 93 | |
Wayne Roberts |
0:9c052ff8dd6a | 94 | void Radio::LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ) |
Wayne Roberts |
0:9c052ff8dd6a | 95 | { |
Wayne Roberts |
0:9c052ff8dd6a | 96 | lora.RegPreamble = preambleLen; |
Wayne Roberts |
0:9c052ff8dd6a | 97 | radio.write_u16(REG_LR_PREAMBLEMSB, lora.RegPreamble); |
Wayne Roberts |
0:9c052ff8dd6a | 98 | |
Wayne Roberts |
0:9c052ff8dd6a | 99 | if (radio.type == SX1276) { |
Wayne Roberts |
0:9c052ff8dd6a | 100 | lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn = fixLen; |
Wayne Roberts |
0:9c052ff8dd6a | 101 | lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn = crcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 102 | radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 103 | } else if (radio.type == SX1272) { |
Wayne Roberts |
0:9c052ff8dd6a | 104 | lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn = fixLen; |
Wayne Roberts |
0:9c052ff8dd6a | 105 | lora.RegModemConfig.sx1272bits.RxPayloadCrcOn = crcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 106 | } |
Wayne Roberts |
0:9c052ff8dd6a | 107 | |
Wayne Roberts |
0:9c052ff8dd6a | 108 | radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 109 | |
Wayne Roberts |
0:9c052ff8dd6a | 110 | lora.invert_tx(invIQ); |
Wayne Roberts |
0:9c052ff8dd6a | 111 | lora.invert_rx(invIQ); |
Wayne Roberts |
0:9c052ff8dd6a | 112 | } |
Wayne Roberts |
0:9c052ff8dd6a | 113 | |
Wayne Roberts |
0:9c052ff8dd6a | 114 | void Radio::GFSKModemConfig(unsigned bps, unsigned bw_hz, unsigned fdev_hz) |
Wayne Roberts |
0:9c052ff8dd6a | 115 | { |
Wayne Roberts |
0:9c052ff8dd6a | 116 | if (radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
0:9c052ff8dd6a | 117 | fsk.enable(false); |
Wayne Roberts |
0:9c052ff8dd6a | 118 | |
Wayne Roberts |
0:9c052ff8dd6a | 119 | fsk.set_bitrate(bps); |
Wayne Roberts |
0:9c052ff8dd6a | 120 | |
Wayne Roberts |
0:9c052ff8dd6a | 121 | fsk.set_rx_dcc_bw_hz(bw_hz, 0); |
Wayne Roberts |
0:9c052ff8dd6a | 122 | fsk.set_rx_dcc_bw_hz(bw_hz * 1.5, 1); |
Wayne Roberts |
0:9c052ff8dd6a | 123 | |
Wayne Roberts |
0:9c052ff8dd6a | 124 | fsk.set_tx_fdev_hz(fdev_hz); |
Wayne Roberts |
0:9c052ff8dd6a | 125 | } |
Wayne Roberts |
0:9c052ff8dd6a | 126 | |
Wayne Roberts |
0:9c052ff8dd6a | 127 | |
Wayne Roberts |
0:9c052ff8dd6a | 128 | void Radio::GFSKPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn) |
Wayne Roberts |
0:9c052ff8dd6a | 129 | { |
Wayne Roberts |
0:9c052ff8dd6a | 130 | if (radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
0:9c052ff8dd6a | 131 | fsk.enable(false); |
Wayne Roberts |
0:9c052ff8dd6a | 132 | |
Wayne Roberts |
0:9c052ff8dd6a | 133 | radio.write_u16(REG_FSK_PREAMBLEMSB, preambleLen); |
Wayne Roberts |
0:9c052ff8dd6a | 134 | |
Wayne Roberts |
0:9c052ff8dd6a | 135 | fsk.RegPktConfig1.bits.PacketFormatVariable = fixLen ? 0 : 1; |
Wayne Roberts |
0:9c052ff8dd6a | 136 | fsk.RegPktConfig1.bits.CrcOn = crcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 137 | radio.write_reg(REG_FSK_PACKETCONFIG1, fsk.RegPktConfig1.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 138 | } |
Wayne Roberts |
0:9c052ff8dd6a | 139 | |
Wayne Roberts |
13:a354f82d12d9 | 140 | void Radio::SetLoRaSymbolTimeout(uint16_t symbs) |
Wayne Roberts |
0:9c052ff8dd6a | 141 | { |
Wayne Roberts |
0:9c052ff8dd6a | 142 | if (!radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
0:9c052ff8dd6a | 143 | lora.enable(); |
Wayne Roberts |
0:9c052ff8dd6a | 144 | |
Wayne Roberts |
13:a354f82d12d9 | 145 | radio.write_reg(REG_LR_SYMBTIMEOUTLSB, symbs & 0xff); |
Wayne Roberts |
13:a354f82d12d9 | 146 | symbs >>= 8; |
Wayne Roberts |
13:a354f82d12d9 | 147 | lora.RegModemConfig2.sx1272bits.SymbTimeoutMsb = symbs; |
Wayne Roberts |
0:9c052ff8dd6a | 148 | radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 149 | } |
Wayne Roberts |
0:9c052ff8dd6a | 150 | |
Wayne Roberts |
0:9c052ff8dd6a | 151 | void Radio::LoRaModemConfig(unsigned bwKHz, uint8_t sf, uint8_t coderate) |
Wayne Roberts |
0:9c052ff8dd6a | 152 | { |
Wayne Roberts |
0:9c052ff8dd6a | 153 | float sp; |
Wayne Roberts |
0:9c052ff8dd6a | 154 | if (!radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
0:9c052ff8dd6a | 155 | lora.enable(); |
Wayne Roberts |
0:9c052ff8dd6a | 156 | |
Wayne Roberts |
0:9c052ff8dd6a | 157 | lora.RegModemConfig2.sx1276bits.SpreadingFactor = sf; |
Wayne Roberts |
0:9c052ff8dd6a | 158 | radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 159 | |
Wayne Roberts |
0:9c052ff8dd6a | 160 | lora.setBw_KHz(bwKHz); |
Wayne Roberts |
0:9c052ff8dd6a | 161 | |
Wayne Roberts |
0:9c052ff8dd6a | 162 | if (radio.type == SX1276) { |
Wayne Roberts |
0:9c052ff8dd6a | 163 | lora.RegModemConfig.sx1276bits.CodingRate = coderate; |
Wayne Roberts |
0:9c052ff8dd6a | 164 | |
Wayne Roberts |
0:9c052ff8dd6a | 165 | sp = lora.get_symbol_period(); |
Wayne Roberts |
0:9c052ff8dd6a | 166 | if (sp > 16) |
Wayne Roberts |
0:9c052ff8dd6a | 167 | lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 1; |
Wayne Roberts |
0:9c052ff8dd6a | 168 | else |
Wayne Roberts |
0:9c052ff8dd6a | 169 | lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 170 | |
Wayne Roberts |
0:9c052ff8dd6a | 171 | radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 172 | } else if (radio.type == SX1272) { |
Wayne Roberts |
0:9c052ff8dd6a | 173 | lora.RegModemConfig.sx1272bits.CodingRate = coderate; |
Wayne Roberts |
0:9c052ff8dd6a | 174 | |
Wayne Roberts |
0:9c052ff8dd6a | 175 | if (lora.get_symbol_period() > 16) |
Wayne Roberts |
0:9c052ff8dd6a | 176 | lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 1; |
Wayne Roberts |
0:9c052ff8dd6a | 177 | else |
Wayne Roberts |
0:9c052ff8dd6a | 178 | lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 179 | } |
Wayne Roberts |
0:9c052ff8dd6a | 180 | radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 181 | } |
Wayne Roberts |
0:9c052ff8dd6a | 182 | |
Wayne Roberts |
1:e79b0a55135f | 183 | void Radio::SetRxMaxPayloadLength(uint8_t max) |
Wayne Roberts |
0:9c052ff8dd6a | 184 | { |
Wayne Roberts |
1:e79b0a55135f | 185 | if (radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
1:e79b0a55135f | 186 | radio.write_reg(REG_LR_RX_MAX_PAYLOADLENGTH, max); |
Wayne Roberts |
1:e79b0a55135f | 187 | else |
Wayne Roberts |
1:e79b0a55135f | 188 | radio.write_reg(REG_FSK_PAYLOADLENGTH, max); |
Wayne Roberts |
0:9c052ff8dd6a | 189 | } |
Wayne Roberts |
0:9c052ff8dd6a | 190 | |
Wayne Roberts |
6:b7bbf31e06e4 | 191 | void Radio::SetFixedPayloadLength(uint8_t len) |
Wayne Roberts |
6:b7bbf31e06e4 | 192 | { |
Wayne Roberts |
6:b7bbf31e06e4 | 193 | lora.RegPayloadLength = len; |
Wayne Roberts |
6:b7bbf31e06e4 | 194 | radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); |
Wayne Roberts |
6:b7bbf31e06e4 | 195 | } |
Wayne Roberts |
6:b7bbf31e06e4 | 196 | |
Wayne Roberts |
0:9c052ff8dd6a | 197 | const RadioEvents_t* RadioEvents; |
Wayne Roberts |
0:9c052ff8dd6a | 198 | |
Wayne Roberts |
0:9c052ff8dd6a | 199 | |
Wayne Roberts |
0:9c052ff8dd6a | 200 | volatile struct pe { |
Wayne Roberts |
0:9c052ff8dd6a | 201 | uint8_t dio0 : 1; |
Wayne Roberts |
0:9c052ff8dd6a | 202 | uint8_t dio1 : 1; |
Wayne Roberts |
0:9c052ff8dd6a | 203 | uint8_t txing : 1; |
Wayne Roberts |
0:9c052ff8dd6a | 204 | } pinEvent; |
Wayne Roberts |
0:9c052ff8dd6a | 205 | |
Wayne Roberts |
0:9c052ff8dd6a | 206 | void |
Wayne Roberts |
0:9c052ff8dd6a | 207 | Radio::dio0UserContext() |
Wayne Roberts |
0:9c052ff8dd6a | 208 | { |
Wayne Roberts |
0:9c052ff8dd6a | 209 | service_action_e act = lora.service(); |
Wayne Roberts |
0:9c052ff8dd6a | 210 | |
Wayne Roberts |
0:9c052ff8dd6a | 211 | if (!pinEvent.txing) { |
Wayne Roberts |
0:9c052ff8dd6a | 212 | if (act == SERVICE_READ_FIFO && RadioEvents->RxDone) { |
Wayne Roberts |
0:9c052ff8dd6a | 213 | int8_t rssi; |
Wayne Roberts |
0:9c052ff8dd6a | 214 | float snr = lora.RegPktSnrValue / 4.0; |
Wayne Roberts |
0:9c052ff8dd6a | 215 | |
Wayne Roberts |
0:9c052ff8dd6a | 216 | rssi = lora.get_pkt_rssi(); |
Wayne Roberts |
0:9c052ff8dd6a | 217 | if (snr < 0) |
Wayne Roberts |
0:9c052ff8dd6a | 218 | rssi += snr; |
Wayne Roberts |
0:9c052ff8dd6a | 219 | RadioEvents->RxDone(lora.RegRxNbBytes, rssi, snr); |
Wayne Roberts |
0:9c052ff8dd6a | 220 | } |
Wayne Roberts |
0:9c052ff8dd6a | 221 | } else if (act == SERVICE_TX_DONE) { |
Wayne Roberts |
0:9c052ff8dd6a | 222 | if (RadioEvents->TxDone_botHalf) |
Wayne Roberts |
0:9c052ff8dd6a | 223 | RadioEvents->TxDone_botHalf(); |
Wayne Roberts |
0:9c052ff8dd6a | 224 | } |
Wayne Roberts |
0:9c052ff8dd6a | 225 | } |
Wayne Roberts |
0:9c052ff8dd6a | 226 | |
Wayne Roberts |
0:9c052ff8dd6a | 227 | void Radio::dio0isr() |
Wayne Roberts |
0:9c052ff8dd6a | 228 | { |
Wayne Roberts |
20:75635d50262e | 229 | #if (MBED_MAJOR_VERSION < 6) |
Wayne Roberts |
0:9c052ff8dd6a | 230 | irqAt = lpt.read_us(); |
Wayne Roberts |
20:75635d50262e | 231 | #else |
Wayne Roberts |
20:75635d50262e | 232 | irqAt = LowPowerClock::now(); |
Wayne Roberts |
20:75635d50262e | 233 | #endif |
Wayne Roberts |
14:94993ae5b164 | 234 | |
Wayne Roberts |
14:94993ae5b164 | 235 | if (RadioEvents->DioPin_top_half) |
Wayne Roberts |
14:94993ae5b164 | 236 | RadioEvents->DioPin_top_half(); |
Wayne Roberts |
0:9c052ff8dd6a | 237 | |
Wayne Roberts |
0:9c052ff8dd6a | 238 | if (pinEvent.txing) { |
Wayne Roberts |
0:9c052ff8dd6a | 239 | /* TxDone handling requires low latency */ |
Wayne Roberts |
0:9c052ff8dd6a | 240 | if (RadioEvents->TxDone_topHalf) |
Wayne Roberts |
0:9c052ff8dd6a | 241 | RadioEvents->TxDone_topHalf(); // TODO in callback read irqAt for timestamp of interrupt |
Wayne Roberts |
0:9c052ff8dd6a | 242 | |
Wayne Roberts |
0:9c052ff8dd6a | 243 | } |
Wayne Roberts |
0:9c052ff8dd6a | 244 | |
Wayne Roberts |
0:9c052ff8dd6a | 245 | pinEvent.dio0 = 1; |
Wayne Roberts |
0:9c052ff8dd6a | 246 | } |
Wayne Roberts |
0:9c052ff8dd6a | 247 | |
Wayne Roberts |
0:9c052ff8dd6a | 248 | void Radio::dio1UserContext() |
Wayne Roberts |
0:9c052ff8dd6a | 249 | { |
Wayne Roberts |
0:9c052ff8dd6a | 250 | lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); |
Wayne Roberts |
0:9c052ff8dd6a | 251 | |
Wayne Roberts |
0:9c052ff8dd6a | 252 | if (RadioEvents->RxTimeout) |
Wayne Roberts |
0:9c052ff8dd6a | 253 | RadioEvents->RxTimeout(); |
Wayne Roberts |
0:9c052ff8dd6a | 254 | |
Wayne Roberts |
0:9c052ff8dd6a | 255 | radio.write_reg(REG_LR_IRQFLAGS, 0x80); // ensure RxTimeout is cleared |
Wayne Roberts |
0:9c052ff8dd6a | 256 | } |
Wayne Roberts |
0:9c052ff8dd6a | 257 | |
Wayne Roberts |
0:9c052ff8dd6a | 258 | void Radio::dio1isr() |
Wayne Roberts |
0:9c052ff8dd6a | 259 | { |
Wayne Roberts |
0:9c052ff8dd6a | 260 | pinEvent.dio1 = 1; |
Wayne Roberts |
14:94993ae5b164 | 261 | |
Wayne Roberts |
14:94993ae5b164 | 262 | if (RadioEvents->DioPin_top_half) |
Wayne Roberts |
14:94993ae5b164 | 263 | RadioEvents->DioPin_top_half(); |
Wayne Roberts |
0:9c052ff8dd6a | 264 | } |
Wayne Roberts |
0:9c052ff8dd6a | 265 | |
Wayne Roberts |
13:a354f82d12d9 | 266 | void Radio::Init(const RadioEvents_t* e, unsigned spi_hz) |
Wayne Roberts |
0:9c052ff8dd6a | 267 | { |
Wayne Roberts |
13:a354f82d12d9 | 268 | radio.m_spi.frequency(spi_hz); |
Wayne Roberts |
13:a354f82d12d9 | 269 | |
Wayne Roberts |
8:0518c6e68b79 | 270 | while (radio.dio0.read() || radio.dio1.read()) { |
Wayne Roberts |
8:0518c6e68b79 | 271 | radio.write_reg(REG_LR_IRQFLAGS, 0xff); // clear stagnant interrupt |
Wayne Roberts |
8:0518c6e68b79 | 272 | } |
Wayne Roberts |
0:9c052ff8dd6a | 273 | dio0.rise(dio0isr); |
Wayne Roberts |
0:9c052ff8dd6a | 274 | dio1.rise(dio1isr); |
Wayne Roberts |
0:9c052ff8dd6a | 275 | |
Wayne Roberts |
0:9c052ff8dd6a | 276 | radio.rf_switch = rfsw_callback; |
Wayne Roberts |
0:9c052ff8dd6a | 277 | boardInit(); |
Wayne Roberts |
0:9c052ff8dd6a | 278 | |
Wayne Roberts |
0:9c052ff8dd6a | 279 | RadioEvents = e; |
Wayne Roberts |
0:9c052ff8dd6a | 280 | lpt.start(); |
Wayne Roberts |
0:9c052ff8dd6a | 281 | } |
Wayne Roberts |
0:9c052ff8dd6a | 282 | |
Wayne Roberts |
7:ba81f66e56d1 | 283 | float Radio::GetRssiInst() |
Wayne Roberts |
7:ba81f66e56d1 | 284 | { |
Wayne Roberts |
7:ba81f66e56d1 | 285 | return lora.get_current_rssi(); |
Wayne Roberts |
7:ba81f66e56d1 | 286 | } |
Wayne Roberts |
7:ba81f66e56d1 | 287 | |
Wayne Roberts |
0:9c052ff8dd6a | 288 | int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh) |
Wayne Roberts |
0:9c052ff8dd6a | 289 | { |
Wayne Roberts |
0:9c052ff8dd6a | 290 | if (radio.RegOpMode.bits.Mode == RF_OPMODE_SLEEP) { |
Wayne Roberts |
0:9c052ff8dd6a | 291 | radio.set_opmode(RF_OPMODE_STANDBY); |
Wayne Roberts |
0:9c052ff8dd6a | 292 | wait_us(1000); |
Wayne Roberts |
0:9c052ff8dd6a | 293 | } |
Wayne Roberts |
0:9c052ff8dd6a | 294 | radio.write_reg(REG_LR_IRQFLAGS, 0x08); // ensure TxDone is cleared |
Wayne Roberts |
0:9c052ff8dd6a | 295 | lora.RegPayloadLength = size; |
Wayne Roberts |
0:9c052ff8dd6a | 296 | radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); |
Wayne Roberts |
0:9c052ff8dd6a | 297 | |
Wayne Roberts |
0:9c052ff8dd6a | 298 | if (maxListenTime > 0) { |
Wayne Roberts |
0:9c052ff8dd6a | 299 | int rssi; |
Wayne Roberts |
0:9c052ff8dd6a | 300 | us_timestamp_t startAt, chFreeAt, now; |
Wayne Roberts |
0:9c052ff8dd6a | 301 | lora.start_rx(RF_OPMODE_RECEIVER); |
Wayne Roberts |
20:75635d50262e | 302 | #if (MBED_MAJOR_VERSION < 6) |
Wayne Roberts |
0:9c052ff8dd6a | 303 | startAt = lpt.read_us(); |
Wayne Roberts |
20:75635d50262e | 304 | #else |
Wayne Roberts |
20:75635d50262e | 305 | startAt = LowPowerClock::now().time_since_epoch().count(); |
Wayne Roberts |
20:75635d50262e | 306 | #endif |
Wayne Roberts |
0:9c052ff8dd6a | 307 | Lstart: |
Wayne Roberts |
0:9c052ff8dd6a | 308 | do { |
Wayne Roberts |
20:75635d50262e | 309 | #if (MBED_MAJOR_VERSION < 6) |
Wayne Roberts |
0:9c052ff8dd6a | 310 | now = lpt.read_us(); |
Wayne Roberts |
20:75635d50262e | 311 | #else |
Wayne Roberts |
20:75635d50262e | 312 | now = LowPowerClock::now().time_since_epoch().count(); |
Wayne Roberts |
20:75635d50262e | 313 | #endif |
Wayne Roberts |
0:9c052ff8dd6a | 314 | if ((now - startAt) > maxListenTime) { |
Wayne Roberts |
0:9c052ff8dd6a | 315 | return -1; |
Wayne Roberts |
0:9c052ff8dd6a | 316 | } |
Wayne Roberts |
0:9c052ff8dd6a | 317 | rssi = lora.get_current_rssi(); |
Wayne Roberts |
0:9c052ff8dd6a | 318 | } while (rssi > rssiThresh); |
Wayne Roberts |
20:75635d50262e | 319 | #if (MBED_MAJOR_VERSION < 6) |
Wayne Roberts |
0:9c052ff8dd6a | 320 | chFreeAt = lpt.read_us(); |
Wayne Roberts |
20:75635d50262e | 321 | #else |
Wayne Roberts |
20:75635d50262e | 322 | chFreeAt = LowPowerClock::now().time_since_epoch().count(); |
Wayne Roberts |
20:75635d50262e | 323 | #endif |
Wayne Roberts |
0:9c052ff8dd6a | 324 | do { |
Wayne Roberts |
20:75635d50262e | 325 | #if (MBED_MAJOR_VERSION < 6) |
Wayne Roberts |
0:9c052ff8dd6a | 326 | now = lpt.read_us(); |
Wayne Roberts |
20:75635d50262e | 327 | #else |
Wayne Roberts |
20:75635d50262e | 328 | now = LowPowerClock::now().time_since_epoch().count(); |
Wayne Roberts |
20:75635d50262e | 329 | #endif |
Wayne Roberts |
0:9c052ff8dd6a | 330 | rssi = lora.get_current_rssi(); |
Wayne Roberts |
0:9c052ff8dd6a | 331 | if (rssi > rssiThresh) { |
Wayne Roberts |
0:9c052ff8dd6a | 332 | goto Lstart; |
Wayne Roberts |
0:9c052ff8dd6a | 333 | } |
Wayne Roberts |
0:9c052ff8dd6a | 334 | } while ((now - chFreeAt) < channelFreeTime); |
Wayne Roberts |
0:9c052ff8dd6a | 335 | } |
Wayne Roberts |
0:9c052ff8dd6a | 336 | |
Wayne Roberts |
0:9c052ff8dd6a | 337 | lora.start_tx(size); |
Wayne Roberts |
0:9c052ff8dd6a | 338 | pinEvent.txing = 1; |
Wayne Roberts |
0:9c052ff8dd6a | 339 | |
Wayne Roberts |
0:9c052ff8dd6a | 340 | return 0; |
Wayne Roberts |
0:9c052ff8dd6a | 341 | } |
Wayne Roberts |
0:9c052ff8dd6a | 342 | |
Wayne Roberts |
0:9c052ff8dd6a | 343 | void Radio::Rx(unsigned timeout) |
Wayne Roberts |
0:9c052ff8dd6a | 344 | { |
Wayne Roberts |
0:9c052ff8dd6a | 345 | if (timeout == 0) { |
Wayne Roberts |
0:9c052ff8dd6a | 346 | lora.start_rx(RF_OPMODE_RECEIVER); |
Wayne Roberts |
0:9c052ff8dd6a | 347 | } else { |
Wayne Roberts |
0:9c052ff8dd6a | 348 | lora.start_rx(RF_OPMODE_RECEIVER_SINGLE); |
Wayne Roberts |
0:9c052ff8dd6a | 349 | } |
Wayne Roberts |
0:9c052ff8dd6a | 350 | |
Wayne Roberts |
0:9c052ff8dd6a | 351 | pinEvent.txing = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 352 | } |
Wayne Roberts |
0:9c052ff8dd6a | 353 | |
Wayne Roberts |
0:9c052ff8dd6a | 354 | |
Wayne Roberts |
0:9c052ff8dd6a | 355 | void Radio::ocp(uint8_t ma) |
Wayne Roberts |
0:9c052ff8dd6a | 356 | { |
Wayne Roberts |
0:9c052ff8dd6a | 357 | if (ma < 130) |
Wayne Roberts |
0:9c052ff8dd6a | 358 | radio.RegOcp.bits.OcpTrim = (ma - 45) / 5; |
Wayne Roberts |
0:9c052ff8dd6a | 359 | else |
Wayne Roberts |
0:9c052ff8dd6a | 360 | radio.RegOcp.bits.OcpTrim = (ma + 30) / 10; |
Wayne Roberts |
0:9c052ff8dd6a | 361 | radio.write_reg(REG_OCP, radio.RegOcp.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 362 | |
Wayne Roberts |
0:9c052ff8dd6a | 363 | radio.RegOcp.octet = radio.read_reg(REG_OCP); |
Wayne Roberts |
0:9c052ff8dd6a | 364 | if (radio.RegOcp.bits.OcpTrim < 16) |
Wayne Roberts |
0:9c052ff8dd6a | 365 | ma = 45 + (5 * radio.RegOcp.bits.OcpTrim); |
Wayne Roberts |
0:9c052ff8dd6a | 366 | else if (radio.RegOcp.bits.OcpTrim < 28) |
Wayne Roberts |
0:9c052ff8dd6a | 367 | ma = (10 * radio.RegOcp.bits.OcpTrim) - 30; |
Wayne Roberts |
0:9c052ff8dd6a | 368 | else |
Wayne Roberts |
0:9c052ff8dd6a | 369 | ma = 240; |
Wayne Roberts |
0:9c052ff8dd6a | 370 | } |
Wayne Roberts |
0:9c052ff8dd6a | 371 | |
Wayne Roberts |
0:9c052ff8dd6a | 372 | |
Wayne Roberts |
0:9c052ff8dd6a | 373 | #if 0 |
Wayne Roberts |
0:9c052ff8dd6a | 374 | void Radio::PrintStatus() |
Wayne Roberts |
0:9c052ff8dd6a | 375 | { |
Wayne Roberts |
0:9c052ff8dd6a | 376 | #ifdef MAC_DEBUG |
Wayne Roberts |
0:9c052ff8dd6a | 377 | radio.RegOpMode.octet = radio.read_reg(REG_OPMODE); |
Wayne Roberts |
0:9c052ff8dd6a | 378 | switch (radio.RegOpMode.bits.Mode) { |
Wayne Roberts |
0:9c052ff8dd6a | 379 | case RF_OPMODE_SLEEP: printf("SLEEP "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 380 | case RF_OPMODE_STANDBY: printf("STBY "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 381 | case RF_OPMODE_SYNTHESIZER_TX: printf("FSTX "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 382 | case RF_OPMODE_TRANSMITTER: printf("TX "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 383 | case RF_OPMODE_SYNTHESIZER_RX: printf("FSRX "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 384 | case RF_OPMODE_RECEIVER: printf("RXC "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 385 | case RF_OPMODE_RECEIVER_SINGLE: printf("RXS "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 386 | case RF_OPMODE_CAD: printf("CAD "); break; |
Wayne Roberts |
0:9c052ff8dd6a | 387 | } |
Wayne Roberts |
0:9c052ff8dd6a | 388 | |
Wayne Roberts |
0:9c052ff8dd6a | 389 | printf("dio:%u:%u opmode:%02x %.2fMHz sf%ubw%u ", radio.dio0.read(), radio.dio1.read(), radio.RegOpMode.octet, radio.get_frf_MHz(), lora.getSf(), lora.getBw()); |
Wayne Roberts |
0:9c052ff8dd6a | 390 | lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); |
Wayne Roberts |
0:9c052ff8dd6a | 391 | printf("irqFlags:%02x\r\n", lora.RegIrqFlags.octet); |
Wayne Roberts |
0:9c052ff8dd6a | 392 | #endif /* MAC_DEBUG */ |
Wayne Roberts |
0:9c052ff8dd6a | 393 | } |
Wayne Roberts |
0:9c052ff8dd6a | 394 | #endif /* if 0 */ |
Wayne Roberts |
0:9c052ff8dd6a | 395 | |
Wayne Roberts |
0:9c052ff8dd6a | 396 | #ifdef DUTY_ENABLE |
Wayne Roberts |
0:9c052ff8dd6a | 397 | us_timestamp_t |
Wayne Roberts |
0:9c052ff8dd6a | 398 | Radio::TimeOnAir(RadioModems_t m, uint8_t pktLen) |
Wayne Roberts |
0:9c052ff8dd6a | 399 | { |
Wayne Roberts |
0:9c052ff8dd6a | 400 | uint32_t airTime = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 401 | |
Wayne Roberts |
0:9c052ff8dd6a | 402 | switch (m) |
Wayne Roberts |
0:9c052ff8dd6a | 403 | { |
Wayne Roberts |
0:9c052ff8dd6a | 404 | case MODEM_FSK: |
Wayne Roberts |
0:9c052ff8dd6a | 405 | { |
Wayne Roberts |
0:9c052ff8dd6a | 406 | /* TODO |
Wayne Roberts |
0:9c052ff8dd6a | 407 | airTime = round( ( 8 * ( SX1272.Settings.Fsk.PreambleLen + |
Wayne Roberts |
0:9c052ff8dd6a | 408 | ( ( SX1272Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) + |
Wayne Roberts |
0:9c052ff8dd6a | 409 | ( ( SX1272.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) + |
Wayne Roberts |
0:9c052ff8dd6a | 410 | ( ( ( SX1272Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) + |
Wayne Roberts |
0:9c052ff8dd6a | 411 | pktLen + |
Wayne Roberts |
0:9c052ff8dd6a | 412 | ( ( SX1272.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) / |
Wayne Roberts |
0:9c052ff8dd6a | 413 | SX1272.Settings.Fsk.Datarate ) * 1e3 ); |
Wayne Roberts |
0:9c052ff8dd6a | 414 | */ |
Wayne Roberts |
0:9c052ff8dd6a | 415 | } |
Wayne Roberts |
0:9c052ff8dd6a | 416 | break; |
Wayne Roberts |
0:9c052ff8dd6a | 417 | case MODEM_LORA: |
Wayne Roberts |
0:9c052ff8dd6a | 418 | { |
Wayne Roberts |
0:9c052ff8dd6a | 419 | double bw = 0.0; |
Wayne Roberts |
0:9c052ff8dd6a | 420 | uint8_t fixLen, bandwidth, LowDatarateOptimize, coderate, crcOn ; |
Wayne Roberts |
0:9c052ff8dd6a | 421 | if (radio.type == SX1276) { |
Wayne Roberts |
0:9c052ff8dd6a | 422 | coderate = lora.RegModemConfig.sx1276bits.CodingRate; |
Wayne Roberts |
0:9c052ff8dd6a | 423 | LowDatarateOptimize = lora.RegModemConfig3.sx1276bits.LowDataRateOptimize; |
Wayne Roberts |
0:9c052ff8dd6a | 424 | fixLen = lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn; |
Wayne Roberts |
0:9c052ff8dd6a | 425 | bandwidth = lora.RegModemConfig.sx1276bits.Bw - 7; |
Wayne Roberts |
0:9c052ff8dd6a | 426 | crcOn = lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 427 | } else if (radio.type == SX1272) { |
Wayne Roberts |
0:9c052ff8dd6a | 428 | coderate = lora.RegModemConfig.sx1272bits.CodingRate; |
Wayne Roberts |
0:9c052ff8dd6a | 429 | LowDatarateOptimize = lora.RegModemConfig.sx1272bits.LowDataRateOptimize; |
Wayne Roberts |
0:9c052ff8dd6a | 430 | fixLen = lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn; |
Wayne Roberts |
0:9c052ff8dd6a | 431 | bandwidth = lora.RegModemConfig.sx1272bits.Bw; |
Wayne Roberts |
0:9c052ff8dd6a | 432 | crcOn = lora.RegModemConfig.sx1272bits.RxPayloadCrcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 433 | } else |
Wayne Roberts |
0:9c052ff8dd6a | 434 | return 0; |
Wayne Roberts |
0:9c052ff8dd6a | 435 | |
Wayne Roberts |
0:9c052ff8dd6a | 436 | switch( bandwidth ) |
Wayne Roberts |
0:9c052ff8dd6a | 437 | { |
Wayne Roberts |
0:9c052ff8dd6a | 438 | case 0: // 125 kHz |
Wayne Roberts |
0:9c052ff8dd6a | 439 | bw = 125;//ms: 125e3; |
Wayne Roberts |
0:9c052ff8dd6a | 440 | break; |
Wayne Roberts |
0:9c052ff8dd6a | 441 | case 1: // 250 kHz |
Wayne Roberts |
0:9c052ff8dd6a | 442 | bw = 250;//ms:250e3; |
Wayne Roberts |
0:9c052ff8dd6a | 443 | break; |
Wayne Roberts |
0:9c052ff8dd6a | 444 | case 2: // 500 kHz |
Wayne Roberts |
0:9c052ff8dd6a | 445 | bw = 500;//ms:500e3; |
Wayne Roberts |
0:9c052ff8dd6a | 446 | break; |
Wayne Roberts |
0:9c052ff8dd6a | 447 | } |
Wayne Roberts |
0:9c052ff8dd6a | 448 | |
Wayne Roberts |
0:9c052ff8dd6a | 449 | // Symbol rate : time for one symbol (secs) |
Wayne Roberts |
0:9c052ff8dd6a | 450 | double rs = bw / ( 1 << lora.RegModemConfig2.sx1276bits.SpreadingFactor ); |
Wayne Roberts |
0:9c052ff8dd6a | 451 | double ts = 1 / rs; |
Wayne Roberts |
0:9c052ff8dd6a | 452 | // time of preamble |
Wayne Roberts |
0:9c052ff8dd6a | 453 | double tPreamble; |
Wayne Roberts |
0:9c052ff8dd6a | 454 | tPreamble = (lora.RegPreamble + 4.25 ) * ts; |
Wayne Roberts |
0:9c052ff8dd6a | 455 | // Symbol length of payload and time |
Wayne Roberts |
0:9c052ff8dd6a | 456 | double tmp = ceil( ( 8 * pktLen - 4 * lora.RegModemConfig2.sx1276bits.SpreadingFactor + |
Wayne Roberts |
0:9c052ff8dd6a | 457 | 28 + 16 * crcOn - |
Wayne Roberts |
0:9c052ff8dd6a | 458 | ( fixLen ? 20 : 0 ) ) / |
Wayne Roberts |
0:9c052ff8dd6a | 459 | ( double )( 4 * ( lora.RegModemConfig2.sx1276bits.SpreadingFactor - |
Wayne Roberts |
0:9c052ff8dd6a | 460 | ( ( LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * |
Wayne Roberts |
0:9c052ff8dd6a | 461 | ( coderate + 4 ); |
Wayne Roberts |
0:9c052ff8dd6a | 462 | double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); |
Wayne Roberts |
0:9c052ff8dd6a | 463 | double tPayload = nPayload * ts; |
Wayne Roberts |
0:9c052ff8dd6a | 464 | // Time on air |
Wayne Roberts |
0:9c052ff8dd6a | 465 | double tOnAir = tPreamble + tPayload; |
Wayne Roberts |
0:9c052ff8dd6a | 466 | // return ms secs |
Wayne Roberts |
0:9c052ff8dd6a | 467 | airTime = floor( tOnAir * 1e3 + 0.999 ); |
Wayne Roberts |
0:9c052ff8dd6a | 468 | } |
Wayne Roberts |
0:9c052ff8dd6a | 469 | break; |
Wayne Roberts |
0:9c052ff8dd6a | 470 | } |
Wayne Roberts |
0:9c052ff8dd6a | 471 | return airTime; |
Wayne Roberts |
0:9c052ff8dd6a | 472 | |
Wayne Roberts |
0:9c052ff8dd6a | 473 | } |
Wayne Roberts |
0:9c052ff8dd6a | 474 | #endif /* DUTY_ENABLE */ |
Wayne Roberts |
0:9c052ff8dd6a | 475 | |
Wayne Roberts |
0:9c052ff8dd6a | 476 | void Radio::service() |
Wayne Roberts |
0:9c052ff8dd6a | 477 | { |
Wayne Roberts |
0:9c052ff8dd6a | 478 | if (pinEvent.dio0) { |
Wayne Roberts |
17:5f34cbe2ac53 | 479 | dio0UserContext(); |
Wayne Roberts |
17:5f34cbe2ac53 | 480 | pinEvent.txing = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 481 | pinEvent.dio0 = 0; |
Wayne Roberts |
10:3303cf2867d4 | 482 | } else if (radio.dio0.read()) { |
Wayne Roberts |
10:3303cf2867d4 | 483 | /* fail: missed interrupt */ |
Wayne Roberts |
10:3303cf2867d4 | 484 | dio0isr(); |
Wayne Roberts |
0:9c052ff8dd6a | 485 | } |
Wayne Roberts |
0:9c052ff8dd6a | 486 | |
Wayne Roberts |
0:9c052ff8dd6a | 487 | if (pinEvent.dio1) { |
Wayne Roberts |
0:9c052ff8dd6a | 488 | dio1UserContext(); |
Wayne Roberts |
0:9c052ff8dd6a | 489 | pinEvent.dio1 = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 490 | } |
Wayne Roberts |
0:9c052ff8dd6a | 491 | } |
Wayne Roberts |
0:9c052ff8dd6a | 492 | |
Wayne Roberts |
0:9c052ff8dd6a | 493 | uint32_t Radio::lora_toa_us( uint8_t pktLen ) |
Wayne Roberts |
0:9c052ff8dd6a | 494 | { |
Wayne Roberts |
0:9c052ff8dd6a | 495 | uint32_t airTime = 0; |
Wayne Roberts |
0:9c052ff8dd6a | 496 | uint8_t chipBW = Radio::lora.getBw(); |
Wayne Roberts |
0:9c052ff8dd6a | 497 | double bwKHz; |
Wayne Roberts |
0:9c052ff8dd6a | 498 | uint8_t LowDataRateOptimize; |
Wayne Roberts |
0:9c052ff8dd6a | 499 | bool FixLen; |
Wayne Roberts |
0:9c052ff8dd6a | 500 | uint8_t crcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 501 | uint16_t preambleLen = Radio::radio.read_u16(REG_LR_PREAMBLEMSB); |
Wayne Roberts |
0:9c052ff8dd6a | 502 | |
Wayne Roberts |
0:9c052ff8dd6a | 503 | Radio::lora.RegModemConfig2.octet = Radio::radio.read_reg(REG_LR_MODEMCONFIG2); |
Wayne Roberts |
0:9c052ff8dd6a | 504 | Radio::lora.RegModemConfig.octet = Radio::radio.read_reg(REG_LR_MODEMCONFIG); |
Wayne Roberts |
0:9c052ff8dd6a | 505 | |
Wayne Roberts |
0:9c052ff8dd6a | 506 | if (Radio::radio.type == SX1276) { |
Wayne Roberts |
0:9c052ff8dd6a | 507 | chipBW -= 7; |
Wayne Roberts |
0:9c052ff8dd6a | 508 | Radio::lora.RegModemConfig3.octet = Radio::radio.read_reg(REG_LR_MODEMCONFIG3); |
Wayne Roberts |
0:9c052ff8dd6a | 509 | LowDataRateOptimize = Radio::lora.RegModemConfig3.sx1276bits.LowDataRateOptimize; |
Wayne Roberts |
0:9c052ff8dd6a | 510 | FixLen = Radio::lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn; |
Wayne Roberts |
0:9c052ff8dd6a | 511 | crcOn = Radio::lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 512 | } else if (Radio::radio.type == SX1272) { |
Wayne Roberts |
0:9c052ff8dd6a | 513 | LowDataRateOptimize = Radio::lora.RegModemConfig.sx1272bits.LowDataRateOptimize; |
Wayne Roberts |
0:9c052ff8dd6a | 514 | FixLen = Radio::lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn; |
Wayne Roberts |
0:9c052ff8dd6a | 515 | crcOn = Radio::lora.RegModemConfig.sx1272bits.RxPayloadCrcOn; |
Wayne Roberts |
0:9c052ff8dd6a | 516 | } else |
Wayne Roberts |
0:9c052ff8dd6a | 517 | return 0; |
Wayne Roberts |
0:9c052ff8dd6a | 518 | |
Wayne Roberts |
0:9c052ff8dd6a | 519 | switch (chipBW) { |
Wayne Roberts |
0:9c052ff8dd6a | 520 | case 0: bwKHz = 125; break; |
Wayne Roberts |
0:9c052ff8dd6a | 521 | case 1: bwKHz = 250; break; |
Wayne Roberts |
0:9c052ff8dd6a | 522 | case 2: bwKHz = 500; break; |
Wayne Roberts |
0:9c052ff8dd6a | 523 | default: return 0; |
Wayne Roberts |
0:9c052ff8dd6a | 524 | } |
Wayne Roberts |
0:9c052ff8dd6a | 525 | |
Wayne Roberts |
0:9c052ff8dd6a | 526 | // Symbol rate : time for one symbol (secs) |
Wayne Roberts |
0:9c052ff8dd6a | 527 | double rs = bwKHz / ( 1 << Radio::lora.RegModemConfig2.sx1276bits.SpreadingFactor ); |
Wayne Roberts |
0:9c052ff8dd6a | 528 | double ts = 1 / rs; |
Wayne Roberts |
0:9c052ff8dd6a | 529 | // time of preamble |
Wayne Roberts |
0:9c052ff8dd6a | 530 | double tPreamble = ( preambleLen + 4.25 ) * ts; |
Wayne Roberts |
0:9c052ff8dd6a | 531 | // Symbol length of payload and time |
Wayne Roberts |
0:9c052ff8dd6a | 532 | double tmp = ceil( ( 8 * pktLen - 4 * Radio::lora.RegModemConfig2.sx1276bits.SpreadingFactor + |
Wayne Roberts |
0:9c052ff8dd6a | 533 | 28 + 16 * crcOn - |
Wayne Roberts |
0:9c052ff8dd6a | 534 | ( FixLen ? 20 : 0 ) ) / |
Wayne Roberts |
0:9c052ff8dd6a | 535 | ( double )( 4 * ( Radio::lora.RegModemConfig2.sx1276bits.SpreadingFactor - |
Wayne Roberts |
0:9c052ff8dd6a | 536 | ( ( LowDataRateOptimize > 0 ) ? 2 : 0 ) ) ) ) * |
Wayne Roberts |
0:9c052ff8dd6a | 537 | ( Radio::lora.getCodingRate(false) + 4 ); |
Wayne Roberts |
0:9c052ff8dd6a | 538 | double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); |
Wayne Roberts |
0:9c052ff8dd6a | 539 | double tPayload = nPayload * ts; |
Wayne Roberts |
0:9c052ff8dd6a | 540 | // Time on air |
Wayne Roberts |
0:9c052ff8dd6a | 541 | double tOnAir = tPreamble + tPayload; |
Wayne Roberts |
0:9c052ff8dd6a | 542 | // return microseconds |
Wayne Roberts |
0:9c052ff8dd6a | 543 | airTime = floor( tOnAir * 1000 + 0.999 ); |
Wayne Roberts |
0:9c052ff8dd6a | 544 | |
Wayne Roberts |
0:9c052ff8dd6a | 545 | return airTime; |
Wayne Roberts |
0:9c052ff8dd6a | 546 | } |
Wayne Roberts |
0:9c052ff8dd6a | 547 | #endif /* ..SX127x_H */ |
Wayne Roberts |
0:9c052ff8dd6a | 548 |