added support for LPC4088
Fork of QEI_hw by
Diff: qeihw.cpp
- Revision:
- 3:9279a8f154c8
- Parent:
- 2:53f8ae2cf502
diff -r 53f8ae2cf502 -r 9279a8f154c8 qeihw.cpp --- a/qeihw.cpp Tue Dec 28 19:32:07 2010 +0000 +++ b/qeihw.cpp Wed Mar 02 10:37:13 2016 +0000 @@ -13,6 +13,7 @@ * @author hb **************************************************************************/ #include "mbed.h" +#include "pinmap.h" #include "qeihw.h" QEIHW *QEIHW::instance; @@ -25,8 +26,9 @@ * @param _invinx Invert index. When = 1, inverts the sense of the index signal * @return None **********************************************************************/ -QEIHW::QEIHW(uint32_t _dirinv, uint32_t _sigmode, uint32_t _capmode, uint32_t _invinx) +QEIHW::QEIHW(uint32_t _dirinv, uint32_t _sigmode, uint32_t _capmode, uint32_t _invinx, uint32_t _crespi) { +#ifdef TARGET_LPC1768 /* Set up clock and power for QEI module */ LPC_SC->PCONP |= PCONP_QEI_ENABLE; @@ -73,6 +75,58 @@ // Clear any pending ints LPC_QEI->QEICLR = QEI_INTCLR_BITMASK; // Set the "clear" bits for for all sources in the Interrupt clear register +#elif TARGET_LPC4088 + /* Set up clock and power for QEI module */ + LPC_SC->PCONP |= PCONP_QEI_ENABLE; + + /* The clock for theQEI module is set to FCCLK, PCLKSEL{4:0] = 0x1 */ + LPC_SC->PCLKSEL = LPC_SC->PCLKSEL & ~(0x1fUL<<0) | ((PCLKSEL_CCLK_DIV_1 & 0x1fUL)<<0); + + /* Assign the pins. They are hard-coded, not user-selected. The index + * pin is assigned, even though it is not easily accessed on the mbed. + * As it may be unconnected, it is given a pull-up resistor to minimize + * power drain. + */ + // MCI0 (PhA) + pin_function(P1_20, 3); // P1.20 = QEI_PHA + pin_mode(P1_20, PullUp); + + // MCI1 (PhB) + pin_function(P1_23, 3); // P1.23 = QEI_PHB + pin_mode(P1_23, PullUp); + + // MCI2 (Index) + pin_function(P1_24, 3); // P1.23 = QEI_IDX + pin_mode(P1_24, PullUp); + + // Initialize all remaining values in QEI peripheral + LPC_QEI->CON = QEI_CON_RESP | QEI_CON_RESV | QEI_CON_RESI; + LPC_QEI->MAXPOS = 0xFFFFFFFF; // Default value + LPC_QEI->CMPOS0 = 0x00; + LPC_QEI->CMPOS1 = 0x00; + LPC_QEI->CMPOS2 = 0x00; + LPC_QEI->INXCMP0 = 0x00; + LPC_QEI->INXCMP1 = 0x00; + LPC_QEI->LOAD = 0x00; + LPC_QEI->VELCOMP = 0x00; + LPC_QEI->FILTERPHA = 0; // Bypass Filter for PHA + LPC_QEI->FILTERPHB = 0; // Bypass Filter for PHB + LPC_QEI->FILTERINX = 0; // Bypass Filter for INDEX + + // Set QEI configuration value corresponding to the call parameters + LPC_QEI->CONF = ( + ((_dirinv << 0) & 1) | \ + ((_sigmode << 1) & 2) | \ + ((_capmode << 2) & 4) | \ + ((_invinx << 3) & 8) | \ + ((_crespi << 4) & 16) ); + + // Mask all int sources + LPC_QEI->IEC = QEI_IECLR_BITMASK; // Set the "clear" bits for all sources in the IE clear register + + // Clear any pending ints + LPC_QEI->CLR = QEI_INTCLR_BITMASK; // Set the "clear" bits for for all sources in the Interrupt clear register +#endif /* preemption = 1, sub-priority = 1 */ NVIC_SetPriority(QEI_IRQn, ((0x01<<3)|0x01)); @@ -98,7 +152,11 @@ **********************************************************************/ void QEIHW::Reset(uint32_t ulResetType) { +#ifdef TARGET_LPC1768 LPC_QEI->QEICON = ulResetType; +#elif TARGET_LPC4088 + LPC_QEI->CON = ulResetType; +#endif } /*********************************************************************//** @@ -112,6 +170,7 @@ /* Turn off clock and power for QEI module */ LPC_SC->PCONP &= PCONP_QEI_DISABLE; +#ifdef TARGET_LPC1768 /* Return pins to their default assignment (PINSEL = 0, PINMODE = PULLDOWN) */ // MCI0 (PhA) -> LED-2 (p1.20) LPC_PINCON->PINSEL3 &= PINSEL3_MCI0_MASK; @@ -124,6 +183,16 @@ // MCI2 (Index) -> p1.24 LPC_PINCON->PINSEL3 &= PINSEL3_MCI2_MASK; LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & PINMODE3_MCI2_MASK) | PINMODE3_GPIO1p24; +#elif TARGET_LPC4088 + pin_function(P1_20, 0); + pin_mode(P1_20, PullDown); + + pin_function(P1_23, 0); + pin_mode(P1_23, PullDown); + + pin_function(P1_24, 0); + pin_mode(P1_24, PullDown); +#endif } /*********************************************************************//** @@ -133,7 +202,11 @@ **********************************************************************/ FlagStatus QEIHW::Direction() { +#ifdef TARGET_LPC1768 return ((LPC_QEI->QEISTAT & QEI_STATUS_DIR) ? SET : RESET); +#elif TARGET_LPC4088 + return ((LPC_QEI->STAT & QEI_STATUS_DIR) ? SET : RESET); +#endif } /*********************************************************************//** @@ -143,7 +216,11 @@ **********************************************************************/ uint32_t QEIHW::GetPosition() { +#ifdef TARGET_LPC1768 return (LPC_QEI->QEIPOS); +#elif TARGET_LPC4088 + return (LPC_QEI->POS); +#endif } /*********************************************************************//** @@ -154,7 +231,11 @@ **********************************************************************/ void QEIHW::SetMaxPosition(uint32_t ulMaxPos) { +#ifdef TARGET_LPC1768 LPC_QEI->QEIMAXPOS = ulMaxPos; +#elif TARGET_LPC4088 + LPC_QEI->MAXPOS = ulMaxPos; +#endif } /*********************************************************************//** @@ -192,7 +273,11 @@ **********************************************************************/ void QEIHW::SetIndexComp( uint32_t ulIndexComp) { +#ifdef TARGET_LPC1768 LPC_QEI->INXCMP = ulIndexComp; +#elif TARGET_LPC4088 + LPC_QEI->INXCMP0 = ulIndexComp; +#endif } /*********************************************************************//** @@ -203,7 +288,11 @@ **********************************************************************/ void QEIHW::SetVelocityTimerReload( uint32_t ulReloadValue) { - LPC_QEI->QEILOAD = ulReloadValue; +#ifdef TARGET_LPC1768 + LPC_QEI->QEILOAD = ulReloadValue; +#elif TARGET_LPC4088 + LPC_QEI->LOAD = ulReloadValue; +#endif } /*********************************************************************//** @@ -219,12 +308,17 @@ //Work out CCLK uint32_t m = (LPC_SC->PLL0CFG & 0xFFFF) + 1; uint32_t n = (LPC_SC->PLL0CFG >> 16) + 1; +#ifdef TARGET_LPC1768 uint32_t cclkdiv = LPC_SC->CCLKCFG + 1; +#elif TARGET_LPC4088 + uint32_t cclkdiv = (LPC_SC->CCLKSEL & 0x1f) + 1; +#endif uint32_t Fcco = (2 * m * XTAL_FREQ) / n; uint32_t cclk = Fcco / cclkdiv; +#ifdef TARGET_LPC1768 // div = CLKPWR_GetPCLKSEL(ClkType); div = LPC_SC->PCLKSEL1 & PCLKSEL1_PCLK_QEI_MASK; switch (div) @@ -247,7 +341,17 @@ } cclk /=div; cclk =((uint64_t)cclk / (1000000/ulReloadValue)) - 1; + LPC_QEI->QEILOAD = (uint32_t) cclk; + +#elif TARGET_LPC4088 + div = LPC_SC->PCLKSEL & PCLKSEL1_PCLK_QEI_MASK; + if (div != 0) + cclk /=div; + cclk =((uint64_t)cclk / (1000000/ulReloadValue)) - 1; + + LPC_QEI->LOAD = (uint32_t) cclk; +#endif } /*********************************************************************//** @@ -257,7 +361,11 @@ **********************************************************************/ uint32_t QEIHW::GetTimer() { +#ifdef TARGET_LPC1768 return (LPC_QEI->QEITIME); +#elif TARGET_LPC4088 + return (LPC_QEI->TIME); +#endif } /*********************************************************************//** @@ -267,7 +375,11 @@ **********************************************************************/ uint32_t QEIHW::GetVelocity() { +#ifdef TARGET_LPC1768 return (LPC_QEI->QEIVEL); +#elif TARGET_LPC4088 + return (LPC_QEI->VEL); +#endif } /*********************************************************************//** @@ -279,7 +391,11 @@ **********************************************************************/ uint32_t QEIHW::GetVelocityCap() { +#ifdef TARGET_LPC1768 return (LPC_QEI->QEICAP); +#elif TARGET_LPC4088 + return (LPC_QEI->CAP); +#endif } /*********************************************************************//** @@ -302,7 +418,13 @@ **********************************************************************/ void QEIHW::SetDigiFilter( uint32_t ulSamplingPulse) { +#ifdef TARGET_LPC1768 LPC_QEI->FILTER = ulSamplingPulse; +#elif TARGET_LPC4088 + LPC_QEI->FILTERPHA = ulSamplingPulse; + LPC_QEI->FILTERPHB = ulSamplingPulse; + LPC_QEI->FILTERINX = ulSamplingPulse; +#endif } /*********************************************************************//** @@ -331,7 +453,11 @@ **********************************************************************/ FlagStatus QEIHW::GetIntStatus( uint32_t ulIntType) { +#ifdef TARGET_LPC1768 return((LPC_QEI->QEIINTSTAT & ulIntType) ? SET : RESET); +#elif TARGET_LPC4088 + return((LPC_QEI->INTSTAT & ulIntType) ? SET : RESET); +#endif } /*********************************************************************//** @@ -362,11 +488,19 @@ **********************************************************************/ void QEIHW::IntCmd( uint32_t ulIntType, FunctionalState NewState) { +#ifdef TARGET_LPC1768 if (NewState == ENABLE) { LPC_QEI->QEIIES = ulIntType; } else { LPC_QEI->QEIIEC = ulIntType; } +#elif TARGET_LPC4088 + if (NewState == ENABLE) { + LPC_QEI->IES = ulIntType; + } else { + LPC_QEI->IEC = ulIntType; + } +#endif } /*********************************************************************//** @@ -394,7 +528,11 @@ **********************************************************************/ void QEIHW::IntSet( uint32_t ulIntType) { +#ifdef TARGET_LPC1768 LPC_QEI->QEISET = ulIntType; +#elif TARGET_LPC4088 + LPC_QEI->SET = ulIntType; +#endif } /*********************************************************************//** @@ -422,7 +560,11 @@ **********************************************************************/ void QEIHW::IntClear( uint32_t ulIntType) { +#ifdef TARGET_LPC1768 LPC_QEI->QEICLR = ulIntType; +#elif TARGET_LPC4088 + LPC_QEI->CLR = ulIntType; +#endif } /*********************************************************************//** @@ -444,10 +586,16 @@ //Work out CCLK uint32_t m = (LPC_SC->PLL0CFG & 0xFFFF) + 1; uint32_t n = (LPC_SC->PLL0CFG >> 16) + 1; +#ifdef TARGET_LPC1768 uint32_t cclkdiv = LPC_SC->CCLKCFG + 1; +#elif TARGET_LPC4088 + uint32_t cclkdiv = (LPC_SC->CCLKSEL & 0x1f) + 1; +#endif uint32_t Fcco = (2 * m * XTAL_FREQ) / n; uint32_t cclk = Fcco / cclkdiv; + +#ifdef TARGET_LPC1768 // div = CLKPWR_GetPCLKSEL(ClkType); div = LPC_SC->PCLKSEL1 & PCLKSEL1_PCLK_QEI_MASK; switch (div) @@ -468,8 +616,8 @@ div = 8; break; } - cclk /= div; - + cclk /=div; + // Get Timer load value (velocity capture period) Load = (uint64_t)(LPC_QEI->QEILOAD + 1); // Get Edge @@ -477,6 +625,21 @@ // Calculate RPM rpm = ((( uint64_t)cclk * ulVelCapValue * 60) / (Load * ulPPR * edges)); +#elif TARGET_LPC4088 + div = LPC_SC->PCLKSEL & PCLKSEL1_PCLK_QEI_MASK; + if (div != 0) + cclk /=div; + + // Get Timer load value (velocity capture period) + Load = (uint64_t)(LPC_QEI->LOAD + 1); + // Get Edge + edges = (uint64_t)((LPC_QEI->CONF & QEI_CONF_CAPMODE) ? 4 : 2); + // Calculate RPM + rpm = ((( uint64_t)cclk * ulVelCapValue * 60) / (Load * ulPPR * edges)); +#endif + + + return (uint32_t)(rpm); } @@ -569,6 +732,7 @@ { int32_t i; +#ifdef TARGET_LPC1768 //User defined interrupt handlers. Check all possible sources, dispatch to corresponding non-null service routines. for(i = 0; i < 13; i++) { if(LPC_QEI->QEIINTSTAT & ((uint32_t)(1<<i)) ) { @@ -577,6 +741,16 @@ } } } +#elif TARGET_LPC4088 + //User defined interrupt handlers. Check all possible sources, dispatch to corresponding non-null service routines. + for(i = 0; i < 16; i++) { + if(LPC_QEI->INTSTAT & ((uint32_t)(1<<i)) ) { + if (_qei_isr[i] != NULL) { + _qei_isr[i](); + } + } + } +#endif return; }