1 //*****************************************************************************
\r
3 // adc.c - Driver for the ADC.
\r
5 // Copyright (c) 2005,2006 Luminary Micro, Inc. All rights reserved.
\r
7 // Software License Agreement
\r
9 // Luminary Micro, Inc. (LMI) is supplying this software for use solely and
\r
10 // exclusively on LMI's Stellaris Family of microcontroller products.
\r
12 // The software is owned by LMI and/or its suppliers, and is protected under
\r
13 // applicable copyright laws. All rights are reserved. Any use in violation
\r
14 // of the foregoing restrictions may subject the user to criminal sanctions
\r
15 // under applicable laws, as well as to civil liability for the breach of the
\r
16 // terms and conditions of this license.
\r
18 // THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
\r
19 // OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
\r
20 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
\r
21 // LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
\r
22 // CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
\r
24 // This is part of revision 991 of the Stellaris Driver Library.
\r
26 //*****************************************************************************
\r
28 //*****************************************************************************
\r
30 //! \addtogroup adc_api
\r
33 //*****************************************************************************
\r
35 #include "../hw_adc.h"
\r
36 #include "../hw_ints.h"
\r
37 #include "../hw_memmap.h"
\r
38 #include "../hw_types.h"
\r
41 #include "interrupt.h"
\r
43 //*****************************************************************************
\r
45 // The currently configured software oversampling factor for each of the ADC
\r
48 //*****************************************************************************
\r
49 #if defined(GROUP_pucoverssamplefactor) || defined(BUILD_ALL)
\r
50 unsigned char g_pucOversampleFactor[3];
\r
52 extern unsigned char g_pucOversampleFactor[3];
\r
55 //*****************************************************************************
\r
57 //! Registers an interrupt handler for an ADC interrupt.
\r
59 //! \param ulBase is the base address of the ADC module.
\r
60 //! \param ulSequenceNum is the sample sequence number.
\r
61 //! \param pfnHandler is a pointer to the function to be called when the
\r
62 //! ADC sample sequence interrupt occurs.
\r
64 //! This function sets the handler to be called when a sample sequence
\r
65 //! interrupt occurs. This will enable the global interrupt in the interrupt
\r
66 //! controller; the sequence interrupt must be enabled with ADCIntEnable(). It
\r
67 //! is the interrupt handler's responsibility to clear the interrupt source via
\r
70 //! \sa IntRegister() for important information about registering interrupt
\r
75 //*****************************************************************************
\r
76 #if defined(GROUP_intregister) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
78 ADCIntRegister(unsigned long ulBase, unsigned long ulSequenceNum,
\r
79 void (*pfnHandler)(void))
\r
81 unsigned long ulInt;
\r
84 // Check the arguments.
\r
86 ASSERT(ulBase == ADC_BASE);
\r
87 ASSERT(ulSequenceNum < 4);
\r
90 // Determine the interrupt to register based on the sequence number.
\r
92 ulInt = INT_ADC0 + ulSequenceNum;
\r
95 // Register the interrupt handler.
\r
97 IntRegister(ulInt, pfnHandler);
\r
100 // Enable the timer interrupt.
\r
106 //*****************************************************************************
\r
108 //! Unregisters the interrupt handler for an ADC interrupt.
\r
110 //! \param ulBase is the base address of the ADC module.
\r
111 //! \param ulSequenceNum is the sample sequence number.
\r
113 //! This function unregisters the interrupt handler. This will disable the
\r
114 //! global interrupt in the interrupt controller; the sequence interrupt must
\r
115 //! be disabled via ADCIntDisable().
\r
117 //! \sa IntRegister() for important information about registering interrupt
\r
122 //*****************************************************************************
\r
123 #if defined(GROUP_intunregister) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
125 ADCIntUnregister(unsigned long ulBase, unsigned long ulSequenceNum)
\r
127 unsigned long ulInt;
\r
130 // Check the arguments.
\r
132 ASSERT(ulBase == ADC_BASE);
\r
133 ASSERT(ulSequenceNum < 4);
\r
136 // Determine the interrupt to unregister based on the sequence number.
\r
138 ulInt = INT_ADC0 + ulSequenceNum;
\r
141 // Disable the interrupt.
\r
146 // Unregister the interrupt handler.
\r
148 IntUnregister(ulInt);
\r
152 //*****************************************************************************
\r
154 //! Disables a sample sequence interrupt.
\r
156 //! \param ulBase is the base address of the ADC module.
\r
157 //! \param ulSequenceNum is the sample sequence number.
\r
159 //! This function disables the requested sample sequence interrupt.
\r
163 //*****************************************************************************
\r
164 #if defined(GROUP_intdisable) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
166 ADCIntDisable(unsigned long ulBase, unsigned long ulSequenceNum)
\r
169 // Check the arguments.
\r
171 ASSERT(ulBase == ADC_BASE);
\r
172 ASSERT(ulSequenceNum < 4);
\r
175 // Disable this sample sequence interrupt.
\r
177 HWREG(ulBase + ADC_O_IM) &= ~(1 << ulSequenceNum);
\r
181 //*****************************************************************************
\r
183 //! Enables a sample sequence interrupt.
\r
185 //! \param ulBase is the base address of the ADC module.
\r
186 //! \param ulSequenceNum is the sample sequence number.
\r
188 //! This function enables the requested sample sequence interrupt. Any
\r
189 //! outstanding interrupts are cleared before enabling the sample sequence
\r
194 //*****************************************************************************
\r
195 #if defined(GROUP_intenable) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
197 ADCIntEnable(unsigned long ulBase, unsigned long ulSequenceNum)
\r
200 // Check the arguments.
\r
202 ASSERT(ulBase == ADC_BASE);
\r
203 ASSERT(ulSequenceNum < 4);
\r
206 // Clear any outstanding interrupts on this sample sequence.
\r
208 HWREG(ulBase + ADC_O_ISC) = 1 << ulSequenceNum;
\r
211 // Enable this sample sequence interrupt.
\r
213 HWREG(ulBase + ADC_O_IM) |= 1 << ulSequenceNum;
\r
217 //*****************************************************************************
\r
219 //! Gets the current interrupt status.
\r
221 //! \param ulBase is the base address of the ADC module.
\r
222 //! \param ulSequenceNum is the sample sequence number.
\r
223 //! \param bMasked is false if the raw interrupt status is required and true if
\r
224 //! the masked interrupt status is required.
\r
226 //! This returns the interrupt status for the specified sample sequence.
\r
227 //! Either the raw interrupt status or the status of interrupts that are
\r
228 //! allowed to reflect to the processor can be returned.
\r
230 //! \return The current raw or masked interrupt status.
\r
232 //*****************************************************************************
\r
233 #if defined(GROUP_intstatus) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
235 ADCIntStatus(unsigned long ulBase, unsigned long ulSequenceNum,
\r
239 // Check the arguments.
\r
241 ASSERT(ulBase == ADC_BASE);
\r
242 ASSERT(ulSequenceNum < 4);
\r
245 // Return either the interrupt status or the raw interrupt status as
\r
250 return(HWREG(ulBase + ADC_O_ISC) & (1 << ulSequenceNum));
\r
254 return(HWREG(ulBase + ADC_O_RIS) & (1 << ulSequenceNum));
\r
259 //*****************************************************************************
\r
261 //! Clears sample sequence interrupt source.
\r
263 //! \param ulBase is the base address of the ADC module.
\r
264 //! \param ulSequenceNum is the sample sequence number.
\r
266 //! The specified sample sequence interrupt is cleared, so that it no longer
\r
267 //! asserts. This must be done in the interrupt handler to keep it from being
\r
268 //! called again immediately upon exit.
\r
272 //*****************************************************************************
\r
273 #if defined(GROUP_intclear) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
275 ADCIntClear(unsigned long ulBase, unsigned long ulSequenceNum)
\r
278 // Check the arugments.
\r
280 ASSERT(ulBase == ADC_BASE);
\r
281 ASSERT(ulSequenceNum < 4);
\r
284 // Clear the interrupt.
\r
286 HWREG(ulBase + ADC_O_ISC) = 1 << ulSequenceNum;
\r
290 //*****************************************************************************
\r
292 //! Enables a sample sequence.
\r
294 //! \param ulBase is the base address of the ADC module.
\r
295 //! \param ulSequenceNum is the sample sequence number.
\r
297 //! Allows the specified sample sequence to be captured when its trigger is
\r
298 //! detected. A sample sequence must be configured before it is enabled.
\r
302 //*****************************************************************************
\r
303 #if defined(GROUP_sequenceenable) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
305 ADCSequenceEnable(unsigned long ulBase, unsigned long ulSequenceNum)
\r
308 // Check the arugments.
\r
310 ASSERT(ulBase == ADC_BASE);
\r
311 ASSERT(ulSequenceNum < 4);
\r
314 // Enable the specified sequence.
\r
316 HWREG(ulBase + ADC_O_ACTSS) |= 1 << ulSequenceNum;
\r
320 //*****************************************************************************
\r
322 //! Disables a sample sequence.
\r
324 //! \param ulBase is the base address of the ADC module.
\r
325 //! \param ulSequenceNum is the sample sequence number.
\r
327 //! Prevents the specified sample sequence from being captured when its trigger
\r
328 //! is detected. A sample sequence should be disabled before it is configured.
\r
332 //*****************************************************************************
\r
333 #if defined(GROUP_sequencedisable) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
335 ADCSequenceDisable(unsigned long ulBase, unsigned long ulSequenceNum)
\r
338 // Check the arugments.
\r
340 ASSERT(ulBase == ADC_BASE);
\r
341 ASSERT(ulSequenceNum < 4);
\r
344 // Disable the specified sequences.
\r
346 HWREG(ulBase + ADC_O_ACTSS) &= ~(1 << ulSequenceNum);
\r
350 //*****************************************************************************
\r
352 //! Configures the trigger source and priority of a sample sequence.
\r
354 //! \param ulBase is the base address of the ADC module.
\r
355 //! \param ulSequenceNum is the sample sequence number.
\r
356 //! \param ulTrigger is the trigger source that initiates the sample sequence;
\r
357 //! must be one of the \b ADC_TRIGGER_* values.
\r
358 //! \param ulPriority is the relative priority of the sample sequence with
\r
359 //! respect to the other sample sequences.
\r
361 //! This function configures the initiation criteria for a sample sequence.
\r
362 //! Valid sample sequences range from zero to three; sequence zero will capture
\r
363 //! up to eight samples, sequences one and two will capture up to four samples,
\r
364 //! and sequence three will capture a single sample. The trigger condition and
\r
365 //! priority (with respect to other sample sequence execution) is set.
\r
367 //! The parameter \b ulTrigger can take on the following values:
\r
369 //! - \b ADC_TRIGGER_PROCESSOR - A trigger generated by the processor, via the
\r
370 //! ADCProcessorTrigger() function.
\r
371 //! - \b ADC_TRIGGER_COMP0 - A trigger generated by the first analog
\r
372 //! comparator; configured with ComparatorConfigure().
\r
373 //! - \b ADC_TRIGGER_COMP1 - A trigger generated by the second analog
\r
374 //! comparator; configured with ComparatorConfigure().
\r
375 //! - \b ADC_TRIGGER_COMP2 - A trigger generated by the third analog
\r
376 //! comparator; configured with ComparatorConfigure().
\r
377 //! - \b ADC_TRIGGER_EXTERNAL - A trigger generated by an input from the Port
\r
379 //! - \b ADC_TRIGGER_TIMER - A trigger generated by a timer; configured with
\r
380 //! TimerControlTrigger().
\r
381 //! - \b ADC_TRIGGER_PWM0 - A trigger generated by the first PWM generator;
\r
382 //! configured with PWMGenIntTrigEnable().
\r
383 //! - \b ADC_TRIGGER_PWM1 - A trigger generated by the second PWM generator;
\r
384 //! configured with PWMGenIntTrigEnable().
\r
385 //! - \b ADC_TRIGGER_PWM2 - A trigger generated by the third PWM generator;
\r
386 //! configured with PWMGenIntTrigEnable().
\r
387 //! - \b ADC_TRIGGER_ALWAYS - A trigger that is always asserted, causing the
\r
388 //! sample sequence to capture repeatedly (so long as
\r
389 //! there is not a higher priority source active).
\r
391 //! Note that not all trigger sources are available on all Stellaris family
\r
392 //! members; consult the data sheet for the device in question to determine the
\r
393 //! availability of triggers.
\r
395 //! The parameter \b ulPriority is a value between 0 and 3, where 0 represents
\r
396 //! the highest priority and 3 the lowest. Note that when programming the
\r
397 //! priority among a set of sample sequences, each must have unique priority;
\r
398 //! it is up to the caller to guarantee the uniqueness of the priorities.
\r
402 //*****************************************************************************
\r
403 #if defined(GROUP_sequenceconfigure) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
405 ADCSequenceConfigure(unsigned long ulBase, unsigned long ulSequenceNum,
\r
406 unsigned long ulTrigger, unsigned long ulPriority)
\r
409 // Check the arugments.
\r
411 ASSERT(ulBase == ADC_BASE);
\r
412 ASSERT(ulSequenceNum < 4);
\r
413 ASSERT((ulTrigger == ADC_TRIGGER_PROCESSOR) ||
\r
414 (ulTrigger == ADC_TRIGGER_COMP0) ||
\r
415 (ulTrigger == ADC_TRIGGER_COMP1) ||
\r
416 (ulTrigger == ADC_TRIGGER_COMP2) ||
\r
417 (ulTrigger == ADC_TRIGGER_EXTERNAL) ||
\r
418 (ulTrigger == ADC_TRIGGER_TIMER) ||
\r
419 (ulTrigger == ADC_TRIGGER_PWM0) ||
\r
420 (ulTrigger == ADC_TRIGGER_PWM1) ||
\r
421 (ulTrigger == ADC_TRIGGER_PWM2) ||
\r
422 (ulTrigger == ADC_TRIGGER_ALWAYS));
\r
423 ASSERT(ulPriority < 4);
\r
426 // Compute the shift for the bits that control this sample sequence.
\r
428 ulSequenceNum *= 4;
\r
431 // Set the trigger event for this sample sequence.
\r
433 HWREG(ulBase + ADC_O_EMUX) = ((HWREG(ulBase + ADC_O_EMUX) &
\r
434 ~(0xf << ulSequenceNum)) |
\r
435 ((ulTrigger & 0xf) << ulSequenceNum));
\r
438 // Set the priority for this sample sequence.
\r
440 HWREG(ulBase + ADC_O_SSPRI) = ((HWREG(ulBase + ADC_O_SSPRI) &
\r
441 ~(0xf << ulSequenceNum)) |
\r
442 ((ulPriority & 0x3) << ulSequenceNum));
\r
446 //*****************************************************************************
\r
448 //! Configure a step of the sample sequencer.
\r
450 //! \param ulBase is the base address of the ADC module.
\r
451 //! \param ulSequenceNum is the sample sequence number.
\r
452 //! \param ulStep is the step to be configured.
\r
453 //! \param ulConfig is the configuration of this step; must be a logical OR of
\r
454 //! \b ADC_CTL_TS, \b ADC_CTL_IE, \b ADC_CTL_END, \b ADC_CTL_D, and one of the
\r
455 //! input channel selects (\b ADC_CTL_CH0 through \b ADC_CTL_CH7).
\r
457 //! This function will set the configuration of the ADC for one step of a
\r
458 //! sample sequence. The ADC can be configured for single-ended or
\r
459 //! differential operation (the \b ADC_CTL_D bit selects differential
\r
460 //! operation when set), the channel to be sampled can be chosen (the
\r
461 //! \b ADC_CTL_CH0 through \b ADC_CTL_CH7 values), and the internal temperature
\r
462 //! sensor can be selected (the \b ADC_CTL_TS bit). Additionally, this step
\r
463 //! can be defined as the last in the sequence (the \b ADC_CTL_END bit) and it
\r
464 //! can be configured to cause an interrupt when the step is complete (the
\r
465 //! \b ADC_CTL_IE bit). The configuration is used by the ADC at the
\r
466 //! appropriate time when the trigger for this sequence occurs.
\r
468 //! The \b ulStep parameter determines the order in which the samples are
\r
469 //! captured by the ADC when the trigger occurs. It can range from zero to
\r
470 //! seven for the first sample sequence, from zero to three for the second and
\r
471 //! third sample sequence, and can only be zero for the fourth sample sequence.
\r
473 //! Differential mode only works with adjacent channel pairs (e.g. 0 and 1).
\r
474 //! The channel select must be the number of the channel pair to sample (e.g.
\r
475 //! \b ADC_CTL_CH0 for 0 and 1, or \b ADC_CTL_CH1 for 2 and 3) or undefined
\r
476 //! results will be returned by the ADC. Additionally, if differential mode is
\r
477 //! selected when the temperature sensor is being sampled, undefined results
\r
478 //! will be returned by the ADC.
\r
480 //! It is the responsibility of the caller to ensure that a valid configuration
\r
481 //! is specified; this function does not check the validity of the specified
\r
486 //*****************************************************************************
\r
487 #if defined(GROUP_sequencestepconfigure) || defined(BUILD_ALL) || \
\r
490 ADCSequenceStepConfigure(unsigned long ulBase, unsigned long ulSequenceNum,
\r
491 unsigned long ulStep, unsigned long ulConfig)
\r
494 // Check the arugments.
\r
496 ASSERT(ulBase == ADC_BASE);
\r
497 ASSERT(ulSequenceNum < 4);
\r
498 ASSERT(((ulSequenceNum == 0) && (ulStep < 8)) ||
\r
499 ((ulSequenceNum == 1) && (ulStep < 4)) ||
\r
500 ((ulSequenceNum == 2) && (ulStep < 4)) ||
\r
501 ((ulSequenceNum == 3) && (ulStep < 1)));
\r
504 // Get the offset of the sequence to be configured.
\r
506 ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);
\r
509 // Compute the shift for the bits that control this step.
\r
514 // Set the analog mux value for this step.
\r
516 HWREG(ulBase + ADC_O_X_SSMUX) = ((HWREG(ulBase + ADC_O_X_SSMUX) &
\r
517 ~(0x0000000f << ulStep)) |
\r
518 ((ulConfig & 0x0f) << ulStep));
\r
521 // Set the control value for this step.
\r
523 HWREG(ulBase + ADC_O_X_SSCTL) = ((HWREG(ulBase + ADC_O_X_SSCTL) &
\r
524 ~(0x0000000f << ulStep)) |
\r
525 (((ulConfig & 0xf0) >> 4) << ulStep));
\r
529 //*****************************************************************************
\r
531 //! Determines if a sample sequence overflow occurred.
\r
533 //! \param ulBase is the base address of the ADC module.
\r
534 //! \param ulSequenceNum is the sample sequence number.
\r
536 //! This determines if a sample sequence overflow has occurred. This will
\r
537 //! happen if the captured samples are not read from the FIFO before the next
\r
538 //! trigger occurs.
\r
540 //! \return Returns zero if there was not an overflow, and non-zero if there
\r
543 //*****************************************************************************
\r
544 #if defined(GROUP_sequenceoverflow) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
546 ADCSequenceOverflow(unsigned long ulBase, unsigned long ulSequenceNum)
\r
549 // Check the arguments.
\r
551 ASSERT(ulBase == ADC_BASE);
\r
552 ASSERT(ulSequenceNum < 4);
\r
555 // Determine if there was an overflow on this sequence.
\r
557 return(HWREG(ulBase + ADC_O_OSTAT) & (1 << ulSequenceNum));
\r
561 //*****************************************************************************
\r
563 //! Determines if a sample sequence underflow occurred.
\r
565 //! \param ulBase is the base address of the ADC module.
\r
566 //! \param ulSequenceNum is the sample sequence number.
\r
568 //! This determines if a sample sequence underflow has occurred. This will
\r
569 //! happen if too many samples are read from the FIFO.
\r
571 //! \return Returns zero if there was not an underflow, and non-zero if there
\r
574 //*****************************************************************************
\r
575 #if defined(GROUP_sequenceunderflow) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
577 ADCSequenceUnderflow(unsigned long ulBase, unsigned long ulSequenceNum)
\r
580 // Check the arguments.
\r
582 ASSERT(ulBase == ADC_BASE);
\r
583 ASSERT(ulSequenceNum < 4);
\r
586 // Determine if there was an underflow on this sequence.
\r
588 return(HWREG(ulBase + ADC_O_USTAT) & (1 << ulSequenceNum));
\r
592 //*****************************************************************************
\r
594 //! Gets the captured data for a sample sequence.
\r
596 //! \param ulBase is the base address of the ADC module.
\r
597 //! \param ulSequenceNum is the sample sequence number.
\r
598 //! \param pulBuffer is the address where the data is stored.
\r
600 //! This function copies data from the specified sample sequence output FIFO to
\r
601 //! a memory resident buffer. The number of samples available in the hardware
\r
602 //! FIFO are copied into the buffer, which is assumed to be large enough to
\r
603 //! hold that many samples. This will only return the samples that are
\r
604 //! presently available, which may not be the entire sample sequence if it is
\r
605 //! in the process of being executed.
\r
607 //! \return Returns the number of samples copied to the buffer.
\r
609 //*****************************************************************************
\r
610 #if defined(GROUP_sequencedataget) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
612 ADCSequenceDataGet(unsigned long ulBase, unsigned long ulSequenceNum,
\r
613 unsigned long *pulBuffer)
\r
615 unsigned long ulCount;
\r
618 // Check the arguments.
\r
620 ASSERT(ulBase == ADC_BASE);
\r
621 ASSERT(ulSequenceNum < 4);
\r
624 // Get the offset of the sequence to be read.
\r
626 ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);
\r
629 // Read samples from the FIFO until it is empty.
\r
632 while(!(HWREG(ulBase + ADC_O_X_SSFSTAT) & ADC_SSFSTAT_EMPTY) &&
\r
636 // Read the FIFO and copy it to the destination.
\r
638 *pulBuffer++ = HWREG(ulBase + ADC_O_X_SSFIFO);
\r
641 // Increment the count of samples read.
\r
647 // Return the number of samples read.
\r
653 //*****************************************************************************
\r
655 //! Causes a processor trigger for a sample sequence.
\r
657 //! \param ulBase is the base address of the ADC module.
\r
658 //! \param ulSequenceNum is the sample sequence number.
\r
660 //! This function triggers a processor-initiated sample sequence if the sample
\r
661 //! sequence trigger is configured to ADC_TRIGGER_PROCESSOR.
\r
665 //*****************************************************************************
\r
666 #if defined(GROUP_processortrigger) || defined(BUILD_ALL) || defined(DOXYGEN)
\r
668 ADCProcessorTrigger(unsigned long ulBase, unsigned long ulSequenceNum)
\r
671 // Check the arguments.
\r
673 ASSERT(ulBase == ADC_BASE);
\r
674 ASSERT(ulSequenceNum < 4);
\r
677 // Generate a processor trigger for this sample sequence.
\r
679 HWREG(ulBase + ADC_O_PSSI) = 1 << ulSequenceNum;
\r
683 //*****************************************************************************
\r
685 //! Configures the software oversampling factor of the ADC.
\r
687 //! \param ulBase is the base address of the ADC module.
\r
688 //! \param ulSequenceNum is the sample sequence number.
\r
689 //! \param ulFactor is the number of samples to be averaged.
\r
691 //! This function configures the software oversampling for the ADC, which can
\r
692 //! be used to provide better resolution on the sampled data. Oversampling is
\r
693 //! accomplished by averaging multiple samples from the same analog input.
\r
694 //! Three different oversampling rates are supported; 2x, 4x, and 8x.
\r
696 //! Oversampling is only supported on the sample sequencers that are more than
\r
697 //! one sample in depth (i.e. the fourth sample sequencer is not supported).
\r
698 //! Oversampling by 2x (for example) divides the depth of the sample sequencer
\r
699 //! by two; so 2x oversampling on the first sample sequencer can only provide
\r
700 //! four samples per trigger. This also means that 8x oversampling is only
\r
701 //! available on the first sample sequencer.
\r
705 //*****************************************************************************
\r
706 #if defined(GROUP_softwareoversampleconfigure) || defined(BUILD_ALL) || \
\r
709 ADCSoftwareOversampleConfigure(unsigned long ulBase,
\r
710 unsigned long ulSequenceNum,
\r
711 unsigned long ulFactor)
\r
713 unsigned long ulValue;
\r
716 // Check the arguments.
\r
718 ASSERT(ulBase == ADC_BASE);
\r
719 ASSERT(ulSequenceNum < 3);
\r
720 ASSERT(((ulFactor == 2) || (ulFactor == 4) || (ulFactor == 8)) &&
\r
721 ((ulSequenceNum == 0) || (ulFactor != 8)));
\r
724 // Convert the oversampling factor to a shift factor.
\r
726 for(ulValue = 0, ulFactor >>= 1; ulFactor; ulValue++, ulFactor >>= 1)
\r
731 // Save the sfiht factor.
\r
733 g_pucOversampleFactor[ulSequenceNum] = ulValue;
\r
737 //*****************************************************************************
\r
739 //! Configures a step of the software oversampled sequencer.
\r
741 //! \param ulBase is the base address of the ADC module.
\r
742 //! \param ulSequenceNum is the sample sequence number.
\r
743 //! \param ulStep is the step to be configured.
\r
744 //! \param ulConfig is the configuration of this step.
\r
746 //! This function configures a step of the sample sequencer when using the
\r
747 //! software oversampling feature. The number of steps available depends on
\r
748 //! the oversampling factor set by ADCSoftwareOversampleConfigure(). The value
\r
749 //! of \e ulConfig is the same as defined for ADCSequenceStepConfigure().
\r
753 //*****************************************************************************
\r
754 #if defined(GROUP_softwareoversamplestepconfigure) || defined(BUILD_ALL) || \
\r
757 ADCSoftwareOversampleStepConfigure(unsigned long ulBase,
\r
758 unsigned long ulSequenceNum,
\r
759 unsigned long ulStep,
\r
760 unsigned long ulConfig)
\r
763 // Check the arguments.
\r
765 ASSERT(ulBase == ADC_BASE);
\r
766 ASSERT(ulSequenceNum < 3);
\r
767 ASSERT(((ulSequenceNum == 0) &&
\r
768 (ulStep < (8 >> g_pucOversampleFactor[ulSequenceNum]))) ||
\r
769 (ulStep < (4 >> g_pucOversampleFactor[ulSequenceNum])));
\r
772 // Get the offset of the sequence to be configured.
\r
774 ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);
\r
777 // Compute the shift for the bits that control this step.
\r
779 ulStep *= 4 << g_pucOversampleFactor[ulSequenceNum];
\r
782 // Loop through the hardware steps that make up this step of the software
\r
783 // oversampled sequence.
\r
785 for(ulSequenceNum = 1 << g_pucOversampleFactor[ulSequenceNum];
\r
786 ulSequenceNum; ulSequenceNum--)
\r
789 // Set the analog mux value for this step.
\r
791 HWREG(ulBase + ADC_O_X_SSMUX) = ((HWREG(ulBase + ADC_O_X_SSMUX) &
\r
792 ~(0x0000000f << ulStep)) |
\r
793 ((ulConfig & 0x0f) << ulStep));
\r
796 // Set the control value for this step.
\r
798 HWREG(ulBase + ADC_O_X_SSCTL) = ((HWREG(ulBase + ADC_O_X_SSCTL) &
\r
799 ~(0x0000000f << ulStep)) |
\r
800 (((ulConfig & 0xf0) >> 4) << ulStep));
\r
801 if(ulSequenceNum != 1)
\r
803 HWREG(ulBase + ADC_O_X_SSCTL) &= ~((ADC_SSCTL_IE0 |
\r
804 ADC_SSCTL_END0) << ulStep);
\r
808 // Go to the next hardware step.
\r
815 //*****************************************************************************
\r
817 //! Gets the captured data for a sample sequence using software oversampling.
\r
819 //! \param ulBase is the base address of the ADC module.
\r
820 //! \param ulSequenceNum is the sample sequence number.
\r
821 //! \param pulBuffer is the address where the data is stored.
\r
822 //! \param ulCount is the number of samples to be read.
\r
824 //! This function copies data from the specified sample sequence output FIFO to
\r
825 //! a memory resident buffer with software oversampling applied. The requested
\r
826 //! number of samples are copied into the data buffer; if there are not enough
\r
827 //! samples in the hardware FIFO to satisfy this many oversampled data items
\r
828 //! then incorrect results will be returned. It is the caller's responsibility
\r
829 //! to read only the samples that are available and wait until enough data is
\r
830 //! available, for example as a result of receiving an interrupt.
\r
834 //*****************************************************************************
\r
835 #if defined(GROUP_softwareoversampledataget) || defined(BUILD_ALL) || \
\r
838 ADCSoftwareOversampleDataGet(unsigned long ulBase, unsigned long ulSequenceNum,
\r
839 unsigned long *pulBuffer, unsigned long ulCount)
\r
841 unsigned long ulIdx, ulAccum;
\r
844 // Check the arguments.
\r
846 ASSERT(ulBase == ADC_BASE);
\r
847 ASSERT(ulSequenceNum < 3);
\r
848 ASSERT(((ulSequenceNum == 0) &&
\r
849 (ulCount < (8 >> g_pucOversampleFactor[ulSequenceNum]))) ||
\r
850 (ulCount < (4 >> g_pucOversampleFactor[ulSequenceNum])));
\r
853 // Get the offset of the sequence to be read.
\r
855 ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);
\r
858 // Read the samples from the FIFO until it is empty.
\r
863 // Compute the sum of the samples.
\r
866 for(ulIdx = 1 << g_pucOversampleFactor[ulSequenceNum]; ulIdx; ulIdx--)
\r
869 // Read the FIFO and add it to the accumulator.
\r
871 ulAccum += HWREG(ulBase + ADC_O_X_SSFIFO);
\r
875 // Write the averaged sample to the output buffer.
\r
877 *pulBuffer++ = ulAccum >> g_pucOversampleFactor[ulSequenceNum];
\r
882 //*****************************************************************************
\r
884 //! Configures the hardware oversampling factor of the ADC.
\r
886 //! \param ulBase is the base address of the ADC module.
\r
887 //! \param ulFactor is the number of samples to be averaged.
\r
889 //! This function configures the hardware oversampling for the ADC, which can
\r
890 //! be used to provide better resolution on the sampled data. Oversampling is
\r
891 //! accomplished by averaging multiple samples from the same analog input. Six
\r
892 //! different oversampling rates are supported; 2x, 4x, 8x, 16x, 32x, and 64x.
\r
893 //! Specifying an oversampling factor of zero will disable the hardware
\r
896 //! Hardware oversampling applies uniformly to all sample sequencers. It does
\r
897 //! not reduce the depth of the sample sequencers like the software
\r
898 //! oversampling APIs; each sample written into the sample sequence FIFO is a
\r
899 //! fully oversampled analog input reading.
\r
901 //! Enabling hardware averaging increases the precision of the ADC at the cost
\r
902 //! of throughput. For example, enabling 4x oversampling reduces the
\r
903 //! throughput of a 250 KSps ADC to 62.5 KSps.
\r
905 //! \note Hardware oversampling is available beginning with Rev C0 of the
\r
906 //! Stellaris microcontroller.
\r
910 //*****************************************************************************
\r
911 #if defined(GROUP_hardwareoversampleconfigure) || defined(BUILD_ALL) || \
\r
914 ADCHardwareOversampleConfigure(unsigned long ulBase,
\r
915 unsigned long ulFactor)
\r
917 unsigned long ulValue;
\r
920 // Check the arguments.
\r
922 ASSERT(ulBase == ADC_BASE);
\r
923 ASSERT(((ulFactor == 0) || (ulFactor == 2) || (ulFactor == 4) ||
\r
924 (ulFactor == 8) || (ulFactor == 16) || (ulFactor == 32) ||
\r
925 (ulFactor == 64)));
\r
928 // Convert the oversampling factor to a shift factor.
\r
930 for(ulValue = 0, ulFactor >>= 1; ulFactor; ulValue++, ulFactor >>= 1)
\r
935 // Write the shift factor to the ADC to configure the hardware oversampler.
\r
937 HWREG(ulBase + ADC_O_SAC) = ulValue;
\r
941 //*****************************************************************************
\r
943 // Close the Doxygen group.
\r
946 //*****************************************************************************
\r