SmartMesh QSL for STM32F4 version

Fork of COG-AD4050_QSL by APS Lab

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dn_serial_mt.c Source File

dn_serial_mt.c

00001 /*
00002 Copyright (c) 2014, Dust Networks. All rights reserved.
00003 
00004 HDLC library.
00005 
00006 \license See attached DN_LICENSE.txt.
00007 */
00008 
00009 #include "dn_serial_mt.h"
00010 #include "dn_hdlc.h"
00011 
00012 //=========================== variables =======================================
00013 
00014 typedef struct {
00015    // packet IDs
00016    uint8_t                   txPacketId;
00017    uint8_t                   rxPacketId;
00018    // reply callback
00019    uint8_t                   replyCmdId;
00020    dn_serial_reply_cbt       replyCb;
00021    // request callback
00022    dn_serial_request_cbt     requestCb;
00023 } dn_serial_mt_vars_t;
00024 
00025 dn_serial_mt_vars_t dn_serial_mt_vars;
00026 
00027 //=========================== prototype =======================================
00028 
00029 void dn_serial_mt_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen);
00030 void dn_serial_mt_dispatch_response(uint8_t cmdId, uint8_t *payload, uint8_t length);
00031 void dn_serial_sendReply(uint8_t cmdId, uint8_t rc, uint8_t *payload, uint8_t length);
00032 
00033 //=========================== public ==========================================
00034 
00035 /**
00036 \brief Setting up the instance.
00037 */
00038 void dn_serial_mt_init(dn_serial_request_cbt requestCb) {
00039    // reset local variables
00040    memset(&dn_serial_mt_vars, 0, sizeof(dn_serial_mt_vars));
00041    
00042    // initialize variables
00043    dn_serial_mt_vars.txPacketId = DN_SERIAL_PACKETID_NOTSET;
00044    dn_serial_mt_vars.rxPacketId = DN_SERIAL_PACKETID_NOTSET;
00045    dn_serial_mt_vars.requestCb  = requestCb;
00046    
00047    // initialize the HDLC module
00048    dn_hdlc_init(dn_serial_mt_rxHdlcFrame);
00049 }
00050 
00051 dn_err_t dn_serial_mt_sendRequest(uint8_t cmdId,  uint8_t extraFlags, uint8_t* payload, uint8_t length, dn_serial_reply_cbt replyCb) {
00052    uint8_t i;
00053    uint8_t flags;
00054    
00055    // register reply callback
00056    dn_serial_mt_vars.replyCmdId      = cmdId;
00057    dn_serial_mt_vars.replyCb         = replyCb;
00058    
00059    // calculate the flags
00060    flags      = 0;
00061    if (dn_serial_mt_vars.txPacketId==DN_SERIAL_PACKETID_NOTSET) {
00062       dn_serial_mt_vars.txPacketId = 0x00;
00063       flags  |= 0x01<<3;                          // sync bit
00064       flags  |= dn_serial_mt_vars.txPacketId<<1;     // txPacketId
00065    } else {
00066       flags  |= dn_serial_mt_vars.txPacketId<<1;     // txPacketId
00067    }
00068    flags     |= extraFlags;
00069    
00070    // send the frame over serial
00071    dn_hdlc_outputOpen();
00072    dn_hdlc_outputWrite(cmdId);                   // cmdId
00073    dn_hdlc_outputWrite(length);                  // length
00074    dn_hdlc_outputWrite(flags);                   // flags
00075    for (i=0; i<length; i++) {                    // payload
00076       dn_hdlc_outputWrite(payload[i]);
00077    }
00078    dn_hdlc_outputClose();
00079    
00080    // toggle the txPacketId
00081    if (dn_serial_mt_vars.txPacketId==0x00) {
00082       dn_serial_mt_vars.txPacketId   = 0x01;
00083    } else {
00084       dn_serial_mt_vars.txPacketId   = 0x00;
00085    }
00086    
00087    return DN_ERR_NONE;
00088 }
00089 
00090 //=========================== private =========================================
00091 
00092 void dn_serial_mt_rxHdlcFrame(uint8_t* rxFrame, uint8_t rxFrameLen) {
00093    // fields in the serial API header
00094    uint8_t cmdId;
00095    uint8_t length;
00096    uint8_t flags;
00097    uint8_t isResponse;
00098    uint8_t packetId;
00099    uint8_t isSync;
00100    // misc
00101    uint8_t isRepeatId;
00102    
00103    // assert length is OK
00104    if (rxFrameLen<3) {
00105       return;
00106    }
00107    
00108    // parse header
00109    cmdId      = rxFrame[0];
00110    length     = rxFrame[1];
00111    flags      = rxFrame[2];
00112    isResponse = ((flags & DN_SERIAL_API_MASK_RESPONSE)!=0);
00113    packetId   = ((flags & DN_SERIAL_API_MASK_PACKETID)!=0);
00114    isSync     = ((flags & DN_SERIAL_API_MASK_SYNC)!=0);
00115    
00116    // check if valid packet ID
00117    if (isResponse) {
00118       // dispatch
00119       
00120       dn_serial_mt_dispatch_response(cmdId,&rxFrame[3],length);
00121    } else {
00122       if (isSync || packetId!=dn_serial_mt_vars.rxPacketId) {
00123          isRepeatId          = FALSE;
00124          dn_serial_mt_vars.rxPacketId = packetId;
00125       } else {
00126          isRepeatId          = TRUE;
00127       }
00128       
00129       // ACK
00130       dn_serial_sendReply(cmdId,DN_SERIAL_RC_OK,NULL,0);
00131       
00132       // dispatch
00133       if (isRepeatId==FALSE && length>0 && dn_serial_mt_vars.requestCb!=NULL) {
00134          dn_serial_mt_vars.requestCb(cmdId,flags,&rxFrame[3],length);
00135       }
00136    }
00137 }
00138 
00139 /**
00140 \note Not public, only used for sending ACK.
00141 */
00142 void dn_serial_sendReply(uint8_t cmdId, uint8_t rc, uint8_t *payload, uint8_t length) {
00143    uint8_t i;
00144    
00145    dn_hdlc_outputOpen();
00146    dn_hdlc_outputWrite(cmdId);                                                    // cmdId
00147    dn_hdlc_outputWrite(length);                                                   // length
00148    dn_hdlc_outputWrite(DN_SERIAL_API_MASK_RESPONSE | (dn_serial_mt_vars.rxPacketId<<1));   // flags
00149    dn_hdlc_outputWrite(rc);                                                       // rc
00150    for (i=0; i<length; i++) {                                                  // payload
00151       dn_hdlc_outputWrite(payload[i]);
00152    }
00153    dn_hdlc_outputClose();
00154 }
00155 
00156 void dn_serial_mt_dispatch_response(uint8_t cmdId, uint8_t* payload, uint8_t length) {
00157    uint8_t rc;
00158    
00159    rc = payload[0];
00160    if (cmdId==dn_serial_mt_vars.replyCmdId && dn_serial_mt_vars.replyCb!=NULL) {
00161       
00162       // call the callback
00163       (dn_serial_mt_vars.replyCb)(cmdId,rc,&payload[1],length);
00164       
00165       // reset
00166       dn_serial_mt_vars.replyCmdId   = 0x00;
00167       dn_serial_mt_vars.replyCb      = NULL;
00168    }
00169 }
00170 
00171 //=========================== helpers =========================================
00172