1 //*****************************************************************************
2 //
3 // qei.c - Driver for the Quadrature Encoder with Index.
4 //
5 // Copyright (c) 2005-2012 Texas Instruments Incorporated. All rights reserved.
6 // Software License Agreement
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 // Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright
16 // notice, this list of conditions and the following disclaimer in the
17 // documentation and/or other materials provided with the
18 // distribution.
19 //
20 // Neither the name of Texas Instruments Incorporated nor the names of
21 // its contributors may be used to endorse or promote products derived
22 // from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 //
36 // This is part of revision 9453 of the Stellaris Peripheral Driver Library.
37 //
38 //*****************************************************************************
39
40 //*****************************************************************************
41 //
42 //! \addtogroup qei_api
43 //! @{
44 //
45 //*****************************************************************************
46
47 #include "inc/hw_ints.h"
48 #include "inc/hw_memmap.h"
49 #include "inc/hw_qei.h"
50 #include "inc/hw_types.h"
51 #include "driverlib/debug.h"
52 #include "driverlib/interrupt.h"
53 #include "driverlib/qei.h"
54
55 //*****************************************************************************
56 //
57 //! Enables the quadrature encoder.
58 //!
59 //! \param ulBase is the base address of the quadrature encoder module.
60 //!
61 //! This function enables operation of the quadrature encoder module. The
62 //! module must be configured before it is enabled.
63 //!
64 //! \sa QEIConfigure()
65 //!
66 //! \return None.
67 //
68 //*****************************************************************************
69 void
QEIEnable(unsigned long ulBase)70 QEIEnable(unsigned long ulBase)
71 {
72 //
73 // Check the arguments.
74 //
75 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
76
77 //
78 // Enable the QEI module.
79 //
80 HWREG(ulBase + QEI_O_CTL) |= QEI_CTL_ENABLE;
81 }
82
83 //*****************************************************************************
84 //
85 //! Disables the quadrature encoder.
86 //!
87 //! \param ulBase is the base address of the quadrature encoder module.
88 //!
89 //! This function disables operation of the quadrature encoder module.
90 //!
91 //! \return None.
92 //
93 //*****************************************************************************
94 void
QEIDisable(unsigned long ulBase)95 QEIDisable(unsigned long ulBase)
96 {
97 //
98 // Check the arguments.
99 //
100 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
101
102 //
103 // Disable the QEI module.
104 //
105 HWREG(ulBase + QEI_O_CTL) &= ~(QEI_CTL_ENABLE);
106 }
107
108 //*****************************************************************************
109 //
110 //! Configures the quadrature encoder.
111 //!
112 //! \param ulBase is the base address of the quadrature encoder module.
113 //! \param ulConfig is the configuration for the quadrature encoder. See below
114 //! for a description of this parameter.
115 //! \param ulMaxPosition specifies the maximum position value.
116 //!
117 //! This function configures the operation of the quadrature encoder. The
118 //! \e ulConfig parameter provides the configuration of the encoder and is the
119 //! logical OR of several values:
120 //!
121 //! - \b QEI_CONFIG_CAPTURE_A or \b QEI_CONFIG_CAPTURE_A_B specify if edges
122 //! on channel A or on both channels A and B should be counted by the
123 //! position integrator and velocity accumulator.
124 //! - \b QEI_CONFIG_NO_RESET or \b QEI_CONFIG_RESET_IDX specify if the
125 //! position integrator should be reset when the index pulse is detected.
126 //! - \b QEI_CONFIG_QUADRATURE or \b QEI_CONFIG_CLOCK_DIR specify if
127 //! quadrature signals are being provided on ChA and ChB, or if a direction
128 //! signal and a clock are being provided instead.
129 //! - \b QEI_CONFIG_NO_SWAP or \b QEI_CONFIG_SWAP to specify if the signals
130 //! provided on ChA and ChB should be swapped before being processed.
131 //!
132 //! \e ulMaxPosition is the maximum value of the position integrator and is
133 //! the value used to reset the position capture when in index reset mode and
134 //! moving in the reverse (negative) direction.
135 //!
136 //! \return None.
137 //
138 //*****************************************************************************
139 void
QEIConfigure(unsigned long ulBase,unsigned long ulConfig,unsigned long ulMaxPosition)140 QEIConfigure(unsigned long ulBase, unsigned long ulConfig,
141 unsigned long ulMaxPosition)
142 {
143 //
144 // Check the arguments.
145 //
146 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
147
148 //
149 // Write the new configuration to the hardware.
150 //
151 HWREG(ulBase + QEI_O_CTL) = ((HWREG(ulBase + QEI_O_CTL) &
152 ~(QEI_CTL_CAPMODE | QEI_CTL_RESMODE |
153 QEI_CTL_SIGMODE | QEI_CTL_SWAP)) |
154 ulConfig);
155
156 //
157 // Set the maximum position.
158 //
159 HWREG(ulBase + QEI_O_MAXPOS) = ulMaxPosition;
160 }
161
162 //*****************************************************************************
163 //
164 //! Gets the current encoder position.
165 //!
166 //! \param ulBase is the base address of the quadrature encoder module.
167 //!
168 //! This function returns the current position of the encoder. Depending upon
169 //! the configuration of the encoder, and the incident of an index pulse, this
170 //! value may or may not contain the expected data (that is, if in reset on
171 //! index mode, if an index pulse has not been encountered, the position
172 //! counter is not yet aligned with the index pulse).
173 //!
174 //! \return The current position of the encoder.
175 //
176 //*****************************************************************************
177 unsigned long
QEIPositionGet(unsigned long ulBase)178 QEIPositionGet(unsigned long ulBase)
179 {
180 //
181 // Check the arguments.
182 //
183 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
184
185 //
186 // Return the current position counter.
187 //
188 return(HWREG(ulBase + QEI_O_POS));
189 }
190
191 //*****************************************************************************
192 //
193 //! Sets the current encoder position.
194 //!
195 //! \param ulBase is the base address of the quadrature encoder module.
196 //! \param ulPosition is the new position for the encoder.
197 //!
198 //! This function sets the current position of the encoder; the encoder
199 //! position is then measured relative to this value.
200 //!
201 //! \return None.
202 //
203 //*****************************************************************************
204 void
QEIPositionSet(unsigned long ulBase,unsigned long ulPosition)205 QEIPositionSet(unsigned long ulBase, unsigned long ulPosition)
206 {
207 //
208 // Check the arguments.
209 //
210 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
211
212 //
213 // Set the position counter.
214 //
215 HWREG(ulBase + QEI_O_POS) = ulPosition;
216 }
217
218 //*****************************************************************************
219 //
220 //! Gets the current direction of rotation.
221 //!
222 //! \param ulBase is the base address of the quadrature encoder module.
223 //!
224 //! This function returns the current direction of rotation. In this case,
225 //! current means the most recently detected direction of the encoder; it may
226 //! not be presently moving but this is the direction it last moved before it
227 //! stopped.
228 //!
229 //! \return Returns 1 if moving in the forward direction or -1 if moving in the
230 //! reverse direction.
231 //
232 //*****************************************************************************
233 long
QEIDirectionGet(unsigned long ulBase)234 QEIDirectionGet(unsigned long ulBase)
235 {
236 //
237 // Check the arguments.
238 //
239 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
240
241 //
242 // Return the direction of rotation.
243 //
244 return((HWREG(ulBase + QEI_O_STAT) & QEI_STAT_DIRECTION) ? -1 : 1);
245 }
246
247 //*****************************************************************************
248 //
249 //! Gets the encoder error indicator.
250 //!
251 //! \param ulBase is the base address of the quadrature encoder module.
252 //!
253 //! This function returns the error indicator for the quadrature encoder. It
254 //! is an error for both of the signals of the quadrature input to change at
255 //! the same time.
256 //!
257 //! \return Returns \b true if an error has occurred and \b false otherwise.
258 //
259 //*****************************************************************************
260 tBoolean
QEIErrorGet(unsigned long ulBase)261 QEIErrorGet(unsigned long ulBase)
262 {
263 //
264 // Check the arguments.
265 //
266 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
267
268 //
269 // Return the error indicator.
270 //
271 return((HWREG(ulBase + QEI_O_STAT) & QEI_STAT_ERROR) ? true : false);
272 }
273
274 //*****************************************************************************
275 //
276 //! Enables the velocity capture.
277 //!
278 //! \param ulBase is the base address of the quadrature encoder module.
279 //!
280 //! This function enables operation of the velocity capture in the quadrature
281 //! encoder module. The module must be configured before velocity capture is
282 //! enabled.
283 //!
284 //! \sa QEIVelocityConfigure() and QEIEnable()
285 //!
286 //! \return None.
287 //
288 //*****************************************************************************
289 void
QEIVelocityEnable(unsigned long ulBase)290 QEIVelocityEnable(unsigned long ulBase)
291 {
292 //
293 // Check the arguments.
294 //
295 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
296
297 //
298 // Enable the velocity capture.
299 //
300 HWREG(ulBase + QEI_O_CTL) |= QEI_CTL_VELEN;
301 }
302
303 //*****************************************************************************
304 //
305 //! Disables the velocity capture.
306 //!
307 //! \param ulBase is the base address of the quadrature encoder module.
308 //!
309 //! This function disables operation of the velocity capture in the quadrature
310 //! encoder module.
311 //!
312 //! \return None.
313 //
314 //*****************************************************************************
315 void
QEIVelocityDisable(unsigned long ulBase)316 QEIVelocityDisable(unsigned long ulBase)
317 {
318 //
319 // Check the arguments.
320 //
321 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
322
323 //
324 // Disable the velocity capture.
325 //
326 HWREG(ulBase + QEI_O_CTL) &= ~(QEI_CTL_VELEN);
327 }
328
329 //*****************************************************************************
330 //
331 //! Configures the velocity capture.
332 //!
333 //! \param ulBase is the base address of the quadrature encoder module.
334 //! \param ulPreDiv specifies the predivider applied to the input quadrature
335 //! signal before it is counted; can be one of \b QEI_VELDIV_1,
336 //! \b QEI_VELDIV_2, \b QEI_VELDIV_4, \b QEI_VELDIV_8, \b QEI_VELDIV_16,
337 //! \b QEI_VELDIV_32, \b QEI_VELDIV_64, or \b QEI_VELDIV_128.
338 //! \param ulPeriod specifies the number of clock ticks over which to measure
339 //! the velocity; must be non-zero.
340 //!
341 //! This function configures the operation of the velocity capture portion of
342 //! the quadrature encoder. The position increment signal is predivided as
343 //! specified by \e ulPreDiv before being accumulated by the velocity capture.
344 //! The divided signal is accumulated over \e ulPeriod system clock before
345 //! being saved and resetting the accumulator.
346 //!
347 //! \return None.
348 //
349 //*****************************************************************************
350 void
QEIVelocityConfigure(unsigned long ulBase,unsigned long ulPreDiv,unsigned long ulPeriod)351 QEIVelocityConfigure(unsigned long ulBase, unsigned long ulPreDiv,
352 unsigned long ulPeriod)
353 {
354 //
355 // Check the arguments.
356 //
357 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
358 ASSERT(!(ulPreDiv & ~(QEI_CTL_VELDIV_M)));
359 ASSERT(ulPeriod != 0);
360
361 //
362 // Set the velocity predivider.
363 //
364 HWREG(ulBase + QEI_O_CTL) = ((HWREG(ulBase + QEI_O_CTL) &
365 ~(QEI_CTL_VELDIV_M)) | ulPreDiv);
366
367 //
368 // Set the timer period.
369 //
370 HWREG(ulBase + QEI_O_LOAD) = ulPeriod - 1;
371 }
372
373 //*****************************************************************************
374 //
375 //! Gets the current encoder speed.
376 //!
377 //! \param ulBase is the base address of the quadrature encoder module.
378 //!
379 //! This function returns the current speed of the encoder. The value returned
380 //! is the number of pulses detected in the specified time period; this number
381 //! can be multiplied by the number of time periods per second and divided by
382 //! the number of pulses per revolution to obtain the number of revolutions per
383 //! second.
384 //!
385 //! \return Returns the number of pulses captured in the given time period.
386 //
387 //*****************************************************************************
388 unsigned long
QEIVelocityGet(unsigned long ulBase)389 QEIVelocityGet(unsigned long ulBase)
390 {
391 //
392 // Check the arguments.
393 //
394 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
395
396 //
397 // Return the speed capture value.
398 //
399 return(HWREG(ulBase + QEI_O_SPEED));
400 }
401
402 //*****************************************************************************
403 //
404 //! Registers an interrupt handler for the quadrature encoder interrupt.
405 //!
406 //! \param ulBase is the base address of the quadrature encoder module.
407 //! \param pfnHandler is a pointer to the function to be called when the
408 //! quadrature encoder interrupt occurs.
409 //!
410 //! This function registers the handler to be called when a quadrature encoder
411 //! interrupt occurs. This function enables the global interrupt in the
412 //! interrupt controller; specific quadrature encoder interrupts must be
413 //! enabled via QEIIntEnable(). It is the interrupt handler's responsibility to
414 //! clear the interrupt source via QEIIntClear().
415 //!
416 //! \sa IntRegister() for important information about registering interrupt
417 //! handlers.
418 //!
419 //! \return None.
420 //
421 //*****************************************************************************
422 void
QEIIntRegister(unsigned long ulBase,void (* pfnHandler)(void))423 QEIIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
424 {
425 unsigned long ulInt;
426
427 //
428 // Check the arguments.
429 //
430 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
431
432 //
433 // Determine the interrupt number based on the QEI module.
434 //
435 ulInt = (ulBase == QEI0_BASE) ? INT_QEI0 : INT_QEI1;
436
437 //
438 // Register the interrupt handler, returning an error if an error occurs.
439 //
440 IntRegister(ulInt, pfnHandler);
441
442 //
443 // Enable the quadrature encoder interrupt.
444 //
445 IntEnable(ulInt);
446 }
447
448 //*****************************************************************************
449 //
450 //! Unregisters an interrupt handler for the quadrature encoder interrupt.
451 //!
452 //! \param ulBase is the base address of the quadrature encoder module.
453 //!
454 //! This function unregisters the handler to be called when a quadrature
455 //! encoder interrupt occurs. This function also masks off the interrupt in
456 //! the interrupt controller so that the interrupt handler no longer is called.
457 //!
458 //! \sa IntRegister() for important information about registering interrupt
459 //! handlers.
460 //!
461 //! \return None.
462 //
463 //*****************************************************************************
464 void
QEIIntUnregister(unsigned long ulBase)465 QEIIntUnregister(unsigned long ulBase)
466 {
467 unsigned long ulInt;
468
469 //
470 // Check the arguments.
471 //
472 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
473
474 //
475 // Determine the interrupt number based on the QEI module.
476 //
477 ulInt = (ulBase == QEI0_BASE) ? INT_QEI0 : INT_QEI1;
478
479 //
480 // Disable the interrupt.
481 //
482 IntDisable(ulInt);
483
484 //
485 // Unregister the interrupt handler.
486 //
487 IntUnregister(ulInt);
488 }
489
490 //*****************************************************************************
491 //
492 //! Enables individual quadrature encoder interrupt sources.
493 //!
494 //! \param ulBase is the base address of the quadrature encoder module.
495 //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
496 //! Can be any of the \b QEI_INTERROR, \b QEI_INTDIR, \b QEI_INTTIMER, or
497 //! \b QEI_INTINDEX values.
498 //!
499 //! This function enables the indicated quadrature encoder interrupt sources.
500 //! Only the sources that are enabled can be reflected to the processor
501 //! interrupt; disabled sources have no effect on the processor.
502 //!
503 //! \return None.
504 //
505 //*****************************************************************************
506 void
QEIIntEnable(unsigned long ulBase,unsigned long ulIntFlags)507 QEIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
508 {
509 //
510 // Check the arguments.
511 //
512 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
513
514 //
515 // Enable the specified interrupts.
516 //
517 HWREG(ulBase + QEI_O_INTEN) |= ulIntFlags;
518 }
519
520 //*****************************************************************************
521 //
522 //! Disables individual quadrature encoder interrupt sources.
523 //!
524 //! \param ulBase is the base address of the quadrature encoder module.
525 //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
526 //! This parameter can be any of the \b QEI_INTERROR, \b QEI_INTDIR,
527 //! \b QEI_INTTIMER, or \b QEI_INTINDEX values.
528 //!
529 //! This function disables the indicated quadrature encoder interrupt sources.
530 //! Only the sources that are enabled can be reflected to the processor
531 //! interrupt; disabled sources have no effect on the processor.
532 //!
533 //! \return None.
534 //
535 //*****************************************************************************
536 void
QEIIntDisable(unsigned long ulBase,unsigned long ulIntFlags)537 QEIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
538 {
539 //
540 // Check the arguments.
541 //
542 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
543
544 //
545 // Disable the specified interrupts.
546 //
547 HWREG(ulBase + QEI_O_INTEN) &= ~(ulIntFlags);
548 }
549
550 //*****************************************************************************
551 //
552 //! Gets the current interrupt status.
553 //!
554 //! \param ulBase is the base address of the quadrature encoder module.
555 //! \param bMasked is false if the raw interrupt status is required and true if
556 //! the masked interrupt status is required.
557 //!
558 //! This function returns the interrupt status for the quadrature encoder
559 //! module. Either the raw interrupt status or the status of interrupts that
560 //! are allowed to reflect to the processor can be returned.
561 //!
562 //! \return Returns the current interrupt status, enumerated as a bit field of
563 //! \b QEI_INTERROR, \b QEI_INTDIR, \b QEI_INTTIMER, and \b QEI_INTINDEX.
564 //
565 //*****************************************************************************
566 unsigned long
QEIIntStatus(unsigned long ulBase,tBoolean bMasked)567 QEIIntStatus(unsigned long ulBase, tBoolean bMasked)
568 {
569 //
570 // Check the arguments.
571 //
572 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
573
574 //
575 // Return either the interrupt status or the raw interrupt status as
576 // requested.
577 //
578 if(bMasked)
579 {
580 return(HWREG(ulBase + QEI_O_ISC));
581 }
582 else
583 {
584 return(HWREG(ulBase + QEI_O_RIS));
585 }
586 }
587
588 //*****************************************************************************
589 //
590 //! Clears quadrature encoder interrupt sources.
591 //!
592 //! \param ulBase is the base address of the quadrature encoder module.
593 //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
594 //! This parameter can be any of the \b QEI_INTERROR, \b QEI_INTDIR,
595 //! \b QEI_INTTIMER, or \b QEI_INTINDEX values.
596 //!
597 //! The specified quadrature encoder interrupt sources are cleared, so that
598 //! they no longer assert. This function must be called in the interrupt
599 //! handler to keep the interrupt from being triggered again immediately upon
600 //! exit.
601 //!
602 //! \note Because there is a write buffer in the Cortex-M processor, it may
603 //! take several clock cycles before the interrupt source is actually cleared.
604 //! Therefore, it is recommended that the interrupt source be cleared early in
605 //! the interrupt handler (as opposed to the very last action) to avoid
606 //! returning from the interrupt handler before the interrupt source is
607 //! actually cleared. Failure to do so may result in the interrupt handler
608 //! being immediately reentered (because the interrupt controller still sees
609 //! the interrupt source asserted).
610 //!
611 //! \return None.
612 //
613 //*****************************************************************************
614 void
QEIIntClear(unsigned long ulBase,unsigned long ulIntFlags)615 QEIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
616 {
617 //
618 // Check the arguments.
619 //
620 ASSERT((ulBase == QEI0_BASE) || (ulBase == QEI1_BASE));
621
622 //
623 // Clear the requested interrupt sources.
624 //
625 HWREG(ulBase + QEI_O_ISC) = ulIntFlags;
626 }
627
628 //*****************************************************************************
629 //
630 // Close the Doxygen group.
631 //! @}
632 //
633 //*****************************************************************************
634