/* -----------------------------------------------------------------------------
 * Copyright (c) 2019 Arm Limited (or its affiliates). All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the License); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 * $Date:        12. November 2019
 * $Revision:    V1.0
 *
 * Project:      Simple serial buffer
 * -------------------------------------------------------------------------- */

#include <string.h>
#include <stdio.h>

#include "ESP8266_Serial.h"
#include "WiFi_ESP8266_Config.h"

#include "kdrv_uart.h"
#include "kdrv_pinmux.h"
#include "kdrv_cmsis_core.h"

/* Serial buffer sizes 
#ifndef SERIAL_TXBUF_SZ
#define SERIAL_TXBUF_SZ   0x1000
#endif*/

#ifndef SERIAL_RXBUF_SZ
#define SERIAL_RXBUF_SZ   0x1000
#endif

/* Static functions */
static void WIFI_UART_Callback (uint32_t event);

typedef struct {
  //ARM_DRIVER_USART *drv;  /* UART driver */
  uint32_t rxc;           /* Rx buffer count */
  //uint32_t rxi;           /* Rx buffer index */
//  uint32_t txi;           /* Tx buffer index */
  uint8_t  txb;           /* Tx busy flag    */
  kdrv_uart_handle_t  handle; /*uart port*/
  uint8_t  r[3];          /* Reserved        */
} WIFI_SERIAL_COM;

static uint8_t RxBuf[SERIAL_RXBUF_SZ];
//static uint8_t TxBuf[SERIAL_TXBUF_SZ];

static WIFI_SERIAL_COM wifi_serial_com;
#define AT_UART_PORT DRVUART_PORT4 //default commucate uart port(wifi module <------> kneron) 

/**
  Callback from the USART driver
*/

static void WIFI_UART_Callback (uint32_t event) {
  //int32_t stat;
  uint32_t flags;

  flags = 0U;

	if (event & (ARM_USART_EVENT_RX_TIMEOUT | ARM_USART_EVENT_RECEIVE_COMPLETE)) {
		
		flags |= SERIAL_CB_RX_DATA_AVAILABLE;
		
		if(event & ARM_USART_EVENT_RECEIVE_COMPLETE)
		{
			
			/* Increment counter of received bytes */
			//wifi_serial_com.rxc += SERIAL_RXBUF_SZ;
		}
		
  }

  if (event & ARM_USART_EVENT_SEND_COMPLETE) {
    flags |= SERIAL_CB_TX_DATA_COMPLETED;
    /* Clear tx busy flag */
    wifi_serial_com.txb = 0U;
  } 
  /* Send events */
  Serial_Cb (flags);
}

/**
  Event callback.
*/
__WEAK void Serial_Cb (uint32_t event) {
  (void)event;
}


/**
  Initialize serial interface.

  \return 0:ok, 1:error
*/
int32_t Serial_Initialize (void) {

  /* Initialize serial control structure */
  wifi_serial_com.rxc = 0U;
 // wifi_serial_com.rxi = 0U;
//  wifi_serial_com.txi = 0U;
  wifi_serial_com.txb = 0U;
  wifi_serial_com.handle = 0U;
 
  kdrv_pinmux_config(KDRV_PIN_SD_DAT_2, PIN_MODE_6, PIN_PULL_NONE, PIN_DRIVING_4MA);
  kdrv_pinmux_config(KDRV_PIN_SD_DAT_3, PIN_MODE_6, PIN_PULL_NONE, PIN_DRIVING_4MA);

   kdrv_status_t sts = kdrv_uart_open(&wifi_serial_com.handle, (kdrv_uart_dev_id_t)AT_UART_PORT, UART_MODE_ASYN_RX | UART_MODE_SYNC_TX, WIFI_UART_Callback);	
  if (sts != KDRV_STATUS_OK)
  {
    //printf(" WIFI UART open failed\n");
    return sts;
  }
	
  kdrv_uart_config_t cfg;
	cfg.baudrate = BAUD_115200;
	cfg.data_bits = 8;
	cfg.frame_length = 0;
	cfg.stop_bits = 1;
	cfg.parity_mode = PARITY_NONE;
	cfg.fifo_en = true;

	 sts = kdrv_uart_configure(wifi_serial_com.handle, UART_CTRL_CONFIG, (void *)&cfg);
    if (sts == KDRV_STATUS_OK) {
        kdrv_uart_read( wifi_serial_com.handle, RxBuf, SERIAL_RXBUF_SZ ); 
    }
		
  return (sts);
}


