/*
 * Copyright (c) 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 * All rights reserved.
 * 
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "board.h"
#include "fsl_usart.h"
#include "pin_mux.h"
#include <stdbool.h>

/*******************************************************************************
 * Macro Definition
 ******************************************************************************/
//USART1 is connected to SPI2USART bridge
//USART1 base address
#define BRIDGE_USART            USART1
//get USART1 clock frequency
#define BRIDGE_USART_CLK_FREQ   CLOCK_GetFreq(kCLOCK_Flexcomm1)
//USART1 interrupt service routine
#define BRIDGE_USART_IRQHandler FLEXCOMM1_IRQHandler
//USART1 interrupt number
#define BRIDGE_USART_IRQn       FLEXCOMM1_IRQn

//USART0 is used as console to provide user to observe data received
#define CONSOLE_USART           USART0
//get USART0 clock frequency
#define CONSOLE_USART_CLK_FREQ  CLOCK_GetFreq(kCLOCK_Flexcomm0)

//LED is used to indicate whether routine is running
//LED port number
#define LED_PORT                1U
//LED pin number
#define LED_PIN                 10U

/*******************************************************************************
 * Variables
 ******************************************************************************/
//systick global counter
static uint32_t g_systickCounter;
//tx buffer from USART peripheral to SPI2USART bridge
static uint8_t  txBuf[64];
static uint8_t  prompt[] = "USART peripheral connected to SPI-USART bridge starts up!\r\n";
/*******************************************************************************
 * Code
 ******************************************************************************/
/*!
 * brief  Systick timer interrupt service routine
 * param  void
 * return void
 */
void SysTick_Handler(void)
{
	if(g_systickCounter != 0U)
	{
		g_systickCounter--;
	}
}

/*!
 * brief  delay function
 * param  uint32_t ms->millisecond
 * return void
 */
void SysTick_DelayTicks(uint32_t ms)
{
	g_systickCounter = ms;
	while(g_systickCounter != 0U)
	{
	}
}

/*!
 * brief  systick timer intialize
 * param  void
 * return void
 */
void SystickInitialize(void)
{
	//Set systick reload value to generate 1ms interrupt
	if(SysTick_Config(SystemCoreClock / 1000U))
	{
		while (1)
		{
		}
	}
}

/*!
 * brief  USART1 interrupt service routine
 * param  void
 * return void
 */
void BRIDGE_USART_IRQHandler(void)
{
	//temporary data
	uint8_t data;
  
	//If new data arrived
  if((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(BRIDGE_USART))
  {
		//read data from USART1 connected to SPI-USART bridge
		data = USART_ReadByte(BRIDGE_USART);
		//send data to USART0 used as console in order to observe data
		USART_WriteBlocking(CONSOLE_USART,&data,1);
  }
}

/*!
 * brief  main entry
 * param  void
 * return void
 */
int main(void)
{
	//USART configuration structure
	usart_config_t config;
	
  //define the init structure for the output LED pin
  gpio_pin_config_t led_config = 
	{
		kGPIO_DigitalOutput, 0,
  };
		
	//attach 12 MHz clock to FLEXCOMM0
	CLOCK_AttachClk(kFRO12M_to_FLEXCOMM0);
  //attach 12 MHz clock to FLEXCOMM1 
  CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1);
	//attach 12 MHz clock to GPIO0 
  CLOCK_EnableClock(kCLOCK_Gpio0);
	//attach 12 MHz clock to GPIO1 
  CLOCK_EnableClock(kCLOCK_Gpio1);
	
	//reset FLEXCOMM0 for USART0
  RESET_PeripheralReset(kFC0_RST_SHIFT_RSTn);
  //reset FLEXCOMM1 for USART1 
  RESET_PeripheralReset(kFC1_RST_SHIFT_RSTn);
	
	//IO Configuration
  BOARD_InitPins();
	//Configure System clock frequency
  BOARD_BootClockFROHF48M();
	//Debug console configuration
  BOARD_InitDebugConsole();
  //Init output LED GPIO
  GPIO_PortInit(GPIO, LED_PORT);
  GPIO_PinInit(GPIO, LED_PORT, LED_PIN, &led_config);
	//Systick timer initialize
	SystickInitialize();
	
  /*
   * config.baudRate_Bps = 115200U;
   * config.parityMode = kUSART_ParityDisabled;
   * config.stopBitCount = kUSART_OneStopBit;
   * config.loopback = false;
   * config.enableTxFifo = false;
   * config.enableRxFifo = false;
   */
	//obtain USART default configuration
	USART_GetDefaultConfig(&config);
	//reconfigure default baud rate
  config.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
	//enable transmitting function
  config.enableTx = true;
	//enable receiving function
  config.enableRx = true;
	//use configuration above to configure USART0 as console
  USART_Init(CONSOLE_USART, &config, CONSOLE_USART_CLK_FREQ);
	//use configuration above to configure USART1 connected to SPI-USART bridge
  USART_Init(BRIDGE_USART, &config, BRIDGE_USART_CLK_FREQ);
  //Enable Bridge USART RX interrupt in USART module
  USART_EnableInterrupts(BRIDGE_USART, kUSART_RxLevelInterruptEnable | kUSART_RxErrorInterruptEnable);
	//Enable Bridge USART RX interrupt in NVIC
  EnableIRQ(BRIDGE_USART_IRQn);
  
	//This is a hint that the system is running 
	USART_WriteBlocking(CONSOLE_USART, prompt,sizeof(prompt) - 1);
	//send 64 data bytes to SPI2USART bridge, data count is equal to rx trigger level of rx buffer in SPI2USART bridge
	for(uint32_t i = 0; i < 64;i++)
  {
		txBuf[i] = i;
		USART_WriteBlocking(BRIDGE_USART, &txBuf[i],1);
  }
	//>=300ms is a must to avoid data corruption
  SysTick_DelayTicks(300);
	
	//send 63 data bytes to SPI2USART bridge, data count less than rx trigger level of rx buffer in SPI2USART bridge
	for(uint32_t i = 0; i < 63;i++)
  {
		txBuf[i] = i;
		USART_WriteBlocking(BRIDGE_USART, &txBuf[i],1);
  }
	//>=300ms is a must to avoid data corruption
  SysTick_DelayTicks(300);

  while (1)
  {
  }
}
