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