/*
 * interrupt.h
 *
 *  Created on: Aug 29, 2019
 *      Author: abody
 */

#ifndef CRC_HANDLER_H_
#define CRC_HANDLER_H_

#include <inttypes.h>

#ifdef HAVE_CONFIG
#include "config.h"
#endif	//	HAVE_CONFIG

#include "f4ll_c/dma_helper.h"

#ifndef CRCTASKCOUNT
#define CRCTASKCOUNT 2
#endif

struct crcslottask_t {
	void     *address;
	uint16_t  wordCount;
	void    (*callback)(void*, uint32_t, uint8_t);
	void     *callbackParam;
};

struct crcslotlistitem_t {
	uint16_t                  count;
	struct crcslotlistitem_t *next;
	struct crcslottask_t     *tasks;
};

struct crcstatus_t {
	DMAINFO	dmaInfo;
	volatile struct crcslotlistitem_t *activeSlot;
	volatile uint8_t activeTask;

	struct crcslotlistitem_t *first;
};

void InitCrcStatus(struct crcstatus_t *status, DMA_TypeDef *dma, uint32_t stream);

uint8_t GetActiveSlot(struct crcslotlistitem_t **slot_out, struct crcstatus_t *status);

static inline uint8_t IsSlotQueued(struct crcslotlistitem_t *slot, uint8_t task) {
	return slot->tasks[task].address != NULL;
}

static inline uint8_t IsSlotActive(struct crcslotlistitem_t *slot, uint8_t task) {
	return slot->tasks[task].callback != NULL || slot->tasks[task].callbackParam != NULL;
}

void AttachCrcTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, struct crcslottask_t *tasks, uint8_t taskCount);

uint8_t EnqueueCrcTask(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task,
		uint8_t *address, uint16_t len, void (*callback)(void*, uint32_t, uint8_t), void* callbackParam);
void WaitCrcResults(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task);
uint32_t ComputeCrc(struct crcstatus_t *status, struct crcslotlistitem_t *slot, uint8_t task, uint8_t *address, uint16_t len);
void ComputeCrcAsync(struct crcstatus_t *status, uint8_t slot,
		uint8_t *address, uint16_t len,
		void (*callback)(void*, uint32_t, uint8_t), void* callbackParam);
void HandleCrcDmaIrq(struct crcstatus_t *status);

#endif /* CRC_HANDLER_H_ */
