#include <stdint.h>
#include "main.h"
#include "uart_DMX.h"
#include "nrf_drv_uart.h"
#include "main.h"

#include "app_error.h"
#include "nrf_log.h"
#include "app_util_platform.h"


/* DMX512 Tripple buffering */
struct DMX512 DMX512_buffers = {
	.buffer_0 = {0},
	.buffer_1 = {0},
	.buffer_2 = {0},
	/* DMX512 Buffers pointers */
	.read = DMX512_buffers.buffer_0,
	.read_prev = DMX512_buffers.buffer_1,
	.write = DMX512_buffers.buffer_1,
	.write_prev = DMX512_buffers.buffer_2,
};
/* Count received DMX512 data bytes in each frame */
uint16_t DMX_received_bytes = 0;
uint16_t DMX512_write_counter = 0;
uint16_t size = sizeof(DMX512_buffers.buffer_0)/sizeof(DMX512_buffers.buffer_0[0]);

/* Create UART instance */
static nrf_drv_uart_t app_uart_inst = NRF_DRV_UART_INSTANCE(APP_UART_DRIVER_INSTANCE);

void uart_handler(nrf_drv_uart_event_t * p_event, void* p_context)
{
	switch (p_event->type)
	{
		case NRF_DRV_UART_EVT_RX_DONE:
			if((DMX512_write_counter + UART_RX_BUF_SIZE) <= (sizeof(DMX512_buffers.buffer_0)/sizeof(DMX512_buffers.buffer_0[0])))
			{
				nrf_drv_uart_rx(&app_uart_inst, DMX512_buffers.write + DMX512_write_counter, UART_RX_BUF_SIZE);
				/* Increment write buffer pointer */
				DMX_received_bytes += p_event->data.rxtx.bytes;
				DMX512_write_counter += UART_RX_BUF_SIZE;
			}else
			{
				nrf_uarte_task_trigger(app_uart_inst.reg.p_uarte, NRF_UARTE_TASK_FLUSHRX);
			}
			break;

		case NRF_DRV_UART_EVT_ERROR:
			if((p_event->data.error.error_mask & UART_ERRORSRC_BREAK_Msk) == UART_ERRORSRC_BREAK_Msk)
			{
				nrf_uarte_task_trigger(app_uart_inst.reg.p_uarte, NRF_UARTE_TASK_FLUSHRX);
				
				/* Switch buffers */
				/* Write new data */
				uint8_t * pointer = DMX512_buffers.write_prev;
				if(DMX512_buffers.write_prev == DMX512_buffers.read)
				{
					DMX512_buffers.write_prev = DMX512_buffers.write;
					DMX512_buffers.write = DMX512_buffers.read_prev;
				}else
				{
					DMX512_buffers.write_prev = DMX512_buffers.write;
					DMX512_buffers.write = pointer;
				}

				DMX_received_bytes += p_event->data.rxtx.bytes;
				DMX512_write_counter = 0;
				nrf_drv_uart_rx(&app_uart_inst, DMX512_buffers.write, UART_RX_BUF_SIZE);
				/* Increment write buffer pointer */
				DMX512_write_counter += UART_RX_BUF_SIZE;

				nrf_drv_uart_rx(&app_uart_inst, DMX512_buffers.write+DMX512_write_counter, UART_RX_BUF_SIZE);
				/* Increment write buffer pointer */
				DMX512_write_counter += UART_RX_BUF_SIZE;

				DMX_received_bytes = 0;
			}else
			{
				
			}
			break;

		case NRF_DRV_UART_EVT_TX_DONE:
			// Get next byte from FIFO.
//			if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS)
//			{
//				(void)nrf_drv_uart_tx(&app_uart_inst, tx_buffer, 1);
//			}
//			else
//			{
//				// Last byte from FIFO transmitted, notify the application.
//				app_uart_event.evt_type = APP_UART_TX_EMPTY;
//				m_event_handler(&app_uart_event);
//			}
			break;

		default:
			break;
	}
}

void init_UART(uint8_t UART_DMX, bool UART_TX_EXT)
{
	uint32_t err_code = 0;

	nrf_drv_uart_config_t config = {
		.pseltxd = (UART_DMX) ? 11 : 13,
		.pselrxd = (UART_TX_EXT) ? 15 :((UART_DMX) ? 14 : 12),
		.pselcts = 0,
		.pselrts = 0,
		.hwfc = NRF_UART_HWFC_DISABLED,
		.parity = NRF_UART_PARITY_EXCLUDED,
		.baudrate = NRF_UART_BAUDRATE_250000,
		.interrupt_priority = APP_IRQ_PRIORITY_LOWEST,
		.use_easy_dma = true,
	};

	err_code = nrf_drv_uart_init(&app_uart_inst, &config, uart_handler);
	APP_ERROR_CHECK(err_code);

	/* Init first transfer */
	nrf_drv_uart_rx(&app_uart_inst, DMX512_buffers.write, UART_RX_BUF_SIZE);
	/* Increment write buffer pointer */
	DMX512_write_counter += UART_RX_BUF_SIZE;
	/* Prepare next transfer */
	nrf_drv_uart_rx(&app_uart_inst, DMX512_buffers.write + DMX512_write_counter, UART_RX_BUF_SIZE);
	/* Increment write buffer pointer */
	DMX512_write_counter += UART_RX_BUF_SIZE;
}
