mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-18 09:08:33 -04:00
Add FreeRTOS-Plus directory.
This commit is contained in:
parent
7bd5f21ad5
commit
f508a5f653
6798 changed files with 134949 additions and 19 deletions
946
FreeRTOS/Demo/CORTEX_LM3S811_IAR/LuminaryCode/adc.c
Normal file
946
FreeRTOS/Demo/CORTEX_LM3S811_IAR/LuminaryCode/adc.c
Normal file
|
@ -0,0 +1,946 @@
|
|||
//*****************************************************************************
|
||||
//
|
||||
// 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.
|
||||
//! @}
|
||||
//
|
||||
//*****************************************************************************
|
Loading…
Add table
Add a link
Reference in a new issue