Display_Avr_3/hdlc/hdlc.h
2023-06-14 15:36:47 +03:00

168 lines
4.4 KiB
C

#ifndef HDLC_H_
#define HDLC_H_
#include <stdint.h>
#include <string.h>
#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_ */