/********************************************************************** | |
* $Id$ lpc18xx_qei.c 2011-06-02 | |
*//** | |
* @file lpc18xx_pwr.c | |
* @brief Contains all functions support for QEI firmware library on LPC18xx | |
* @version 1.0 | |
* @date 02. June. 2011 | |
* @author NXP MCU SW Application Team | |
* | |
* Copyright(C) 2011, NXP Semiconductor | |
* All rights reserved. | |
* | |
*********************************************************************** | |
* Software that is described herein is for illustrative purposes only | |
* which provides customers with programming information regarding the | |
* products. This software is supplied "AS IS" without any warranties. | |
* NXP Semiconductors assumes no responsibility or liability for the | |
* use of the software, conveys no license or title under any patent, | |
* copyright, or mask work right to the product. NXP Semiconductors | |
* reserves the right to make changes in the software without | |
* notification. NXP Semiconductors also make no representation or | |
* warranty that such application will be suitable for the specified | |
* use without further testing or modification. | |
**********************************************************************/ | |
/* Peripheral group ----------------------------------------------------------- */ | |
/** @addtogroup QEI | |
* @{ | |
*/ | |
/* Includes ------------------------------------------------------------------- */ | |
#include "lpc18xx_qei.h" | |
#include "lpc18xx_cgu.h" | |
/* If this source file built with example, the LPC18xx FW library configuration | |
* file in each example directory ("lpc18xx_libcfg.h") must be included, | |
* otherwise the default FW library configuration file must be included instead | |
*/ | |
#ifdef __BUILD_WITH_EXAMPLE__ | |
#include "lpc18xx_libcfg.h" | |
#else | |
#include "lpc18xx_libcfg_default.h" | |
#endif /* __BUILD_WITH_EXAMPLE__ */ | |
#ifdef _QEI | |
/* Private Types -------------------------------------------------------------- */ | |
/** @defgroup QEI_Private_Types QEI Private Types | |
* @{ | |
*/ | |
/** | |
* @brief QEI configuration union type definition | |
*/ | |
typedef union { | |
QEI_CFG_Type bmQEIConfig; | |
uint32_t ulQEIConfig; | |
} QEI_CFGOPT_Type; | |
/** | |
* @} | |
*/ | |
LPC_QEI_Type* QEI_GetPointer(uint8_t qeiId); | |
/* Public Functions ----------------------------------------------------------- */ | |
/** @addtogroup QEI_Public_Functions | |
* @{ | |
*/ | |
/*********************************************************************//** | |
* @brief Get the point to typedef of QEI component | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @return None | |
**********************************************************************/ | |
LPC_QEI_Type* QEI_GetPointer(uint8_t qeiId) | |
{ | |
LPC_QEI_Type* pQei = NULL; | |
if(qeiId == 0) | |
{ | |
pQei = LPC_QEI; | |
} | |
return pQei; | |
} | |
/*********************************************************************//** | |
* @brief Resets value for each type of QEI value, such as velocity, | |
* counter, position, etc.. | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulResetType QEI Reset Type, should be one of the following: | |
* - QEI_RESET_POS :Reset Position Counter | |
* - QEI_RESET_POSOnIDX :Reset Position Counter on Index signal | |
* - QEI_RESET_VEL :Reset Velocity | |
* - QEI_RESET_IDX :Reset Index Counter | |
* @return None | |
**********************************************************************/ | |
void QEI_Reset(uint8_t qeiId, uint32_t ulResetType) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
pQei->CON = ulResetType; | |
} | |
/*********************************************************************//** | |
* @brief Initializes the QEI peripheral according to the specified | |
* parameters in the QEI_ConfigStruct. | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] QEI_ConfigStruct Pointer to a QEI_CFG_Type structure | |
* that contains the configuration information for the | |
* specified QEI peripheral | |
* @return None | |
**********************************************************************/ | |
void QEI_Init(uint8_t qeiId, QEI_CFG_Type *QEI_ConfigStruct) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
/* Set up clock and power for QEI module */ | |
// Already enabled by BASE_M3_CLK | |
// Reset all remaining value in QEI peripheral | |
pQei->MAXPOS = 0x00; | |
pQei->CMPOS0 = 0x00; | |
pQei->CMPOS1 = 0x00; | |
pQei->CMPOS2 = 0x00; | |
pQei->INXCMP0 = 0x00; | |
pQei->VELCOMP = 0x00; | |
pQei->LOAD = 0x00; | |
pQei->CON = QEI_CON_RESP | QEI_CON_RESV | QEI_CON_RESI; | |
pQei->FILTERPHA = 0x00; | |
pQei->FILTERPHB = 0x00; | |
pQei->FILTERINX = 0x00; | |
// Disable all Interrupt | |
pQei->IEC = QEI_IECLR_BITMASK; | |
// Clear all Interrupt pending | |
pQei->CLR = QEI_INTCLR_BITMASK; | |
// Set QEI configuration value corresponding to its setting up value | |
pQei->CONF = ((QEI_CFGOPT_Type *)QEI_ConfigStruct)->ulQEIConfig; | |
} | |
/*********************************************************************//** | |
* @brief De-Initalize QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @return None | |
**********************************************************************/ | |
void QEI_DeInit(uint8_t qeiId) | |
{ | |
/* Turn off clock and power for QEI module */ | |
} | |
/*****************************************************************************//** | |
* @brief Fills each QIE_InitStruct member with its default value: | |
* - DirectionInvert = QEI_DIRINV_NONE | |
* - SignalMode = QEI_SIGNALMODE_QUAD | |
* - CaptureMode = QEI_CAPMODE_4X | |
* - InvertIndex = QEI_INVINX_NONE | |
* @param[in] QIE_InitStruct Pointer to a QEI_CFG_Type structure which will be | |
* initialized. | |
* @return None | |
*******************************************************************************/ | |
void QEI_GetCfgDefault(QEI_CFG_Type *QIE_InitStruct) | |
{ | |
QIE_InitStruct->CaptureMode = QEI_CAPMODE_4X; | |
QIE_InitStruct->DirectionInvert = QEI_DIRINV_NONE; | |
QIE_InitStruct->InvertIndex = QEI_INVINX_NONE; | |
QIE_InitStruct->SignalMode = QEI_SIGNALMODE_QUAD; | |
} | |
/*********************************************************************//** | |
* @brief Check whether if specified flag status is set or not | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulFlagType Status Flag Type, should be one of the following: | |
* - QEI_STATUS_DIR: Direction Status | |
* @return New Status of this status flag (SET or RESET) | |
**********************************************************************/ | |
FlagStatus QEI_GetStatus(uint8_t qeiId, uint32_t ulFlagType) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
return ((pQei->STAT & ulFlagType) ? SET : RESET); | |
} | |
/*********************************************************************//** | |
* @brief Get current position value in QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @return Current position value of QEI peripheral | |
**********************************************************************/ | |
uint32_t QEI_GetPosition(uint8_t qeiId) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
return (pQei->POS); | |
} | |
/*********************************************************************//** | |
* @brief Set max position value for QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulMaxPos Max position value to set | |
* @return None | |
**********************************************************************/ | |
void QEI_SetMaxPosition(uint8_t qeiId, uint32_t ulMaxPos) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
pQei->MAXPOS = ulMaxPos; | |
} | |
/*********************************************************************//** | |
* @brief Set position compare value for QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] bPosCompCh Compare Position channel, should be: | |
* - QEI_COMPPOS_CH_0 :QEI compare position channel 0 | |
* - QEI_COMPPOS_CH_1 :QEI compare position channel 1 | |
* - QEI_COMPPOS_CH_2 :QEI compare position channel 2 | |
* @param[in] ulPosComp Compare Position value to set | |
* @return None | |
**********************************************************************/ | |
void QEI_SetPositionComp(uint8_t qeiId, uint8_t bPosCompCh, uint32_t ulPosComp) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
uint32_t *tmp; | |
tmp = (uint32_t *) (&(pQei->CMPOS0) + bPosCompCh * 4); | |
*tmp = ulPosComp; | |
} | |
/*********************************************************************//** | |
* @brief Get current index counter of QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @return Current value of QEI index counter | |
**********************************************************************/ | |
uint32_t QEI_GetIndex(uint8_t qeiId) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
return (pQei->INXCNT); | |
} | |
/*********************************************************************//** | |
* @brief Set value for index compare in QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulIndexComp Compare Index Value to set | |
* @return None | |
**********************************************************************/ | |
void QEI_SetIndexComp(uint8_t qeiId, uint32_t ulIndexComp) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
pQei->INXCMP0 = ulIndexComp; | |
} | |
/*********************************************************************//** | |
* @brief Set timer reload value for QEI peripheral. When the velocity timer is | |
* over-flow, the value that set for Timer Reload register will be loaded | |
* into the velocity timer for next period. The calculated velocity in RPM | |
* therefore will be affect by this value. | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] QEIReloadStruct QEI reload structure | |
* @return None | |
**********************************************************************/ | |
void QEI_SetTimerReload(uint8_t qeiId, QEI_RELOADCFG_Type *QEIReloadStruct) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
uint64_t pclk; | |
if (QEIReloadStruct->ReloadOption == QEI_TIMERRELOAD_TICKVAL) | |
{ | |
pQei->LOAD = QEIReloadStruct->ReloadValue - 1; | |
} | |
else | |
{ | |
#if 1 | |
pclk = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M3CORE); | |
pclk = (pclk /(1000000/QEIReloadStruct->ReloadValue)) - 1; | |
pQei->LOAD = (uint32_t)pclk; | |
#else | |
ld = M3Frequency; | |
if (ld/1000000 > 0) | |
{ | |
ld /= 1000000; | |
ld *= QEIReloadStruct->ReloadValue; | |
ld -= 1; | |
} | |
else | |
{ | |
ld *= QEIReloadStruct->ReloadValue; | |
ld /= 1000000; | |
ld -= 1; | |
} | |
pQei->LOAD = ld; | |
#endif | |
} | |
} | |
/*********************************************************************//** | |
* @brief Get current timer counter in QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @return Current timer counter in QEI peripheral | |
**********************************************************************/ | |
uint32_t QEI_GetTimer(uint8_t qeiId) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
return (pQei->TIME); | |
} | |
/*********************************************************************//** | |
* @brief Get current velocity pulse counter in current time period | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @return Current velocity pulse counter value | |
**********************************************************************/ | |
uint32_t QEI_GetVelocity(uint8_t qeiId) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
return (pQei->VEL); | |
} | |
/*********************************************************************//** | |
* @brief Get the most recently measured velocity of the QEI. When | |
* the Velocity timer in QEI is over-flow, the current velocity | |
* value will be loaded into Velocity Capture register. | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @return The most recently measured velocity value | |
**********************************************************************/ | |
uint32_t QEI_GetVelocityCap(uint8_t qeiId) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
return (pQei->CAP); | |
} | |
/*********************************************************************//** | |
* @brief Set Velocity Compare value for QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulVelComp Compare Velocity value to set | |
* @return None | |
**********************************************************************/ | |
void QEI_SetVelocityComp(uint8_t qeiId, uint32_t ulVelComp) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
pQei->VELCOMP = ulVelComp; | |
} | |
/*********************************************************************//** | |
* @brief Set value of sampling count for the digital filter in | |
* QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulSamplingPulse Value of sampling count to set | |
* @return None | |
**********************************************************************/ | |
void QEI_SetDigiFilter(uint8_t qeiId, st_Qei_FilterCfg FilterVal) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
pQei->FILTERPHA = FilterVal.PHA_FilterVal; | |
pQei->FILTERPHB = FilterVal.PHB_FilterVal; | |
pQei->FILTERINX = FilterVal.INX_FilterVal; | |
} | |
/*********************************************************************//** | |
* @brief Check whether if specified interrupt flag status in QEI | |
* peripheral is set or not | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulIntType Interrupt Flag Status type, should be: | |
* - QEI_INTFLAG_INX_Int : index pulse was detected interrupt | |
* - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt | |
* - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt | |
* - QEI_INTFLAG_DIR_Int : Change of direction interrupt | |
* - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt | |
* - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt | |
* - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt | |
* - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt | |
* - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt | |
* - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt | |
* @return New State of specified interrupt flag status (SET or RESET) | |
**********************************************************************/ | |
FlagStatus QEI_GetIntStatus(uint8_t qeiId, uint32_t ulIntType) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
return((pQei->INTSTAT & ulIntType) ? SET : RESET); | |
} | |
/*********************************************************************//** | |
* @brief Enable/Disable specified interrupt in QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulIntType Interrupt Flag Status type, should be: | |
* - QEI_INTFLAG_INX_Int : index pulse was detected interrupt | |
* - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt | |
* - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt | |
* - QEI_INTFLAG_DIR_Int : Change of direction interrupt | |
* - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt | |
* - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt | |
* - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt | |
* - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt | |
* - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt | |
* - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt | |
* @param[in] NewState New function state, should be: | |
* - DISABLE | |
* - ENABLE | |
* @return None | |
**********************************************************************/ | |
void QEI_IntCmd(uint8_t qeiId, uint32_t ulIntType, FunctionalState NewState) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
if (NewState == ENABLE) | |
{ | |
pQei->IES = ulIntType; | |
} | |
else | |
{ | |
pQei->IEC = ulIntType; | |
} | |
} | |
/*********************************************************************//** | |
* @brief Sets (forces) specified interrupt in QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulIntType Interrupt Flag Status type, should be: | |
* - QEI_INTFLAG_INX_Int : index pulse was detected interrupt | |
* - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt | |
* - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt | |
* - QEI_INTFLAG_DIR_Int : Change of direction interrupt | |
* - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt | |
* - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt | |
* - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt | |
* - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt | |
* - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt | |
* - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt | |
* @return None | |
**********************************************************************/ | |
void QEI_IntSet(uint8_t qeiId, uint32_t ulIntType) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
pQei->SET = ulIntType; | |
} | |
/*********************************************************************//** | |
* @brief Clear (force) specified interrupt (pending) in QEI peripheral | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulIntType Interrupt Flag Status type, should be: | |
* - QEI_INTFLAG_INX_Int : index pulse was detected interrupt | |
* - QEI_INTFLAG_TIM_Int : Velocity timer over flow interrupt | |
* - QEI_INTFLAG_VELC_Int : Capture velocity is less than compare interrupt | |
* - QEI_INTFLAG_DIR_Int : Change of direction interrupt | |
* - QEI_INTFLAG_ERR_Int : An encoder phase error interrupt | |
* - QEI_INTFLAG_ENCLK_Int : An encoder clock pulse was detected interrupt | |
* - QEI_INTFLAG_POS0_Int : position 0 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS1_Int : position 1 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_POS2_Int : position 2 compare value is equal to the current position interrupt | |
* - QEI_INTFLAG_REV_Int : Index compare value is equal to the current index count interrupt | |
* - QEI_INTFLAG_POS0REV_Int : Combined position 0 and revolution count interrupt | |
* - QEI_INTFLAG_POS1REV_Int : Combined position 1 and revolution count interrupt | |
* - QEI_INTFLAG_POS2REV_Int : Combined position 2 and revolution count interrupt | |
* @return None | |
**********************************************************************/ | |
void QEI_IntClear(uint8_t qeiId, uint32_t ulIntType) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
pQei->CLR = ulIntType; | |
} | |
/*********************************************************************//** | |
* @brief Calculates the actual velocity in RPM passed via velocity | |
* capture value and Pulse Per Round (of the encoder) value | |
* parameter input. | |
* @param[in] qeiId The Id of the expected QEI component, should be: 0 | |
* @param[in] ulVelCapValue Velocity capture input value that can be | |
* got from QEI_GetVelocityCap() function | |
* @param[in] ulPPR Pulse per round of encoder | |
* @return The actual value of velocity in RPM (Round per minute) | |
**********************************************************************/ | |
uint32_t QEI_CalculateRPM(uint8_t qeiId, uint32_t ulVelCapValue, uint32_t ulPPR) | |
{ | |
LPC_QEI_Type* pQei = QEI_GetPointer(qeiId); | |
uint64_t rpm, clock, Load, edges; | |
// Get current Clock rate for timer input | |
clock = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M3CORE); | |
// Get Timer load value (velocity capture period) | |
Load = (uint64_t)(pQei->LOAD + 1); | |
// Get Edge | |
edges = (uint64_t)((pQei->CONF & QEI_CONF_CAPMODE) ? 4 : 2); | |
// Calculate RPM | |
rpm = ((clock * ulVelCapValue * 60) / (Load * ulPPR * edges)); | |
return (uint32_t)(rpm); | |
} | |
/** | |
* @} | |
*/ | |
#endif /* _QEI */ | |
/** | |
* @} | |
*/ | |
/* --------------------------------- End Of File ------------------------------ */ | |