/* ---------------------------------------------------------------------------- | |
* ATMEL Microcontroller Software Support | |
* ---------------------------------------------------------------------------- | |
* Copyright (c) 2008, Atmel Corporation | |
* | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* - Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the disclaimer below. | |
* | |
* Atmel's name may not be used to endorse or promote products derived from | |
* this software without specific prior written permission. | |
* | |
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR | |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, | |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | |
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* ---------------------------------------------------------------------------- | |
*/ | |
//------------------------------------------------------------------------------ | |
// Headers | |
//------------------------------------------------------------------------------ | |
#include <board.h> | |
#include <adc/adc.h> | |
#include <utility/trace.h> | |
#include <utility/assert.h> | |
//----------------------------------------------------------------------------- | |
/// Configure the Mode Register of the ADC controller | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param mode value to write in mode register | |
//----------------------------------------------------------------------------- | |
//replaced with macro definition in adc.h | |
//void ADC_CfgModeReg(AT91S_ADC *pAdc, unsigned int mode, unsigned int extmode) | |
//{ | |
// ASSERT((mode&0xF00000C0)== 0, "ADC Bad configuration ADC MR"); | |
// | |
// // Write to the MR register | |
// pAdc->ADC_MR = mode; | |
//} | |
//------------------------------------------------------------------------------ | |
// Global Functions | |
//------------------------------------------------------------------------------ | |
//----------------------------------------------------------------------------- | |
/// Initialize the ADC controller | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param trgEn trigger mode, software or Hardware | |
/// \param trgSel hardware trigger selection | |
/// \param sleepMode sleep mode selection | |
/// \param resolution resolution selection 8 bits or 10 bits | |
/// \param mckClock value of MCK in Hz | |
/// \param adcClock value of the ADC clock in Hz | |
/// \param startupTime value of the start up time (in µs) (see datasheet) | |
/// \param sampleAndHoldTime (in ns) | |
//----------------------------------------------------------------------------- | |
void ADC_Initialize (AT91S_ADC *pAdc, | |
unsigned char idAdc, | |
unsigned char trgEn, | |
unsigned char trgSel, | |
unsigned char sleepMode, | |
unsigned char resolution, | |
unsigned int mckClock, | |
unsigned int adcClock, | |
unsigned int startupTime, | |
unsigned int sampleAndHoldTime) | |
{ | |
unsigned int prescal; | |
unsigned int startup; | |
unsigned int shtim; | |
ASSERT(startupTime<=ADC_STARTUP_TIME_MAX, "ADC Bad startupTime\n\r"); | |
ASSERT(sampleAndHoldTime>=ADC_TRACK_HOLD_TIME_MIN, "ADC Bad sampleAndHoldTime\n\r"); | |
// Example: | |
// 5 MHz operation, 20µs startup time, 600ns track and hold time | |
// PRESCAL: Prescaler Rate Selection ADCClock = MCK / ( (PRESCAL+1) * 2 ) | |
// PRESCAL = [MCK / (ADCClock * 2)] -1 = [48/(5*2)]-1 = 3,8 | |
// PRESCAL = 4 -> 48/((4+1)*2) = 48/10 = 4.8MHz | |
// 48/((3+1)*2) = 48/8 = 6MHz | |
// Startup Time = (STARTUP+1) * 8 / ADCClock | |
// STARTUP = [(Startup Time * ADCClock)/8]-1 = [(20 10e-6 * 5000000)/8]-1 = 11,5 | |
// STARTUP = 11 -> (11+1)*8/48000000 = 96/4800000 = 20µs | |
// | |
// Sample & Hold Time = (SHTIM+1) / ADCClock | |
// SHTIM = (HoldTime * ADCClock)-1 = (600 10e-9 * 5000000)-1 = 2 | |
// SHTIM = 2 -> (2+1)/4800000 = 1/1200000 = 833ns | |
prescal = (mckClock / (2*adcClock)) - 1; | |
startup = ((adcClock/1000000) * startupTime / 8) - 1; | |
shtim = (((adcClock/1000000) * sampleAndHoldTime)/1000) - 1; | |
ASSERT( (prescal<0x3F), "ADC Bad PRESCAL\n\r"); | |
ASSERT(startup<0x7F, "ADC Bad STARTUP\n\r"); | |
ASSERT(shtim<0xF, "ADC Bad SampleAndHoldTime\n\r"); | |
TRACE_DEBUG("adcClock:%d MasterClock:%d\n\r", (mckClock/((prescal+1)*2)), mckClock); | |
TRACE_DEBUG("prescal:0x%X startup:0x%X shtim:0x%X\n\r", prescal, startup, shtim); | |
if( adcClock != (mckClock/((prescal+1)*2)) ) { | |
TRACE_WARNING("User and calculated adcClocks are different : user=%d calc=%d\n\r", | |
adcClock, (mckClock/((prescal+1)*2))); | |
} | |
// Enable peripheral clock | |
AT91C_BASE_PMC->PMC_PCER = 1 << idAdc; | |
// Reset the controller | |
ADC_SoftReset(pAdc); | |
// Write to the MR register | |
ADC_CfgModeReg( pAdc, | |
( trgEn & AT91C_ADC_TRGEN) | |
| ( trgSel & AT91C_ADC_TRGSEL) | |
| ( resolution & AT91C_ADC_LOWRES) | |
| ( sleepMode & AT91C_ADC_SLEEP) | |
| ( (prescal<<8) & AT91C_ADC_PRESCAL) | |
| ( (startup<<16) & AT91C_ADC_STARTUP) | |
| ( (shtim<<24) & AT91C_ADC_SHTIM) ); | |
} | |
//----------------------------------------------------------------------------- | |
/// Return the Mode Register of the ADC controller value | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \return ADC Mode register | |
//----------------------------------------------------------------------------- | |
//replaced with macro definition in adc.h | |
//unsigned int ADC_GetModeReg(AT91S_ADC *pAdc) | |
//{ | |
// return pAdc->ADC_MR; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Enable Channel | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param channel channel to enable | |
//----------------------------------------------------------------------------- | |
//void ADC_EnableChannel(AT91S_ADC *pAdc, unsigned int channel) | |
//{ | |
// ASSERT(channel < 8, "ADC Channel not exist"); | |
// | |
// // Write to the CHER register | |
// pAdc->ADC_CHER = (1 << channel); | |
//} | |
//----------------------------------------------------------------------------- | |
/// Disable Channel | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param channel channel to disable | |
//----------------------------------------------------------------------------- | |
//void ADC_DisableChannel (AT91S_ADC *pAdc, unsigned int channel) | |
//{ | |
// ASSERT(channel < 8, "ADC Channel not exist"); | |
// | |
// // Write to the CHDR register | |
// pAdc->ADC_CHDR = (1 << channel); | |
//} | |
//----------------------------------------------------------------------------- | |
/// Return chanel status | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \return ADC Channel Status Register | |
//----------------------------------------------------------------------------- | |
//unsigned int ADC_GetChannelStatus(AT91S_ADC *pAdc) | |
//{ | |
// return pAdc->ADC_CHSR; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Software request for a analog to digital conversion | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
//----------------------------------------------------------------------------- | |
//void ADC_StartConversion(AT91S_ADC *pAdc) | |
//{ | |
// pAdc->ADC_CR = AT91C_ADC_START; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Software reset | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
//----------------------------------------------------------------------------- | |
//void ADC_SoftReset(AT91S_ADC *pAdc) | |
//{ | |
// pAdc->ADC_CR = AT91C_ADC_SWRST; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Return the Last Converted Data | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \return Last Converted Data | |
//----------------------------------------------------------------------------- | |
//unsigned int ADC_GetLastConvertedData(AT91S_ADC *pAdc) | |
//{ | |
// return pAdc->ADC_LCDR; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Return the Channel Converted Data | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param channel channel to get converted value | |
/// \return Channel converted data of the specified channel | |
//----------------------------------------------------------------------------- | |
unsigned int ADC_GetConvertedData(AT91S_ADC *pAdc, unsigned int channel) | |
{ | |
unsigned int data=0; | |
ASSERT(channel < 8, "ADC channel not exist"); | |
switch(channel) { | |
case 0: data = pAdc->ADC_CDR0; break; | |
case 1: data = pAdc->ADC_CDR1; break; | |
case 2: data = pAdc->ADC_CDR2; break; | |
case 3: data = pAdc->ADC_CDR3; break; | |
#ifdef AT91C_ADC_CDR4 | |
case 4: data = pAdc->ADC_CDR4; break; | |
#endif | |
#ifdef AT91C_ADC_CDR5 | |
case 5: data = pAdc->ADC_CDR5; break; | |
#endif | |
#ifdef AT91C_ADC_CDR6 | |
case 6: data = pAdc->ADC_CDR6; break; | |
#endif | |
#ifdef AT91C_ADC_CDR7 | |
case 7: data = pAdc->ADC_CDR7; break; | |
#endif | |
} | |
return data; | |
} | |
//----------------------------------------------------------------------------- | |
/// Enable ADC interrupt | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param flag IT to be enabled | |
//----------------------------------------------------------------------------- | |
//void ADC_EnableIt(AT91S_ADC *pAdc, unsigned int flag) | |
//{ | |
// ASSERT((flag&0xFFF00000)== 0, "ADC bad interrupt IER"); | |
// | |
// // Write to the IER register | |
// pAdc->ADC_IER = flag; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Enable ADC Data Ready interrupt | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
//----------------------------------------------------------------------------- | |
//void ADC_EnableDataReadyIt(AT91S_ADC *pAdc) | |
//{ | |
// pAdc->ADC_IER = AT91C_ADC_DRDY; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Disable ADC interrupt | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param flag IT to be disabled | |
//----------------------------------------------------------------------------- | |
//void ADC_DisableIt(AT91S_ADC *pAdc, unsigned int flag) | |
//{ | |
// ASSERT((flag&0xFFF00000)== 0, "ADC bad interrupt IDR"); | |
// | |
// // Write to the IDR register | |
// pAdc->ADC_IDR = flag; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Return ADC Interrupt Status | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \return ADC Stats register | |
//----------------------------------------------------------------------------- | |
//unsigned int ADC_GetStatus(AT91S_ADC *pAdc) | |
//{ | |
// return pAdc->ADC_SR; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Return ADC Interrupt Mask Status | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \return ADC Interrupt Mask Register | |
//----------------------------------------------------------------------------- | |
//unsigned int ADC_GetInterruptMaskStatus(AT91S_ADC *pAdc) | |
//{ | |
// return pAdc->ADC_IMR; | |
//} | |
//----------------------------------------------------------------------------- | |
/// Test if ADC Interrupt is Masked | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param flag flag to be tested | |
/// \return 1 if interrupt is masked, otherwise 0 | |
//----------------------------------------------------------------------------- | |
unsigned int ADC_IsInterruptMasked(AT91S_ADC *pAdc, unsigned int flag) | |
{ | |
return (ADC_GetInterruptMaskStatus(pAdc) & flag); | |
} | |
//----------------------------------------------------------------------------- | |
/// Test if ADC Status is Set | |
/// \param pAdc Pointer to an AT91S_ADC instance. | |
/// \param flag flag to be tested | |
/// \return 1 if the staus is set; 0 otherwise | |
//----------------------------------------------------------------------------- | |
unsigned int ADC_IsStatusSet(AT91S_ADC *pAdc, unsigned int flag) | |
{ | |
return (ADC_GetStatus(pAdc) & flag); | |
} | |
//----------------------------------------------------------------------------- | |
/// 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 | |
//----------------------------------------------------------------------------- | |
unsigned char ADC_IsChannelInterruptStatusSet(unsigned int adc_sr, | |
unsigned int channel) | |
{ | |
unsigned char status; | |
if((adc_sr & (1<<channel)) == (1<<channel)) { | |
status = 1; | |
} | |
else { | |
status = 0; | |
} | |
return status; | |
} | |