/*!
 * @file    	apm32f10x_adc.c
 * @brief	 	This file provides all the ADC firmware functions
 *
 * @details	
 *
 * @version		V1.0.0
 * @author  	
 * @date    	2019-8-6
 *
 */
#include "apm32f10x_adc.h"
#include "apm32f10x_rcm.h"




/*!
 * @brief		Reset adc peripheral registers to their default reset values
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_Reset(ADC_T* adc)
{
	if(adc == ADC1)
	{
		RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_ADC1);
		RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_ADC1);
	}
	else if(adc == ADC2)
	{
		RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_ADC2);
		RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_ADC2);
	}
	else
	{
		if (adc == ADC3)
		{
			RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_ADC3);
			RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_ADC3);
		}
	}
}

/*!
 * @brief		Config the ADC peripheral according to the specified parameters in the configStruct
 *
 * @param		adc: ADC peripheral
 *
 * @retval		configStruct: pointer to a ADC_ConfigStruct_T structure
 *
 * @note 
 */
void ADC_Config(ADC_T* adc, ADC_ConfigStruct_T* configStruct)
{
	adc->CTRL1_B.DMS = RESET;
	adc->CTRL1_B.SMEN = RESET;
	adc->CTRL1 |= (uint32_t)((configStruct->Mode) | ((uint32_t)configStruct->ScanConvMode << 8));
	
	adc->CTRL2_B.CCM = RESET;
	adc->CTRL2_B.DAM = RESET;
	adc->CTRL2_B.RGEXTSEL = RESET;
	adc->CTRL2 |= (uint32_t)(configStruct->DataAlign | configStruct->ExternalTrigConv |
				((uint32_t)configStruct->ContinuosConvMode << 1));
	
	adc->RGSQ1_B.RGSL = RESET;
	adc->RGSQ1_B.RGSL |= (uint8_t)(configStruct->NbrOfChannel - (uint8_t)1);
}

/*!
 * @brief		Fills each ADC_ConfigStruct_T member with its default value
 *
 * @param		configStruct: pointer to a ADC_ConfigStruct_T structure which will be initialized
 *
 * @retval		None
 *
 * @note 
 */
void ADC_StructInit(ADC_ConfigStruct_T* configStruct)
{
	configStruct->Mode = ADC_MODE_INDEPENDENT;
	configStruct->ScanConvMode = DISABLE;
	configStruct->ContinuosConvMode = DISABLE;
	configStruct->ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
	configStruct->DataAlign = ADC_DATA_ALIGN_RIGHT;
	configStruct->NbrOfChannel = 1;
}

/*!
 * @brief		Enables the specified ADC peripheral
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_Enable(ADC_T* adc)
{
	adc->CTRL2_B.ADCON = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC peripheral
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_Disable(ADC_T* adc)
{
	adc->CTRL2_B.ADCON = BIT_RESET;
}

/*!
 * @brief		Disable the specified ADC DMA request
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_DMA_Enable(ADC_T* adc)
{
	adc->CTRL2_B.DMAEN = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC DMA request
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_DMA_Disable(ADC_T* adc)
{
	adc->CTRL2_B.DMAEN = BIT_RESET;
}

/*!
 * @brief		Enable the specified ADC interrupt
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		interrupt: Select the ADC interrupt sources
 *
 * @retval		None
 *
 * @note 
 */
void ADC_EnableInterrupt(ADC_T* adc, uint16_t interrupt)
{
	uint8_t mask = 0;
	mask = (uint8_t)interrupt;
	adc->CTRL1 |= mask;
}

/*!
 * @brief		Disable the specified ADC interrupt
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		interrupt: Select the ADC interrupt sources
 *
 * @retval		None
 *
 * @note 
 */
void ADC_DisableInterrupt(ADC_T* adc, uint16_t interrupt)
{
	uint8_t mask = 0;
	mask = (uint8_t)interrupt;
	adc->CTRL1 &= (~(uint32_t)mask);
}

