//***************************************************************************** // // Main cap-touch example. // //***************************************************************************** int main(void) { uint8_t ui8CenterButtonTouched; uint32_t ui32WheelTouchCounter; uint8_t ui8ConvertedWheelPosition; uint8_t ui8GestureDetected; uint8_t ui8Loop; // // Enable lazy stacking for interrupt handlers. This allows floating-point // instructions to be used within interrupt handlers, but at the expense of // extra stack usage. // ROM_FPULazyStackingEnable(); // // Set the clocking to run directly from the PLL at 80 MHz. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // // Initialize a few GPIO outputs for the LEDs // ROM_GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_4); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_5); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_4); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_6); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_7); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE, GPIO_PIN_5); // // Turn on the Center LED // ROM_GPIOPinWrite(GPIO_PORTB_BASE, GPIO_PIN_5, GPIO_PIN_5); // // Initialize the UART. // ROM_GPIOPinConfigure(GPIO_PA0_U0RX); ROM_GPIOPinConfigure(GPIO_PA1_U0TX); ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTStdioConfig(0, 9600, ROM_SysCtlClockGet()); // // Configure the pins needed for capacitive touch sensing. The capsense // driver assumes that these pins are already configured, and that they // will be accessed through the AHB bus // SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOA); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_AHB_BASE, GPIO_PIN_2); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_AHB_BASE, GPIO_PIN_3); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_AHB_BASE, GPIO_PIN_4); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_AHB_BASE, GPIO_PIN_6); ROM_GPIOPinTypeGPIOOutput(GPIO_PORTA_AHB_BASE, GPIO_PIN_7); // // Start up Systick to measure time. This is also required by the capsense // drivers. // ROM_SysTickPeriodSet(0x00FFFFFF); ROM_SysTickEnable(); // // Set the baseline capacitance measurements for our wheel and center // button. // TI_CAPT_Init_Baseline(&g_sSensorWheel); TI_CAPT_Update_Baseline(&g_sSensorWheel, 10); TI_CAPT_Init_Baseline(&g_sMiddleButton); TI_CAPT_Update_Baseline(&g_sMiddleButton, 10); // // Send the "sleep" code. The TIVA C-series version of this app doesn't // actually sleep, but the MSP430-based GUI it interacts with expects to // see this code on startup, so we will provide it here. // UARTprintf("\0xDE\0xAD"); // // Send the "awake" code. // UARTprintf("\0xBE\0xEF"); // // Perform an LED startup sequence. // for(ui8Loop = 0; ui8Loop < 16; ui8Loop++) { LEDOutput(ui8Loop); DelayMs(10); } LEDOutput(0); // // Assume that the center button starts off "untouched", the wheel has no // position, and no gestures are in progress. // ui8CenterButtonTouched = 0; ui8ConvertedWheelPosition = INVALID_CONVERTED_POSITION; ui8GestureDetected = 0; // // This "wheel counter" gets incremented when a button on the wheel is held // down. Every time it hits the value of WHEEL_TOUCH_DELAY, the device // sends a signal to the GUI reporting another button press. We want this // delay normally, but we'll set the counter to just below the threshold // for now, so we'll avoid any percieved lag between the initial button // press and the first position report to the GUI. // ui32WheelTouchCounter = WHEEL_TOUCH_DELAY - 1; // // Begin the main capsense loop. // while(1) { // // Start by taking a fresh measurement from the wheel. If it remains // set to ILLEGAL_SLIDER_WHEEL_POSITION, we will know it has not been // touched at all. Otherwise we will have an updated position. // g_ui32WheelPosition = ILLEGAL_SLIDER_WHEEL_POSITION; g_ui32WheelPosition = TI_CAPT_Wheel(&g_sSensorWheel); // // If we registered a touch somewhere on the wheel, we will need to // figure out how to report that touch back to the GUI on the PC. // if(g_ui32WheelPosition != ILLEGAL_SLIDER_WHEEL_POSITION) { // // First, make sure we're not reporting center button touches while // the wheel is active. // ui8CenterButtonTouched = 0; // // We need to do a quick formatting change on the wheel position. // The "zero" postion as reported by the driver is about 40 degrees // off from "up" on the physical wheel. We'll do that correction // here. // if(g_ui32WheelPosition < 8) { g_ui32WheelPosition += 64 - 8; } else { g_ui32WheelPosition -= 8; } // // We also need to reduce the effective number of positions on the // wheel. The driver reports a wheel position from zero to // sixty-three, but the GUI only recognizes positions from zero to // sixteen. Dividing our position by four accomplishes the // necessary conversion. // g_ui32WheelPosition = g_ui32WheelPosition >> 2; // // Now that we have a properly formatted wheel position, we will // use the GetGesture function to determine whether the user has // been sliding their finger around the wheel. If so, this function // will return the magnitude and direction of the slide (Check the // function description for an example of how this is formated). // Otherwise, we will get back a zero. // ui8ConvertedWheelPosition = GetGesture(g_ui32WheelPosition); // // If the magnitude of our slide was one wheel position (of // sixteen) or less, don't register it. This prevents excessive // reporting of toggles between two adjacent wheel positions. // if((ui8GestureDetected == 0) && ((ui8ConvertedWheelPosition <= 1) || (ui8ConvertedWheelPosition == 0x11) || (ui8ConvertedWheelPosition == 0x10))) { // // If we obtained a valid wheel position last time we ran this // loop, keep our wheel position set to that instead of // updating it. This prevents a mismatch between our recorded // absolute position and our recorded swipe magnitude. // if(g_ui32PreviousWheelPosition != ILLEGAL_SLIDER_WHEEL_POSITION) { g_ui32WheelPosition = g_ui32PreviousWheelPosition; } // // Set the swipe magnitude to zero. // ui8ConvertedWheelPosition = 0; } // // We've made all of the position adjustments we're going to make, // so turn on LEDs to indicate that we've detected a finger on the // wheel. // LEDOutput(g_ui32WheelPosition); // // If the (adjusted) magnitude of the swipe we detected earlier is // valid and non-zero, we should alert the GUI that a gesture is // occurring. // if((ui8ConvertedWheelPosition != 0) && (ui8ConvertedWheelPosition != 16) && (ui8ConvertedWheelPosition != INVALID_CONVERTED_POSITION)) { // // If this is a new gesture, we will need to send the gesture // start code. // if(ui8GestureDetected == 0) { // // Remember that we've started a gesture. // ui8GestureDetected = 1; // // Transmit gesture start status update & position via UART // to PC. // ROM_UARTCharPut(UART0_BASE, GESTURE_START); ROM_UARTCharPut(UART0_BASE, (g_ui32PreviousWheelPosition + GESTURE_POSITION_OFFSET)); } // // Transmit gesture & position via UART to PC // ROM_UARTCharPut(UART0_BASE, ui8ConvertedWheelPosition); ROM_UARTCharPut(UART0_BASE, (g_ui32WheelPosition + GESTURE_POSITION_OFFSET)); } else { // // If we get here, the wheel has been touched, but there hasn't // been any sliding recently. If there hasn't been any sliding // AT ALL, then this is a "press" event, and we need to start // sending press-style updates to the PC // if(ui8GestureDetected == 0) { // // Increment our wheel counter. // ui32WheelTouchCounter = ui32WheelTouchCounter + 1; // // If the user's finger is still in the same place... // if(ui32WheelTouchCounter >= WHEEL_TOUCH_DELAY) { // // Transmit wheel position (twice) via UART to PC. // ui32WheelTouchCounter = 0; ROM_UARTCharPut(UART0_BASE, (g_ui32WheelPosition + WHEEL_POSITION_OFFSET)); ROM_UARTCharPut(UART0_BASE, (g_ui32WheelPosition + WHEEL_POSITION_OFFSET)); } } else { // // We've received a slide input somewhat recently, but not // during this loop instance. This most likely means that // the user started a gesture, but is currently just // holding their finger in one spot. This isn't really a // "press" event, so there isn't anything to report. We // should, however, make sure the touch counter is primed // for future press events. // ui32WheelTouchCounter = WHEEL_TOUCH_DELAY - 1; } } // // Regardless of all pressing, sliding, reporting, and LED events // that may have occurred, we need to record our measured // (adjusted) wheel position for reference for the next pass // through the loop. // g_ui32PreviousWheelPosition = g_ui32WheelPosition; } else { // // If we get here, there were no touches recorded on the slider // wheel. We should check our middle button to see if it has been // pressed, and clean up our recorded state to prepare for future // possible wheel-touch events. // if(TI_CAPT_Button(&g_sMiddleButton))
/* ----------------CapTouchActiveMode---------------------------------------------- * Determine immediate gesture based on current & previous wheel position * * * * * * * * -------------------------------------------------------------------------------*/ void CapTouchActiveMode() { unsigned char idleCounter, activeCounter; unsigned char gesture, gestureDetected; unsigned char centerButtonTouched = 0; unsigned int wheelTouchCounter = WHEEL_TOUCH_DELAY - 1; gesture = INVALID_GESTURE; // Wipes out gesture history /* Send status via UART: 'wake up' = [0xBE, 0xEF] */ SendByte(WAKE_UP_UART_CODE); SendByte(WAKE_UP_UART_CODE2); idleCounter = 0; activeCounter = 0; gestureDetected = 0; while (idleCounter++ < MAX_IDLE_TIME) { /* Set DCO to 8MHz */ /* SMCLK = 8MHz/8 = 1MHz */ // BCSCTL1 = CALBC1_8MHZ; // DCOCTL = CALDCO_8MHZ; // BCSCTL2 |= DIVS_3; /* SMCLK = 1MHz/4 = 250kHz */ BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; BCSCTL2 |= DIVS_2; TACCTL0 &= ~CCIE; wheel_position = ILLEGAL_SLIDER_WHEEL_POSITION; wheel_position = TI_CAPT_Wheel(&wheel); /* Process wheel touch/position/gesture if a wheel touch is registered*/ /* Wheel processing has higher priority than center button*/ if(wheel_position != ILLEGAL_SLIDER_WHEEL_POSITION) { centerButtonTouched = 0; /* Adjust wheel position based: rotate CCW by 2 positions */ if (wheel_position < 0x08) { wheel_position += 0x40 - 0x08; } else { wheel_position -= 0x08; /* Adjust wheel position based: rotate CCW by 2 positions */ } wheel_position = wheel_position >>2; // divide by four gesture = GetGesture(wheel_position); /* Add hysteresis to reduce toggling between wheel positions if no gesture * has been TRULY detected. */ if ( (gestureDetected==0) && ((gesture<=1) || (gesture==0x11) || (gesture==0x10))) { if (last_wheel_position != ILLEGAL_SLIDER_WHEEL_POSITION) wheel_position = last_wheel_position; gesture = 0; } /* Turn on corresponding LED(s) */ P1OUT = (P1OUT & BIT0) | LedWheelPosition[wheel_position]; if ((gesture != 0) && (gesture != 16) && (gesture != INVALID_GESTURE)) { /* A gesture has been detected */ if (gestureDetected ==0) { /* Starting of a new gesture sequence */ gestureDetected = 1; /* Transmit gesture start status update & position via UART to PC */ SendByte(GESTURE_START); SendByte(last_wheel_position + GESTURE_POSITION_OFFSET); } /* Transmit gesture & position via UART to PC */ SendByte(gesture); SendByte(wheel_position + GESTURE_POSITION_OFFSET); } else if (gestureDetected==0) { /* If no gesture was detected, this is constituted as a touch/tap */ if (++wheelTouchCounter >= WHEEL_TOUCH_DELAY) { /* Transmit wheel position [twice] via UART to PC */ wheelTouchCounter = 0; SendByte(wheel_position + WHEEL_POSITION_OFFSET ); SendByte(wheel_position + WHEEL_POSITION_OFFSET ); } } else wheelTouchCounter = WHEEL_TOUCH_DELAY - 1; idleCounter = 0; // Reset idle counter activeCounter++; last_wheel_position = wheel_position; } else { /* no wheel position was detected */ if(TI_CAPT_Button(&middle_button))