Part: Tm4c123BH6ZRB
Quad encoder connected to PF0/PF1 (correctly unlocked and configured)
I get the QEI_INTDIR irq when changing direction on the quad encoder (basic unbounded knob).
When enabling the TIMER/Velocity feature, I can track the position accurately, but I don't really want to be handling irq's that often b/c the knob isn't the primary input.
What I would like/expect is an irq for each 'click' on the knob. I believe that is what my user would expect as well.
How does one get an IRQ for each turn of the knob? Note that each turn of the knob does indeed produce a PHA/PHB signal, so it seems like this should be a reasonable request.
Here's the relevant code. I have a ton of extraneous lines here to help with learning how the QEI is behaving. I feel like this should be possible, I just don't have the right config to make it work this way.
static void knobIsr() { uint32_t status = ROM_QEIIntStatus(QEI0_BASE, false); uint8_t button = KNOB_ROTATE_RIGHT_CHANNEL; ROM_QEIIntDisable(QEI0_BASE, QEI_INTDIR | QEI_INTINDEX | QEI_INTTIMER | QEI_INTERROR); ROM_QEIIntClear(QEI0_BASE, status); cnt++; if ( status & QEI_INTDIR ) { // change in direction? utilLog("change dir "); utilLogByte(cnt); utilLog("\r\n"); } utilLog("Index "); utilLogByte(ROM_QEIPositionGet(QEI0_BASE));utilLog(" "); utilLogByte(status); utilLog("\r\n"); if ( status & QEI_INTINDEX ) { utilLog("change idx "); utilLogByte(cnt); utilLog("\r\n"); // index was updated ,so we detected a turn int32_t dir = ROM_QEIDirectionGet(QEI0_BASE); if ( dir < 0 ) { button = KNOB_ROTATE_LEFT_CHANNEL; toggleRight = !toggleRight; keypadSet(1, toggleRight); } else { toggleLeft = !toggleLeft; keypadSet(2, toggleLeft); } RingBufWrite(&g_quadeRingBuf, &button, 1); } ROM_QEIIntEnable(QEI0_BASE, QEI_INTDIR | QEI_INTINDEX | QEI_INTTIMER | QEI_INTERROR); }
static void knobInit() { // not directly related, but close enough levelLedInit(); #define USE_QUAD_ENCODER #ifdef USE_QUAD_ENCODER ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_QEI0); ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_4|GPIO_PIN_5); // just in case pins #ifdef USE_TIVAWARE HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY; #else HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD; #endif // Allow the register AFSEL, PUR, PDR and DEN to be written. HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= GPIO_PIN_0; // Clear the AFSEL register per the workaround. HWREG(GPIO_PORTF_BASE + GPIO_O_AFSEL) &= 0xfe; // Clear the DEN register per the workaround. HWREG(GPIO_PORTF_BASE + GPIO_O_DEN) &= 0xfe; ROM_GPIOPinTypeQEI(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1); ROM_GPIOPinConfigure(GPIO_PF0_PHA0); ROM_GPIOPinConfigure(GPIO_PF1_PHB0); // Lock the GPIO. HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0; RingBufInit(&g_quadeRingBuf, g_quadeBuffer, sizeof(g_quadeBuffer)); ROM_QEIConfigure(QEI0_BASE,QEI_CONFIG_CAPTURE_A | QEI_CONFIG_RESET_IDX | QEI_CONFIG_QUADRATURE, 16 ); // enable the filter to prevent noise from making extra ticks HWREG(QEI0_BASE + QEI_O_CTL ) |= QEI_CTL_FILTEN; ROM_QEIPositionSet(QEI0_BASE, 0); ROM_QEIVelocityEnable(QEI0_BASE); ROM_QEIVelocityConfigure(QEI0_BASE, QEI_VELDIV_1, ROM_SysCtlClockGet()); QEIIntRegister(QEI0_BASE, knobIsr ); ROM_QEIIntClear(QEI0_BASE, QEI_INTDIR | QEI_INTINDEX | QEI_INTTIMER | QEI_INTERROR); ROM_QEIIntEnable(QEI0_BASE, QEI_INTDIR | QEI_INTINDEX | QEI_INTTIMER | QEI_INTERROR); ROM_QEIEnable(QEI0_BASE); #else ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_4|GPIO_PIN_5); // just in case pins ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); ROM_GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_1); GPIOIntClear(GPIO_PORTE_BASE, GPIO_PIN_0); ROM_GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_0|GPIO_PIN_1, GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD); ROM_GPIOIntTypeSet(GPIO_PORTF_BASE, GPIO_PIN_0, GPIO_BOTH_EDGES); GPIOIntRegister(GPIO_PORTF_BASE, quadEhandler); GPIOIntEnable(GPIO_PORTF_BASE, GPIO_PIN_0); #endif // watch the IRQ line from both lines ROM_GPIOPinTypeGPIOInput(GPIO_PORTE_BASE, GPIO_PIN_6); // just in case pins ROM_GPIOPadConfigSet(GPIO_PORTE_BASE,GPIO_PIN_6, GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD); ROM_GPIOIntTypeSet(GPIO_PORTE_BASE, GPIO_PIN_6, GPIO_FALLING_EDGE); // GPIOIntRegister(GPIO_PORTE_BASE, quadIrqHandler); // GPIOIntEnable(GPIO_PORTE_BASE, GPIO_PIN_6); utilLog("knob init\r\n"); }
TIA.