wayne roberts / Mbed OS LoRaWAN_singlechannel_gateway

Dependencies:   SX127x sx12xx_hal

Committer:
dudmuck
Date:
Fri Aug 11 15:37:39 2017 -0700
Revision:
17:763412df6872
Parent:
16:67fa19bc6331
Child:
18:806cf9b7a904
print sensor payload with multiple sensor samples

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dudmuck 0:2ff18de8d48b 1 #include "lorawan.h"
dudmuck 0:2ff18de8d48b 2 #include "tim.h"
dudmuck 8:307f7faeb594 3 #include "commands.h"
dudmuck 13:fa2095be01c4 4 #define __STDC_FORMAT_MACROS
dudmuck 13:fa2095be01c4 5 #include <inttypes.h>
dudmuck 0:2ff18de8d48b 6
dudmuck 15:fea23ad8eafa 7 //#define TYPE_ABZ
dudmuck 4:7e743e402681 8 RawSerial pc(USBTX, USBRX);
dudmuck 0:2ff18de8d48b 9 Timer timer;
dudmuck 0:2ff18de8d48b 10
dudmuck 10:6783623cc886 11 //#if defined(TARGET_DISCO_L072CZ_LRWAN1)
dudmuck 10:6783623cc886 12 #if defined(TARGET_NUCLEO_L073RZ) && defined(TYPE_ABZ)
dudmuck 2:9628d5e4b1bf 13 SPI spi(PA_7, PA_6, PB_3); // mosi, miso, sclk
dudmuck 2:9628d5e4b1bf 14 // dio0, dio1, nss, spi, rst
dudmuck 2:9628d5e4b1bf 15 SX127x radio(PB_4, PB_1, PA_15, spi, PC_0); // sx1276 arduino shield
dudmuck 2:9628d5e4b1bf 16
dudmuck 2:9628d5e4b1bf 17 #define CRF1 PA_1
dudmuck 2:9628d5e4b1bf 18 #define CRF2 PC_2
dudmuck 2:9628d5e4b1bf 19 #define CRF3 PC_1
dudmuck 2:9628d5e4b1bf 20 DigitalOut Vctl1(CRF1);
dudmuck 2:9628d5e4b1bf 21 DigitalOut Vctl2(CRF2);
dudmuck 2:9628d5e4b1bf 22 DigitalOut Vctl3(CRF3);
dudmuck 2:9628d5e4b1bf 23
dudmuck 2:9628d5e4b1bf 24 void rfsw_callback()
dudmuck 2:9628d5e4b1bf 25 {
dudmuck 2:9628d5e4b1bf 26 if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER) {
dudmuck 2:9628d5e4b1bf 27 Vctl1 = 0;
dudmuck 2:9628d5e4b1bf 28 if (radio.RegPaConfig.bits.PaSelect) {
dudmuck 2:9628d5e4b1bf 29 Vctl2 = 0;
dudmuck 2:9628d5e4b1bf 30 Vctl3 = 1;
dudmuck 2:9628d5e4b1bf 31 } else {
dudmuck 2:9628d5e4b1bf 32 Vctl2 = 1;
dudmuck 2:9628d5e4b1bf 33 Vctl3 = 0;
dudmuck 2:9628d5e4b1bf 34 }
dudmuck 2:9628d5e4b1bf 35 } else {
dudmuck 2:9628d5e4b1bf 36 if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER || radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER_SINGLE)
dudmuck 2:9628d5e4b1bf 37 Vctl1 = 1;
dudmuck 2:9628d5e4b1bf 38 else
dudmuck 2:9628d5e4b1bf 39 Vctl1 = 0;
dudmuck 2:9628d5e4b1bf 40
dudmuck 2:9628d5e4b1bf 41 Vctl2 = 0;
dudmuck 2:9628d5e4b1bf 42 Vctl3 = 0;
dudmuck 2:9628d5e4b1bf 43 }
dudmuck 2:9628d5e4b1bf 44 }
dudmuck 2:9628d5e4b1bf 45 #else
dudmuck 2:9628d5e4b1bf 46 SPI spi(D11, D12, D13); // mosi, miso, sclk
dudmuck 2:9628d5e4b1bf 47 // dio0, dio1, nss, spi, rst
dudmuck 2:9628d5e4b1bf 48 SX127x radio( D2, D3, D10, spi, A0); // sx1276 arduino shield
dudmuck 2:9628d5e4b1bf 49
dudmuck 2:9628d5e4b1bf 50 DigitalInOut rfsw(A4);
dudmuck 2:9628d5e4b1bf 51
dudmuck 2:9628d5e4b1bf 52 void rfsw_callback()
dudmuck 2:9628d5e4b1bf 53 {
dudmuck 2:9628d5e4b1bf 54 if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER)
dudmuck 2:9628d5e4b1bf 55 rfsw = 1;
dudmuck 2:9628d5e4b1bf 56 else
dudmuck 2:9628d5e4b1bf 57 rfsw = 0;
dudmuck 2:9628d5e4b1bf 58 }
dudmuck 2:9628d5e4b1bf 59 #endif
dudmuck 0:2ff18de8d48b 60
dudmuck 0:2ff18de8d48b 61 char pcbuf[64];
dudmuck 0:2ff18de8d48b 62 int pcbuf_len;
dudmuck 9:a0ce66c18ec0 63 uint8_t beacon_payload[4];
dudmuck 12:9a8c13c4298b 64 uint32_t tx_ms;
dudmuck 0:2ff18de8d48b 65
dudmuck 0:2ff18de8d48b 66 unsigned int skip_beacon_cnt;
dudmuck 0:2ff18de8d48b 67
dudmuck 0:2ff18de8d48b 68 SX127x_lora lora(radio);
dudmuck 0:2ff18de8d48b 69
dudmuck 12:9a8c13c4298b 70 float starting_bg_rssi;
dudmuck 0:2ff18de8d48b 71
dudmuck 0:2ff18de8d48b 72 #define N_SAMPLES 64
dudmuck 0:2ff18de8d48b 73 void channel_scan()
dudmuck 0:2ff18de8d48b 74 {
dudmuck 0:2ff18de8d48b 75 int min_ch, ch;
dudmuck 0:2ff18de8d48b 76 uint32_t hz = LORAMAC_FIRST_CHANNEL;
dudmuck 0:2ff18de8d48b 77 int acc[LORA_MAX_NB_CHANNELS];
dudmuck 0:2ff18de8d48b 78
dudmuck 0:2ff18de8d48b 79 radio.set_opmode(RF_OPMODE_STANDBY);
dudmuck 0:2ff18de8d48b 80
dudmuck 0:2ff18de8d48b 81 for (ch = 0; ch < LORA_MAX_NB_CHANNELS; ch++) {
dudmuck 0:2ff18de8d48b 82 int i;
dudmuck 0:2ff18de8d48b 83 float MHz = (float)hz / 1e6;
dudmuck 0:2ff18de8d48b 84 radio.set_frf_MHz(MHz);
dudmuck 0:2ff18de8d48b 85 radio.set_opmode(RF_OPMODE_RECEIVER);
dudmuck 0:2ff18de8d48b 86 acc[ch] = 0;
dudmuck 0:2ff18de8d48b 87 for (i = 0; i < N_SAMPLES; i++) {
dudmuck 0:2ff18de8d48b 88 int rssi = lora.get_current_rssi();
dudmuck 0:2ff18de8d48b 89 acc[ch] += rssi;
dudmuck 0:2ff18de8d48b 90 wait(0.01);
dudmuck 0:2ff18de8d48b 91 }
dudmuck 0:2ff18de8d48b 92 radio.set_opmode(RF_OPMODE_STANDBY);
dudmuck 0:2ff18de8d48b 93 printf("ch%u: %f\r\n", ch, acc[ch] / (float)N_SAMPLES);
dudmuck 0:2ff18de8d48b 94 hz += LORAMAC_STEPWIDTH_CHANNEL;
dudmuck 0:2ff18de8d48b 95 radio.set_frf_MHz((float)hz/1e6);
dudmuck 0:2ff18de8d48b 96 }
dudmuck 0:2ff18de8d48b 97
dudmuck 0:2ff18de8d48b 98 int min = 0x7fffffff;
dudmuck 0:2ff18de8d48b 99 min_ch = 0;
dudmuck 0:2ff18de8d48b 100 for (ch = 0; ch < LORA_MAX_NB_CHANNELS; ch++) {
dudmuck 0:2ff18de8d48b 101 if (acc[ch] < min) {
dudmuck 0:2ff18de8d48b 102 min = acc[ch];
dudmuck 0:2ff18de8d48b 103 min_ch = ch;
dudmuck 0:2ff18de8d48b 104 }
dudmuck 0:2ff18de8d48b 105 }
dudmuck 0:2ff18de8d48b 106 hz = LORAMAC_FIRST_CHANNEL + (min_ch * LORAMAC_STEPWIDTH_CHANNEL);
dudmuck 0:2ff18de8d48b 107 printf("using ch%u, %luhz\r\n", min_ch, hz);
dudmuck 0:2ff18de8d48b 108 radio.set_frf_MHz((float)hz/1e6);
dudmuck 12:9a8c13c4298b 109
dudmuck 12:9a8c13c4298b 110 starting_bg_rssi = acc[min_ch] / (float)N_SAMPLES;
dudmuck 12:9a8c13c4298b 111 }
dudmuck 12:9a8c13c4298b 112
dudmuck 12:9a8c13c4298b 113 void measure_ambient()
dudmuck 12:9a8c13c4298b 114 {
dudmuck 12:9a8c13c4298b 115 int i, acc = 0;
dudmuck 12:9a8c13c4298b 116 float bg_rssi;
dudmuck 12:9a8c13c4298b 117 float diff;
dudmuck 12:9a8c13c4298b 118 static unsigned cnt = 0;
dudmuck 12:9a8c13c4298b 119
dudmuck 12:9a8c13c4298b 120 for (i = 0; i < N_SAMPLES; i++) {
dudmuck 12:9a8c13c4298b 121 int rssi = lora.get_current_rssi();
dudmuck 12:9a8c13c4298b 122 acc += rssi;
dudmuck 12:9a8c13c4298b 123 wait(0.01);
dudmuck 12:9a8c13c4298b 124 }
dudmuck 12:9a8c13c4298b 125 bg_rssi = acc / (float)N_SAMPLES;
dudmuck 12:9a8c13c4298b 126 diff = bg_rssi - starting_bg_rssi;
dudmuck 12:9a8c13c4298b 127 printf("bg_rssi:%.1fdBm vs %1.fdBm, diff:%.1f, %d\r\n", bg_rssi, starting_bg_rssi, diff, cnt);
dudmuck 12:9a8c13c4298b 128 if (diff > 10) {
dudmuck 12:9a8c13c4298b 129 if (++cnt > 3) {
dudmuck 12:9a8c13c4298b 130 /* find better channel */
dudmuck 12:9a8c13c4298b 131 channel_scan();
dudmuck 12:9a8c13c4298b 132 lora.start_rx(RF_OPMODE_RECEIVER);
dudmuck 12:9a8c13c4298b 133 cnt = 0;
dudmuck 12:9a8c13c4298b 134 }
dudmuck 12:9a8c13c4298b 135 } else
dudmuck 12:9a8c13c4298b 136 cnt = 0;
dudmuck 0:2ff18de8d48b 137 }
dudmuck 0:2ff18de8d48b 138
dudmuck 0:2ff18de8d48b 139 void init_radio()
dudmuck 0:2ff18de8d48b 140 {
dudmuck 0:2ff18de8d48b 141 radio.set_opmode(RF_OPMODE_STANDBY);
dudmuck 0:2ff18de8d48b 142
dudmuck 0:2ff18de8d48b 143 radio.RegPaConfig.bits.OutputPower = 15;
dudmuck 0:2ff18de8d48b 144 radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
dudmuck 0:2ff18de8d48b 145 lora.enable();
dudmuck 13:fa2095be01c4 146 lora.setBw_KHz(BANDWIDTH_KHZ);
dudmuck 0:2ff18de8d48b 147 lora.setSf(LoRaWan::Datarates[LORAMAC_DEFAULT_DATARATE]);
dudmuck 0:2ff18de8d48b 148 printf("using sf%u\r\n", LoRaWan::Datarates[LORAMAC_DEFAULT_DATARATE]);
dudmuck 0:2ff18de8d48b 149
dudmuck 0:2ff18de8d48b 150 channel_scan();
dudmuck 0:2ff18de8d48b 151
dudmuck 0:2ff18de8d48b 152 radio.write_reg(REG_LR_SYNC_BYTE, LORA_MAC_PUBLIC_SYNCWORD);
dudmuck 0:2ff18de8d48b 153 radio.write_reg(REG_LR_RX_MAX_PAYLOADLENGTH, 255);
dudmuck 0:2ff18de8d48b 154 }
dudmuck 0:2ff18de8d48b 155
dudmuck 0:2ff18de8d48b 156 void printLoraIrqs(bool clear)
dudmuck 0:2ff18de8d48b 157 {
dudmuck 0:2ff18de8d48b 158 printf("\r\nIrqFlags:");
dudmuck 0:2ff18de8d48b 159 if (lora.RegIrqFlags.bits.CadDetected)
dudmuck 0:2ff18de8d48b 160 printf("CadDetected ");
dudmuck 0:2ff18de8d48b 161 if (lora.RegIrqFlags.bits.FhssChangeChannel) {
dudmuck 0:2ff18de8d48b 162 printf("FhssChangeChannel:%d ", lora.RegHopChannel.bits.FhssPresentChannel);
dudmuck 0:2ff18de8d48b 163 }
dudmuck 0:2ff18de8d48b 164 if (lora.RegIrqFlags.bits.CadDone)
dudmuck 0:2ff18de8d48b 165 printf("CadDone ");
dudmuck 0:2ff18de8d48b 166 if (lora.RegIrqFlags.bits.TxDone)
dudmuck 12:9a8c13c4298b 167 printf("TxDone-dio0:%d ", radio.dio0.read());
dudmuck 0:2ff18de8d48b 168 if (lora.RegIrqFlags.bits.ValidHeader)
dudmuck 0:2ff18de8d48b 169 printf("ValidHeader ");
dudmuck 0:2ff18de8d48b 170 if (lora.RegIrqFlags.bits.PayloadCrcError)
dudmuck 0:2ff18de8d48b 171 printf("PayloadCrcError ");
dudmuck 0:2ff18de8d48b 172 if (lora.RegIrqFlags.bits.RxDone)
dudmuck 0:2ff18de8d48b 173 printf("RxDone ");
dudmuck 0:2ff18de8d48b 174 if (lora.RegIrqFlags.bits.RxTimeout)
dudmuck 0:2ff18de8d48b 175 printf("RxTimeout ");
dudmuck 0:2ff18de8d48b 176
dudmuck 0:2ff18de8d48b 177 printf("\r\n");
dudmuck 0:2ff18de8d48b 178
dudmuck 0:2ff18de8d48b 179 if (clear)
dudmuck 0:2ff18de8d48b 180 radio.write_reg(REG_LR_IRQFLAGS, lora.RegIrqFlags.octet);
dudmuck 0:2ff18de8d48b 181 }
dudmuck 0:2ff18de8d48b 182
dudmuck 0:2ff18de8d48b 183 void printOpMode()
dudmuck 0:2ff18de8d48b 184 {
dudmuck 0:2ff18de8d48b 185 radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
dudmuck 0:2ff18de8d48b 186 switch (radio.RegOpMode.bits.Mode) {
dudmuck 0:2ff18de8d48b 187 case RF_OPMODE_SLEEP: printf("sleep"); break;
dudmuck 0:2ff18de8d48b 188 case RF_OPMODE_STANDBY: printf("stby"); break;
dudmuck 0:2ff18de8d48b 189 case RF_OPMODE_SYNTHESIZER_TX: printf("fstx"); break;
dudmuck 0:2ff18de8d48b 190 case RF_OPMODE_TRANSMITTER: printf("tx"); break;
dudmuck 0:2ff18de8d48b 191 case RF_OPMODE_SYNTHESIZER_RX: printf("fsrx"); break;
dudmuck 0:2ff18de8d48b 192 case RF_OPMODE_RECEIVER: printf("rx"); break;
dudmuck 0:2ff18de8d48b 193 case 6:
dudmuck 0:2ff18de8d48b 194 if (radio.RegOpMode.bits.LongRangeMode)
dudmuck 0:2ff18de8d48b 195 printf("rxs");
dudmuck 0:2ff18de8d48b 196 else
dudmuck 0:2ff18de8d48b 197 printf("-6-");
dudmuck 0:2ff18de8d48b 198 break; // todo: different lora/fsk
dudmuck 0:2ff18de8d48b 199 case 7:
dudmuck 0:2ff18de8d48b 200 if (radio.RegOpMode.bits.LongRangeMode)
dudmuck 0:2ff18de8d48b 201 printf("cad");
dudmuck 0:2ff18de8d48b 202 else
dudmuck 0:2ff18de8d48b 203 printf("-7-");
dudmuck 0:2ff18de8d48b 204 break; // todo: different lora/fsk
dudmuck 0:2ff18de8d48b 205 }
dudmuck 0:2ff18de8d48b 206 }
dudmuck 0:2ff18de8d48b 207
dudmuck 17:763412df6872 208 //#define GPO_IDX 6
dudmuck 16:67fa19bc6331 209 void decrypted_uplink(uint32_t dev_addr, uint8_t* buf, uint8_t buflen, uint8_t port)
dudmuck 9:a0ce66c18ec0 210 {
dudmuck 9:a0ce66c18ec0 211 if (port == SENSOR_PORT) {
dudmuck 17:763412df6872 212 uint8_t i = 0;
dudmuck 17:763412df6872 213 uint16_t lum = buf[i++] << 8;
dudmuck 17:763412df6872 214 lum += buf[i++];
dudmuck 17:763412df6872 215 LoRaWan::filtered_printf(dev_addr, "SENSOR lum:%u\r\n", lum);
dudmuck 17:763412df6872 216 while (i < buflen) {
dudmuck 17:763412df6872 217 uint16_t a_a, a_b, p;
dudmuck 17:763412df6872 218 a_a = buf[i++] << 8;
dudmuck 17:763412df6872 219 a_a += buf[i++];
dudmuck 17:763412df6872 220 a_b = buf[i++] << 8;
dudmuck 17:763412df6872 221 a_b += buf[i++];
dudmuck 17:763412df6872 222 p = buf[i++];
dudmuck 17:763412df6872 223 LoRaWan::filtered_printf(dev_addr, "%x, %u, %u, %u, %u\r\n",
dudmuck 17:763412df6872 224 dev_addr,
dudmuck 17:763412df6872 225 a_a, /* analog */
dudmuck 17:763412df6872 226 a_b, /* analog */
dudmuck 17:763412df6872 227 (p & 2) >> 1, /* digital in */
dudmuck 17:763412df6872 228 p & 1 /* digital out */
dudmuck 17:763412df6872 229 );
dudmuck 17:763412df6872 230 }
dudmuck 9:a0ce66c18ec0 231 } else {
dudmuck 9:a0ce66c18ec0 232 int i;
dudmuck 16:67fa19bc6331 233 LoRaWan::filtered_printf(dev_addr, "port%u: ", port);
dudmuck 9:a0ce66c18ec0 234 for (i = 0; i < buflen; i++)
dudmuck 16:67fa19bc6331 235 LoRaWan::filtered_printf(dev_addr, "%02x ", buf[i]);
dudmuck 16:67fa19bc6331 236 LoRaWan::filtered_printf(dev_addr, "\r\n");
dudmuck 9:a0ce66c18ec0 237 }
dudmuck 9:a0ce66c18ec0 238 }
dudmuck 9:a0ce66c18ec0 239
dudmuck 0:2ff18de8d48b 240 EventQueue queue;
dudmuck 3:7c01b8978638 241
dudmuck 3:7c01b8978638 242 volatile bool get_tx_done;
dudmuck 3:7c01b8978638 243 volatile bool beacon_guard;
dudmuck 0:2ff18de8d48b 244 bool restore_tx_invert;
dudmuck 3:7c01b8978638 245 bool restore_header_mode;
dudmuck 0:2ff18de8d48b 246
dudmuck 0:2ff18de8d48b 247 void send_downlink()
dudmuck 0:2ff18de8d48b 248 {
dudmuck 12:9a8c13c4298b 249 if (!beacon_guard && LoRaWan::do_downlink) {
dudmuck 0:2ff18de8d48b 250 radio.set_opmode(RF_OPMODE_STANDBY);
dudmuck 0:2ff18de8d48b 251 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 0:2ff18de8d48b 252 lora.invert_tx(true);
dudmuck 0:2ff18de8d48b 253 restore_tx_invert = true;
dudmuck 0:2ff18de8d48b 254 lora.setRxPayloadCrcOn(false);
dudmuck 0:2ff18de8d48b 255 lora.start_tx(lora.RegPayloadLength);
dudmuck 0:2ff18de8d48b 256 LoRaWan::do_downlink = false;
dudmuck 3:7c01b8978638 257 get_tx_done = true;
dudmuck 12:9a8c13c4298b 258 tx_ms = timer.read_ms();
dudmuck 0:2ff18de8d48b 259 }
dudmuck 0:2ff18de8d48b 260 }
dudmuck 0:2ff18de8d48b 261
dudmuck 12:9a8c13c4298b 262
dudmuck 0:2ff18de8d48b 263 void
dudmuck 0:2ff18de8d48b 264 service_radio()
dudmuck 0:2ff18de8d48b 265 {
dudmuck 0:2ff18de8d48b 266 service_action_e act = lora.service();
dudmuck 0:2ff18de8d48b 267
dudmuck 0:2ff18de8d48b 268 switch (act) {
dudmuck 0:2ff18de8d48b 269 case SERVICE_ERROR:
dudmuck 0:2ff18de8d48b 270 printf("SERVICE_ERROR\r\n");
dudmuck 0:2ff18de8d48b 271 case SERVICE_TX_DONE:
dudmuck 0:2ff18de8d48b 272 case SERVICE_NONE:
dudmuck 0:2ff18de8d48b 273 break;
dudmuck 0:2ff18de8d48b 274 case SERVICE_READ_FIFO:
dudmuck 3:7c01b8978638 275 LoRaWan::rx_slot = tim_get_current_slot();
dudmuck 3:7c01b8978638 276 LoRaWan::rx_ms = timer.read_ms();
dudmuck 12:9a8c13c4298b 277 radio.set_opmode(RF_OPMODE_STANDBY);
dudmuck 12:9a8c13c4298b 278 LoRaWan::parse_receive();
dudmuck 12:9a8c13c4298b 279 if (!LoRaWan::do_downlink) {
dudmuck 12:9a8c13c4298b 280 /* if not sending downlink, start receiver now */
dudmuck 3:7c01b8978638 281 lora.start_rx(RF_OPMODE_RECEIVER);
dudmuck 0:2ff18de8d48b 282 }
dudmuck 12:9a8c13c4298b 283
dudmuck 0:2ff18de8d48b 284 break;
dudmuck 0:2ff18de8d48b 285 } // ..switch (act)
dudmuck 0:2ff18de8d48b 286 }
dudmuck 0:2ff18de8d48b 287
dudmuck 0:2ff18de8d48b 288 volatile float prev_beacon_send_at;
dudmuck 0:2ff18de8d48b 289 volatile float beacon_send_at;
dudmuck 0:2ff18de8d48b 290 volatile float beacon_loaded_at;
dudmuck 0:2ff18de8d48b 291
dudmuck 0:2ff18de8d48b 292 volatile bool beacon_loaded;
dudmuck 0:2ff18de8d48b 293 void
dudmuck 0:2ff18de8d48b 294 send_beacon()
dudmuck 0:2ff18de8d48b 295 {
dudmuck 0:2ff18de8d48b 296 prev_beacon_send_at = beacon_send_at;
dudmuck 0:2ff18de8d48b 297 beacon_send_at = timer.read();
dudmuck 0:2ff18de8d48b 298
dudmuck 0:2ff18de8d48b 299 if (!beacon_loaded)
dudmuck 0:2ff18de8d48b 300 return;
dudmuck 0:2ff18de8d48b 301
dudmuck 0:2ff18de8d48b 302 radio.set_opmode(RF_OPMODE_TRANSMITTER);
dudmuck 0:2ff18de8d48b 303 beacon_loaded = false;
dudmuck 3:7c01b8978638 304 get_tx_done = true;
dudmuck 12:9a8c13c4298b 305 tx_ms = timer.read_ms();
dudmuck 0:2ff18de8d48b 306 }
dudmuck 0:2ff18de8d48b 307
dudmuck 0:2ff18de8d48b 308 static uint16_t beacon_crc( uint8_t *buffer, uint16_t length )
dudmuck 0:2ff18de8d48b 309 {
dudmuck 0:2ff18de8d48b 310 // The CRC calculation follows CCITT
dudmuck 0:2ff18de8d48b 311 const uint16_t polynom = 0x1021;
dudmuck 0:2ff18de8d48b 312 // CRC initial value
dudmuck 0:2ff18de8d48b 313 uint16_t crc = 0x0000;
dudmuck 0:2ff18de8d48b 314
dudmuck 0:2ff18de8d48b 315 if( buffer == NULL )
dudmuck 0:2ff18de8d48b 316 {
dudmuck 0:2ff18de8d48b 317 return 0;
dudmuck 0:2ff18de8d48b 318 }
dudmuck 0:2ff18de8d48b 319
dudmuck 0:2ff18de8d48b 320 for( uint16_t i = 0; i < length; ++i )
dudmuck 0:2ff18de8d48b 321 {
dudmuck 0:2ff18de8d48b 322 crc ^= ( uint16_t ) buffer[i] << 8;
dudmuck 0:2ff18de8d48b 323 for( uint16_t j = 0; j < 8; ++j )
dudmuck 0:2ff18de8d48b 324 {
dudmuck 0:2ff18de8d48b 325 crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 );
dudmuck 0:2ff18de8d48b 326 }
dudmuck 0:2ff18de8d48b 327 }
dudmuck 0:2ff18de8d48b 328
dudmuck 0:2ff18de8d48b 329 return crc;
dudmuck 0:2ff18de8d48b 330 }
dudmuck 0:2ff18de8d48b 331
dudmuck 0:2ff18de8d48b 332 void
dudmuck 3:7c01b8978638 333 _load_beacon()
dudmuck 0:2ff18de8d48b 334 {
dudmuck 0:2ff18de8d48b 335 uint16_t crc;
dudmuck 12:9a8c13c4298b 336 radio.set_opmode(RF_OPMODE_STANDBY);
dudmuck 12:9a8c13c4298b 337 // clear any flags which might have been set during beacon_guard
dudmuck 12:9a8c13c4298b 338 radio.write_reg(REG_LR_IRQFLAGS, 0xff);
dudmuck 0:2ff18de8d48b 339 lora.RegPayloadLength = BEACON_SIZE;
dudmuck 0:2ff18de8d48b 340 radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength);
dudmuck 0:2ff18de8d48b 341 lora.setHeaderMode(true);
dudmuck 3:7c01b8978638 342 restore_header_mode = true;
dudmuck 0:2ff18de8d48b 343
dudmuck 0:2ff18de8d48b 344 if (skip_beacon_cnt > 0) {
dudmuck 1:107435401168 345 //printf("skip_beacon_cnt:%d\r\n", skip_beacon_cnt);
dudmuck 0:2ff18de8d48b 346 lora.invert_tx(true);
dudmuck 0:2ff18de8d48b 347 restore_tx_invert = true;
dudmuck 0:2ff18de8d48b 348 skip_beacon_cnt--;
dudmuck 0:2ff18de8d48b 349 }
dudmuck 0:2ff18de8d48b 350
dudmuck 9:a0ce66c18ec0 351 radio.tx_buf[0] = beacon_payload[0];
dudmuck 9:a0ce66c18ec0 352 radio.tx_buf[1] = beacon_payload[1];
dudmuck 9:a0ce66c18ec0 353 radio.tx_buf[2] = beacon_payload[2];
dudmuck 9:a0ce66c18ec0 354 radio.tx_buf[3] = beacon_payload[3];
dudmuck 9:a0ce66c18ec0 355 beacon_payload[0] = CMD_NONE;
dudmuck 9:a0ce66c18ec0 356
dudmuck 0:2ff18de8d48b 357 crc = beacon_crc(radio.tx_buf, 4);
dudmuck 0:2ff18de8d48b 358 radio.tx_buf[4] = crc & 0xff;
dudmuck 0:2ff18de8d48b 359 radio.tx_buf[5] = crc >> 8;
dudmuck 0:2ff18de8d48b 360
dudmuck 0:2ff18de8d48b 361 // DIO0 to TxDone
dudmuck 3:7c01b8978638 362 radio.RegDioMapping1.bits.Dio0Mapping = 1;
dudmuck 3:7c01b8978638 363 radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
dudmuck 0:2ff18de8d48b 364
dudmuck 0:2ff18de8d48b 365 // set FifoPtrAddr to FifoTxPtrBase
dudmuck 0:2ff18de8d48b 366 radio.write_reg(REG_LR_FIFOADDRPTR, radio.read_reg(REG_LR_FIFOTXBASEADDR));
dudmuck 0:2ff18de8d48b 367
dudmuck 0:2ff18de8d48b 368 // write PayloadLength bytes to fifo
dudmuck 0:2ff18de8d48b 369 lora.write_fifo(lora.RegPayloadLength);
dudmuck 0:2ff18de8d48b 370
dudmuck 0:2ff18de8d48b 371 // prepare for tx to occur in send_beacon()
dudmuck 0:2ff18de8d48b 372 radio.set_opmode(RF_OPMODE_SYNTHESIZER_TX);
dudmuck 0:2ff18de8d48b 373 beacon_loaded = true;
dudmuck 0:2ff18de8d48b 374
dudmuck 0:2ff18de8d48b 375 beacon_loaded_at = timer.read();
dudmuck 0:2ff18de8d48b 376 }
dudmuck 0:2ff18de8d48b 377
dudmuck 3:7c01b8978638 378 void load_beacon()
dudmuck 3:7c01b8978638 379 {
dudmuck 3:7c01b8978638 380 beacon_guard = true;
dudmuck 12:9a8c13c4298b 381 queue.call_in(200, _load_beacon);
dudmuck 3:7c01b8978638 382 }
dudmuck 3:7c01b8978638 383
dudmuck 0:2ff18de8d48b 384 void get_time_till_beacon()
dudmuck 0:2ff18de8d48b 385 {
dudmuck 0:2ff18de8d48b 386 uint16_t slots = tim_get_current_slot();
dudmuck 0:2ff18de8d48b 387 printf("slots:%u\r\n", slots);
dudmuck 0:2ff18de8d48b 388 }
dudmuck 0:2ff18de8d48b 389
dudmuck 4:7e743e402681 390 void rx_isr()
dudmuck 0:2ff18de8d48b 391 {
dudmuck 0:2ff18de8d48b 392 static uint8_t pcbuf_idx = 0;
dudmuck 0:2ff18de8d48b 393 static uint8_t prev_len = 0;;
dudmuck 0:2ff18de8d48b 394 char c = pc.getc();
dudmuck 0:2ff18de8d48b 395
dudmuck 0:2ff18de8d48b 396 if (c == 8) {
dudmuck 0:2ff18de8d48b 397 if (pcbuf_idx > 0) {
dudmuck 0:2ff18de8d48b 398 pc.putc(8);
dudmuck 0:2ff18de8d48b 399 pc.putc(' ');
dudmuck 0:2ff18de8d48b 400 pc.putc(8);
dudmuck 0:2ff18de8d48b 401 pcbuf_idx--;
dudmuck 0:2ff18de8d48b 402 }
dudmuck 0:2ff18de8d48b 403 } else if (c == 3) { // ctrl-C
dudmuck 0:2ff18de8d48b 404 pcbuf_len = -1;
dudmuck 0:2ff18de8d48b 405 } else if (c == '\r') {
dudmuck 0:2ff18de8d48b 406 if (pcbuf_idx == 0) {
dudmuck 0:2ff18de8d48b 407 pcbuf_len = prev_len;
dudmuck 0:2ff18de8d48b 408 } else {
dudmuck 0:2ff18de8d48b 409 pcbuf[pcbuf_idx] = 0; // null terminate
dudmuck 0:2ff18de8d48b 410 prev_len = pcbuf_idx;
dudmuck 0:2ff18de8d48b 411 pcbuf_idx = 0;
dudmuck 0:2ff18de8d48b 412 pcbuf_len = prev_len;
dudmuck 0:2ff18de8d48b 413 }
dudmuck 0:2ff18de8d48b 414 } else if (pcbuf_idx < sizeof(pcbuf)) {
dudmuck 0:2ff18de8d48b 415 pcbuf[pcbuf_idx++] = c;
dudmuck 0:2ff18de8d48b 416 pc.putc(c);
dudmuck 0:2ff18de8d48b 417 }
dudmuck 0:2ff18de8d48b 418 }
dudmuck 0:2ff18de8d48b 419
dudmuck 0:2ff18de8d48b 420 void cmd_skip_beacon(uint8_t idx)
dudmuck 0:2ff18de8d48b 421 {
dudmuck 0:2ff18de8d48b 422 if (pcbuf[idx] >= '0' && pcbuf[idx] <= '9') {
dudmuck 0:2ff18de8d48b 423 sscanf(pcbuf+idx, "%u", &skip_beacon_cnt);
dudmuck 0:2ff18de8d48b 424 }
dudmuck 0:2ff18de8d48b 425 printf("skip_beacon_cnt:%u\r\n", skip_beacon_cnt);
dudmuck 0:2ff18de8d48b 426 }
dudmuck 0:2ff18de8d48b 427
dudmuck 0:2ff18de8d48b 428 void cmd_list_motes(uint8_t idx)
dudmuck 0:2ff18de8d48b 429 {
dudmuck 0:2ff18de8d48b 430 int i;
dudmuck 0:2ff18de8d48b 431 for (i = 0; i < N_MOTES; i++) {
dudmuck 0:2ff18de8d48b 432 if (motes[i].dev_addr != DEVADDR_NONE) {
dudmuck 13:fa2095be01c4 433 LoRaWan::print_octets_rev("", motes[i].dev_eui, LORA_EUI_LENGTH);
dudmuck 13:fa2095be01c4 434 printf(" %" PRIx32 "\r\n", motes[i].dev_addr);
dudmuck 0:2ff18de8d48b 435 }
dudmuck 0:2ff18de8d48b 436 }
dudmuck 0:2ff18de8d48b 437 }
dudmuck 0:2ff18de8d48b 438
dudmuck 0:2ff18de8d48b 439 void
dudmuck 0:2ff18de8d48b 440 cmd_beacon_payload(uint8_t idx)
dudmuck 0:2ff18de8d48b 441 {
dudmuck 9:a0ce66c18ec0 442 uint32_t i;
dudmuck 9:a0ce66c18ec0 443 uint32_t* ptr;
dudmuck 13:fa2095be01c4 444 sscanf(pcbuf+idx, "%" PRIx32, &i);
dudmuck 13:fa2095be01c4 445 printf("beacon_payload:%08" PRIx32 "\r\n", i);
dudmuck 9:a0ce66c18ec0 446 ptr = (uint32_t*)beacon_payload;
dudmuck 9:a0ce66c18ec0 447 *ptr = i;
dudmuck 8:307f7faeb594 448 }
dudmuck 8:307f7faeb594 449
dudmuck 0:2ff18de8d48b 450 void
dudmuck 0:2ff18de8d48b 451 cmd_send_downlink(uint8_t idx)
dudmuck 0:2ff18de8d48b 452 {
dudmuck 0:2ff18de8d48b 453 ota_mote_t* mote = NULL;
dudmuck 0:2ff18de8d48b 454 int i;
dudmuck 0:2ff18de8d48b 455 unsigned int dev_addr;
dudmuck 0:2ff18de8d48b 456 sscanf(pcbuf+idx, "%x", &dev_addr);
dudmuck 0:2ff18de8d48b 457 for (i = 0; i < N_MOTES; i++) {
dudmuck 0:2ff18de8d48b 458 if (motes[i].dev_addr == dev_addr) {
dudmuck 0:2ff18de8d48b 459 break;
dudmuck 0:2ff18de8d48b 460 }
dudmuck 0:2ff18de8d48b 461 }
dudmuck 0:2ff18de8d48b 462 if (i == N_MOTES) {
dudmuck 0:2ff18de8d48b 463 printf("mote %x not found\r\n", dev_addr);
dudmuck 0:2ff18de8d48b 464 return;
dudmuck 0:2ff18de8d48b 465 }
dudmuck 0:2ff18de8d48b 466 mote = &motes[i];
dudmuck 0:2ff18de8d48b 467
dudmuck 0:2ff18de8d48b 468 while (pcbuf[idx] != ' ') {
dudmuck 0:2ff18de8d48b 469 if (pcbuf[++idx] == 0) {
dudmuck 0:2ff18de8d48b 470 printf("hit end\r\n");
dudmuck 0:2ff18de8d48b 471 return;
dudmuck 0:2ff18de8d48b 472 }
dudmuck 0:2ff18de8d48b 473 }
dudmuck 0:2ff18de8d48b 474 idx++; // step past space
dudmuck 0:2ff18de8d48b 475
dudmuck 0:2ff18de8d48b 476 mote->user_downlink_length = 0;
dudmuck 0:2ff18de8d48b 477 while (pcbuf[idx] > ' ') {
dudmuck 0:2ff18de8d48b 478 int o;
dudmuck 0:2ff18de8d48b 479 sscanf(pcbuf+idx, "%02x", &o);
dudmuck 0:2ff18de8d48b 480 LoRaWan::user_downlink[mote->user_downlink_length++] = o;
dudmuck 0:2ff18de8d48b 481 idx += 2;
dudmuck 0:2ff18de8d48b 482 }
dudmuck 0:2ff18de8d48b 483
dudmuck 13:fa2095be01c4 484 printf("%u bytes scheduled for %" PRIx32 "\r\n", mote->user_downlink_length, mote->dev_addr);
dudmuck 0:2ff18de8d48b 485 }
dudmuck 0:2ff18de8d48b 486
dudmuck 9:a0ce66c18ec0 487 void cmd_rx_restart(uint8_t idx)
dudmuck 9:a0ce66c18ec0 488 {
dudmuck 9:a0ce66c18ec0 489 /*radio.set_opmode(RF_OPMODE_STANDBY);
dudmuck 9:a0ce66c18ec0 490 printf("standby\r\n");*/
dudmuck 9:a0ce66c18ec0 491 radio.set_opmode(RF_OPMODE_SLEEP);
dudmuck 9:a0ce66c18ec0 492 printf("sleep\r\n");
dudmuck 9:a0ce66c18ec0 493 wait(0.05);
dudmuck 9:a0ce66c18ec0 494 radio.set_opmode(RF_OPMODE_RECEIVER);
dudmuck 9:a0ce66c18ec0 495 printf("receive\r\n");
dudmuck 9:a0ce66c18ec0 496 }
dudmuck 9:a0ce66c18ec0 497
dudmuck 9:a0ce66c18ec0 498 void cmd_beacon_gpo(uint8_t idx)
dudmuck 9:a0ce66c18ec0 499 {
dudmuck 9:a0ce66c18ec0 500 int gpo;
dudmuck 9:a0ce66c18ec0 501 sscanf(pcbuf+idx, "%d", &gpo);
dudmuck 9:a0ce66c18ec0 502 beacon_payload[0] = CMD_GPIO_OUT;
dudmuck 9:a0ce66c18ec0 503 beacon_payload[1] = gpo;
dudmuck 9:a0ce66c18ec0 504 printf("beacon gpo: %d\r\n", gpo);
dudmuck 9:a0ce66c18ec0 505 }
dudmuck 9:a0ce66c18ec0 506
dudmuck 9:a0ce66c18ec0 507 void cmd_beacon_rgb(uint8_t idx)
dudmuck 9:a0ce66c18ec0 508 {
dudmuck 9:a0ce66c18ec0 509 int r, g ,b;
dudmuck 9:a0ce66c18ec0 510 sscanf(pcbuf+idx, "%d %d %d", &r, &g, &b);
dudmuck 9:a0ce66c18ec0 511 beacon_payload[0] = CMD_LED_RGB;
dudmuck 9:a0ce66c18ec0 512 beacon_payload[1] = r;
dudmuck 9:a0ce66c18ec0 513 beacon_payload[2] = g;
dudmuck 9:a0ce66c18ec0 514 beacon_payload[3] = b;
dudmuck 9:a0ce66c18ec0 515 printf("beacon rgb: %d %d %d\r\n", r, g, b);
dudmuck 9:a0ce66c18ec0 516 }
dudmuck 9:a0ce66c18ec0 517
dudmuck 9:a0ce66c18ec0 518 void cmd_downlink_rgb(uint8_t idx)
dudmuck 9:a0ce66c18ec0 519 {
dudmuck 9:a0ce66c18ec0 520 ota_mote_t* mote = NULL;
dudmuck 9:a0ce66c18ec0 521 int i, r, g ,b;
dudmuck 9:a0ce66c18ec0 522 unsigned int dev_addr;
dudmuck 9:a0ce66c18ec0 523 sscanf(pcbuf+idx, "%x %d %d %d", &dev_addr, &r, &g, &b);
dudmuck 9:a0ce66c18ec0 524 for (i = 0; i < N_MOTES; i++) {
dudmuck 9:a0ce66c18ec0 525 if (motes[i].dev_addr == dev_addr) {
dudmuck 9:a0ce66c18ec0 526 break;
dudmuck 9:a0ce66c18ec0 527 }
dudmuck 9:a0ce66c18ec0 528 }
dudmuck 9:a0ce66c18ec0 529 if (i == N_MOTES) {
dudmuck 9:a0ce66c18ec0 530 printf("mote %x not found\r\n", dev_addr);
dudmuck 9:a0ce66c18ec0 531 return;
dudmuck 9:a0ce66c18ec0 532 }
dudmuck 9:a0ce66c18ec0 533 mote = &motes[i];
dudmuck 9:a0ce66c18ec0 534
dudmuck 9:a0ce66c18ec0 535 mote->user_downlink_length = 0;
dudmuck 9:a0ce66c18ec0 536 LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_LED_RGB;
dudmuck 9:a0ce66c18ec0 537 LoRaWan::user_downlink[mote->user_downlink_length++] = r;
dudmuck 9:a0ce66c18ec0 538 LoRaWan::user_downlink[mote->user_downlink_length++] = g;
dudmuck 9:a0ce66c18ec0 539 LoRaWan::user_downlink[mote->user_downlink_length++] = b;
dudmuck 9:a0ce66c18ec0 540
dudmuck 13:fa2095be01c4 541 printf("rgb %d %d %d to mote %" PRIx32 "\r\n", r, g, b, mote->dev_addr);
dudmuck 9:a0ce66c18ec0 542 }
dudmuck 9:a0ce66c18ec0 543
dudmuck 9:a0ce66c18ec0 544 void cmd_downlink_gpo(uint8_t idx)
dudmuck 9:a0ce66c18ec0 545 {
dudmuck 9:a0ce66c18ec0 546 ota_mote_t* mote = NULL;
dudmuck 9:a0ce66c18ec0 547 int i, gpo;
dudmuck 9:a0ce66c18ec0 548 unsigned int dev_addr;
dudmuck 9:a0ce66c18ec0 549 sscanf(pcbuf+idx, "%x %d", &dev_addr, &gpo);
dudmuck 9:a0ce66c18ec0 550 for (i = 0; i < N_MOTES; i++) {
dudmuck 9:a0ce66c18ec0 551 if (motes[i].dev_addr == dev_addr) {
dudmuck 9:a0ce66c18ec0 552 break;
dudmuck 9:a0ce66c18ec0 553 }
dudmuck 9:a0ce66c18ec0 554 }
dudmuck 9:a0ce66c18ec0 555 if (i == N_MOTES) {
dudmuck 9:a0ce66c18ec0 556 printf("mote %x not found\r\n", dev_addr);
dudmuck 9:a0ce66c18ec0 557 return;
dudmuck 9:a0ce66c18ec0 558 }
dudmuck 9:a0ce66c18ec0 559 mote = &motes[i];
dudmuck 9:a0ce66c18ec0 560
dudmuck 9:a0ce66c18ec0 561 mote->user_downlink_length = 0;
dudmuck 9:a0ce66c18ec0 562 LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_GPIO_OUT;
dudmuck 9:a0ce66c18ec0 563 LoRaWan::user_downlink[mote->user_downlink_length++] = gpo;
dudmuck 9:a0ce66c18ec0 564
dudmuck 13:fa2095be01c4 565 printf("gpo %d to mote %" PRIx32 "\r\n", gpo, mote->dev_addr);
dudmuck 9:a0ce66c18ec0 566 }
dudmuck 9:a0ce66c18ec0 567
dudmuck 0:2ff18de8d48b 568 void cmd_status(uint8_t idx)
dudmuck 0:2ff18de8d48b 569 {
dudmuck 14:c6284654d1b0 570 radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
dudmuck 14:c6284654d1b0 571 if (radio.RegPaConfig.bits.PaSelect)
dudmuck 14:c6284654d1b0 572 printf("PA_BOOST ");
dudmuck 14:c6284654d1b0 573 else
dudmuck 14:c6284654d1b0 574 printf("RFO ");
dudmuck 14:c6284654d1b0 575
dudmuck 0:2ff18de8d48b 576 radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
dudmuck 2:9628d5e4b1bf 577 printf("%.3fMHz sf%ubw%u ", radio.get_frf_MHz(), lora.getSf(), lora.getBw());
dudmuck 0:2ff18de8d48b 578 printOpMode();
dudmuck 0:2ff18de8d48b 579 if (!radio.RegOpMode.bits.LongRangeMode) {
dudmuck 0:2ff18de8d48b 580 printf("FSK\r\n");
dudmuck 0:2ff18de8d48b 581 return;
dudmuck 0:2ff18de8d48b 582 }
dudmuck 0:2ff18de8d48b 583
dudmuck 0:2ff18de8d48b 584 lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS);
dudmuck 0:2ff18de8d48b 585 printLoraIrqs(false);
dudmuck 0:2ff18de8d48b 586
dudmuck 12:9a8c13c4298b 587 printf(" do_downlink:%u get_tx_done:%u, ", LoRaWan::do_downlink, get_tx_done);
dudmuck 9:a0ce66c18ec0 588 lora.RegTest33.octet = radio.read_reg(REG_LR_TEST33); // invert_i_q
dudmuck 9:a0ce66c18ec0 589 lora.RegDriftInvert.octet = radio.read_reg(REG_LR_DRIFT_INVERT);
dudmuck 9:a0ce66c18ec0 590 printf("modemstat:%02x, rxinv:%x,%x\r\n", radio.read_reg(REG_LR_MODEMSTAT), lora.RegTest33.octet, lora.RegDriftInvert.octet);
dudmuck 2:9628d5e4b1bf 591 radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1);
dudmuck 2:9628d5e4b1bf 592 printf("\r\nskip_beacon_cnt:%u, currently:%u dio0map:%u\r\n", skip_beacon_cnt, tim_get_current_slot(), radio.RegDioMapping1.bits.Dio0Mapping);
dudmuck 12:9a8c13c4298b 593 printf("FIfoAddrPtr:%02x RxBase:%02x\r\n", radio.read_reg(REG_LR_FIFOADDRPTR), radio.read_reg(REG_LR_FIFORXBASEADDR));
dudmuck 0:2ff18de8d48b 594 }
dudmuck 0:2ff18de8d48b 595
dudmuck 16:67fa19bc6331 596 void cmd_filter(uint8_t idx)
dudmuck 16:67fa19bc6331 597 {
dudmuck 16:67fa19bc6331 598 if (sscanf(pcbuf+idx, "%lx", &LoRaWan::dev_addr_filter) != 1) {
dudmuck 16:67fa19bc6331 599 LoRaWan::dev_addr_filter = 0;
dudmuck 16:67fa19bc6331 600 printf("filter off\r\n");
dudmuck 16:67fa19bc6331 601 } else
dudmuck 16:67fa19bc6331 602 printf("filtering %lx\r\n", LoRaWan::dev_addr_filter);
dudmuck 16:67fa19bc6331 603 }
dudmuck 16:67fa19bc6331 604
dudmuck 11:50d0558a4e37 605 void cmd_op(uint8_t idx)
dudmuck 11:50d0558a4e37 606 {
dudmuck 11:50d0558a4e37 607 int i, dbm;
dudmuck 11:50d0558a4e37 608 RegPdsTrim1_t pds_trim;
dudmuck 11:50d0558a4e37 609 uint8_t adr;
dudmuck 11:50d0558a4e37 610 if (radio.type == SX1276)
dudmuck 11:50d0558a4e37 611 adr = REG_PDSTRIM1_SX1276;
dudmuck 11:50d0558a4e37 612 else
dudmuck 11:50d0558a4e37 613 adr = REG_PDSTRIM1_SX1272;
dudmuck 11:50d0558a4e37 614
dudmuck 11:50d0558a4e37 615 pds_trim.octet = radio.read_reg(adr);
dudmuck 11:50d0558a4e37 616
dudmuck 11:50d0558a4e37 617 if (pcbuf[idx] >= '0' && (pcbuf[idx] <= '9' || pcbuf[idx] == '-')) {
dudmuck 11:50d0558a4e37 618 sscanf(pcbuf+idx, "%d", &i);
dudmuck 11:50d0558a4e37 619 if (radio.RegPaConfig.bits.PaSelect) {
dudmuck 11:50d0558a4e37 620 /* PABOOST used: +2dbm to +17, or +20 */
dudmuck 11:50d0558a4e37 621 if (i == 20) {
dudmuck 11:50d0558a4e37 622 printf("+20dBm PADAC bias\r\n");
dudmuck 11:50d0558a4e37 623 i -= 3;
dudmuck 11:50d0558a4e37 624 pds_trim.bits.prog_txdac = 7;
dudmuck 11:50d0558a4e37 625 radio.write_reg(adr, pds_trim.octet);
dudmuck 11:50d0558a4e37 626 }
dudmuck 11:50d0558a4e37 627 if (i > 1)
dudmuck 11:50d0558a4e37 628 radio.RegPaConfig.bits.OutputPower = i - 2;
dudmuck 11:50d0558a4e37 629 } else {
dudmuck 11:50d0558a4e37 630 /* RFO used: -1 to +14dbm */
dudmuck 11:50d0558a4e37 631 if (i < 15)
dudmuck 11:50d0558a4e37 632 radio.RegPaConfig.bits.OutputPower = i + 1;
dudmuck 11:50d0558a4e37 633 }
dudmuck 11:50d0558a4e37 634 radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
dudmuck 11:50d0558a4e37 635 }
dudmuck 11:50d0558a4e37 636 radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG);
dudmuck 11:50d0558a4e37 637 if (radio.RegPaConfig.bits.PaSelect) {
dudmuck 11:50d0558a4e37 638 printf("PA_BOOST ");
dudmuck 11:50d0558a4e37 639 dbm = radio.RegPaConfig.bits.OutputPower + pds_trim.bits.prog_txdac - 2;
dudmuck 11:50d0558a4e37 640 } else {
dudmuck 11:50d0558a4e37 641 printf("RFO ");
dudmuck 11:50d0558a4e37 642 dbm = radio.RegPaConfig.bits.OutputPower - 1;
dudmuck 11:50d0558a4e37 643 }
dudmuck 11:50d0558a4e37 644 printf("OutputPower:%ddBm\r\n", dbm);
dudmuck 11:50d0558a4e37 645 }
dudmuck 11:50d0558a4e37 646
dudmuck 14:c6284654d1b0 647 #ifdef TYPE_ABZ
dudmuck 14:c6284654d1b0 648 void cmd_pa_select(uint8_t idx)
dudmuck 14:c6284654d1b0 649 {
dudmuck 14:c6284654d1b0 650 radio.RegPaConfig.bits.PaSelect ^= 1;
dudmuck 14:c6284654d1b0 651 radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet);
dudmuck 14:c6284654d1b0 652 if (radio.RegPaConfig.bits.PaSelect)
dudmuck 14:c6284654d1b0 653 printf("PA_BOOST\r\n");
dudmuck 14:c6284654d1b0 654 else
dudmuck 14:c6284654d1b0 655 printf("RFO\r\n");
dudmuck 14:c6284654d1b0 656 }
dudmuck 14:c6284654d1b0 657 #endif /* TYPE_ABZ */
dudmuck 14:c6284654d1b0 658
dudmuck 12:9a8c13c4298b 659 void cmd_set_time(uint8_t idx)
dudmuck 12:9a8c13c4298b 660 {
dudmuck 12:9a8c13c4298b 661 set_time(0);
dudmuck 13:fa2095be01c4 662 printf("time:%" PRIu32 "\r\n", time(NULL));
dudmuck 12:9a8c13c4298b 663 }
dudmuck 12:9a8c13c4298b 664
dudmuck 13:fa2095be01c4 665
dudmuck 13:fa2095be01c4 666 void cmd_pwm(uint8_t idx)
dudmuck 12:9a8c13c4298b 667 {
dudmuck 13:fa2095be01c4 668 ota_mote_t* mote;
dudmuck 12:9a8c13c4298b 669 int i;
dudmuck 13:fa2095be01c4 670 unsigned dev_addr, p, d;
dudmuck 13:fa2095be01c4 671
dudmuck 13:fa2095be01c4 672 if (sscanf(pcbuf+idx, "%x %u %u", &dev_addr, &p, &d) != 3) {
dudmuck 13:fa2095be01c4 673 printf("parse fail\r\n");
dudmuck 13:fa2095be01c4 674 return;
dudmuck 13:fa2095be01c4 675 }
dudmuck 12:9a8c13c4298b 676 for (i = 0; i < N_MOTES; i++) {
dudmuck 12:9a8c13c4298b 677 if (motes[i].dev_addr == dev_addr) {
dudmuck 12:9a8c13c4298b 678 break;
dudmuck 12:9a8c13c4298b 679 }
dudmuck 12:9a8c13c4298b 680 }
dudmuck 12:9a8c13c4298b 681 if (i == N_MOTES) {
dudmuck 12:9a8c13c4298b 682 printf("mote %x not found\r\n", dev_addr);
dudmuck 12:9a8c13c4298b 683 return;
dudmuck 12:9a8c13c4298b 684 }
dudmuck 12:9a8c13c4298b 685
dudmuck 12:9a8c13c4298b 686 mote = &motes[i];
dudmuck 12:9a8c13c4298b 687
dudmuck 12:9a8c13c4298b 688 mote->user_downlink_length = 0;
dudmuck 13:fa2095be01c4 689 LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_PWM;
dudmuck 13:fa2095be01c4 690 LoRaWan::user_downlink[mote->user_downlink_length++] = p;
dudmuck 13:fa2095be01c4 691 LoRaWan::user_downlink[mote->user_downlink_length++] = d;
dudmuck 12:9a8c13c4298b 692
dudmuck 13:fa2095be01c4 693 printf("period:%u duty:%u to mote %" PRIx32 "\r\n", p, d, mote->dev_addr);
dudmuck 13:fa2095be01c4 694 }
dudmuck 13:fa2095be01c4 695
dudmuck 13:fa2095be01c4 696 void cmd_beacon_pwm(uint8_t idx)
dudmuck 13:fa2095be01c4 697 {
dudmuck 13:fa2095be01c4 698 unsigned p, d;
dudmuck 13:fa2095be01c4 699 if (sscanf(pcbuf+idx, "%u %u", &p, &d) != 2) {
dudmuck 13:fa2095be01c4 700 printf("parse fail\r\n");
dudmuck 13:fa2095be01c4 701 return;
dudmuck 13:fa2095be01c4 702 }
dudmuck 13:fa2095be01c4 703
dudmuck 13:fa2095be01c4 704 beacon_payload[0] = CMD_PWM;
dudmuck 13:fa2095be01c4 705 beacon_payload[1] = p;
dudmuck 13:fa2095be01c4 706 beacon_payload[2] = d;
dudmuck 13:fa2095be01c4 707
dudmuck 13:fa2095be01c4 708 printf("period:%u duty:%u\r\n", p, d);
dudmuck 12:9a8c13c4298b 709 }
dudmuck 12:9a8c13c4298b 710
dudmuck 14:c6284654d1b0 711 void cmd_endnode_txp(uint8_t idx)
dudmuck 14:c6284654d1b0 712 {
dudmuck 14:c6284654d1b0 713 ota_mote_t* mote;
dudmuck 14:c6284654d1b0 714 int i;
dudmuck 14:c6284654d1b0 715 unsigned dev_addr, txi;
dudmuck 14:c6284654d1b0 716
dudmuck 14:c6284654d1b0 717 if (sscanf(pcbuf+idx, "%x %u", &dev_addr, &txi) != 2) {
dudmuck 14:c6284654d1b0 718 printf("parse fail\r\n");
dudmuck 14:c6284654d1b0 719 return;
dudmuck 14:c6284654d1b0 720 }
dudmuck 14:c6284654d1b0 721 for (i = 0; i < N_MOTES; i++) {
dudmuck 14:c6284654d1b0 722 if (motes[i].dev_addr == dev_addr) {
dudmuck 14:c6284654d1b0 723 break;
dudmuck 14:c6284654d1b0 724 }
dudmuck 14:c6284654d1b0 725 }
dudmuck 14:c6284654d1b0 726 if (i == N_MOTES) {
dudmuck 14:c6284654d1b0 727 printf("mote %x not found\r\n", dev_addr);
dudmuck 14:c6284654d1b0 728 return;
dudmuck 14:c6284654d1b0 729 }
dudmuck 14:c6284654d1b0 730
dudmuck 14:c6284654d1b0 731 mote = &motes[i];
dudmuck 14:c6284654d1b0 732
dudmuck 14:c6284654d1b0 733 mote->user_downlink_length = 0;
dudmuck 14:c6284654d1b0 734 LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_TX_POWER;
dudmuck 14:c6284654d1b0 735 LoRaWan::user_downlink[mote->user_downlink_length++] = txi;
dudmuck 14:c6284654d1b0 736
dudmuck 14:c6284654d1b0 737 printf("txp index %u to mote %" PRIx32 "\r\n", txi, mote->dev_addr);
dudmuck 14:c6284654d1b0 738 }
dudmuck 14:c6284654d1b0 739
dudmuck 14:c6284654d1b0 740 void cmd_beacon_endnode_txp(uint8_t idx)
dudmuck 14:c6284654d1b0 741 {
dudmuck 14:c6284654d1b0 742 unsigned txi;
dudmuck 14:c6284654d1b0 743 if (sscanf(pcbuf+idx, "%u", &txi) != 1) {
dudmuck 14:c6284654d1b0 744 printf("parse fail\r\n");
dudmuck 14:c6284654d1b0 745 return;
dudmuck 14:c6284654d1b0 746 }
dudmuck 14:c6284654d1b0 747
dudmuck 14:c6284654d1b0 748 beacon_payload[0] = CMD_TX_POWER;
dudmuck 14:c6284654d1b0 749 beacon_payload[1] = txi;
dudmuck 14:c6284654d1b0 750
dudmuck 14:c6284654d1b0 751 printf("txp index:%u\r\n", txi);
dudmuck 14:c6284654d1b0 752 }
dudmuck 14:c6284654d1b0 753
dudmuck 0:2ff18de8d48b 754 void cmd_help(uint8_t);
dudmuck 0:2ff18de8d48b 755
dudmuck 0:2ff18de8d48b 756 typedef struct {
dudmuck 0:2ff18de8d48b 757 const char* const cmd;
dudmuck 0:2ff18de8d48b 758 void (*handler)(uint8_t args_at);
dudmuck 0:2ff18de8d48b 759 const char* const arg_descr;
dudmuck 0:2ff18de8d48b 760 const char* const description;
dudmuck 0:2ff18de8d48b 761 } menu_item_t;
dudmuck 0:2ff18de8d48b 762
dudmuck 0:2ff18de8d48b 763 const menu_item_t menu_items[] =
dudmuck 0:2ff18de8d48b 764 { /* after first character, command names must be [A-Za-z] */
dudmuck 0:2ff18de8d48b 765 { "?", cmd_help, "","show available commands"},
dudmuck 0:2ff18de8d48b 766 { ".", cmd_status, "","read status"},
dudmuck 16:67fa19bc6331 767 { "f", cmd_filter, "%x","set dev_addr print filter"},
dudmuck 0:2ff18de8d48b 768 { "b", cmd_beacon_payload, "<%x>","set beacon payload"},
dudmuck 0:2ff18de8d48b 769 { "sb", cmd_skip_beacon, "<%d>","skip beacons"},
dudmuck 0:2ff18de8d48b 770 { "list", cmd_list_motes, "","list active motes"},
dudmuck 0:2ff18de8d48b 771 { "dl", cmd_send_downlink, "[%x %s]","send downlink <mote-hex-dev-addr> <hex-payload>"},
dudmuck 9:a0ce66c18ec0 772 { "rxr", cmd_rx_restart, "", "restart RX"},
dudmuck 9:a0ce66c18ec0 773 { "brgb", cmd_beacon_rgb, "%u %u %u", "load RGB command into next beacon" },
dudmuck 9:a0ce66c18ec0 774 { "rgb", cmd_downlink_rgb, "%x %u %u %u", "load RGB command to mote"},
dudmuck 9:a0ce66c18ec0 775 { "bgpo", cmd_beacon_gpo, "%d", "load output pin command into next beacon"},
dudmuck 9:a0ce66c18ec0 776 { "gpo", cmd_downlink_gpo, "%x %d", "load output pin command to mote"},
dudmuck 12:9a8c13c4298b 777 { "op", cmd_op, "<dBm>","(TX) get/set TX power"},
dudmuck 14:c6284654d1b0 778 #ifdef TYPE_ABZ
dudmuck 14:c6284654d1b0 779 { "pas", cmd_pa_select, "","(TX) toggle PaSelect"},
dudmuck 14:c6284654d1b0 780 #endif
dudmuck 13:fa2095be01c4 781 { "tz", cmd_set_time, "", "set seconds to zero"},
dudmuck 13:fa2095be01c4 782 { "p", cmd_pwm, "%x %u %u", "send pwm period, duty to dev_addr"},
dudmuck 13:fa2095be01c4 783 { "bp", cmd_beacon_pwm, "%u %u", "send pwm period, duty on beacon"},
dudmuck 14:c6284654d1b0 784 { "ntxp", cmd_endnode_txp, "%x %u", "send txpower index to dev_addr"},
dudmuck 14:c6284654d1b0 785 { "bntxp", cmd_beacon_endnode_txp, "%u", "send txpower index on beacon"},
dudmuck 0:2ff18de8d48b 786 { NULL, NULL, NULL, NULL }
dudmuck 0:2ff18de8d48b 787 };
dudmuck 0:2ff18de8d48b 788
dudmuck 0:2ff18de8d48b 789 void cmd_help(uint8_t args_at)
dudmuck 0:2ff18de8d48b 790 {
dudmuck 0:2ff18de8d48b 791 int i;
dudmuck 0:2ff18de8d48b 792
dudmuck 0:2ff18de8d48b 793 for (i = 0; menu_items[i].cmd != NULL ; i++) {
dudmuck 0:2ff18de8d48b 794 printf("%s%s\t%s\r\n", menu_items[i].cmd, menu_items[i].arg_descr, menu_items[i].description);
dudmuck 0:2ff18de8d48b 795 }
dudmuck 0:2ff18de8d48b 796
dudmuck 0:2ff18de8d48b 797 }
dudmuck 0:2ff18de8d48b 798
dudmuck 0:2ff18de8d48b 799 void
dudmuck 0:2ff18de8d48b 800 console()
dudmuck 0:2ff18de8d48b 801 {
dudmuck 0:2ff18de8d48b 802 int i;
dudmuck 0:2ff18de8d48b 803 uint8_t user_cmd_len;
dudmuck 0:2ff18de8d48b 804
dudmuck 0:2ff18de8d48b 805 if (pcbuf_len < 0) { // ctrl-C
dudmuck 0:2ff18de8d48b 806 //printf("abort\r\n");
dudmuck 0:2ff18de8d48b 807 return;
dudmuck 0:2ff18de8d48b 808 }
dudmuck 0:2ff18de8d48b 809 if (pcbuf_len == 0)
dudmuck 0:2ff18de8d48b 810 return;
dudmuck 0:2ff18de8d48b 811
dudmuck 0:2ff18de8d48b 812 printf("\r\n");
dudmuck 0:2ff18de8d48b 813
dudmuck 0:2ff18de8d48b 814 /* get end of user-entered command */
dudmuck 0:2ff18de8d48b 815 user_cmd_len = 1; // first character can be any character
dudmuck 0:2ff18de8d48b 816 for (i = 1; i <= pcbuf_len; i++) {
dudmuck 0:2ff18de8d48b 817 if (pcbuf[i] < 'A' || (pcbuf[i] > 'Z' && pcbuf[i] < 'a') || pcbuf[i] > 'z') {
dudmuck 0:2ff18de8d48b 818 user_cmd_len = i;
dudmuck 0:2ff18de8d48b 819 break;
dudmuck 0:2ff18de8d48b 820 }
dudmuck 0:2ff18de8d48b 821 }
dudmuck 0:2ff18de8d48b 822
dudmuck 0:2ff18de8d48b 823 for (i = 0; menu_items[i].cmd != NULL ; i++) {
dudmuck 0:2ff18de8d48b 824 int mi_len = strlen(menu_items[i].cmd);
dudmuck 0:2ff18de8d48b 825
dudmuck 0:2ff18de8d48b 826 if (menu_items[i].handler && user_cmd_len == mi_len && (strncmp(pcbuf, menu_items[i].cmd, mi_len) == 0)) {
dudmuck 0:2ff18de8d48b 827 while (pcbuf[mi_len] == ' ') // skip past spaces
dudmuck 0:2ff18de8d48b 828 mi_len++;
dudmuck 0:2ff18de8d48b 829 menu_items[i].handler(mi_len);
dudmuck 0:2ff18de8d48b 830 break;
dudmuck 0:2ff18de8d48b 831 }
dudmuck 0:2ff18de8d48b 832 }
dudmuck 0:2ff18de8d48b 833
dudmuck 0:2ff18de8d48b 834 pcbuf_len = 0;
dudmuck 0:2ff18de8d48b 835 printf("> ");
dudmuck 0:2ff18de8d48b 836 fflush(stdout);
dudmuck 0:2ff18de8d48b 837 }
dudmuck 0:2ff18de8d48b 838
dudmuck 0:2ff18de8d48b 839 int main()
dudmuck 0:2ff18de8d48b 840 {
dudmuck 0:2ff18de8d48b 841 Thread eventThread;
dudmuck 3:7c01b8978638 842 pc.baud(38400);
dudmuck 12:9a8c13c4298b 843 printf("\r\nreset %f\r\n", radio.get_frf_MHz());
dudmuck 11:50d0558a4e37 844 set_time(0);
dudmuck 0:2ff18de8d48b 845
dudmuck 0:2ff18de8d48b 846 radio.hw_reset();
dudmuck 12:9a8c13c4298b 847 printf("%fMHz\r\n", radio.get_frf_MHz());
dudmuck 0:2ff18de8d48b 848
dudmuck 10:6783623cc886 849 #ifndef TYPE_ABZ
dudmuck 15:fea23ad8eafa 850 /* LoRa arduino shield... */
dudmuck 15:fea23ad8eafa 851 #ifdef USE_BAND_433
dudmuck 15:fea23ad8eafa 852 radio.RegPaConfig.bits.PaSelect = 0; // RFO_LF connected
dudmuck 15:fea23ad8eafa 853 #else
dudmuck 0:2ff18de8d48b 854 rfsw.input();
dudmuck 0:2ff18de8d48b 855 if (rfsw.read()) {
dudmuck 0:2ff18de8d48b 856 printf("LAS\r\n");
dudmuck 0:2ff18de8d48b 857 /* LAS HF=PA_BOOST LF=RFO */
dudmuck 0:2ff18de8d48b 858 radio.RegPaConfig.bits.PaSelect = 1;
dudmuck 0:2ff18de8d48b 859 } else {
dudmuck 0:2ff18de8d48b 860 printf("MAS\r\n");
dudmuck 0:2ff18de8d48b 861 radio.RegPaConfig.bits.PaSelect = 0;
dudmuck 0:2ff18de8d48b 862 }
dudmuck 15:fea23ad8eafa 863 #endif /* !USE_BAND_433 */
dudmuck 0:2ff18de8d48b 864 rfsw.output();
dudmuck 15:fea23ad8eafa 865 /* ...LoRa arduino shield */
dudmuck 15:fea23ad8eafa 866 #endif
dudmuck 0:2ff18de8d48b 867
dudmuck 0:2ff18de8d48b 868 radio.rf_switch = rfsw_callback;
dudmuck 0:2ff18de8d48b 869
dudmuck 0:2ff18de8d48b 870 init_radio();
dudmuck 0:2ff18de8d48b 871
dudmuck 0:2ff18de8d48b 872 lora.start_rx(RF_OPMODE_RECEIVER);
dudmuck 0:2ff18de8d48b 873
dudmuck 0:2ff18de8d48b 874 eventThread.start(callback(&queue, &EventQueue::dispatch_forever));
dudmuck 0:2ff18de8d48b 875 LoRaWan::init();
dudmuck 0:2ff18de8d48b 876
dudmuck 0:2ff18de8d48b 877 timer.start();
dudmuck 0:2ff18de8d48b 878 tim_init();
dudmuck 4:7e743e402681 879
dudmuck 4:7e743e402681 880 pc.attach(&rx_isr);
dudmuck 9:a0ce66c18ec0 881
dudmuck 0:2ff18de8d48b 882
dudmuck 0:2ff18de8d48b 883 for (;;) {
dudmuck 0:2ff18de8d48b 884 console();
dudmuck 1:107435401168 885
dudmuck 1:107435401168 886 if (radio.dio0) {
dudmuck 3:7c01b8978638 887 if (get_tx_done) {
dudmuck 3:7c01b8978638 888 get_tx_done = false;
dudmuck 3:7c01b8978638 889 lora.RegIrqFlags.octet = 0;
dudmuck 3:7c01b8978638 890 lora.RegIrqFlags.bits.TxDone = 1;
dudmuck 3:7c01b8978638 891 radio.write_reg(REG_LR_IRQFLAGS, lora.RegIrqFlags.octet);
dudmuck 3:7c01b8978638 892
dudmuck 3:7c01b8978638 893 if (restore_tx_invert) {
dudmuck 3:7c01b8978638 894 lora.invert_tx(false);
dudmuck 3:7c01b8978638 895 restore_tx_invert = false;
dudmuck 3:7c01b8978638 896 }
dudmuck 3:7c01b8978638 897
dudmuck 3:7c01b8978638 898 if (restore_header_mode) {
dudmuck 3:7c01b8978638 899 lora.setHeaderMode(false);
dudmuck 3:7c01b8978638 900 restore_header_mode = false;
dudmuck 3:7c01b8978638 901 }
dudmuck 12:9a8c13c4298b 902
dudmuck 3:7c01b8978638 903 lora.start_rx(RF_OPMODE_RECEIVER);
dudmuck 12:9a8c13c4298b 904
dudmuck 12:9a8c13c4298b 905 if (beacon_guard) { // beacon done transmitting
dudmuck 12:9a8c13c4298b 906 measure_ambient();
dudmuck 12:9a8c13c4298b 907 beacon_guard = false;
dudmuck 12:9a8c13c4298b 908 }
dudmuck 3:7c01b8978638 909 } else {
dudmuck 3:7c01b8978638 910 if (!beacon_guard)
dudmuck 3:7c01b8978638 911 service_radio();
dudmuck 3:7c01b8978638 912 }
dudmuck 12:9a8c13c4298b 913 } else if (get_tx_done) {
dudmuck 12:9a8c13c4298b 914 /* dio0 not yet asserted */
dudmuck 12:9a8c13c4298b 915 uint32_t since = timer.read_ms() - tx_ms;
dudmuck 12:9a8c13c4298b 916 if (since > 4000) {
dudmuck 12:9a8c13c4298b 917 radio.RegOpMode.octet = radio.read_reg(REG_OPMODE);
dudmuck 12:9a8c13c4298b 918 if (radio.RegOpMode.bits.Mode == RF_OPMODE_STANDBY) {
dudmuck 12:9a8c13c4298b 919 /* done transmitting, but dio0 not asserted */
dudmuck 12:9a8c13c4298b 920 printf("txDone but no dio0\r\n");
dudmuck 12:9a8c13c4298b 921 radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1);
dudmuck 12:9a8c13c4298b 922 if (radio.RegDioMapping1.bits.Dio0Mapping != 1) {
dudmuck 12:9a8c13c4298b 923 printf("dio0mapping-fail\r\n");
dudmuck 12:9a8c13c4298b 924 radio.RegDioMapping1.bits.Dio0Mapping = 1;
dudmuck 12:9a8c13c4298b 925 radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet);
dudmuck 12:9a8c13c4298b 926 }
dudmuck 12:9a8c13c4298b 927 }
dudmuck 12:9a8c13c4298b 928 }
dudmuck 12:9a8c13c4298b 929 }
dudmuck 12:9a8c13c4298b 930
dudmuck 12:9a8c13c4298b 931 if (LoRaWan::do_downlink && !beacon_guard) {
dudmuck 12:9a8c13c4298b 932 uint32_t since = timer.read_ms() - LoRaWan::rx_ms;
dudmuck 12:9a8c13c4298b 933 if (since > 110)
dudmuck 13:fa2095be01c4 934 printf("since-tx:%lu\r\n", since);
dudmuck 12:9a8c13c4298b 935 if (since > 500) {
dudmuck 12:9a8c13c4298b 936 LoRaWan::do_downlink = false;
dudmuck 12:9a8c13c4298b 937 printf("stalled-tx\r\n");
dudmuck 12:9a8c13c4298b 938 cmd_rx_restart(0);
dudmuck 12:9a8c13c4298b 939 }
dudmuck 1:107435401168 940 }
dudmuck 8:307f7faeb594 941
dudmuck 0:2ff18de8d48b 942 } // ..for(;;)
dudmuck 0:2ff18de8d48b 943 }