/*******************************************************************************
* Project:      Amped'RF Bluetooth
* File name:    GKI_uart.c
* Description:  Uart abstraction layer
*               Note -- This source is for reference only
*
* Copyright (c) 2013 Amped'RF Inc., AR Technology  All rights reserved.
*******************************************************************************/
#include "Common.h"
#include "GKI_lib.h"
#include <string.h>
#include "AT_pvt.h"


// UART Registers
USART_TypeDef * UART[2]={
    ((USART_TypeDef *) USART1_BASE),
    ((USART_TypeDef *) USART2_BASE)
};


#define UartDev         UART[u]             // Uart Base Address
#define MainUartDev     UART[GKI_MainUart]  // Uart Base Address

#define pUart           (&TM_UartDev[u])    // Uart Structure
#define RX              (pUart->Rx)
#define TX              (pUart->Tx)
#define UartPin         (pUart->Pin)
#define RX_LOW_WM       64



#if  defined(STM32F2xx) || defined(STM32F4xx)

u32 UART_RX_DMA_Stream[2]={DMA2_Stream2_BASE, DMA1_Stream5_BASE};
u32 UART_TX_DMA_Stream[2]={DMA2_Stream7_BASE, DMA1_Stream6_BASE};

u8  UART_Channel_IRQn[2]={USART1_IRQn, USART2_IRQn};

#endif





//---------------
//   GLOBALS
//---------------
//#ifdef DEVKIT
extern uint8 HciDmaRxBuf[];
extern uint8 MainDmaRxBuf[];
//#else
//uint8 HciDmaRxBuf[TM_UART_HCI_RX_DMA_SIZE];
//uint8 MainDmaRxBuf[TM_UART_MAIN_RX_DMA_SIZE];
//#endif
void MainUartBufRelease(tBP_Pool *pool);
void HciUartBufRelease(tBP_Pool *pool);



/*******************************************************************************
* Function:     GKI_UartConfigPins
* Description:  Configure UART pins
*******************************************************************************/
void GKI_UartConfigPins(tGKI_Uart u)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_StructInit(&GPIO_InitStructure);

    switch (u) {
    case eTM_MainUart:
        GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Pin     = _MASK(IO_MAIN_RX);
        GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
        GPIO_Init(_BASE(IO_MAIN_RX), &GPIO_InitStructure);
#if defined(STM32F2xx) || defined(STM32F4xx)
        GPIO_PinAFConfig(_BASE(IO_MAIN_TX),  _PIN(IO_MAIN_TX),  GPIO_AF_USART1);
        GPIO_PinAFConfig(_BASE(IO_MAIN_RX),  _PIN(IO_MAIN_RX),  GPIO_AF_USART1);
        GPIO_PinAFConfig(_BASE(IO_MAIN_CTS), _PIN(IO_MAIN_CTS), GPIO_AF_USART1);
        GPIO_PinAFConfig(_BASE(IO_MAIN_RTS), _PIN(IO_MAIN_RTS), GPIO_AF_USART1);
#endif
        GKI_io_Config(IO_MAIN_TX,  GKI_IO_AF_PP);
        GKI_io_Config(IO_MAIN_CTS, GKI_IO_AF_IN);//GKI_IO_IPD);
        GKI_io_Config(IO_MAIN_RTS, GKI_IO_OUT_PP);//GKI_IO_OUT_PP);
        GKI_io_WriteBit(IO_MAIN_RTS, 1);
        GKI_io_WriteBit(IO_MAIN_RTS, 0);
        break;

    case eTM_HciUart:
        GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Pin     = _MASK(IO_HCI_RX);
        GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
#if defined(STM32F2xx) || defined(STM32F4xx)
        GPIO_PinAFConfig(_BASE(IO_HCI_TX),  _PIN(IO_HCI_TX),  GPIO_AF_USART2);
        GPIO_PinAFConfig(_BASE(IO_HCI_RX),  _PIN(IO_HCI_RX),  GPIO_AF_USART2);
        GPIO_PinAFConfig(_BASE(IO_HCI_CTS), _PIN(IO_HCI_CTS), GPIO_AF_USART2);
        GPIO_PinAFConfig(_BASE(IO_HCI_RTS), _PIN(IO_HCI_RTS), GPIO_AF_USART2);
#endif
        GKI_io_Config(IO_HCI_RX,  GKI_IO_AF_IN);
        GKI_io_Config(IO_HCI_TX,  GKI_IO_AF_PP);
#if !defined(BT24)
        GKI_io_Config(IO_HCI_CTS, GKI_IO_AF_IN);    //GKI_IO_IN_FLOATING);

#endif
        GKI_io_Config(IO_HCI_RTS, GKI_IO_OUT_PP);   // GKI_io_Config(IO_HCI_RTS, GKI_IO_AF_PP);
        GKI_io_WriteBit(IO_HCI_RTS, 1);
        GKI_io_WriteBit(IO_HCI_RTS, 0);
        break;
    }
}



