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@14:c6284654d1b0, 2017-08-07 (annotated)
- Committer:
- dudmuck
- Date:
- Mon Aug 07 12:41:55 2017 -0700
- Revision:
- 14:c6284654d1b0
- Parent:
- 13:fa2095be01c4
- Child:
- 15:fea23ad8eafa
add command to send downlink with power instruction
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 | 12:9a8c13c4298b | 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 | 9:a0ce66c18ec0 | 208 | #define GPO_IDX 6 |
| dudmuck | 9:a0ce66c18ec0 | 209 | void decrypted_uplink(uint8_t* buf, uint8_t buflen, uint8_t port) |
| dudmuck | 9:a0ce66c18ec0 | 210 | { |
| dudmuck | 9:a0ce66c18ec0 | 211 | if (port == SENSOR_PORT) { |
| dudmuck | 9:a0ce66c18ec0 | 212 | uint16_t a_1, a_3, lum; |
| dudmuck | 9:a0ce66c18ec0 | 213 | a_1 = buf[0] << 8; |
| dudmuck | 9:a0ce66c18ec0 | 214 | a_1 += buf[1]; |
| dudmuck | 9:a0ce66c18ec0 | 215 | a_3 = buf[2] << 8; |
| dudmuck | 9:a0ce66c18ec0 | 216 | a_3 += buf[3]; |
| dudmuck | 9:a0ce66c18ec0 | 217 | lum = buf[4] << 8; |
| dudmuck | 9:a0ce66c18ec0 | 218 | lum += buf[5]; |
| dudmuck | 10:6783623cc886 | 219 | printf("SENSOR gpi:%u, gpo:%u, a1:%u, a3:%u, lum:%u\r\n", (buf[GPO_IDX] & 2) >> 1, buf[GPO_IDX] & 1, a_1, a_3, lum); |
| dudmuck | 9:a0ce66c18ec0 | 220 | } else if (port == TEXT_PORT) { |
| dudmuck | 9:a0ce66c18ec0 | 221 | buf[buflen] = 0; |
| dudmuck | 9:a0ce66c18ec0 | 222 | printf("TEXT %s\r\n", buf); |
| dudmuck | 9:a0ce66c18ec0 | 223 | } else { |
| dudmuck | 9:a0ce66c18ec0 | 224 | int i; |
| dudmuck | 9:a0ce66c18ec0 | 225 | printf("port%u: ", port); |
| dudmuck | 9:a0ce66c18ec0 | 226 | for (i = 0; i < buflen; i++) |
| dudmuck | 9:a0ce66c18ec0 | 227 | printf("%02x ", buf[i]); |
| dudmuck | 9:a0ce66c18ec0 | 228 | printf("\r\n"); |
| dudmuck | 9:a0ce66c18ec0 | 229 | } |
| dudmuck | 9:a0ce66c18ec0 | 230 | } |
| dudmuck | 9:a0ce66c18ec0 | 231 | |
| dudmuck | 0:2ff18de8d48b | 232 | EventQueue queue; |
| dudmuck | 3:7c01b8978638 | 233 | |
| dudmuck | 3:7c01b8978638 | 234 | volatile bool get_tx_done; |
| dudmuck | 3:7c01b8978638 | 235 | volatile bool beacon_guard; |
| dudmuck | 0:2ff18de8d48b | 236 | bool restore_tx_invert; |
| dudmuck | 3:7c01b8978638 | 237 | bool restore_header_mode; |
| dudmuck | 0:2ff18de8d48b | 238 | |
| dudmuck | 0:2ff18de8d48b | 239 | void send_downlink() |
| dudmuck | 0:2ff18de8d48b | 240 | { |
| dudmuck | 12:9a8c13c4298b | 241 | if (!beacon_guard && LoRaWan::do_downlink) { |
| dudmuck | 0:2ff18de8d48b | 242 | radio.set_opmode(RF_OPMODE_STANDBY); |
| dudmuck | 0:2ff18de8d48b | 243 | radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); |
| dudmuck | 0:2ff18de8d48b | 244 | lora.invert_tx(true); |
| dudmuck | 0:2ff18de8d48b | 245 | restore_tx_invert = true; |
| dudmuck | 0:2ff18de8d48b | 246 | lora.setRxPayloadCrcOn(false); |
| dudmuck | 0:2ff18de8d48b | 247 | lora.start_tx(lora.RegPayloadLength); |
| dudmuck | 0:2ff18de8d48b | 248 | LoRaWan::do_downlink = false; |
| dudmuck | 3:7c01b8978638 | 249 | get_tx_done = true; |
| dudmuck | 12:9a8c13c4298b | 250 | tx_ms = timer.read_ms(); |
| dudmuck | 0:2ff18de8d48b | 251 | } |
| dudmuck | 0:2ff18de8d48b | 252 | } |
| dudmuck | 0:2ff18de8d48b | 253 | |
| dudmuck | 12:9a8c13c4298b | 254 | |
| dudmuck | 0:2ff18de8d48b | 255 | void |
| dudmuck | 0:2ff18de8d48b | 256 | service_radio() |
| dudmuck | 0:2ff18de8d48b | 257 | { |
| dudmuck | 0:2ff18de8d48b | 258 | service_action_e act = lora.service(); |
| dudmuck | 0:2ff18de8d48b | 259 | |
| dudmuck | 0:2ff18de8d48b | 260 | switch (act) { |
| dudmuck | 0:2ff18de8d48b | 261 | case SERVICE_ERROR: |
| dudmuck | 0:2ff18de8d48b | 262 | printf("SERVICE_ERROR\r\n"); |
| dudmuck | 0:2ff18de8d48b | 263 | case SERVICE_TX_DONE: |
| dudmuck | 0:2ff18de8d48b | 264 | case SERVICE_NONE: |
| dudmuck | 0:2ff18de8d48b | 265 | break; |
| dudmuck | 0:2ff18de8d48b | 266 | case SERVICE_READ_FIFO: |
| dudmuck | 3:7c01b8978638 | 267 | LoRaWan::rx_slot = tim_get_current_slot(); |
| dudmuck | 3:7c01b8978638 | 268 | LoRaWan::rx_ms = timer.read_ms(); |
| dudmuck | 14:c6284654d1b0 | 269 | printf("%u, %lu, %.1fdB, %ddBm, ", |
| dudmuck | 14:c6284654d1b0 | 270 | LoRaWan::rx_slot, |
| dudmuck | 14:c6284654d1b0 | 271 | time(NULL), |
| dudmuck | 14:c6284654d1b0 | 272 | lora.RegPktSnrValue / 4.0, |
| dudmuck | 14:c6284654d1b0 | 273 | lora.get_pkt_rssi() |
| dudmuck | 14:c6284654d1b0 | 274 | ); |
| dudmuck | 12:9a8c13c4298b | 275 | radio.set_opmode(RF_OPMODE_STANDBY); |
| dudmuck | 12:9a8c13c4298b | 276 | LoRaWan::parse_receive(); |
| dudmuck | 12:9a8c13c4298b | 277 | if (!LoRaWan::do_downlink) { |
| dudmuck | 12:9a8c13c4298b | 278 | /* if not sending downlink, start receiver now */ |
| dudmuck | 3:7c01b8978638 | 279 | lora.start_rx(RF_OPMODE_RECEIVER); |
| dudmuck | 0:2ff18de8d48b | 280 | } |
| dudmuck | 12:9a8c13c4298b | 281 | |
| dudmuck | 0:2ff18de8d48b | 282 | break; |
| dudmuck | 0:2ff18de8d48b | 283 | } // ..switch (act) |
| dudmuck | 0:2ff18de8d48b | 284 | } |
| dudmuck | 0:2ff18de8d48b | 285 | |
| dudmuck | 0:2ff18de8d48b | 286 | volatile float prev_beacon_send_at; |
| dudmuck | 0:2ff18de8d48b | 287 | volatile float beacon_send_at; |
| dudmuck | 0:2ff18de8d48b | 288 | volatile float beacon_loaded_at; |
| dudmuck | 0:2ff18de8d48b | 289 | |
| dudmuck | 0:2ff18de8d48b | 290 | volatile bool beacon_loaded; |
| dudmuck | 0:2ff18de8d48b | 291 | void |
| dudmuck | 0:2ff18de8d48b | 292 | send_beacon() |
| dudmuck | 0:2ff18de8d48b | 293 | { |
| dudmuck | 0:2ff18de8d48b | 294 | prev_beacon_send_at = beacon_send_at; |
| dudmuck | 0:2ff18de8d48b | 295 | beacon_send_at = timer.read(); |
| dudmuck | 0:2ff18de8d48b | 296 | |
| dudmuck | 0:2ff18de8d48b | 297 | if (!beacon_loaded) |
| dudmuck | 0:2ff18de8d48b | 298 | return; |
| dudmuck | 0:2ff18de8d48b | 299 | |
| dudmuck | 0:2ff18de8d48b | 300 | radio.set_opmode(RF_OPMODE_TRANSMITTER); |
| dudmuck | 0:2ff18de8d48b | 301 | beacon_loaded = false; |
| dudmuck | 3:7c01b8978638 | 302 | get_tx_done = true; |
| dudmuck | 12:9a8c13c4298b | 303 | tx_ms = timer.read_ms(); |
| dudmuck | 0:2ff18de8d48b | 304 | } |
| dudmuck | 0:2ff18de8d48b | 305 | |
| dudmuck | 0:2ff18de8d48b | 306 | static uint16_t beacon_crc( uint8_t *buffer, uint16_t length ) |
| dudmuck | 0:2ff18de8d48b | 307 | { |
| dudmuck | 0:2ff18de8d48b | 308 | // The CRC calculation follows CCITT |
| dudmuck | 0:2ff18de8d48b | 309 | const uint16_t polynom = 0x1021; |
| dudmuck | 0:2ff18de8d48b | 310 | // CRC initial value |
| dudmuck | 0:2ff18de8d48b | 311 | uint16_t crc = 0x0000; |
| dudmuck | 0:2ff18de8d48b | 312 | |
| dudmuck | 0:2ff18de8d48b | 313 | if( buffer == NULL ) |
| dudmuck | 0:2ff18de8d48b | 314 | { |
| dudmuck | 0:2ff18de8d48b | 315 | return 0; |
| dudmuck | 0:2ff18de8d48b | 316 | } |
| dudmuck | 0:2ff18de8d48b | 317 | |
| dudmuck | 0:2ff18de8d48b | 318 | for( uint16_t i = 0; i < length; ++i ) |
| dudmuck | 0:2ff18de8d48b | 319 | { |
| dudmuck | 0:2ff18de8d48b | 320 | crc ^= ( uint16_t ) buffer[i] << 8; |
| dudmuck | 0:2ff18de8d48b | 321 | for( uint16_t j = 0; j < 8; ++j ) |
| dudmuck | 0:2ff18de8d48b | 322 | { |
| dudmuck | 0:2ff18de8d48b | 323 | crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 ); |
| dudmuck | 0:2ff18de8d48b | 324 | } |
| dudmuck | 0:2ff18de8d48b | 325 | } |
| dudmuck | 0:2ff18de8d48b | 326 | |
| dudmuck | 0:2ff18de8d48b | 327 | return crc; |
| dudmuck | 0:2ff18de8d48b | 328 | } |
| dudmuck | 0:2ff18de8d48b | 329 | |
| dudmuck | 0:2ff18de8d48b | 330 | void |
| dudmuck | 3:7c01b8978638 | 331 | _load_beacon() |
| dudmuck | 0:2ff18de8d48b | 332 | { |
| dudmuck | 0:2ff18de8d48b | 333 | uint16_t crc; |
| dudmuck | 12:9a8c13c4298b | 334 | radio.set_opmode(RF_OPMODE_STANDBY); |
| dudmuck | 12:9a8c13c4298b | 335 | // clear any flags which might have been set during beacon_guard |
| dudmuck | 12:9a8c13c4298b | 336 | radio.write_reg(REG_LR_IRQFLAGS, 0xff); |
| dudmuck | 0:2ff18de8d48b | 337 | lora.RegPayloadLength = BEACON_SIZE; |
| dudmuck | 0:2ff18de8d48b | 338 | radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); |
| dudmuck | 0:2ff18de8d48b | 339 | lora.setHeaderMode(true); |
| dudmuck | 3:7c01b8978638 | 340 | restore_header_mode = true; |
| dudmuck | 0:2ff18de8d48b | 341 | |
| dudmuck | 0:2ff18de8d48b | 342 | if (skip_beacon_cnt > 0) { |
| dudmuck | 1:107435401168 | 343 | //printf("skip_beacon_cnt:%d\r\n", skip_beacon_cnt); |
| dudmuck | 0:2ff18de8d48b | 344 | lora.invert_tx(true); |
| dudmuck | 0:2ff18de8d48b | 345 | restore_tx_invert = true; |
| dudmuck | 0:2ff18de8d48b | 346 | skip_beacon_cnt--; |
| dudmuck | 0:2ff18de8d48b | 347 | } |
| dudmuck | 0:2ff18de8d48b | 348 | |
| dudmuck | 9:a0ce66c18ec0 | 349 | radio.tx_buf[0] = beacon_payload[0]; |
| dudmuck | 9:a0ce66c18ec0 | 350 | radio.tx_buf[1] = beacon_payload[1]; |
| dudmuck | 9:a0ce66c18ec0 | 351 | radio.tx_buf[2] = beacon_payload[2]; |
| dudmuck | 9:a0ce66c18ec0 | 352 | radio.tx_buf[3] = beacon_payload[3]; |
| dudmuck | 9:a0ce66c18ec0 | 353 | beacon_payload[0] = CMD_NONE; |
| dudmuck | 9:a0ce66c18ec0 | 354 | |
| dudmuck | 0:2ff18de8d48b | 355 | crc = beacon_crc(radio.tx_buf, 4); |
| dudmuck | 0:2ff18de8d48b | 356 | radio.tx_buf[4] = crc & 0xff; |
| dudmuck | 0:2ff18de8d48b | 357 | radio.tx_buf[5] = crc >> 8; |
| dudmuck | 0:2ff18de8d48b | 358 | |
| dudmuck | 0:2ff18de8d48b | 359 | // DIO0 to TxDone |
| dudmuck | 3:7c01b8978638 | 360 | radio.RegDioMapping1.bits.Dio0Mapping = 1; |
| dudmuck | 3:7c01b8978638 | 361 | radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet); |
| dudmuck | 0:2ff18de8d48b | 362 | |
| dudmuck | 0:2ff18de8d48b | 363 | // set FifoPtrAddr to FifoTxPtrBase |
| dudmuck | 0:2ff18de8d48b | 364 | radio.write_reg(REG_LR_FIFOADDRPTR, radio.read_reg(REG_LR_FIFOTXBASEADDR)); |
| dudmuck | 0:2ff18de8d48b | 365 | |
| dudmuck | 0:2ff18de8d48b | 366 | // write PayloadLength bytes to fifo |
| dudmuck | 0:2ff18de8d48b | 367 | lora.write_fifo(lora.RegPayloadLength); |
| dudmuck | 0:2ff18de8d48b | 368 | |
| dudmuck | 0:2ff18de8d48b | 369 | // prepare for tx to occur in send_beacon() |
| dudmuck | 0:2ff18de8d48b | 370 | radio.set_opmode(RF_OPMODE_SYNTHESIZER_TX); |
| dudmuck | 0:2ff18de8d48b | 371 | beacon_loaded = true; |
| dudmuck | 0:2ff18de8d48b | 372 | |
| dudmuck | 0:2ff18de8d48b | 373 | beacon_loaded_at = timer.read(); |
| dudmuck | 0:2ff18de8d48b | 374 | } |
| dudmuck | 0:2ff18de8d48b | 375 | |
| dudmuck | 3:7c01b8978638 | 376 | void load_beacon() |
| dudmuck | 3:7c01b8978638 | 377 | { |
| dudmuck | 3:7c01b8978638 | 378 | beacon_guard = true; |
| dudmuck | 12:9a8c13c4298b | 379 | queue.call_in(200, _load_beacon); |
| dudmuck | 3:7c01b8978638 | 380 | } |
| dudmuck | 3:7c01b8978638 | 381 | |
| dudmuck | 0:2ff18de8d48b | 382 | void get_time_till_beacon() |
| dudmuck | 0:2ff18de8d48b | 383 | { |
| dudmuck | 0:2ff18de8d48b | 384 | uint16_t slots = tim_get_current_slot(); |
| dudmuck | 0:2ff18de8d48b | 385 | printf("slots:%u\r\n", slots); |
| dudmuck | 0:2ff18de8d48b | 386 | } |
| dudmuck | 0:2ff18de8d48b | 387 | |
| dudmuck | 4:7e743e402681 | 388 | void rx_isr() |
| dudmuck | 0:2ff18de8d48b | 389 | { |
| dudmuck | 0:2ff18de8d48b | 390 | static uint8_t pcbuf_idx = 0; |
| dudmuck | 0:2ff18de8d48b | 391 | static uint8_t prev_len = 0;; |
| dudmuck | 0:2ff18de8d48b | 392 | char c = pc.getc(); |
| dudmuck | 0:2ff18de8d48b | 393 | |
| dudmuck | 0:2ff18de8d48b | 394 | if (c == 8) { |
| dudmuck | 0:2ff18de8d48b | 395 | if (pcbuf_idx > 0) { |
| dudmuck | 0:2ff18de8d48b | 396 | pc.putc(8); |
| dudmuck | 0:2ff18de8d48b | 397 | pc.putc(' '); |
| dudmuck | 0:2ff18de8d48b | 398 | pc.putc(8); |
| dudmuck | 0:2ff18de8d48b | 399 | pcbuf_idx--; |
| dudmuck | 0:2ff18de8d48b | 400 | } |
| dudmuck | 0:2ff18de8d48b | 401 | } else if (c == 3) { // ctrl-C |
| dudmuck | 0:2ff18de8d48b | 402 | pcbuf_len = -1; |
| dudmuck | 0:2ff18de8d48b | 403 | } else if (c == '\r') { |
| dudmuck | 0:2ff18de8d48b | 404 | if (pcbuf_idx == 0) { |
| dudmuck | 0:2ff18de8d48b | 405 | pcbuf_len = prev_len; |
| dudmuck | 0:2ff18de8d48b | 406 | } else { |
| dudmuck | 0:2ff18de8d48b | 407 | pcbuf[pcbuf_idx] = 0; // null terminate |
| dudmuck | 0:2ff18de8d48b | 408 | prev_len = pcbuf_idx; |
| dudmuck | 0:2ff18de8d48b | 409 | pcbuf_idx = 0; |
| dudmuck | 0:2ff18de8d48b | 410 | pcbuf_len = prev_len; |
| dudmuck | 0:2ff18de8d48b | 411 | } |
| dudmuck | 0:2ff18de8d48b | 412 | } else if (pcbuf_idx < sizeof(pcbuf)) { |
| dudmuck | 0:2ff18de8d48b | 413 | pcbuf[pcbuf_idx++] = c; |
| dudmuck | 0:2ff18de8d48b | 414 | pc.putc(c); |
| dudmuck | 0:2ff18de8d48b | 415 | } |
| dudmuck | 0:2ff18de8d48b | 416 | } |
| dudmuck | 0:2ff18de8d48b | 417 | |
| dudmuck | 0:2ff18de8d48b | 418 | void cmd_skip_beacon(uint8_t idx) |
| dudmuck | 0:2ff18de8d48b | 419 | { |
| dudmuck | 0:2ff18de8d48b | 420 | if (pcbuf[idx] >= '0' && pcbuf[idx] <= '9') { |
| dudmuck | 0:2ff18de8d48b | 421 | sscanf(pcbuf+idx, "%u", &skip_beacon_cnt); |
| dudmuck | 0:2ff18de8d48b | 422 | } |
| dudmuck | 0:2ff18de8d48b | 423 | printf("skip_beacon_cnt:%u\r\n", skip_beacon_cnt); |
| dudmuck | 0:2ff18de8d48b | 424 | } |
| dudmuck | 0:2ff18de8d48b | 425 | |
| dudmuck | 0:2ff18de8d48b | 426 | void cmd_list_motes(uint8_t idx) |
| dudmuck | 0:2ff18de8d48b | 427 | { |
| dudmuck | 0:2ff18de8d48b | 428 | int i; |
| dudmuck | 0:2ff18de8d48b | 429 | for (i = 0; i < N_MOTES; i++) { |
| dudmuck | 0:2ff18de8d48b | 430 | if (motes[i].dev_addr != DEVADDR_NONE) { |
| dudmuck | 13:fa2095be01c4 | 431 | LoRaWan::print_octets_rev("", motes[i].dev_eui, LORA_EUI_LENGTH); |
| dudmuck | 13:fa2095be01c4 | 432 | printf(" %" PRIx32 "\r\n", motes[i].dev_addr); |
| dudmuck | 0:2ff18de8d48b | 433 | } |
| dudmuck | 0:2ff18de8d48b | 434 | } |
| dudmuck | 0:2ff18de8d48b | 435 | } |
| dudmuck | 0:2ff18de8d48b | 436 | |
| dudmuck | 0:2ff18de8d48b | 437 | void |
| dudmuck | 0:2ff18de8d48b | 438 | cmd_beacon_payload(uint8_t idx) |
| dudmuck | 0:2ff18de8d48b | 439 | { |
| dudmuck | 9:a0ce66c18ec0 | 440 | uint32_t i; |
| dudmuck | 9:a0ce66c18ec0 | 441 | uint32_t* ptr; |
| dudmuck | 13:fa2095be01c4 | 442 | sscanf(pcbuf+idx, "%" PRIx32, &i); |
| dudmuck | 13:fa2095be01c4 | 443 | printf("beacon_payload:%08" PRIx32 "\r\n", i); |
| dudmuck | 9:a0ce66c18ec0 | 444 | ptr = (uint32_t*)beacon_payload; |
| dudmuck | 9:a0ce66c18ec0 | 445 | *ptr = i; |
| dudmuck | 8:307f7faeb594 | 446 | } |
| dudmuck | 8:307f7faeb594 | 447 | |
| dudmuck | 0:2ff18de8d48b | 448 | void |
| dudmuck | 0:2ff18de8d48b | 449 | cmd_send_downlink(uint8_t idx) |
| dudmuck | 0:2ff18de8d48b | 450 | { |
| dudmuck | 0:2ff18de8d48b | 451 | ota_mote_t* mote = NULL; |
| dudmuck | 0:2ff18de8d48b | 452 | int i; |
| dudmuck | 0:2ff18de8d48b | 453 | unsigned int dev_addr; |
| dudmuck | 0:2ff18de8d48b | 454 | sscanf(pcbuf+idx, "%x", &dev_addr); |
| dudmuck | 0:2ff18de8d48b | 455 | for (i = 0; i < N_MOTES; i++) { |
| dudmuck | 0:2ff18de8d48b | 456 | if (motes[i].dev_addr == dev_addr) { |
| dudmuck | 0:2ff18de8d48b | 457 | break; |
| dudmuck | 0:2ff18de8d48b | 458 | } |
| dudmuck | 0:2ff18de8d48b | 459 | } |
| dudmuck | 0:2ff18de8d48b | 460 | if (i == N_MOTES) { |
| dudmuck | 0:2ff18de8d48b | 461 | printf("mote %x not found\r\n", dev_addr); |
| dudmuck | 0:2ff18de8d48b | 462 | return; |
| dudmuck | 0:2ff18de8d48b | 463 | } |
| dudmuck | 0:2ff18de8d48b | 464 | mote = &motes[i]; |
| dudmuck | 0:2ff18de8d48b | 465 | |
| dudmuck | 0:2ff18de8d48b | 466 | while (pcbuf[idx] != ' ') { |
| dudmuck | 0:2ff18de8d48b | 467 | if (pcbuf[++idx] == 0) { |
| dudmuck | 0:2ff18de8d48b | 468 | printf("hit end\r\n"); |
| dudmuck | 0:2ff18de8d48b | 469 | return; |
| dudmuck | 0:2ff18de8d48b | 470 | } |
| dudmuck | 0:2ff18de8d48b | 471 | } |
| dudmuck | 0:2ff18de8d48b | 472 | idx++; // step past space |
| dudmuck | 0:2ff18de8d48b | 473 | |
| dudmuck | 0:2ff18de8d48b | 474 | mote->user_downlink_length = 0; |
| dudmuck | 0:2ff18de8d48b | 475 | while (pcbuf[idx] > ' ') { |
| dudmuck | 0:2ff18de8d48b | 476 | int o; |
| dudmuck | 0:2ff18de8d48b | 477 | sscanf(pcbuf+idx, "%02x", &o); |
| dudmuck | 0:2ff18de8d48b | 478 | LoRaWan::user_downlink[mote->user_downlink_length++] = o; |
| dudmuck | 0:2ff18de8d48b | 479 | idx += 2; |
| dudmuck | 0:2ff18de8d48b | 480 | } |
| dudmuck | 0:2ff18de8d48b | 481 | |
| dudmuck | 13:fa2095be01c4 | 482 | printf("%u bytes scheduled for %" PRIx32 "\r\n", mote->user_downlink_length, mote->dev_addr); |
| dudmuck | 0:2ff18de8d48b | 483 | } |
| dudmuck | 0:2ff18de8d48b | 484 | |
| dudmuck | 9:a0ce66c18ec0 | 485 | void cmd_rx_restart(uint8_t idx) |
| dudmuck | 9:a0ce66c18ec0 | 486 | { |
| dudmuck | 9:a0ce66c18ec0 | 487 | /*radio.set_opmode(RF_OPMODE_STANDBY); |
| dudmuck | 9:a0ce66c18ec0 | 488 | printf("standby\r\n");*/ |
| dudmuck | 9:a0ce66c18ec0 | 489 | radio.set_opmode(RF_OPMODE_SLEEP); |
| dudmuck | 9:a0ce66c18ec0 | 490 | printf("sleep\r\n"); |
| dudmuck | 9:a0ce66c18ec0 | 491 | wait(0.05); |
| dudmuck | 9:a0ce66c18ec0 | 492 | radio.set_opmode(RF_OPMODE_RECEIVER); |
| dudmuck | 9:a0ce66c18ec0 | 493 | printf("receive\r\n"); |
| dudmuck | 9:a0ce66c18ec0 | 494 | } |
| dudmuck | 9:a0ce66c18ec0 | 495 | |
| dudmuck | 9:a0ce66c18ec0 | 496 | void cmd_beacon_gpo(uint8_t idx) |
| dudmuck | 9:a0ce66c18ec0 | 497 | { |
| dudmuck | 9:a0ce66c18ec0 | 498 | int gpo; |
| dudmuck | 9:a0ce66c18ec0 | 499 | sscanf(pcbuf+idx, "%d", &gpo); |
| dudmuck | 9:a0ce66c18ec0 | 500 | beacon_payload[0] = CMD_GPIO_OUT; |
| dudmuck | 9:a0ce66c18ec0 | 501 | beacon_payload[1] = gpo; |
| dudmuck | 9:a0ce66c18ec0 | 502 | printf("beacon gpo: %d\r\n", gpo); |
| dudmuck | 9:a0ce66c18ec0 | 503 | } |
| dudmuck | 9:a0ce66c18ec0 | 504 | |
| dudmuck | 9:a0ce66c18ec0 | 505 | void cmd_beacon_rgb(uint8_t idx) |
| dudmuck | 9:a0ce66c18ec0 | 506 | { |
| dudmuck | 9:a0ce66c18ec0 | 507 | int r, g ,b; |
| dudmuck | 9:a0ce66c18ec0 | 508 | sscanf(pcbuf+idx, "%d %d %d", &r, &g, &b); |
| dudmuck | 9:a0ce66c18ec0 | 509 | beacon_payload[0] = CMD_LED_RGB; |
| dudmuck | 9:a0ce66c18ec0 | 510 | beacon_payload[1] = r; |
| dudmuck | 9:a0ce66c18ec0 | 511 | beacon_payload[2] = g; |
| dudmuck | 9:a0ce66c18ec0 | 512 | beacon_payload[3] = b; |
| dudmuck | 9:a0ce66c18ec0 | 513 | printf("beacon rgb: %d %d %d\r\n", r, g, b); |
| dudmuck | 9:a0ce66c18ec0 | 514 | } |
| dudmuck | 9:a0ce66c18ec0 | 515 | |
| dudmuck | 9:a0ce66c18ec0 | 516 | void cmd_downlink_rgb(uint8_t idx) |
| dudmuck | 9:a0ce66c18ec0 | 517 | { |
| dudmuck | 9:a0ce66c18ec0 | 518 | ota_mote_t* mote = NULL; |
| dudmuck | 9:a0ce66c18ec0 | 519 | int i, r, g ,b; |
| dudmuck | 9:a0ce66c18ec0 | 520 | unsigned int dev_addr; |
| dudmuck | 9:a0ce66c18ec0 | 521 | sscanf(pcbuf+idx, "%x %d %d %d", &dev_addr, &r, &g, &b); |
| dudmuck | 9:a0ce66c18ec0 | 522 | for (i = 0; i < N_MOTES; i++) { |
| dudmuck | 9:a0ce66c18ec0 | 523 | if (motes[i].dev_addr == dev_addr) { |
| dudmuck | 9:a0ce66c18ec0 | 524 | break; |
| dudmuck | 9:a0ce66c18ec0 | 525 | } |
| dudmuck | 9:a0ce66c18ec0 | 526 | } |
| dudmuck | 9:a0ce66c18ec0 | 527 | if (i == N_MOTES) { |
| dudmuck | 9:a0ce66c18ec0 | 528 | printf("mote %x not found\r\n", dev_addr); |
| dudmuck | 9:a0ce66c18ec0 | 529 | return; |
| dudmuck | 9:a0ce66c18ec0 | 530 | } |
| dudmuck | 9:a0ce66c18ec0 | 531 | mote = &motes[i]; |
| dudmuck | 9:a0ce66c18ec0 | 532 | |
| dudmuck | 9:a0ce66c18ec0 | 533 | mote->user_downlink_length = 0; |
| dudmuck | 9:a0ce66c18ec0 | 534 | LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_LED_RGB; |
| dudmuck | 9:a0ce66c18ec0 | 535 | LoRaWan::user_downlink[mote->user_downlink_length++] = r; |
| dudmuck | 9:a0ce66c18ec0 | 536 | LoRaWan::user_downlink[mote->user_downlink_length++] = g; |
| dudmuck | 9:a0ce66c18ec0 | 537 | LoRaWan::user_downlink[mote->user_downlink_length++] = b; |
| dudmuck | 9:a0ce66c18ec0 | 538 | |
| dudmuck | 13:fa2095be01c4 | 539 | printf("rgb %d %d %d to mote %" PRIx32 "\r\n", r, g, b, mote->dev_addr); |
| dudmuck | 9:a0ce66c18ec0 | 540 | } |
| dudmuck | 9:a0ce66c18ec0 | 541 | |
| dudmuck | 9:a0ce66c18ec0 | 542 | void cmd_downlink_gpo(uint8_t idx) |
| dudmuck | 9:a0ce66c18ec0 | 543 | { |
| dudmuck | 9:a0ce66c18ec0 | 544 | ota_mote_t* mote = NULL; |
| dudmuck | 9:a0ce66c18ec0 | 545 | int i, gpo; |
| dudmuck | 9:a0ce66c18ec0 | 546 | unsigned int dev_addr; |
| dudmuck | 9:a0ce66c18ec0 | 547 | sscanf(pcbuf+idx, "%x %d", &dev_addr, &gpo); |
| dudmuck | 9:a0ce66c18ec0 | 548 | for (i = 0; i < N_MOTES; i++) { |
| dudmuck | 9:a0ce66c18ec0 | 549 | if (motes[i].dev_addr == dev_addr) { |
| dudmuck | 9:a0ce66c18ec0 | 550 | break; |
| dudmuck | 9:a0ce66c18ec0 | 551 | } |
| dudmuck | 9:a0ce66c18ec0 | 552 | } |
| dudmuck | 9:a0ce66c18ec0 | 553 | if (i == N_MOTES) { |
| dudmuck | 9:a0ce66c18ec0 | 554 | printf("mote %x not found\r\n", dev_addr); |
| dudmuck | 9:a0ce66c18ec0 | 555 | return; |
| dudmuck | 9:a0ce66c18ec0 | 556 | } |
| dudmuck | 9:a0ce66c18ec0 | 557 | mote = &motes[i]; |
| dudmuck | 9:a0ce66c18ec0 | 558 | |
| dudmuck | 9:a0ce66c18ec0 | 559 | mote->user_downlink_length = 0; |
| dudmuck | 9:a0ce66c18ec0 | 560 | LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_GPIO_OUT; |
| dudmuck | 9:a0ce66c18ec0 | 561 | LoRaWan::user_downlink[mote->user_downlink_length++] = gpo; |
| dudmuck | 9:a0ce66c18ec0 | 562 | |
| dudmuck | 13:fa2095be01c4 | 563 | printf("gpo %d to mote %" PRIx32 "\r\n", gpo, mote->dev_addr); |
| dudmuck | 9:a0ce66c18ec0 | 564 | } |
| dudmuck | 9:a0ce66c18ec0 | 565 | |
| dudmuck | 0:2ff18de8d48b | 566 | void cmd_status(uint8_t idx) |
| dudmuck | 0:2ff18de8d48b | 567 | { |
| dudmuck | 14:c6284654d1b0 | 568 | radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG); |
| dudmuck | 14:c6284654d1b0 | 569 | if (radio.RegPaConfig.bits.PaSelect) |
| dudmuck | 14:c6284654d1b0 | 570 | printf("PA_BOOST "); |
| dudmuck | 14:c6284654d1b0 | 571 | else |
| dudmuck | 14:c6284654d1b0 | 572 | printf("RFO "); |
| dudmuck | 14:c6284654d1b0 | 573 | |
| dudmuck | 0:2ff18de8d48b | 574 | radio.RegOpMode.octet = radio.read_reg(REG_OPMODE); |
| dudmuck | 2:9628d5e4b1bf | 575 | printf("%.3fMHz sf%ubw%u ", radio.get_frf_MHz(), lora.getSf(), lora.getBw()); |
| dudmuck | 0:2ff18de8d48b | 576 | printOpMode(); |
| dudmuck | 0:2ff18de8d48b | 577 | if (!radio.RegOpMode.bits.LongRangeMode) { |
| dudmuck | 0:2ff18de8d48b | 578 | printf("FSK\r\n"); |
| dudmuck | 0:2ff18de8d48b | 579 | return; |
| dudmuck | 0:2ff18de8d48b | 580 | } |
| dudmuck | 0:2ff18de8d48b | 581 | |
| dudmuck | 0:2ff18de8d48b | 582 | lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); |
| dudmuck | 0:2ff18de8d48b | 583 | printLoraIrqs(false); |
| dudmuck | 0:2ff18de8d48b | 584 | |
| dudmuck | 12:9a8c13c4298b | 585 | printf(" do_downlink:%u get_tx_done:%u, ", LoRaWan::do_downlink, get_tx_done); |
| dudmuck | 9:a0ce66c18ec0 | 586 | lora.RegTest33.octet = radio.read_reg(REG_LR_TEST33); // invert_i_q |
| dudmuck | 9:a0ce66c18ec0 | 587 | lora.RegDriftInvert.octet = radio.read_reg(REG_LR_DRIFT_INVERT); |
| dudmuck | 9:a0ce66c18ec0 | 588 | printf("modemstat:%02x, rxinv:%x,%x\r\n", radio.read_reg(REG_LR_MODEMSTAT), lora.RegTest33.octet, lora.RegDriftInvert.octet); |
| dudmuck | 2:9628d5e4b1bf | 589 | radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1); |
| dudmuck | 2:9628d5e4b1bf | 590 | 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 | 591 | printf("FIfoAddrPtr:%02x RxBase:%02x\r\n", radio.read_reg(REG_LR_FIFOADDRPTR), radio.read_reg(REG_LR_FIFORXBASEADDR)); |
| dudmuck | 0:2ff18de8d48b | 592 | } |
| dudmuck | 0:2ff18de8d48b | 593 | |
| dudmuck | 11:50d0558a4e37 | 594 | void cmd_op(uint8_t idx) |
| dudmuck | 11:50d0558a4e37 | 595 | { |
| dudmuck | 11:50d0558a4e37 | 596 | int i, dbm; |
| dudmuck | 11:50d0558a4e37 | 597 | RegPdsTrim1_t pds_trim; |
| dudmuck | 11:50d0558a4e37 | 598 | uint8_t adr; |
| dudmuck | 11:50d0558a4e37 | 599 | if (radio.type == SX1276) |
| dudmuck | 11:50d0558a4e37 | 600 | adr = REG_PDSTRIM1_SX1276; |
| dudmuck | 11:50d0558a4e37 | 601 | else |
| dudmuck | 11:50d0558a4e37 | 602 | adr = REG_PDSTRIM1_SX1272; |
| dudmuck | 11:50d0558a4e37 | 603 | |
| dudmuck | 11:50d0558a4e37 | 604 | pds_trim.octet = radio.read_reg(adr); |
| dudmuck | 11:50d0558a4e37 | 605 | |
| dudmuck | 11:50d0558a4e37 | 606 | if (pcbuf[idx] >= '0' && (pcbuf[idx] <= '9' || pcbuf[idx] == '-')) { |
| dudmuck | 11:50d0558a4e37 | 607 | sscanf(pcbuf+idx, "%d", &i); |
| dudmuck | 11:50d0558a4e37 | 608 | if (radio.RegPaConfig.bits.PaSelect) { |
| dudmuck | 11:50d0558a4e37 | 609 | /* PABOOST used: +2dbm to +17, or +20 */ |
| dudmuck | 11:50d0558a4e37 | 610 | if (i == 20) { |
| dudmuck | 11:50d0558a4e37 | 611 | printf("+20dBm PADAC bias\r\n"); |
| dudmuck | 11:50d0558a4e37 | 612 | i -= 3; |
| dudmuck | 11:50d0558a4e37 | 613 | pds_trim.bits.prog_txdac = 7; |
| dudmuck | 11:50d0558a4e37 | 614 | radio.write_reg(adr, pds_trim.octet); |
| dudmuck | 11:50d0558a4e37 | 615 | } |
| dudmuck | 11:50d0558a4e37 | 616 | if (i > 1) |
| dudmuck | 11:50d0558a4e37 | 617 | radio.RegPaConfig.bits.OutputPower = i - 2; |
| dudmuck | 11:50d0558a4e37 | 618 | } else { |
| dudmuck | 11:50d0558a4e37 | 619 | /* RFO used: -1 to +14dbm */ |
| dudmuck | 11:50d0558a4e37 | 620 | if (i < 15) |
| dudmuck | 11:50d0558a4e37 | 621 | radio.RegPaConfig.bits.OutputPower = i + 1; |
| dudmuck | 11:50d0558a4e37 | 622 | } |
| dudmuck | 11:50d0558a4e37 | 623 | radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet); |
| dudmuck | 11:50d0558a4e37 | 624 | } |
| dudmuck | 11:50d0558a4e37 | 625 | radio.RegPaConfig.octet = radio.read_reg(REG_PACONFIG); |
| dudmuck | 11:50d0558a4e37 | 626 | if (radio.RegPaConfig.bits.PaSelect) { |
| dudmuck | 11:50d0558a4e37 | 627 | printf("PA_BOOST "); |
| dudmuck | 11:50d0558a4e37 | 628 | dbm = radio.RegPaConfig.bits.OutputPower + pds_trim.bits.prog_txdac - 2; |
| dudmuck | 11:50d0558a4e37 | 629 | } else { |
| dudmuck | 11:50d0558a4e37 | 630 | printf("RFO "); |
| dudmuck | 11:50d0558a4e37 | 631 | dbm = radio.RegPaConfig.bits.OutputPower - 1; |
| dudmuck | 11:50d0558a4e37 | 632 | } |
| dudmuck | 11:50d0558a4e37 | 633 | printf("OutputPower:%ddBm\r\n", dbm); |
| dudmuck | 11:50d0558a4e37 | 634 | } |
| dudmuck | 11:50d0558a4e37 | 635 | |
| dudmuck | 14:c6284654d1b0 | 636 | #ifdef TYPE_ABZ |
| dudmuck | 14:c6284654d1b0 | 637 | void cmd_pa_select(uint8_t idx) |
| dudmuck | 14:c6284654d1b0 | 638 | { |
| dudmuck | 14:c6284654d1b0 | 639 | radio.RegPaConfig.bits.PaSelect ^= 1; |
| dudmuck | 14:c6284654d1b0 | 640 | radio.write_reg(REG_PACONFIG, radio.RegPaConfig.octet); |
| dudmuck | 14:c6284654d1b0 | 641 | if (radio.RegPaConfig.bits.PaSelect) |
| dudmuck | 14:c6284654d1b0 | 642 | printf("PA_BOOST\r\n"); |
| dudmuck | 14:c6284654d1b0 | 643 | else |
| dudmuck | 14:c6284654d1b0 | 644 | printf("RFO\r\n"); |
| dudmuck | 14:c6284654d1b0 | 645 | } |
| dudmuck | 14:c6284654d1b0 | 646 | #endif /* TYPE_ABZ */ |
| dudmuck | 14:c6284654d1b0 | 647 | |
| dudmuck | 12:9a8c13c4298b | 648 | void cmd_set_time(uint8_t idx) |
| dudmuck | 12:9a8c13c4298b | 649 | { |
| dudmuck | 12:9a8c13c4298b | 650 | set_time(0); |
| dudmuck | 13:fa2095be01c4 | 651 | printf("time:%" PRIu32 "\r\n", time(NULL)); |
| dudmuck | 12:9a8c13c4298b | 652 | } |
| dudmuck | 12:9a8c13c4298b | 653 | |
| dudmuck | 13:fa2095be01c4 | 654 | |
| dudmuck | 13:fa2095be01c4 | 655 | void cmd_pwm(uint8_t idx) |
| dudmuck | 12:9a8c13c4298b | 656 | { |
| dudmuck | 13:fa2095be01c4 | 657 | ota_mote_t* mote; |
| dudmuck | 12:9a8c13c4298b | 658 | int i; |
| dudmuck | 13:fa2095be01c4 | 659 | unsigned dev_addr, p, d; |
| dudmuck | 13:fa2095be01c4 | 660 | |
| dudmuck | 13:fa2095be01c4 | 661 | if (sscanf(pcbuf+idx, "%x %u %u", &dev_addr, &p, &d) != 3) { |
| dudmuck | 13:fa2095be01c4 | 662 | printf("parse fail\r\n"); |
| dudmuck | 13:fa2095be01c4 | 663 | return; |
| dudmuck | 13:fa2095be01c4 | 664 | } |
| dudmuck | 12:9a8c13c4298b | 665 | for (i = 0; i < N_MOTES; i++) { |
| dudmuck | 12:9a8c13c4298b | 666 | if (motes[i].dev_addr == dev_addr) { |
| dudmuck | 12:9a8c13c4298b | 667 | break; |
| dudmuck | 12:9a8c13c4298b | 668 | } |
| dudmuck | 12:9a8c13c4298b | 669 | } |
| dudmuck | 12:9a8c13c4298b | 670 | if (i == N_MOTES) { |
| dudmuck | 12:9a8c13c4298b | 671 | printf("mote %x not found\r\n", dev_addr); |
| dudmuck | 12:9a8c13c4298b | 672 | return; |
| dudmuck | 12:9a8c13c4298b | 673 | } |
| dudmuck | 12:9a8c13c4298b | 674 | |
| dudmuck | 12:9a8c13c4298b | 675 | mote = &motes[i]; |
| dudmuck | 12:9a8c13c4298b | 676 | |
| dudmuck | 12:9a8c13c4298b | 677 | mote->user_downlink_length = 0; |
| dudmuck | 13:fa2095be01c4 | 678 | LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_PWM; |
| dudmuck | 13:fa2095be01c4 | 679 | LoRaWan::user_downlink[mote->user_downlink_length++] = p; |
| dudmuck | 13:fa2095be01c4 | 680 | LoRaWan::user_downlink[mote->user_downlink_length++] = d; |
| dudmuck | 12:9a8c13c4298b | 681 | |
| dudmuck | 13:fa2095be01c4 | 682 | printf("period:%u duty:%u to mote %" PRIx32 "\r\n", p, d, mote->dev_addr); |
| dudmuck | 13:fa2095be01c4 | 683 | } |
| dudmuck | 13:fa2095be01c4 | 684 | |
| dudmuck | 13:fa2095be01c4 | 685 | void cmd_beacon_pwm(uint8_t idx) |
| dudmuck | 13:fa2095be01c4 | 686 | { |
| dudmuck | 13:fa2095be01c4 | 687 | unsigned p, d; |
| dudmuck | 13:fa2095be01c4 | 688 | if (sscanf(pcbuf+idx, "%u %u", &p, &d) != 2) { |
| dudmuck | 13:fa2095be01c4 | 689 | printf("parse fail\r\n"); |
| dudmuck | 13:fa2095be01c4 | 690 | return; |
| dudmuck | 13:fa2095be01c4 | 691 | } |
| dudmuck | 13:fa2095be01c4 | 692 | |
| dudmuck | 13:fa2095be01c4 | 693 | beacon_payload[0] = CMD_PWM; |
| dudmuck | 13:fa2095be01c4 | 694 | beacon_payload[1] = p; |
| dudmuck | 13:fa2095be01c4 | 695 | beacon_payload[2] = d; |
| dudmuck | 13:fa2095be01c4 | 696 | |
| dudmuck | 13:fa2095be01c4 | 697 | printf("period:%u duty:%u\r\n", p, d); |
| dudmuck | 12:9a8c13c4298b | 698 | } |
| dudmuck | 12:9a8c13c4298b | 699 | |
| dudmuck | 14:c6284654d1b0 | 700 | void cmd_endnode_txp(uint8_t idx) |
| dudmuck | 14:c6284654d1b0 | 701 | { |
| dudmuck | 14:c6284654d1b0 | 702 | ota_mote_t* mote; |
| dudmuck | 14:c6284654d1b0 | 703 | int i; |
| dudmuck | 14:c6284654d1b0 | 704 | unsigned dev_addr, txi; |
| dudmuck | 14:c6284654d1b0 | 705 | |
| dudmuck | 14:c6284654d1b0 | 706 | if (sscanf(pcbuf+idx, "%x %u", &dev_addr, &txi) != 2) { |
| dudmuck | 14:c6284654d1b0 | 707 | printf("parse fail\r\n"); |
| dudmuck | 14:c6284654d1b0 | 708 | return; |
| dudmuck | 14:c6284654d1b0 | 709 | } |
| dudmuck | 14:c6284654d1b0 | 710 | for (i = 0; i < N_MOTES; i++) { |
| dudmuck | 14:c6284654d1b0 | 711 | if (motes[i].dev_addr == dev_addr) { |
| dudmuck | 14:c6284654d1b0 | 712 | break; |
| dudmuck | 14:c6284654d1b0 | 713 | } |
| dudmuck | 14:c6284654d1b0 | 714 | } |
| dudmuck | 14:c6284654d1b0 | 715 | if (i == N_MOTES) { |
| dudmuck | 14:c6284654d1b0 | 716 | printf("mote %x not found\r\n", dev_addr); |
| dudmuck | 14:c6284654d1b0 | 717 | return; |
| dudmuck | 14:c6284654d1b0 | 718 | } |
| dudmuck | 14:c6284654d1b0 | 719 | |
| dudmuck | 14:c6284654d1b0 | 720 | mote = &motes[i]; |
| dudmuck | 14:c6284654d1b0 | 721 | |
| dudmuck | 14:c6284654d1b0 | 722 | mote->user_downlink_length = 0; |
| dudmuck | 14:c6284654d1b0 | 723 | LoRaWan::user_downlink[mote->user_downlink_length++] = CMD_TX_POWER; |
| dudmuck | 14:c6284654d1b0 | 724 | LoRaWan::user_downlink[mote->user_downlink_length++] = txi; |
| dudmuck | 14:c6284654d1b0 | 725 | |
| dudmuck | 14:c6284654d1b0 | 726 | printf("txp index %u to mote %" PRIx32 "\r\n", txi, mote->dev_addr); |
| dudmuck | 14:c6284654d1b0 | 727 | } |
| dudmuck | 14:c6284654d1b0 | 728 | |
| dudmuck | 14:c6284654d1b0 | 729 | void cmd_beacon_endnode_txp(uint8_t idx) |
| dudmuck | 14:c6284654d1b0 | 730 | { |
| dudmuck | 14:c6284654d1b0 | 731 | unsigned txi; |
| dudmuck | 14:c6284654d1b0 | 732 | if (sscanf(pcbuf+idx, "%u", &txi) != 1) { |
| dudmuck | 14:c6284654d1b0 | 733 | printf("parse fail\r\n"); |
| dudmuck | 14:c6284654d1b0 | 734 | return; |
| dudmuck | 14:c6284654d1b0 | 735 | } |
| dudmuck | 14:c6284654d1b0 | 736 | |
| dudmuck | 14:c6284654d1b0 | 737 | beacon_payload[0] = CMD_TX_POWER; |
| dudmuck | 14:c6284654d1b0 | 738 | beacon_payload[1] = txi; |
| dudmuck | 14:c6284654d1b0 | 739 | |
| dudmuck | 14:c6284654d1b0 | 740 | printf("txp index:%u\r\n", txi); |
| dudmuck | 14:c6284654d1b0 | 741 | } |
| dudmuck | 14:c6284654d1b0 | 742 | |
| dudmuck | 0:2ff18de8d48b | 743 | void cmd_help(uint8_t); |
| dudmuck | 0:2ff18de8d48b | 744 | |
| dudmuck | 0:2ff18de8d48b | 745 | typedef struct { |
| dudmuck | 0:2ff18de8d48b | 746 | const char* const cmd; |
| dudmuck | 0:2ff18de8d48b | 747 | void (*handler)(uint8_t args_at); |
| dudmuck | 0:2ff18de8d48b | 748 | const char* const arg_descr; |
| dudmuck | 0:2ff18de8d48b | 749 | const char* const description; |
| dudmuck | 0:2ff18de8d48b | 750 | } menu_item_t; |
| dudmuck | 0:2ff18de8d48b | 751 | |
| dudmuck | 0:2ff18de8d48b | 752 | const menu_item_t menu_items[] = |
| dudmuck | 0:2ff18de8d48b | 753 | { /* after first character, command names must be [A-Za-z] */ |
| dudmuck | 0:2ff18de8d48b | 754 | { "?", cmd_help, "","show available commands"}, |
| dudmuck | 0:2ff18de8d48b | 755 | { ".", cmd_status, "","read status"}, |
| dudmuck | 0:2ff18de8d48b | 756 | { "b", cmd_beacon_payload, "<%x>","set beacon payload"}, |
| dudmuck | 0:2ff18de8d48b | 757 | { "sb", cmd_skip_beacon, "<%d>","skip beacons"}, |
| dudmuck | 0:2ff18de8d48b | 758 | { "list", cmd_list_motes, "","list active motes"}, |
| dudmuck | 0:2ff18de8d48b | 759 | { "dl", cmd_send_downlink, "[%x %s]","send downlink <mote-hex-dev-addr> <hex-payload>"}, |
| dudmuck | 9:a0ce66c18ec0 | 760 | { "rxr", cmd_rx_restart, "", "restart RX"}, |
| dudmuck | 9:a0ce66c18ec0 | 761 | { "brgb", cmd_beacon_rgb, "%u %u %u", "load RGB command into next beacon" }, |
| dudmuck | 9:a0ce66c18ec0 | 762 | { "rgb", cmd_downlink_rgb, "%x %u %u %u", "load RGB command to mote"}, |
| dudmuck | 9:a0ce66c18ec0 | 763 | { "bgpo", cmd_beacon_gpo, "%d", "load output pin command into next beacon"}, |
| dudmuck | 9:a0ce66c18ec0 | 764 | { "gpo", cmd_downlink_gpo, "%x %d", "load output pin command to mote"}, |
| dudmuck | 12:9a8c13c4298b | 765 | { "op", cmd_op, "<dBm>","(TX) get/set TX power"}, |
| dudmuck | 14:c6284654d1b0 | 766 | #ifdef TYPE_ABZ |
| dudmuck | 14:c6284654d1b0 | 767 | { "pas", cmd_pa_select, "","(TX) toggle PaSelect"}, |
| dudmuck | 14:c6284654d1b0 | 768 | #endif |
| dudmuck | 13:fa2095be01c4 | 769 | { "tz", cmd_set_time, "", "set seconds to zero"}, |
| dudmuck | 13:fa2095be01c4 | 770 | { "p", cmd_pwm, "%x %u %u", "send pwm period, duty to dev_addr"}, |
| dudmuck | 13:fa2095be01c4 | 771 | { "bp", cmd_beacon_pwm, "%u %u", "send pwm period, duty on beacon"}, |
| dudmuck | 14:c6284654d1b0 | 772 | { "ntxp", cmd_endnode_txp, "%x %u", "send txpower index to dev_addr"}, |
| dudmuck | 14:c6284654d1b0 | 773 | { "bntxp", cmd_beacon_endnode_txp, "%u", "send txpower index on beacon"}, |
| dudmuck | 0:2ff18de8d48b | 774 | { NULL, NULL, NULL, NULL } |
| dudmuck | 0:2ff18de8d48b | 775 | }; |
| dudmuck | 0:2ff18de8d48b | 776 | |
| dudmuck | 0:2ff18de8d48b | 777 | void cmd_help(uint8_t args_at) |
| dudmuck | 0:2ff18de8d48b | 778 | { |
| dudmuck | 0:2ff18de8d48b | 779 | int i; |
| dudmuck | 0:2ff18de8d48b | 780 | |
| dudmuck | 0:2ff18de8d48b | 781 | for (i = 0; menu_items[i].cmd != NULL ; i++) { |
| dudmuck | 0:2ff18de8d48b | 782 | printf("%s%s\t%s\r\n", menu_items[i].cmd, menu_items[i].arg_descr, menu_items[i].description); |
| dudmuck | 0:2ff18de8d48b | 783 | } |
| dudmuck | 0:2ff18de8d48b | 784 | |
| dudmuck | 0:2ff18de8d48b | 785 | } |
| dudmuck | 0:2ff18de8d48b | 786 | |
| dudmuck | 0:2ff18de8d48b | 787 | void |
| dudmuck | 0:2ff18de8d48b | 788 | console() |
| dudmuck | 0:2ff18de8d48b | 789 | { |
| dudmuck | 0:2ff18de8d48b | 790 | int i; |
| dudmuck | 0:2ff18de8d48b | 791 | uint8_t user_cmd_len; |
| dudmuck | 0:2ff18de8d48b | 792 | |
| dudmuck | 0:2ff18de8d48b | 793 | if (pcbuf_len < 0) { // ctrl-C |
| dudmuck | 0:2ff18de8d48b | 794 | //printf("abort\r\n"); |
| dudmuck | 0:2ff18de8d48b | 795 | return; |
| dudmuck | 0:2ff18de8d48b | 796 | } |
| dudmuck | 0:2ff18de8d48b | 797 | if (pcbuf_len == 0) |
| dudmuck | 0:2ff18de8d48b | 798 | return; |
| dudmuck | 0:2ff18de8d48b | 799 | |
| dudmuck | 0:2ff18de8d48b | 800 | printf("\r\n"); |
| dudmuck | 0:2ff18de8d48b | 801 | |
| dudmuck | 0:2ff18de8d48b | 802 | /* get end of user-entered command */ |
| dudmuck | 0:2ff18de8d48b | 803 | user_cmd_len = 1; // first character can be any character |
| dudmuck | 0:2ff18de8d48b | 804 | for (i = 1; i <= pcbuf_len; i++) { |
| dudmuck | 0:2ff18de8d48b | 805 | if (pcbuf[i] < 'A' || (pcbuf[i] > 'Z' && pcbuf[i] < 'a') || pcbuf[i] > 'z') { |
| dudmuck | 0:2ff18de8d48b | 806 | user_cmd_len = i; |
| dudmuck | 0:2ff18de8d48b | 807 | break; |
| dudmuck | 0:2ff18de8d48b | 808 | } |
| dudmuck | 0:2ff18de8d48b | 809 | } |
| dudmuck | 0:2ff18de8d48b | 810 | |
| dudmuck | 0:2ff18de8d48b | 811 | for (i = 0; menu_items[i].cmd != NULL ; i++) { |
| dudmuck | 0:2ff18de8d48b | 812 | int mi_len = strlen(menu_items[i].cmd); |
| dudmuck | 0:2ff18de8d48b | 813 | |
| dudmuck | 0:2ff18de8d48b | 814 | if (menu_items[i].handler && user_cmd_len == mi_len && (strncmp(pcbuf, menu_items[i].cmd, mi_len) == 0)) { |
| dudmuck | 0:2ff18de8d48b | 815 | while (pcbuf[mi_len] == ' ') // skip past spaces |
| dudmuck | 0:2ff18de8d48b | 816 | mi_len++; |
| dudmuck | 0:2ff18de8d48b | 817 | menu_items[i].handler(mi_len); |
| dudmuck | 0:2ff18de8d48b | 818 | break; |
| dudmuck | 0:2ff18de8d48b | 819 | } |
| dudmuck | 0:2ff18de8d48b | 820 | } |
| dudmuck | 0:2ff18de8d48b | 821 | |
| dudmuck | 0:2ff18de8d48b | 822 | pcbuf_len = 0; |
| dudmuck | 0:2ff18de8d48b | 823 | printf("> "); |
| dudmuck | 0:2ff18de8d48b | 824 | fflush(stdout); |
| dudmuck | 0:2ff18de8d48b | 825 | } |
| dudmuck | 0:2ff18de8d48b | 826 | |
| dudmuck | 0:2ff18de8d48b | 827 | int main() |
| dudmuck | 0:2ff18de8d48b | 828 | { |
| dudmuck | 0:2ff18de8d48b | 829 | Thread eventThread; |
| dudmuck | 3:7c01b8978638 | 830 | pc.baud(38400); |
| dudmuck | 12:9a8c13c4298b | 831 | printf("\r\nreset %f\r\n", radio.get_frf_MHz()); |
| dudmuck | 11:50d0558a4e37 | 832 | set_time(0); |
| dudmuck | 0:2ff18de8d48b | 833 | |
| dudmuck | 0:2ff18de8d48b | 834 | radio.hw_reset(); |
| dudmuck | 12:9a8c13c4298b | 835 | printf("%fMHz\r\n", radio.get_frf_MHz()); |
| dudmuck | 0:2ff18de8d48b | 836 | |
| dudmuck | 10:6783623cc886 | 837 | //#ifndef TARGET_DISCO_L072CZ_LRWAN1 |
| dudmuck | 10:6783623cc886 | 838 | #ifndef TYPE_ABZ |
| dudmuck | 0:2ff18de8d48b | 839 | rfsw.input(); |
| dudmuck | 0:2ff18de8d48b | 840 | if (rfsw.read()) { |
| dudmuck | 0:2ff18de8d48b | 841 | printf("LAS\r\n"); |
| dudmuck | 0:2ff18de8d48b | 842 | /* LAS HF=PA_BOOST LF=RFO */ |
| dudmuck | 0:2ff18de8d48b | 843 | radio.RegPaConfig.bits.PaSelect = 1; |
| dudmuck | 0:2ff18de8d48b | 844 | } else { |
| dudmuck | 0:2ff18de8d48b | 845 | printf("MAS\r\n"); |
| dudmuck | 0:2ff18de8d48b | 846 | radio.RegPaConfig.bits.PaSelect = 0; |
| dudmuck | 0:2ff18de8d48b | 847 | } |
| dudmuck | 0:2ff18de8d48b | 848 | rfsw.output(); |
| dudmuck | 5:ceacaa560cfd | 849 | #endif /* !TARGET_DISCO_L072CZ_LRWAN1 */ |
| dudmuck | 0:2ff18de8d48b | 850 | |
| dudmuck | 0:2ff18de8d48b | 851 | radio.rf_switch = rfsw_callback; |
| dudmuck | 0:2ff18de8d48b | 852 | |
| dudmuck | 0:2ff18de8d48b | 853 | init_radio(); |
| dudmuck | 0:2ff18de8d48b | 854 | |
| dudmuck | 0:2ff18de8d48b | 855 | lora.start_rx(RF_OPMODE_RECEIVER); |
| dudmuck | 0:2ff18de8d48b | 856 | |
| dudmuck | 0:2ff18de8d48b | 857 | eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); |
| dudmuck | 0:2ff18de8d48b | 858 | LoRaWan::init(); |
| dudmuck | 0:2ff18de8d48b | 859 | |
| dudmuck | 0:2ff18de8d48b | 860 | timer.start(); |
| dudmuck | 0:2ff18de8d48b | 861 | tim_init(); |
| dudmuck | 4:7e743e402681 | 862 | |
| dudmuck | 4:7e743e402681 | 863 | pc.attach(&rx_isr); |
| dudmuck | 9:a0ce66c18ec0 | 864 | |
| dudmuck | 0:2ff18de8d48b | 865 | |
| dudmuck | 0:2ff18de8d48b | 866 | for (;;) { |
| dudmuck | 0:2ff18de8d48b | 867 | console(); |
| dudmuck | 1:107435401168 | 868 | |
| dudmuck | 1:107435401168 | 869 | if (radio.dio0) { |
| dudmuck | 3:7c01b8978638 | 870 | if (get_tx_done) { |
| dudmuck | 3:7c01b8978638 | 871 | get_tx_done = false; |
| dudmuck | 3:7c01b8978638 | 872 | lora.RegIrqFlags.octet = 0; |
| dudmuck | 3:7c01b8978638 | 873 | lora.RegIrqFlags.bits.TxDone = 1; |
| dudmuck | 3:7c01b8978638 | 874 | radio.write_reg(REG_LR_IRQFLAGS, lora.RegIrqFlags.octet); |
| dudmuck | 3:7c01b8978638 | 875 | |
| dudmuck | 3:7c01b8978638 | 876 | if (restore_tx_invert) { |
| dudmuck | 3:7c01b8978638 | 877 | lora.invert_tx(false); |
| dudmuck | 3:7c01b8978638 | 878 | restore_tx_invert = false; |
| dudmuck | 3:7c01b8978638 | 879 | } |
| dudmuck | 3:7c01b8978638 | 880 | |
| dudmuck | 3:7c01b8978638 | 881 | if (restore_header_mode) { |
| dudmuck | 3:7c01b8978638 | 882 | lora.setHeaderMode(false); |
| dudmuck | 3:7c01b8978638 | 883 | restore_header_mode = false; |
| dudmuck | 3:7c01b8978638 | 884 | } |
| dudmuck | 12:9a8c13c4298b | 885 | |
| dudmuck | 3:7c01b8978638 | 886 | lora.start_rx(RF_OPMODE_RECEIVER); |
| dudmuck | 12:9a8c13c4298b | 887 | |
| dudmuck | 12:9a8c13c4298b | 888 | if (beacon_guard) { // beacon done transmitting |
| dudmuck | 12:9a8c13c4298b | 889 | measure_ambient(); |
| dudmuck | 12:9a8c13c4298b | 890 | beacon_guard = false; |
| dudmuck | 12:9a8c13c4298b | 891 | } |
| dudmuck | 3:7c01b8978638 | 892 | } else { |
| dudmuck | 3:7c01b8978638 | 893 | if (!beacon_guard) |
| dudmuck | 3:7c01b8978638 | 894 | service_radio(); |
| dudmuck | 3:7c01b8978638 | 895 | } |
| dudmuck | 12:9a8c13c4298b | 896 | } else if (get_tx_done) { |
| dudmuck | 12:9a8c13c4298b | 897 | /* dio0 not yet asserted */ |
| dudmuck | 12:9a8c13c4298b | 898 | uint32_t since = timer.read_ms() - tx_ms; |
| dudmuck | 12:9a8c13c4298b | 899 | if (since > 4000) { |
| dudmuck | 12:9a8c13c4298b | 900 | radio.RegOpMode.octet = radio.read_reg(REG_OPMODE); |
| dudmuck | 12:9a8c13c4298b | 901 | if (radio.RegOpMode.bits.Mode == RF_OPMODE_STANDBY) { |
| dudmuck | 12:9a8c13c4298b | 902 | /* done transmitting, but dio0 not asserted */ |
| dudmuck | 12:9a8c13c4298b | 903 | printf("txDone but no dio0\r\n"); |
| dudmuck | 12:9a8c13c4298b | 904 | radio.RegDioMapping1.octet = radio.read_reg(REG_DIOMAPPING1); |
| dudmuck | 12:9a8c13c4298b | 905 | if (radio.RegDioMapping1.bits.Dio0Mapping != 1) { |
| dudmuck | 12:9a8c13c4298b | 906 | printf("dio0mapping-fail\r\n"); |
| dudmuck | 12:9a8c13c4298b | 907 | radio.RegDioMapping1.bits.Dio0Mapping = 1; |
| dudmuck | 12:9a8c13c4298b | 908 | radio.write_reg(REG_DIOMAPPING1, radio.RegDioMapping1.octet); |
| dudmuck | 12:9a8c13c4298b | 909 | } |
| dudmuck | 12:9a8c13c4298b | 910 | } |
| dudmuck | 12:9a8c13c4298b | 911 | } |
| dudmuck | 12:9a8c13c4298b | 912 | } |
| dudmuck | 12:9a8c13c4298b | 913 | |
| dudmuck | 12:9a8c13c4298b | 914 | if (LoRaWan::do_downlink && !beacon_guard) { |
| dudmuck | 12:9a8c13c4298b | 915 | uint32_t since = timer.read_ms() - LoRaWan::rx_ms; |
| dudmuck | 12:9a8c13c4298b | 916 | if (since > 110) |
| dudmuck | 13:fa2095be01c4 | 917 | printf("since-tx:%lu\r\n", since); |
| dudmuck | 12:9a8c13c4298b | 918 | if (since > 500) { |
| dudmuck | 12:9a8c13c4298b | 919 | LoRaWan::do_downlink = false; |
| dudmuck | 12:9a8c13c4298b | 920 | printf("stalled-tx\r\n"); |
| dudmuck | 12:9a8c13c4298b | 921 | cmd_rx_restart(0); |
| dudmuck | 12:9a8c13c4298b | 922 | } |
| dudmuck | 1:107435401168 | 923 | } |
| dudmuck | 8:307f7faeb594 | 924 | |
| dudmuck | 0:2ff18de8d48b | 925 | } // ..for(;;) |
| dudmuck | 0:2ff18de8d48b | 926 | } |