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

#ifndef USART_HANDLER_H_
#define USART_HANDLER_H_
#include <inttypes.h>
#include <platform/usart_ll.h>
#include <f4ll_cpp/uartbase.h>

#define USART_STATS_DISABLED

namespace f4ll_cpp {

class PacketUart : public UartBase, public CrcScheduler::ICrcCallback
{
public:
	struct Buffer;

	struct IPacketUsartCallback {
		virtual void PacketReceived(void *userParam, Buffer *buffer) = 0;
	};

	struct 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;
	};

	struct Header {
		uint8_t startByte;
		uint8_t serial;
		uint8_t payloadLength;
		uint8_t hash;
	};

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

	struct Buffer {
		Packet packet;
		//transfer area ends here
		volatile uint8_t busy;
		volatile uint8_t error;
		uint16_t requestedLength;
		uint32_t errorInfo;
	};


	typedef void (*pku_packetreceivedcallback_t)(void *userParam, Buffer *Buffer);

	PacketUart(
		USART_TypeDef *uart, DMA_TypeDef *dma, uint32_t stream_rx, uint32_t stream_tx, CrcScheduler *crcScheduler,
		PacketUart::pku_packetreceivedcallback_t packetReceivedCallback, void * packetReceivedCallbackParam);

	uint8_t* GetTxBuffer();

	uint8_t Post(uint8_t const *payload, uint8_t length, uint8_t waitForCrcQueue);
	void SetupReceive();
	void ConsumePacket(uint8_t packetIndex);

	static void HandleRxDmaIrq(void* param) { reinterpret_cast<PacketUart*>(param)->HandleRxDmaIrq(); }
	static void HandleTxDmaIrq(void* param) { reinterpret_cast<PacketUart*>(param)->HandleTxDmaIrq(); }
	static void HandleUsartIrq(void* param) { reinterpret_cast<PacketUart*>(param)->HandleUsartIrq(); }

	uint8_t CheckHeader(struct Packet *packet);

protected:

private:
	void HandleRxDmaIrq();
	void HandleTxDmaIrq();
	void HandleUsartIrq();

	virtual void CrcCalculationCompleted(void*, uint32_t, uint8_t);

	CrcScheduler *m_crcScheduler;
	CrcScheduler::crcslot_t crcSlot;
	CrcScheduler::crctask_t crcTasks[2];

	uint8_t rxSerial;
	uint8_t txSerial;
	Stats stats;
	uint8_t activeRxBuf;
	pku_packetreceivedcallback_t packetReceivedCallback;
	void *packetReceivedCallbackParam;
	Buffer txBuffer;
	Buffer rxBuffers[2];
};

}	//	f4ll_cpp

#endif /* UART_HANDLER_H_ */
