/* --COPYRIGHT--,BSD * Copyright (c) 2013, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ //***************************************************************************** // //! main.c // //! 430BOOST-SHARP96 Capacitive Touch Slider Example Project //! This project demonstrates the use of the two capacitive touch //! slider sensors on the 430BOOST-SHARP96 booster pack. // //! Capacitive Touch Slider Implementation: //! - Two vertical sliders //! - Three elements each //! - End element is split between the top and the bottom on each slider, //! enabling four electrodes on the PCB to be driven with three pins //! and 3 software elements. As such, each slider actually looks like //! a wheel sensor to software (since the ends are electrically connected, //! they appear as one element). The MSP430 Capacitive Touch Library is //! used to measure the electrodes and calculate a wheel position, and the //! Sliders_update function in this file is used to derive a slider position //! from that. // //! Build Requirements: //! - GCC Extentions // //! \author Texas Instruments //! \author MSP430 Strategic Applications // //! \version 1.0 - W. Schnoor, 1/7/14: Initial Release // //***************************************************************************** // // Include Standard Libraries // #include #include // // Include the MSP430 Capacitive Touch Library // #include "CTS_Layer.h" // // Include Touch Pro GUI Tools // #include "TouchProGUI.h" // //! \def TOGGLE_LEDR is a macro for toggling the MSP-EXP430G2 //! LaunchPad red LED (LED1) //! \def TOGGLE_LEDG is a macro for toggling the MSP-EXP430G2 //! LaunchPad green LED (LED2) // #define LP_LEDPORT (P1OUT) #define LP_LEDPORTDIR (P1DIR) #define LP_LEDR (BIT0) #define LP_LEDG (BIT6) #define TOGGLE_LEDR (P1OUT ^= LP_LEDR) #define TOGGLE_LEDG (P1OUT ^= LP_LEDG) // //! \def RESPONSE_TIME_MILLISECONDS specifies the response time of the //! panel in ms; i.e. how often the LCD image is re-drawn with the //! updated slider position. // //! \def RESPONSE_TIME_CYCLES specifies the response time of the //! panel in VLO clock cycles. // #define RESPONSE_TIME_MILLISECONDS 50 #define RESPONSE_TIME_CYCLES (RESPONSE_TIME_MILLISECONDS * 12) // //! \def LEFT_SLIDER specifies the index of the left slider in the //! slider pointer array and the position of the slider output in the //! measurement array (g_ui16MeasurementArray). // //! \def RIGHT_SLIDER specifies the index of the right slider in the //! slider pointer array and the position of the slider output in the //! measurement array (g_ui16MeasurementArray). // //! \def NUM_OF_SLIDERS specifies the number of sliders to process. // #define LEFT_SLIDER (0) #define RIGHT_SLIDER (1) #define NUM_OF_SLIDERS (2) // //! \var g_pSlider contains pointers to the sliders to process. // //! \var g_ui16LowerTrim contains the lower trim point for the two sliders. // //! \var g_ui16UpperTrim contains the upper trim point for the two sliders. // const struct Sensor* g_pSlider[NUM_OF_SLIDERS] = { &leftSlider, &rightSlider }; const uint16_t g_ui16LowerTrim[NUM_OF_SLIDERS] = { 2, 2 }; const uint16_t g_ui16UpperTrim[NUM_OF_SLIDERS] = { 62, 62 }; // // \var g_bUpdatePanel indicates to the background loop that the // panel should be scanned and the g_ui16MeasurementArray updated. // TouchProGUI is also sent an update at this time. // bool g_bUpdatePanel = false; // //! \var g_ui16MeasurementArray contains the outputs of the capacitive touch //! algorithms. There are two sliders with three elements each for a total of //! 6 raw channels and 2 position channels (8 total channels). // //! The array is used as follows: //! -[0] = Left Slider Position //! -[1] = Right Slider Position //! -[2] = Left Slider Element 0 Delta //! -[3] = Left Slider Element 1 Delta //! -[4] = Left Slider Element 2 Delta //! -[5] = Right Slider Element 0 Delta //! -[6] = Right Slider Element 1 Delta //! -[7] = Right Slider Element 2 Delta // uint16_t g_ui16MeasurementArray[8] = {0}; // // Local Function Prototypes // bool Sliders_update(void); void errorTrap(void); //***************************************************************************** // //! main() //! This is the point of entry into the program, //! and houses the background loop. // //***************************************************************************** void main(void) { bool bPanelTouched; // // Hold the watchdog timer. // NOTE: The watchdog timer is utilized in this program by // the capacitive touch library (in interval mode). // As such, it is unavailable to the application to be used in // watchdog mode (though it can be shared with the touch library // via time multiplexing. // WDTCTL = WDTPW | WDTHOLD; // // Configure Port 1 Pins 0 and 6 to be Output Low. // These pins are the LED pins on the MSP-EXP430G2 LaunchPad. // LP_LEDPORT = 0x00; LP_LEDPORTDIR = LP_LEDR | LP_LEDG; // // Configure the G2xx Basic Clock Module (BCM+) // - MCLK = 12MHz // - SMCLK = 6MHz // - ACLK = ~12kHz // if ((CALBC1_1MHZ == 0xFF) || (CALBC1_8MHZ==0xFF)) { // // If DCO calibrations are erased, trap CPU // errorTrap(); } DCOCTL = 0x00; BCSCTL1 = CALBC1_12MHZ; DCOCTL = CALDCO_12MHZ; BCSCTL2 = DIVS_1; BCSCTL3 |= LFXT1S_2; // // Initialize the TouchPro GUI USCI UART interface. // TouchProGUI_init(); // // Initialize the baseline measurement for each element // in the left slider and the right slider. // TI_CAPT_Update_Tracking_Rate(TRIDOI_MED | TRADOI_SLOW); TI_CAPT_Init_Baseline(&leftSlider); TI_CAPT_Init_Baseline(&rightSlider); // // Perform baseline averaging to ensure the starting // baseline value is accurate. // TI_CAPT_Update_Baseline(&leftSlider, 5); TI_CAPT_Update_Baseline(&rightSlider, 5); // // Start the periodic interval wakeup timer (Timer A1 is used in this example). // TA1CCTL0 = CCIE; TA1CCR0 = RESPONSE_TIME_CYCLES; TA1CTL = TASSEL_1 | MC_1; // // Enable CPU interrupts // __enable_interrupt(); // // Background Loop // while (1) { if (g_bUpdatePanel == true) { g_bUpdatePanel = false; TOGGLE_LEDR; bPanelTouched = Sliders_update(); TouchProGUI_sendData(g_ui16MeasurementArray, 8); if (bPanelTouched == true) { LP_LEDPORT |= LP_LEDG; } else { LP_LEDPORT &= ~LP_LEDG; } } LPM0; } } //***************************************************************************** // //! Sliders_update() //! Measure the left and right slider sensors, storing new measurement info in //! the global array g_ui16MeasurementArray. This function calls into the //! capacitive touch library to get measurents back, than handles the wheel //! unwrapping, basic edge trim, and a single-level averaging filter. // //! /param none. //! /return true if either of the two sliders are being touched, else false. // //***************************************************************************** bool Sliders_update(void) { uint16_t ui16newPosition[NUM_OF_SLIDERS]; uint8_t ui8currSlider; uint16_t ui16ZeroPoint; // // Get Delta Measurement. This data will be used to display in TouchPro GUI. // TI_CAPT_Custom(&leftSlider, &g_ui16MeasurementArray[2]); TI_CAPT_Custom(&rightSlider, &g_ui16MeasurementArray[5]); // // Get Current Slider Positions. // The Capacitive Touch Library wheel abstraction is used to handle // the electrode geometry, and is unwrapped into a slider in the // processing code below. // for (ui8currSlider=0; ui8currSliderpoints / g_pSlider[ui8currSlider]->numElements) >> 1; // // If below zero point, the user is at the top of the slider // if(ui16newPosition[ui8currSlider] < ui16ZeroPoint) { ui16newPosition[ui8currSlider] += g_pSlider[ui8currSlider]->points - ui16ZeroPoint; } // // Else if above the zero point, the user is at the bottom or middle of the slider // else { ui16newPosition[ui8currSlider] -= ui16ZeroPoint; } // // Trim edges to prevent un-intentional wraparound // if (ui16newPosition[ui8currSlider] > g_ui16LowerTrim[ui8currSlider]) { ui16newPosition[ui8currSlider] -= g_ui16LowerTrim[ui8currSlider]; } else { ui16newPosition[ui8currSlider] = 0; } ui16newPosition[ui8currSlider] = (ui16newPosition[ui8currSlider] * g_pSlider[ui8currSlider]->points); ui16newPosition[ui8currSlider] /= g_ui16UpperTrim[ui8currSlider] - g_ui16LowerTrim[ui8currSlider]; if (ui16newPosition[ui8currSlider] > g_pSlider[ui8currSlider]->points) { ui16newPosition[ui8currSlider] = g_pSlider[ui8currSlider]->points; } // // Average in new positions to the measurement array ([0] = Left Slider Position, [1] = Right Slider Position) // g_ui16MeasurementArray[ui8currSlider] += ui16newPosition[ui8currSlider]; g_ui16MeasurementArray[ui8currSlider] >>= 1; // // Panel is being touched, return true // return true; } } // // Panel not touched, return false // return false; } //***************************************************************************** // //! errorTrap() will hold the CPU and light both LEDs if called. // //! \param none. //! \return none. // //***************************************************************************** void errorTrap(void) { LP_LEDPORT |= LP_LEDR | LP_LEDG; while(1) { __no_operation(); }; } //***************************************************************************** // //! IntervalWakeup provides periodic wake up from LPM3 to measure the //! capacitive touch sliders. // //***************************************************************************** #pragma vector=TIMER1_A0_VECTOR __interrupt void IntervalWakeupISR (void) { // // Set flag to update panel, then wake from LPM3 sleep // g_bUpdatePanel = true; LPM3_EXIT; } //***************************************************************************** // //! ISR Trap // //***************************************************************************** #pragma vector= PORT2_VECTOR,PORT1_VECTOR,ADC10_VECTOR,NMI_VECTOR, \ USCIAB0RX_VECTOR,TIMER0_A1_VECTOR, COMPARATORA_VECTOR, \ TIMER1_A1_VECTOR,TIMER0_A0_VECTOR __interrupt void ISR_trap(void) { // // Trap the CPU and flag an error // errorTrap(); }