operate LoRa radio over I2C
Dependencies: TimeoutAbs lib_i2c_slave_block sx12xx_hal
radio chip selection
Radio chip driver is not included, allowing choice of radio device.
If you're using SX1272 or SX1276, then import sx127x driver into your program.
if you're using SX1261 or SX1262, then import sx126x driver into your program.
if you're using SX1280, then import sx1280 driver into your program.
If you're using NAmote72 or Murata discovery, then you must import only sx127x driver.
This project is used as slave device with i2c_lora_master on raspberry pi. This i2c_lora_slave offloads the real-time requirements onto microcontroller. Also permits multiple slave radio devices connected to master. Radio MAC layer exists on I2C master, along with application layer.
If beacon operation is enabled, I2C functions which access radio chip are blocked while beacon is loaded and transmitted.
See lib_i2c_slave_block for wiring connections.
main.cpp@0:9eb5b8bf9f7b, 2019-02-08 (annotated)
- Committer:
- Wayne Roberts
- Date:
- Fri Feb 08 11:58:09 2019 -0800
- Revision:
- 0:9eb5b8bf9f7b
first commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wayne Roberts |
0:9eb5b8bf9f7b | 1 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 2 | #include <mbed.h> |
Wayne Roberts |
0:9eb5b8bf9f7b | 3 | #include "LowPowerTimeoutAbs.h" |
Wayne Roberts |
0:9eb5b8bf9f7b | 4 | #include "radio_device.h" |
Wayne Roberts |
0:9eb5b8bf9f7b | 5 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 6 | #define IRQ_OUT_PIN D6 |
Wayne Roberts |
0:9eb5b8bf9f7b | 7 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 8 | #define BEACON_PRELOAD_us 500000 |
Wayne Roberts |
0:9eb5b8bf9f7b | 9 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 10 | typedef struct { |
Wayne Roberts |
0:9eb5b8bf9f7b | 11 | uint8_t beacon_enabled : 1; // 0 |
Wayne Roberts |
0:9eb5b8bf9f7b | 12 | uint8_t beacon_guard : 1; // 1 |
Wayne Roberts |
0:9eb5b8bf9f7b | 13 | uint8_t beacon_loaded : 1; // 2 |
Wayne Roberts |
0:9eb5b8bf9f7b | 14 | uint8_t beacon_test : 1; // 3 |
Wayne Roberts |
0:9eb5b8bf9f7b | 15 | uint8_t req_type : 4; // 4,5,6,7 |
Wayne Roberts |
0:9eb5b8bf9f7b | 16 | } flags_t; |
Wayne Roberts |
0:9eb5b8bf9f7b | 17 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 18 | const int SLAVE_ADDRESS = 0xA0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 19 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 20 | RawSerial pc(USBTX, USBRX); |
Wayne Roberts |
0:9eb5b8bf9f7b | 21 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 22 | EventQueue queue; |
Wayne Roberts |
0:9eb5b8bf9f7b | 23 | uint8_t skip_beacon_cnt = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 24 | uint16_t beaconPreambleSymbs; |
Wayne Roberts |
0:9eb5b8bf9f7b | 25 | uint16_t preambleSymbs; |
Wayne Roberts |
0:9eb5b8bf9f7b | 26 | unsigned beaconInterval_us; |
Wayne Roberts |
0:9eb5b8bf9f7b | 27 | uint8_t beaconSizeBytes; |
Wayne Roberts |
0:9eb5b8bf9f7b | 28 | /* low power timer used because hi-speed timer doesnt have crystal, and 32Khz crystal is 20ppm */ |
Wayne Roberts |
0:9eb5b8bf9f7b | 29 | LowPowerTimeoutAbs send_beaconTimer; |
Wayne Roberts |
0:9eb5b8bf9f7b | 30 | LowPowerTimeoutAbs load_beaconTimer; |
Wayne Roberts |
0:9eb5b8bf9f7b | 31 | uint8_t beacon_payload[4]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 32 | cfg_t cfg; |
Wayne Roberts |
0:9eb5b8bf9f7b | 33 | uint8_t get_n_rssi; |
Wayne Roberts |
0:9eb5b8bf9f7b | 34 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 35 | volatile flags_t flags; |
Wayne Roberts |
0:9eb5b8bf9f7b | 36 | volatile uint8_t bs; |
Wayne Roberts |
0:9eb5b8bf9f7b | 37 | volatile uint16_t rx_slot; |
Wayne Roberts |
0:9eb5b8bf9f7b | 38 | volatile us_timestamp_t beaconAt; |
Wayne Roberts |
0:9eb5b8bf9f7b | 39 | volatile uint8_t blocked_cmd; |
Wayne Roberts |
0:9eb5b8bf9f7b | 40 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 41 | DigitalOut irqOutPin(IRQ_OUT_PIN); |
Wayne Roberts |
0:9eb5b8bf9f7b | 42 | irq_t irq; |
Wayne Roberts |
0:9eb5b8bf9f7b | 43 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 44 | uint8_t toI2C_rx_pkt[256]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 45 | volatile uint16_t toI2C_rx_pkt_idx; // incremented by 32: will overflow 8bit |
Wayne Roberts |
0:9eb5b8bf9f7b | 46 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 47 | int tx_pkt_len; |
Wayne Roberts |
0:9eb5b8bf9f7b | 48 | uint8_t tx_pkt_idx; |
Wayne Roberts |
0:9eb5b8bf9f7b | 49 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 50 | void console() |
Wayne Roberts |
0:9eb5b8bf9f7b | 51 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 52 | char c; |
Wayne Roberts |
0:9eb5b8bf9f7b | 53 | if (pc.readable() != 1) |
Wayne Roberts |
0:9eb5b8bf9f7b | 54 | return; |
Wayne Roberts |
0:9eb5b8bf9f7b | 55 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 56 | c = pc.getc(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 57 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 58 | if (c == '.') { |
Wayne Roberts |
0:9eb5b8bf9f7b | 59 | pc.printf("beacon_guard%u ", flags.beacon_guard); |
Wayne Roberts |
0:9eb5b8bf9f7b | 60 | pc.printf("beacon_loaded%u ", flags.beacon_loaded); |
Wayne Roberts |
0:9eb5b8bf9f7b | 61 | pc.printf("bs:%u\r\n", bs); |
Wayne Roberts |
0:9eb5b8bf9f7b | 62 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 63 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 64 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 65 | void |
Wayne Roberts |
0:9eb5b8bf9f7b | 66 | send_beacon() |
Wayne Roberts |
0:9eb5b8bf9f7b | 67 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 68 | bs = 3; |
Wayne Roberts |
0:9eb5b8bf9f7b | 69 | if (!flags.beacon_loaded) |
Wayne Roberts |
0:9eb5b8bf9f7b | 70 | return; |
Wayne Roberts |
0:9eb5b8bf9f7b | 71 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 72 | bs = 4; |
Wayne Roberts |
0:9eb5b8bf9f7b | 73 | Radio::Send(beaconSizeBytes, 0, 0, 0); |
Wayne Roberts |
0:9eb5b8bf9f7b | 74 | flags.beacon_loaded = false; |
Wayne Roberts |
0:9eb5b8bf9f7b | 75 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 76 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 77 | static uint16_t beacon_crc( uint8_t *buffer, uint16_t length ) |
Wayne Roberts |
0:9eb5b8bf9f7b | 78 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 79 | // The CRC calculation follows CCITT |
Wayne Roberts |
0:9eb5b8bf9f7b | 80 | const uint16_t polynom = 0x1021; |
Wayne Roberts |
0:9eb5b8bf9f7b | 81 | // CRC initial value |
Wayne Roberts |
0:9eb5b8bf9f7b | 82 | uint16_t crc = 0x0000; |
Wayne Roberts |
0:9eb5b8bf9f7b | 83 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 84 | if( buffer == NULL ) |
Wayne Roberts |
0:9eb5b8bf9f7b | 85 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 86 | return 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 87 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 88 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 89 | for( uint16_t i = 0; i < length; ++i ) |
Wayne Roberts |
0:9eb5b8bf9f7b | 90 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 91 | crc ^= ( uint16_t ) buffer[i] << 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 92 | for( uint16_t j = 0; j < 8; ++j ) |
Wayne Roberts |
0:9eb5b8bf9f7b | 93 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 94 | crc = ( crc & 0x8000 ) ? ( crc << 1 ) ^ polynom : ( crc << 1 ); |
Wayne Roberts |
0:9eb5b8bf9f7b | 95 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 96 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 97 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 98 | return crc; |
Wayne Roberts |
0:9eb5b8bf9f7b | 99 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 100 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 101 | void |
Wayne Roberts |
0:9eb5b8bf9f7b | 102 | _load_beacon() |
Wayne Roberts |
0:9eb5b8bf9f7b | 103 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 104 | bool inv_iq = false; |
Wayne Roberts |
0:9eb5b8bf9f7b | 105 | uint16_t crc; |
Wayne Roberts |
0:9eb5b8bf9f7b | 106 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 107 | bs = 2; |
Wayne Roberts |
0:9eb5b8bf9f7b | 108 | Radio::Standby( ); |
Wayne Roberts |
0:9eb5b8bf9f7b | 109 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 110 | if (skip_beacon_cnt > 0) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 111 | inv_iq = true; |
Wayne Roberts |
0:9eb5b8bf9f7b | 112 | skip_beacon_cnt--; |
Wayne Roberts |
0:9eb5b8bf9f7b | 113 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 114 | // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
0:9eb5b8bf9f7b | 115 | Radio::LoRaPacketConfig(beaconPreambleSymbs, true, false, inv_iq); |
Wayne Roberts |
0:9eb5b8bf9f7b | 116 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 117 | Radio::SetFixedPayloadLength(beaconSizeBytes); |
Wayne Roberts |
0:9eb5b8bf9f7b | 118 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 119 | Radio::radio.tx_buf[0] = beacon_payload[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 120 | Radio::radio.tx_buf[1] = beacon_payload[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 121 | Radio::radio.tx_buf[2] = beacon_payload[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 122 | Radio::radio.tx_buf[3] = beacon_payload[3]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 123 | //beacon_payload[0] = CMD_NONE; |
Wayne Roberts |
0:9eb5b8bf9f7b | 124 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 125 | crc = beacon_crc(Radio::radio.tx_buf, 4); |
Wayne Roberts |
0:9eb5b8bf9f7b | 126 | Radio::radio.tx_buf[4] = crc & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 127 | Radio::radio.tx_buf[5] = crc >> 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 128 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 129 | flags.beacon_loaded = true; |
Wayne Roberts |
0:9eb5b8bf9f7b | 130 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 131 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 132 | uint16_t tim_get_current_slot() |
Wayne Roberts |
0:9eb5b8bf9f7b | 133 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 134 | us_timestamp_t us_until = beaconAt - send_beaconTimer.read_us(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 135 | return us_until / 30000; |
Wayne Roberts |
0:9eb5b8bf9f7b | 136 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 137 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 138 | void load_beacon() |
Wayne Roberts |
0:9eb5b8bf9f7b | 139 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 140 | if (flags.beacon_enabled) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 141 | flags.beacon_guard = true; |
Wayne Roberts |
0:9eb5b8bf9f7b | 142 | bs = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 143 | queue.call_in(200, _load_beacon); |
Wayne Roberts |
0:9eb5b8bf9f7b | 144 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 145 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 146 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 147 | void get_random() |
Wayne Roberts |
0:9eb5b8bf9f7b | 148 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 149 | uint32_t r; |
Wayne Roberts |
0:9eb5b8bf9f7b | 150 | Radio::Rx(0); |
Wayne Roberts |
0:9eb5b8bf9f7b | 151 | wait(0.01); |
Wayne Roberts |
0:9eb5b8bf9f7b | 152 | r = Radio::Random(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 153 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 154 | irq.buf[1] = r & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 155 | r >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 156 | irq.buf[2] = r & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 157 | r >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 158 | irq.buf[3] = r & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 159 | r >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 160 | irq.buf[4] = r & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 161 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 162 | irq.fields.flags.irq_type = IRQ_TYPE_RANDOM; |
Wayne Roberts |
0:9eb5b8bf9f7b | 163 | irqOutPin = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 164 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 165 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 166 | void cf_read() |
Wayne Roberts |
0:9eb5b8bf9f7b | 167 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 168 | uint32_t hz; |
Wayne Roberts |
0:9eb5b8bf9f7b | 169 | float MHz; |
Wayne Roberts |
0:9eb5b8bf9f7b | 170 | #ifdef SX127x_H |
Wayne Roberts |
0:9eb5b8bf9f7b | 171 | MHz = Radio::radio.get_frf_MHz(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 172 | #else |
Wayne Roberts |
0:9eb5b8bf9f7b | 173 | MHz = Radio::radio.getMHz(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 174 | #endif |
Wayne Roberts |
0:9eb5b8bf9f7b | 175 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 176 | hz = MHz * 1000000; |
Wayne Roberts |
0:9eb5b8bf9f7b | 177 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 178 | irq.buf[1] = hz & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 179 | hz >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 180 | irq.buf[2] = hz & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 181 | hz >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 182 | irq.buf[3] = hz & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 183 | hz >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 184 | irq.buf[4] = hz & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 185 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 186 | irq.fields.flags.irq_type = IRQ_TYPE_CF; |
Wayne Roberts |
0:9eb5b8bf9f7b | 187 | irqOutPin = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 188 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 189 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 190 | void measure_ambient(uint8_t n_samples) |
Wayne Roberts |
0:9eb5b8bf9f7b | 191 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 192 | int i, acc = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 193 | float bg_rssi; |
Wayne Roberts |
0:9eb5b8bf9f7b | 194 | for (i = 0; i < n_samples; i++) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 195 | int rssi = Radio::GetRssiInst(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 196 | acc += rssi; |
Wayne Roberts |
0:9eb5b8bf9f7b | 197 | wait(0.01); |
Wayne Roberts |
0:9eb5b8bf9f7b | 198 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 199 | bg_rssi = acc / (float)n_samples; |
Wayne Roberts |
0:9eb5b8bf9f7b | 200 | pc.printf("bg_rssi:%.1fdBm ", bg_rssi); |
Wayne Roberts |
0:9eb5b8bf9f7b | 201 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 202 | irq.fields.rssi = bg_rssi * 10; |
Wayne Roberts |
0:9eb5b8bf9f7b | 203 | irq.fields.flags.irq_type = IRQ_TYPE_RSSI; |
Wayne Roberts |
0:9eb5b8bf9f7b | 204 | irqOutPin = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 205 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 206 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 207 | void txDoneCB() |
Wayne Roberts |
0:9eb5b8bf9f7b | 208 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 209 | if (flags.beacon_test) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 210 | flags.beacon_test = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 211 | return; |
Wayne Roberts |
0:9eb5b8bf9f7b | 212 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 213 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 214 | if (cfg.fields.flags.rxOnTxDone) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 215 | // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
0:9eb5b8bf9f7b | 216 | Radio::LoRaPacketConfig(preambleSymbs, false, true, false); |
Wayne Roberts |
0:9eb5b8bf9f7b | 217 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 218 | Radio::Rx(0); |
Wayne Roberts |
0:9eb5b8bf9f7b | 219 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 220 | bs = 5; |
Wayne Roberts |
0:9eb5b8bf9f7b | 221 | if (flags.beacon_guard) { // beacon done transmitting |
Wayne Roberts |
0:9eb5b8bf9f7b | 222 | measure_ambient(cfg.fields.n_rssi_samples); |
Wayne Roberts |
0:9eb5b8bf9f7b | 223 | flags.beacon_guard = false; |
Wayne Roberts |
0:9eb5b8bf9f7b | 224 | bs = 6; |
Wayne Roberts |
0:9eb5b8bf9f7b | 225 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 226 | beaconAt += beaconInterval_us; |
Wayne Roberts |
0:9eb5b8bf9f7b | 227 | load_beaconTimer.attach_us(load_beacon, beaconAt - BEACON_PRELOAD_us); |
Wayne Roberts |
0:9eb5b8bf9f7b | 228 | send_beaconTimer.attach_us(send_beacon, beaconAt); |
Wayne Roberts |
0:9eb5b8bf9f7b | 229 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 230 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 231 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 232 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 233 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 234 | void send_downlink() |
Wayne Roberts |
0:9eb5b8bf9f7b | 235 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 236 | if (tx_pkt_len > 0 && tx_pkt_idx >= tx_pkt_len) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 237 | Radio::Send(tx_pkt_len, |
Wayne Roberts |
0:9eb5b8bf9f7b | 238 | cfg.fields.maxListenTime, |
Wayne Roberts |
0:9eb5b8bf9f7b | 239 | cfg.fields.channelFreeTime, |
Wayne Roberts |
0:9eb5b8bf9f7b | 240 | cfg.fields.rssiThresh |
Wayne Roberts |
0:9eb5b8bf9f7b | 241 | ); |
Wayne Roberts |
0:9eb5b8bf9f7b | 242 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 243 | tx_pkt_len = 0; // packet only sent once, as requested by host |
Wayne Roberts |
0:9eb5b8bf9f7b | 244 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 245 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 246 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 247 | void rxDoneCB(uint8_t size, float rssi, float snr) |
Wayne Roberts |
0:9eb5b8bf9f7b | 248 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 249 | if (cfg.fields.flags.rxOnTxDone) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 250 | queue.call_in(cfg.fields.downlinkOffset, send_downlink); |
Wayne Roberts |
0:9eb5b8bf9f7b | 251 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 252 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 253 | if (irq.fields.flags.rx_pkt == 0) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 254 | if (flags.beacon_enabled) |
Wayne Roberts |
0:9eb5b8bf9f7b | 255 | irq.fields.rx_slot = tim_get_current_slot(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 256 | else |
Wayne Roberts |
0:9eb5b8bf9f7b | 257 | irq.fields.rx_slot = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 258 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 259 | irq.fields.rssi = rssi * 10; |
Wayne Roberts |
0:9eb5b8bf9f7b | 260 | irq.fields.pkt_snr = snr; |
Wayne Roberts |
0:9eb5b8bf9f7b | 261 | irq.fields.pkt_len = size; |
Wayne Roberts |
0:9eb5b8bf9f7b | 262 | memcpy(toI2C_rx_pkt, Radio::radio.rx_buf, size); |
Wayne Roberts |
0:9eb5b8bf9f7b | 263 | irq.fields.flags.rx_pkt = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 264 | irqOutPin = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 265 | pc.printf("rxlen%u snr:%.1f rssi:%.1f slot:%u\r\n", size, snr, rssi, irq.fields.rx_slot); |
Wayne Roberts |
0:9eb5b8bf9f7b | 266 | } else { |
Wayne Roberts |
0:9eb5b8bf9f7b | 267 | pc.printf("rx_pkt_overrun\r\n"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 268 | irq.fields.flags.rx_pkt_overrun = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 269 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 270 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 271 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 272 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 273 | void tim_init() |
Wayne Roberts |
0:9eb5b8bf9f7b | 274 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 275 | beaconAt = send_beaconTimer.read_us() + beaconInterval_us; |
Wayne Roberts |
0:9eb5b8bf9f7b | 276 | load_beaconTimer.attach_us(load_beacon, beaconAt - BEACON_PRELOAD_us); |
Wayne Roberts |
0:9eb5b8bf9f7b | 277 | send_beaconTimer.attach_us(send_beacon, beaconAt); |
Wayne Roberts |
0:9eb5b8bf9f7b | 278 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 279 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 280 | volatile uint8_t cnt = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 281 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 282 | void fill_tx_buf(uint8_t cmd) // called from isr |
Wayne Roberts |
0:9eb5b8bf9f7b | 283 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 284 | unsigned i; |
Wayne Roberts |
0:9eb5b8bf9f7b | 285 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 286 | /* Master is reading from slave |
Wayne Roberts |
0:9eb5b8bf9f7b | 287 | * Called from ISR; must return immediately */ |
Wayne Roberts |
0:9eb5b8bf9f7b | 288 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 289 | if (flags.beacon_guard && cmd >= CMD_RADIO) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 290 | blocked_cmd = cmd; |
Wayne Roberts |
0:9eb5b8bf9f7b | 291 | return; |
Wayne Roberts |
0:9eb5b8bf9f7b | 292 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 293 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 294 | switch (cmd) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 295 | case CMD_TEST: |
Wayne Roberts |
0:9eb5b8bf9f7b | 296 | for (i = 0; i < cmd_to_length[CMD_TEST]; i++) |
Wayne Roberts |
0:9eb5b8bf9f7b | 297 | i2c.tx_buf[i] = i + cnt; |
Wayne Roberts |
0:9eb5b8bf9f7b | 298 | cnt++; |
Wayne Roberts |
0:9eb5b8bf9f7b | 299 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 300 | case CMD_TEST32: |
Wayne Roberts |
0:9eb5b8bf9f7b | 301 | for (i = 0; i < cmd_to_length[CMD_TEST32]; i++) |
Wayne Roberts |
0:9eb5b8bf9f7b | 302 | i2c.tx_buf[i] = i + cnt; |
Wayne Roberts |
0:9eb5b8bf9f7b | 303 | cnt++; |
Wayne Roberts |
0:9eb5b8bf9f7b | 304 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 305 | case CMD_RX_PAYLOAD: |
Wayne Roberts |
0:9eb5b8bf9f7b | 306 | memcpy(i2c.tx_buf, toI2C_rx_pkt+toI2C_rx_pkt_idx, sizeof(i2c.tx_buf)); |
Wayne Roberts |
0:9eb5b8bf9f7b | 307 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 308 | toI2C_rx_pkt_idx += cmd_to_length[CMD_RX_PAYLOAD]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 309 | if (toI2C_rx_pkt_idx >= irq.fields.pkt_len) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 310 | irq.fields.pkt_len = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 311 | irq.fields.flags.rx_pkt = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 312 | if (irq.buf[0] == 0) |
Wayne Roberts |
0:9eb5b8bf9f7b | 313 | irqOutPin = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 314 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 315 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 316 | case CMD_SKIP_BEACONS: |
Wayne Roberts |
0:9eb5b8bf9f7b | 317 | i2c.tx_buf[0] = skip_beacon_cnt; |
Wayne Roberts |
0:9eb5b8bf9f7b | 318 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 319 | case CMD_CURRENT_SLOT: |
Wayne Roberts |
0:9eb5b8bf9f7b | 320 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 321 | uint16_t *u16ptr = (uint16_t*)i2c.tx_buf; |
Wayne Roberts |
0:9eb5b8bf9f7b | 322 | *u16ptr = tim_get_current_slot(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 323 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 324 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 325 | case CMD_REQ_RANDOM: |
Wayne Roberts |
0:9eb5b8bf9f7b | 326 | flags.req_type = IRQ_TYPE_RANDOM; |
Wayne Roberts |
0:9eb5b8bf9f7b | 327 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 328 | case CMD_IRQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 329 | if (irq.fields.flags.rx_pkt) |
Wayne Roberts |
0:9eb5b8bf9f7b | 330 | toI2C_rx_pkt_idx = 0; // packet reading expected to start |
Wayne Roberts |
0:9eb5b8bf9f7b | 331 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 332 | for (i = 0; i < cmd_to_length[CMD_IRQ]; i++) |
Wayne Roberts |
0:9eb5b8bf9f7b | 333 | i2c.tx_buf[i] = irq.buf[i]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 334 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 335 | irq.fields.flags.rx_pkt_overrun = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 336 | irq.fields.flags.irq_type = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 337 | if (irq.buf[0] == 0) |
Wayne Roberts |
0:9eb5b8bf9f7b | 338 | irqOutPin = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 339 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 340 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 341 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 342 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 343 | } // ..fill_tx_buf() |
Wayne Roberts |
0:9eb5b8bf9f7b | 344 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 345 | void service_i2c_write(uint8_t cmd, uint8_t len, const uint8_t* req) |
Wayne Roberts |
0:9eb5b8bf9f7b | 346 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 347 | uint32_t u32; |
Wayne Roberts |
0:9eb5b8bf9f7b | 348 | uint8_t s8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 349 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 350 | if (flags.beacon_guard && cmd >= CMD_RADIO) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 351 | blocked_cmd = cmd; |
Wayne Roberts |
0:9eb5b8bf9f7b | 352 | return; |
Wayne Roberts |
0:9eb5b8bf9f7b | 353 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 354 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 355 | switch (cmd) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 356 | case CMD_TEST: |
Wayne Roberts |
0:9eb5b8bf9f7b | 357 | case CMD_TEST32: |
Wayne Roberts |
0:9eb5b8bf9f7b | 358 | pc.printf("test:"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 359 | for (s8 = 0; s8 < cmd_to_length[cmd]; s8++) |
Wayne Roberts |
0:9eb5b8bf9f7b | 360 | pc.printf("%02x ", req[s8]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 361 | pc.printf("\r\n"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 362 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 363 | case CMD_CFHZ_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 364 | flags.req_type = IRQ_TYPE_CF; |
Wayne Roberts |
0:9eb5b8bf9f7b | 365 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 366 | case CMD_FSK_MODEM_CFG_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 367 | flags.req_type = IRQ_TYPE_FSK_MODEM; |
Wayne Roberts |
0:9eb5b8bf9f7b | 368 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 369 | case CMD_FSK_PKT_CFG_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 370 | flags.req_type = IRQ_TYPE_FSK_PKT; |
Wayne Roberts |
0:9eb5b8bf9f7b | 371 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 372 | case CMD_FSK_SYNC_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 373 | flags.req_type = IRQ_TYPE_FSK_SYNC; |
Wayne Roberts |
0:9eb5b8bf9f7b | 374 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 375 | case CMD_TXDBM_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 376 | flags.req_type = IRQ_TYPE_TXDBM; |
Wayne Roberts |
0:9eb5b8bf9f7b | 377 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 378 | case CMD_LORA_MODEM_CFG_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 379 | flags.req_type = IRQ_TYPE_LORA_MODEM; |
Wayne Roberts |
0:9eb5b8bf9f7b | 380 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 381 | case CMD_LORA_PKT_CFG_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 382 | flags.req_type = IRQ_TYPE_LORA_PKT; |
Wayne Roberts |
0:9eb5b8bf9f7b | 383 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 384 | case CMD_OPMODE_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 385 | flags.req_type = IRQ_TYPE_OPMODE; |
Wayne Roberts |
0:9eb5b8bf9f7b | 386 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 387 | case CMD_RADIO_RESET: |
Wayne Roberts |
0:9eb5b8bf9f7b | 388 | load_beaconTimer.detach(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 389 | send_beaconTimer.detach(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 390 | flags.beacon_enabled = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 391 | radio_reset(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 392 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 393 | case CMD_CFHZ_WRITE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 394 | u32 = req[3]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 395 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 396 | u32 |= req[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 397 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 398 | u32 |= req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 399 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 400 | u32 |= req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 401 | pc.printf("setCh %luhz\r\n", u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 402 | Radio::SetChannel(u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 403 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 404 | case CMD_TXDBM_WRITE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 405 | s8 = req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 406 | Radio::set_tx_dbm(s8); |
Wayne Roberts |
0:9eb5b8bf9f7b | 407 | pc.printf("set tx dBm:%d\r\n", s8); |
Wayne Roberts |
0:9eb5b8bf9f7b | 408 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 409 | case CMD_LORA_MODEM_CFG_WRITE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 410 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 411 | uint8_t sf, cr; |
Wayne Roberts |
0:9eb5b8bf9f7b | 412 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 413 | u32 = req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 414 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 415 | u32 |= req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 416 | pc.printf("(%04lx) ", u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 417 | sf = req[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 418 | cr = req[3]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 419 | pc.printf("modemcfg %luKhz sf%u cr%u\r\n", u32, sf, cr); |
Wayne Roberts |
0:9eb5b8bf9f7b | 420 | Radio::LoRaModemConfig(u32, sf, cr); |
Wayne Roberts |
0:9eb5b8bf9f7b | 421 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 422 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 423 | case CMD_RX_START: |
Wayne Roberts |
0:9eb5b8bf9f7b | 424 | u32 = req[3]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 425 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 426 | u32 |= req[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 427 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 428 | u32 |= req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 429 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 430 | u32 |= req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 431 | Radio::Rx(u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 432 | pc.printf("rx(%lu)\r\n", u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 433 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 434 | case CMD_LORA_PKT_CFG_WRITE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 435 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 436 | pktcfg_t pktcfg; |
Wayne Roberts |
0:9eb5b8bf9f7b | 437 | u32 = req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 438 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 439 | u32 |= req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 440 | preambleSymbs = u32; |
Wayne Roberts |
0:9eb5b8bf9f7b | 441 | pktcfg.octet = req[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 442 | pc.printf("pktcfg pre%lu fixlen%u crc%u inv%u\r\n", u32, pktcfg.bits.fixLen, pktcfg.bits.crcOn, pktcfg.bits.invIQ); |
Wayne Roberts |
0:9eb5b8bf9f7b | 443 | Radio::LoRaPacketConfig(u32, pktcfg.bits.fixLen, pktcfg.bits.crcOn, pktcfg.bits.invIQ); |
Wayne Roberts |
0:9eb5b8bf9f7b | 444 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 445 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 446 | case CMD_BEACON_CFG_WRITE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 447 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 448 | us_timestamp_t txStartAt; |
Wayne Roberts |
0:9eb5b8bf9f7b | 449 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 450 | u32 = req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 451 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 452 | u32 |= req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 453 | pc.printf("bi%lu ", u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 454 | beaconInterval_us = u32 * 1000000; |
Wayne Roberts |
0:9eb5b8bf9f7b | 455 | pc.printf("{%u} ", beaconInterval_us); |
Wayne Roberts |
0:9eb5b8bf9f7b | 456 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 457 | u32 = req[3]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 458 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 459 | u32 |= req[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 460 | pc.printf("ps%lu ", u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 461 | beaconPreambleSymbs = u32; |
Wayne Roberts |
0:9eb5b8bf9f7b | 462 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 463 | beaconSizeBytes = req[4]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 464 | pc.printf("len%u\r\n", beaconSizeBytes); |
Wayne Roberts |
0:9eb5b8bf9f7b | 465 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 466 | if (beaconInterval_us > 0) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 467 | _load_beacon(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 468 | send_beacon(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 469 | txStartAt = Radio::lpt.read_us(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 470 | flags.beacon_test = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 471 | while (flags.beacon_test) |
Wayne Roberts |
0:9eb5b8bf9f7b | 472 | Radio::service(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 473 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 474 | u32 = Radio::irqAt - txStartAt; |
Wayne Roberts |
0:9eb5b8bf9f7b | 475 | pc.printf("beaconDur:%lu, 0x%lx\r\n", u32, u32); |
Wayne Roberts |
0:9eb5b8bf9f7b | 476 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 477 | tim_init(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 478 | flags.beacon_enabled = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 479 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 480 | irq.buf[1] = u32 & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 481 | u32 >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 482 | irq.buf[2] = u32 & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 483 | u32 >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 484 | irq.buf[3] = u32 & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 485 | u32 >>= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 486 | irq.buf[4] = u32 & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 487 | irq.fields.flags.irq_type = IRQ_TYPE_BEACON_DUR; |
Wayne Roberts |
0:9eb5b8bf9f7b | 488 | //pc.printf("BDirq.buf[0]:%02x\r\n", irq.buf[0]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 489 | irqOutPin = 1; |
Wayne Roberts |
0:9eb5b8bf9f7b | 490 | } else { |
Wayne Roberts |
0:9eb5b8bf9f7b | 491 | load_beaconTimer.detach(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 492 | send_beaconTimer.detach(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 493 | flags.beacon_enabled = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 494 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 495 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 496 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 497 | case CMD_BEACON_PAYLOAD: |
Wayne Roberts |
0:9eb5b8bf9f7b | 498 | beacon_payload[0] = req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 499 | beacon_payload[1] = req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 500 | beacon_payload[2] = req[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 501 | beacon_payload[3] = req[3]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 502 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 503 | case CMD_CFG: |
Wayne Roberts |
0:9eb5b8bf9f7b | 504 | memcpy(cfg.buf, req, sizeof(cfg_t)); |
Wayne Roberts |
0:9eb5b8bf9f7b | 505 | pc.printf("cfg %u\r\n", cfg.fields.n_rssi_samples); |
Wayne Roberts |
0:9eb5b8bf9f7b | 506 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 507 | case CMD_STANDBY: |
Wayne Roberts |
0:9eb5b8bf9f7b | 508 | Radio::Standby(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 509 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 510 | case CMD_PUBLIC_NET: |
Wayne Roberts |
0:9eb5b8bf9f7b | 511 | pc.printf("pubnet%02x\r\n", req[0]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 512 | Radio::SetPublicNetwork(req[0] == 0 ? false : true); |
Wayne Roberts |
0:9eb5b8bf9f7b | 513 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 514 | case CMD_MAX_PAYLEN_WRITE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 515 | pc.printf("maxpay%02x\r\n", req[0]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 516 | Radio::SetRxMaxPayloadLength(req[0]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 517 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 518 | case CMD_TX_BUF_START: |
Wayne Roberts |
0:9eb5b8bf9f7b | 519 | if (cfg.fields.flags.rxOnTxDone) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 520 | /* turn off receiver in preparation for downlink */ |
Wayne Roberts |
0:9eb5b8bf9f7b | 521 | Radio::Standby(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 522 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 523 | // preambleLen, fixLen, crcOn, invIQ |
Wayne Roberts |
0:9eb5b8bf9f7b | 524 | Radio::LoRaPacketConfig(preambleSymbs, false, false, true); |
Wayne Roberts |
0:9eb5b8bf9f7b | 525 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 526 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 527 | tx_pkt_len = req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 528 | memcpy(Radio::radio.tx_buf, req+1, 31); |
Wayne Roberts |
0:9eb5b8bf9f7b | 529 | tx_pkt_idx = 31; |
Wayne Roberts |
0:9eb5b8bf9f7b | 530 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 531 | case CMD_TX_BUF: |
Wayne Roberts |
0:9eb5b8bf9f7b | 532 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 533 | uint8_t len = 32; |
Wayne Roberts |
0:9eb5b8bf9f7b | 534 | uint8_t end = (tx_pkt_idx + 32) & 0xff; |
Wayne Roberts |
0:9eb5b8bf9f7b | 535 | if (end < 32) |
Wayne Roberts |
0:9eb5b8bf9f7b | 536 | len -= end; |
Wayne Roberts |
0:9eb5b8bf9f7b | 537 | memcpy(Radio::radio.tx_buf + tx_pkt_idx, req, len); |
Wayne Roberts |
0:9eb5b8bf9f7b | 538 | tx_pkt_idx += len; |
Wayne Roberts |
0:9eb5b8bf9f7b | 539 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 540 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 541 | case CMD_RSSI_REQ: |
Wayne Roberts |
0:9eb5b8bf9f7b | 542 | get_n_rssi = req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 543 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 544 | case CMD_SEND: |
Wayne Roberts |
0:9eb5b8bf9f7b | 545 | Radio::Send(tx_pkt_len, |
Wayne Roberts |
0:9eb5b8bf9f7b | 546 | cfg.fields.maxListenTime, |
Wayne Roberts |
0:9eb5b8bf9f7b | 547 | cfg.fields.channelFreeTime, |
Wayne Roberts |
0:9eb5b8bf9f7b | 548 | cfg.fields.rssiThresh |
Wayne Roberts |
0:9eb5b8bf9f7b | 549 | ); |
Wayne Roberts |
0:9eb5b8bf9f7b | 550 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 551 | case CMD_SKIP_BEACONS: |
Wayne Roberts |
0:9eb5b8bf9f7b | 552 | skip_beacon_cnt = req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 553 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 554 | case CMD_LORA_SYMBTO_WRITE: // 1 byte |
Wayne Roberts |
0:9eb5b8bf9f7b | 555 | Radio::SetLoRaSymbolTimeout(req[0]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 556 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 557 | case CMD_FSK_MODEM_CFG_WRITE: // 10bytes |
Wayne Roberts |
0:9eb5b8bf9f7b | 558 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 559 | uint32_t bps, fdev_hz; |
Wayne Roberts |
0:9eb5b8bf9f7b | 560 | uint16_t khz_bw; |
Wayne Roberts |
0:9eb5b8bf9f7b | 561 | u32 = req[3]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 562 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 563 | u32 |= req[2]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 564 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 565 | u32 |= req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 566 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 567 | u32 |= req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 568 | bps = u32; |
Wayne Roberts |
0:9eb5b8bf9f7b | 569 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 570 | u32 = req[5]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 571 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 572 | u32 |= req[4]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 573 | khz_bw = u32; |
Wayne Roberts |
0:9eb5b8bf9f7b | 574 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 575 | u32 = req[9]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 576 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 577 | u32 |= req[8]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 578 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 579 | u32 |= req[7]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 580 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 581 | u32 |= req[6]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 582 | fdev_hz = u32; |
Wayne Roberts |
0:9eb5b8bf9f7b | 583 | Radio::GFSKModemConfig(bps, khz_bw, fdev_hz); |
Wayne Roberts |
0:9eb5b8bf9f7b | 584 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 585 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 586 | case CMD_FSK_PKT_CFG_WRITE: // 4 bytes |
Wayne Roberts |
0:9eb5b8bf9f7b | 587 | u32 = req[1]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 588 | u32 <<= 8; |
Wayne Roberts |
0:9eb5b8bf9f7b | 589 | u32 |= req[0]; |
Wayne Roberts |
0:9eb5b8bf9f7b | 590 | Radio::GFSKPacketConfig(u32, req[2], req[3]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 591 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 592 | case CMD_FSK_SYNC_WRITE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 593 | /* TODO */ |
Wayne Roberts |
0:9eb5b8bf9f7b | 594 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 595 | #ifdef DEBUG_SMBUS |
Wayne Roberts |
0:9eb5b8bf9f7b | 596 | case CMD_ISR: |
Wayne Roberts |
0:9eb5b8bf9f7b | 597 | pc.printf("i%02x ", req[0]); // lsbyte of I2C_ISR |
Wayne Roberts |
0:9eb5b8bf9f7b | 598 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 599 | case CMD_STOPF: |
Wayne Roberts |
0:9eb5b8bf9f7b | 600 | pc.printf("STOPF\r\n"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 601 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 602 | case CMD_AF: |
Wayne Roberts |
0:9eb5b8bf9f7b | 603 | pc.printf("AF%u ", req[0]); // req[0] is dma tx cndtr |
Wayne Roberts |
0:9eb5b8bf9f7b | 604 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 605 | #endif /* DEBUG_SMBUS */ |
Wayne Roberts |
0:9eb5b8bf9f7b | 606 | case CMD_BUSERR: |
Wayne Roberts |
0:9eb5b8bf9f7b | 607 | pc.printf("BUSERR%u\r\n", req[0]); |
Wayne Roberts |
0:9eb5b8bf9f7b | 608 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 609 | /* failures: */ |
Wayne Roberts |
0:9eb5b8bf9f7b | 610 | case CMD_ARLO: |
Wayne Roberts |
0:9eb5b8bf9f7b | 611 | pc.printf("ARLO%u,%u\r\n", toI2C_rx_pkt_idx, req[0]); // req[0] tx_cndtr |
Wayne Roberts |
0:9eb5b8bf9f7b | 612 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 613 | case CMD_TIMEOUT: |
Wayne Roberts |
0:9eb5b8bf9f7b | 614 | pc.printf("TIMEOUT(tx%u,rx%u)\r\n", req[0], req[1]); // req[0] tx_cndtr |
Wayne Roberts |
0:9eb5b8bf9f7b | 615 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 616 | default: |
Wayne Roberts |
0:9eb5b8bf9f7b | 617 | pc.printf("??%02x??\r\n", cmd); |
Wayne Roberts |
0:9eb5b8bf9f7b | 618 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 619 | } // ..switch (cmd) |
Wayne Roberts |
0:9eb5b8bf9f7b | 620 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 621 | } // ..service_i2c_write() |
Wayne Roberts |
0:9eb5b8bf9f7b | 622 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 623 | const RadioEvents_t rev = { |
Wayne Roberts |
0:9eb5b8bf9f7b | 624 | /* Dio0_top_half */ NULL, |
Wayne Roberts |
0:9eb5b8bf9f7b | 625 | /* TxDone_topHalf */ NULL, |
Wayne Roberts |
0:9eb5b8bf9f7b | 626 | /* TxDone_botHalf */ txDoneCB, |
Wayne Roberts |
0:9eb5b8bf9f7b | 627 | /* TxTimeout */ NULL, |
Wayne Roberts |
0:9eb5b8bf9f7b | 628 | /* RxDone */ rxDoneCB, |
Wayne Roberts |
0:9eb5b8bf9f7b | 629 | /* RxTimeout */ NULL, |
Wayne Roberts |
0:9eb5b8bf9f7b | 630 | /* RxError */ NULL, |
Wayne Roberts |
0:9eb5b8bf9f7b | 631 | /* FhssChangeChannel */NULL, |
Wayne Roberts |
0:9eb5b8bf9f7b | 632 | /* CadDone */ NULL |
Wayne Roberts |
0:9eb5b8bf9f7b | 633 | }; |
Wayne Roberts |
0:9eb5b8bf9f7b | 634 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 635 | int main() |
Wayne Roberts |
0:9eb5b8bf9f7b | 636 | { |
Wayne Roberts |
0:9eb5b8bf9f7b | 637 | Thread eventThread(osPriorityNormal, 512); |
Wayne Roberts |
0:9eb5b8bf9f7b | 638 | int res; |
Wayne Roberts |
0:9eb5b8bf9f7b | 639 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 640 | pc.baud(115200); |
Wayne Roberts |
0:9eb5b8bf9f7b | 641 | pc.printf("\r\nreset\r\n"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 642 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 643 | Radio::Init(&rev); |
Wayne Roberts |
0:9eb5b8bf9f7b | 644 | radio_device_init(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 645 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 646 | res = smbus_init(I2C_SDA, I2C_SCL, SLAVE_ADDRESS); |
Wayne Roberts |
0:9eb5b8bf9f7b | 647 | pc.printf("%d = smbus_init()\r\n", res); |
Wayne Roberts |
0:9eb5b8bf9f7b | 648 | if (res < 0) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 649 | for (;;) asm("nop"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 650 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 651 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 652 | eventThread.start(callback(&queue, &EventQueue::dispatch_forever)); |
Wayne Roberts |
0:9eb5b8bf9f7b | 653 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 654 | while (1) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 655 | if (i2c.c_overrun) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 656 | pc.printf("c_overrun\r\n"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 657 | for (;;) asm("nop"); |
Wayne Roberts |
0:9eb5b8bf9f7b | 658 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 659 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 660 | service_i2c(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 661 | console(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 662 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 663 | if (get_n_rssi > 0) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 664 | measure_ambient(get_n_rssi); |
Wayne Roberts |
0:9eb5b8bf9f7b | 665 | get_n_rssi = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 666 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 667 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 668 | if (flags.req_type != IRQ_TYPE_PKT) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 669 | switch (flags.req_type) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 670 | case IRQ_TYPE_CF: |
Wayne Roberts |
0:9eb5b8bf9f7b | 671 | cf_read(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 672 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 673 | case IRQ_TYPE_RANDOM: |
Wayne Roberts |
0:9eb5b8bf9f7b | 674 | get_random(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 675 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 676 | case IRQ_TYPE_FSK_MODEM: |
Wayne Roberts |
0:9eb5b8bf9f7b | 677 | get_fsk_modem(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 678 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 679 | case IRQ_TYPE_FSK_PKT: |
Wayne Roberts |
0:9eb5b8bf9f7b | 680 | get_fsk_packet(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 681 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 682 | case IRQ_TYPE_FSK_SYNC: |
Wayne Roberts |
0:9eb5b8bf9f7b | 683 | get_fsk_sync(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 684 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 685 | case IRQ_TYPE_TXDBM: |
Wayne Roberts |
0:9eb5b8bf9f7b | 686 | get_tx_dbm(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 687 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 688 | case IRQ_TYPE_LORA_MODEM: |
Wayne Roberts |
0:9eb5b8bf9f7b | 689 | get_lora_modem(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 690 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 691 | case IRQ_TYPE_LORA_PKT: |
Wayne Roberts |
0:9eb5b8bf9f7b | 692 | get_lora_packet(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 693 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 694 | case IRQ_TYPE_OPMODE: |
Wayne Roberts |
0:9eb5b8bf9f7b | 695 | get_opmode(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 696 | break; |
Wayne Roberts |
0:9eb5b8bf9f7b | 697 | } // ..switch (flags.req_type) |
Wayne Roberts |
0:9eb5b8bf9f7b | 698 | flags.req_type = IRQ_TYPE_PKT; |
Wayne Roberts |
0:9eb5b8bf9f7b | 699 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 700 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 701 | if (blocked_cmd) { |
Wayne Roberts |
0:9eb5b8bf9f7b | 702 | pc.printf("blocked_cmd:%02x\r\n", blocked_cmd); |
Wayne Roberts |
0:9eb5b8bf9f7b | 703 | blocked_cmd = 0; |
Wayne Roberts |
0:9eb5b8bf9f7b | 704 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 705 | |
Wayne Roberts |
0:9eb5b8bf9f7b | 706 | Radio::service(); |
Wayne Roberts |
0:9eb5b8bf9f7b | 707 | } // ..while (1) |
Wayne Roberts |
0:9eb5b8bf9f7b | 708 | } |
Wayne Roberts |
0:9eb5b8bf9f7b | 709 |