Port to LPC1549. Partially tested, not all features ported

Fork of QEI_hw by Hexley Ball

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qeihw.cpp Source File

qeihw.cpp

Go to the documentation of this file.
00001  /* mbed Library - QEI driver for LP1768 hardware
00002  * Copyright (c) 2010, hball
00003  * released under MIT license http://mbed.org/licence/mit
00004  */
00005  
00006 /***********************************************************************//**
00007  * @file        qeihw.cpp
00008  * @brief       Driver file for the QEI hardware. Requires connection to
00009  *              internal mbed circuit nodes. Adapted from the CMSIS
00010  *              driver, lpc17xx_qei.c, v 2.0
00011  * @version     0.1
00012  * @date        28 Dec 2010
00013  * @author      hb
00014  **************************************************************************/
00015 #include "mbed.h"
00016 #include "qeihw.h"
00017 
00018 QEIHW *QEIHW::instance;
00019 
00020 /*********************************************************************//**
00021  * @brief        Create a QEI object and configure it.
00022  * @param _dirinv Direction invert. When = 1, complements the QEICONF register DIR bit
00023  * @param _sigmode Signal mode. When = 0, PhA and PhB are quadrature inputs. When = 1, PhA is direction and PhB is clock
00024  * @param _capmode Capture mode. When = 0, count PhA edges only (2X mode). Whe = 1, count PhB edges also (4X mode).
00025  * @param _invinx Invert index. When = 1, inverts the sense of the index signal
00026  * @return        None
00027  **********************************************************************/
00028 QEIHW::QEIHW(uint32_t _dirinv, uint32_t _sigmode, uint32_t _capmode, uint32_t _invinx)
00029 {
00030 #ifdef TARGET_LPC1768    
00031     /* Set up clock and power for QEI module */
00032     LPC_SC->PCONP |= PCONP_QEI_ENABLE;
00033 
00034     /* The clock for theQEI module is set to FCCLK  */
00035     LPC_SC->PCLKSEL1 = LPC_SC->PCLKSEL1 & ~(3UL<<0) | ((PCLKSEL_CCLK_DIV_1 & 3)<<0); 
00036 #elif defined(TARGET_LPC1549)
00037     /* Enable clock for the QEI module */
00038     LPC_SYSCON->SYSAHBCLKCTRL1 = LPC_SYSCON->SYSAHBCLKCTRL1 | (1<<21);
00039     /* Clear peripheral reset for entire comparator block */
00040     LPC_SYSCON->PRESETCTRL1 = 0;
00041 #endif
00042 
00043 #ifdef TARGET_LPC1768
00044     /* Assign the pins. They are hard-coded, not user-selected. The index
00045      * pin is assigned, even though it is not easily accessed on the mbed.
00046      * As it may be unconnected, it is given a pull-up resistor to minimize
00047      * power drain.
00048      */
00049     // MCI0 (PhA)
00050     LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & PINSEL3_MCI0_MASK) | PINSEL3_MCI0 ;
00051     LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & PINMODE3_MCI0_MASK) | PINMODE3_MCI0;
00052 
00053     // MCI1 (PhB)
00054     LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & PINSEL3_MCI1_MASK) | PINSEL3_MCI1 ;
00055     LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & PINMODE3_MCI1_MASK) | PINMODE3_MCI1;
00056 
00057     // MCI2 (Index)
00058     LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & PINSEL3_MCI2_MASK) | PINSEL3_MCI2 ;
00059     LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & PINMODE3_MCI2_MASK) | PINMODE3_MCI2;
00060 #elif defined(TARGET_LPC1549) // Assign pins
00061     LPC_SWM->PINASSIGN14 = (LPC_SWM->PINASSIGN14 & 0x000000FF) 
00062         |(24<<QEIO_PHA_I) | (0<<QEIO_PHB_I) | (34<<QEIO_IDX_I);
00063         // P0_24              P0_0              P1_3
00064 #endif
00065     
00066     // Initialize all remaining values in QEI peripheral
00067     LPC_QEI->QEICON = QEI_CON_RESP | QEI_CON_RESV | QEI_CON_RESI;
00068     LPC_QEI->QEIMAXPOS = 0xFFFFFFFF;                          // Default value
00069     LPC_QEI->CMPOS0 = 0x00;
00070     LPC_QEI->CMPOS1 = 0x00;
00071     LPC_QEI->CMPOS2 = 0x00;
00072     LPC_QEI->INXCMP = 0x00;
00073     LPC_QEI->QEILOAD = 0x00;
00074     LPC_QEI->VELCOMP = 0x00;
00075 #ifdef TARGET_LPC1768
00076     LPC_QEI->FILTER = 200000;       // Default for mechanical switches.
00077 #elif defined(TARGET_LPC1549)
00078     LPC_QEI->FILTERPHA = 200000;
00079     LPC_QEI->FILTERPHB = 200000;
00080     LPC_QEI->FILTERINX = 200000;
00081 #endif
00082 
00083     // Set QEI configuration value corresponding to the call parameters
00084     LPC_QEI->QEICONF = (
00085         ((_dirinv << 0) & 1) | \
00086         ((_sigmode << 1) & 2) | \
00087         ((_capmode << 2) & 4) | \
00088         ((_invinx <<3) & 8) );
00089        
00090     // Mask all int sources   
00091     LPC_QEI->QEIIEC = QEI_IECLR_BITMASK;    // Set the "clear" bits for all sources in the IE clear register              
00092 
00093     // Clear any pending ints    
00094     LPC_QEI->QEICLR = QEI_INTCLR_BITMASK;   // Set the "clear" bits for for all sources in the Interrupt clear register             
00095     
00096     /* preemption = 1, sub-priority = 1 */
00097     NVIC_SetPriority(QEI_IRQn, ((0x01<<3)|0x01));
00098 
00099     //* Attach IRQ
00100     instance = this;
00101     NVIC_SetVector(QEI_IRQn, (uint32_t)&_Qeiisr);
00102 
00103     /* Enable interrupt for QEI  */
00104     NVIC_EnableIRQ(QEI_IRQn);                       
00105   
00106 }
00107 
00108 /*********************************************************************//**
00109  * @brief        Resets value for each type of QEI value, such as velocity,
00110  *                 counter, position, etc..
00111  * @param[in]    ulResetType        QEI Reset Type, should be one of the following:
00112  *                                 - QEI_RESET_POS: Reset Position Counter
00113  *                                 - QEI_RESET_POSOnIDX: Reset Position Counter on Index signal
00114  *                                 - QEI_RESET_VEL: Reset Velocity
00115  *                                 - QEI_RESET_IDX: Reset Index Counter
00116  * @return        None
00117  **********************************************************************/
00118 void QEIHW::Reset(uint32_t ulResetType)
00119 {
00120     LPC_QEI->QEICON = ulResetType;
00121 }
00122 
00123 /*********************************************************************//**
00124  * @brief        De-initializes the QEI peripheral registers to their
00125  *                  default reset values.
00126  *
00127  * @return         None
00128  **********************************************************************/
00129 void QEIHW::DeInit()
00130 {
00131 #ifdef TARGET_LPC1768
00132     /* Turn off clock and power for QEI module */
00133     LPC_SC->PCONP &= PCONP_QEI_DISABLE;
00134 
00135 
00136     /* Return pins to their default assignment (PINSEL = 0, PINMODE = PULLDOWN) */
00137     // MCI0 (PhA) -> LED-2 (p1.20)
00138     LPC_PINCON->PINSEL3 &= PINSEL3_MCI0_MASK;
00139     LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & PINMODE3_MCI0_MASK) | PINMODE3_GPIO1p20;
00140 
00141     // MCI1 (PhB) -> LED-4 (p1.23)
00142     LPC_PINCON->PINSEL3 &= PINSEL3_MCI1_MASK;
00143     LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & PINMODE3_MCI1_MASK) | PINMODE3_GPIO1p23;
00144 
00145     // MCI2 (Index) -> p1.24
00146     LPC_PINCON->PINSEL3 &= PINSEL3_MCI2_MASK;
00147     LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & PINMODE3_MCI2_MASK) | PINMODE3_GPIO1p24;
00148 #elif defined(TARGET_LPC1549)
00149     LPC_SWM->PINASSIGN14 = LPC_SWM ->PINASSIGN14 & 0x000000FF;
00150 #endif
00151 }
00152 
00153 /*********************************************************************//**
00154  * @brief        Report direction (QEISTAT bit DIR)
00155  *                             
00156  * @return       State of the DIR bit (SET or RESET)
00157  **********************************************************************/
00158 FlagStatus QEIHW::Direction()
00159 {
00160     return ((LPC_QEI->QEISTAT & QEI_STATUS_DIR) ? SET : RESET);
00161 }
00162 
00163 /*********************************************************************//**
00164  * @brief        Get current position value in QEI peripheral
00165  * 
00166  * @return        Current position value of QEI peripheral
00167  **********************************************************************/
00168 uint32_t QEIHW::GetPosition()
00169 {
00170     return (LPC_QEI->QEIPOS);
00171 }
00172 
00173 /*********************************************************************//**
00174  * @brief        Set max position value for QEI peripheral
00175  *
00176  * @param[in]    ulMaxPos    Max position value to set
00177  * @return        None
00178  **********************************************************************/
00179 void QEIHW::SetMaxPosition(uint32_t ulMaxPos)
00180 {
00181     LPC_QEI->QEIMAXPOS = ulMaxPos;
00182 }
00183 
00184 /*********************************************************************//**
00185  * @brief        Set position compare value for QEI peripheral
00186  * @param[in]    QEIx        QEI peripheral, should be LPC_QEI
00187  * @param[in]    bPosCompCh    Compare Position channel, should be:
00188  *                             - QEI_COMPPOS_CH_0: QEI compare position channel 0
00189  *                             - QEI_COMPPOS_CH_1: QEI compare position channel 1
00190  *                             - QEI_COMPPOS_CH_2: QEI compare position channel 2
00191  * @param[in]    ulPosComp    Compare Position value to set
00192  * @return        None
00193  **********************************************************************/
00194 void QEIHW::SetPositionComp( uint8_t bPosCompCh, uint32_t ulPosComp)
00195 {
00196     uint32_t *tmp;
00197 
00198     tmp = (uint32_t *) (&(LPC_QEI->CMPOS0) + bPosCompCh * 4);
00199     *tmp = ulPosComp;
00200 }
00201 
00202 /*********************************************************************//**
00203  * @brief        Get current index counter of QEI peripheral
00204  *
00205  * @return        Current value of QEI index counter
00206  **********************************************************************/
00207 uint32_t QEIHW::GetIndex()
00208 {
00209     return (LPC_QEI->INXCNT);
00210 }
00211 
00212 /*********************************************************************//**
00213  * @brief        Set value for index compare in QEI peripheral
00214  * @param[in]    ulIndexComp        Compare Index Value to set
00215  * @return        None
00216  **********************************************************************/
00217 void QEIHW::SetIndexComp( uint32_t ulIndexComp)
00218 {
00219     LPC_QEI->INXCMP = ulIndexComp;
00220 }
00221 
00222 /*********************************************************************//**
00223  * @brief        Set Velocity timer reload value
00224  *
00225  * @param[in]    ulReloadValue    Velocity timer reload count
00226  * @return        None
00227  **********************************************************************/
00228 void QEIHW::SetVelocityTimerReload( uint32_t ulReloadValue)
00229 {   
00230          LPC_QEI->QEILOAD = ulReloadValue;
00231 }
00232 
00233 /*********************************************************************//**
00234  * @brief        Set Velocity timer reload value in microseconds
00235  *
00236  * @param[in]    ulReloadValue    Velocity timer reload count
00237  * @return        None
00238  **********************************************************************/
00239 void QEIHW::SetVelocityTimerReload_us( uint32_t ulReloadValue)
00240 {
00241 #ifdef TARGET_LPC1768
00242     int div;
00243 
00244     //Work out CCLK
00245     uint32_t m = (LPC_SC->PLL0CFG & 0xFFFF) + 1;
00246     uint32_t n = (LPC_SC->PLL0CFG >> 16) + 1;
00247     uint32_t cclkdiv = LPC_SC->CCLKCFG + 1;
00248     uint32_t Fcco = (2 * m * XTAL_FREQ) / n;
00249     uint32_t cclk = Fcco / cclkdiv;
00250     
00251 
00252     
00253 //    div = CLKPWR_GetPCLKSEL(ClkType);
00254     div = LPC_SC->PCLKSEL1 & PCLKSEL1_PCLK_QEI_MASK;
00255     switch (div)
00256     {
00257     case 0:
00258         div = 4;
00259         break;
00260 
00261     case 1:
00262         div = 1;
00263         break;
00264 
00265     case 2:
00266         div = 2;
00267         break;
00268 
00269     case 3:
00270         div = 8;
00271         break;
00272     }
00273     cclk /=div;
00274     cclk =((uint64_t)cclk / (1000000/ulReloadValue)) - 1;
00275     LPC_QEI->QEILOAD = (uint32_t) cclk;
00276 #elif defined(TARGET_LPC1549)
00277     uint32_t p;
00278     uint32_t sysclk; 
00279     uint32_t qeicount;
00280 
00281     // Assuming using crystal as clock source
00282     // Workout system clock (pg 63 LPC15xx user guide)
00283     uint32_t psel = ((LPC_SYSCON->SYSPLLCTRL & 0x000000C0) >> 6); // p value
00284     uint32_t msel = ((LPC_SYSCON->SYSPLLCTRL & 0x0000001F) + 1); // m description = msel value + 1
00285     
00286     switch(psel)                     // p description
00287     {
00288         case 0: p = 1; break;
00289         case 1: p = 2; break;
00290         case 2: p = 4; break;
00291         case 3: p = 8; break;
00292     }
00293     
00294     sysclk = msel * XTAL_FREQ /(p * 2);
00295     
00296     ulReloadValue = LPC_QEI->LOAD;
00297     
00298     qeicount = ((uint64_t)sysclk / (1000000/ulReloadValue)) - 1;
00299     
00300     //LPC_QEI->LOAD = (uint32_t)qeicount;
00301     LPC_QEI->LOAD = (uint32_t)(ulReloadValue);
00302 #endif
00303 }
00304 
00305 /*********************************************************************//**
00306  * @brief        Get current timer counter in QEI peripheral
00307  * 
00308  * @return        Current timer counter in QEI peripheral
00309  **********************************************************************/
00310 uint32_t QEIHW::GetTimer()
00311 {
00312     return (LPC_QEI->QEITIME);
00313 }
00314 
00315 /*********************************************************************//**
00316  * @brief        Get current velocity pulse counter in current time period
00317  * 
00318  * @return        Current velocity pulse counter value
00319  **********************************************************************/
00320 uint32_t QEIHW::GetVelocity()
00321 {
00322     return (LPC_QEI->QEIVEL);
00323 }
00324 
00325 /*********************************************************************//**
00326  * @brief        Get the most recently captured velocity of the QEI. When
00327  *                 the Velocity timer in QEI is over-flow, the current velocity
00328  *                 value will be loaded into Velocity Capture register.
00329  * 
00330  * @return        The most recently measured velocity value
00331  **********************************************************************/
00332 uint32_t QEIHW::GetVelocityCap()
00333 {
00334     //return (LPC_QEI->QEICAP);
00335     return (LPC_QEI->QEILOAD);
00336 }
00337 
00338 /*********************************************************************//**
00339  * @brief        Set Velocity Compare value for QEI peripheral
00340  *
00341  * @param[in]    ulVelComp        Compare Velocity value to set
00342  * @return        None
00343  **********************************************************************/
00344 void QEIHW::SetVelocityComp( uint32_t ulVelComp)
00345 {
00346     LPC_QEI->VELCOMP = ulVelComp;
00347 }
00348 
00349 /*********************************************************************//**
00350  * @brief        Set value of sampling count for the digital filter in
00351  *                 QEI peripheral
00352  * 
00353  * @param[in]    ulSamplingPulse    Value of sampling count to set
00354  * @return        None
00355  **********************************************************************/
00356 void QEIHW::SetDigiFilter( uint32_t ulSamplingPulse)
00357 {
00358 #ifdef TARGET_LPC1768
00359     LPC_QEI->FILTER = ulSamplingPulse;
00360 #elif defined(TARGET_LPC1549)
00361     LPC_QEI->FILTERPHA = ulSamplingPulse;
00362     LPC_QEI->FILTERPHB = ulSamplingPulse;
00363     LPC_QEI->FILTERINX = ulSamplingPulse;
00364 #endif
00365     
00366 }
00367 
00368 /*********************************************************************//**
00369  * @brief        Check whether if specified interrupt flag status in QEI
00370  *                 peripheral is set or not
00371  * 
00372  * @param[in]    ulIntType        Interrupt Flag Status type, should be:
00373                                 - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
00374                                 - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
00375                                 - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
00376                                 - QEI_INTFLAG_DIR_Int: Change of direction interrupt
00377                                 - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
00378                                 - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
00379                                 - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
00380                                                         current position interrupt
00381                                 - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
00382                                                         current position interrupt
00383                                 - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
00384                                                         current position interrupt
00385                                 - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
00386                                                         index count interrupt
00387                                 - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
00388                                 - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
00389                                 - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
00390  * @return        New State of specified interrupt flag status (SET or RESET)
00391  **********************************************************************/
00392 FlagStatus QEIHW::GetIntStatus( uint32_t ulIntType)
00393 {
00394     return((LPC_QEI->QEIINTSTAT & ulIntType) ? SET : RESET);
00395 }
00396 
00397 /*********************************************************************//**
00398  * @brief        Enable/Disable specified interrupt in QEI peripheral
00399  * 
00400  * @param[in]    ulIntType        Interrupt Flag Status type, should be:
00401  *                                - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
00402  *                                - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
00403  *                                - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
00404  *                                - QEI_INTFLAG_DIR_Int: Change of direction interrupt
00405  *                                - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
00406  *                                - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
00407  *                                - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
00408  *                                                        current position interrupt
00409  *                                - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
00410  *                                                        current position interrupt
00411  *                                - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
00412  *                                                        current position interrupt
00413  *                                - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
00414  *                                                        index count interrupt
00415  *                                - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
00416  *                                - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
00417  *                                - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
00418  * @param[in]    NewState        New function state, should be:
00419  *                                - DISABLE
00420  *                                - ENABLE
00421  * @return        None
00422  **********************************************************************/
00423 void QEIHW::IntCmd( uint32_t ulIntType, FunctionalState NewState)
00424 {
00425     if (NewState == ENABLE) {
00426         LPC_QEI->QEIIES = ulIntType;
00427     } else {
00428         LPC_QEI->QEIIEC = ulIntType;
00429     }
00430 }
00431 
00432 /*********************************************************************//**
00433  * @brief       Assert specified interrupt in QEI peripheral
00434  * 
00435  * @param[in]    ulIntType        Interrupt Flag Status type, should be:
00436                                 - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
00437                                 - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
00438                                 - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
00439                                 - QEI_INTFLAG_DIR_Int: Change of direction interrupt
00440                                 - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
00441                                 - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
00442                                 - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
00443                                                         current position interrupt
00444                                 - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
00445                                                         current position interrupt
00446                                 - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
00447                                                         current position interrupt
00448                                 - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
00449                                                         index count interrupt
00450                                 - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
00451                                 - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
00452                                 - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
00453  * @return        None
00454  **********************************************************************/
00455 void QEIHW::IntSet( uint32_t ulIntType)
00456 {
00457     LPC_QEI->QEISET = ulIntType;
00458 }
00459 
00460 /*********************************************************************//**
00461  * @brief       De-assert specified interrupt (pending) in QEI peripheral
00462  * 
00463  * @param[in]    ulIntType        Interrupt Flag Status type, should be:
00464                                 - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
00465                                 - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
00466                                 - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
00467                                 - QEI_INTFLAG_DIR_Int: Change of direction interrupt
00468                                 - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
00469                                 - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
00470                                 - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
00471                                                         current position interrupt
00472                                 - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
00473                                                         current position interrupt
00474                                 - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
00475                                                         current position interrupt
00476                                 - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
00477                                                         index count interrupt
00478                                 - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
00479                                 - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
00480                                 - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
00481  * @return        None
00482  **********************************************************************/
00483 void QEIHW::IntClear( uint32_t ulIntType)
00484 {
00485     LPC_QEI->QEICLR = ulIntType;
00486 }
00487 
00488 /*********************************************************************//**
00489  * @brief        Calculates the actual velocity in RPM passed via velocity
00490  *                 capture value and Pulse Per Revolution (of the encoder) value
00491  *                 parameter input.
00492  * 
00493  * @param[in]    ulVelCapValue    Velocity capture input value that can
00494  *                                 be got from QEI_GetVelocityCap() function
00495  * @param[in]    ulPPR            Pulse per round of encoder
00496  * @return        The actual value of velocity in RPM (Revolutions per minute)
00497  **********************************************************************/
00498 uint32_t QEIHW::CalculateRPM( uint32_t ulVelCapValue, uint32_t ulPPR)
00499 {
00500     uint64_t rpm, Load, edges;
00501     int div;
00502     
00503 #ifdef TARGET_LPC1768
00504     // Get current Clock rate for timer input
00505     //Work out CCLK
00506     uint32_t m = (LPC_SC->PLL0CFG & 0xFFFF) + 1;
00507     uint32_t n = (LPC_SC->PLL0CFG >> 16) + 1;
00508     uint32_t cclkdiv = LPC_SC->CCLKCFG + 1;
00509     uint32_t Fcco = (2 * m * XTAL_FREQ) / n;
00510     uint32_t cclk = Fcco / cclkdiv;
00511     
00512 //    div = CLKPWR_GetPCLKSEL(ClkType);
00513     div = LPC_SC->PCLKSEL1 & PCLKSEL1_PCLK_QEI_MASK;
00514     switch (div)
00515     {
00516     case 0:
00517         div = 4;
00518         break;
00519 
00520     case 1:
00521         div = 1;
00522         break;
00523 
00524     case 2:
00525         div = 2;
00526         break;
00527 
00528     case 3:
00529         div = 8;
00530         break;
00531     }
00532     cclk /= div;
00533     
00534     // Get Timer load value (velocity capture period)
00535     Load  = (uint64_t)(LPC_QEI->QEILOAD + 1);
00536     // Get Edge
00537     edges = (uint64_t)((LPC_QEI->QEICONF & QEI_CONF_CAPMODE) ? 4 : 2);
00538     // Calculate RPM
00539     rpm = ((( uint64_t)cclk * ulVelCapValue * 60) / (Load * ulPPR * edges));
00540 #elif defined(TARGET_LPC1549)
00541     // Assuming using crystal as clock source
00542     // Workout system clock (pg 63 LPC15xx user guide)
00543     uint32_t psel = ((LPC_SYSCON->SYSPLLCTRL & 0x000000C0) >> 6); // p value
00544     uint32_t msel = ((LPC_SYSCON->SYSPLLCTRL & 0x0000001F) + 1); // m description = msel value + 1
00545     
00546     uint32_t p;
00547     uint32_t sysclk; 
00548     uint32_t qeicount;
00549     uint32_t ulReloadValue;
00550     
00551     switch(psel)                     // p description
00552     {
00553         case 0: p = 1; break;
00554         case 1: p = 2; break;
00555         case 2: p = 4; break;
00556         case 3: p = 8; break;
00557     }
00558     
00559     sysclk = msel * XTAL_FREQ /(p * 2);
00560     
00561     ulReloadValue = LPC_QEI->LOAD;
00562     
00563     qeicount = ((uint64_t)sysclk / (1000000/ulReloadValue)) - 1;
00564     
00565     // Get Timer load value (velocity capture period)
00566     Load  = (uint64_t)(LPC_QEI->LOAD + 1);
00567 
00568     // Get Edge
00569     edges = (uint64_t)((LPC_QEI->CONF & QEI_CONF_CAPMODE) ? 4 : 2);
00570     
00571     rpm = (sysclk * ulVelCapValue * 60) / (Load * ulPPR * edges);
00572 #endif
00573 
00574     return (uint32_t)(rpm);
00575 }
00576 
00577 /*********************************************************************//**
00578  * @brief        Append interrupt handler for specific QEI interrupt source
00579  * 
00580  * @param[in]    ulISRType        Interrupt Flag Status type, should be:
00581  *                                - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
00582  *                                - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
00583  *                                - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
00584  *                                - QEI_INTFLAG_DIR_Int: Change of direction interrupt
00585  *                                - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
00586  *                                - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
00587  *                                - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
00588  *                                                        current position interrupt
00589  *                                - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
00590  *                                                        current position interrupt
00591  *                                - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
00592  *                                                        current position interrupt
00593  *                                - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
00594  *                                                        index count interrupt
00595  *                                - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
00596  *                                - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
00597  *                                - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
00598  *                                 
00599  * @return       none
00600  **********************************************************************/
00601 void QEIHW::AppendISR(uint32_t ulISRType, void(*fptr)(void)) {
00602     int i;
00603     
00604     for(i = 0; i < 13; i++) {
00605         if( ulISRType == (1UL << i) ) {
00606             _qei_isr[i] = fptr;
00607             break;
00608         }
00609     }
00610     return;
00611 }
00612 
00613 /*********************************************************************//**
00614  * @brief        Unappend interrupt handler for specific QEI interrupt source
00615  * 
00616  * @param[in]    ulISRType        Interrupt Flag Status type, should be:
00617  *                                - QEI_INTFLAG_INX_Int: index pulse was detected interrupt
00618  *                                - QEI_INTFLAG_TIM_Int: Velocity timer over flow interrupt
00619  *                                - QEI_INTFLAG_VELC_Int: Capture velocity is less than compare interrupt
00620  *                                - QEI_INTFLAG_DIR_Int: Change of direction interrupt
00621  *                                - QEI_INTFLAG_ERR_Int: An encoder phase error interrupt
00622  *                                - QEI_INTFLAG_ENCLK_Int: An encoder clock pulse was detected interrupt
00623  *                                - QEI_INTFLAG_POS0_Int: position 0 compare value is equal to the
00624  *                                                        current position interrupt
00625  *                                - QEI_INTFLAG_POS1_Int: position 1 compare value is equal to the
00626  *                                                        current position interrupt
00627  *                                - QEI_INTFLAG_POS2_Int: position 2 compare value is equal to the
00628  *                                                        current position interrupt
00629  *                                - QEI_INTFLAG_REV_Int: Index compare value is equal to the current
00630  *                                                        index count interrupt
00631  *                                - QEI_INTFLAG_POS0REV_Int: Combined position 0 and revolution count interrupt
00632  *                                - QEI_INTFLAG_POS1REV_Int: Combined position 1 and revolution count interrupt
00633  *                                - QEI_INTFLAG_POS2REV_Int: Combined position 2 and revolution count interrupt
00634  *                                 
00635  * @return       none
00636  **********************************************************************/
00637 void QEIHW::UnAppendISR(uint32_t ulISRType) {
00638     int i;
00639     
00640     for(i = 0; i < 13; i++) {
00641         if( ulISRType == (1UL << i) ) {
00642             _qei_isr[i] = NULL;
00643             break;
00644         }
00645     }
00646     return;
00647 }
00648 
00649 
00650 void QEIHW::_Qeiisr(void)
00651 {
00652     instance->Qeiisr();
00653 }
00654 
00655 /*********************************************************************//**
00656  * @brief        QEI interrupt service dispatcher. 
00657  * 
00658  * @param[in]    none
00659  *                                 
00660  * @return       none
00661  **********************************************************************/
00662 void QEIHW::Qeiisr(void)  
00663 {
00664     int32_t i;
00665 
00666     //User defined interrupt handlers. Check all possible sources, dispatch to corresponding non-null service routines.
00667     for(i = 0; i < 13; i++) {
00668         if(LPC_QEI->QEIINTSTAT & ((uint32_t)(1<<i)) ) {
00669             if (_qei_isr[i] != NULL) {
00670                 _qei_isr[i]();
00671             }
00672         }
00673     }
00674     return;
00675 }
00676