/*!
 * @file        apm32f10x_dac.c
 *
 * @brief       This file provides all the DAC firmware functions
 *
 * @version     V1.0.1
 *
 * @date        2021-03-23
 *
 */

#include "apm32f10x_dac.h"
#include "apm32f10x_rcm.h"

/** @addtogroup Peripherals_Library Standard Peripheral Library
  @{
*/

/** @addtogroup DAC_Driver DAC Driver
  @{
*/

/** @addtogroup DAC_Fuctions Fuctions
  @{
*/

/*!
 * @brief        Reset dac peripheral registers to their default reset values.
 *
 * @param        None
 *
 * @retval       None
 */
void DAC_Reset(void)
{
    RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_DAC);
    RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_DAC);
}

/*!
 * @brief        Config the DAC peripheral according to the specified parameters in the configStruct
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @param        configStruct: pointer to a DAC_ConfigStruct_T structure
 *
 * @retval       None
 */
void DAC_Config(uint32_t channel, DAC_ConfigStruct_T* configStruct)
{
    uint32_t tmp1 = 0, tmp2 = 0;

    tmp1 = DAC->CTRL;

    tmp1 &= ~(((uint32_t)0x00000FFE) << channel);

    tmp2 = (configStruct->trigger | configStruct->waveGeneration | configStruct->maskAmplitudeSelect | configStruct->outputBuffer);
    tmp1 |= tmp2 << channel;

    DAC->CTRL = tmp1;
}

/*!
 * @brief        Fills each DAC_ConfigStruct_T member with its default value
 *
 * @param        configStruct: pointer to a DAC_ConfigStruct_T structure which will be initialized
 *
 * @retval       None
 */
void DAC_ConfigStructInit(DAC_ConfigStruct_T* configStruct)
{
    /* Initialize the DAC_Trigger member */
    configStruct->trigger = DAC_TRIGGER_NONE;
    /* Initialize the DAC_WaveGeneration member */
    configStruct->waveGeneration = DAC_WAVE_GENERATION_NONE;
    /* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */
    configStruct->maskAmplitudeSelect = DAC_LFSR_MASK_BIT11_1;
    /* Initialize the DAC_OutputBuffer member */
    configStruct->outputBuffer = DAC_OUTPUT_BUFFER_ENBALE;
}

/*!
 * @brief        Enables the specified DAC peripheral
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @retval       None
 */
void DAC_Enable(DAC_CHANNEL_T channel)
{
    if (channel == DAC_CHANNEL_1)
    {
        DAC->CTRL_B.ENCH1 = BIT_SET;
    }
    else if (channel == DAC_CHANNEL_2)
    {
        DAC->CTRL_B.ENCH2 = BIT_SET;
    }
}

/*!
 * @brief        Disables the specified DAC peripheral
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @retval       None
 */
void DAC_Disable(DAC_CHANNEL_T channel)
{
    if (channel == DAC_CHANNEL_1)
    {
        DAC->CTRL_B.ENCH1 = BIT_RESET;
    }
    else if (channel == DAC_CHANNEL_2)
    {
        DAC->CTRL_B.ENCH2 = BIT_RESET;
    }
}


/*!
 * @brief        Enables the specified DAC channel DMA request
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @retval       None
 */
void DAC_DMA_Enable(DAC_CHANNEL_T channel)
{
    if (channel == DAC_CHANNEL_1)
    {
        DAC->CTRL_B.DMAENCH1 = BIT_SET;
    }
    else if (channel == DAC_CHANNEL_2)
    {
        DAC->CTRL_B.DMAENCH2 = BIT_SET;
    }
}

/*!
 * @brief        Disables the specified DAC channel DMA request
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @retval       None
 */
void DAC_DMA_Disable(DAC_CHANNEL_T channel)
{
    if (channel == DAC_CHANNEL_1)
    {
        DAC->CTRL_B.DMAENCH1 = BIT_RESET;
    }
    else if (channel == DAC_CHANNEL_2)
    {
        DAC->CTRL_B.DMAENCH2 = BIT_RESET;
    }
}

/*!
 * @brief        Enables the selected DAC channel software trigger
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @retval       None
 */
void DAC_EnableSoftwareTrigger(DAC_CHANNEL_T channel)
{
    if (channel == DAC_CHANNEL_1)
    {
        DAC->SWTRG_B.SWTRG1 = BIT_SET;
    }
    else if (channel == DAC_CHANNEL_2)
    {
        DAC->SWTRG_B.SWTRG2 = BIT_SET;
    }
}

/*!
 * @brief        Disable the selected DAC channel software trigger
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @retval       None
 */
void DAC_DisableSoftwareTrigger(DAC_CHANNEL_T channel)
{
    if (channel == DAC_CHANNEL_1)
    {
        DAC->SWTRG_B.SWTRG1 = BIT_RESET;
    }
    else if (channel == DAC_CHANNEL_2)
    {
        DAC->SWTRG_B.SWTRG2 = BIT_RESET;
    }
}
/*!
 * @brief        Enables simultaneously the two DAC channels software
 *
 * @param        None
 *
 * @retval       None
 */
void DAC_EnableDualSoftwareTrigger(void)
{
    DAC->SWTRG_B.SWTRG1 = BIT_SET;
    DAC->SWTRG_B.SWTRG2 = BIT_SET;
}

/*!
 * @brief        Disables simultaneously the two DAC channels software
 *
 * @param        None
 *
 * @retval       None
 */
