/* %atmel_license% */ /** \addtogroup adc_module Working with ADC * The ADC driver provides the interface to configure and use the ADC peripheral. * \n * * It converts the analog input to digital format. The converted result could be * 12bit or 10bit. The ADC supports up to 16 analog lines. * * To Enable a ADC conversion,the user has to follow these few steps: * * * For more accurate information, please look at the ADC section of the * Datasheet. * * Related files :\n * \ref adc.c\n * \ref adc.h\n */ /*@{*/ /*@}*/ /** * \file * * Implementation of Analog-to-Digital Converter (ADC). * */ /*---------------------------------------------------------------------------- * Headers *----------------------------------------------------------------------------*/ #include "chip.h" /*---------------------------------------------------------------------------- * Exported functions *----------------------------------------------------------------------------*/ /** * \brief Initialize the ADC controller * * \param pAdc Pointer to an Adc instance. * \param idAdc ADC Index * \param trgEn trigger mode, software or Hardware * \param trgSel hardware trigger selection * \param sleepMode sleep mode selection * \param resolution resolution selection 10 bits or 12 bits * \param mckClock value of MCK in Hz * \param adcClock value of the ADC clock in Hz * \param startup value of the start up time (in ADCClock) (see datasheet) * \param tracking Tracking Time (in ADCClock cycle) */ extern void ADC_Initialize( Adc* pAdc, uint32_t idAdc ) { /* Enable peripheral clock*/ PMC_EnablePeripheral( idAdc ) ; /* Reset the controller */ pAdc->ADC_CR = ADC_CR_SWRST; /* Reset Mode Register set to default */ /* TrackTime set to 0 */ /* Transfer set to 1 */ /* settling set to 3 */ pAdc->ADC_MR = ADC_MR_TRANSFER(1) | ADC_MR_TRACKTIM(0) | ADC_MR_SETTLING_AST17 ; } /** * \brief Initialize the ADC Timing */ extern void ADC_CfgTiming( Adc* pAdc, uint32_t tracking, uint32_t settling, uint32_t transfer ) { pAdc->ADC_MR = ADC_MR_TRANSFER( transfer ) | settling | ADC_MR_TRACKTIM( tracking ) ; } /** * \brief Initialize the ADC Timing */ extern void ADC_cfgFrequency( Adc* pAdc, uint32_t startup, uint32_t prescal ) { pAdc->ADC_MR |= ADC_MR_PRESCAL( prescal ) | ( (startup<ADC_MR |= ((trgEn<<0) & ADC_MR_TRGEN) | ((trgSel<ADC_MR |= (resolution<<4) & ADC_MR_LOWRES; } /** * \brief Initialize the ADC PowerSave */ extern void ADC_CfgPowerSave( Adc* pAdc, uint32_t sleep, uint32_t fwup ) { pAdc->ADC_MR |= ( ((sleep<<5) & ADC_MR_SLEEP) | ((fwup<<6) & ADC_MR_FWUP) ); } /** * \brief Initialize the ADC Channel Mode */ extern void ADC_CfgChannelMode( Adc* pAdc, uint32_t useq, uint32_t anach ) { pAdc->ADC_MR |= ( ((anach<<23) & ADC_MR_ANACH) | ((useq <<31) & (uint32_t)ADC_MR_USEQ) ); } /** * \brief calcul_startup */ static uint32_t calcul_startup( uint32_t dwStartup ) { static uint32_t adwValue[16]={ 0, 8, 16, 24, 64, 80, 96, 112, 512, 576, 640, 704, 768, 832, 896, 960 } ; assert( dwStartup < sizeof( adwValue )/sizeof( adwValue[0] ) ) ; return adwValue[dwStartup] ; } /** * Return the Channel Converted Data * * \param pAdc Pointer to an Adc instance. * \param channel channel to get converted value */ extern uint32_t ADC_GetConvertedData( Adc* pAdc, uint32_t dwChannel ) { uint32_t dwData = 0; assert( dwChannel < 16 ) ; if ( 15 >= dwChannel ) { dwData=*(pAdc->ADC_CDR+dwChannel) ; } return dwData ; } /** * Set compare channel * * \param pAdc Pointer to an Adc instance. * \param channel channel number to be set,16 for all channels */ extern void ADC_SetCompareChannel( Adc* pAdc, uint32_t dwChannel ) { assert( dwChannel <= 16 ) ; if ( dwChannel < 16 ) { pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPALL); pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPSEL_Msk); pAdc->ADC_EMR |= (dwChannel << ADC_EMR_CMPSEL_Pos); } else { pAdc->ADC_EMR |= ADC_EMR_CMPALL; } } /** * Set compare mode * * \param pAdc Pointer to an Adc instance. * \param mode compare mode */ extern void ADC_SetCompareMode( Adc* pAdc, uint32_t dwMode ) { pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPMODE_Msk); pAdc->ADC_EMR |= (dwMode & ADC_EMR_CMPMODE_Msk) ; } /** * Set comparison window, one threshold each time * * \param pAdc Pointer to an Adc instance. * \param hi_lo Comparison Window */ extern void ADC_SetComparisonWindow( Adc* pAdc, uint32_t dwHi_Lo ) { pAdc->ADC_CWR = dwHi_Lo ; } /**---------------------------------------------------------------------------- * Test if ADC Interrupt is Masked * * \param pAdc Pointer to an Adc instance. * \param flag flag to be tested * * \return 1 if interrupt is masked, otherwise 0 */ uint32_t ADC_IsInterruptMasked( Adc* pAdc, uint32_t dwFlag ) { return (ADC_GetInterruptMaskStatus( pAdc ) & dwFlag) ; } /**---------------------------------------------------------------------------- * Test if ADC Status is Set * * \param pAdc Pointer to an Adc instance. * \param flag flag to be tested * * \return 1 if the staus is set; 0 otherwise */ extern uint32_t ADC_IsStatusSet( Adc* pAdc, uint32_t dwFlag ) { return (ADC_GetStatus( pAdc ) & dwFlag) ; } /**---------------------------------------------------------------------------- * Test if ADC channel interrupt Status is Set * * \param adc_sr Value of SR register * \param channel Channel to be tested * * \return 1 if interrupt status is set, otherwise 0 */ extern uint32_t ADC_IsChannelInterruptStatusSet( uint32_t dwAdc_sr, uint32_t dwChannel ) { uint32_t dwStatus ; if ( (dwAdc_sr & ((uint32_t)1 << dwChannel)) == ((uint32_t)1 << dwChannel) ) { dwStatus = 1 ; } else { dwStatus = 0 ; } return dwStatus ; } /** * \brief Read converted data through PDC channel * * \param pADC the pointer of adc peripheral * \param pBuffer the destination buffer * \param dwSize the size of the buffer */ extern uint32_t ADC_ReadBuffer( Adc* pADC, int16_t *pwBuffer, uint32_t dwSize ) { /* Check if the first PDC bank is free*/ if ( (pADC->ADC_RCR == 0) && (pADC->ADC_RNCR == 0) ) { pADC->ADC_RPR = (uint32_t)pwBuffer ; pADC->ADC_RCR = dwSize ; pADC->ADC_PTCR = ADC_PTCR_RXTEN; return 1; } /* Check if the second PDC bank is free*/ else { if ( pADC->ADC_RNCR == 0 ) { pADC->ADC_RNPR = (uint32_t)pwBuffer ; pADC->ADC_RNCR = dwSize ; return 1 ; } else { return 0 ; } } }