Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: SX127x sx12xx_hal
main.cpp@17:763412df6872, 2017-08-11 (annotated)
- 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?
| User | Revision | Line number | New 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("[42mValidHeader[0m "); |
| dudmuck | 0:2ff18de8d48b | 170 | if (lora.RegIrqFlags.bits.PayloadCrcError) |
| dudmuck | 0:2ff18de8d48b | 171 | printf("[41mPayloadCrcError[0m "); |
| dudmuck | 0:2ff18de8d48b | 172 | if (lora.RegIrqFlags.bits.RxDone) |
| dudmuck | 0:2ff18de8d48b | 173 | printf("[42mRxDone[0m "); |
| 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("[7msleep[0m"); break; |
| dudmuck | 0:2ff18de8d48b | 188 | case RF_OPMODE_STANDBY: printf("[7mstby[0m"); break; |
| dudmuck | 0:2ff18de8d48b | 189 | case RF_OPMODE_SYNTHESIZER_TX: printf("[33mfstx[0m"); break; |
| dudmuck | 0:2ff18de8d48b | 190 | case RF_OPMODE_TRANSMITTER: printf("[31mtx[0m"); break; |
| dudmuck | 0:2ff18de8d48b | 191 | case RF_OPMODE_SYNTHESIZER_RX: printf("[33mfsrx[0m"); break; |
| dudmuck | 0:2ff18de8d48b | 192 | case RF_OPMODE_RECEIVER: printf("[32mrx[0m"); break; |
| dudmuck | 0:2ff18de8d48b | 193 | case 6: |
| dudmuck | 0:2ff18de8d48b | 194 | if (radio.RegOpMode.bits.LongRangeMode) |
| dudmuck | 0:2ff18de8d48b | 195 | printf("[42mrxs[0m"); |
| 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("[45mcad[0m"); |
| 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 | } |