You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

412 lines
12 KiB

/* --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();
}