star-mesh LoRa network

Dependencies:   sx12xx_hal

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers downstream_interface.cpp Source File

downstream_interface.cpp

00001 
00002 ///* downstream: interface away from gateway 35m = magenta */;
00003 #include "main.h"
00004 
00005 lid_list_t* attachedDevices;
00006 struct remove downRemove;
00007 
00008 void request_remove_device()
00009 {
00010     txBuf[txBuf_idx++] = CMD_REMOVE_DEVICE_REQ;
00011     putu32ToBuf(&txBuf[txBuf_idx], downRemove.removeID);
00012     txBuf_idx += 4;
00013     tx_dest_id = downRemove.destID;
00014     queue.call_in(500, txBuf_send, true);
00015     reqFlags.bits.currentOp = CMD_REMOVE_DEVICE_REQ;
00016 }
00017 
00018 /* return true: device is new */
00019 static bool list_add_local_device(uint32_t newID)
00020 {
00021     Rx_log_printf("newID:%lx ", newID);
00022     if (attachedDevices == NULL) {
00023         attachedDevices = (lid_list_t*)malloc(sizeof(lid_list_t));
00024         attachedDevices->id = newID;
00025         attachedDevices->attachedList = NULL;
00026         attachedDevices->next = NULL;
00027         return true;
00028     } else {
00029         lid_list_t *L, **mallocTarget;
00030         /* first check if this device was previously attached to a device attached to us */
00031         for (L = attachedDevices; L != NULL; L = L->next) {
00032             cid_list_t* children;
00033             for (children = L->attachedList;  children != NULL; children = children->next) {
00034                 Rx_log_printf("checkChild:%lx_onLocal:%lx ", children->id, L->id);
00035                 if (children->id == newID) {
00036                     Rx_log_printf("CLEARing_%lx_from_%lx ", children->id, L->id);
00037                     children->id = ID_NONE;
00038                 }
00039             }
00040         }
00041 
00042         L = attachedDevices;
00043         mallocTarget = &attachedDevices->next;
00044         do {
00045             if (L->id == newID) {
00046                 Rx_log_printf("alreadyHave:%lx ", L->id);
00047                 //return false;
00048                 return true; /* return true: notify upstream of moved device */
00049             } else if (L->id == ID_NONE) {
00050                 Rx_log_printf("replaceCleared ");
00051                 L->id = newID;
00052                 return true; /* return true: notify upstream of moved device */
00053             }
00054             mallocTarget = &L->next;
00055             L = L->next;
00056         } while (L != NULL);
00057         *mallocTarget = (lid_list_t*)malloc(sizeof(lid_list_t));
00058         L = *mallocTarget;
00059         L->id = newID;
00060         L->attachedList = NULL;
00061         L->next = NULL;
00062         Rx_log_printf("addedToList:%lx ", L->id);
00063         return true;
00064     }
00065 }
00066 
00067 static void add_new_downstream_attached(uint32_t attachedTo, uint32_t newID)
00068 {
00069     lid_list_t* L;
00070     /* first find if this device already exists anywhere, and remove/clear it */
00071     for (L = attachedDevices; L != NULL; L = L->next) {
00072         cid_list_t* children;
00073         if (L->id == newID) {
00074             L->id = ID_NONE;
00075         }
00076         if (L->attachedList == NULL)
00077             continue;
00078         for (children = L->attachedList;  children != NULL; children = children->next) {
00079             if (children->id == newID) {
00080 #ifdef GATEWAY
00081                 if (L->id != attachedTo) {
00082                     /* notify downstream */
00083                     downRemove.destID = L->id;
00084                     downRemove.removeID = newID;
00085                 }
00086 #endif /* GATEWAY */
00087                 children->id = ID_NONE;
00088             }
00089         }
00090     }
00091 
00092     /* add */
00093     for (L = attachedDevices; L != NULL; L = L->next) {
00094         if (L->id == attachedTo) {
00095             cid_list_t* child;
00096             if (L->attachedList == NULL) { // first added child
00097                 L->attachedList = (cid_list_t*)malloc(sizeof(cid_list_t));
00098                 L->attachedList->id = newID;
00099                 L->attachedList->next = NULL;
00100                 return;
00101             }
00102             /* first check for vacated slot */
00103             for (child = L->attachedList; child != NULL; child = child->next) {
00104                 if (child->id == ID_NONE) {
00105                     child->id = newID;
00106                     return;
00107                 } else if (child->next == NULL)
00108                     break;  // next pointer available to malloc
00109             }
00110             child->next = (cid_list_t*)malloc(sizeof(cid_list_t));
00111             child = child->next;
00112             child->id = newID;
00113             child->next = NULL;
00114             return;
00115         }
00116     }
00117 } // ..add_new_downstream_attached()
00118 
00119 
00120 void downstream_ans_rxDoneCB(float rssi, float snr, uint8_t* Idx, uint32_t sendingID, uint8_t cmd)
00121 {
00122     if (reqFlags.bits.currentOp == CMD_USER_PAYLOAD_DN_REQ) {
00123         reqFlags.bits.currentOp = CMD_UNUSED;
00124     } else if (reqFlags.bits.currentOp == CMD_REMOVE_DEVICE_REQ) {
00125         downRemove.destID = ID_NONE;    // removal request complete
00126         reqFlags.bits.currentOp = CMD_UNUSED;
00127     } else if (reqFlags.bits.currentOp == CMD_DOWNSTREAM_NOT_RESPONDING) {
00128         reqFlags.bits.currentOp = CMD_UNUSED;
00129     }
00130 }
00131 
00132 void discovery_tx_end()
00133 {
00134     flags.discoverAnswering = 0;
00135     start_periodic_rxing(0x90);
00136 }
00137 
00138 #ifdef GATEWAY
00139 void downstream_req_rxDoneCB(float rssi, float snr, uint8_t* Idx, uint32_t sendingID, uint8_t cmd, upInfo_t* up)
00140 #else
00141 void downstream_req_rxDoneCB(float rssi, float snr, uint8_t* Idx, uint32_t sendingID, uint8_t cmd)
00142 #endif
00143 {
00144 
00145     if (cmd == CMD_DISCOVERY_REQ) {
00146         unsigned toms, rnd;
00147         int8_t sq;
00148 
00149         Radio::Standby();
00150         reqFlags.bits.currentOp = CMD_DISCOVERY_ANS;
00151         
00152         txBuf[txBuf_idx++] = CMD_DISCOVERY_ANS;
00153         sq = rssi + snr;
00154         txBuf[txBuf_idx++] = sq;
00155         txBuf[txBuf_idx++] = hops_from_gateway;
00156 
00157         /* schedule transmit to occur randomly, twice */
00158         flags.firstDiscoverAns = 1;
00159         flags.discoverAnswering = 1;
00160         tx_dest_id = sendingID;     // discovery req -> ans
00161         setPreambleSize(false, 1); // sending discovery answer
00162         rnd = Radio::Random() % N_HALF_DISCOVERY_ANS;
00163         queue.call_in((discovery_ans_time_step_us * rnd) / 1000, txBuf_send, false);
00164         toms = discovery_ans_time_total_us / 1000;
00165         queue.call_in(toms, discovery_tx_end);
00166     } else if (cmd == CMD_ATTACH_REQ) {
00167         Radio::Standby();
00168         reqFlags.bits.txAns = ANSWER_OK;
00169 
00170 #ifndef GATEWAY
00171         if (sendingID == attUp.id) {
00172             /* upstream device restarted or re-connected  */
00173             init_attached_upstream();
00174             hops_from_gateway = HFG_UNATTACHED;
00175         }
00176 #endif /* GATEWAY */
00177 
00178         /* add sending_ID to list of attached devices */
00179         if (list_add_local_device(sendingID)) {
00180             /* device is new: if hfg > 0: notify upstream of new device upon txdone of CMD_ATTACH_ANS sent downstream */
00181 #ifndef GATEWAY
00182             id_newDeviceNotification = sendingID;
00183 #endif /* GATEWAY */
00184         }
00185 
00186     } else if (cmd == CMD_NEW_DEVICE_ATTACHED_REQ) { // rxDone callback
00187         uint32_t new_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
00188         *Idx += 4;
00189         /* new device not attached directly to me, but to a downstream device attached to me */
00190         add_new_downstream_attached(sendingID, new_id);
00191 
00192         /* ack sent first downstream, then (if we;re not a gateway) newDeviceNotification sent upstream */
00193 
00194 #ifdef GATEWAY
00195         reqFlags.bits.txAns = ANSWER_OK;
00196 #else
00197         if (id_newDeviceNotification == ID_NONE) {
00198             reqFlags.bits.txAns = ANSWER_OK;
00199             id_newDeviceNotification = new_id;
00200         } else
00201             reqFlags.bits.txAns = ANSWER_BUSY;
00202 #endif /* !GATEWAY */
00203     } else if (cmd == CMD_USER_PAYLOAD_UP_REQ) { // rxDone callback, pkt from downstream
00204         uint8_t len;
00205         uint32_t originating_src_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
00206         *Idx += 4;
00207         len = Radio::radio.rx_buf[*Idx];
00208         (*Idx)++;
00209 #ifdef GATEWAY
00210         //gateway_uplink(len, originating_src_id, &Radio::radio.rx_buf[*Idx]);
00211         up->rxBufIdx = *Idx;
00212         up->originating_src_id = originating_src_id;
00213         up->len = len;
00214         reqFlags.bits.txAns = ANSWER_OK;
00215 #else
00216         if (fwd.len == -1) {
00217             fwd.len = len;
00218             fwd.B_id = originating_src_id;
00219             fwd.tx_dest_id = attUp.id;
00220             memcpy(fwd.buf, &Radio::radio.rx_buf[*Idx], len);
00221             reqFlags.bits.currentOp = CMD_USER_PAYLOAD_UP_REQ;   // this is uplink
00222             reqFlags.bits.txAns = ANSWER_OK;
00223             // txBuf_send() (for forwarding) will be called after ANS sent
00224         } else
00225             reqFlags.bits.txAns = ANSWER_BUSY;
00226 
00227 #endif
00228         (*Idx) += len;
00229     } else if (cmd == CMD_DOWNSTREAM_NOT_RESPONDING) { // rxDone callback, pkt from downstream
00230 #ifndef GATEWAY
00231         uint32_t reporting_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
00232 #endif /* !reporting_id */
00233         *Idx += 4;
00234 #ifndef GATEWAY
00235         uint32_t device_not_respoding_id = getu32FromBuf(&Radio::radio.rx_buf[*Idx]);
00236 #endif /* !reporting_id */
00237         *Idx += 4;
00238 #ifdef GATEWAY
00239         reqFlags.bits.txAns = ANSWER_OK;
00240 #else
00241         if (notResponding.reporting_id == ID_NONE) {
00242             reqFlags.bits.currentOp = CMD_DOWNSTREAM_NOT_RESPONDING; 
00243             notResponding.reporting_id = reporting_id;
00244             notResponding.device_not_respoding_id = device_not_respoding_id;
00245             reqFlags.bits.txAns = ANSWER_OK;
00246         } else
00247             reqFlags.bits.txAns = ANSWER_BUSY;
00248 #endif /* !GATEWAY */
00249     }
00250 
00251 } // ..downstream_req_rxDoneCB()
00252