/*!
 * @brief		Reset the specified ADC calibration registers
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_Calibration_Reset(ADC_T* adc)
{
	adc->CTRL2_B.CALRST = BIT_SET;
}

/*!
 * @brief		Reads the specified ADC calibration reset flag
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		The new state of ADC calibration reset registers
 *
 * @note 
 */
uint8_t ADC_ReadCalibrationResetFlag(ADC_T* adc)
{
	uint8_t ret;
	ret = (adc->CTRL2_B.CALRST) ? BIT_SET : BIT_RESET;
	return ret;
}

/*!
 * @brief		Starts the specified ADC calibration
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_CalibrationStart(ADC_T* adc)
{
	adc->CTRL2_B.CALSTR = BIT_SET;
}

/*!
 * @brief		Reads the specified ADC calibration start flag
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		The new state of ADC calibration start registers
 *
 * @note 
 */
uint8_t ADC_ReadCalibrationStartFlag(ADC_T* adc)
{
	uint8_t ret;
	ret = (adc->CTRL2_B.CALSTR) ? BIT_SET : BIT_RESET;
	return ret;
}

/*!
 * @brief		Enables the specified ADC software start conversion
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_SoftwareStartConvEnable(ADC_T* adc)
{
	adc->CTRL2_B.RGEXTGEN = BIT_SET;
	adc->CTRL2_B.RGSWSTR = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC software start conversion
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_SoftwareStartConvDisable(ADC_T* adc)
{
	adc->CTRL2_B.RGEXTGEN = BIT_RESET;
	adc->CTRL2_B.RGSWSTR = BIT_RESET;
}

/*!
 * @brief		Reads the specified ADC Software start conversion flag
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		The new state of ADC Software start conversion registers
 *
 * @note 
 */
uint8_t ADC_ReadSoftwareStartConvFlag(ADC_T* adc)
{
	uint8_t ret;
	ret = (adc->CTRL2_B.RGSWSTR) ? BIT_SET : BIT_RESET;
	return ret;
}

/*!
 * @brief		Configures the specified ADC regular discontinuous mode
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		number: The number of the discontinuous mode regular channels
 *
 * @retval		None
 *
 * @note 
 */
void ADC_DiscModeChannelCountConfig(ADC_T* adc, uint8_t number)
{
	adc->CTRL1_B.DMCC |= number - 1;
}

/*!
 * @brief		Enable the specified ADC regular discontinuous mode
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_DiscModeEnable(ADC_T* adc)
{
	adc->CTRL1_B.RGDMEN = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC regular discontinuous mode
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_DiscModeDisable(ADC_T* adc)
{
	adc->CTRL1_B.RGDMEN = BIT_RESET;
}

/*!
 * @brief		Configures the specified ADC regular channel
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		channel: Select the ADC channel
 *
 * @param		rank: The rank in the regular group sequencer
 *
 * @param		sampleTime: the specified ADC channel SampleTime
 *
 * @retval		None
 *
 * @note 
 */
void ADC_RegularChannelConfig(ADC_T* adc, uint8_t channel,uint8_t rank, uint8_t sampleTime)
{
	uint32_t temp1 = 0;
	uint32_t temp2 = 0;
	if(channel > ADC_CHANNEL_9)
	{
		temp1 = adc->SMPT1;
		temp2 = SMPT1_SMPT_SET << (3 * (channel - 10));
		temp1 &= ~temp2;
		temp2 = (uint32_t)sampleTime << (3 * (channel - 10));
		temp1 |= temp2;
		adc->SMPT1 = temp1;
	}
	else
	{
		temp1 = adc->SMPT2;
		temp2 = SMPT2_SMPT_SET << (3 * channel);
		temp1 &= ~temp2;
		temp2 = (uint32_t)sampleTime << (3 * channel);
		temp1 |= temp2;
		adc->SMPT2 = temp1;
	}
	
	if(rank < 7)
	{
		temp1 = adc->RGSQ3;
		temp2 = RGSQ3_RGSQ_SET << (5 * (rank - 1));
		temp1 &= ~temp2;
		temp2 = (uint32_t)channel << (5 * (rank - 1));
		temp1 |= temp2;
		adc->RGSQ3 = temp1;
	}
	else if(rank < 13)
	{
		temp1 = adc->RGSQ2;
		temp2 = RGSQ2_RGSQ_SET << (5 * (rank - 7));
		temp1 &= ~temp2;
		temp2 = (uint32_t)channel << (5 * (rank - 7));
		temp1 |= temp2;
		adc->RGSQ2 = temp1;		
	}
	else
	{
		temp1 = adc->RGSQ1;
		temp2 = RGSQ1_RGSQ_SET << (5 * (rank - 13));
		temp1 &= ~temp2;
		temp2 = (uint32_t)channel << (5 * (rank - 13));
		temp1 |= temp2;
		adc->RGSQ1 = temp1;
	}
}

