wayne roberts / lorawan1v1

Dependencies:   sx12xx_hal

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

Committer:
Wayne Roberts
Date:
Wed May 23 10:20:07 2018 -0700
Revision:
8:5a5ea7cc946f
permit either sx127x or sx126x radio chips to be used

Who changed what in which revision?

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