APS Lab
/
STM32F4_SmartMesh_QSL
SmartMesh QSL for STM32F4 version
Fork of COG-AD4050_QSL by
Diff: sm_clib/dn_serial_mt.c
- 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 ========================================= +