/**
  Uninitialize serial interface.

  \return 0:ok
*/
int32_t Serial_Uninitialize (void) {

  kdrv_uart_close(wifi_serial_com.handle);

  memset (RxBuf, 0x00, SERIAL_RXBUF_SZ);
  //memset (TxBuf, 0x00, SERIAL_TXBUF_SZ);

  return (0);
}

/**
  Set serial interface baudrate.
  
  \param[in]  baudrate    desired baudrate
  \return 0:ok, 1:error
*/
int32_t Serial_SetBaudrate (uint32_t baudrate) {
 
	wifi_serial_com.rxc = 0U;
  //wifi_serial_com.rxi = 0U;
//  wifi_serial_com.txi = 0U;
  wifi_serial_com.txb = 0U;
 
  kdrv_uart_config_t cfg;
  cfg.baudrate = baudrate; //default baudrate 115200
  cfg.data_bits = 8;
  cfg.frame_length = 0;
  cfg.stop_bits = 1;
  cfg.parity_mode = PARITY_NONE;
  cfg.fifo_en = true;     
	
  kdrv_status_t sts = kdrv_uart_configure(wifi_serial_com.handle, UART_CTRL_CONFIG, (void *)&cfg);
  if (sts == KDRV_STATUS_OK) {
     kdrv_uart_read( wifi_serial_com.handle, RxBuf, SERIAL_RXBUF_SZ );   
  }

	return (sts);
 
}

/**
  Get number of bytes free in transmit buffer.

  \return number of bytes
*/
uint32_t Serial_GetTxFree (void) {
  uint32_t n;

  if (Serial_GetTxCount() != 0U) {
    n = 0;
  } else {
    //n = SERIAL_TXBUF_SZ;
		n = 0X1000;
  }

  return (n);
}

/**
  Try to send len of characters from the specified buffer.

  If there is not enough space in the transmit buffer, number
  of characters sent will be less than specified with len.

  \return number of bytes actually sent or -1 in case of error
*/
int32_t Serial_SendBuf (const uint8_t *buf, uint32_t len) {
  
  int32_t  n;
  kdrv_status_t  stat;


  stat = kdrv_uart_write(wifi_serial_com.handle, (uint8_t *)buf, len);

  if (stat == KDRV_STATUS_OK) {
    wifi_serial_com.txb = 1U;
    n = len;
  }
  else {
    wifi_serial_com.txb = 0U;
    n = -1;
  }

  return n;
}


/**
  Read len characters from the serial receive buffers and put them into buffer buf.

  \return number of characters read
*/
int32_t Serial_ReadBuf(uint8_t *buf, uint32_t len) {
  
	uint32_t i, n;
	static uint32_t rxi = 0;
	wifi_serial_com.rxc = Serial_GetRxCount(); //get total data count
	n = wifi_serial_com.rxc;
	n -= rxi; // get reserved data count
	
	if(len < n)
	{
		n = len;
	}
	
	for (i = 0U; i < n; i++) 
	{
		 buf[i] = RxBuf[rxi++];
	}

	if(rxi == wifi_serial_com.rxc)
	{	
		rxi = 0;
		memset(RxBuf,0, wifi_serial_com.rxc);
		wifi_serial_com.rxc = 0;
	}
	
  return ( n);
}

void Serial_uart_read()
{
	kdrv_uart_read(wifi_serial_com.handle, RxBuf, SERIAL_RXBUF_SZ);
}
/**
  Retrieve total number of bytes to read
*/
uint32_t Serial_GetRxCount(void) {
  uint32_t u;
	
  u  = kdrv_uart_get_rx_count(wifi_serial_com.handle);
  return (u);
	
}

uint32_t Serial_GetTxCount(void) {
  uint32_t n;

  n = kdrv_uart_get_tx_count(wifi_serial_com.handle);
  return (n);
}



