| //***************************************************************************** | |
| // | |
| // adc.c - Driver for the ADC. | |
| // | |
| // Copyright (c) 2005,2006 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 Stellaris Family of microcontroller products. | |
| // | |
| // The software is owned by LMI and/or its suppliers, and is protected under | |
| // applicable copyright laws. All rights are reserved. 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 991 of the Stellaris Driver Library. | |
| // | |
| //***************************************************************************** | |
| //***************************************************************************** | |
| // | |
| //! \addtogroup adc_api | |
| //! @{ | |
| // | |
| //***************************************************************************** | |
| #include "../hw_adc.h" | |
| #include "../hw_ints.h" | |
| #include "../hw_memmap.h" | |
| #include "../hw_types.h" | |
| #include "adc.h" | |
| #include "debug.h" | |
| #include "interrupt.h" | |
| //***************************************************************************** | |
| // | |
| // The currently configured software oversampling factor for each of the ADC | |
| // sequencers. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_pucoverssamplefactor) || defined(BUILD_ALL) | |
| unsigned char g_pucOversampleFactor[3]; | |
| #else | |
| extern unsigned char g_pucOversampleFactor[3]; | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_intregister) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCIntRegister(unsigned long ulBase, unsigned long ulSequenceNum, | |
| void (*pfnHandler)(void)) | |
| { | |
| unsigned long ulInt; | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_intunregister) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCIntUnregister(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| unsigned long ulInt; | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_intdisable) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCIntDisable(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Disable this sample sequence interrupt. | |
| // | |
| HWREG(ulBase + ADC_O_IM) &= ~(1 << ulSequenceNum); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_intenable) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCIntEnable(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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; | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_intstatus) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| unsigned long | |
| ADCIntStatus(unsigned long ulBase, unsigned long ulSequenceNum, | |
| tBoolean bMasked) | |
| { | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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)); | |
| } | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| //! | |
| //! \return None. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_intclear) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCIntClear(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arugments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Clear the interrupt. | |
| // | |
| HWREG(ulBase + ADC_O_ISC) = 1 << ulSequenceNum; | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_sequenceenable) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCSequenceEnable(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arugments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Enable the specified sequence. | |
| // | |
| HWREG(ulBase + ADC_O_ACTSS) |= 1 << ulSequenceNum; | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_sequencedisable) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCSequenceDisable(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arugments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Disable the specified sequences. | |
| // | |
| HWREG(ulBase + ADC_O_ACTSS) &= ~(1 << ulSequenceNum); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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 parameter \b ulTrigger 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 parameter \b ulPriority 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_sequenceconfigure) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCSequenceConfigure(unsigned long ulBase, unsigned long ulSequenceNum, | |
| unsigned long ulTrigger, unsigned long ulPriority) | |
| { | |
| // | |
| // Check the arugments. | |
| // | |
| ASSERT(ulBase == ADC_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)); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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 \b 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 (e.g. 0 and 1). | |
| //! The channel select must be the number of the channel pair to sample (e.g. | |
| //! \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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_sequencestepconfigure) || defined(BUILD_ALL) || \ | |
| defined(DOXYGEN) | |
| void | |
| ADCSequenceStepConfigure(unsigned long ulBase, unsigned long ulSequenceNum, | |
| unsigned long ulStep, unsigned long ulConfig) | |
| { | |
| // | |
| // Check the arugments. | |
| // | |
| ASSERT(ulBase == ADC_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_O_SEQ + (ADC_O_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_O_X_SSMUX) = ((HWREG(ulBase + ADC_O_X_SSMUX) & | |
| ~(0x0000000f << ulStep)) | | |
| ((ulConfig & 0x0f) << ulStep)); | |
| // | |
| // Set the control value for this step. | |
| // | |
| HWREG(ulBase + ADC_O_X_SSCTL) = ((HWREG(ulBase + ADC_O_X_SSCTL) & | |
| ~(0x0000000f << ulStep)) | | |
| (((ulConfig & 0xf0) >> 4) << ulStep)); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_sequenceoverflow) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| long | |
| ADCSequenceOverflow(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Determine if there was an overflow on this sequence. | |
| // | |
| return(HWREG(ulBase + ADC_O_OSTAT) & (1 << ulSequenceNum)); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_sequenceunderflow) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| long | |
| ADCSequenceUnderflow(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Determine if there was an underflow on this sequence. | |
| // | |
| return(HWREG(ulBase + ADC_O_USTAT) & (1 << ulSequenceNum)); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_sequencedataget) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| long | |
| ADCSequenceDataGet(unsigned long ulBase, unsigned long ulSequenceNum, | |
| unsigned long *pulBuffer) | |
| { | |
| unsigned long ulCount; | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Get the offset of the sequence to be read. | |
| // | |
| ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum); | |
| // | |
| // Read samples from the FIFO until it is empty. | |
| // | |
| ulCount = 0; | |
| while(!(HWREG(ulBase + ADC_O_X_SSFSTAT) & ADC_SSFSTAT_EMPTY) && | |
| (ulCount < 8)) | |
| { | |
| // | |
| // Read the FIFO and copy it to the destination. | |
| // | |
| *pulBuffer++ = HWREG(ulBase + ADC_O_X_SSFIFO); | |
| // | |
| // Increment the count of samples read. | |
| // | |
| ulCount++; | |
| } | |
| // | |
| // Return the number of samples read. | |
| // | |
| return(ulCount); | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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 ADC_TRIGGER_PROCESSOR. | |
| //! | |
| //! \return None. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_processortrigger) || defined(BUILD_ALL) || defined(DOXYGEN) | |
| void | |
| ADCProcessorTrigger(unsigned long ulBase, unsigned long ulSequenceNum) | |
| { | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_BASE); | |
| ASSERT(ulSequenceNum < 4); | |
| // | |
| // Generate a processor trigger for this sample sequence. | |
| // | |
| HWREG(ulBase + ADC_O_PSSI) = 1 << ulSequenceNum; | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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 (i.e. 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_softwareoversampleconfigure) || defined(BUILD_ALL) || \ | |
| defined(DOXYGEN) | |
| void | |
| ADCSoftwareOversampleConfigure(unsigned long ulBase, | |
| unsigned long ulSequenceNum, | |
| unsigned long ulFactor) | |
| { | |
| unsigned long ulValue; | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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; | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_softwareoversamplestepconfigure) || defined(BUILD_ALL) || \ | |
| defined(DOXYGEN) | |
| void | |
| ADCSoftwareOversampleStepConfigure(unsigned long ulBase, | |
| unsigned long ulSequenceNum, | |
| unsigned long ulStep, | |
| unsigned long ulConfig) | |
| { | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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_O_SEQ + (ADC_O_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_O_X_SSMUX) = ((HWREG(ulBase + ADC_O_X_SSMUX) & | |
| ~(0x0000000f << ulStep)) | | |
| ((ulConfig & 0x0f) << ulStep)); | |
| // | |
| // Set the control value for this step. | |
| // | |
| HWREG(ulBase + ADC_O_X_SSCTL) = ((HWREG(ulBase + ADC_O_X_SSCTL) & | |
| ~(0x0000000f << ulStep)) | | |
| (((ulConfig & 0xf0) >> 4) << ulStep)); | |
| if(ulSequenceNum != 1) | |
| { | |
| HWREG(ulBase + ADC_O_X_SSCTL) &= ~((ADC_SSCTL_IE0 | | |
| ADC_SSCTL_END0) << ulStep); | |
| } | |
| // | |
| // Go to the next hardware step. | |
| // | |
| ulStep += 4; | |
| } | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_softwareoversampledataget) || defined(BUILD_ALL) || \ | |
| defined(DOXYGEN) | |
| void | |
| ADCSoftwareOversampleDataGet(unsigned long ulBase, unsigned long ulSequenceNum, | |
| unsigned long *pulBuffer, unsigned long ulCount) | |
| { | |
| unsigned long ulIdx, ulAccum; | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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_O_SEQ + (ADC_O_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_O_X_SSFIFO); | |
| } | |
| // | |
| // Write the averaged sample to the output buffer. | |
| // | |
| *pulBuffer++ = ulAccum >> g_pucOversampleFactor[ulSequenceNum]; | |
| } | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| //! 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 the hardware | |
| //! oversampler. | |
| //! | |
| //! 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. | |
| // | |
| //***************************************************************************** | |
| #if defined(GROUP_hardwareoversampleconfigure) || defined(BUILD_ALL) || \ | |
| defined(DOXYGEN) | |
| void | |
| ADCHardwareOversampleConfigure(unsigned long ulBase, | |
| unsigned long ulFactor) | |
| { | |
| unsigned long ulValue; | |
| // | |
| // Check the arguments. | |
| // | |
| ASSERT(ulBase == ADC_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; | |
| } | |
| #endif | |
| //***************************************************************************** | |
| // | |
| // Close the Doxygen group. | |
| //! @} | |
| // | |
| //***************************************************************************** |