/*******************************************************************************
* Function:     GKI_UartConfig
* Description:  Configure UART
*******************************************************************************/
tGKI_IoStatus GKI_UartConfig(tGKI_Uart u, tUartConf * pConfigStruct)
{
    // Sanity check for parameters - Return if not OK
    if (!TM_SetupUart(u,
        pConfigStruct->DataBits,
        pConfigStruct->StopBits,
        pConfigStruct->Parity,
        pConfigStruct->Baudrate))
    {
        return eTM_UnacceptableParamatersSetting;
    }

    // Parameters are OK - Accept them
    memcpy(&pUart->Config, &pConfigStruct, sizeof(tUartConf));
    pUart->Config.DataBits   = pConfigStruct->DataBits;
    pUart->Config.StopBits   = pConfigStruct->StopBits;
    pUart->Config.Parity     = pConfigStruct->Parity;
    pUart->Config.Baudrate   = pConfigStruct->Baudrate;
    pUart->Config.TimeoutEnb = pConfigStruct->TimeoutEnb;

    return eTM_Success;
}



/*******************************************************************************
* Function:     GKI_uart_SetBaudrate -- was TM_SetBaud
* Description:  Change baudrate
*******************************************************************************/
void GKI_uart_SetBaudrate(u16 u, u32 baudrate)
{
#if defined(STM32F2xx) || defined(STM32F4xx)

    USART_TypeDef* USARTx = UART[u];
    uint32_t tmpreg = 0x00, apbclock = 0x00;
    uint32_t integerdivider = 0x00;
    uint32_t fractionaldivider = 0x00;
    RCC_ClocksTypeDef RCC_ClocksStatus;

    if (u==eTM_HciUart) {
        char msg[32];
        sprintf(msg, "SetBaud(HCI,%d)", baudrate);
        AddFootprintText(msg);
    }

    /* Configure the USART Baud Rate */
    RCC_GetClocksFreq(&RCC_ClocksStatus);

    if ((USARTx == USART1) || (USARTx == USART6)) {
        apbclock = RCC_ClocksStatus.PCLK2_Frequency;
    }
    else {
        apbclock = RCC_ClocksStatus.PCLK1_Frequency;
    }

    /* Determine the integer part */
    if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
    {
        /* Integer part computing in case Oversampling mode is 8 Samples */
        integerdivider = ((25 * apbclock) / (2 * (baudrate)));
    }
    else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
    {
        /* Integer part computing in case Oversampling mode is 16 Samples */
        integerdivider = ((25 * apbclock) / (4 * (baudrate)));
    }
    tmpreg = (integerdivider / 100) << 4;

    /* Determine the fractional part */
    fractionaldivider = integerdivider - (100 * (tmpreg >> 4));

    /* Implement the fractional part in the register */
    if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
    {
        tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
    }
    else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
    {
        tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
    }

    /* Write to USART BRR register */
    USARTx->BRR = (uint16_t)tmpreg;

#elif defined(STM32F10x)

    USART_TypeDef* USARTx = UART[u];
    u32 tmpreg = 0x00, apbclock = 0x00;
    u32 integerdivider = 0x00;
    u32 fractionaldivider = 0x00;
    RCC_ClocksTypeDef RCC_ClocksStatus;

    // Store baudrate value
    TM_UartDev[u].Baudrate = baudrate;

    RCC_GetClocksFreq(&RCC_ClocksStatus);
    if ((u32)UART[u] == USART1_BASE)
    {
        apbclock = RCC_ClocksStatus.PCLK2_Frequency;
    }
    else
    {
        apbclock = RCC_ClocksStatus.PCLK1_Frequency;
    }

    /* Determine the integer part */
    integerdivider = ((0x19 * apbclock) / (0x04 * (baudrate)));
    tmpreg = (integerdivider / 0x64) << 0x04;

    /* Determine the fractional part */
    fractionaldivider = integerdivider - (0x64 * (tmpreg >> 0x04));
    tmpreg |= ((((fractionaldivider * 0x10) + 0x32) / 0x64)) & ((u8)0x0F);

    /* Write to USART BRR */
    USARTx->BRR = (u16)tmpreg;

#endif
}


