/**
  *********************************************************************************
  *
  * @file    hal_pis.c
  * @brief   PIS module driver.
  *
  * @version V1.0
  * @date    27 Nov 2017
  * @author  AE Team
  * @note
  *
  * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
  *
  *********************************************************************************
  */

#include "hal_pis.h"

/** @addtogroup ES32FXXX_HAL
  * @{
  */

/** @defgroup PIS PIS
  * @brief PIS module driver
  * @{
  */
#ifdef HAL_PIS

/** @defgroup PIS_Public_Functions PIS Public Functions
  * @{
  */

/** @defgroup PIS_Public_Functions_Group1 Initialization functions
  * @brief Initialization and Configuration functions
  * @{
  */

/**
  * @brief  Create the PIS mode according to the specified parameters in
  *         the pis_handle_t and create the associated handle.
  * @param  hperh: Pointer to a pis_handle_t structure that contains
  *         the configuration information for the specified PIS module.
  * @retval Status, see @ref hal_status_t.
  */
hal_status_t pis_create(pis_handle_t *hperh)
{
	pis_divide_t temp;
	uint8_t clock_menu = 0;

	if (hperh == NULL)
		return ERROR;

	assert_param(IS_PIS_SRC(hperh->init.producer_src));
	assert_param(IS_PIS_TRIG(hperh->init.consumer_trig));
	assert_param(IS_PIS_CLOCK(hperh->init.producer_clk));
	assert_param(IS_PIS_CLOCK(hperh->init.consumer_clk));
	assert_param(IS_PIS_EDGE(hperh->init.producer_edge));

	__LOCK(hperh);
	hperh->perh = PIS;

	/* get location of consumer in channel and position of con0/con1
	 * accord to comsumer_trig information */
	temp.HalfWord            = (hperh->init.consumer_trig);
	hperh->consumer_ch       = (pis_ch_t)(temp.ch);
	hperh->consumer_con      = (pis_con_t)(temp.con);
	hperh->consumer_position = (1 << temp.shift);

	/* union producer clock and consumer clock */
	clock_menu = (hperh->init.producer_clk << 4) | (hperh->init.consumer_clk);

	if (hperh->perh->CH_CON[hperh->consumer_ch].Word != 0) {
		__UNLOCK(hperh);
		return BUSY;
	}

	hperh->perh->CH_CON[hperh->consumer_ch].SRCS  = ((hperh->init.producer_src) >> 4);
	hperh->perh->CH_CON[hperh->consumer_ch].MSIGS = ((hperh->init.producer_src) & 0xf);

	/* configure sync clock, judging by producer clock with consumer clock */
	switch (clock_menu) {
	case 0x00:
	case 0x11:
	case 0x22:
	case 0x33:
		hperh->perh->CH_CON[hperh->consumer_ch].SYNCSEL = 0;
		break;
	case 0x01:
		hperh->perh->CH_CON[hperh->consumer_ch].SYNCSEL = 5;
		break;
	case 0x02:
	case 0x12:
		hperh->perh->CH_CON[hperh->consumer_ch].SYNCSEL = 6;
		break;
	case 0x21:
		hperh->perh->CH_CON[hperh->consumer_ch].SYNCSEL = 4;
		break;
	case 0x30:
		hperh->perh->CH_CON[hperh->consumer_ch].SYNCSEL = 1;
		break;
	case 0x31:
		hperh->perh->CH_CON[hperh->consumer_ch].SYNCSEL = 2;
		break;
	case 0x32:
		hperh->perh->CH_CON[hperh->consumer_ch].SYNCSEL = 3;
	default:
		break;
	}

	hperh->perh->CH_CON[hperh->consumer_ch].PULCK = hperh->init.consumer_clk;
	hperh->perh->CH_CON[hperh->consumer_ch].EDGS  = hperh->init.producer_edge;
	hperh->check_info = hperh->perh->CH_CON[hperh->consumer_ch].Word;

	/* enable consumer bit, switch pin of consumer */
	switch (hperh->consumer_con) {
	case PIS_CON_0:
		PIS->TAR_CON0.Word |= hperh->consumer_position;
		break;
	case PIS_CON_1:
		PIS->TAR_CON1.Word |= hperh->consumer_position;
		break;
	default:
		break;
	}

	__UNLOCK(hperh);
	return OK;
}

/**
  * @brief  Destroy the PIS mode according to the specified parameters in
  *         the pis_init_t and create the associated handle.
  * @param  hperh: Pointer to a pis_handle_t structure that contains
  *         the configuration information for the specified PIS module.
  * @retval Status, see @ref hal_status_t.
  */
hal_status_t pis_destroy(pis_handle_t *hperh)
{
	assert_param(IS_PIS(hperh->perh));

	if (hperh->check_info != hperh->perh->CH_CON[hperh->consumer_ch].Word)
		return ERROR;

	__LOCK(hperh);

	PIS->CH_OER.Word &= ~(1 << hperh->consumer_ch);
	hperh->perh->CH_CON[hperh->consumer_ch].Word = 0;

	switch (hperh->consumer_con) {
	case PIS_CON_0:
		PIS->TAR_CON0.Word &= ~(hperh->consumer_position);
		break;
	case PIS_CON_1:
		PIS->TAR_CON1.Word &= ~(hperh->consumer_position);
		break;
	default:
		break;
	}

	hperh->state = PIS_STATE_RESET;
	__UNLOCK(hperh);

	return OK;
}
/**
  * @}
  */

