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

5 years ago
  1. /* --COPYRIGHT--,BSD
  2. * Copyright (c) 2013, Texas Instruments Incorporated
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of Texas Instruments Incorporated nor the names of
  17. * its contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  22. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  27. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  28. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. * --/COPYRIGHT--*/
  32. //*****************************************************************************
  33. //
  34. //! main.c
  35. //
  36. //! 430BOOST-SHARP96 Capacitive Touch Slider Example Project
  37. //! This project demonstrates the use of the two capacitive touch
  38. //! slider sensors on the 430BOOST-SHARP96 booster pack.
  39. //
  40. //! Capacitive Touch Slider Implementation:
  41. //! - Two vertical sliders
  42. //! - Three elements each
  43. //! - End element is split between the top and the bottom on each slider,
  44. //! enabling four electrodes on the PCB to be driven with three pins
  45. //! and 3 software elements. As such, each slider actually looks like
  46. //! a wheel sensor to software (since the ends are electrically connected,
  47. //! they appear as one element). The MSP430 Capacitive Touch Library is
  48. //! used to measure the electrodes and calculate a wheel position, and the
  49. //! Sliders_update function in this file is used to derive a slider position
  50. //! from that.
  51. //
  52. //! Build Requirements:
  53. //! - GCC Extentions
  54. //
  55. //! \author Texas Instruments
  56. //! \author MSP430 Strategic Applications
  57. //
  58. //! \version 1.0 - W. Schnoor, 1/7/14: Initial Release
  59. //
  60. //*****************************************************************************
  61. //
  62. // Include Standard Libraries
  63. //
  64. #include <msp430.h>
  65. #include <stdbool.h>
  66. //
  67. // Include the MSP430 Capacitive Touch Library
  68. //
  69. #include "CTS_Layer.h"
  70. //
  71. // Include Touch Pro GUI Tools
  72. //
  73. #include "TouchProGUI.h"
  74. //
  75. //! \def TOGGLE_LEDR is a macro for toggling the MSP-EXP430G2
  76. //! LaunchPad red LED (LED1)
  77. //! \def TOGGLE_LEDG is a macro for toggling the MSP-EXP430G2
  78. //! LaunchPad green LED (LED2)
  79. //
  80. #define LP_LEDPORT (P1OUT)
  81. #define LP_LEDPORTDIR (P1DIR)
  82. #define LP_LEDR (BIT0)
  83. #define LP_LEDG (BIT6)
  84. #define TOGGLE_LEDR (P1OUT ^= LP_LEDR)
  85. #define TOGGLE_LEDG (P1OUT ^= LP_LEDG)
  86. //
  87. //! \def RESPONSE_TIME_MILLISECONDS specifies the response time of the
  88. //! panel in ms; i.e. how often the LCD image is re-drawn with the
  89. //! updated slider position.
  90. //
  91. //! \def RESPONSE_TIME_CYCLES specifies the response time of the
  92. //! panel in VLO clock cycles.
  93. //
  94. #define RESPONSE_TIME_MILLISECONDS 50
  95. #define RESPONSE_TIME_CYCLES (RESPONSE_TIME_MILLISECONDS * 12)
  96. //
  97. //! \def LEFT_SLIDER specifies the index of the left slider in the
  98. //! slider pointer array and the position of the slider output in the
  99. //! measurement array (g_ui16MeasurementArray).
  100. //
  101. //! \def RIGHT_SLIDER specifies the index of the right slider in the
  102. //! slider pointer array and the position of the slider output in the
  103. //! measurement array (g_ui16MeasurementArray).
  104. //
  105. //! \def NUM_OF_SLIDERS specifies the number of sliders to process.
  106. //
  107. #define LEFT_SLIDER (0)
  108. #define RIGHT_SLIDER (1)
  109. #define NUM_OF_SLIDERS (2)
  110. //
  111. //! \var g_pSlider contains pointers to the sliders to process.
  112. //
  113. //! \var g_ui16LowerTrim contains the lower trim point for the two sliders.
  114. //
  115. //! \var g_ui16UpperTrim contains the upper trim point for the two sliders.
  116. //
  117. const struct Sensor* g_pSlider[NUM_OF_SLIDERS] = { &leftSlider, &rightSlider };
  118. const uint16_t g_ui16LowerTrim[NUM_OF_SLIDERS] = { 2, 2 };
  119. const uint16_t g_ui16UpperTrim[NUM_OF_SLIDERS] = { 62, 62 };
  120. //
  121. // \var g_bUpdatePanel indicates to the background loop that the
  122. // panel should be scanned and the g_ui16MeasurementArray updated.
  123. // TouchProGUI is also sent an update at this time.
  124. //
  125. bool g_bUpdatePanel = false;
  126. //
  127. //! \var g_ui16MeasurementArray contains the outputs of the capacitive touch
  128. //! algorithms. There are two sliders with three elements each for a total of
  129. //! 6 raw channels and 2 position channels (8 total channels).
  130. //
  131. //! The array is used as follows:
  132. //! -[0] = Left Slider Position
  133. //! -[1] = Right Slider Position
  134. //! -[2] = Left Slider Element 0 Delta
  135. //! -[3] = Left Slider Element 1 Delta
  136. //! -[4] = Left Slider Element 2 Delta
  137. //! -[5] = Right Slider Element 0 Delta
  138. //! -[6] = Right Slider Element 1 Delta
  139. //! -[7] = Right Slider Element 2 Delta
  140. //
  141. uint16_t g_ui16MeasurementArray[8] = {0};
  142. //
  143. // Local Function Prototypes
  144. //
  145. bool Sliders_update(void);
  146. void errorTrap(void);
  147. //*****************************************************************************
  148. //
  149. //! main()
  150. //! This is the point of entry into the program,
  151. //! and houses the background loop.
  152. //
  153. //*****************************************************************************
  154. void
  155. main(void)
  156. {
  157. bool bPanelTouched;
  158. //
  159. // Hold the watchdog timer.
  160. // NOTE: The watchdog timer is utilized in this program by
  161. // the capacitive touch library (in interval mode).
  162. // As such, it is unavailable to the application to be used in
  163. // watchdog mode (though it can be shared with the touch library
  164. // via time multiplexing.
  165. //
  166. WDTCTL = WDTPW | WDTHOLD;
  167. //
  168. // Configure Port 1 Pins 0 and 6 to be Output Low.
  169. // These pins are the LED pins on the MSP-EXP430G2 LaunchPad.
  170. //
  171. LP_LEDPORT = 0x00;
  172. LP_LEDPORTDIR = LP_LEDR | LP_LEDG;
  173. //
  174. // Configure the G2xx Basic Clock Module (BCM+)
  175. // - MCLK = 12MHz
  176. // - SMCLK = 6MHz
  177. // - ACLK = ~12kHz
  178. //
  179. if ((CALBC1_1MHZ == 0xFF) || (CALBC1_8MHZ==0xFF))
  180. {
  181. //
  182. // If DCO calibrations are erased, trap CPU
  183. //
  184. errorTrap();
  185. }
  186. DCOCTL = 0x00;
  187. BCSCTL1 = CALBC1_12MHZ;
  188. DCOCTL = CALDCO_12MHZ;
  189. BCSCTL2 = DIVS_1;
  190. BCSCTL3 |= LFXT1S_2;
  191. //
  192. // Initialize the TouchPro GUI USCI UART interface.
  193. //
  194. TouchProGUI_init();
  195. //
  196. // Initialize the baseline measurement for each element
  197. // in the left slider and the right slider.
  198. //
  199. TI_CAPT_Update_Tracking_Rate(TRIDOI_MED | TRADOI_SLOW);
  200. TI_CAPT_Init_Baseline(&leftSlider);
  201. TI_CAPT_Init_Baseline(&rightSlider);
  202. //
  203. // Perform baseline averaging to ensure the starting
  204. // baseline value is accurate.
  205. //
  206. TI_CAPT_Update_Baseline(&leftSlider, 5);
  207. TI_CAPT_Update_Baseline(&rightSlider, 5);
  208. //
  209. // Start the periodic interval wakeup timer (Timer A1 is used in this example).
  210. //
  211. TA1CCTL0 = CCIE;
  212. TA1CCR0 = RESPONSE_TIME_CYCLES;
  213. TA1CTL = TASSEL_1 | MC_1;
  214. //
  215. // Enable CPU interrupts
  216. //
  217. __enable_interrupt();
  218. //
  219. // Background Loop
  220. //
  221. while (1)
  222. {
  223. if (g_bUpdatePanel == true)
  224. {
  225. g_bUpdatePanel = false;
  226. TOGGLE_LEDR;
  227. bPanelTouched = Sliders_update();
  228. TouchProGUI_sendData(g_ui16MeasurementArray, 8);
  229. if (bPanelTouched == true)
  230. {
  231. LP_LEDPORT |= LP_LEDG;
  232. }
  233. else
  234. {
  235. LP_LEDPORT &= ~LP_LEDG;
  236. }
  237. }
  238. LPM0;
  239. }
  240. }
  241. //*****************************************************************************
  242. //
  243. //! Sliders_update()
  244. //! Measure the left and right slider sensors, storing new measurement info in
  245. //! the global array g_ui16MeasurementArray. This function calls into the
  246. //! capacitive touch library to get measurents back, than handles the wheel
  247. //! unwrapping, basic edge trim, and a single-level averaging filter.
  248. //
  249. //! /param none.
  250. //! /return true if either of the two sliders are being touched, else false.
  251. //
  252. //*****************************************************************************
  253. bool
  254. Sliders_update(void)
  255. {
  256. uint16_t ui16newPosition[NUM_OF_SLIDERS];
  257. uint8_t ui8currSlider;
  258. uint16_t ui16ZeroPoint;
  259. //
  260. // Get Delta Measurement. This data will be used to display in TouchPro GUI.
  261. //
  262. TI_CAPT_Custom(&leftSlider, &g_ui16MeasurementArray[2]);
  263. TI_CAPT_Custom(&rightSlider, &g_ui16MeasurementArray[5]);
  264. //
  265. // Get Current Slider Positions.
  266. // The Capacitive Touch Library wheel abstraction is used to handle
  267. // the electrode geometry, and is unwrapped into a slider in the
  268. // processing code below.
  269. //
  270. for (ui8currSlider=0; ui8currSlider<NUM_OF_SLIDERS; ui8currSlider++)
  271. {
  272. ui16newPosition[ui8currSlider] = TI_CAPT_Wheel(g_pSlider[ui8currSlider]);
  273. //
  274. // If new position is valid, unwrap the wheel value back to a slider value
  275. //
  276. if (ui16newPosition[ui8currSlider] != ILLEGAL_SLIDER_WHEEL_POSITION)
  277. {
  278. //
  279. // Calculate Zero Point (bottom/top division point)
  280. //
  281. ui16ZeroPoint = (g_pSlider[ui8currSlider]->points / g_pSlider[ui8currSlider]->numElements) >> 1;
  282. //
  283. // If below zero point, the user is at the top of the slider
  284. //
  285. if(ui16newPosition[ui8currSlider] < ui16ZeroPoint)
  286. {
  287. ui16newPosition[ui8currSlider] += g_pSlider[ui8currSlider]->points - ui16ZeroPoint;
  288. }
  289. //
  290. // Else if above the zero point, the user is at the bottom or middle of the slider
  291. //
  292. else
  293. {
  294. ui16newPosition[ui8currSlider] -= ui16ZeroPoint;
  295. }
  296. //
  297. // Trim edges to prevent un-intentional wraparound
  298. //
  299. if (ui16newPosition[ui8currSlider] > g_ui16LowerTrim[ui8currSlider])
  300. {
  301. ui16newPosition[ui8currSlider] -= g_ui16LowerTrim[ui8currSlider];
  302. }
  303. else
  304. {
  305. ui16newPosition[ui8currSlider] = 0;
  306. }
  307. ui16newPosition[ui8currSlider] = (ui16newPosition[ui8currSlider] * g_pSlider[ui8currSlider]->points);
  308. ui16newPosition[ui8currSlider] /= g_ui16UpperTrim[ui8currSlider] - g_ui16LowerTrim[ui8currSlider];
  309. if (ui16newPosition[ui8currSlider] > g_pSlider[ui8currSlider]->points)
  310. {
  311. ui16newPosition[ui8currSlider] = g_pSlider[ui8currSlider]->points;
  312. }
  313. //
  314. // Average in new positions to the measurement array ([0] = Left Slider Position, [1] = Right Slider Position)
  315. //
  316. g_ui16MeasurementArray[ui8currSlider] += ui16newPosition[ui8currSlider];
  317. g_ui16MeasurementArray[ui8currSlider] >>= 1;
  318. //
  319. // Panel is being touched, return true
  320. //
  321. return true;
  322. }
  323. }
  324. //
  325. // Panel not touched, return false
  326. //
  327. return false;
  328. }
  329. //*****************************************************************************
  330. //
  331. //! errorTrap() will hold the CPU and light both LEDs if called.
  332. //
  333. //! \param none.
  334. //! \return none.
  335. //
  336. //*****************************************************************************
  337. void
  338. errorTrap(void)
  339. {
  340. LP_LEDPORT |= LP_LEDR | LP_LEDG;
  341. while(1)
  342. {
  343. __no_operation();
  344. };
  345. }
  346. //*****************************************************************************
  347. //
  348. //! IntervalWakeup provides periodic wake up from LPM3 to measure the
  349. //! capacitive touch sliders.
  350. //
  351. //*****************************************************************************
  352. #pragma vector=TIMER1_A0_VECTOR
  353. __interrupt void IntervalWakeupISR (void)
  354. {
  355. //
  356. // Set flag to update panel, then wake from LPM3 sleep
  357. //
  358. g_bUpdatePanel = true;
  359. LPM3_EXIT;
  360. }
  361. //*****************************************************************************
  362. //
  363. //! ISR Trap
  364. //
  365. //*****************************************************************************
  366. #pragma vector= PORT2_VECTOR,PORT1_VECTOR,ADC10_VECTOR,NMI_VECTOR, \
  367. USCIAB0RX_VECTOR,TIMER0_A1_VECTOR, COMPARATORA_VECTOR, \
  368. TIMER1_A1_VECTOR,TIMER0_A0_VECTOR
  369. __interrupt void ISR_trap(void)
  370. {
  371. //
  372. // Trap the CPU and flag an error
  373. //
  374. errorTrap();
  375. }