]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_LM3S811_IAR/LuminaryCode/adc.c
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / CORTEX_LM3S811_IAR / LuminaryCode / adc.c
1 //*****************************************************************************\r
2 //\r
3 // adc.c - Driver for the ADC.\r
4 //\r
5 // Copyright (c) 2005,2006 Luminary Micro, Inc.  All rights reserved.\r
6 //\r
7 // Software License Agreement\r
8 //\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
11 //\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
17 //\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
23 //\r
24 // This is part of revision 991 of the Stellaris Driver Library.\r
25 //\r
26 //*****************************************************************************\r
27 \r
28 //*****************************************************************************\r
29 //\r
30 //! \addtogroup adc_api\r
31 //! @{\r
32 //\r
33 //*****************************************************************************\r
34 \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
39 #include "adc.h"\r
40 #include "debug.h"\r
41 #include "interrupt.h"\r
42 \r
43 //*****************************************************************************\r
44 //\r
45 // The currently configured software oversampling factor for each of the ADC\r
46 // sequencers.\r
47 //\r
48 //*****************************************************************************\r
49 #if defined(GROUP_pucoverssamplefactor) || defined(BUILD_ALL)\r
50 unsigned char g_pucOversampleFactor[3];\r
51 #else\r
52 extern unsigned char g_pucOversampleFactor[3];\r
53 #endif\r
54 \r
55 //*****************************************************************************\r
56 //\r
57 //! Registers an interrupt handler for an ADC interrupt.\r
58 //!\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
63 //!\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
68 //! ADCIntClear().\r
69 //!\r
70 //! \sa IntRegister() for important information about registering interrupt\r
71 //! handlers.\r
72 //!\r
73 //! \return None.\r
74 //\r
75 //*****************************************************************************\r
76 #if defined(GROUP_intregister) || defined(BUILD_ALL) || defined(DOXYGEN)\r
77 void\r
78 ADCIntRegister(unsigned long ulBase, unsigned long ulSequenceNum,\r
79                void (*pfnHandler)(void))\r
80 {\r
81     unsigned long ulInt;\r
82 \r
83     //\r
84     // Check the arguments.\r
85     //\r
86     ASSERT(ulBase == ADC_BASE);\r
87     ASSERT(ulSequenceNum < 4);\r
88 \r
89     //\r
90     // Determine the interrupt to register based on the sequence number.\r
91     //\r
92     ulInt = INT_ADC0 + ulSequenceNum;\r
93 \r
94     //\r
95     // Register the interrupt handler.\r
96     //\r
97     IntRegister(ulInt, pfnHandler);\r
98 \r
99     //\r
100     // Enable the timer interrupt.\r
101     //\r
102     IntEnable(ulInt);\r
103 }\r
104 #endif\r
105 \r
106 //*****************************************************************************\r
107 //\r
108 //! Unregisters the interrupt handler for an ADC interrupt.\r
109 //!\r
110 //! \param ulBase is the base address of the ADC module.\r
111 //! \param ulSequenceNum is the sample sequence number.\r
112 //!\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
116 //!\r
117 //! \sa IntRegister() for important information about registering interrupt\r
118 //! handlers.\r
119 //!\r
120 //! \return None.\r
121 //\r
122 //*****************************************************************************\r
123 #if defined(GROUP_intunregister) || defined(BUILD_ALL) || defined(DOXYGEN)\r
124 void\r
125 ADCIntUnregister(unsigned long ulBase, unsigned long ulSequenceNum)\r
126 {\r
127     unsigned long ulInt;\r
128 \r
129     //\r
130     // Check the arguments.\r
131     //\r
132     ASSERT(ulBase == ADC_BASE);\r
133     ASSERT(ulSequenceNum < 4);\r
134 \r
135     //\r
136     // Determine the interrupt to unregister based on the sequence number.\r
137     //\r
138     ulInt = INT_ADC0 + ulSequenceNum;\r
139 \r
140     //\r
141     // Disable the interrupt.\r
142     //\r
143     IntDisable(ulInt);\r
144 \r
145     //\r
146     // Unregister the interrupt handler.\r
147     //\r
148     IntUnregister(ulInt);\r
149 }\r
150 #endif\r
151 \r
152 //*****************************************************************************\r
153 //\r
154 //! Disables a sample sequence interrupt.\r
155 //!\r
156 //! \param ulBase is the base address of the ADC module.\r
157 //! \param ulSequenceNum is the sample sequence number.\r
158 //!\r
159 //! This function disables the requested sample sequence interrupt.\r
160 //!\r
161 //! \return None.\r
162 //\r
163 //*****************************************************************************\r
164 #if defined(GROUP_intdisable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
165 void\r
166 ADCIntDisable(unsigned long ulBase, unsigned long ulSequenceNum)\r
167 {\r
168     //\r
169     // Check the arguments.\r
170     //\r
171     ASSERT(ulBase == ADC_BASE);\r
172     ASSERT(ulSequenceNum < 4);\r
173 \r
174     //\r
175     // Disable this sample sequence interrupt.\r
176     //\r
177     HWREG(ulBase + ADC_O_IM) &= ~(1 << ulSequenceNum);\r
178 }\r
179 #endif\r
180 \r
181 //*****************************************************************************\r
182 //\r
183 //! Enables a sample sequence interrupt.\r
184 //!\r
185 //! \param ulBase is the base address of the ADC module.\r
186 //! \param ulSequenceNum is the sample sequence number.\r
187 //!\r
188 //! This function enables the requested sample sequence interrupt.  Any\r
189 //! outstanding interrupts are cleared before enabling the sample sequence\r
190 //! interrupt.\r
191 //!\r
192 //! \return None.\r
193 //\r
194 //*****************************************************************************\r
195 #if defined(GROUP_intenable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
196 void\r
197 ADCIntEnable(unsigned long ulBase, unsigned long ulSequenceNum)\r
198 {\r
199     //\r
200     // Check the arguments.\r
201     //\r
202     ASSERT(ulBase == ADC_BASE);\r
203     ASSERT(ulSequenceNum < 4);\r
204 \r
205     //\r
206     // Clear any outstanding interrupts on this sample sequence.\r
207     //\r
208     HWREG(ulBase + ADC_O_ISC) = 1 << ulSequenceNum;\r
209 \r
210     //\r
211     // Enable this sample sequence interrupt.\r
212     //\r
213     HWREG(ulBase + ADC_O_IM) |= 1 << ulSequenceNum;\r
214 }\r
215 #endif\r
216 \r
217 //*****************************************************************************\r
218 //\r
219 //! Gets the current interrupt status.\r
220 //!\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
225 //!\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
229 //!\r
230 //! \return The current raw or masked interrupt status.\r
231 //\r
232 //*****************************************************************************\r
233 #if defined(GROUP_intstatus) || defined(BUILD_ALL) || defined(DOXYGEN)\r
234 unsigned long\r
235 ADCIntStatus(unsigned long ulBase, unsigned long ulSequenceNum,\r
236              tBoolean bMasked)\r
237 {\r
238     //\r
239     // Check the arguments.\r
240     //\r
241     ASSERT(ulBase == ADC_BASE);\r
242     ASSERT(ulSequenceNum < 4);\r
243 \r
244     //\r
245     // Return either the interrupt status or the raw interrupt status as\r
246     // requested.\r
247     //\r
248     if(bMasked)\r
249     {\r
250         return(HWREG(ulBase + ADC_O_ISC) & (1 << ulSequenceNum));\r
251     }\r
252     else\r
253     {\r
254         return(HWREG(ulBase + ADC_O_RIS) & (1 << ulSequenceNum));\r
255     }\r
256 }\r
257 #endif\r
258 \r
259 //*****************************************************************************\r
260 //\r
261 //! Clears sample sequence interrupt source.\r
262 //!\r
263 //! \param ulBase is the base address of the ADC module.\r
264 //! \param ulSequenceNum is the sample sequence number.\r
265 //!\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
269 //!\r
270 //! \return None.\r
271 //\r
272 //*****************************************************************************\r
273 #if defined(GROUP_intclear) || defined(BUILD_ALL) || defined(DOXYGEN)\r
274 void\r
275 ADCIntClear(unsigned long ulBase, unsigned long ulSequenceNum)\r
276 {\r
277     //\r
278     // Check the arugments.\r
279     //\r
280     ASSERT(ulBase == ADC_BASE);\r
281     ASSERT(ulSequenceNum < 4);\r
282 \r
283     //\r
284     // Clear the interrupt.\r
285     //\r
286     HWREG(ulBase + ADC_O_ISC) = 1 << ulSequenceNum;\r
287 }\r
288 #endif\r
289 \r
290 //*****************************************************************************\r
291 //\r
292 //! Enables a sample sequence.\r
293 //!\r
294 //! \param ulBase is the base address of the ADC module.\r
295 //! \param ulSequenceNum is the sample sequence number.\r
296 //!\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
299 //!\r
300 //! \return None.\r
301 //\r
302 //*****************************************************************************\r
303 #if defined(GROUP_sequenceenable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
304 void\r
305 ADCSequenceEnable(unsigned long ulBase, unsigned long ulSequenceNum)\r
306 {\r
307     //\r
308     // Check the arugments.\r
309     //\r
310     ASSERT(ulBase == ADC_BASE);\r
311     ASSERT(ulSequenceNum < 4);\r
312 \r
313     //\r
314     // Enable the specified sequence.\r
315     //\r
316     HWREG(ulBase + ADC_O_ACTSS) |= 1 << ulSequenceNum;\r
317 }\r
318 #endif\r
319 \r
320 //*****************************************************************************\r
321 //\r
322 //! Disables a sample sequence.\r
323 //!\r
324 //! \param ulBase is the base address of the ADC module.\r
325 //! \param ulSequenceNum is the sample sequence number.\r
326 //!\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
329 //!\r
330 //! \return None.\r
331 //\r
332 //*****************************************************************************\r
333 #if defined(GROUP_sequencedisable) || defined(BUILD_ALL) || defined(DOXYGEN)\r
334 void\r
335 ADCSequenceDisable(unsigned long ulBase, unsigned long ulSequenceNum)\r
336 {\r
337     //\r
338     // Check the arugments.\r
339     //\r
340     ASSERT(ulBase == ADC_BASE);\r
341     ASSERT(ulSequenceNum < 4);\r
342 \r
343     //\r
344     // Disable the specified sequences.\r
345     //\r
346     HWREG(ulBase + ADC_O_ACTSS) &= ~(1 << ulSequenceNum);\r
347 }\r
348 #endif\r
349 \r
350 //*****************************************************************************\r
351 //\r
352 //! Configures the trigger source and priority of a sample sequence.\r
353 //!\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
360 //!\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
366 //!\r
367 //! The parameter \b ulTrigger can take on the following values:\r
368 //!\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
378 //!                             B4 pin.\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
390 //!\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
394 //!\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
399 //!\r
400 //! \return None.\r
401 //\r
402 //*****************************************************************************\r
403 #if defined(GROUP_sequenceconfigure) || defined(BUILD_ALL) || defined(DOXYGEN)\r
404 void\r
405 ADCSequenceConfigure(unsigned long ulBase, unsigned long ulSequenceNum,\r
406                      unsigned long ulTrigger, unsigned long ulPriority)\r
407 {\r
408     //\r
409     // Check the arugments.\r
410     //\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
424 \r
425     //\r
426     // Compute the shift for the bits that control this sample sequence.\r
427     //\r
428     ulSequenceNum *= 4;\r
429 \r
430     //\r
431     // Set the trigger event for this sample sequence.\r
432     //\r
433     HWREG(ulBase + ADC_O_EMUX) = ((HWREG(ulBase + ADC_O_EMUX) &\r
434                                    ~(0xf << ulSequenceNum)) |\r
435                                   ((ulTrigger & 0xf) << ulSequenceNum));\r
436 \r
437     //\r
438     // Set the priority for this sample sequence.\r
439     //\r
440     HWREG(ulBase + ADC_O_SSPRI) = ((HWREG(ulBase + ADC_O_SSPRI) &\r
441                                     ~(0xf << ulSequenceNum)) |\r
442                                    ((ulPriority & 0x3) << ulSequenceNum));\r
443 }\r
444 #endif\r
445 \r
446 //*****************************************************************************\r
447 //\r
448 //! Configure a step of the sample sequencer.\r
449 //!\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
456 //!\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
467 //!\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
472 //!\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
479 //!\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
482 //! configuration.\r
483 //!\r
484 //! \return None.\r
485 //\r
486 //*****************************************************************************\r
487 #if defined(GROUP_sequencestepconfigure) || defined(BUILD_ALL) || \\r
488     defined(DOXYGEN)\r
489 void\r
490 ADCSequenceStepConfigure(unsigned long ulBase, unsigned long ulSequenceNum,\r
491                          unsigned long ulStep, unsigned long ulConfig)\r
492 {\r
493     //\r
494     // Check the arugments.\r
495     //\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
502 \r
503     //\r
504     // Get the offset of the sequence to be configured.\r
505     //\r
506     ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);\r
507 \r
508     //\r
509     // Compute the shift for the bits that control this step.\r
510     //\r
511     ulStep *= 4;\r
512 \r
513     //\r
514     // Set the analog mux value for this step.\r
515     //\r
516     HWREG(ulBase + ADC_O_X_SSMUX) = ((HWREG(ulBase + ADC_O_X_SSMUX) &\r
517                                       ~(0x0000000f << ulStep)) |\r
518                                      ((ulConfig & 0x0f) << ulStep));\r
519 \r
520     //\r
521     // Set the control value for this step.\r
522     //\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
526 }\r
527 #endif\r
528 \r
529 //*****************************************************************************\r
530 //\r
531 //! Determines if a sample sequence overflow occurred.\r
532 //!\r
533 //! \param ulBase is the base address of the ADC module.\r
534 //! \param ulSequenceNum is the sample sequence number.\r
535 //!\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
539 //!\r
540 //! \return Returns zero if there was not an overflow, and non-zero if there\r
541 //! was.\r
542 //\r
543 //*****************************************************************************\r
544 #if defined(GROUP_sequenceoverflow) || defined(BUILD_ALL) || defined(DOXYGEN)\r
545 long\r
546 ADCSequenceOverflow(unsigned long ulBase, unsigned long ulSequenceNum)\r
547 {\r
548     //\r
549     // Check the arguments.\r
550     //\r
551     ASSERT(ulBase == ADC_BASE);\r
552     ASSERT(ulSequenceNum < 4);\r
553 \r
554     //\r
555     // Determine if there was an overflow on this sequence.\r
556     //\r
557     return(HWREG(ulBase + ADC_O_OSTAT) & (1 << ulSequenceNum));\r
558 }\r
559 #endif\r
560 \r
561 //*****************************************************************************\r
562 //\r
563 //! Determines if a sample sequence underflow occurred.\r
564 //!\r
565 //! \param ulBase is the base address of the ADC module.\r
566 //! \param ulSequenceNum is the sample sequence number.\r
567 //!\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
570 //!\r
571 //! \return Returns zero if there was not an underflow, and non-zero if there\r
572 //! was.\r
573 //\r
574 //*****************************************************************************\r
575 #if defined(GROUP_sequenceunderflow) || defined(BUILD_ALL) || defined(DOXYGEN)\r
576 long\r
577 ADCSequenceUnderflow(unsigned long ulBase, unsigned long ulSequenceNum)\r
578 {\r
579     //\r
580     // Check the arguments.\r
581     //\r
582     ASSERT(ulBase == ADC_BASE);\r
583     ASSERT(ulSequenceNum < 4);\r
584 \r
585     //\r
586     // Determine if there was an underflow on this sequence.\r
587     //\r
588     return(HWREG(ulBase + ADC_O_USTAT) & (1 << ulSequenceNum));\r
589 }\r
590 #endif\r
591 \r
592 //*****************************************************************************\r
593 //\r
594 //! Gets the captured data for a sample sequence.\r
595 //!\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
599 //!\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
606 //!\r
607 //! \return Returns the number of samples copied to the buffer.\r
608 //\r
609 //*****************************************************************************\r
610 #if defined(GROUP_sequencedataget) || defined(BUILD_ALL) || defined(DOXYGEN)\r
611 long\r
612 ADCSequenceDataGet(unsigned long ulBase, unsigned long ulSequenceNum,\r
613                    unsigned long *pulBuffer)\r
614 {\r
615     unsigned long ulCount;\r
616 \r
617     //\r
618     // Check the arguments.\r
619     //\r
620     ASSERT(ulBase == ADC_BASE);\r
621     ASSERT(ulSequenceNum < 4);\r
622 \r
623     //\r
624     // Get the offset of the sequence to be read.\r
625     //\r
626     ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);\r
627 \r
628     //\r
629     // Read samples from the FIFO until it is empty.\r
630     //\r
631     ulCount = 0;\r
632     while(!(HWREG(ulBase + ADC_O_X_SSFSTAT) & ADC_SSFSTAT_EMPTY) &&\r
633           (ulCount < 8))\r
634     {\r
635         //\r
636         // Read the FIFO and copy it to the destination.\r
637         //\r
638         *pulBuffer++ = HWREG(ulBase + ADC_O_X_SSFIFO);\r
639 \r
640         //\r
641         // Increment the count of samples read.\r
642         //\r
643         ulCount++;\r
644     }\r
645 \r
646     //\r
647     // Return the number of samples read.\r
648     //\r
649     return(ulCount);\r
650 }\r
651 #endif\r
652 \r
653 //*****************************************************************************\r
654 //\r
655 //! Causes a processor trigger for a sample sequence.\r
656 //!\r
657 //! \param ulBase is the base address of the ADC module.\r
658 //! \param ulSequenceNum is the sample sequence number.\r
659 //!\r
660 //! This function triggers a processor-initiated sample sequence if the sample\r
661 //! sequence trigger is configured to ADC_TRIGGER_PROCESSOR.\r
662 //!\r
663 //! \return None.\r
664 //\r
665 //*****************************************************************************\r
666 #if defined(GROUP_processortrigger) || defined(BUILD_ALL) || defined(DOXYGEN)\r
667 void\r
668 ADCProcessorTrigger(unsigned long ulBase, unsigned long ulSequenceNum)\r
669 {\r
670     //\r
671     // Check the arguments.\r
672     //\r
673     ASSERT(ulBase == ADC_BASE);\r
674     ASSERT(ulSequenceNum < 4);\r
675 \r
676     //\r
677     // Generate a processor trigger for this sample sequence.\r
678     //\r
679     HWREG(ulBase + ADC_O_PSSI) = 1 << ulSequenceNum;\r
680 }\r
681 #endif\r
682 \r
683 //*****************************************************************************\r
684 //\r
685 //! Configures the software oversampling factor of the ADC.\r
686 //!\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
690 //!\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
695 //!\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
702 //!\r
703 //! \return None.\r
704 //\r
705 //*****************************************************************************\r
706 #if defined(GROUP_softwareoversampleconfigure) || defined(BUILD_ALL) || \\r
707     defined(DOXYGEN)\r
708 void\r
709 ADCSoftwareOversampleConfigure(unsigned long ulBase,\r
710                                unsigned long ulSequenceNum,\r
711                                unsigned long ulFactor)\r
712 {\r
713     unsigned long ulValue;\r
714 \r
715     //\r
716     // Check the arguments.\r
717     //\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
722 \r
723     //\r
724     // Convert the oversampling factor to a shift factor.\r
725     //\r
726     for(ulValue = 0, ulFactor >>= 1; ulFactor; ulValue++, ulFactor >>= 1)\r
727     {\r
728     }\r
729 \r
730     //\r
731     // Save the sfiht factor.\r
732     //\r
733     g_pucOversampleFactor[ulSequenceNum] = ulValue;\r
734 }\r
735 #endif\r
736 \r
737 //*****************************************************************************\r
738 //\r
739 //! Configures a step of the software oversampled sequencer.\r
740 //!\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
745 //!\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
750 //!\r
751 //! \return None.\r
752 //\r
753 //*****************************************************************************\r
754 #if defined(GROUP_softwareoversamplestepconfigure) || defined(BUILD_ALL) || \\r
755     defined(DOXYGEN)\r
756 void\r
757 ADCSoftwareOversampleStepConfigure(unsigned long ulBase,\r
758                                    unsigned long ulSequenceNum,\r
759                                    unsigned long ulStep,\r
760                                    unsigned long ulConfig)\r
761 {\r
762     //\r
763     // Check the arguments.\r
764     //\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
770 \r
771     //\r
772     // Get the offset of the sequence to be configured.\r
773     //\r
774     ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);\r
775 \r
776     //\r
777     // Compute the shift for the bits that control this step.\r
778     //\r
779     ulStep *= 4 << g_pucOversampleFactor[ulSequenceNum];\r
780 \r
781     //\r
782     // Loop through the hardware steps that make up this step of the software\r
783     // oversampled sequence.\r
784     //\r
785     for(ulSequenceNum = 1 << g_pucOversampleFactor[ulSequenceNum];\r
786         ulSequenceNum; ulSequenceNum--)\r
787     {\r
788         //\r
789         // Set the analog mux value for this step.\r
790         //\r
791         HWREG(ulBase + ADC_O_X_SSMUX) = ((HWREG(ulBase + ADC_O_X_SSMUX) &\r
792                                           ~(0x0000000f << ulStep)) |\r
793                                          ((ulConfig & 0x0f) << ulStep));\r
794 \r
795         //\r
796         // Set the control value for this step.\r
797         //\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
802         {\r
803             HWREG(ulBase + ADC_O_X_SSCTL) &= ~((ADC_SSCTL_IE0 |\r
804                                                 ADC_SSCTL_END0) << ulStep);\r
805         }\r
806 \r
807         //\r
808         // Go to the next hardware step.\r
809         //\r
810         ulStep += 4;\r
811     }\r
812 }\r
813 #endif\r
814 \r
815 //*****************************************************************************\r
816 //\r
817 //! Gets the captured data for a sample sequence using software oversampling.\r
818 //!\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
823 //!\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
831 //!\r
832 //! \return None.\r
833 //\r
834 //*****************************************************************************\r
835 #if defined(GROUP_softwareoversampledataget) || defined(BUILD_ALL) || \\r
836     defined(DOXYGEN)\r
837 void\r
838 ADCSoftwareOversampleDataGet(unsigned long ulBase, unsigned long ulSequenceNum,\r
839                              unsigned long *pulBuffer, unsigned long ulCount)\r
840 {\r
841     unsigned long ulIdx, ulAccum;\r
842 \r
843     //\r
844     // Check the arguments.\r
845     //\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
851 \r
852     //\r
853     // Get the offset of the sequence to be read.\r
854     //\r
855     ulBase += ADC_O_SEQ + (ADC_O_SEQ_STEP * ulSequenceNum);\r
856 \r
857     //\r
858     // Read the samples from the FIFO until it is empty.\r
859     //\r
860     while(ulCount--)\r
861     {\r
862         //\r
863         // Compute the sum of the samples.\r
864         //\r
865         ulAccum = 0;\r
866         for(ulIdx = 1 << g_pucOversampleFactor[ulSequenceNum]; ulIdx; ulIdx--)\r
867         {\r
868             //\r
869             // Read the FIFO and add it to the accumulator.\r
870             //\r
871             ulAccum += HWREG(ulBase + ADC_O_X_SSFIFO);\r
872         }\r
873 \r
874         //\r
875         // Write the averaged sample to the output buffer.\r
876         //\r
877         *pulBuffer++ = ulAccum >> g_pucOversampleFactor[ulSequenceNum];\r
878     }\r
879 }\r
880 #endif\r
881 \r
882 //*****************************************************************************\r
883 //\r
884 //! Configures the hardware oversampling factor of the ADC.\r
885 //!\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
888 //!\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
894 //! oversampler.\r
895 //!\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
900 //!\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
904 //!\r
905 //! \note Hardware oversampling is available beginning with Rev C0 of the\r
906 //! Stellaris microcontroller.\r
907 //!\r
908 //! \return None.\r
909 //\r
910 //*****************************************************************************\r
911 #if defined(GROUP_hardwareoversampleconfigure) || defined(BUILD_ALL) || \\r
912     defined(DOXYGEN)\r
913 void\r
914 ADCHardwareOversampleConfigure(unsigned long ulBase,\r
915                                unsigned long ulFactor)\r
916 {\r
917     unsigned long ulValue;\r
918 \r
919     //\r
920     // Check the arguments.\r
921     //\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
926 \r
927     //\r
928     // Convert the oversampling factor to a shift factor.\r
929     //\r
930     for(ulValue = 0, ulFactor >>= 1; ulFactor; ulValue++, ulFactor >>= 1)\r
931     {\r
932     }\r
933 \r
934     //\r
935     // Write the shift factor to the ADC to configure the hardware oversampler.\r
936     //\r
937     HWREG(ulBase + ADC_O_SAC) = ulValue;\r
938 }\r
939 #endif\r
940 \r
941 //*****************************************************************************\r
942 //\r
943 // Close the Doxygen group.\r
944 //! @}\r
945 //\r
946 //*****************************************************************************\r