wayne roberts / Mbed OS lora_mesh

Dependencies:   sx12xx_hal

Committer:
Wayne Roberts
Date:
Tue Dec 03 09:48:53 2019 -0800
Revision:
0:6015834e4279
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Wayne Roberts 0:6015834e4279 1 /* upstream: interface towards gateway 36m cyan */
Wayne Roberts 0:6015834e4279 2 #include "main.h"
Wayne Roberts 0:6015834e4279 3
Wayne Roberts 0:6015834e4279 4 #ifndef GATEWAY
Wayne Roberts 0:6015834e4279 5 struct {
Wayne Roberts 0:6015834e4279 6 int preference;
Wayne Roberts 0:6015834e4279 7 uint32_t id;
Wayne Roberts 0:6015834e4279 8 uint8_t hfg;
Wayne Roberts 0:6015834e4279 9 } best_upstream;
Wayne Roberts 0:6015834e4279 10
Wayne Roberts 0:6015834e4279 11 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 12
Wayne Roberts 0:6015834e4279 13
Wayne Roberts 0:6015834e4279 14 /* packets received from upstream */
Wayne Roberts 0:6015834e4279 15 void upstream_req_rxDoneCB(float rssi, float snr, uint8_t* Idx, uint32_t sendingID, uint8_t cmd)
Wayne Roberts 0:6015834e4279 16 {
Wayne Roberts 0:6015834e4279 17 if (cmd == CMD_REMOVE_DEVICE_REQ) {
Wayne Roberts 0:6015834e4279 18 uint32_t remove_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
Wayne Roberts 0:6015834e4279 19 *Idx += 4;
Wayne Roberts 0:6015834e4279 20 if (!remove_directlyAttached_device(remove_id)) {
Wayne Roberts 0:6015834e4279 21 /* wasnt found locally, check child devices */
Wayne Roberts 0:6015834e4279 22 uint32_t removedFrom;
Wayne Roberts 0:6015834e4279 23 remove_childDevice(remove_id, &removedFrom);
Wayne Roberts 0:6015834e4279 24 if (removedFrom != ID_NONE) {
Wayne Roberts 0:6015834e4279 25 /* forward this remove down */
Wayne Roberts 0:6015834e4279 26 downRemove.destID = removedFrom;
Wayne Roberts 0:6015834e4279 27 downRemove.removeID = remove_id;
Wayne Roberts 0:6015834e4279 28 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 29 } else
Wayne Roberts 0:6015834e4279 30 reqFlags.bits.txAns = ANSWER_BUSY;
Wayne Roberts 0:6015834e4279 31 } else
Wayne Roberts 0:6015834e4279 32 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 33
Wayne Roberts 0:6015834e4279 34 } else if (cmd == CMD_DISCOVERY_ANS) {
Wayne Roberts 0:6015834e4279 35 #ifdef GATEWAY
Wayne Roberts 0:6015834e4279 36 *Idx += 6;
Wayne Roberts 0:6015834e4279 37 #else
Wayne Roberts 0:6015834e4279 38 int my_sq, peer_sq;
Wayne Roberts 0:6015834e4279 39 uint8_t idxCpy = *Idx;
Wayne Roberts 0:6015834e4279 40 uint8_t hfg;
Wayne Roberts 0:6015834e4279 41 float signal_preference;
Wayne Roberts 0:6015834e4279 42 int hops_preference, preference;
Wayne Roberts 0:6015834e4279 43 /* everything is upstream when we arent associated on network */
Wayne Roberts 0:6015834e4279 44
Wayne Roberts 0:6015834e4279 45 // signal quality is negative: rss + snr
Wayne Roberts 0:6015834e4279 46 peer_sq = Radio::radio.rx_buf[idxCpy++] - 0x100;
Wayne Roberts 0:6015834e4279 47 my_sq = rssi + snr;
Wayne Roberts 0:6015834e4279 48 signal_preference = (peer_sq + my_sq) / 2; // round-trip signal quality
Wayne Roberts 0:6015834e4279 49 hfg = Radio::radio.rx_buf[idxCpy++];
Wayne Roberts 0:6015834e4279 50 if (hfg != HFG_UNATTACHED) {
Wayne Roberts 0:6015834e4279 51 hops_preference = 1 - hfg; // lower number preferable
Wayne Roberts 0:6015834e4279 52 preference = signal_preference + (hops_preference * 10);
Wayne Roberts 0:6015834e4279 53 if (preference > best_upstream.preference) {
Wayne Roberts 0:6015834e4279 54 best_upstream.preference = preference;
Wayne Roberts 0:6015834e4279 55 best_upstream.id = sendingID;
Wayne Roberts 0:6015834e4279 56 best_upstream.hfg = hfg;
Wayne Roberts 0:6015834e4279 57 }
Wayne Roberts 0:6015834e4279 58 }
Wayne Roberts 0:6015834e4279 59
Wayne Roberts 0:6015834e4279 60 *Idx += 2;
Wayne Roberts 0:6015834e4279 61 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 62 } else if (cmd == CMD_USER_PAYLOAD_DN_REQ) { // rxDone callback, pkt from upstream
Wayne Roberts 0:6015834e4279 63 uint8_t len;
Wayne Roberts 0:6015834e4279 64 #ifndef GATEWAY
Wayne Roberts 0:6015834e4279 65 uint32_t final_dest_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
Wayne Roberts 0:6015834e4279 66 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 67 *Idx += 4;
Wayne Roberts 0:6015834e4279 68 len = Radio::radio.rx_buf[*Idx];
Wayne Roberts 0:6015834e4279 69 (*Idx)++;
Wayne Roberts 0:6015834e4279 70 #ifdef GATEWAY
Wayne Roberts 0:6015834e4279 71 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 72 #else
Wayne Roberts 0:6015834e4279 73 if (final_dest_id == my_id) {
Wayne Roberts 0:6015834e4279 74 app_downlink(len, &Radio::radio.rx_buf[*Idx]);
Wayne Roberts 0:6015834e4279 75 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 76 } else {
Wayne Roberts 0:6015834e4279 77 if (attUp.id == ID_NONE) {
Wayne Roberts 0:6015834e4279 78 reqFlags.bits.txAns = ANSWER_UNATTACHED;
Wayne Roberts 0:6015834e4279 79 } else {
Wayne Roberts 0:6015834e4279 80 if (fwd.len == -1) {
Wayne Roberts 0:6015834e4279 81 fwd.len = len;
Wayne Roberts 0:6015834e4279 82 fwd.A_id = final_dest_id;
Wayne Roberts 0:6015834e4279 83 fwd.tx_dest_id = find_dest_id(final_dest_id);
Wayne Roberts 0:6015834e4279 84 memcpy(fwd.buf, &Radio::radio.rx_buf[*Idx], len);
Wayne Roberts 0:6015834e4279 85 reqFlags.bits.currentOp = CMD_USER_PAYLOAD_DN_REQ; // this is downlink
Wayne Roberts 0:6015834e4279 86 reqFlags.bits.txAns = ANSWER_OK;
Wayne Roberts 0:6015834e4279 87 } else
Wayne Roberts 0:6015834e4279 88 reqFlags.bits.txAns = ANSWER_BUSY;
Wayne Roberts 0:6015834e4279 89 }
Wayne Roberts 0:6015834e4279 90 }
Wayne Roberts 0:6015834e4279 91 #endif /* !GATEWAY */
Wayne Roberts 0:6015834e4279 92 (*Idx) += len;
Wayne Roberts 0:6015834e4279 93 }
Wayne Roberts 0:6015834e4279 94
Wayne Roberts 0:6015834e4279 95 } // ..upstream_req_rxDoneCB()
Wayne Roberts 0:6015834e4279 96
Wayne Roberts 0:6015834e4279 97 #ifndef GATEWAY
Wayne Roberts 0:6015834e4279 98
Wayne Roberts 0:6015834e4279 99 upstream_t attUp;
Wayne Roberts 0:6015834e4279 100 upstream_t prospect;
Wayne Roberts 0:6015834e4279 101 uint32_t id_newDeviceNotification;
Wayne Roberts 0:6015834e4279 102
Wayne Roberts 0:6015834e4279 103 void upstream_ans_rxDoneCB(float rssi, float snr, uint8_t* Idx, uint32_t sendingID, uint8_t cmd)
Wayne Roberts 0:6015834e4279 104 {
Wayne Roberts 0:6015834e4279 105 if (reqFlags.bits.currentOp == CMD_ATTACH_REQ) {
Wayne Roberts 0:6015834e4279 106 if (sendingID == best_upstream.id) {
Wayne Roberts 0:6015834e4279 107 attUp.id = best_upstream.id;
Wayne Roberts 0:6015834e4279 108 attUp.preference = best_upstream.preference;
Wayne Roberts 0:6015834e4279 109 attUp.hfg = best_upstream.hfg;
Wayne Roberts 0:6015834e4279 110 hops_from_gateway = best_upstream.hfg + 1;
Wayne Roberts 0:6015834e4279 111 prospect.id = ID_NONE;
Wayne Roberts 0:6015834e4279 112 }
Wayne Roberts 0:6015834e4279 113
Wayne Roberts 0:6015834e4279 114 reqFlags.bits.currentOp = CMD_UNUSED;
Wayne Roberts 0:6015834e4279 115 } else if (reqFlags.bits.currentOp == CMD_USER_PAYLOAD_UP_REQ) {
Wayne Roberts 0:6015834e4279 116 app_uplink_complete();
Wayne Roberts 0:6015834e4279 117 reqFlags.bits.currentOp = CMD_UNUSED;
Wayne Roberts 0:6015834e4279 118 } else if (reqFlags.bits.currentOp == CMD_NEW_DEVICE_ATTACHED_REQ) {
Wayne Roberts 0:6015834e4279 119 id_newDeviceNotification = ID_NONE;
Wayne Roberts 0:6015834e4279 120 reqFlags.bits.currentOp = CMD_UNUSED;
Wayne Roberts 0:6015834e4279 121 }
Wayne Roberts 0:6015834e4279 122
Wayne Roberts 0:6015834e4279 123 } // ..upstream_ans_rxDoneCB()
Wayne Roberts 0:6015834e4279 124
Wayne Roberts 0:6015834e4279 125 void upstream_print_status()
Wayne Roberts 0:6015834e4279 126 {
Wayne Roberts 0:6015834e4279 127 pc.printf("attUp.id:%lx ", attUp.id);
Wayne Roberts 0:6015834e4279 128 if (hops_from_gateway == HFG_UNATTACHED) {
Wayne Roberts 0:6015834e4279 129 pc.printf("best_upstream %lx, %d hfg:%u\r\n", best_upstream.id, best_upstream.preference, best_upstream.hfg);
Wayne Roberts 0:6015834e4279 130 }
Wayne Roberts 0:6015834e4279 131 }
Wayne Roberts 0:6015834e4279 132
Wayne Roberts 0:6015834e4279 133 void upstream_new_device_notify() /* called from txDone */
Wayne Roberts 0:6015834e4279 134 {
Wayne Roberts 0:6015834e4279 135 txBuf[txBuf_idx++] = CMD_NEW_DEVICE_ATTACHED_REQ;
Wayne Roberts 0:6015834e4279 136 putu32ToBuf(&txBuf[txBuf_idx], id_newDeviceNotification);
Wayne Roberts 0:6015834e4279 137 txBuf_idx += 4;
Wayne Roberts 0:6015834e4279 138 tx_dest_id = attUp.id;
Wayne Roberts 0:6015834e4279 139 queue.call_in(500, txBuf_send, true);
Wayne Roberts 0:6015834e4279 140 reqFlags.bits.currentOp = CMD_NEW_DEVICE_ATTACHED_REQ;
Wayne Roberts 0:6015834e4279 141 //mdbg_printf("newDeviceNotify_tx ");
Wayne Roberts 0:6015834e4279 142 }
Wayne Roberts 0:6015834e4279 143
Wayne Roberts 0:6015834e4279 144 void discovery_rx_end()
Wayne Roberts 0:6015834e4279 145 {
Wayne Roberts 0:6015834e4279 146 Radio::Sleep();
Wayne Roberts 0:6015834e4279 147 //mdbg_printf("discoveryAnsRxEnd ");
Wayne Roberts 0:6015834e4279 148
Wayne Roberts 0:6015834e4279 149 if (best_upstream.preference == INT_MIN) {
Wayne Roberts 0:6015834e4279 150 /* nothing received, try discoverying again */
Wayne Roberts 0:6015834e4279 151 queue.call_in(1000, txBuf_send, true);
Wayne Roberts 0:6015834e4279 152 pc.printf("discoveredNothing\r\n");
Wayne Roberts 0:6015834e4279 153 } else {
Wayne Roberts 0:6015834e4279 154 /* best gateway heard, attach to it */
Wayne Roberts 0:6015834e4279 155 txBuf_idx = 0; // squash discovery request, no longer needed
Wayne Roberts 0:6015834e4279 156 txBuf[txBuf_idx++] = CMD_ATTACH_REQ;
Wayne Roberts 0:6015834e4279 157 tx_dest_id = best_upstream.id;
Wayne Roberts 0:6015834e4279 158 queue.call_in(500, txBuf_send, true);
Wayne Roberts 0:6015834e4279 159 pc.printf("attach-to-%lx\r\n", best_upstream.id);
Wayne Roberts 0:6015834e4279 160 reqFlags.bits.currentOp = CMD_ATTACH_REQ;
Wayne Roberts 0:6015834e4279 161 }
Wayne Roberts 0:6015834e4279 162 } // ..discovery_rx_end()
Wayne Roberts 0:6015834e4279 163
Wayne Roberts 0:6015834e4279 164 void upstream_init()
Wayne Roberts 0:6015834e4279 165 {
Wayne Roberts 0:6015834e4279 166 pc.printf("txDiscoverReq:%u ", txBuf_idx);
Wayne Roberts 0:6015834e4279 167 txBuf[txBuf_idx++] = CMD_DISCOVERY_REQ;
Wayne Roberts 0:6015834e4279 168 tx_dest_id = ANY_ID;
Wayne Roberts 0:6015834e4279 169 txBuf_send(true);
Wayne Roberts 0:6015834e4279 170
Wayne Roberts 0:6015834e4279 171 best_upstream.preference = INT_MIN;
Wayne Roberts 0:6015834e4279 172 init_attached_upstream();
Wayne Roberts 0:6015834e4279 173 hops_from_gateway = HFG_UNATTACHED;
Wayne Roberts 0:6015834e4279 174 reqFlags.bits.currentOp = CMD_DISCOVERY_REQ;
Wayne Roberts 0:6015834e4279 175 }
Wayne Roberts 0:6015834e4279 176
Wayne Roberts 0:6015834e4279 177 int uplink(const uint8_t* userPayload, uint8_t userPayloadSize)
Wayne Roberts 0:6015834e4279 178 {
Wayne Roberts 0:6015834e4279 179 unsigned n;
Wayne Roberts 0:6015834e4279 180 //mdbg_printf("uplink_tx%u ", userPayloadSize);
Wayne Roberts 0:6015834e4279 181 if (reqFlags.bits.currentOp == CMD_USER_PAYLOAD_UP_REQ) {
Wayne Roberts 0:6015834e4279 182 //mdbg_printf("busy\r\n");
Wayne Roberts 0:6015834e4279 183 return -1;
Wayne Roberts 0:6015834e4279 184 }
Wayne Roberts 0:6015834e4279 185
Wayne Roberts 0:6015834e4279 186 reqFlags.bits.currentOp = CMD_USER_PAYLOAD_UP_REQ;
Wayne Roberts 0:6015834e4279 187
Wayne Roberts 0:6015834e4279 188 txBuf[txBuf_idx++] = CMD_USER_PAYLOAD_UP_REQ;
Wayne Roberts 0:6015834e4279 189
Wayne Roberts 0:6015834e4279 190 // originating ID, to be preserved all the way up to gateway
Wayne Roberts 0:6015834e4279 191 putu32ToBuf(&txBuf[txBuf_idx], my_id);
Wayne Roberts 0:6015834e4279 192 txBuf_idx += 4;
Wayne Roberts 0:6015834e4279 193
Wayne Roberts 0:6015834e4279 194 txBuf[txBuf_idx++] = userPayloadSize;
Wayne Roberts 0:6015834e4279 195 for (n = 0; n < userPayloadSize; n++)
Wayne Roberts 0:6015834e4279 196 txBuf[txBuf_idx++] = userPayload[n];
Wayne Roberts 0:6015834e4279 197
Wayne Roberts 0:6015834e4279 198 tx_dest_id = attUp.id;
Wayne Roberts 0:6015834e4279 199 flags.CallTXRequest = 1; // transmit will occur in idle-rxsingle cycle
Wayne Roberts 0:6015834e4279 200
Wayne Roberts 0:6015834e4279 201 return 0;
Wayne Roberts 0:6015834e4279 202 }
Wayne Roberts 0:6015834e4279 203
Wayne Roberts 0:6015834e4279 204 void upstream_attached_check(uint32_t sending_id)
Wayne Roberts 0:6015834e4279 205 {
Wayne Roberts 0:6015834e4279 206 if (sending_id != attUp.id)
Wayne Roberts 0:6015834e4279 207 return;
Wayne Roberts 0:6015834e4279 208
Wayne Roberts 0:6015834e4279 209 cmd_e cmd = (cmd_e)Radio::radio.rx_buf[9];
Wayne Roberts 0:6015834e4279 210 Mdbg_printf("upAttCmd:%s? ", cmdStrs[cmd]);
Wayne Roberts 0:6015834e4279 211 if (cmd == CMD_ATTACH_REQ) {
Wayne Roberts 0:6015834e4279 212 pc.printf("\e[31muppreattach\e[0m ");
Wayne Roberts 0:6015834e4279 213 /* TODO appropriate action when upstream path changes */
Wayne Roberts 0:6015834e4279 214 }
Wayne Roberts 0:6015834e4279 215 }
Wayne Roberts 0:6015834e4279 216
Wayne Roberts 0:6015834e4279 217 void init_attached_upstream()
Wayne Roberts 0:6015834e4279 218 {
Wayne Roberts 0:6015834e4279 219 attUp.id = ID_NONE;
Wayne Roberts 0:6015834e4279 220 attUp.cnt = 0;
Wayne Roberts 0:6015834e4279 221 attUp.preference = INT_MIN;
Wayne Roberts 0:6015834e4279 222
Wayne Roberts 0:6015834e4279 223 prospect.id = ID_NONE;
Wayne Roberts 0:6015834e4279 224 prospect.cnt = 0;
Wayne Roberts 0:6015834e4279 225 prospect.preference = INT_MIN;
Wayne Roberts 0:6015834e4279 226 }
Wayne Roberts 0:6015834e4279 227
Wayne Roberts 0:6015834e4279 228 void upstream_signal_check(float rssi, float snr, uint8_t rx_hfg, uint32_t rx_id)
Wayne Roberts 0:6015834e4279 229 {
Wayne Roberts 0:6015834e4279 230 float signal_preference;
Wayne Roberts 0:6015834e4279 231 int this_preference, my_sq, hops_preference = 1 - rx_hfg;
Wayne Roberts 0:6015834e4279 232 my_sq = rssi + snr;
Wayne Roberts 0:6015834e4279 233 signal_preference = my_sq;
Wayne Roberts 0:6015834e4279 234 this_preference = signal_preference + (hops_preference * 10);
Wayne Roberts 0:6015834e4279 235 if (rx_id == attUp.id) {
Wayne Roberts 0:6015834e4279 236 /* how much has path to upstream changed ? */
Wayne Roberts 0:6015834e4279 237 Rx_log_printf("attachedChange initial:%d vs this:%d ", attUp.preference, this_preference);
Wayne Roberts 0:6015834e4279 238 if (attUp.preference > this_preference) {
Wayne Roberts 0:6015834e4279 239 attUp.cnt++;
Wayne Roberts 0:6015834e4279 240 } else
Wayne Roberts 0:6015834e4279 241 attUp.cnt = 0;
Wayne Roberts 0:6015834e4279 242 } else {
Wayne Roberts 0:6015834e4279 243 /* check for better upstream */
Wayne Roberts 0:6015834e4279 244 Rx_log_printf("attached:%d vs this:%d ", attUp.preference, this_preference);
Wayne Roberts 0:6015834e4279 245 if ((this_preference-10) > attUp.preference) { // -10: significantly better
Wayne Roberts 0:6015834e4279 246 Rx_log_printf("better");
Wayne Roberts 0:6015834e4279 247 if (prospect.id == ID_NONE) {
Wayne Roberts 0:6015834e4279 248 prospect.cnt = 1;
Wayne Roberts 0:6015834e4279 249 prospect.id = rx_id;
Wayne Roberts 0:6015834e4279 250 Rx_log_printf("Init");
Wayne Roberts 0:6015834e4279 251 } else {
Wayne Roberts 0:6015834e4279 252 prospect.cnt++;
Wayne Roberts 0:6015834e4279 253 Rx_log_printf("Inc%u", prospect.cnt);
Wayne Roberts 0:6015834e4279 254 if (prospect.cnt > 3) {
Wayne Roberts 0:6015834e4279 255 init_attached_upstream();
Wayne Roberts 0:6015834e4279 256 hops_from_gateway = HFG_UNATTACHED;
Wayne Roberts 0:6015834e4279 257 queue.call_in(2000, upstream_init);
Wayne Roberts 0:6015834e4279 258 Rx_log_printf("\e[33mreattach\e[0m ");
Wayne Roberts 0:6015834e4279 259 }
Wayne Roberts 0:6015834e4279 260 }
Wayne Roberts 0:6015834e4279 261 } else if (this_preference < attUp.preference) {
Wayne Roberts 0:6015834e4279 262 Rx_log_printf("worse");
Wayne Roberts 0:6015834e4279 263 if (prospect.id == rx_id) {
Wayne Roberts 0:6015834e4279 264 prospect.id = ID_NONE;
Wayne Roberts 0:6015834e4279 265 prospect.cnt = 0;
Wayne Roberts 0:6015834e4279 266 Rx_log_printf("Clear");
Wayne Roberts 0:6015834e4279 267 }
Wayne Roberts 0:6015834e4279 268 }
Wayne Roberts 0:6015834e4279 269
Wayne Roberts 0:6015834e4279 270 Rx_log_printf(" ");
Wayne Roberts 0:6015834e4279 271 } // ..rx from other-than-attached
Wayne Roberts 0:6015834e4279 272 }
Wayne Roberts 0:6015834e4279 273
Wayne Roberts 0:6015834e4279 274 #endif /* !GATEWAY */