/***************************************************************************//** * @brief Determine which button if any is being pressed * @param groupOfElements Pointer to buttons to be scanned * @return result pointer to element (button) being pressed or 0 none ******************************************************************************/ const struct Element *TI_CAPT_Buttons(const struct Sensor *groupOfElements) { uint8_t index; #ifndef RAM_FOR_FLASH uint16_t *measCnt; measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t)); if(measCnt ==0) { while(1); } #endif TI_CAPT_Custom(groupOfElements, measCnt); if(ctsStatusReg & EVNT) { index = Dominant_Element(groupOfElements, measCnt); //ctsStatusReg &= ~EVNT; index++; } else { index = 0; } #ifndef RAM_FOR_FLASH free(measCnt); #endif if(index) { return groupOfElements->arrayPtr[index-1]; } return 0; }
//***************************************************************************** // //! Determine which element in a multi-element sensor is being pressed, if any. //! //! \param psSensor Pointer to sensor containing elements to be scanned. //! //! This function takes a capacitive measurement of all elements in \e //! psSensor, and checks to see if any element has exceeded the threshold for a //! touch event. If so, it will will return a pointer to the most active //! element, normalized by the \e ui32MaxResponse for each element. This //! function can be used with multi-element sensors to create an array of //! mutually exclusive buttons. //! //! Please note that this function will also update the baseline capacitance //! for all elements in the sensor psSensor. //! //! \return Returns a pointer to the element (button) being pressed or 0 if no //! element was pressed. // //***************************************************************************** const tCapTouchElement * TI_CAPT_Buttons(const tSensor *psSensor) { uint8_t ui8Index; // // Find the delta counts of all elements in the given sensor. // TI_CAPT_Custom(psSensor, g_pui32MeasCount); // // If at least one element was pressed, find the dominant element // (normalized by maximum response), and return a pointer to that element // back to the caller. // if(g_ui32CtsStatusReg & EVNT) { ui8Index = Dominant_Element(psSensor, g_pui32MeasCount); return(psSensor->psElement[ui8Index]); } else { // // If there were no touch events at all, return a zero. // return(0); } }
//***************************************************************************** // //! Determine if any element in the given sensor is being pressed. //! //! \param psSensor pointer to the sensor structure whose elements are to be //! scanned for button presses. //! //! This function takes measrements of all elements in \e psSensor and checks //! to see if any element has exceeded its threshold for a touch event. This //! function can be used with single-element sensors to create a capacitive //! "button". The return value is a simple 1 or 0 indication of whether the //! button is currently being pressed. //! //! Please note that this function will also update the baseline capacitance //! for all elements in the sensor psSensor. //! //! \return Indication if button is pressed (1) or is not being pressed (0) // //***************************************************************************** uint8_t TI_CAPT_Button(const tSensor *psSensor) { uint8_t ui8Result; // // Start with the assumption that no button was pressed. // ui8Result = 0; // // Perform a quick measurement of the delta counts on the chosen sensor. // TI_CAPT_Custom(psSensor, g_pui32MeasCount); // // Check to see if any threshold-crossing events were recorded. // if(g_ui32CtsStatusReg & EVNT) { // // If so, the button is being pressed. Return a 1. Otherwise return a // zero. // ui8Result = 1; } return ui8Result; }
// Main Function void main(void) { // Initialize System Clocks WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer //Clock Setting CSCTL1 &= ~(DCORSEL_7); // Clear DCO frequency select bits first CSCTL1 |= DCORSEL_3; // Set DCO = 8MHz, max in G6021 CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source CSCTL4 = SELMS__DCOCLKDIV | SELREF__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz CSCTL5 |= DIVM_0 | DIVS_0; // SMCLK = MCLK = DCODIV/1 = 8MHz // Initializing GPIO P8DIR |= BIT1; //Set the pin controlling the center LED P8.1 as output pin PM5CTL0 &= ~LOCKLPM5; // Initialize Baseline measurement TI_CAPT_Init_Baseline(&one_button); //TI_CAPT_Init_Baseline(&one_button); //Update baseline measurement (Average 100 measurements) TI_CAPT_Update_Baseline(&one_button,100); // Main loop starts here while (1) { #ifdef ELEMENT_CHARACTERIZATION_MODE // Get the raw delta counts for element characterization TI_CAPT_Custom(&one_button,&dCnt); __no_operation(); // Set breakpoint here #endif #ifndef ELEMENT_CHARACTERIZATION_MODE // Check if the middle element sensor has been triggered. The API call // compares the value from the sensor against the threshold to determine // trigger condition if(TI_CAPT_Button(&one_button)) { // Do something P8OUT |= BIT1; // Turn on center LED } else { P8OUT &= ~BIT1; // Turn off center LED } // Put the MSP430 into LPM3 for a certain DELAY period sleep(DELAY); #endif } } // End Main
// Main Function void main(void) { // Initialize System Clocks WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1, 8, 12 or 16MHz DCOCTL = CALDCO_1MHZ; BCSCTL2 |= DIVS_2; // divide SMCLK by 4 for 250khz BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO P1OUT = 0x00; // Clear Port 1 bits P1DIR |= BIT0; // Set P1.0 as output pin P2SEL &= ~(BIT6 + BIT7); // Configure XIN (P2.6) and XOUT (P2.7) to GPIO P2OUT = 0x00; // Drive all Port 2 pins low P2DIR = 0xFF; // Configure all Port 2 pins outputs // Initialize Baseline measurement TI_CAPT_Init_Baseline(&one_button); // Update baseline measurement (Average 5 measurements) TI_CAPT_Update_Baseline(&one_button,5); // Main loop starts here while (1) { #ifdef ELEMENT_CHARACTERIZATION_MODE // Get the raw delta counts for element characterization TI_CAPT_Custom(&one_button,&dCnt); __no_operation(); // Set breakpoint here #endif #ifndef ELEMENT_CHARACTERIZATION_MODE // Check if the middle element sensor has been triggered. The API call // compares the value from the sensor against the threshold to determine // trigger condition if(TI_CAPT_Button(&one_button)) { // Do something P1OUT |= BIT0; // Turn on center LED } else { P1OUT &= ~BIT0; // Turn off center LED } // Put the MSP430 into LPM3 for a certain DELAY period sleep(DELAY); #endif } } // End Main
// Main Function void main(void) { // Initialize System Clocks WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer //Clock Setting CSCTL0_H = 0xA5; // Unlock CS CSCTL1 = DCORSEL + DCOFSEL_5; // Set DCO = 20MHz, use this clk when fRO CSCTL2 = SELA__VLOCLK + SELS_3 + SELM_3; // set SMCLK = MCLK = DCO LFXT1 = VLO CSCTL0_H = 0; // Lock CS registers P4DIR |= BIT2; // Set the pin controlling the center LED P4.2 as output pin // Initialize Baseline measurement TI_CAPT_Init_Baseline(&one_button); // Update baseline measurement (Average 5 measurements) TI_CAPT_Update_Baseline(&one_button,5); // Main loop starts here while (1) { #ifdef ELEMENT_CHARACTERIZATION_MODE // Get the raw delta counts for element characterization TI_CAPT_Custom(&one_button,&dCnt); __no_operation(); // Set breakpoint here #endif #ifndef ELEMENT_CHARACTERIZATION_MODE // Check if the middle element sensor has been triggered. The API call // compares the value from the sensor against the threshold to determine // trigger condition if(TI_CAPT_Button(&one_button)) { // Do something P4OUT |= BIT2; // Turn on center LED } else { P4OUT &= ~BIT2; // Turn off center LED } // Put the MSP430 into LPM3 for a certain DELAY period sleep(DELAY); #endif } } // End Main
/* ----------------CapTouchIdleMode----------------------------------------- * Device stays in LPM3 'sleep' mode, only Proximity Sensor is used to detect * any movement triggering device wake up * ------------------------------------------------------------------------*/ void CapTouchIdleMode(void) { /* Send status via UART: 'sleep' = [0xDE, 0xAD] */ SendByte(SLEEP_MODE_UART_CODE); SendByte(SLEEP_MODE_UART_CODE2); /* Set DCO to 1MHz */ /* Set SMCLK to 8MHz / 8 = 1MHz */ // BCSCTL1 = CALBC1_8MHZ; // DCOCTL = CALDCO_8MHZ; // BCSCTL2 |= DIVS_3; /* Set SMCLK to 1MHz / 4 = 250kHz */ // BCSCTL1 = CALBC1_1MHZ; // DCOCTL = CALDCO_1MHZ; // BCSCTL2 |= DIVS_2; /* Set SMCLK to 1.5MHz */ BCSCTL1 = CALBC1_12MHZ; DCOCTL = CALDCO_12MHZ; // BCSCTL2 |= DIVS_3; P1OUT |= BIT0; // Turn on center LED deltaCnts[0] = 0; /* Sleeping in LPM3 with ACLK/100 = 12Khz/100 = 120Hz wake up interval */ /* Measure proximity sensor count upon wake up */ /* Wake up if proximity deltaCnts > THRESHOLD */ do { TACCR0 = 100; TACTL = TASSEL_1 + MC_1; TACCTL0 |= CCIE; __bis_SR_register(LPM3_bits+GIE); TACCTL0 &= ~CCIE; TI_CAPT_Custom(&proximity_sensor,deltaCnts); } while (deltaCnts[0] <= PROXIMITY_THRESHOLD); P1OUT &= ~BIT0; // Turn off center LED }
/***************************************************************************//** * @brief Determine if a button is being pressed * @param groupOfElements Pointer to button to be scanned * @return result Indication if button is (1) or is not (0) being pressed ******************************************************************************/ uint8_t TI_CAPT_Button(const struct Sensor * groupOfElements) { uint8_t result = 0; #ifndef RAM_FOR_FLASH uint16_t *measCnt; measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t)); if(measCnt ==0) { while(1); } #endif TI_CAPT_Custom(groupOfElements, measCnt); #ifndef RAM_FOR_FLASH free(measCnt); #endif if(ctsStatusReg & EVNT) { result = 1; } return result; }
// Main Function void main(void) { uint8_t last = 0; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL1 = CALBC1_16MHZ; // Set DCO to 1, 8, 12 or 16MHz DCOCTL = CALDCO_16MHZ; BCSCTL1 |= DIVA_0; // ACLK/1 [ACLK/(0:1,1:2,2:4,3:8)] //BCSCTL2 |= DIVS_3; // SMCLK/8 [SMCLK/(0:1,1:2,2:4,3:8)] BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO Clock Source P1OUT |= BIT0; // P1.0 out P1DIR |= BIT0; // P1.0 high P2DIR |= BIT0 | BIT1 | BIT4 | BIT5; // Configure Port 2 pins outputs // Initialize Baseline measurement TI_CAPT_Init_Baseline(&button_bar); // Update baseline measurement (Average 5 measurements) TI_CAPT_Update_Baseline(&button_bar,5); SPISetup(); // Initialize SPI Display //drawBitmap(blackbird_96_64, 96, 8, 0, 0); clear(); //setcharmode(1); //largechars //writeString(2,1,"Press button!"); // Main loop starts here while (1) { #ifdef ELEMENT_CHARACTERIZATION_MODE // Get the raw delta counts for element characterization TI_CAPT_Custom(&button_bar,wheelCnt); __no_operation(); // Set breakpoint here #endif #ifndef ELEMENT_CHARACTERIZATION_MODE // Return the pointer to the element which has been touched keyPressed = (struct Element *)TI_CAPT_Buttons(&button_bar); // If a button has been touched, then take some action if(keyPressed) { // Up Element if(keyPressed == &a_element) { P1OUT |= BIT0; // Turn on center LED if (last != 2) { clear(); last = 2; drawBitmap(big_1, 32, 6, 32, 1); //writeString(4,3,"A Pressed"); } } if(keyPressed == &b_element) { P1OUT |= BIT0; // Turn on center LED if (last != 3) { clear(); last = 3; drawBitmap(big_2, 32, 6, 32, 1); //writeString(4,3,"B Pressed"); } } if(keyPressed == &c_element) { P1OUT |= BIT0; // Turn on center LED if (last != 1) { clear(); last = 1; drawBitmap(big_3, 32, 6, 32, 1); //writeString(4,3,"C Pressed"); } } if(keyPressed == &d_element) { P1OUT |= BIT0; // Turn on center LED if (last != 4) { clear(); last = 4; drawBitmap(big_4, 32, 6, 32, 1); //writeString(4,3,"D Pressed"); } } } else { P1OUT &= ~(BIT0); // Turn off center LED if (last != 0) { drawBitmap(blackbird_96_64, 96, 8, 0, 0); //writeString(4,4,"Press a button"); last = 0; } } // Put the MSP430 into LPM3 for a certain DELAY period sleep(DELAY); #endif } } // End Main
/***************************************************************************//** * @brief Determine the position on a wheel * @param groupOfElements Pointer to wheel * @return result position on wheel or illegal value if no touch ******************************************************************************/ uint16_t TI_CAPT_Wheel(const struct Sensor* groupOfElements) { uint8_t index; int16_t position; // allocate memory for measurement #ifndef RAM_FOR_FLASH uint16_t *measCnt; measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t)); if(measCnt ==0) { while(1); } #endif position = ILLEGAL_SLIDER_WHEEL_POSITION; //make measurement TI_CAPT_Custom(groupOfElements, measCnt); // Translate the EVNT flag from an element level EVNT to a sensor level EVNT. // The sensor must read at least 75% cumulative response before indicating a // touch. if(ctsStatusReg & EVNT) { index = Dominant_Element(groupOfElements, &measCnt[0]); // The index represents the element within the array with the highest return. // if(index == 0) { // Special case of 1st element in slider, add 1st, last, and 2nd position = measCnt[0] + measCnt[groupOfElements->numElements -1] + measCnt[1]; } else if(index == (groupOfElements->numElements -1)) { // Special case of Last element in slider, add last, 1st, and 2nd to last position = measCnt[index] + measCnt[0] + measCnt[index-1]; } else { position = measCnt[index] + measCnt[index+1] + measCnt[index-1]; } if(position > groupOfElements->sensorThreshold) { //index = Dominant_Element(groupOfElements, &measCnt[0]); // The index represents the element within the array with the highest return. // position = index*(groupOfElements->points/groupOfElements->numElements); position += (groupOfElements->points/groupOfElements->numElements)/2; if(index == 0) { // Special case of 1st element in slider, which only has one neighbor, measCnt[1] // measCnt is limited to maxResponse within dominantElement function position += (measCnt[1]*(groupOfElements->points/groupOfElements->numElements))/100; position -= (measCnt[groupOfElements->numElements -1]*(groupOfElements->points/groupOfElements->numElements))/100; if(position < 0) { position = position + (int16_t)groupOfElements->points; } } else if(index == (groupOfElements->numElements -1)) { // Special case of Last element in slider, which only has one neighbor, measCnt[x-1] or measCnt[numElements-1] // measCnt is limited to maxResponse within dominantElement function position += (measCnt[0]*(groupOfElements->points/groupOfElements->numElements))/100; position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100; if(position > (groupOfElements->points -1)) { position = position - (int16_t)groupOfElements->points; } } else { position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100; position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100; } if((position > groupOfElements->points) || position < 0) { position = ILLEGAL_SLIDER_WHEEL_POSITION; } } else { position = ILLEGAL_SLIDER_WHEEL_POSITION; } } #ifndef RAM_FOR_FLASH free(measCnt); #endif return position; }
/***************************************************************************//** * @brief Determine the position on a slider * @param groupOfElements Pointer to slider * @return result position on slider or illegal value if no touch ******************************************************************************/ uint16_t TI_CAPT_Slider(const struct Sensor* groupOfElements) { uint8_t index; int16_t position; // allocate memory for measurement #ifndef RAM_FOR_FLASH uint16_t *measCnt; measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t)); if(measCnt ==0) { while(1); } #endif position = ILLEGAL_SLIDER_WHEEL_POSITION; //make measurement TI_CAPT_Custom(groupOfElements, measCnt); // Use EVNT flag to determine if slider was touched. // The EVNT flag is a global variable and managed within the TI_CAPT_Custom function. if(ctsStatusReg & EVNT) { index = Dominant_Element(groupOfElements, &measCnt[0]); // The index represents the element within the array with the highest return. if(index == 0) { // Special case of 1st element in slider, add 1st, last, and 2nd position = measCnt[0] + measCnt[1]; } else if(index == (groupOfElements->numElements -1)) { // Special case of Last element in slider, add last, 1st, and 2nd to last position = measCnt[groupOfElements->numElements -1] + measCnt[groupOfElements->numElements -2]; } else { position = measCnt[index] + measCnt[index+1] + measCnt[index-1]; } // Determine if sensor threshold criteria is met if(position > groupOfElements->sensorThreshold) { // calculate position position = index*(groupOfElements->points/groupOfElements->numElements); position += (groupOfElements->points/groupOfElements->numElements)/2; if(index == 0) { // Special case of 1st element in slider, which only has one // neighbor, measCnt[1]. measCnt is limited to maxResponse // within dominantElement function if(measCnt[1]) { position += (measCnt[1]*(groupOfElements->points/groupOfElements->numElements))/100; } else { position = (measCnt[0]*(groupOfElements->points/groupOfElements->numElements)/2)/100; } } else if(index == (groupOfElements->numElements -1)) { // Special case of Last element in slider, which only has one // neighbor, measCnt[x-1] or measCnt[numElements-1] if(measCnt[index-1]) { position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100; } else { position = groupOfElements->points; position -= (measCnt[index]*(groupOfElements->points/groupOfElements->numElements)/2)/100; } } else { position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100; position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100; } if((position > groupOfElements->points) || (position < 0)) { position = ILLEGAL_SLIDER_WHEEL_POSITION; } } else { position = ILLEGAL_SLIDER_WHEEL_POSITION; } } #ifndef RAM_FOR_FLASH free(measCnt); #endif return position; }
//***************************************************************************** // //! Detect touch events on a wheel element, and return the position of any //! touch event found in units of points. //! //! \param psSensor Pointer to the wheel element to be measured. //! //! This function performs a capacitive measurement on the given sensor \e //! psSensor, and interprets the results assuming that this sensor represents a //! physical wheel. Its return value is a numerical position along the surface //! of the wheel. A position of zero represents a touch on the wheel centered //! at the point where the element of index zero and the last element in the //! array physically touch. Position values increase around the circumference //! of the wheel in the same direction as increasing element indices in the \e //! psSensor structure. //! //! Please note that this function will also update the baseline capacitance //! for all elements in the sensor \e psSensor. //! //! \return Returns the calculate position of the touch event on the wheel or //! an illegal value \b ILLEGAL_SLIDER_WHEEL_POSITION if no touch was detected. // //***************************************************************************** uint32_t TI_CAPT_Wheel(const tSensor* psSensor) { uint8_t ui8NumElements, ui8Points, ui8PointsPerElement; uint8_t ui8Index; uint32_t ui32SensorThreshold, ui32WheelPosition; uint32_t ui32ThresholdCheck; // // Gather important sensor-level information // ui32SensorThreshold = psSensor->ui32SensorThreshold; ui8NumElements = psSensor->ui8NumElements; ui8Points = psSensor->ui8Points; ui8PointsPerElement = ui8Points / ui8NumElements; // // Take a measurement of delta counts, and store it in our global // measurement array. // TI_CAPT_Custom(psSensor, g_pui32MeasCount); // // Check the global EVNT flag to see if any elements in this sensor are // active. If not, we can skip the calculations and simply return an // illegal position. // if(g_ui32CtsStatusReg & EVNT) { // // If we did have a touch event, normalize the responses and find the // index of the dominant element. // ui8Index = Dominant_Element(psSensor, &g_pui32MeasCount[0]); // // Check to see if the normalized responses of the dominant element and // the adjacent elements are collectively high enough to cross the // overall sensor threshold. If so, we can conclude that the touch // event is somewhere within the intended track of the physical wheel, // and we can go ahead and calculate the position. Make sure to handle // the first and last elements carefully, as their neighbors wrap // around the array boundary. // if(ui8Index == 0) { ui32ThresholdCheck = (g_pui32MeasCount[ui8Index] + g_pui32MeasCount[ui8Index + 1] + g_pui32MeasCount[ui8NumElements - 1]); } else if(ui8Index == (ui8NumElements - 1)) { ui32ThresholdCheck = (g_pui32MeasCount[ui8Index] + g_pui32MeasCount[ui8Index - 1] + g_pui32MeasCount[0]); } else { ui32ThresholdCheck = (g_pui32MeasCount[ui8Index] + g_pui32MeasCount[ui8Index + 1] + g_pui32MeasCount[ui8Index - 1]); } // // If we didn't pass our threshold check, we probably have a touch // event close to the sensor, but not actually in the desired region of // the physical wheel. This means we should stop our calculation here // and return an illegal position value. // if(ui32ThresholdCheck < ui32SensorThreshold) { return ILLEGAL_SLIDER_WHEEL_POSITION; } // // If we passed the check, it's time to calculate the position (in // points) of the touch. We will start with the assumption that the // touch is in the exact center of the dominant element // ui32WheelPosition = ((ui8Index * ui8PointsPerElement) + (ui8PointsPerElement / 2)); // // Then we will improve our calculation of the touch position by // factoring in the measurements from the two adjacent elements. The // first and last sensors in the wheel are special cases, as each of // them only has one adjacent element. // if(ui8Index == 0) { // // Special case for the first element in the array, which requires // wrapping of the index. // ui32WheelPosition += ((g_pui32MeasCount[ui8Index + 1] * ui8PointsPerElement) / 100); ui32WheelPosition -= ((g_pui32MeasCount[ui8NumElements - 1] * ui8PointsPerElement) / 100); } else if(ui8Index == (ui8NumElements - 1)) { // // Special case for the last element in the array, which requires // wrapping of the index. // ui32WheelPosition += ((g_pui32MeasCount[0] * ui8PointsPerElement) / 100); ui32WheelPosition -= ((g_pui32MeasCount[ui8Index - 1] * ui8PointsPerElement) / 100); } else { // // No wrapping necessary, so just push the position based on the // measurements of the adjacent elements // ui32WheelPosition += ((g_pui32MeasCount[ui8Index + 1] * ui8PointsPerElement) / 100); ui32WheelPosition -= ((g_pui32MeasCount[ui8Index - 1] * ui8PointsPerElement) / 100); } // // Return the adjusted position back to the caller. // return ui32WheelPosition; } else { // // We didn't register any touch events at all, so return an illegal // wheel position // return ILLEGAL_SLIDER_WHEEL_POSITION; } }