/*******************************************************************************
* Function:     GKI_uart_Cmd
* Description:  Enable/Disable Uart
*******************************************************************************/
void GKI_uart_Cmd(u16 u, u16 enb)
{
    if (enb)
        USART_Cmd(UART[u], enb);
}


/*******************************************************************************
* Function:     GKI_EnableUartTxInterrupt
* Description:  Enable Tx interrupts
*******************************************************************************/
void GKI_EnableUartTxInterrupt(u16 u)
{
    TM_UartDev[u].Tx.IsrEnb = true;
    GKI_uart_ITConfig(u, USART_IT_TXE, ENABLE);
}


/*******************************************************************************
* Function:     GKI_DisableUartTxInterrupt
* Description:  Disable Tx interrupts
*******************************************************************************/
void GKI_DisableUartTxInterrupt(u16 u)
{
    TM_UartDev[u].Tx.IsrEnb = false;
    GKI_uart_ITConfig(u, USART_IT_TXE, DISABLE);
}




/*******************************************************************************
* Function Name  : GKI_uart_InitStruct
* Description    : Initialize the uart structure
*******************************************************************************/
void GKI_uart_InitStruct(tGKI_uart_Init *USART_InitStruct)
{
    /* USART_InitStruct members default value */
    USART_InitStruct->USART_BaudRate            = 115200;
    USART_InitStruct->USART_WordLength          = GKI_uart_WordLength_8b;
    USART_InitStruct->USART_StopBits            = GKI_uart_StopBits_1;
    USART_InitStruct->USART_Parity              = GKI_uart_Parity_No ;
    USART_InitStruct->USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct->USART_HardwareFlowControl = GKI_uart_HardwareFlowControl_None;
}





/*******************************************************************************
* Function Name  : GKI_uart_Init
* Description    : Initialize the uart hardware
*******************************************************************************/
void GKI_uart_Init(u16 u, tGKI_uart_Init *GKI_uart_InitStruct)
{
    USART_InitTypeDef USART_InitStruct;

    USART_InitStruct.USART_BaudRate             =   GKI_uart_InitStruct->USART_BaudRate;
    USART_InitStruct.USART_WordLength           =   GKI_uart_InitStruct->USART_WordLength;
    USART_InitStruct.USART_StopBits             =   GKI_uart_InitStruct->USART_StopBits;
    USART_InitStruct.USART_Parity               =   GKI_uart_InitStruct->USART_Parity;
    USART_InitStruct.USART_Mode                 =   USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_HardwareFlowControl  =   GKI_uart_InitStruct->USART_HardwareFlowControl;

    USART_Init(UART[u], &USART_InitStruct);
}