/** @defgroup PIS_Public_Functions_Group2 Operation functions
  * @brief PIS output enable or disable functions
  * @{
  */

/**
  * @brief  Start the PIS output function.
  * @param  hperh: Pointer to a pis_handle_t structure that contains
  *         the configuration information for the specified PIS module.
  * @param  ch: The PIS channel enable output
  *	    This parameter can be one of the following values:
  *		@arg PIS_OUTPUT_CH_0
  *		@arg PIS_OUTPUT_CH_1
  *		@arg PIS_OUTPUT_CH_2
  *		@arg PIS_OUTPUT_CH_3
  * @retval Status, see @ref hal_status_t.
  */
hal_status_t pis_output_start(pis_handle_t *hperh, pis_out_ch_t ch)
{
	assert_param(IS_PIS(hperh->perh));
	assert_param(IS_PIS_OUPUT_CH(ch));
	__LOCK(hperh);

	PIS->CH_OER.Word |= (1 << ch);
	__UNLOCK(hperh);
	return OK;
}

/**
  * @brief  Stop the PIS output function.
  * @param  hperh: Pointer to a pis_handle_t structure that contains
  *         the configuration information for the specified PIS module.
  * @param  ch: The PIS channel disable output
  *	    This parameter can be one of the following values:
  *		@arg PIS_OUTPUT_CH_0
  *		@arg PIS_OUTPUT_CH_1
  *		@arg PIS_OUTPUT_CH_2
  *		@arg PIS_OUTPUT_CH_3
  * @retval Status, see @ref hal_status_t.
  */
hal_status_t pis_output_stop(pis_handle_t *hperh, pis_out_ch_t ch)
{
	assert_param(IS_PIS(hperh->perh));
	assert_param(IS_PIS_OUPUT_CH(ch));
	__LOCK(hperh);

	PIS->CH_OER.Word &= ~(1 << ch);
	__UNLOCK(hperh);
	return OK;
}
/**
  * @}
  */

/** @defgroup PIS_Public_Functions_Group3 Peripheral State and Errors functions
  *  @brief   PIS State and Errors functions
  * @{
  */

/**
  * @brief  Returns the PIS state.
  * @param  hperh: Pointer to a pis_handle_t structure that contains
  *         the configuration information for the specified PIS module.
  * @retval HAL state
  */
pis_state_t pis_get_state(pis_handle_t *hperh)
{
	assert_param(IS_PIS(hperh->perh));
	return hperh->state;
}

/**
  * @}
  */

/** @defgroup PIS_Public_Functions_Group4 modulate output functions
  *  @brief   PIS modulate output signal functions
  * @{
  */

/**
  * @brief  Config the PIS modulate signal function
  * @param  hperh: Pointer to a pis_handle_t structure that contains
  *         the configuration information for the specified PIS module.
  * @param  config: Pointer to a pis_modulate_config_t structure that
  *         contains the selected target (UART0,UART1,UART2,UART3 or
  *         LPUART0) how to modulate the target output signal.
  * @retval Status, see @ref hal_status_t.
  */
hal_status_t pis_modulation_output_config(pis_handle_t *hperh, pis_modulate_config_t *config)
{
	assert_param(IS_PIS(hperh->perh));
	assert_param(IS_PIS_MODU_TARGET(config->modulate_target));
	assert_param(IS_PIS_MODU_LEVEL(config->modulate_level));
	assert_param(IS_PIS_MODU_SRC(config->modulate_src));
	assert_param(IS_PIS_MODU_CHANNEL(config->modulate_channel));
	__LOCK(hperh);

	switch(config->modulate_target) {
	case PIS_MODULATE_UART0_TX:
		hperh->perh->UART0_TXMCR.TXMLVLS = config->modulate_level;
		hperh->perh->UART0_TXMCR.TXMSS   = config->modulate_src;
		hperh->perh->UART0_TXMCR.TXSIGS  = config->modulate_channel;
		break;

	case PIS_MODULATE_UART1_TX:
		hperh->perh->UART1_TXMCR.TXMLVLS = config->modulate_level;
		hperh->perh->UART1_TXMCR.TXMSS   = config->modulate_src;
		hperh->perh->UART1_TXMCR.TXSIGS  = config->modulate_channel;
		break;

	case PIS_MODULATE_UART2_TX:
		hperh->perh->UART2_TXMCR.TXMLVLS = config->modulate_level;
		hperh->perh->UART2_TXMCR.TXMSS   = config->modulate_src;
		hperh->perh->UART2_TXMCR.TXSIGS  = config->modulate_channel;
		break;

	case PIS_MODULATE_UART3_TX:
		hperh->perh->UART3_TXMCR.TXMLVLS = config->modulate_level;
		hperh->perh->UART3_TXMCR.TXMSS   = config->modulate_src;
		hperh->perh->UART3_TXMCR.TXSIGS  = config->modulate_channel;
		break;

	case PIS_MODULATE_LPUART0_TX:
		hperh->perh->LPUART0_TXMCR.TXMLVLS = config->modulate_level;
		hperh->perh->LPUART0_TXMCR.TXMSS   = config->modulate_src;
		hperh->perh->LPUART0_TXMCR.TXSIGS  = config->modulate_channel;
		break;

	default:
		break;
	}

	__UNLOCK(hperh);
	return OK;
}
/**
  * @}
  */
/**
  * @}
  */
#endif /* HAL_PIS */
/**
  * @}
  */
/**
  * @}
  */
