SmartMesh QSL for STM32F4 version

Fork of COG-AD4050_QSL by APS Lab

Revision:
0:8ca1e814a851
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sm_clib/dn_serial_mt.c	Wed May 02 09:26:10 2018 +0000
@@ -0,0 +1,172 @@
+/*
+Copyright (c) 2014, Dust Networks. All rights reserved.
+
+HDLC library.
+
+\license See attached DN_LICENSE.txt.
+*/
+
+#include "dn_serial_mt.h"
+#include "dn_hdlc.h"
+
+//=========================== variables =======================================
+
+typedef struct {
+   // packet IDs
+   uint8_t                   txPacketId;
+   uint8_t                   rxPacketId;
+   // reply callback
+   uint8_t                   replyCmdId;
+   dn_serial_reply_cbt       replyCb;
+   // request callback
+   dn_serial_request_cbt     requestCb;
+} dn_serial_mt_vars_t;
+
+dn_serial_mt_vars_t dn_serial_mt_vars;
+
+//=========================== prototype =======================================
+
+void dn_serial_mt_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen);
+void dn_serial_mt_dispatch_response(uint8_t cmdId, uint8_t *payload, uint8_t length);
+void dn_serial_sendReply(uint8_t cmdId, uint8_t rc, uint8_t *payload, uint8_t length);
+
+//=========================== public ==========================================
+
+/**
+\brief Setting up the instance.
+*/
+void dn_serial_mt_init(dn_serial_request_cbt requestCb) {
+   // reset local variables
+   memset(&dn_serial_mt_vars, 0, sizeof(dn_serial_mt_vars));
+   
+   // initialize variables
+   dn_serial_mt_vars.txPacketId = DN_SERIAL_PACKETID_NOTSET;
+   dn_serial_mt_vars.rxPacketId = DN_SERIAL_PACKETID_NOTSET;
+   dn_serial_mt_vars.requestCb  = requestCb;
+   
+   // initialize the HDLC module
+   dn_hdlc_init(dn_serial_mt_rxHdlcFrame);
+}
+
+dn_err_t dn_serial_mt_sendRequest(uint8_t cmdId,  uint8_t extraFlags, uint8_t* payload, uint8_t length, dn_serial_reply_cbt replyCb) {
+   uint8_t i;
+   uint8_t flags;
+   
+   // register reply callback
+   dn_serial_mt_vars.replyCmdId      = cmdId;
+   dn_serial_mt_vars.replyCb         = replyCb;
+   
+   // calculate the flags
+   flags      = 0;
+   if (dn_serial_mt_vars.txPacketId==DN_SERIAL_PACKETID_NOTSET) {
+      dn_serial_mt_vars.txPacketId = 0x00;
+      flags  |= 0x01<<3;                          // sync bit
+      flags  |= dn_serial_mt_vars.txPacketId<<1;     // txPacketId
+   } else {
+      flags  |= dn_serial_mt_vars.txPacketId<<1;     // txPacketId
+   }
+   flags     |= extraFlags;
+   
+   // send the frame over serial
+   dn_hdlc_outputOpen();
+   dn_hdlc_outputWrite(cmdId);                   // cmdId
+   dn_hdlc_outputWrite(length);                  // length
+   dn_hdlc_outputWrite(flags);                   // flags
+   for (i=0; i<length; i++) {                    // payload
+      dn_hdlc_outputWrite(payload[i]);
+   }
+   dn_hdlc_outputClose();
+   
+   // toggle the txPacketId
+   if (dn_serial_mt_vars.txPacketId==0x00) {
+      dn_serial_mt_vars.txPacketId   = 0x01;
+   } else {
+      dn_serial_mt_vars.txPacketId   = 0x00;
+   }
+   
+   return DN_ERR_NONE;
+}
+
+//=========================== private =========================================
+
+void dn_serial_mt_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen) {
+   // fields in the serial API header
+   uint8_t cmdId;
+   uint8_t length;
+   uint8_t flags;
+   uint8_t isResponse;
+   uint8_t packetId;
+   uint8_t isSync;
+   // misc
+   uint8_t isRepeatId;
+   
+   // assert length is OK
+   if (rxFrameLen<3) {
+      return;
+   }
+   
+   // parse header
+   cmdId      = rxFrame[0];
+   length     = rxFrame[1];
+   flags      = rxFrame[2];
+   isResponse = ((flags & DN_SERIAL_API_MASK_RESPONSE)!=0);
+   packetId   = ((flags & DN_SERIAL_API_MASK_PACKETID)!=0);
+   isSync     = ((flags & DN_SERIAL_API_MASK_SYNC)!=0);
+   
+   // check if valid packet ID
+   if (isResponse) {
+      // dispatch
+      
+      dn_serial_mt_dispatch_response(cmdId,&rxFrame[3],length);
+   } else {
+      if (isSync || packetId!=dn_serial_mt_vars.rxPacketId) {
+         isRepeatId          = FALSE;
+         dn_serial_mt_vars.rxPacketId = packetId;
+      } else {
+         isRepeatId          = TRUE;
+      }
+      
+      // ACK
+      dn_serial_sendReply(cmdId,DN_SERIAL_RC_OK,NULL,0);
+      
+      // dispatch
+      if (isRepeatId==FALSE && length>0 && dn_serial_mt_vars.requestCb!=NULL) {
+         dn_serial_mt_vars.requestCb(cmdId,flags,&rxFrame[3],length);
+      }
+   }
+}
+
+/**
+\note Not public, only used for sending ACK.
+*/
+void dn_serial_sendReply(uint8_t cmdId, uint8_t rc, uint8_t *payload, uint8_t length) {
+   uint8_t i;
+   
+   dn_hdlc_outputOpen();
+   dn_hdlc_outputWrite(cmdId);                                                    // cmdId
+   dn_hdlc_outputWrite(length);                                                   // length
+   dn_hdlc_outputWrite(DN_SERIAL_API_MASK_RESPONSE | (dn_serial_mt_vars.rxPacketId<<1));   // flags
+   dn_hdlc_outputWrite(rc);                                                       // rc
+   for (i=0; i<length; i++) {                                                  // payload
+      dn_hdlc_outputWrite(payload[i]);
+   }
+   dn_hdlc_outputClose();
+}
+
+void dn_serial_mt_dispatch_response(uint8_t cmdId, uint8_t* payload, uint8_t length) {
+   uint8_t rc;
+   
+   rc = payload[0];
+   if (cmdId==dn_serial_mt_vars.replyCmdId && dn_serial_mt_vars.replyCb!=NULL) {
+      
+      // call the callback
+      (dn_serial_mt_vars.replyCb)(cmdId,rc,&payload[1],length);
+      
+      // reset
+      dn_serial_mt_vars.replyCmdId   = 0x00;
+      dn_serial_mt_vars.replyCb      = NULL;
+   }
+}
+
+//=========================== helpers =========================================
+