From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- peripherals/tsadcc/tsadcc.c | 324 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 324 insertions(+) create mode 100644 peripherals/tsadcc/tsadcc.c (limited to 'peripherals/tsadcc/tsadcc.c') diff --git a/peripherals/tsadcc/tsadcc.c b/peripherals/tsadcc/tsadcc.c new file mode 100644 index 0000000..430ef8a --- /dev/null +++ b/peripherals/tsadcc/tsadcc.c @@ -0,0 +1,324 @@ +/* ---------------------------------------------------------------------------- + * 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 + +#ifdef AT91C_BASE_TSADC + +#include +#include + +//------------------------------------------------------------------------------ +// Local variables +//------------------------------------------------------------------------------ + +/// TSADC clock frequency in Hz. +static unsigned int lAdcclk = 0; + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Sets the operating mode of the TSADCC peripheral. The mode value can be +/// one of the following: +/// - AT91C_TSADC_TSAMOD_ADC_ONLY_MODE +/// - AT91C_TSADC_TSAMOD_TS_ONLY_MODE +/// \param mode Desired mode for the TSADCC. +//------------------------------------------------------------------------------ +void TSADCC_SetOperatingMode(unsigned int mode) +{ + SANITY_CHECK( (mode == AT91C_TSADC_TSAMOD_ADC_ONLY_MODE) + | (mode == AT91C_TSADC_TSAMOD_TS_ONLY_MODE)); + + AT91C_BASE_TSADC->TSADC_MR = (AT91C_BASE_TSADC->TSADC_MR + & ~AT91C_TSADC_TSAMOD) + | mode; +} + +//------------------------------------------------------------------------------ +/// Enables or disables the low resolution precision on the TSADC. +/// \param enable If true, low resolution (8 bit) is used; otherwise the TSADC +/// will use a 10-bit resolution. +//------------------------------------------------------------------------------ +void TSADCC_SetLowResolution(unsigned char enable) +{ + if (enable) { + + AT91C_BASE_TSADC->TSADC_MR |= AT91C_TSADC_LOWRES; + } + else { + + AT91C_BASE_TSADC->TSADC_MR &= ~AT91C_TSADC_LOWRES; + } +} + +//------------------------------------------------------------------------------ +/// Enables or disable SLEEP mode on the TSADC. +/// \param enable If true, the TSADC is put into sleep mode; in normal mode +/// otherwise. +//------------------------------------------------------------------------------ +void TSADCC_SetSleepMode(unsigned char enable) +{ + if (enable) { + + AT91C_BASE_TSADC->TSADC_MR |= AT91C_TSADC_SLEEP; + } + else { + + AT91C_BASE_TSADC->TSADC_MR &= ~AT91C_TSADC_SLEEP; + } +} + +//------------------------------------------------------------------------------ +/// Enables or disables pen detection on the TSADC. +/// \param enable If true, pen detection is enabled; otherwise it is disabled. +//------------------------------------------------------------------------------ +void TSADCC_SetPenDetect(unsigned char enable) +{ + if (enable) { + + AT91C_BASE_TSADC->TSADC_MR |= AT91C_TSADC_PENDET; + } + else { + + AT91C_BASE_TSADC->TSADC_MR &= ~AT91C_TSADC_PENDET; + } +} + +//------------------------------------------------------------------------------ +/// Sets the TSADC clock to the desired frequency. The prescaler is calculated +/// by this function so the resulting frequency is equal or inferior to the +/// desired one. +/// \param adcclk Desired ADC clock frequency in Hz. +/// \param mck Master clock frequency in Hz. +//------------------------------------------------------------------------------ +void TSADCC_SetAdcFrequency(unsigned int adcclk, unsigned int mck) +{ + unsigned int prescal; + + // Formula for PRESCAL is: + // PRESCAL = (MCK / (2 * ADCCLK)) + 1 + // First, we do the division, multiplied by 10 to get higher precision + // If the last digit is not zero, we round up to avoid generating a higher + // than required frequency. + prescal = (mck * 5) / adcclk; + if ((prescal % 10) > 0) { + + prescal = (prescal / 10); + } + else { + + SANITY_CHECK((prescal / 10) != 0); + prescal = (prescal / 10) - 1; + } + SANITY_CHECK(((prescal << 8) & ~AT91C_TSADC_PRESCAL) == 0); + + AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR + & ~AT91C_TSADC_PRESCAL) + | (prescal << 8); + + // Save clock frequency for further timing calculations + lAdcclk = adcclk; +} + +//------------------------------------------------------------------------------ +/// Sets the TSADC startup time. This function relies on the ADCCLK frequency +/// that has been set using TSADCC_SetAdcFrequency(), so it must have been +/// called first. +/// \param time Startup time in µseconds. +//------------------------------------------------------------------------------ +void TSADCC_SetStartupTime(unsigned int time) +{ + unsigned int startup; + + SANITY_CHECK(lAdcclk != 0); + + // Formula for STARTUP is: + // STARTUP = (time x ADCCLK) / (1000000 x 8) - 1 + // Division multiplied by 10 for higher precision + startup = (time * lAdcclk) / (800000); + if ((startup % 10) > 0) { + + startup /= 10; + } + else { + + startup /= 10; + if (startup > 0) { + + startup--; + } + } + + SANITY_CHECK((startup & ~0x7F) == 0); + AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR + & ~AT91C_TSADC_STARTUP) + | (startup << 16); +} + +//------------------------------------------------------------------------------ +/// Sets the TSADC track and hold time. This function relies on the ADCCLK +/// frequency that has been set with TSADCC_SetAdcFrequency(), to it must be +/// called first. +/// This function also sets the track and hold time in the TSADC_TSR register. +/// \param time Track and hold time in nanoseconds. +//------------------------------------------------------------------------------ +void TSADCC_SetTrackAndHoldTime(unsigned int time) +{ + unsigned int shtim; + + SANITY_CHECK(lAdcclk != 0); + + // Formula for SHTIM: + // SHTIM = (time x ADCCLK) / 1000000000 - 1 + // Since 1 billion is close to the maximum value for an integer, we first + // divide ADCCLK by 1000 to avoid an overflow + shtim = (time * (lAdcclk / 1000)) / 100000; + if ((shtim % 10) > 0) { + + shtim /= 10; + } + else { + + shtim /= 10; + if (shtim > 0) shtim--; + } + + SANITY_CHECK((shtim & ~0xF) == 0); + AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR + & ~AT91C_TSADC_SHTIM) + | (shtim << 24); + AT91C_BASE_TSADC->TSADC_TSR = shtim << 24; +} + +//------------------------------------------------------------------------------ +/// Sets the TSADC debounce time. This function relies on the ADCCLK +/// frequency that has been set with TSADCC_SetAdcFrequency(), to it must be +/// called first. +/// \param time Debounce time in nanoseconds (cannot be 0). +//------------------------------------------------------------------------------ +void TSADCC_SetDebounceTime(unsigned int time) +{ + unsigned int divisor = 1000000000; + unsigned int clock = lAdcclk; + unsigned int pendbc = 0; + unsigned int targetValue; + unsigned int currentValue; + + SANITY_CHECK(lAdcclk != 0); + SANITY_CHECK(time != 0); + + // Divide time & ADCCLK first to avoid overflows + while ((divisor > 1) && ((time % 10) == 0)) { + + time /= 10; + divisor /= 10; + } + while ((divisor > 1) && ((clock % 10) == 0)) { + + clock /= 10; + divisor /= 10; + } + + // Compute PENDBC value + targetValue = time * clock / divisor; + currentValue = 1; + while (currentValue < targetValue) { + + pendbc++; + currentValue *= 2; + } + + SANITY_CHECK((pendbc & ~0xF) == 0); + AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR + & ~AT91C_TSADC_PENDBC) + | (pendbc << 28); +} + +//------------------------------------------------------------------------------ +/// Sets the trigger mode of the TSADCC to one of the following values: +/// - AT91C_TSADC_TRGMOD_NO_TRIGGER +/// - AT91C_TSADC_TRGMOD_EXTERNAL_TRIGGER_RE +/// - AT91C_TSADC_TRGMOD_EXTERNAL_TRIGGER_FE +/// - AT91C_TSADC_TRGMOD_EXTERNAL_TRIGGER_AE +/// - AT91C_TSADC_TRGMOD_PENDET_TRIGGER +/// - AT91C_TSADC_TRGMOD_PERIODIC_TRIGGER +/// - AT91C_TSADC_TRGMOD_CONT_TRIGGER +/// \param mode Trigger mode. +//------------------------------------------------------------------------------ +void TSADCC_SetTriggerMode(unsigned int mode) +{ + SANITY_CHECK(((mode & ~AT91C_TSADC_TRGMOD) == 0) + | ((mode & AT91C_TSADC_TRGMOD) != 0x7)); + + AT91C_BASE_TSADC->TSADC_TRGR = (AT91C_BASE_TSADC->TSADC_TRGR + & ~AT91C_TSADC_TRGMOD) + | mode; +} + +//------------------------------------------------------------------------------ +/// Sets the trigger period when using the TSADCC in periodic trigger mode. +/// As usual, this function requires TSADCC_SetAdcFrequency() to be called +/// before it. +/// \param period Trigger period in nanoseconds. +//------------------------------------------------------------------------------ +void TSADCC_SetTriggerPeriod(unsigned int period) +{ + unsigned int trgper; + unsigned int divisor = 100000000; + + while ((period >= 10) && (divisor >= 10)) { + + period /= 10; + divisor /= 10; + } + + trgper = (period * lAdcclk) / divisor; + if ((trgper % 10) > 0) { + + trgper /= 10; + } + else { + + trgper /= 10; + if (trgper > 0) trgper--; + } + + SANITY_CHECK((trgper & ~0xFFFF) == 0); + AT91C_BASE_TSADC->TSADC_TRGR = (AT91C_BASE_TSADC->TSADC_TRGR + & ~AT91C_TSADC_TRGPER) + | (trgper << 16); +} + +#endif //#ifdef AT91C_BASE_TSADC -- cgit v1.2.3