123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979 |
- //*****************************************************************************
- //
- // adc.c - Driver for the ADC.
- //
- // Copyright (c) 2005-2009 Luminary Micro, Inc. All rights reserved.
- // Software License Agreement
- //
- // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
- // exclusively on LMI's microcontroller products.
- //
- // The software is owned by LMI and/or its suppliers, and is protected under
- // applicable copyright laws. All rights are reserved. You may not combine
- // this software with "viral" open-source software in order to form a larger
- // program. Any use in violation of the foregoing restrictions may subject
- // the user to criminal sanctions under applicable laws, as well as to civil
- // liability for the breach of the terms and conditions of this license.
- //
- // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
- // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
- // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
- // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
- // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
- //
- // This is part of revision 4694 of the Stellaris Peripheral Driver Library.
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- //! \addtogroup adc_api
- //! @{
- //
- //*****************************************************************************
- #include "inc/hw_adc.h"
- #include "inc/hw_ints.h"
- #include "inc/hw_memmap.h"
- #include "inc/hw_types.h"
- #include "driverlib/adc.h"
- #include "driverlib/debug.h"
- #include "driverlib/interrupt.h"
- //*****************************************************************************
- //
- // These defines are used by the ADC driver to simplify access to the ADC
- // sequencer's registers.
- //
- //*****************************************************************************
- #define ADC_SEQ (ADC_O_SSMUX0)
- #define ADC_SEQ_STEP (ADC_O_SSMUX1 - ADC_O_SSMUX0)
- #define ADC_SSMUX (ADC_O_SSMUX0 - ADC_O_SSMUX0)
- #define ADC_SSCTL (ADC_O_SSCTL0 - ADC_O_SSMUX0)
- #define ADC_SSFIFO (ADC_O_SSFIFO0 - ADC_O_SSMUX0)
- #define ADC_SSFSTAT (ADC_O_SSFSTAT0 - ADC_O_SSMUX0)
- //*****************************************************************************
- //
- // The currently configured software oversampling factor for each of the ADC
- // sequencers.
- //
- //*****************************************************************************
- static unsigned char g_pucOversampleFactor[3];
- //*****************************************************************************
- //
- //! Registers an interrupt handler for an ADC interrupt.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param pfnHandler is a pointer to the function to be called when the
- //! ADC sample sequence interrupt occurs.
- //!
- //! This function sets the handler to be called when a sample sequence
- //! interrupt occurs. This will enable the global interrupt in the interrupt
- //! controller; the sequence interrupt must be enabled with ADCIntEnable(). It
- //! is the interrupt handler's responsibility to clear the interrupt source via
- //! ADCIntClear().
- //!
- //! \sa IntRegister() for important information about registering interrupt
- //! handlers.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCIntRegister(unsigned long ulBase, unsigned long ulSequenceNum,
- void (*pfnHandler)(void))
- {
- unsigned long ulInt;
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Determine the interrupt to register based on the sequence number.
- //
- ulInt = INT_ADC0 + ulSequenceNum;
- //
- // Register the interrupt handler.
- //
- IntRegister(ulInt, pfnHandler);
- //
- // Enable the timer interrupt.
- //
- IntEnable(ulInt);
- }
- //*****************************************************************************
- //
- //! Unregisters the interrupt handler for an ADC interrupt.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This function unregisters the interrupt handler. This will disable the
- //! global interrupt in the interrupt controller; the sequence interrupt must
- //! be disabled via ADCIntDisable().
- //!
- //! \sa IntRegister() for important information about registering interrupt
- //! handlers.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCIntUnregister(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- unsigned long ulInt;
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Determine the interrupt to unregister based on the sequence number.
- //
- ulInt = INT_ADC0 + ulSequenceNum;
- //
- // Disable the interrupt.
- //
- IntDisable(ulInt);
- //
- // Unregister the interrupt handler.
- //
- IntUnregister(ulInt);
- }
- //*****************************************************************************
- //
- //! Disables a sample sequence interrupt.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This function disables the requested sample sequence interrupt.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCIntDisable(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Disable this sample sequence interrupt.
- //
- HWREG(ulBase + ADC_O_IM) &= ~(1 << ulSequenceNum);
- }
- //*****************************************************************************
- //
- //! Enables a sample sequence interrupt.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This function enables the requested sample sequence interrupt. Any
- //! outstanding interrupts are cleared before enabling the sample sequence
- //! interrupt.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCIntEnable(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Clear any outstanding interrupts on this sample sequence.
- //
- HWREG(ulBase + ADC_O_ISC) = 1 << ulSequenceNum;
- //
- // Enable this sample sequence interrupt.
- //
- HWREG(ulBase + ADC_O_IM) |= 1 << ulSequenceNum;
- }
- //*****************************************************************************
- //
- //! Gets the current interrupt status.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param bMasked is false if the raw interrupt status is required and true if
- //! the masked interrupt status is required.
- //!
- //! This returns the interrupt status for the specified sample sequence.
- //! Either the raw interrupt status or the status of interrupts that are
- //! allowed to reflect to the processor can be returned.
- //!
- //! \return The current raw or masked interrupt status.
- //
- //*****************************************************************************
- unsigned long
- ADCIntStatus(unsigned long ulBase, unsigned long ulSequenceNum,
- tBoolean bMasked)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Return either the interrupt status or the raw interrupt status as
- // requested.
- //
- if(bMasked)
- {
- return(HWREG(ulBase + ADC_O_ISC) & (1 << ulSequenceNum));
- }
- else
- {
- return(HWREG(ulBase + ADC_O_RIS) & (1 << ulSequenceNum));
- }
- }
- //*****************************************************************************
- //
- //! Clears sample sequence interrupt source.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! The specified sample sequence interrupt is cleared, so that it no longer
- //! asserts. This must be done in the interrupt handler to keep it from being
- //! called again immediately upon exit.
- //!
- //! \note Since there is a write buffer in the Cortex-M3 processor, it may take
- //! several clock cycles before the interrupt source is actually cleared.
- //! Therefore, it is recommended that the interrupt source be cleared early in
- //! the interrupt handler (as opposed to the very last action) to avoid
- //! returning from the interrupt handler before the interrupt source is
- //! actually cleared. Failure to do so may result in the interrupt handler
- //! being immediately reentered (since NVIC still sees the interrupt source
- //! asserted).
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCIntClear(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arugments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Clear the interrupt.
- //
- HWREG(ulBase + ADC_O_ISC) = 1 << ulSequenceNum;
- }
- //*****************************************************************************
- //
- //! Enables a sample sequence.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! Allows the specified sample sequence to be captured when its trigger is
- //! detected. A sample sequence must be configured before it is enabled.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSequenceEnable(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arugments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Enable the specified sequence.
- //
- HWREG(ulBase + ADC_O_ACTSS) |= 1 << ulSequenceNum;
- }
- //*****************************************************************************
- //
- //! Disables a sample sequence.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! Prevents the specified sample sequence from being captured when its trigger
- //! is detected. A sample sequence should be disabled before it is configured.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSequenceDisable(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arugments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Disable the specified sequences.
- //
- HWREG(ulBase + ADC_O_ACTSS) &= ~(1 << ulSequenceNum);
- }
- //*****************************************************************************
- //
- //! Configures the trigger source and priority of a sample sequence.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param ulTrigger is the trigger source that initiates the sample sequence;
- //! must be one of the \b ADC_TRIGGER_* values.
- //! \param ulPriority is the relative priority of the sample sequence with
- //! respect to the other sample sequences.
- //!
- //! This function configures the initiation criteria for a sample sequence.
- //! Valid sample sequences range from zero to three; sequence zero will capture
- //! up to eight samples, sequences one and two will capture up to four samples,
- //! and sequence three will capture a single sample. The trigger condition and
- //! priority (with respect to other sample sequence execution) is set.
- //!
- //! The \e ulTrigger parameter can take on the following values:
- //!
- //! - \b ADC_TRIGGER_PROCESSOR - A trigger generated by the processor, via the
- //! ADCProcessorTrigger() function.
- //! - \b ADC_TRIGGER_COMP0 - A trigger generated by the first analog
- //! comparator; configured with ComparatorConfigure().
- //! - \b ADC_TRIGGER_COMP1 - A trigger generated by the second analog
- //! comparator; configured with ComparatorConfigure().
- //! - \b ADC_TRIGGER_COMP2 - A trigger generated by the third analog
- //! comparator; configured with ComparatorConfigure().
- //! - \b ADC_TRIGGER_EXTERNAL - A trigger generated by an input from the Port
- //! B4 pin.
- //! - \b ADC_TRIGGER_TIMER - A trigger generated by a timer; configured with
- //! TimerControlTrigger().
- //! - \b ADC_TRIGGER_PWM0 - A trigger generated by the first PWM generator;
- //! configured with PWMGenIntTrigEnable().
- //! - \b ADC_TRIGGER_PWM1 - A trigger generated by the second PWM generator;
- //! configured with PWMGenIntTrigEnable().
- //! - \b ADC_TRIGGER_PWM2 - A trigger generated by the third PWM generator;
- //! configured with PWMGenIntTrigEnable().
- //! - \b ADC_TRIGGER_ALWAYS - A trigger that is always asserted, causing the
- //! sample sequence to capture repeatedly (so long as
- //! there is not a higher priority source active).
- //!
- //! Note that not all trigger sources are available on all Stellaris family
- //! members; consult the data sheet for the device in question to determine the
- //! availability of triggers.
- //!
- //! The \e ulPriority parameter is a value between 0 and 3, where 0 represents
- //! the highest priority and 3 the lowest. Note that when programming the
- //! priority among a set of sample sequences, each must have unique priority;
- //! it is up to the caller to guarantee the uniqueness of the priorities.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSequenceConfigure(unsigned long ulBase, unsigned long ulSequenceNum,
- unsigned long ulTrigger, unsigned long ulPriority)
- {
- //
- // Check the arugments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- ASSERT((ulTrigger == ADC_TRIGGER_PROCESSOR) ||
- (ulTrigger == ADC_TRIGGER_COMP0) ||
- (ulTrigger == ADC_TRIGGER_COMP1) ||
- (ulTrigger == ADC_TRIGGER_COMP2) ||
- (ulTrigger == ADC_TRIGGER_EXTERNAL) ||
- (ulTrigger == ADC_TRIGGER_TIMER) ||
- (ulTrigger == ADC_TRIGGER_PWM0) ||
- (ulTrigger == ADC_TRIGGER_PWM1) ||
- (ulTrigger == ADC_TRIGGER_PWM2) ||
- (ulTrigger == ADC_TRIGGER_ALWAYS));
- ASSERT(ulPriority < 4);
- //
- // Compute the shift for the bits that control this sample sequence.
- //
- ulSequenceNum *= 4;
- //
- // Set the trigger event for this sample sequence.
- //
- HWREG(ulBase + ADC_O_EMUX) = ((HWREG(ulBase + ADC_O_EMUX) &
- ~(0xf << ulSequenceNum)) |
- ((ulTrigger & 0xf) << ulSequenceNum));
- //
- // Set the priority for this sample sequence.
- //
- HWREG(ulBase + ADC_O_SSPRI) = ((HWREG(ulBase + ADC_O_SSPRI) &
- ~(0xf << ulSequenceNum)) |
- ((ulPriority & 0x3) << ulSequenceNum));
- }
- //*****************************************************************************
- //
- //! Configure a step of the sample sequencer.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param ulStep is the step to be configured.
- //! \param ulConfig is the configuration of this step; must be a logical OR of
- //! \b ADC_CTL_TS, \b ADC_CTL_IE, \b ADC_CTL_END, \b ADC_CTL_D, and one of the
- //! input channel selects (\b ADC_CTL_CH0 through \b ADC_CTL_CH7).
- //!
- //! This function will set the configuration of the ADC for one step of a
- //! sample sequence. The ADC can be configured for single-ended or
- //! differential operation (the \b ADC_CTL_D bit selects differential
- //! operation when set), the channel to be sampled can be chosen (the
- //! \b ADC_CTL_CH0 through \b ADC_CTL_CH7 values), and the internal temperature
- //! sensor can be selected (the \b ADC_CTL_TS bit). Additionally, this step
- //! can be defined as the last in the sequence (the \b ADC_CTL_END bit) and it
- //! can be configured to cause an interrupt when the step is complete (the
- //! \b ADC_CTL_IE bit). The configuration is used by the ADC at the
- //! appropriate time when the trigger for this sequence occurs.
- //!
- //! The \e ulStep parameter determines the order in which the samples are
- //! captured by the ADC when the trigger occurs. It can range from zero to
- //! seven for the first sample sequence, from zero to three for the second and
- //! third sample sequence, and can only be zero for the fourth sample sequence.
- //!
- //! Differential mode only works with adjacent channel pairs (for example, 0
- //! and 1). The channel select must be the number of the channel pair to
- //! sample (for example, \b ADC_CTL_CH0 for 0 and 1, or \b ADC_CTL_CH1 for 2
- //! and 3) or undefined results will be returned by the ADC. Additionally, if
- //! differential mode is selected when the temperature sensor is being sampled,
- //! undefined results will be returned by the ADC.
- //!
- //! It is the responsibility of the caller to ensure that a valid configuration
- //! is specified; this function does not check the validity of the specified
- //! configuration.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSequenceStepConfigure(unsigned long ulBase, unsigned long ulSequenceNum,
- unsigned long ulStep, unsigned long ulConfig)
- {
- //
- // Check the arugments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- ASSERT(((ulSequenceNum == 0) && (ulStep < 8)) ||
- ((ulSequenceNum == 1) && (ulStep < 4)) ||
- ((ulSequenceNum == 2) && (ulStep < 4)) ||
- ((ulSequenceNum == 3) && (ulStep < 1)));
- //
- // Get the offset of the sequence to be configured.
- //
- ulBase += ADC_SEQ + (ADC_SEQ_STEP * ulSequenceNum);
- //
- // Compute the shift for the bits that control this step.
- //
- ulStep *= 4;
- //
- // Set the analog mux value for this step.
- //
- HWREG(ulBase + ADC_SSMUX) = ((HWREG(ulBase + ADC_SSMUX) &
- ~(0x0000000f << ulStep)) |
- ((ulConfig & 0x0f) << ulStep));
- //
- // Set the control value for this step.
- //
- HWREG(ulBase + ADC_SSCTL) = ((HWREG(ulBase + ADC_SSCTL) &
- ~(0x0000000f << ulStep)) |
- (((ulConfig & 0xf0) >> 4) << ulStep));
- }
- //*****************************************************************************
- //
- //! Determines if a sample sequence overflow occurred.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This determines if a sample sequence overflow has occurred. This will
- //! happen if the captured samples are not read from the FIFO before the next
- //! trigger occurs.
- //!
- //! \return Returns zero if there was not an overflow, and non-zero if there
- //! was.
- //
- //*****************************************************************************
- long
- ADCSequenceOverflow(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Determine if there was an overflow on this sequence.
- //
- return(HWREG(ulBase + ADC_O_OSTAT) & (1 << ulSequenceNum));
- }
- //*****************************************************************************
- //
- //! Clears the overflow condition on a sample sequence.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This will clear an overflow condition on one of the sample sequences. The
- //! overflow condition must be cleared in order to detect a subsequent overflow
- //! condition (it otherwise causes no harm).
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSequenceOverflowClear(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Clear the overflow condition for this sequence.
- //
- HWREG(ulBase + ADC_O_OSTAT) = 1 << ulSequenceNum;
- }
- //*****************************************************************************
- //
- //! Determines if a sample sequence underflow occurred.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This determines if a sample sequence underflow has occurred. This will
- //! happen if too many samples are read from the FIFO.
- //!
- //! \return Returns zero if there was not an underflow, and non-zero if there
- //! was.
- //
- //*****************************************************************************
- long
- ADCSequenceUnderflow(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Determine if there was an underflow on this sequence.
- //
- return(HWREG(ulBase + ADC_O_USTAT) & (1 << ulSequenceNum));
- }
- //*****************************************************************************
- //
- //! Clears the underflow condition on a sample sequence.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This will clear an underflow condition on one of the sample sequences. The
- //! underflow condition must be cleared in order to detect a subsequent
- //! underflow condition (it otherwise causes no harm).
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSequenceUnderflowClear(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Clear the underflow condition for this sequence.
- //
- HWREG(ulBase + ADC_O_USTAT) = 1 << ulSequenceNum;
- }
- //*****************************************************************************
- //
- //! Gets the captured data for a sample sequence.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param pulBuffer is the address where the data is stored.
- //!
- //! This function copies data from the specified sample sequence output FIFO to
- //! a memory resident buffer. The number of samples available in the hardware
- //! FIFO are copied into the buffer, which is assumed to be large enough to
- //! hold that many samples. This will only return the samples that are
- //! presently available, which may not be the entire sample sequence if it is
- //! in the process of being executed.
- //!
- //! \return Returns the number of samples copied to the buffer.
- //
- //*****************************************************************************
- long
- ADCSequenceDataGet(unsigned long ulBase, unsigned long ulSequenceNum,
- unsigned long *pulBuffer)
- {
- unsigned long ulCount;
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Get the offset of the sequence to be read.
- //
- ulBase += ADC_SEQ + (ADC_SEQ_STEP * ulSequenceNum);
- //
- // Read samples from the FIFO until it is empty.
- //
- ulCount = 0;
- while(!(HWREG(ulBase + ADC_SSFSTAT) & ADC_SSFSTAT0_EMPTY) && (ulCount < 8))
- {
- //
- // Read the FIFO and copy it to the destination.
- //
- *pulBuffer++ = HWREG(ulBase + ADC_SSFIFO);
- //
- // Increment the count of samples read.
- //
- ulCount++;
- }
- //
- // Return the number of samples read.
- //
- return(ulCount);
- }
- //*****************************************************************************
- //
- //! Causes a processor trigger for a sample sequence.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //!
- //! This function triggers a processor-initiated sample sequence if the sample
- //! sequence trigger is configured to \b ADC_TRIGGER_PROCESSOR.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCProcessorTrigger(unsigned long ulBase, unsigned long ulSequenceNum)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 4);
- //
- // Generate a processor trigger for this sample sequence.
- //
- HWREG(ulBase + ADC_O_PSSI) = 1 << ulSequenceNum;
- }
- //*****************************************************************************
- //
- //! Configures the software oversampling factor of the ADC.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param ulFactor is the number of samples to be averaged.
- //!
- //! This function configures the software oversampling for the ADC, which can
- //! be used to provide better resolution on the sampled data. Oversampling is
- //! accomplished by averaging multiple samples from the same analog input.
- //! Three different oversampling rates are supported; 2x, 4x, and 8x.
- //!
- //! Oversampling is only supported on the sample sequencers that are more than
- //! one sample in depth (that is, the fourth sample sequencer is not
- //! supported). Oversampling by 2x (for example) divides the depth of the
- //! sample sequencer by two; so 2x oversampling on the first sample sequencer
- //! can only provide four samples per trigger. This also means that 8x
- //! oversampling is only available on the first sample sequencer.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSoftwareOversampleConfigure(unsigned long ulBase,
- unsigned long ulSequenceNum,
- unsigned long ulFactor)
- {
- unsigned long ulValue;
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 3);
- ASSERT(((ulFactor == 2) || (ulFactor == 4) || (ulFactor == 8)) &&
- ((ulSequenceNum == 0) || (ulFactor != 8)));
- //
- // Convert the oversampling factor to a shift factor.
- //
- for(ulValue = 0, ulFactor >>= 1; ulFactor; ulValue++, ulFactor >>= 1)
- {
- }
- //
- // Save the sfiht factor.
- //
- g_pucOversampleFactor[ulSequenceNum] = ulValue;
- }
- //*****************************************************************************
- //
- //! Configures a step of the software oversampled sequencer.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param ulStep is the step to be configured.
- //! \param ulConfig is the configuration of this step.
- //!
- //! This function configures a step of the sample sequencer when using the
- //! software oversampling feature. The number of steps available depends on
- //! the oversampling factor set by ADCSoftwareOversampleConfigure(). The value
- //! of \e ulConfig is the same as defined for ADCSequenceStepConfigure().
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSoftwareOversampleStepConfigure(unsigned long ulBase,
- unsigned long ulSequenceNum,
- unsigned long ulStep,
- unsigned long ulConfig)
- {
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 3);
- ASSERT(((ulSequenceNum == 0) &&
- (ulStep < (8 >> g_pucOversampleFactor[ulSequenceNum]))) ||
- (ulStep < (4 >> g_pucOversampleFactor[ulSequenceNum])));
- //
- // Get the offset of the sequence to be configured.
- //
- ulBase += ADC_SEQ + (ADC_SEQ_STEP * ulSequenceNum);
- //
- // Compute the shift for the bits that control this step.
- //
- ulStep *= 4 << g_pucOversampleFactor[ulSequenceNum];
- //
- // Loop through the hardware steps that make up this step of the software
- // oversampled sequence.
- //
- for(ulSequenceNum = 1 << g_pucOversampleFactor[ulSequenceNum];
- ulSequenceNum; ulSequenceNum--)
- {
- //
- // Set the analog mux value for this step.
- //
- HWREG(ulBase + ADC_SSMUX) = ((HWREG(ulBase + ADC_SSMUX) &
- ~(0x0000000f << ulStep)) |
- ((ulConfig & 0x0f) << ulStep));
- //
- // Set the control value for this step.
- //
- HWREG(ulBase + ADC_SSCTL) = ((HWREG(ulBase + ADC_SSCTL) &
- ~(0x0000000f << ulStep)) |
- (((ulConfig & 0xf0) >> 4) << ulStep));
- if(ulSequenceNum != 1)
- {
- HWREG(ulBase + ADC_SSCTL) &= ~((ADC_SSCTL0_IE0 |
- ADC_SSCTL0_END0) << ulStep);
- }
- //
- // Go to the next hardware step.
- //
- ulStep += 4;
- }
- }
- //*****************************************************************************
- //
- //! Gets the captured data for a sample sequence using software oversampling.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulSequenceNum is the sample sequence number.
- //! \param pulBuffer is the address where the data is stored.
- //! \param ulCount is the number of samples to be read.
- //!
- //! This function copies data from the specified sample sequence output FIFO to
- //! a memory resident buffer with software oversampling applied. The requested
- //! number of samples are copied into the data buffer; if there are not enough
- //! samples in the hardware FIFO to satisfy this many oversampled data items
- //! then incorrect results will be returned. It is the caller's responsibility
- //! to read only the samples that are available and wait until enough data is
- //! available, for example as a result of receiving an interrupt.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCSoftwareOversampleDataGet(unsigned long ulBase, unsigned long ulSequenceNum,
- unsigned long *pulBuffer, unsigned long ulCount)
- {
- unsigned long ulIdx, ulAccum;
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(ulSequenceNum < 3);
- ASSERT(((ulSequenceNum == 0) &&
- (ulCount < (8 >> g_pucOversampleFactor[ulSequenceNum]))) ||
- (ulCount < (4 >> g_pucOversampleFactor[ulSequenceNum])));
- //
- // Get the offset of the sequence to be read.
- //
- ulBase += ADC_SEQ + (ADC_SEQ_STEP * ulSequenceNum);
- //
- // Read the samples from the FIFO until it is empty.
- //
- while(ulCount--)
- {
- //
- // Compute the sum of the samples.
- //
- ulAccum = 0;
- for(ulIdx = 1 << g_pucOversampleFactor[ulSequenceNum]; ulIdx; ulIdx--)
- {
- //
- // Read the FIFO and add it to the accumulator.
- //
- ulAccum += HWREG(ulBase + ADC_SSFIFO);
- }
- //
- // Write the averaged sample to the output buffer.
- //
- *pulBuffer++ = ulAccum >> g_pucOversampleFactor[ulSequenceNum];
- }
- }
- //*****************************************************************************
- //
- //! Configures the hardware oversampling factor of the ADC.
- //!
- //! \param ulBase is the base address of the ADC module.
- //! \param ulFactor is the number of samples to be averaged.
- //!
- //! This function configures the hardware oversampling for the ADC, which can
- //! be used to provide better resolution on the sampled data. Oversampling is
- //! accomplished by averaging multiple samples from the same analog input. Six
- //! different oversampling rates are supported; 2x, 4x, 8x, 16x, 32x, and 64x.
- //! Specifying an oversampling factor of zero will disable hardware
- //! oversampling.
- //!
- //! Hardware oversampling applies uniformly to all sample sequencers. It does
- //! not reduce the depth of the sample sequencers like the software
- //! oversampling APIs; each sample written into the sample sequence FIFO is a
- //! fully oversampled analog input reading.
- //!
- //! Enabling hardware averaging increases the precision of the ADC at the cost
- //! of throughput. For example, enabling 4x oversampling reduces the
- //! throughput of a 250 Ksps ADC to 62.5 Ksps.
- //!
- //! \note Hardware oversampling is available beginning with Rev C0 of the
- //! Stellaris microcontroller.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- ADCHardwareOversampleConfigure(unsigned long ulBase, unsigned long ulFactor)
- {
- unsigned long ulValue;
- //
- // Check the arguments.
- //
- ASSERT((ulBase == ADC0_BASE) || (ulBase == ADC1_BASE));
- ASSERT(((ulFactor == 0) || (ulFactor == 2) || (ulFactor == 4) ||
- (ulFactor == 8) || (ulFactor == 16) || (ulFactor == 32) ||
- (ulFactor == 64)));
- //
- // Convert the oversampling factor to a shift factor.
- //
- for(ulValue = 0, ulFactor >>= 1; ulFactor; ulValue++, ulFactor >>= 1)
- {
- }
- //
- // Write the shift factor to the ADC to configure the hardware oversampler.
- //
- HWREG(ulBase + ADC_O_SAC) = ulValue;
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|