wayne roberts / lorawan1v1

Dependencies:   sx12xx_hal

Dependents:   LoRaWAN-SanJose_Bootcamp LoRaWAN-grove-cayenne LoRaWAN-classC-demo LoRaWAN-grove-cayenne ... more

Committer:
Wayne Roberts
Date:
Fri May 04 11:00:06 2018 -0700
Revision:
7:4b6f960dcca2
Parent:
4:e4bfe9183f94
Add class-C support, and LBT

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 0:6b3ac9c5a042 1 #include "board.h"
Wayne Roberts 0:6b3ac9c5a042 2 #include "radio.h"
Wayne Roberts 0:6b3ac9c5a042 3
Wayne Roberts 0:6b3ac9c5a042 4 LowPowerTimer Radio::lpt;
Wayne Roberts 0:6b3ac9c5a042 5
Wayne Roberts 0:6b3ac9c5a042 6 void Radio::Sleep()
Wayne Roberts 0:6b3ac9c5a042 7 {
Wayne Roberts 0:6b3ac9c5a042 8 radio.set_opmode(RF_OPMODE_SLEEP);
Wayne Roberts 0:6b3ac9c5a042 9 }
Wayne Roberts 0:6b3ac9c5a042 10
Wayne Roberts 0:6b3ac9c5a042 11 void Radio::Standby()
Wayne Roberts 0:6b3ac9c5a042 12 {
Wayne Roberts 0:6b3ac9c5a042 13 radio.set_opmode(RF_OPMODE_STANDBY);
Wayne Roberts 0:6b3ac9c5a042 14 }
Wayne Roberts 0:6b3ac9c5a042 15
Wayne Roberts 0:6b3ac9c5a042 16 bool Radio::CheckRfFrequency(unsigned hz)
Wayne Roberts 0:6b3ac9c5a042 17 {
Wayne Roberts 0:6b3ac9c5a042 18 return true;
Wayne Roberts 0:6b3ac9c5a042 19 }
Wayne Roberts 0:6b3ac9c5a042 20
Wayne Roberts 0:6b3ac9c5a042 21 void Radio::SetChannel(unsigned hz)
Wayne Roberts 0:6b3ac9c5a042 22 {
Wayne Roberts 0:6b3ac9c5a042 23 radio.set_frf_MHz(hz / 1000000.0);
Wayne Roberts 0:6b3ac9c5a042 24 MAC_PRINTF(" %uhz ", hz);
Wayne Roberts 0:6b3ac9c5a042 25 }
Wayne Roberts 0:6b3ac9c5a042 26
Wayne Roberts 0:6b3ac9c5a042 27 LowPowerTimeout TxTimeoutEvent;
Wayne Roberts 0:6b3ac9c5a042 28
Wayne Roberts 0:6b3ac9c5a042 29 void SX1272OnTimeoutIrq( void )
Wayne Roberts 0:6b3ac9c5a042 30 {
Wayne Roberts 0:6b3ac9c5a042 31 Radio::radio.set_opmode(RF_OPMODE_STANDBY);
Wayne Roberts 0:6b3ac9c5a042 32 }
Wayne Roberts 0:6b3ac9c5a042 33
Wayne Roberts 0:6b3ac9c5a042 34 void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us)
Wayne Roberts 0:6b3ac9c5a042 35 {
Wayne Roberts 0:6b3ac9c5a042 36 Radio::SetChannel(hz);
Wayne Roberts 0:6b3ac9c5a042 37 /* TODO: fsk enable, set regPacketConfig2.datamode */
Wayne Roberts 0:6b3ac9c5a042 38 set_tx_dbm(dbm);
Wayne Roberts 0:6b3ac9c5a042 39 TxTimeoutEvent.attach_us(SX1272OnTimeoutIrq, timeout_us);
Wayne Roberts 0:6b3ac9c5a042 40 radio.set_opmode(RF_OPMODE_TRANSMITTER);
Wayne Roberts 0:6b3ac9c5a042 41 }
Wayne Roberts 0:6b3ac9c5a042 42
Wayne Roberts 0:6b3ac9c5a042 43 #define LORA_MAC_PRIVATE_SYNCWORD 0x12
Wayne Roberts 0:6b3ac9c5a042 44 #define LORA_MAC_PUBLIC_SYNCWORD 0x34
Wayne Roberts 0:6b3ac9c5a042 45 void Radio::SetPublicNetwork(bool en)
Wayne Roberts 0:6b3ac9c5a042 46 {
Wayne Roberts 0:6b3ac9c5a042 47 radio.write_reg(REG_LR_SYNC_BYTE, en ? LORA_MAC_PUBLIC_SYNCWORD : LORA_MAC_PRIVATE_SYNCWORD);
Wayne Roberts 0:6b3ac9c5a042 48 }
Wayne Roberts 0:6b3ac9c5a042 49
Wayne Roberts 0:6b3ac9c5a042 50 uint32_t Radio::Random(void)
Wayne Roberts 0:6b3ac9c5a042 51 {
Wayne Roberts 0:6b3ac9c5a042 52 uint32_t ret = 0;
Wayne Roberts 0:6b3ac9c5a042 53 unsigned i;
Wayne Roberts 0:6b3ac9c5a042 54
Wayne Roberts 0:6b3ac9c5a042 55 radio.set_opmode(RF_OPMODE_RECEIVER);
Wayne Roberts 0:6b3ac9c5a042 56 for (i = 0; i < 32; i++) {
Wayne Roberts 0:6b3ac9c5a042 57 uint32_t r;
Wayne Roberts 0:6b3ac9c5a042 58 wait_us(3000);
Wayne Roberts 0:6b3ac9c5a042 59 r = radio.read_reg(REG_LR_WIDEBAND_RSSI);
Wayne Roberts 0:6b3ac9c5a042 60 r <<= ((i & 7) << 2);
Wayne Roberts 0:6b3ac9c5a042 61 ret ^= r;
Wayne Roberts 0:6b3ac9c5a042 62 }
Wayne Roberts 0:6b3ac9c5a042 63
Wayne Roberts 0:6b3ac9c5a042 64 return ret;
Wayne Roberts 0:6b3ac9c5a042 65 }
Wayne Roberts 0:6b3ac9c5a042 66
Wayne Roberts 0:6b3ac9c5a042 67 void Radio::LoRaConfig(uint32_t bandwidth, uint8_t datarate, uint8_t coderate, uint16_t preambleLen, bool fixLen, bool crcOn)
Wayne Roberts 0:6b3ac9c5a042 68 {
Wayne Roberts 0:6b3ac9c5a042 69 float sp;
Wayne Roberts 0:6b3ac9c5a042 70
Wayne Roberts 0:6b3ac9c5a042 71 if (!radio.RegOpMode.bits.LongRangeMode) {
Wayne Roberts 0:6b3ac9c5a042 72 lora.enable();
Wayne Roberts 0:6b3ac9c5a042 73 }
Wayne Roberts 0:6b3ac9c5a042 74 radio.write_reg(REG_LR_IRQFLAGSMASK, 0);
Wayne Roberts 0:6b3ac9c5a042 75
Wayne Roberts 0:6b3ac9c5a042 76 MAC_PRINTF("sf%u bw%u ", datarate, bandwidth);
Wayne Roberts 0:6b3ac9c5a042 77 lora.RegModemConfig2.sx1276bits.SpreadingFactor = datarate;
Wayne Roberts 0:6b3ac9c5a042 78 if (radio.type == SX1276) {
Wayne Roberts 0:6b3ac9c5a042 79 MAC_PRINTF("sx1276 ");
Wayne Roberts 0:6b3ac9c5a042 80 lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn = crcOn;
Wayne Roberts 0:6b3ac9c5a042 81 lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn = fixLen;
Wayne Roberts 0:6b3ac9c5a042 82 lora.RegModemConfig.sx1276bits.CodingRate = coderate;
Wayne Roberts 0:6b3ac9c5a042 83 lora.RegModemConfig.sx1276bits.Bw = bandwidth + 7;
Wayne Roberts 0:6b3ac9c5a042 84 lora.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3);
Wayne Roberts 0:6b3ac9c5a042 85 sp = lora.get_symbol_period();
Wayne Roberts 0:6b3ac9c5a042 86 if (sp > 16)
Wayne Roberts 0:6b3ac9c5a042 87 lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 1;
Wayne Roberts 0:6b3ac9c5a042 88 else
Wayne Roberts 0:6b3ac9c5a042 89 lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 0;
Wayne Roberts 0:6b3ac9c5a042 90 radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet);
Wayne Roberts 0:6b3ac9c5a042 91 } else if (radio.type == SX1272) {
Wayne Roberts 0:6b3ac9c5a042 92 lora.RegModemConfig.sx1272bits.RxPayloadCrcOn = crcOn;
Wayne Roberts 0:6b3ac9c5a042 93 lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn = fixLen;
Wayne Roberts 0:6b3ac9c5a042 94 lora.RegModemConfig.sx1272bits.CodingRate = coderate;
Wayne Roberts 0:6b3ac9c5a042 95 lora.RegModemConfig.sx1272bits.Bw = bandwidth;
Wayne Roberts 0:6b3ac9c5a042 96 if (lora.get_symbol_period() > 16)
Wayne Roberts 0:6b3ac9c5a042 97 lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 1;
Wayne Roberts 0:6b3ac9c5a042 98 else
Wayne Roberts 0:6b3ac9c5a042 99 lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 0;
Wayne Roberts 0:6b3ac9c5a042 100 MAC_PRINTF("sx1272 ");
Wayne Roberts 0:6b3ac9c5a042 101 } else {
Wayne Roberts 0:6b3ac9c5a042 102 MAC_PRINTF("\e[31msx127?\e[0m ");
Wayne Roberts 0:6b3ac9c5a042 103 return;
Wayne Roberts 0:6b3ac9c5a042 104 }
Wayne Roberts 0:6b3ac9c5a042 105
Wayne Roberts 0:6b3ac9c5a042 106 //printf(" {%02x %02x} ", lora.RegModemConfig.octet, lora.RegModemConfig2.octet);
Wayne Roberts 0:6b3ac9c5a042 107 radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet);
Wayne Roberts 0:6b3ac9c5a042 108 radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet);
Wayne Roberts 0:6b3ac9c5a042 109
Wayne Roberts 0:6b3ac9c5a042 110 lora.RegPreamble = preambleLen;
Wayne Roberts 0:6b3ac9c5a042 111 radio.write_u16(REG_LR_PREAMBLEMSB, lora.RegPreamble);
Wayne Roberts 0:6b3ac9c5a042 112 }
Wayne Roberts 0:6b3ac9c5a042 113
Wayne Roberts 0:6b3ac9c5a042 114 void Radio::SetRxConfig(
Wayne Roberts 0:6b3ac9c5a042 115 RadioModems_t modem,
Wayne Roberts 0:6b3ac9c5a042 116 uint32_t bandwidth,
Wayne Roberts 0:6b3ac9c5a042 117 uint32_t datarate,
Wayne Roberts 0:6b3ac9c5a042 118 uint8_t coderate,
Wayne Roberts 0:6b3ac9c5a042 119 uint32_t bandwidthAfc,
Wayne Roberts 0:6b3ac9c5a042 120 uint16_t preambleLen,
Wayne Roberts 0:6b3ac9c5a042 121 uint16_t symbTimeout,
Wayne Roberts 0:6b3ac9c5a042 122 bool fixLen,
Wayne Roberts 0:6b3ac9c5a042 123 uint8_t payloadLen,
Wayne Roberts 0:6b3ac9c5a042 124 bool crcOn,
Wayne Roberts 0:6b3ac9c5a042 125 bool iqInverted)
Wayne Roberts 0:6b3ac9c5a042 126 {
Wayne Roberts 0:6b3ac9c5a042 127 if (modem == MODEM_FSK) {
Wayne Roberts 0:6b3ac9c5a042 128 if (radio.RegOpMode.bits.LongRangeMode)
Wayne Roberts 0:6b3ac9c5a042 129 fsk.enable(false);
Wayne Roberts 0:6b3ac9c5a042 130 /* TODO */
Wayne Roberts 0:6b3ac9c5a042 131 //uint32_t bandwidthAfc,
Wayne Roberts 0:6b3ac9c5a042 132 } else if (modem == MODEM_LORA) {
Wayne Roberts 0:6b3ac9c5a042 133 uint16_t reg_u16;
Wayne Roberts 0:6b3ac9c5a042 134
Wayne Roberts 0:6b3ac9c5a042 135 LoRaConfig(bandwidth, datarate, coderate, preambleLen, fixLen, crcOn);
Wayne Roberts 0:6b3ac9c5a042 136
Wayne Roberts 0:6b3ac9c5a042 137 reg_u16 = radio.read_u16(REG_LR_MODEMCONFIG2);
Wayne Roberts 0:6b3ac9c5a042 138 reg_u16 &= 0xfc00;
Wayne Roberts 0:6b3ac9c5a042 139 reg_u16 |= symbTimeout;
Wayne Roberts 0:6b3ac9c5a042 140 radio.write_u16(REG_LR_MODEMCONFIG2, reg_u16);
Wayne Roberts 0:6b3ac9c5a042 141 //MAC_PRINTF("rxconf symbt %02x %02x mask:%02x\r\n", radio.read_reg(REG_LR_MODEMCONFIG2), radio.read_reg(REG_LR_MODEMCONFIG2+1), radio.read_reg(REG_LR_IRQFLAGSMASK));
Wayne Roberts 0:6b3ac9c5a042 142
Wayne Roberts 0:6b3ac9c5a042 143 lora.invert_rx(iqInverted);
Wayne Roberts 0:6b3ac9c5a042 144 }
Wayne Roberts 0:6b3ac9c5a042 145 }
Wayne Roberts 0:6b3ac9c5a042 146
Wayne Roberts 0:6b3ac9c5a042 147 void Radio::SetTxConfig(
Wayne Roberts 0:6b3ac9c5a042 148 RadioModems_t modem,
Wayne Roberts 0:6b3ac9c5a042 149 int8_t dbm,
Wayne Roberts 0:6b3ac9c5a042 150 uint32_t fdev,
Wayne Roberts 0:6b3ac9c5a042 151 uint32_t bandwidth,
Wayne Roberts 0:6b3ac9c5a042 152 uint32_t datarate,
Wayne Roberts 0:6b3ac9c5a042 153 uint8_t coderate,
Wayne Roberts 0:6b3ac9c5a042 154 uint16_t preambleLen,
Wayne Roberts 0:6b3ac9c5a042 155 bool fixLen,
Wayne Roberts 0:6b3ac9c5a042 156 bool crcOn,
Wayne Roberts 0:6b3ac9c5a042 157 bool iqInverted)
Wayne Roberts 0:6b3ac9c5a042 158 {
Wayne Roberts 0:6b3ac9c5a042 159 set_tx_dbm(dbm);
Wayne Roberts 0:6b3ac9c5a042 160
Wayne Roberts 0:6b3ac9c5a042 161 if (modem == MODEM_FSK) {
Wayne Roberts 0:6b3ac9c5a042 162 if (radio.RegOpMode.bits.LongRangeMode)
Wayne Roberts 0:6b3ac9c5a042 163 fsk.enable(false);
Wayne Roberts 0:6b3ac9c5a042 164 /* TODO */
Wayne Roberts 0:6b3ac9c5a042 165 } else if (modem == MODEM_LORA) {
Wayne Roberts 0:6b3ac9c5a042 166 LoRaConfig(bandwidth, datarate, coderate, preambleLen, fixLen, crcOn);
Wayne Roberts 0:6b3ac9c5a042 167
Wayne Roberts 0:6b3ac9c5a042 168 lora.invert_tx(iqInverted);
Wayne Roberts 0:6b3ac9c5a042 169 }
Wayne Roberts 0:6b3ac9c5a042 170 }
Wayne Roberts 0:6b3ac9c5a042 171
Wayne Roberts 0:6b3ac9c5a042 172 void Radio::SetRxMaxPayloadLength(RadioModems_t modem, uint8_t max)
Wayne Roberts 0:6b3ac9c5a042 173 {
Wayne Roberts 0:6b3ac9c5a042 174 /* TODO fsk */
Wayne Roberts 0:6b3ac9c5a042 175 radio.write_reg(REG_LR_RX_MAX_PAYLOADLENGTH, max);
Wayne Roberts 0:6b3ac9c5a042 176 }
Wayne Roberts 0:6b3ac9c5a042 177
Wayne Roberts 0:6b3ac9c5a042 178 const RadioEvents_t* RadioEvents;
Wayne Roberts 0:6b3ac9c5a042 179
Wayne Roberts 0:6b3ac9c5a042 180
Wayne Roberts 0:6b3ac9c5a042 181 #if 0
Wayne Roberts 0:6b3ac9c5a042 182 void dumpregs()
Wayne Roberts 0:6b3ac9c5a042 183 {
Wayne Roberts 0:6b3ac9c5a042 184 unsigned i;
Wayne Roberts 0:6b3ac9c5a042 185 //MAC_PRINTF("%02x) %02x\r\n", i, radio.read_reg(i));
Wayne Roberts 0:6b3ac9c5a042 186 for (i = 0; i < 0x70; i++) {
Wayne Roberts 0:6b3ac9c5a042 187 MAC_PRINTF("%02x) %02x\r\n", i, radio.read_reg(i));
Wayne Roberts 0:6b3ac9c5a042 188 }
Wayne Roberts 0:6b3ac9c5a042 189 }
Wayne Roberts 0:6b3ac9c5a042 190 #endif /* if 0 */
Wayne Roberts 0:6b3ac9c5a042 191
Wayne Roberts 4:e4bfe9183f94 192 volatile struct pe {
Wayne Roberts 4:e4bfe9183f94 193 uint8_t dio0 : 1;
Wayne Roberts 4:e4bfe9183f94 194 uint8_t dio1 : 1;
Wayne Roberts 4:e4bfe9183f94 195 uint8_t txing : 1;
Wayne Roberts 4:e4bfe9183f94 196 } pinEvent;
Wayne Roberts 4:e4bfe9183f94 197 volatile us_timestamp_t dio0at;
Wayne Roberts 0:6b3ac9c5a042 198
Wayne Roberts 4:e4bfe9183f94 199 void
Wayne Roberts 4:e4bfe9183f94 200 Radio::dio0UserContext()
Wayne Roberts 4:e4bfe9183f94 201 {
Wayne Roberts 4:e4bfe9183f94 202 if (!pinEvent.txing) {
Wayne Roberts 0:6b3ac9c5a042 203 lora.service();
Wayne Roberts 0:6b3ac9c5a042 204 if (!lora.RegIrqFlags.bits.RxDone) {
Wayne Roberts 0:6b3ac9c5a042 205 MAC_PRINTF("not-rxdone\r\n");
Wayne Roberts 0:6b3ac9c5a042 206 } else if (RadioEvents->RxDone) {
Wayne Roberts 0:6b3ac9c5a042 207 int8_t rssi;
Wayne Roberts 0:6b3ac9c5a042 208 float snr = lora.RegPktSnrValue / 4.0;
Wayne Roberts 0:6b3ac9c5a042 209
Wayne Roberts 0:6b3ac9c5a042 210 rssi = lora.get_pkt_rssi();
Wayne Roberts 0:6b3ac9c5a042 211 if (snr < 0)
Wayne Roberts 0:6b3ac9c5a042 212 rssi += snr;
Wayne Roberts 0:6b3ac9c5a042 213 //MAC_PRINTF("rxdone snr:%.2f, rssi:%d\r\n", snr, rssi);
Wayne Roberts 4:e4bfe9183f94 214 RadioEvents->RxDone(radio.rx_buf, lora.RegRxNbBytes, rssi, snr, dio0at);
Wayne Roberts 0:6b3ac9c5a042 215 }
Wayne Roberts 4:e4bfe9183f94 216 }
Wayne Roberts 4:e4bfe9183f94 217 }
Wayne Roberts 4:e4bfe9183f94 218
Wayne Roberts 4:e4bfe9183f94 219 void Radio::dio0isr()
Wayne Roberts 4:e4bfe9183f94 220 {
Wayne Roberts 4:e4bfe9183f94 221 dio0at = lpt.read_us();
Wayne Roberts 4:e4bfe9183f94 222
Wayne Roberts 4:e4bfe9183f94 223 if (pinEvent.txing) {
Wayne Roberts 4:e4bfe9183f94 224 /* TxDone handling requires low latency */
Wayne Roberts 4:e4bfe9183f94 225 if (RadioEvents->TxDone)
Wayne Roberts 4:e4bfe9183f94 226 RadioEvents->TxDone(dio0at);
Wayne Roberts 4:e4bfe9183f94 227
Wayne Roberts 0:6b3ac9c5a042 228 lora.service();
Wayne Roberts 4:e4bfe9183f94 229 pinEvent.txing = 0;
Wayne Roberts 4:e4bfe9183f94 230 } else
Wayne Roberts 4:e4bfe9183f94 231 pinEvent.dio0 = 1;
Wayne Roberts 4:e4bfe9183f94 232 }
Wayne Roberts 0:6b3ac9c5a042 233
Wayne Roberts 4:e4bfe9183f94 234 void Radio::dio1UserContext()
Wayne Roberts 0:6b3ac9c5a042 235 {
Wayne Roberts 0:6b3ac9c5a042 236 lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
Wayne Roberts 0:6b3ac9c5a042 237
Wayne Roberts 0:6b3ac9c5a042 238 MAC_PRINTF("\e[7mdio1:%02x\e[0m\r\n", lora.RegIrqFlags.octet);
Wayne Roberts 7:4b6f960dcca2 239
Wayne Roberts 7:4b6f960dcca2 240 if (RadioEvents->RxTimeout)
Wayne Roberts 0:6b3ac9c5a042 241 RadioEvents->RxTimeout();
Wayne Roberts 7:4b6f960dcca2 242
Wayne Roberts 7:4b6f960dcca2 243 radio.write_reg(REG_LR_IRQFLAGS, 0x80); // ensure RxTimeout is cleared
Wayne Roberts 0:6b3ac9c5a042 244 }
Wayne Roberts 0:6b3ac9c5a042 245
Wayne Roberts 4:e4bfe9183f94 246 void Radio::dio1isr()
Wayne Roberts 4:e4bfe9183f94 247 {
Wayne Roberts 4:e4bfe9183f94 248 pinEvent.dio1 = 1;
Wayne Roberts 4:e4bfe9183f94 249 }
Wayne Roberts 4:e4bfe9183f94 250
Wayne Roberts 0:6b3ac9c5a042 251 void Radio::Init(const RadioEvents_t* e)
Wayne Roberts 0:6b3ac9c5a042 252 {
Wayne Roberts 4:e4bfe9183f94 253 dio0.rise(dio0isr);
Wayne Roberts 4:e4bfe9183f94 254 dio1.rise(dio1isr);
Wayne Roberts 0:6b3ac9c5a042 255
Wayne Roberts 0:6b3ac9c5a042 256 radio.rf_switch = rfsw_callback;
Wayne Roberts 0:6b3ac9c5a042 257 boardInit();
Wayne Roberts 0:6b3ac9c5a042 258
Wayne Roberts 0:6b3ac9c5a042 259 RadioEvents = e;
Wayne Roberts 0:6b3ac9c5a042 260 lpt.start();
Wayne Roberts 0:6b3ac9c5a042 261 }
Wayne Roberts 0:6b3ac9c5a042 262
Wayne Roberts 7:4b6f960dcca2 263 int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh)
Wayne Roberts 0:6b3ac9c5a042 264 {
Wayne Roberts 0:6b3ac9c5a042 265 if (radio.RegOpMode.bits.Mode == RF_OPMODE_SLEEP) {
Wayne Roberts 0:6b3ac9c5a042 266 radio.set_opmode(RF_OPMODE_STANDBY);
Wayne Roberts 0:6b3ac9c5a042 267 wait_us(1000);
Wayne Roberts 0:6b3ac9c5a042 268 }
Wayne Roberts 7:4b6f960dcca2 269 radio.write_reg(REG_LR_IRQFLAGS, 0x08); // ensure TxDone is cleared
Wayne Roberts 7:4b6f960dcca2 270 MAC_PRINTF("Radio::Send() dio:%u:%u opmode:%02x ", radio.dio0.read(), radio.dio1.read(), radio.read_reg(REG_OPMODE));
Wayne Roberts 0:6b3ac9c5a042 271 lora.RegPayloadLength = size;
Wayne Roberts 0:6b3ac9c5a042 272 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
Wayne Roberts 7:4b6f960dcca2 273
Wayne Roberts 7:4b6f960dcca2 274 if (maxListenTime > 0) {
Wayne Roberts 7:4b6f960dcca2 275 int rssi;
Wayne Roberts 7:4b6f960dcca2 276 us_timestamp_t startAt, chFreeAt, now;
Wayne Roberts 7:4b6f960dcca2 277 lora.start_rx(RF_OPMODE_RECEIVER);
Wayne Roberts 7:4b6f960dcca2 278 startAt = lpt.read_us();
Wayne Roberts 7:4b6f960dcca2 279 Lstart:
Wayne Roberts 7:4b6f960dcca2 280 do {
Wayne Roberts 7:4b6f960dcca2 281 now = lpt.read_us();
Wayne Roberts 7:4b6f960dcca2 282 if ((now - startAt) > maxListenTime) {
Wayne Roberts 7:4b6f960dcca2 283 return -1;
Wayne Roberts 7:4b6f960dcca2 284 }
Wayne Roberts 7:4b6f960dcca2 285 rssi = lora.get_current_rssi();
Wayne Roberts 7:4b6f960dcca2 286 } while (rssi > rssiThresh);
Wayne Roberts 7:4b6f960dcca2 287 chFreeAt = lpt.read_us();
Wayne Roberts 7:4b6f960dcca2 288 do {
Wayne Roberts 7:4b6f960dcca2 289 now = lpt.read_us();
Wayne Roberts 7:4b6f960dcca2 290 rssi = lora.get_current_rssi();
Wayne Roberts 7:4b6f960dcca2 291 if (rssi > rssiThresh) {
Wayne Roberts 7:4b6f960dcca2 292 goto Lstart;
Wayne Roberts 7:4b6f960dcca2 293 }
Wayne Roberts 7:4b6f960dcca2 294 } while ((now - chFreeAt) < channelFreeTime);
Wayne Roberts 7:4b6f960dcca2 295 }
Wayne Roberts 7:4b6f960dcca2 296
Wayne Roberts 0:6b3ac9c5a042 297 lora.start_tx(size);
Wayne Roberts 4:e4bfe9183f94 298 pinEvent.txing = 1;
Wayne Roberts 7:4b6f960dcca2 299
Wayne Roberts 7:4b6f960dcca2 300 return 0;
Wayne Roberts 0:6b3ac9c5a042 301 }
Wayne Roberts 0:6b3ac9c5a042 302
Wayne Roberts 0:6b3ac9c5a042 303 void Radio::Rx(unsigned timeout)
Wayne Roberts 0:6b3ac9c5a042 304 {
Wayne Roberts 7:4b6f960dcca2 305 if (timeout == 0) {
Wayne Roberts 0:6b3ac9c5a042 306 lora.start_rx(RF_OPMODE_RECEIVER);
Wayne Roberts 7:4b6f960dcca2 307 MAC_PRINTF("startRxC ");
Wayne Roberts 7:4b6f960dcca2 308 } else {
Wayne Roberts 7:4b6f960dcca2 309 lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); // yyy tmp remove
Wayne Roberts 0:6b3ac9c5a042 310 lora.start_rx(RF_OPMODE_RECEIVER_SINGLE);
Wayne Roberts 7:4b6f960dcca2 311 MAC_PRINTF("startRxS:%02x ", lora.RegIrqFlags.octet);
Wayne Roberts 7:4b6f960dcca2 312 }
Wayne Roberts 0:6b3ac9c5a042 313
Wayne Roberts 4:e4bfe9183f94 314 pinEvent.txing = 0;
Wayne Roberts 4:e4bfe9183f94 315
Wayne Roberts 0:6b3ac9c5a042 316 }
Wayne Roberts 0:6b3ac9c5a042 317
Wayne Roberts 0:6b3ac9c5a042 318
Wayne Roberts 0:6b3ac9c5a042 319 void Radio::ocp(uint8_t ma)
Wayne Roberts 0:6b3ac9c5a042 320 {
Wayne Roberts 0:6b3ac9c5a042 321 if (ma < 130)
Wayne Roberts 0:6b3ac9c5a042 322 radio.RegOcp.bits.OcpTrim = (ma - 45) / 5;
Wayne Roberts 0:6b3ac9c5a042 323 else
Wayne Roberts 0:6b3ac9c5a042 324 radio.RegOcp.bits.OcpTrim = (ma + 30) / 10;
Wayne Roberts 0:6b3ac9c5a042 325 radio.write_reg(REG_OCP, radio.RegOcp.octet);
Wayne Roberts 0:6b3ac9c5a042 326
Wayne Roberts 0:6b3ac9c5a042 327 radio.RegOcp.octet = radio.read_reg(REG_OCP);
Wayne Roberts 0:6b3ac9c5a042 328 if (radio.RegOcp.bits.OcpTrim < 16)
Wayne Roberts 0:6b3ac9c5a042 329 ma = 45 + (5 * radio.RegOcp.bits.OcpTrim);
Wayne Roberts 0:6b3ac9c5a042 330 else if (radio.RegOcp.bits.OcpTrim < 28)
Wayne Roberts 0:6b3ac9c5a042 331 ma = (10 * radio.RegOcp.bits.OcpTrim) - 30;
Wayne Roberts 0:6b3ac9c5a042 332 else
Wayne Roberts 0:6b3ac9c5a042 333 ma = 240;
Wayne Roberts 0:6b3ac9c5a042 334 //MAC_PRINTF("Ocp: %dmA\r\n", ma);
Wayne Roberts 0:6b3ac9c5a042 335 }
Wayne Roberts 0:6b3ac9c5a042 336
Wayne Roberts 0:6b3ac9c5a042 337
Wayne Roberts 0:6b3ac9c5a042 338 void Radio::PrintStatus()
Wayne Roberts 0:6b3ac9c5a042 339 {
Wayne Roberts 7:4b6f960dcca2 340 #ifdef MAC_DEBUG
Wayne Roberts 7:4b6f960dcca2 341 radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
Wayne Roberts 7:4b6f960dcca2 342 switch (radio.RegOpMode.bits.Mode) {
Wayne Roberts 7:4b6f960dcca2 343 case RF_OPMODE_SLEEP: MAC_PRINTF("SLEEP "); break;
Wayne Roberts 7:4b6f960dcca2 344 case RF_OPMODE_STANDBY: MAC_PRINTF("STBY "); break;
Wayne Roberts 7:4b6f960dcca2 345 case RF_OPMODE_SYNTHESIZER_TX: MAC_PRINTF("FSTX "); break;
Wayne Roberts 7:4b6f960dcca2 346 case RF_OPMODE_TRANSMITTER: MAC_PRINTF("TX "); break;
Wayne Roberts 7:4b6f960dcca2 347 case RF_OPMODE_SYNTHESIZER_RX: MAC_PRINTF("FSRX "); break;
Wayne Roberts 7:4b6f960dcca2 348 case RF_OPMODE_RECEIVER: MAC_PRINTF("RXC "); break;
Wayne Roberts 7:4b6f960dcca2 349 case RF_OPMODE_RECEIVER_SINGLE: MAC_PRINTF("RXS "); break;
Wayne Roberts 7:4b6f960dcca2 350 case RF_OPMODE_CAD: MAC_PRINTF("CAD "); break;
Wayne Roberts 7:4b6f960dcca2 351 }
Wayne Roberts 7:4b6f960dcca2 352
Wayne Roberts 7:4b6f960dcca2 353 MAC_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:6b3ac9c5a042 354 lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
Wayne Roberts 0:6b3ac9c5a042 355 MAC_PRINTF("irqFlags:%02x\r\n", lora.RegIrqFlags.octet);
Wayne Roberts 7:4b6f960dcca2 356 #endif /* MAC_DEBUG */
Wayne Roberts 0:6b3ac9c5a042 357 }
Wayne Roberts 0:6b3ac9c5a042 358
Wayne Roberts 0:6b3ac9c5a042 359 #ifdef DUTY_ENABLE
Wayne Roberts 0:6b3ac9c5a042 360 us_timestamp_t
Wayne Roberts 0:6b3ac9c5a042 361 Radio::TimeOnAir(RadioModems_t m, uint8_t pktLen)
Wayne Roberts 0:6b3ac9c5a042 362 {
Wayne Roberts 0:6b3ac9c5a042 363 uint32_t airTime = 0;
Wayne Roberts 0:6b3ac9c5a042 364
Wayne Roberts 0:6b3ac9c5a042 365 switch (m)
Wayne Roberts 0:6b3ac9c5a042 366 {
Wayne Roberts 0:6b3ac9c5a042 367 case MODEM_FSK:
Wayne Roberts 0:6b3ac9c5a042 368 {
Wayne Roberts 0:6b3ac9c5a042 369 /* TODO
Wayne Roberts 0:6b3ac9c5a042 370 airTime = round( ( 8 * ( SX1272.Settings.Fsk.PreambleLen +
Wayne Roberts 0:6b3ac9c5a042 371 ( ( SX1272Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) +
Wayne Roberts 0:6b3ac9c5a042 372 ( ( SX1272.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) +
Wayne Roberts 0:6b3ac9c5a042 373 ( ( ( SX1272Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) +
Wayne Roberts 0:6b3ac9c5a042 374 pktLen +
Wayne Roberts 0:6b3ac9c5a042 375 ( ( SX1272.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) /
Wayne Roberts 0:6b3ac9c5a042 376 SX1272.Settings.Fsk.Datarate ) * 1e3 );
Wayne Roberts 0:6b3ac9c5a042 377 */
Wayne Roberts 0:6b3ac9c5a042 378 }
Wayne Roberts 0:6b3ac9c5a042 379 break;
Wayne Roberts 0:6b3ac9c5a042 380 case MODEM_LORA:
Wayne Roberts 0:6b3ac9c5a042 381 {
Wayne Roberts 0:6b3ac9c5a042 382 double bw = 0.0;
Wayne Roberts 0:6b3ac9c5a042 383 uint8_t fixLen, bandwidth, LowDatarateOptimize, coderate, crcOn ;
Wayne Roberts 0:6b3ac9c5a042 384 if (radio.type == SX1276) {
Wayne Roberts 0:6b3ac9c5a042 385 coderate = lora.RegModemConfig.sx1276bits.CodingRate;
Wayne Roberts 0:6b3ac9c5a042 386 LowDatarateOptimize = lora.RegModemConfig3.sx1276bits.LowDataRateOptimize;
Wayne Roberts 0:6b3ac9c5a042 387 fixLen = lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn;
Wayne Roberts 0:6b3ac9c5a042 388 bandwidth = lora.RegModemConfig.sx1276bits.Bw - 7;
Wayne Roberts 0:6b3ac9c5a042 389 crcOn = lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn;
Wayne Roberts 0:6b3ac9c5a042 390 } else if (radio.type == SX1272) {
Wayne Roberts 0:6b3ac9c5a042 391 coderate = lora.RegModemConfig.sx1272bits.CodingRate;
Wayne Roberts 0:6b3ac9c5a042 392 LowDatarateOptimize = lora.RegModemConfig.sx1272bits.LowDataRateOptimize;
Wayne Roberts 0:6b3ac9c5a042 393 fixLen = lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn;
Wayne Roberts 0:6b3ac9c5a042 394 bandwidth = lora.RegModemConfig.sx1272bits.Bw;
Wayne Roberts 0:6b3ac9c5a042 395 crcOn = lora.RegModemConfig.sx1272bits.RxPayloadCrcOn;
Wayne Roberts 0:6b3ac9c5a042 396 } else
Wayne Roberts 0:6b3ac9c5a042 397 return 0;
Wayne Roberts 0:6b3ac9c5a042 398
Wayne Roberts 0:6b3ac9c5a042 399 switch( bandwidth )
Wayne Roberts 0:6b3ac9c5a042 400 {
Wayne Roberts 0:6b3ac9c5a042 401 case 0: // 125 kHz
Wayne Roberts 0:6b3ac9c5a042 402 bw = 125;//ms: 125e3;
Wayne Roberts 0:6b3ac9c5a042 403 break;
Wayne Roberts 0:6b3ac9c5a042 404 case 1: // 250 kHz
Wayne Roberts 0:6b3ac9c5a042 405 bw = 250;//ms:250e3;
Wayne Roberts 0:6b3ac9c5a042 406 break;
Wayne Roberts 0:6b3ac9c5a042 407 case 2: // 500 kHz
Wayne Roberts 0:6b3ac9c5a042 408 bw = 500;//ms:500e3;
Wayne Roberts 0:6b3ac9c5a042 409 break;
Wayne Roberts 0:6b3ac9c5a042 410 }
Wayne Roberts 0:6b3ac9c5a042 411
Wayne Roberts 0:6b3ac9c5a042 412 // Symbol rate : time for one symbol (secs)
Wayne Roberts 0:6b3ac9c5a042 413 double rs = bw / ( 1 << lora.RegModemConfig2.sx1276bits.SpreadingFactor );
Wayne Roberts 0:6b3ac9c5a042 414 double ts = 1 / rs;
Wayne Roberts 0:6b3ac9c5a042 415 // time of preamble
Wayne Roberts 0:6b3ac9c5a042 416 double tPreamble;
Wayne Roberts 0:6b3ac9c5a042 417 tPreamble = (lora.RegPreamble + 4.25 ) * ts;
Wayne Roberts 0:6b3ac9c5a042 418 // Symbol length of payload and time
Wayne Roberts 0:6b3ac9c5a042 419 double tmp = ceil( ( 8 * pktLen - 4 * lora.RegModemConfig2.sx1276bits.SpreadingFactor +
Wayne Roberts 0:6b3ac9c5a042 420 28 + 16 * crcOn -
Wayne Roberts 0:6b3ac9c5a042 421 ( fixLen ? 20 : 0 ) ) /
Wayne Roberts 0:6b3ac9c5a042 422 ( double )( 4 * ( lora.RegModemConfig2.sx1276bits.SpreadingFactor -
Wayne Roberts 0:6b3ac9c5a042 423 ( ( LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) *
Wayne Roberts 0:6b3ac9c5a042 424 ( coderate + 4 );
Wayne Roberts 0:6b3ac9c5a042 425 double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 );
Wayne Roberts 0:6b3ac9c5a042 426 double tPayload = nPayload * ts;
Wayne Roberts 0:6b3ac9c5a042 427 // Time on air
Wayne Roberts 0:6b3ac9c5a042 428 double tOnAir = tPreamble + tPayload;
Wayne Roberts 0:6b3ac9c5a042 429 // return ms secs
Wayne Roberts 0:6b3ac9c5a042 430 airTime = floor( tOnAir * 1e3 + 0.999 );
Wayne Roberts 0:6b3ac9c5a042 431 }
Wayne Roberts 0:6b3ac9c5a042 432 break;
Wayne Roberts 0:6b3ac9c5a042 433 }
Wayne Roberts 0:6b3ac9c5a042 434 return airTime;
Wayne Roberts 0:6b3ac9c5a042 435
Wayne Roberts 0:6b3ac9c5a042 436 }
Wayne Roberts 0:6b3ac9c5a042 437 #endif /* DUTY_ENABLE */
Wayne Roberts 0:6b3ac9c5a042 438
Wayne Roberts 4:e4bfe9183f94 439 void Radio::UserContext()
Wayne Roberts 4:e4bfe9183f94 440 {
Wayne Roberts 4:e4bfe9183f94 441 if (pinEvent.dio0) {
Wayne Roberts 4:e4bfe9183f94 442 dio0UserContext();
Wayne Roberts 4:e4bfe9183f94 443 pinEvent.dio0 = 0;
Wayne Roberts 4:e4bfe9183f94 444 }
Wayne Roberts 4:e4bfe9183f94 445
Wayne Roberts 4:e4bfe9183f94 446 if (pinEvent.dio1) {
Wayne Roberts 4:e4bfe9183f94 447 dio1UserContext();
Wayne Roberts 4:e4bfe9183f94 448 pinEvent.dio1 = 0;
Wayne Roberts 4:e4bfe9183f94 449 }
Wayne Roberts 4:e4bfe9183f94 450 }