/*!
 * @brief		Enable the specified ADC regular channel external trigger
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_ExternalTrigConvEnable(ADC_T* adc)
{
	adc->CTRL2_B.RGEXTGEN = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC regular channel external trigger
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_ExternalTrigConvDisable(ADC_T* adc)
{
	adc->CTRL2_B.RGEXTGEN = BIT_RESET;
}

/*!
 * @brief		Reads the specified ADC conversion result data
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		The Data conversion value
 *
 * @note 
 */
uint16_t ADC_ReadConversionValue(ADC_T* adc)
{
	return (uint16_t) adc->RDG;
}

/*!
 * @brief		Reads the specified ADC conversion result data in dual mode
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		The Data conversion value
 *
 * @note 
 */
uint32_t ADC_ReadDualModeConversionValue(ADC_T* adc)
{
	  return (*(__IOM uint32_t *) RDG_ADDRESS);
}

/*!
 * @brief		Enable the specified ADC automatic injected group
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_InjectedConvEnable(ADC_T* adc)
{
	adc->CTRL1_B.IJAEN = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC automatic injected group
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_InjectedConvDisable(ADC_T* adc)
{
	adc->CTRL1_B.IJAEN = BIT_RESET;
}

/*!
 * @brief		Enable the specified ADC discontinuous mode for injected group
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_InjectedDiscModeEnable(ADC_T* adc)
{
	adc->CTRL1_B.IJDMEN = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC discontinuous mode for injected group
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_InjectedDiscModeDisable(ADC_T* adc)
{
	adc->CTRL1_B.IJDMEN = BIT_RESET;
}

/*!
 * @brief		Configures the specified ADC external trigger for injected channels conversion
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		externalTrigInjecConv: Select the ADC trigger to start injected conversion
 *
 * @retval		None
 *
 * @note 
 */
void ADC_ExternalTrigInjectedConvConfig(ADC_T* adc, uint32_t externalTrigInjecConv)
{
	adc->CTRL2_B.IJEXTSEL = RESET;
	adc->CTRL2_B.IJEXTSEL |= externalTrigInjecConv;
}

/*!
 * @brief		Ensable the specified ADC injected channels conversion through
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_ExternalTrigInjectedConvEnable(ADC_T* adc)
{
	adc->CTRL2_B.IJEXTGEN = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC injected channels conversion through
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_ExternalTrigInjectedConvDisable(ADC_T* adc)
{
	adc->CTRL2_B.IJEXTGEN = BIT_RESET;
}

/*!
 * @brief		Enable the specified ADC start of the injected
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_SoftwareStartInjectedConvEnable(ADC_T* adc)
{
	adc->CTRL2_B.IJEXTGEN = BIT_SET;
	adc->CTRL2_B.IJSWSTR = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC start of the injected
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_SoftwareStartInjectedConvDisable(ADC_T* adc)
{
	adc->CTRL2_B.IJEXTGEN = BIT_RESET;
	adc->CTRL2_B.IJSWSTR = BIT_RESET;
}

/*!
 * @brief		Reads the specified ADC Software start injected conversion Flag
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		The new state of ADC Software start injected conversion
 *
 * @note 
 */