void DAC_DisableDualSoftwareTrigger(void)
{
    DAC->SWTRG_B.SWTRG1 = BIT_RESET;
    DAC->SWTRG_B.SWTRG2 = BIT_RESET;
}

/*!
 * @brief        Enables the selected DAC channel wave generation
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @param        wave: Select the wave
 *                     This parameter can be one of the following values:
 *                     @arg DAC_WAVE_GENERATION_NONE     : no wave generation
 *                     @arg DAC_WAVE_GENERATION_NOISE    : Noise wave generation
 *                     @arg DAC_WAVE_GENERATION_TRIANGLE : Triangle wave generation
 *
 * @retval       None
 */
void DAC_EnableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave)
{
    DAC->CTRL &= 0xFF3FFF3F;
    DAC->CTRL |= wave << channel;
}

/*!
 * @brief        Disables the selected DAC channel wave generation
 *
 * @param        channel: Select the DAC channel.
 *                        This parameter can be one of the following values:
 *                        @arg DAC_CHANNEL_1 : DAC channel 1
 *                        @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @param        wave: Select the wave
 *                     This parameter can be one of the following values:
 *                     @arg DAC_WAVE_GENERATION_NONE     : no wave generation
 *                     @arg DAC_WAVE_GENERATION_NOISE    : Noise wave generation
 *                     @arg DAC_WAVE_GENERATION_TRIANGLE : Triangle wave generation
 *
 * @retval       None
 */
void DAC_DisableWaveGeneration(DAC_CHANNEL_T channel, DAC_WAVE_GENERATION_T wave)
{
    DAC->CTRL &= ~(wave << channel);
}

/*!
 * @brief        Set the specified data holding register value for DAC channel 1
 *
 * @param        align: DAC channel 1 data alignment
 *                      This parameter can be one of the following values:
 *                      @arg DAC_ALIGN_12BIT_R : 12-bit right-aligned data
 *                      @arg DAC_ALIGN_12BIT_L : 12-bit left-aligned data
 *                      @arg DAC_ALIGN_8BIT_R  : 8-bit right-aligned data
 *
 * @param        data: The data to be loaded in the selected data register.
 *
 * @retval       None
 */
void DAC_ConfigChannel1Data(DAC_ALIGN_T align, uint16_t data)
{
    __IO uint32_t tmp = 0;

    tmp = (uint32_t)DAC_BASE;
    tmp += 0x00000008 + align;

    /* Set the DAC channel1 selected data holding register */
    *(__IO uint32_t *) tmp = data;
}

/*!
 * @brief        Set the specified data holding register value for DAC channel 2
 *
 * @param        align: DAC channel 2 data alignment
 *                      This parameter can be one of the following values:
 *                      @arg DAC_ALIGN_12BIT_R : 12-bit right-aligned data
 *                      @arg DAC_ALIGN_12BIT_L : 12-bit left-aligned data
 *                      @arg DAC_ALIGN_8BIT_R  : 8-bit right-aligned data
 *
 * @param        data: The data to be loaded in the selected data register.
 *
 * @retval       None
 */
void DAC_ConfigChannel2Data(DAC_ALIGN_T align, uint16_t data)
{
    __IO uint32_t tmp = 0;

    tmp = (uint32_t)DAC_BASE;
    tmp += 0x00000014 + align;

    /* Set the DAC channel1 selected data holding register */
    *(__IO uint32_t *) tmp = data;
}

/*!
 * @brief        Set the specified data holding register value for dual DAC channel
 *
 * @param        align: Dual DAC channel data alignment
 *                      This parameter can be one of the following values:
 *                      @arg DAC_ALIGN_12BIT_R : 12-bit right-aligned data
 *                      @arg DAC_ALIGN_12BIT_L : 12-bit left-aligned data
 *                      @arg DAC_ALIGN_8BIT_R  : 8-bit right-aligned data
 *
 * @param        data2: Data for channel2 to be loaded in the selected data register.
 *
 * @param        data1: Data for channel1 to be loaded in the selected data register
 *
 * @retval       None
 */
void DAC_ConfigDualChannelData(DAC_ALIGN_T align, uint16_t data2, uint16_t data1)
{
    uint32_t data = 0, tmp = 0;

    /* Calculate and set dual DAC data holding register value */
    if (align == DAC_ALIGN_8BIT_R)
    {
        data = ((uint32_t)data2 << 8) | data1;
    }
    else
    {
        data = ((uint32_t)data2 << 16) | data1;
    }

    tmp = (uint32_t)DAC_BASE;
    tmp += 0x00000020 + align;

    /* Set the dual DAC selected data holding register */
    *(__IO uint32_t *)tmp = data;
}

/*!
 * @brief     Reads the specified DAC channel data output value.
 *
 * @param     channel: Select the DAC channel.
 *                     This parameter can be one of the following values:
 *                     @arg DAC_CHANNEL_1 : DAC channel 1
 *                     @arg DAC_CHANNEL_2 : DAC channel 2
 *
 * @retval    The data output value of the specified DAC channel.
 */
uint16_t DAC_ReadDataOutputValue(DAC_CHANNEL_T channel)
{
    __IO uint32_t tmp = 0;

    tmp = (uint32_t) DAC_BASE ;
    tmp += 0x0000002C + ((uint32_t)channel >> 2);

    /* Returns the DAC channel data output register value */
    return (uint16_t) (*(__IO uint32_t*) tmp);
}

/**@} end of group DAC_Fuctions*/
/**@} end of group DAC_Driver*/
/**@} end of group Peripherals_Library*/
