|
/* --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 <msp430.h>
|
|
#include <stdbool.h>
|
|
|
|
//
|
|
// 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; ui8currSlider<NUM_OF_SLIDERS; ui8currSlider++)
|
|
{
|
|
ui16newPosition[ui8currSlider] = TI_CAPT_Wheel(g_pSlider[ui8currSlider]);
|
|
|
|
//
|
|
// If new position is valid, unwrap the wheel value back to a slider value
|
|
//
|
|
if (ui16newPosition[ui8currSlider] != ILLEGAL_SLIDER_WHEEL_POSITION)
|
|
{
|
|
//
|
|
// Calculate Zero Point (bottom/top division point)
|
|
//
|
|
ui16ZeroPoint = (g_pSlider[ui8currSlider]->points / 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();
|
|
}
|