uint8_t ADC_ReadSoftwareStartInjectedConvFlag(ADC_T* adc)
{
	uint8_t ret;
	ret = (adc->CTRL2_B.IJSWSTR) ? BIT_SET : BIT_RESET;
	return ret;
}

/*!
 * @brief		Configures the specified ADC injected channel
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		channel: Select the ADC injected channel
 *
 * @param		rank: The rank in the injected group sequencer
 *
 * @param		sampleTime: the specified ADC channel SampleTime
 *
 * @retval		None
 *
 * @note 
 */
void ADC_InjectedChannelConfig(ADC_T* adc, uint8_t channel, uint8_t rank, uint8_t sampleTime)
{
	uint32_t temp1 = 0;
	uint32_t temp2 = 0;
	uint32_t temp3 = 0;
	if (channel > ADC_CHANNEL_9)
	{
		temp1 = adc->SMPT1;
		temp2 = SMPT1_SMPT_SET << (3*(channel - 10));
		temp1 &= ~temp2;
		temp2 = (uint32_t)sampleTime << (3*(channel - 10));
		temp1 |= temp2;
		adc->SMPT1 = temp1;
	}
	else
	{
		temp1 = adc->SMPT2;
		temp2 = SMPT2_SMPT_SET << (3 * channel);
		temp1 &= ~temp2;
		temp2 = (uint32_t)sampleTime << (3 * channel);
		temp1 |= temp2;
		adc->SMPT2 = temp1;
	}
	temp1 = adc->IJSQ;
	temp3 =  (temp1 & IJSQ_IJSL_SET)>> 20;
	temp2 = IJSQ_IJSQ_SET << (5 * (uint8_t)((rank + 3) - (temp3 + 1)));
	temp1 &= ~temp2;
	temp2 = (uint32_t)channel << (5 * (uint8_t)((rank + 3) - (temp3 + 1)));
	temp1 |= temp2;
	adc->IJSQ = temp1;
}

/*!
 * @brief		Configures the specified ADC injected channel
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		length: The sequencer length
 *
 * @retval		None
 *
 * @note 
 */
void ADC_InjectedSequencerLengthConfig(ADC_T* adc, uint8_t length)
{
	adc->IJSQ_B.IJSL = RESET;
	adc->IJSQ_B.IJSL |= length - 1;
}

/*!
 * @brief		Set the specified ADC injected channel conversion value offset
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		channel: Select the ADC injected channel
 *
 * @param		offSet: The specified ADC injected channel offset
 *
 * @retval		None
 *
 * @note 
 */
void ADC_SetInjectedOffset(ADC_T* adc, uint8_t channel, uint16_t offSet)
{
	__IOM uint32_t tmp = 0;

	tmp = (uint32_t)adc;
	tmp += channel;

	*(__IOM uint32_t *) tmp = (uint32_t)offSet;	
}

/*!
 * @brief		Reads the ADC injected channel conversion value
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		channel: Select the ADC injected channel
 *
 * @retval		The Data of conversion value
 *
 * @note 
 */
uint16_t ADC_ReadInjectedConversionValue(ADC_T* adc, uint8_t channel)
{
  __IOM uint32_t temp = 0;

  temp = (uint32_t)adc;
  temp += channel + IJD_OFFSET;

  return (uint16_t) (*(__IOM uint32_t*)  temp);
}

/*!
 * @brief		Enable the specified ADC analog watchdog
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		analogWatchdog: The ADC analog watchdog configuration
 *
 * @retval		None
 *
 * @note 
 */
void ADC_AnalogWatchdogEnable(ADC_T* adc, uint32_t analogWatchdog)
{
	adc->CTRL1_B.AWDCS = BIT_RESET;
	adc->CTRL1_B.IJAWDEN = BIT_RESET;
	adc->CTRL1_B.RGAWDEN = BIT_RESET;
	adc->CTRL1 |= analogWatchdog;
}

