#ifndef HDLC_H_ #define HDLC_H_ #include #include #include "crc.h" #define HDLC_TEMPLATE \ int16_t (*readByte)(void), \ void (*writeByte)(uint8_t data), \ uint16_t rxBuffLen, \ struct CRC #define HDLC_TEMPLATETYPE \ readByte, \ writeByte, \ rxBuffLen, \ CRC struct HDLC { const uint8_t DATAINVBIT; const uint8_t DATASTART; const uint8_t DATAESCAPE; const uint8_t* DATAESCAPELIST; int16_t (*readByte)(void); void (*writeByte)(uint8_t data); uint16_t rxBuffLen; CRC16_CCITT rxcrc; const uint16_t RXBFLEN; int8_t status; uint16_t len; CRC16_CCITT txcrc; uint8_t data[]; }; void escapeAndWriteByte(struct HDLC* hdlc, uint8_t data) { const uint8_t* escapeList = hdlc->DATAESCAPELIST; while (*escapeList != 0) { if (data == *escapeList) { hdlc->writeByte(hdlc->DATAESCAPE); data ^= hdlc->DATAINVBIT; break; } escapeList++; } hdlc->writeByte(data); } #define ESCAPED (-1) #define RECEIVING 0 #define OK 1 #define CRCERR 2 void HDLC_init(struct HDLC* hdlc){ hdlc->len = 0U; hdlc->status = RECEIVING; crc_init(&hdlc->rxcrc); };; void HDLC_transmitStart(struct HDLC *hdlc); void HDLC_transmitStart(struct HDLC *hdlc) { hdlc->writeByte(hdlc->DATASTART); crc_init(&hdlc->txcrc); } void HDLC_transmitByte(struct HDLC* hdlc, uint8_t data); void HDLC_transmitByte(struct HDLC* hdlc, uint8_t data){ escapeAndWriteByte(hdlc, data); crc_update(&hdlc->txcrc, data); } void HDLC_transmitBytes(struct HDLC* hdlc, const void *vdata, uint16_t len); void HDLC_transmitBytes(struct HDLC* hdlc, const void *vdata, uint16_t len){ const uint8_t* data = (const uint8_t*)vdata; while(len) { HDLC_transmitByte(hdlc, *data); ++data; --len; } } void HDLC_transmitEnd(struct HDLC *hdlc); void HDLC_transmitEnd(struct HDLC *hdlc){ crc_final(&hdlc->txcrc); for(int i = 0; i < hdlc->txcrc.size; ++i) escapeAndWriteByte(hdlc, hdlc->txcrc.crc); hdlc->writeByte(hdlc->DATASTART); } void HDLC_transmitBlock(struct HDLC* hdlc, const void* vdata, uint16_t len){ HDLC_transmitStart(hdlc); HDLC_transmitBytes(hdlc, vdata, len); HDLC_transmitEnd(hdlc); } uint16_t HDLC_receive(struct HDLC* hdlc); uint16_t HDLC_receive(struct HDLC* hdlc){ int16_t c = hdlc->readByte(); if(c == -1) return 0U; if(hdlc->status >= OK) HDLC_init(hdlc); uint16_t retv = 0U; if(c == hdlc->DATASTART) { if(hdlc->status == RECEIVING && hdlc->len != 0U) { if(crc_good(&hdlc->rxcrc)) { hdlc->status = OK; hdlc->len -= hdlc->rxcrc.size; retv = hdlc->len; } else { hdlc->status = CRCERR; } } else { HDLC_init(hdlc); } } else { if(hdlc->status == ESCAPED) { hdlc->status = RECEIVING; c ^= hdlc->DATAINVBIT; crc_update(&hdlc->rxcrc, c); if (hdlc->len < hdlc->RXBFLEN) hdlc->data[hdlc->len] = c; ++hdlc->len; } else if(c != hdlc->DATAESCAPE) { crc_update(&hdlc->rxcrc, c); if(hdlc->len < hdlc->RXBFLEN) hdlc->data[hdlc->len] = c; ++hdlc->len; } else { hdlc->status = ESCAPED; } } return retv; } uint16_t HDLC_copyReceivedMessage(const struct HDLC* hdlc, uint8_t buff[]); uint16_t HDLC_copyReceivedMessage(const struct HDLC* hdlc, uint8_t buff[]){ const uint16_t datalen = (hdlc->len > hdlc->RXBFLEN) ? hdlc->RXBFLEN : hdlc->len; memcpy(buff, hdlc->data, datalen); return datalen; } uint16_t HDLC_copyReceivedMessage2(const struct HDLC* hdlc, uint8_t* buff, uint16_t pos, uint16_t num); #endif /* HDLC_H_ */