1 /**********************************************************************
\r
2 * $Id$ lpc18xx_qei.c 2011-06-02
\r
4 * @file lpc18xx_pwr.c
\r
5 * @brief Contains all functions support for QEI firmware library on LPC18xx
\r
7 * @date 02. June. 2011
\r
8 * @author NXP MCU SW Application Team
\r
10 * Copyright(C) 2011, NXP Semiconductor
\r
11 * All rights reserved.
\r
13 ***********************************************************************
\r
14 * Software that is described herein is for illustrative purposes only
\r
15 * which provides customers with programming information regarding the
\r
16 * products. This software is supplied "AS IS" without any warranties.
\r
17 * NXP Semiconductors assumes no responsibility or liability for the
\r
18 * use of the software, conveys no license or title under any patent,
\r
19 * copyright, or mask work right to the product. NXP Semiconductors
\r
20 * reserves the right to make changes in the software without
\r
21 * notification. NXP Semiconductors also make no representation or
\r
22 * warranty that such application will be suitable for the specified
\r
23 * use without further testing or modification.
\r
24 **********************************************************************/
\r
26 /* Peripheral group ----------------------------------------------------------- */
\r
31 /* Includes ------------------------------------------------------------------- */
\r
32 #include "lpc18xx_qei.h"
\r
33 #include "lpc18xx_cgu.h"
\r
35 /* If this source file built with example, the LPC18xx FW library configuration
\r
36 * file in each example directory ("lpc18xx_libcfg.h") must be included,
\r
37 * otherwise the default FW library configuration file must be included instead
\r
39 #ifdef __BUILD_WITH_EXAMPLE__
\r
40 #include "lpc18xx_libcfg.h"
\r
42 #include "lpc18xx_libcfg_default.h"
\r
43 #endif /* __BUILD_WITH_EXAMPLE__ */
\r
47 /* Private Types -------------------------------------------------------------- */
\r
48 /** @defgroup QEI_Private_Types QEI Private Types
\r
53 * @brief QEI configuration union type definition
\r
56 QEI_CFG_Type bmQEIConfig;
\r
57 uint32_t ulQEIConfig;
\r
64 LPC_QEI_Type* QEI_GetPointer(uint8_t qeiId);
\r
67 /* Public Functions ----------------------------------------------------------- */
\r
68 /** @addtogroup QEI_Public_Functions
\r
72 /*********************************************************************//**
\r
73 * @brief Get the point to typedef of QEI component
\r
74 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
76 **********************************************************************/
\r
77 LPC_QEI_Type* QEI_GetPointer(uint8_t qeiId)
\r
79 LPC_QEI_Type* pQei = NULL;
\r
90 /*********************************************************************//**
\r
91 * @brief Resets value for each type of QEI value, such as velocity,
\r
92 * counter, position, etc..
\r
93 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
94 * @param[in] ulResetType QEI Reset Type, should be one of the following:
\r
95 * - QEI_RESET_POS :Reset Position Counter
\r
96 * - QEI_RESET_POSOnIDX :Reset Position Counter on Index signal
\r
97 * - QEI_RESET_VEL :Reset Velocity
\r
98 * - QEI_RESET_IDX :Reset Index Counter
\r
100 **********************************************************************/
\r
101 void QEI_Reset(uint8_t qeiId, uint32_t ulResetType)
\r
103 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
105 pQei->CON = ulResetType;
\r
108 /*********************************************************************//**
\r
109 * @brief Initializes the QEI peripheral according to the specified
\r
110 * parameters in the QEI_ConfigStruct.
\r
111 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
112 * @param[in] QEI_ConfigStruct Pointer to a QEI_CFG_Type structure
\r
113 * that contains the configuration information for the
\r
114 * specified QEI peripheral
\r
116 **********************************************************************/
\r
117 void QEI_Init(uint8_t qeiId, QEI_CFG_Type *QEI_ConfigStruct)
\r
119 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
121 /* Set up clock and power for QEI module */
\r
122 // Already enabled by BASE_M3_CLK
\r
124 // Reset all remaining value in QEI peripheral
\r
126 pQei->MAXPOS = 0x00;
\r
127 pQei->CMPOS0 = 0x00;
\r
128 pQei->CMPOS1 = 0x00;
\r
129 pQei->CMPOS2 = 0x00;
\r
130 pQei->INXCMP0 = 0x00;
\r
131 pQei->VELCOMP = 0x00;
\r
134 pQei->CON = QEI_CON_RESP | QEI_CON_RESV | QEI_CON_RESI;
\r
136 pQei->FILTERPHA = 0x00;
\r
137 pQei->FILTERPHB = 0x00;
\r
138 pQei->FILTERINX = 0x00;
\r
140 // Disable all Interrupt
\r
141 pQei->IEC = QEI_IECLR_BITMASK;
\r
143 // Clear all Interrupt pending
\r
144 pQei->CLR = QEI_INTCLR_BITMASK;
\r
146 // Set QEI configuration value corresponding to its setting up value
\r
147 pQei->CONF = ((QEI_CFGOPT_Type *)QEI_ConfigStruct)->ulQEIConfig;
\r
151 /*********************************************************************//**
\r
152 * @brief De-Initalize QEI peripheral
\r
153 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
155 **********************************************************************/
\r
156 void QEI_DeInit(uint8_t qeiId)
\r
158 /* Turn off clock and power for QEI module */
\r
163 /*****************************************************************************//**
\r
164 * @brief Fills each QIE_InitStruct member with its default value:
\r
165 * - DirectionInvert = QEI_DIRINV_NONE
\r
166 * - SignalMode = QEI_SIGNALMODE_QUAD
\r
167 * - CaptureMode = QEI_CAPMODE_4X
\r
168 * - InvertIndex = QEI_INVINX_NONE
\r
169 * @param[in] QIE_InitStruct Pointer to a QEI_CFG_Type structure which will be
\r
172 *******************************************************************************/
\r
173 void QEI_GetCfgDefault(QEI_CFG_Type *QIE_InitStruct)
\r
175 QIE_InitStruct->CaptureMode = QEI_CAPMODE_4X;
\r
176 QIE_InitStruct->DirectionInvert = QEI_DIRINV_NONE;
\r
177 QIE_InitStruct->InvertIndex = QEI_INVINX_NONE;
\r
178 QIE_InitStruct->SignalMode = QEI_SIGNALMODE_QUAD;
\r
182 /*********************************************************************//**
\r
183 * @brief Check whether if specified flag status is set or not
\r
184 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
185 * @param[in] ulFlagType Status Flag Type, should be one of the following:
\r
186 * - QEI_STATUS_DIR: Direction Status
\r
187 * @return New Status of this status flag (SET or RESET)
\r
188 **********************************************************************/
\r
189 FlagStatus QEI_GetStatus(uint8_t qeiId, uint32_t ulFlagType)
\r
191 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
193 return ((pQei->STAT & ulFlagType) ? SET : RESET);
\r
197 /*********************************************************************//**
\r
198 * @brief Get current position value in QEI peripheral
\r
199 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
200 * @return Current position value of QEI peripheral
\r
201 **********************************************************************/
\r
202 uint32_t QEI_GetPosition(uint8_t qeiId)
\r
204 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
206 return (pQei->POS);
\r
209 /*********************************************************************//**
\r
210 * @brief Set max position value for QEI peripheral
\r
211 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
212 * @param[in] ulMaxPos Max position value to set
\r
214 **********************************************************************/
\r
215 void QEI_SetMaxPosition(uint8_t qeiId, uint32_t ulMaxPos)
\r
217 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
219 pQei->MAXPOS = ulMaxPos;
\r
222 /*********************************************************************//**
\r
223 * @brief Set position compare value for QEI peripheral
\r
224 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
225 * @param[in] bPosCompCh Compare Position channel, should be:
\r
226 * - QEI_COMPPOS_CH_0 :QEI compare position channel 0
\r
227 * - QEI_COMPPOS_CH_1 :QEI compare position channel 1
\r
228 * - QEI_COMPPOS_CH_2 :QEI compare position channel 2
\r
229 * @param[in] ulPosComp Compare Position value to set
\r
231 **********************************************************************/
\r
232 void QEI_SetPositionComp(uint8_t qeiId, uint8_t bPosCompCh, uint32_t ulPosComp)
\r
234 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
237 tmp = (uint32_t *) (&(pQei->CMPOS0) + bPosCompCh * 4);
\r
241 /*********************************************************************//**
\r
242 * @brief Get current index counter of QEI peripheral
\r
243 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
244 * @return Current value of QEI index counter
\r
245 **********************************************************************/
\r
246 uint32_t QEI_GetIndex(uint8_t qeiId)
\r
248 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
250 return (pQei->INXCNT);
\r
253 /*********************************************************************//**
\r
254 * @brief Set value for index compare in QEI peripheral
\r
255 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
256 * @param[in] ulIndexComp Compare Index Value to set
\r
258 **********************************************************************/
\r
259 void QEI_SetIndexComp(uint8_t qeiId, uint32_t ulIndexComp)
\r
261 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
263 pQei->INXCMP0 = ulIndexComp;
\r
266 /*********************************************************************//**
\r
267 * @brief Set timer reload value for QEI peripheral. When the velocity timer is
\r
268 * over-flow, the value that set for Timer Reload register will be loaded
\r
269 * into the velocity timer for next period. The calculated velocity in RPM
\r
270 * therefore will be affect by this value.
\r
271 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
272 * @param[in] QEIReloadStruct QEI reload structure
\r
274 **********************************************************************/
\r
275 void QEI_SetTimerReload(uint8_t qeiId, QEI_RELOADCFG_Type *QEIReloadStruct)
\r
277 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
280 if (QEIReloadStruct->ReloadOption == QEI_TIMERRELOAD_TICKVAL)
\r
282 pQei->LOAD = QEIReloadStruct->ReloadValue - 1;
\r
287 pclk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M3CORE);
\r
289 pclk = (pclk /(1000000/QEIReloadStruct->ReloadValue)) - 1;
\r
291 pQei->LOAD = (uint32_t)pclk;
\r
295 if (ld/1000000 > 0)
\r
298 ld *= QEIReloadStruct->ReloadValue;
\r
303 ld *= QEIReloadStruct->ReloadValue;
\r
313 /*********************************************************************//**
\r
314 * @brief Get current timer counter in QEI peripheral
\r
315 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
316 * @return Current timer counter in QEI peripheral
\r
317 **********************************************************************/
\r
318 uint32_t QEI_GetTimer(uint8_t qeiId)
\r
320 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
322 return (pQei->TIME);
\r
325 /*********************************************************************//**
\r
326 * @brief Get current velocity pulse counter in current time period
\r
327 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
328 * @return Current velocity pulse counter value
\r
329 **********************************************************************/
\r
330 uint32_t QEI_GetVelocity(uint8_t qeiId)
\r
332 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
334 return (pQei->VEL);
\r
337 /*********************************************************************//**
\r
338 * @brief Get the most recently measured velocity of the QEI. When
\r
339 * the Velocity timer in QEI is over-flow, the current velocity
\r
340 * value will be loaded into Velocity Capture register.
\r
341 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
342 * @return The most recently measured velocity value
\r
343 **********************************************************************/
\r
344 uint32_t QEI_GetVelocityCap(uint8_t qeiId)
\r
346 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
348 return (pQei->CAP);
\r
351 /*********************************************************************//**
\r
352 * @brief Set Velocity Compare value for QEI peripheral
\r
353 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
354 * @param[in] ulVelComp Compare Velocity value to set
\r
356 **********************************************************************/
\r
357 void QEI_SetVelocityComp(uint8_t qeiId, uint32_t ulVelComp)
\r
359 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
361 pQei->VELCOMP = ulVelComp;
\r
364 /*********************************************************************//**
\r
365 * @brief Set value of sampling count for the digital filter in
\r
367 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
368 * @param[in] ulSamplingPulse Value of sampling count to set
\r
370 **********************************************************************/
\r
371 void QEI_SetDigiFilter(uint8_t qeiId, st_Qei_FilterCfg FilterVal)
\r
373 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
375 pQei->FILTERPHA = FilterVal.PHA_FilterVal;
\r
376 pQei->FILTERPHB = FilterVal.PHB_FilterVal;
\r
377 pQei->FILTERINX = FilterVal.INX_FilterVal;
\r
380 /*********************************************************************//**
\r
381 * @brief Check whether if specified interrupt flag status in QEI
\r
382 * peripheral is set or not
\r
383 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
384 * @param[in] ulIntType Interrupt Flag Status type, should be:
\r
385 * - QEI_INTFLAG_INX_Int : index pulse was detected interrupt
\r
386 * - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt
\r
387 * - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt
\r
388 * - QEI_INTFLAG_DIR_Int : Change of direction interrupt
\r
389 * - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt
\r
390 * - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt
\r
391 * - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt
\r
392 * - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt
\r
393 * - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt
\r
394 * - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt
\r
395 * - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt
\r
396 * - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt
\r
397 * - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt
\r
398 * @return New State of specified interrupt flag status (SET or RESET)
\r
399 **********************************************************************/
\r
400 FlagStatus QEI_GetIntStatus(uint8_t qeiId, uint32_t ulIntType)
\r
402 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
404 return((pQei->INTSTAT & ulIntType) ? SET : RESET);
\r
407 /*********************************************************************//**
\r
408 * @brief Enable/Disable specified interrupt in QEI peripheral
\r
409 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
410 * @param[in] ulIntType Interrupt Flag Status type, should be:
\r
411 * - QEI_INTFLAG_INX_Int : index pulse was detected interrupt
\r
412 * - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt
\r
413 * - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt
\r
414 * - QEI_INTFLAG_DIR_Int : Change of direction interrupt
\r
415 * - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt
\r
416 * - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt
\r
417 * - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt
\r
418 * - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt
\r
419 * - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt
\r
420 * - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt
\r
421 * - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt
\r
422 * - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt
\r
423 * - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt
\r
424 * @param[in] NewState New function state, should be:
\r
428 **********************************************************************/
\r
429 void QEI_IntCmd(uint8_t qeiId, uint32_t ulIntType, FunctionalState NewState)
\r
431 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
433 if (NewState == ENABLE)
\r
435 pQei->IES = ulIntType;
\r
439 pQei->IEC = ulIntType;
\r
444 /*********************************************************************//**
\r
445 * @brief Sets (forces) specified interrupt in QEI peripheral
\r
446 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
447 * @param[in] ulIntType Interrupt Flag Status type, should be:
\r
448 * - QEI_INTFLAG_INX_Int : index pulse was detected interrupt
\r
449 * - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt
\r
450 * - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt
\r
451 * - QEI_INTFLAG_DIR_Int : Change of direction interrupt
\r
452 * - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt
\r
453 * - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt
\r
454 * - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt
\r
455 * - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt
\r
456 * - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt
\r
457 * - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt
\r
458 * - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt
\r
459 * - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt
\r
460 * - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt
\r
462 **********************************************************************/
\r
463 void QEI_IntSet(uint8_t qeiId, uint32_t ulIntType)
\r
465 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
467 pQei->SET = ulIntType;
\r
470 /*********************************************************************//**
\r
471 * @brief Clear (force) specified interrupt (pending) in QEI peripheral
\r
472 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
473 * @param[in] ulIntType Interrupt Flag Status type, should be:
\r
474 * - QEI_INTFLAG_INX_Int : index pulse was detected interrupt
\r
475 * - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt
\r
476 * - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt
\r
477 * - QEI_INTFLAG_DIR_Int : Change of direction interrupt
\r
478 * - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt
\r
479 * - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt
\r
480 * - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt
\r
481 * - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt
\r
482 * - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt
\r
483 * - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt
\r
484 * - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt
\r
485 * - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt
\r
486 * - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt
\r
488 **********************************************************************/
\r
489 void QEI_IntClear(uint8_t qeiId, uint32_t ulIntType)
\r
491 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
493 pQei->CLR = ulIntType;
\r
497 /*********************************************************************//**
\r
498 * @brief Calculates the actual velocity in RPM passed via velocity
\r
499 * capture value and Pulse Per Round (of the encoder) value
\r
501 * @param[in] qeiId The Id of the expected QEI component, should be: 0
\r
502 * @param[in] ulVelCapValue Velocity capture input value that can be
\r
503 * got from QEI_GetVelocityCap() function
\r
504 * @param[in] ulPPR Pulse per round of encoder
\r
505 * @return The actual value of velocity in RPM (Round per minute)
\r
506 **********************************************************************/
\r
507 uint32_t QEI_CalculateRPM(uint8_t qeiId, uint32_t ulVelCapValue, uint32_t ulPPR)
\r
509 LPC_QEI_Type* pQei = QEI_GetPointer(qeiId);
\r
511 uint64_t rpm, clock, Load, edges;
\r
513 // Get current Clock rate for timer input
\r
514 clock = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M3CORE);
\r
516 // Get Timer load value (velocity capture period)
\r
517 Load = (uint64_t)(pQei->LOAD + 1);
\r
520 edges = (uint64_t)((pQei->CONF & QEI_CONF_CAPMODE) ? 4 : 2);
\r
523 rpm = ((clock * ulVelCapValue * 60) / (Load * ulPPR * edges));
\r
525 return (uint32_t)(rpm);
\r
539 /* --------------------------------- End Of File ------------------------------ */
\r