/*******************************************************************************
* Function Name  : GKI_uart_ITConfig
* Description    : Enables or disables the specified USART interrupts.
********************************************************************************/
void GKI_uart_ITConfig(tGKI_Uart u, u16 it, FunctionalState NewState)
{
    USART_ITConfig(UartDev, it, NewState);
}



/*******************************************************************************
* Function Name  : GKI_dma_GetRxDataCounter
* Description    : Get current Rx DMA Counter
********************************************************************************/
u16 GKI_dma_GetRxDataCounter(u16 u)
{
    return DMA_GetCurrDataCounter((DMA_Stream_TypeDef *) UART_RX_DMA_Stream[u]);
}



/*******************************************************************************
* Function Name  : GKI_dma_GetTxDataCounter
* Description    : Get current Tx DMA Counter
********************************************************************************/
u16 GKI_dma_GetTxDataCounter(u16 u)
{
    return DMA_GetCurrDataCounter((DMA_Stream_TypeDef *) UART_TX_DMA_Stream[u]);
}




/*******************************************************************************
* Function Name  : GKI_dma_GetAvdtpDataCounter
* Description    : Get current Avdtp DMA Counter
********************************************************************************/
u16 GKI_dma_GetAvdtpDataCounter(void)
{
    return 0;
    //return DMA_GetCurrDataCounter(DMA1_Channel5);
}




//-------------------------------------------------------------
// Generate a SWI for the HCI UART
//-------------------------------------------------------------
void GKI_SWI_HCI(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
#if defined(STM32F10x)
    NVIC_InitStructure.NVIC_IRQChannel      = EXTI2_IRQChannel;
#elif defined(STM32F2xx) || defined(STM32F4xx)
    NVIC_InitStructure.NVIC_IRQChannel      = EXTI2_IRQn;
#else
#warning "Invalid Platform"
#endif
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TM_ExtPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_StructInit(&EXTI_InitStruct);
    EXTI_InitStruct.EXTI_Line               = GKI_EXTI_Line2;
    EXTI_InitStruct.EXTI_Mode               = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger            = EXTI_Trigger_Rising_Falling;
    EXTI_InitStruct.EXTI_LineCmd            = ENABLE;
    EXTI_Init(&EXTI_InitStruct);
    EXTI_GenerateSWInterrupt(GKI_EXTI_Line2);
}


//-------------------------------------------------------------
// Generate a SWI for the Main UART
//-------------------------------------------------------------
void GKI_SWI_MAIN(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
#if defined(STM32F10x)
    NVIC_InitStructure.NVIC_IRQChannel      = EXTI3_IRQChannel;
#elif defined(STM32F2xx) || defined(STM32F4xx)
    NVIC_InitStructure.NVIC_IRQChannel      = EXTI3_IRQn;
#else
#warning "Invalid Platform"
#endif
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = TM_ExtPriority;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd   = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    EXTI_InitTypeDef EXTI_InitStruct;
    EXTI_StructInit(&EXTI_InitStruct);
    EXTI_InitStruct.EXTI_Line               = GKI_EXTI_Line3;
    EXTI_InitStruct.EXTI_Mode               = EXTI_Mode_Interrupt;
    EXTI_InitStruct.EXTI_Trigger            = EXTI_Trigger_Rising_Falling;
    EXTI_InitStruct.EXTI_LineCmd            = ENABLE;
    EXTI_Init(&EXTI_InitStruct);
    EXTI_GenerateSWInterrupt(GKI_EXTI_Line3);
}





#define USARTx USART1
#define USART_TX_PIN            GPIO_Pin_9
#define USART_RX_PIN            GPIO_Pin_10



#define GKI_MAIN_TX_DMA_PENDING (DMA_IT_FEIF7 | DMA_IT_DMEIF7 | DMA_IT_TEIF7 | DMA_IT_HTIF7 | DMA_IT_TCIF7)
#define GKI_HCI_TX_DMA_PENDING  (DMA_IT_FEIF6 | DMA_IT_DMEIF6 | DMA_IT_TEIF6 | DMA_IT_HTIF6 | DMA_IT_TCIF6)







