/*
Copyright (c) 2015, Dust Networks. All rights reserved.

Port of the uart module to the ADuCM363.


\license See attached DN_LICENSE.txt.
*/

#include "dn_uart.h"

#include "../common.h"
#include "../gpio.h"
#include <drivers/uart/adi_uart.h>
#include <drivers/xint/adi_xint.h>

//============================ defines ========================================

#define UART_RX_BUFSIZE 256  // RX buffer size - must be 2^N
#define UART_TX_BUFSIZE 256  // TX buffer size - must be 2^N

//==== interrupt info
#define API_IRQ_PIN        ADI_XINT_EVENT_INT2
#define API_IRQ_POLARITY   ADI_XINT_IRQ_RISING_EDGE

//============================ typedef ========================================

typedef struct
{
    //==== TX
    uint8_t              txBuf[UART_TX_BUFSIZE];
    uint8_t              txBufFill;

    //==== RX
    dn_uart_rxByte_cbt   rxByte_cb;
    uint8_t              rxBuf[UART_RX_BUFSIZE];
} dn_uart_vars_t;

//=========================== variables =======================================

dn_uart_vars_t       dn_uart_vars;
ADI_UART_HANDLE      LTC5800_UART;
uint8_t              LTC5800_UART_DevMem[ADI_UART_BIDIR_MEMORY_SIZE];
static IRQn_Type     LTC5800_IRQ = UART0_EVT_IRQn;
static IRQn_Type     SYSWAKE2_IRQ = XINT_EVT2_IRQn;

//=========================== prototypes ======================================

void         dn_uart_rxByte(void *pCBParam, uint32_t Event, void *pArg);
void         dn_uart_rxPacket(void *pCBParam, uint32_t Event, void *pArg);

//=========================== public ==========================================

void dn_uart_init(dn_uart_rxByte_cbt rxByte_cb)
{
    // clear local variables
    memset(&dn_uart_vars,    0, sizeof(dn_uart_vars));

    // store call back function
    dn_uart_vars.rxByte_cb = rxByte_cb;
	
	  // flow control
	  gpio_moteRxRts_Inactive(); // we are not using flow control for now
    gpio_moteTxCts_Active();   // these are recommended states

    // init UART device
    adi_uart_Open(
        0, // UART0
        ADI_UART_DIR_BIDIRECTION,
        LTC5800_UART_DevMem,
        ADI_UART_BIDIR_MEMORY_SIZE,
        &LTC5800_UART
    );

    // register callback for RX byte oriented channel
    adi_uart_RegisterCallback(LTC5800_UART, dn_uart_rxByte, &LTC5800_IRQ);
	
	  // TODO new callback for whole packed received event
	  adi_xint_RegisterCallback(API_IRQ_PIN, dn_uart_rxPacket, &SYSWAKE2_IRQ);
   // adi_xint_EnableIRQ(API_IRQ_PIN, API_IRQ_POLARITY);

    adi_uart_SubmitRxBuffer(
        LTC5800_UART,
        dn_uart_vars.rxBuf,
        1,//sizeof(dn_uart_vars.rxBuf),
        false
    );

    NVIC_SetPriority(UART0_EVT_IRQn, 1);    // High priority
}

void dn_uart_txByte(uint8_t byte)
{
    dn_uart_vars.txBuf[dn_uart_vars.txBufFill++] = byte;
    dn_uart_vars.txBufFill %= UART_TX_BUFSIZE;   // Index roll over
}

void dn_uart_txFlush()
{
		// Init UART TX DMA transfer
    adi_uart_SubmitTxBuffer(
        LTC5800_UART,
        dn_uart_vars.txBuf,
        dn_uart_vars.txBufFill,
        true                     // DMA transfer
    );
}

void dn_uart_rxByte (            /*!< Callback function pointer */
    void      *pCBParam,         /*!< Client supplied callback param */
    uint32_t   Event,            /*!< Event ID specific to the Driver/Service */
    void      *pArg)             /*!< Pointer to the event specific argument */
{
    uint8_t *rxBuf;

    switch (Event)
    {
    case ADI_UART_EVENT_RX_BUFFER_PROCESSED:

        rxBuf = (uint8_t*) pArg;

        dn_uart_vars.rxByte_cb(rxBuf[0]);

        adi_uart_SubmitRxBuffer(
            LTC5800_UART,
            dn_uart_vars.rxBuf,
            1,//sizeof(dn_uart_vars.rxBuf),
            false
        );
        break;

		case ADI_UART_EVENT_NO_RX_BUFFER_EVENT:	
				break;
    case ADI_UART_EVENT_TX_BUFFER_PROCESSED:
			  dn_uart_vars.txBufFill = 0;
        break;
    
    case ADI_UART_EVENT_AUTOBAUD_COMPLETE:
    case ADI_UART_EVENT_HW_ERROR_DETECTED:
    case ADI_UART_EVENT_AUTOBAUD_ERROR_DETECTED:
    default:
        ERR_MSG("uart0 error\n");
        break;
    };
}

void         dn_uart_rxPacket(void *pCBParam, uint32_t Event, void *pArg)
{
	DEBUG_MSG("Packet received\n");
}
