/*
 * usart_handler.h
 *
 *  Created on: Sep 16, 2019
 *      Author: abody
 */

#ifndef USART_HANDLER_H_
#define USART_HANDLER_H_
#include <inttypes.h>

#include "dma_helper.h"
#include "crc_handler.h"

struct _usart_status;
typedef struct _usart_status USARTSTATUS;
struct usart_buffer;

typedef void (*PACKETRECEIVEDCALLBACK)(void *userParam, struct usart_buffer *buffer);

void InitUartStatus(
	USARTSTATUS *st, USART_TypeDef *usart, DMA_TypeDef *dma,
	uint32_t stream_rx, uint32_t stream_tx,
	CRCSTATUS *crcStatus, uint8_t rxCrcSlot, uint8_t txCrcSlot,
	PACKETRECEIVEDCALLBACK packetReceivedCallback, void * packetReceivedCallbackParam);

uint8_t* GetTxBuffer(USARTSTATUS *status);

uint8_t PostPacket(USARTSTATUS *status, uint8_t const *payload, uint16_t length, CRCSTATUS *crcStatus);
void SetupReceive(USARTSTATUS *status);
void SetupTransmit(USART_TypeDef *usart, DMA_TypeDef* dma, uint32_t stream, void *buffer, uint32_t length);
void ConsumePacket(USARTSTATUS *status, uint8_t packetIndex, CRCSTATUS *crcStatus);

void HandleUsartRxDmaIrq(USARTSTATUS *status);
void HandleUsartTxDmaIrq(USARTSTATUS *status);
void HandleUsartIrq(USARTSTATUS *status);

/******************************************************************************************
 * 
 * 
 * 
 */
 
struct usart_stats {
	uint32_t overrun;
	uint32_t hdrError;
	uint32_t lastErrHdr;
	uint32_t payloadErrror;
	uint32_t pep1, pep2;
	uint32_t dmaError;
	uint32_t rcvd;
	uint32_t premature_hdr;
	uint32_t premature_payload;
	uint32_t sent;
	uint32_t skiped;
};

typedef struct {
	uint8_t startByte;
	uint8_t serial;
	uint8_t payloadLength;
	uint8_t hash;
} USARTPACKETHEADER;

typedef struct {
	USARTPACKETHEADER	header;
	//!!! should start on word offset !!!
	uint8_t				payload[256+sizeof(uint32_t)];	// extra room for crc32
} __attribute__((aligned)) USARTPACKET;

struct usart_buffer {
	USARTPACKET packet;
	//transfer area ends here
	volatile uint8_t busy;
	volatile uint8_t error;
	uint16_t requestedLength;
	uint32_t errorInfo;
	USARTSTATUS *usartStatus;
};

struct _usart_status {
	USART_TypeDef *usart;
	DMAINFO rxDmaInfo;
	DMAINFO txDmaInfo;
	CRCSTATUS *crcStatus;
	uint8_t rxSerial;
	uint8_t txSerial;
	struct usart_stats stats;
	uint8_t activeRxBuf;
	uint8_t rxCrcSlot;
	uint8_t txCrcSlot;
	PACKETRECEIVEDCALLBACK packetReceivedCallback;
	void *packetReceivedCallbacParam;
	struct usart_buffer txBuffer;
	struct usart_buffer rxBuffers[2];
};

#ifndef USART_STATS_DISABLED
static inline void StatsIncOverrun(struct usart_stats *s) {
	++s->overrun;
}
static inline void StatsIncHdrError(struct usart_stats *s, uint32_t hdr) {
	++s->hdrError;
	s->lastErrHdr = hdr;
}
static inline void StatsIncPayloadError(struct usart_stats *s, uint32_t pep1, uint32_t pep2) {
	++s->payloadErrror;
	s->pep1 = pep1;
	s->pep2 = pep2;
}
static inline void StatsIncDmaError(struct usart_stats *s) {
	++s->dmaError;
}
static inline void StatsIncRcvd(struct usart_stats *s) {
	++s->rcvd;
}
static inline void StatsIncPremature_hdr(struct usart_stats *s) {
	++s->premature_hdr;
}
static inline void StatsIncPremature_payload(struct usart_stats *s) {
	++s->premature_payload;
}
static inline void StatsIncSent(struct usart_stats *s) {
	++s->sent;
}
static inline void StatsAddSkiped(struct usart_stats *s, uint8_t cnt) {
	s->skiped += s->rcvd > 2 ? cnt : 0;
}

#else	//	USART_STATS_DISABLED
#define StatsIncOverrun(x)
#define StatsIncHdrError(x,y)
#define StatsIncPayloadError(x,y,z)
#define StatsIncDmaError(x)
#define StatsIncRcvd(x)
#define StatsIncPremature_hdr(x)
#define StatsIncPremature_payload(x)
#define StatsIncSent(x)
#define StatsAddSkiped(x)
#endif	//	USART_STATS_DISABLED

#endif /* UART_HANDLER_H_ */