/*!
 * @brief		Disable the specified ADC analog watchdog
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_AnalogWatchdogDisable(ADC_T* adc)
{
	adc->CTRL1_B.AWDCS = BIT_RESET;
	adc->CTRL1_B.IJAWDEN = BIT_RESET;
	adc->CTRL1_B.RGAWDEN = BIT_RESET;
	adc->CTRL1 |= ADC_ANALOG_WATCHDOG_NONE;
}

/*!
 * @brief		Configures the specified ADC high and low thresholds of the analog watchdog
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		highThreshold: The ADC analog watchdog High threshold value
 *
 * @param		lowThreshold: The ADC analog watchdog Low threshold value
 *
 * @retval		None
 *
 * @note 
 */
void ADC_AnalogWatchdogThresholdsConfig(ADC_T* adc, uint16_t highThreshold, uint16_t lowThreshold)
{
	adc->AWDHT = highThreshold;
	adc->AWDLT = lowThreshold;
}

/*!
 * @brief		Configures the specified ADC analog watchdog guarded single channel
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		channel: Select the ADC channel
 *
 * @retval		None
 *
 * @note 
 */
void ADC_AnalogWatchdogSingleChannelConfig(ADC_T* adc, uint8_t channel)
{
	adc->CTRL1_B.AWDCS = BIT_RESET;
	adc->CTRL1 |= channel;
}

/*!
 * @brief		Enable the specified ADC temperature sensor and Vrefint channel
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_TempSensorVrefintEnable(ADC_T* adc)
{
	adc->CTRL2_B.TVEN = BIT_SET;
}

/*!
 * @brief		Disable the specified ADC temperature sensor and Vrefint channel
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @retval		None
 *
 * @note 
 */
void ADC_TempSensorVrefintDisable(ADC_T* adc)
{
	adc->CTRL2_B.TVEN = BIT_RESET;
}

/*!
 * @brief		Reads the specified ADC flag
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		flag: Select the flag to check
 *
 * @retval		The new state of ADC flag
 *
 * @note 
 */
uint8_t ADC_ReadFlag(ADC_T* adc, uint8_t flag)
{
	uint8_t	status = RESET;

	if ((adc->STS & flag) != (uint8_t)RESET)
	{
		status = SET;
	}
	else
	{
	status = RESET;
	}
	return  status;
}

/*!
 * @brief		Clears the specified ADC flag
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		flag: Select the flag to clear
 *
 * @retval		None
 *
 * @note 
 */
void ADC_ClearFlag(ADC_T* adc, uint8_t flag)
{
	adc->STS = ~(uint32_t)flag;
}

/*!
 * @brief		Reads the specified ADC Interrupt flag
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		interrupt: Select the ADC interrupt source
 *
 * @retval		The new state of ADC interrupt
 *
 * @note 
 */
uint8_t ADC_ReadIntFlag(ADC_T* adc, uint16_t interrupt)
{
	uint8_t bitStatus = RESET;
	uint32_t itmask = 0;
	uint32_t enableStatus = 0;

	itmask = interrupt >> 8;
	enableStatus = (adc->CTRL1 & (uint8_t)interrupt);
	
	if (((adc->STS & itmask) != (uint32_t)RESET) && enableStatus)
	{
		bitStatus = SET;
	}
	else
	{
		bitStatus = RESET;
	}
	return  bitStatus;
}

/*!
 * @brief		Clears the specified ADC Interrupt pending bits
 *
 * @param		adc: Select the ADC or the ADC peripheral
 *
 * @param		interrupt: Select the ADC interrupt source
 *
 * @retval		None
 *
 * @note 
 */
void ADC_ClearIntPendingBit(ADC_T* adc, uint16_t interrupt)
{
  uint8_t mask = 0;

  mask = (uint8_t)(interrupt >> 8);
  adc->STS = ~(uint32_t)mask;
}