/*******************************************************************************
* Function Name  : TM_SetupUart
* Description    : Check for valid parameters, then configure the UartDevice format
*******************************************************************************/
bool GKI_uart_Setup(tTM_UartType      u,
                  tTM_UartDataBits  DataBits,
                  tTM_UartStopBits  StopBits,
                  tTM_UartParity    Parity,
                  tTM_UartBaudRate  BaudRate)
{
    tGKI_uart_Init   Usart_Structure;

    GKI_UartConfigPins(u);

    GKI_uart_InitStruct(&Usart_Structure);
    pUart->Baudrate                    = BaudRate;
    Usart_Structure.USART_BaudRate     = BaudRate;
    //Usart_Structure.USART_Mode         = USART_Mode_Rx|USART_Mode_Tx;
    Usart_Structure.USART_HardwareFlowControl = pUart->HardwareFlowControl;

    if (u==eTM_HciUart) {
        Usart_Structure.USART_WordLength   = GKI_uart_WordLength_8b;
        Usart_Structure.USART_StopBits     = GKI_uart_StopBits_1;
        Usart_Structure.USART_Parity       = GKI_uart_Parity_No;
    }
    else {
        Usart_Structure.USART_WordLength   = AT_UART_DEFAULT_DATA_BITS_MASK;
        Usart_Structure.USART_StopBits     = AT_UART_DEFAULT_STOP_BITS_MASK;
        Usart_Structure.USART_Parity       = AT_UART_DEFAULT_PARITY_MASK;
        NOP;
    }
    GKI_uart_Init(u, &Usart_Structure);

    GKI_uart_SetCharTimeout(u, RX.Timeout);
    GKI_uart_Cmd(u, ENABLE);

    // Setup Interrupt
    GKI_nvic_SetUartIsr(u, pUart->IRQPriority);

    return(true);
}






//#define DEBUG_MAIN_RTS

/*******************************************************************************
* Function Name  : GKI_uart_ReceiveEnable
* Description    : Drive UART RTS to Receive Enable/Disable
*******************************************************************************/
#ifdef TI2564
extern bool Rf2564DSMflag;
#endif
void GKI_uart_ReceiveEnable(uint16 u, bool enb)
{
#ifdef DEBUG_MAIN_RTS
    static bool initialized=false;
    static u16 io_dbg=IO_UNDEFINED;
    if (!initialized) {
        io_dbg = TM_GPIO(7);
        GKI_io_Config(io_dbg, GKI_IO_OUT_PP);
        GKI_io_WriteBit(io_dbg, 0);
        initialized = true;
    }
#endif
    switch (u) {
    case eTM_MainUart:
        GKI_io_WriteBit(IO_MAIN_RTS, !enb);
#ifdef DEBUG_MAIN_RTS
        GKI_io_WriteBit(io_dbg, enb);
#endif
        break;
    case eTM_HciUart:
#ifdef TI2564
        if(Rf2564DSMflag)
          {
             if(!enb)
             {
               GKI_io_WriteBit(IO_HCI_RTS, !enb);
             }
          }
        else
          {
             GKI_io_WriteBit(IO_HCI_RTS, !enb);
          }
#else
        //GKI_io_Config(IO_HCI_RTS, enb ? GKI_IO_AF_PP : GKI_IO_OUT_PP);
        GKI_io_WriteBit(IO_HCI_RTS, !enb);
#endif

        break;
    }
}

//when sysclk changed,then reset uart
void GKI_uart_ReSetup(uint16 u)
{
	tTM_UartDev *pUsart = &TM_UartDev[u];
    GKI_uart_Setup(u,pUsart->Config.DataBits,
        			 pUsart->Config.StopBits,
        			 pUsart->Config.Parity,
        			 pUsart->Config.Baudrate);
}

//--------------------------------------------------------------
//