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.

933 lines
33 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. * @file CTS_Layer.c
  34. *
  35. * @brief This source file contains the API calls and one support function.
  36. *
  37. * @par Project:
  38. * MSP430 Capacitive Touch Library
  39. *
  40. * @par Developed using:
  41. * CCS Version : 5.4.0.00048, w/support for GCC extensions (--gcc)
  42. * \n IAR Version : 5.51.6 [Kickstart]
  43. *
  44. * @author C. Sterzik
  45. * @author T. Hwang
  46. *
  47. * @version 1.2
  48. * Updated HALs for new devices.
  49. *
  50. * @par Supported API Calls:
  51. * - TI_CAPT_Init_Baseline()
  52. * - TI_CAPT_Update_Baseline()
  53. * - TI_CAPT_Reset_Tracking()
  54. * - TI_CAPT_Update_Tracking_DOI()
  55. * - TI_CAPT_Update_Tracking_Rate()
  56. * - TI_CAPT_Raw()
  57. * - TI_CAPT_Custom()
  58. * - TI_CAPT_Button()
  59. * - TI_CAPT_Buttons()
  60. * - TI_CAPT_Slider()
  61. * - TI_CAPT_Wheel()
  62. */
  63. #include "CTS_Layer.h"
  64. /*! @defgroup GLOBAL_VARS Global Variables
  65. * @{
  66. */
  67. #ifdef TOTAL_NUMBER_OF_ELEMENTS
  68. /*!
  69. * The baseline tracking variables
  70. */
  71. uint16_t baseCnt[TOTAL_NUMBER_OF_ELEMENTS];
  72. #ifdef RAM_FOR_FLASH
  73. /*!
  74. * The current measurement variables
  75. */
  76. uint16_t measCnt[MAXIMUM_NUMBER_OF_ELEMENTS_PER_SENSOR];
  77. #endif
  78. /*!
  79. * The Status Register
  80. */
  81. uint16_t ctsStatusReg = (DOI_INC+TRADOI_FAST+TRIDOI_SLOW);
  82. #endif
  83. /*!
  84. * @}
  85. */
  86. /** @defgroup CTS_API API Group
  87. * @{
  88. */
  89. /***************************************************************************//**
  90. * @brief Measure the capacitance of each element within the Sensor
  91. *
  92. * This function selects the appropriate HAL to perform the capacitance
  93. * measurement based upon the halDefinition found in the sensor
  94. * structure.
  95. * The order of the elements within the Sensor structure is arbitrary
  96. * but must be consistent between the application and configuration.
  97. * The first element in the array (counts) corresponds to the first
  98. * element within the Sensor structure.
  99. * @param groupOfElements Pointer to Sensor structure to be measured
  100. * @param counts Address to where the measurements are to be written
  101. * @return none
  102. ******************************************************************************/
  103. void TI_CAPT_Raw(const struct Sensor* groupOfElements, uint16_t * counts)
  104. {
  105. #ifdef RO_CSIO_TA2_WDTA
  106. if(groupOfElements->halDefinition == RO_CSIO_TA2_WDTA)
  107. {
  108. TI_CTS_RO_CSIO_TA2_WDTA_HAL(groupOfElements, counts);
  109. }
  110. #endif
  111. #ifdef RO_CSIO_TA2_TA3
  112. if(groupOfElements->halDefinition == RO_CSIO_TA2_TA3)
  113. {
  114. TI_CTS_RO_CSIO_TA2_TA3_HAL(groupOfElements, counts);
  115. }
  116. #endif
  117. #ifdef fRO_CSIO_TA2_TA3
  118. if(groupOfElements->halDefinition == fRO_CSIO_TA2_TA3)
  119. {
  120. TI_CTS_fRO_CSIO_TA2_TA3_HAL(groupOfElements, counts);
  121. }
  122. #endif
  123. #ifdef RO_COMPB_TB0_WDTA
  124. if(groupOfElements->halDefinition == RO_COMPB_TB0_WDTA)
  125. {
  126. TI_CTS_RO_COMPB_TB0_WDTA_HAL(groupOfElements, counts);
  127. }
  128. #endif
  129. #ifdef RO_PINOSC_TA0_TA1
  130. if(groupOfElements->halDefinition == RO_PINOSC_TA0_TA1)
  131. {
  132. TI_CTS_RO_PINOSC_TA0_TA1_HAL(groupOfElements, counts);
  133. }
  134. #endif
  135. #ifdef fRO_PINOSC_TA0_TA1
  136. if(groupOfElements->halDefinition == fRO_PINOSC_TA0_TA1)
  137. {
  138. TI_CTS_fRO_PINOSC_TA0_TA1_HAL(groupOfElements, counts);
  139. }
  140. #endif
  141. #ifdef RO_COMPAp_TA0_WDTp
  142. if(groupOfElements->halDefinition == RO_COMPAp_TA0_WDTp)
  143. {
  144. TI_CTS_RO_COMPAp_TA0_WDTp_HAL(groupOfElements, counts);
  145. }
  146. #endif
  147. #ifdef fRO_COMPAp_TA0_SW
  148. if(groupOfElements->halDefinition == fRO_COMPAp_TA0_SW)
  149. {
  150. TI_CTS_fRO_COMPAp_TA0_SW_HAL(groupOfElements, counts);
  151. }
  152. #endif
  153. #ifdef fRO_COMPAp_SW_TA0
  154. if(groupOfElements->halDefinition == fRO_COMPAp_SW_TA0)
  155. {
  156. TI_CTS_fRO_COMPAp_SW_TA0_HAL(groupOfElements, counts);
  157. }
  158. #endif
  159. #ifdef RO_COMPAp_TA1_WDTp
  160. if(groupOfElements->halDefinition == RO_COMPAp_TA1_WDTp)
  161. {
  162. TI_CTS_RO_COMPAp_TA1_WDTp_HAL(groupOfElements, counts);
  163. }
  164. #endif
  165. #ifdef fRO_COMPAp_TA1_SW
  166. if(groupOfElements->halDefinition == fRO_COMPAp_TA1_SW)
  167. {
  168. TI_CTS_fRO_COMPAp_TA1_SW_HAL(groupOfElements, counts);
  169. }
  170. #endif
  171. #ifdef RC_PAIR_TA0
  172. if(groupOfElements->halDefinition == RC_PAIR_TA0)
  173. {
  174. TI_CTS_RC_PAIR_TA0_HAL(groupOfElements, counts);
  175. }
  176. #endif
  177. #ifdef RO_PINOSC_TA0_WDTp
  178. if(groupOfElements->halDefinition == RO_PINOSC_TA0_WDTp)
  179. {
  180. TI_CTS_RO_PINOSC_TA0_WDTp_HAL(groupOfElements, counts);
  181. }
  182. #endif
  183. #ifdef RO_PINOSC_TA0
  184. if(groupOfElements->halDefinition == RO_PINOSC_TA0)
  185. {
  186. TI_CTS_RO_PINOSC_TA0_HAL(groupOfElements, counts);
  187. }
  188. #endif
  189. #ifdef fRO_PINOSC_TA0_SW
  190. if(groupOfElements->halDefinition == fRO_PINOSC_TA0_SW)
  191. {
  192. TI_CTS_fRO_PINOSC_TA0_SW_HAL(groupOfElements, counts);
  193. }
  194. #endif
  195. #ifdef RO_COMPB_TA0_WDTA
  196. if(groupOfElements->halDefinition == RO_COMPB_TA0_WDTA)
  197. {
  198. TI_CTS_RO_COMPB_TA0_WDTA_HAL(groupOfElements, counts);
  199. }
  200. #endif
  201. #ifdef fRO_COMPB_TA0_SW
  202. if(groupOfElements->halDefinition == fRO_COMPB_TA0_SW)
  203. {
  204. TI_CTS_fRO_COMPB_TA0_SW_HAL(groupOfElements, counts);
  205. }
  206. #endif
  207. #ifdef RO_COMPB_TA1_WDTA
  208. if(groupOfElements->halDefinition == RO_COMPB_TA1_WDTA)
  209. {
  210. TI_CTS_RO_COMPB_TA1_WDTA_HAL(groupOfElements, counts);
  211. }
  212. #endif
  213. #ifdef fRO_COMPB_TA1_SW
  214. if(groupOfElements->halDefinition == fRO_COMPB_TA1_SW)
  215. {
  216. TI_CTS_fRO_COMPB_TA1_SW_HAL(groupOfElements, counts);
  217. }
  218. #endif
  219. #ifdef RO_COMPB_TA1_TA0
  220. if(groupOfElements->halDefinition == RO_COMPB_TA1_TA0)
  221. {
  222. TI_CTS_RO_COMPB_TA1_TA0_HAL(groupOfElements, counts);
  223. }
  224. #endif
  225. #ifdef fRO_COMPB_TA1_TA0
  226. if(groupOfElements->halDefinition == fRO_COMPB_TA1_TA0)
  227. {
  228. TI_CTS_fRO_COMPB_TA1_TA0_HAL(groupOfElements, counts);
  229. }
  230. #endif
  231. #ifdef RO_PINOSC_TA1_WDTp
  232. if(groupOfElements->halDefinition == RO_PINOSC_TA1_WDTp)
  233. {
  234. TI_CTS_RO_PINOSC_TA1_WDTp_HAL(groupOfElements, counts);
  235. }
  236. #endif
  237. #ifdef RO_PINOSC_TA1_TB0
  238. if(groupOfElements->halDefinition == RO_PINOSC_TA1_TB0)
  239. {
  240. TI_CTS_RO_PINOSC_TA1_TB0_HAL(groupOfElements, counts);
  241. }
  242. #endif
  243. #ifdef fRO_PINOSC_TA1_TA0
  244. if(groupOfElements->halDefinition == fRO_PINOSC_TA1_TA0)
  245. {
  246. TI_CTS_fRO_PINOSC_TA1_TA0_HAL(groupOfElements, counts);
  247. }
  248. #endif
  249. #ifdef fRO_PINOSC_TA1_TB0
  250. if(groupOfElements->halDefinition == fRO_PINOSC_TA1_TB0)
  251. {
  252. TI_CTS_fRO_PINOSC_TA1_TB0_HAL(groupOfElements, counts);
  253. }
  254. #endif
  255. }
  256. #ifdef TOTAL_NUMBER_OF_ELEMENTS
  257. /***************************************************************************//**
  258. * @brief Make a single capacitance meausrment to initialize baseline tracking
  259. * @param groupOfElements Pointer to Sensor structure to be measured
  260. * @return none
  261. ******************************************************************************/
  262. void TI_CAPT_Init_Baseline(const struct Sensor* groupOfElements)
  263. {
  264. TI_CAPT_Raw(groupOfElements, &baseCnt[groupOfElements->baseOffset]);
  265. }
  266. /***************************************************************************//**
  267. * @brief Update baseline tracking by averaging several measurements
  268. * @param groupOfElements Pointer to Sensor structure to be measured
  269. * @param numberOfAverages Number of measurements to be averaged
  270. * @return none
  271. ******************************************************************************/
  272. void TI_CAPT_Update_Baseline(const struct Sensor* groupOfElements, uint8_t numberOfAverages)
  273. {
  274. uint8_t i,j;
  275. #ifndef RAM_FOR_FLASH
  276. uint16_t *measCnt;
  277. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  278. if(measCnt ==0)
  279. {
  280. while(1);
  281. }
  282. #endif
  283. for(j=0; j < numberOfAverages; j++)
  284. {
  285. for(i=0; i < groupOfElements->numElements; i++)
  286. {
  287. TI_CAPT_Raw(groupOfElements, measCnt);
  288. baseCnt[i+groupOfElements->baseOffset]
  289. = measCnt[i]/2 + baseCnt[i+groupOfElements->baseOffset]/2;
  290. }
  291. }
  292. #ifndef RAM_FOR_FLASH
  293. free(measCnt);
  294. #endif
  295. }
  296. /***************************************************************************//**
  297. * @brief Reset the Baseline Tracking algorithm to the default state
  298. * @param none
  299. * @return none
  300. ******************************************************************************/
  301. void TI_CAPT_Reset_Tracking(void)
  302. {
  303. ctsStatusReg = (DOI_INC+TRADOI_FAST+TRIDOI_SLOW);
  304. }
  305. /***************************************************************************//**
  306. * @brief Update the Baseline Tracking algorithm Direction of Interest
  307. * @param direction Direction of increasing or decreasing capacitance
  308. * @return none
  309. ******************************************************************************/
  310. void TI_CAPT_Update_Tracking_DOI(uint8_t direction)
  311. {
  312. if(direction)
  313. {
  314. ctsStatusReg |= DOI_INC;
  315. }
  316. else
  317. {
  318. ctsStatusReg &= ~DOI_INC;
  319. }
  320. }
  321. /***************************************************************************//**
  322. * @brief Update the baseling tracking algorithm tracking rates
  323. * @param rate Rate of tracking changes in and against direction of intrest
  324. * @return none
  325. ******************************************************************************/
  326. void TI_CAPT_Update_Tracking_Rate(uint8_t rate)
  327. {
  328. ctsStatusReg &= ~(TRIDOI_FAST+TRADOI_VSLOW); // clear fields
  329. ctsStatusReg |= (rate & 0xF0); // update fields
  330. }
  331. /***************************************************************************//**
  332. * @brief Measure the change in capacitance of the Sensor
  333. *
  334. * This function measures the change in capacitance of each element
  335. * within a sensor and updates the baseline tracking in the event that
  336. * no change exceeds the detection threshold.
  337. * The order of the elements within the Sensor structure is arbitrary
  338. * but must be consistent between the application and configuration.
  339. * The first element in the array (deltaCnt) corresponds to the first
  340. * element within the Sensor structure.
  341. * @param groupOfElements Pointer to Sensor structure to be measured
  342. * @param deltaCnt Address to where the measurements are to be written
  343. * @return none
  344. ******************************************************************************/
  345. void TI_CAPT_Custom(const struct Sensor* groupOfElements, uint16_t * deltaCnt)
  346. {
  347. uint8_t j;
  348. uint16_t tempCnt, remainder;
  349. ctsStatusReg &= ~ EVNT;
  350. TI_CAPT_Raw(groupOfElements, &deltaCnt[0]); // measure group of sensors
  351. for (j = 0; j < (groupOfElements->numElements); j++)
  352. {
  353. tempCnt = deltaCnt[j];
  354. if(deltaCnt[j])
  355. {
  356. if(((ctsStatusReg & DOI_MASK)
  357. && (groupOfElements->halDefinition & RO_MASK))
  358. ||
  359. ((!(ctsStatusReg & DOI_MASK))
  360. && (!(groupOfElements->halDefinition & RO_MASK))))
  361. {
  362. /*
  363. * Interested in a decrease in counts. Either the decrease
  364. * represents an increase in capacitance (a touch) with the
  365. * RO method, or the decrease represents a decrease in capacitance
  366. * (release) with the fRO or RC methods.
  367. */
  368. if(baseCnt[j+groupOfElements->baseOffset] < deltaCnt[j])
  369. {
  370. /*
  371. * The measured value is greater than the baseline therefore
  372. * no detection logic is needed. The measured value is
  373. * preserved in tempCnt and is used for baseline updates.
  374. */
  375. deltaCnt[j] = 0;
  376. if(((groupOfElements->arrayPtr[j])->threshold)
  377. &&
  378. (baseCnt[j+groupOfElements->baseOffset]
  379. +((groupOfElements->arrayPtr[j])->threshold/2) < tempCnt))
  380. {
  381. /*
  382. * When the threshold is valid (non-calibration state),
  383. * limit the measurement to the baseline + threshold/2.
  384. */
  385. tempCnt = baseCnt[j+groupOfElements->baseOffset]
  386. +((groupOfElements->arrayPtr[j])->threshold)/2;
  387. }
  388. }
  389. else
  390. {
  391. /*
  392. * deltaCnt now represents the magnitude of change relative to
  393. * the baseline.
  394. */
  395. deltaCnt[j] = baseCnt[j+groupOfElements->baseOffset]
  396. - deltaCnt[j];
  397. }
  398. }
  399. if(((!(ctsStatusReg & DOI_MASK))
  400. && (groupOfElements->halDefinition & RO_MASK))
  401. ||
  402. ((ctsStatusReg & DOI_MASK)
  403. && (!(groupOfElements->halDefinition & RO_MASK))))
  404. {
  405. /*
  406. * Interested in an increase in counts. Either the increase
  407. * represents a decrease in capacitance (a release) with the
  408. * RO method, or the increase represents a increase in capacitance
  409. * (touch) with the fRO or RC methods.
  410. */
  411. if(baseCnt[j+groupOfElements->baseOffset] > deltaCnt[j])
  412. {
  413. /*
  414. * The measured value is less than the baseline therefore
  415. * no detection logic is needed. The measured value is
  416. * preserved in tempCnt and is used for baseline updates.
  417. */
  418. deltaCnt[j] = 0;
  419. if(((groupOfElements->arrayPtr[j])->threshold)
  420. &&
  421. (baseCnt[j+groupOfElements->baseOffset]
  422. -((groupOfElements->arrayPtr[j])->threshold/2) > tempCnt))
  423. {
  424. /*
  425. * When the threshold is valid (non-calibration state),
  426. * limit the measurement to the baseline - threshold/2.
  427. */
  428. tempCnt = baseCnt[j+groupOfElements->baseOffset]
  429. -((groupOfElements->arrayPtr[j])->threshold)/2;
  430. }
  431. }
  432. else
  433. {
  434. /*
  435. * deltaCnt now represents the magnitude of change relative to
  436. * the baseline.
  437. */
  438. deltaCnt[j] = deltaCnt[j]
  439. - baseCnt[j+groupOfElements->baseOffset];
  440. }
  441. }
  442. // This section updates the baseline capacitance************************
  443. if (deltaCnt[j]==0)
  444. { // if delta counts is 0, then the change in capacitance was opposite
  445. // the direction of interest. The baseCnt[i] is updated with the
  446. // saved tempCnt value for the current index value 'i'.
  447. remainder = 0;
  448. switch ((ctsStatusReg & TRADOI_VSLOW))
  449. {
  450. case TRADOI_FAST://Fast
  451. tempCnt = tempCnt/2;
  452. baseCnt[j+groupOfElements->baseOffset]
  453. = (baseCnt[j+groupOfElements->baseOffset]/2);
  454. break;
  455. case TRADOI_MED://Medium
  456. tempCnt = tempCnt/4;
  457. baseCnt[j+groupOfElements->baseOffset]
  458. = 3*(baseCnt[j+groupOfElements->baseOffset]/4);
  459. break;
  460. case TRADOI_SLOW://slow
  461. /* Calculate remainder associated with (x + 63*y)/64 */
  462. remainder = 0x003F & baseCnt[j+groupOfElements->baseOffset];
  463. remainder = remainder * 63;
  464. remainder += 0x003F & tempCnt;
  465. remainder = remainder >> 6;
  466. tempCnt = tempCnt/64;
  467. baseCnt[j+groupOfElements->baseOffset]
  468. = 63*(baseCnt[j+groupOfElements->baseOffset]/64);
  469. break;
  470. case TRADOI_VSLOW://very slow
  471. /* Calculate remainder associated with (x+127*y)/128 */
  472. remainder = 0x007F & baseCnt[j+groupOfElements->baseOffset];
  473. remainder = remainder * 127;
  474. remainder += 0x007F & tempCnt;
  475. remainder = remainder >> 7;
  476. tempCnt = tempCnt/128;
  477. baseCnt[j+groupOfElements->baseOffset]
  478. = 127*(baseCnt[j+groupOfElements->baseOffset]/128);
  479. break;
  480. }
  481. /* Base_Capacitance = (Measured_Capacitance/Z)
  482. + Y*(Base_Capacitance/Z) */
  483. tempCnt += remainder;
  484. baseCnt[j+groupOfElements->baseOffset] += tempCnt;
  485. /* In the case that DOI is set and */
  486. if(groupOfElements->halDefinition & RO_MASK)
  487. {
  488. /* If the RO_MASK is set then the direction of interest is
  489. * decreasing (counts decrease with capacitance) and therefore
  490. * movement against the direction of interest would be an
  491. * increase: increment.
  492. */
  493. baseCnt[j+groupOfElements->baseOffset]++;
  494. }
  495. else
  496. {
  497. /* RO_MASK is not set and therefore a decrease is against
  498. * the direction of interest: decrement
  499. */
  500. baseCnt[j+groupOfElements->baseOffset]--;
  501. }
  502. }
  503. /* deltaCnt is either 0, less than threshold, or greater than
  504. threshold, never negative. */
  505. else if(deltaCnt[j]<(groupOfElements->arrayPtr[j])->threshold
  506. && !(ctsStatusReg & PAST_EVNT))
  507. { //if delta counts is positive but less than threshold,
  508. remainder = 1;
  509. switch ((ctsStatusReg & TRIDOI_FAST))
  510. {
  511. case TRIDOI_VSLOW:
  512. tempCnt = 0;
  513. break;
  514. case TRIDOI_SLOW://slow
  515. remainder = 2;
  516. tempCnt = 0;
  517. break;
  518. case TRIDOI_MED://medium
  519. tempCnt = tempCnt/4;
  520. baseCnt[j+groupOfElements->baseOffset] = 3*(baseCnt[j+groupOfElements->baseOffset]/4);
  521. break;
  522. case TRIDOI_FAST://fast
  523. tempCnt = tempCnt/2;
  524. baseCnt[j+groupOfElements->baseOffset] = (baseCnt[j+groupOfElements->baseOffset]/2);
  525. break;
  526. }
  527. /*
  528. * Base_Capacitance = (Measured_Capacitance/Z) +
  529. * Y*(Base_Capacitance/Z)
  530. */
  531. baseCnt[j+groupOfElements->baseOffset] += tempCnt;
  532. if(groupOfElements->halDefinition & RO_MASK)
  533. {
  534. /* If the RO_MASK is set then the direction of interest is
  535. * decreasing (counts decrease with capacitance) and
  536. * therefore movement in the direction of interest would
  537. * be a decrease: decrement.
  538. */
  539. baseCnt[j+groupOfElements->baseOffset]-= remainder;
  540. }
  541. else
  542. {
  543. /* RO_MASK is not set and therefore an increase is in the
  544. * direction of interest: increment
  545. */
  546. baseCnt[j+groupOfElements->baseOffset]+= remainder;
  547. }
  548. }
  549. //if delta counts above the threshold, event has occurred
  550. else if(deltaCnt[j]>=(groupOfElements->arrayPtr[j])->threshold)
  551. {
  552. ctsStatusReg |= EVNT;
  553. ctsStatusReg |= PAST_EVNT;
  554. }
  555. }
  556. }// end of for-loop
  557. if(!(ctsStatusReg & EVNT))
  558. {
  559. ctsStatusReg &= ~PAST_EVNT;
  560. }
  561. }
  562. /***************************************************************************//**
  563. * @brief Determine if a button is being pressed
  564. * @param groupOfElements Pointer to button to be scanned
  565. * @return result Indication if button is (1) or is not (0) being pressed
  566. ******************************************************************************/
  567. uint8_t TI_CAPT_Button(const struct Sensor * groupOfElements)
  568. {
  569. uint8_t result = 0;
  570. #ifndef RAM_FOR_FLASH
  571. uint16_t *measCnt;
  572. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  573. if(measCnt ==0)
  574. {
  575. while(1);
  576. }
  577. #endif
  578. TI_CAPT_Custom(groupOfElements, measCnt);
  579. #ifndef RAM_FOR_FLASH
  580. free(measCnt);
  581. #endif
  582. if(ctsStatusReg & EVNT)
  583. {
  584. result = 1;
  585. }
  586. return result;
  587. }
  588. /***************************************************************************//**
  589. * @brief Determine which button if any is being pressed
  590. * @param groupOfElements Pointer to buttons to be scanned
  591. * @return result pointer to element (button) being pressed or 0 none
  592. ******************************************************************************/
  593. const struct Element *TI_CAPT_Buttons(const struct Sensor *groupOfElements)
  594. {
  595. uint8_t index;
  596. #ifndef RAM_FOR_FLASH
  597. uint16_t *measCnt;
  598. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  599. if(measCnt ==0)
  600. {
  601. while(1);
  602. }
  603. #endif
  604. TI_CAPT_Custom(groupOfElements, measCnt);
  605. if(ctsStatusReg & EVNT)
  606. {
  607. index = Dominant_Element(groupOfElements, measCnt);
  608. //ctsStatusReg &= ~EVNT;
  609. index++;
  610. }
  611. else
  612. {
  613. index = 0;
  614. }
  615. #ifndef RAM_FOR_FLASH
  616. free(measCnt);
  617. #endif
  618. if(index)
  619. {
  620. return groupOfElements->arrayPtr[index-1];
  621. }
  622. return 0;
  623. }
  624. #ifdef SLIDER
  625. /***************************************************************************//**
  626. * @brief Determine the position on a slider
  627. * @param groupOfElements Pointer to slider
  628. * @return result position on slider or illegal value if no touch
  629. ******************************************************************************/
  630. uint16_t TI_CAPT_Slider(const struct Sensor* groupOfElements)
  631. {
  632. uint8_t index;
  633. int16_t position;
  634. // allocate memory for measurement
  635. #ifndef RAM_FOR_FLASH
  636. uint16_t *measCnt;
  637. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  638. if(measCnt ==0)
  639. {
  640. while(1);
  641. }
  642. #endif
  643. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  644. //make measurement
  645. TI_CAPT_Custom(groupOfElements, measCnt);
  646. // Use EVNT flag to determine if slider was touched.
  647. // The EVNT flag is a global variable and managed within the TI_CAPT_Custom
  648. // function.
  649. if(ctsStatusReg & EVNT)
  650. {
  651. index = Dominant_Element(groupOfElements, &measCnt[0]);
  652. // The index represents the element within the array with the highest
  653. // return.
  654. if(index == 0)
  655. {
  656. // Special case of 1st element in slider, add 1st, last, and 2nd
  657. position = measCnt[0] + measCnt[1];
  658. }
  659. else if(index == (groupOfElements->numElements -1))
  660. {
  661. // Special case of Last element in slider, add last,
  662. // 1st, and 2nd to last
  663. position = measCnt[groupOfElements->numElements -1]
  664. + measCnt[groupOfElements->numElements -2];
  665. }
  666. else
  667. {
  668. position = measCnt[index] + measCnt[index+1] + measCnt[index-1];
  669. }
  670. // Determine if sensor threshold criteria is met
  671. if(position >= groupOfElements->sensorThreshold)
  672. {
  673. // calculate position
  674. position = index
  675. *(groupOfElements->points
  676. /groupOfElements->numElements);
  677. position += (groupOfElements->points/groupOfElements->numElements)
  678. /2;
  679. if(index == 0)
  680. {
  681. // Special case of 1st element in slider, which only has one
  682. // neighbor, measCnt[1]. measCnt is limited to maxResponse
  683. // within dominantElement function
  684. if(measCnt[1])
  685. {
  686. position += (measCnt[1]
  687. *(groupOfElements->points
  688. /groupOfElements->numElements))/100;
  689. }
  690. else
  691. {
  692. /* Calculate position based upon measCnt[0] */
  693. position = (measCnt[0]
  694. *(groupOfElements->points
  695. /groupOfElements->numElements)/2)/100;
  696. }
  697. }
  698. else if(index == (groupOfElements->numElements -1))
  699. {
  700. // Special case of Last element in slider, which only has one
  701. // neighbor, measCnt[x-1] or measCnt[numElements-1]
  702. if(measCnt[index-1])
  703. {
  704. position -= (measCnt[index-1]
  705. *(groupOfElements->points
  706. /groupOfElements->numElements))/100;
  707. }
  708. else
  709. {
  710. position = groupOfElements->points;
  711. position -= (measCnt[index]
  712. *(groupOfElements->points
  713. /groupOfElements->numElements)/2)/100;
  714. }
  715. }
  716. else
  717. {
  718. position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100;
  719. position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
  720. }
  721. if((position > groupOfElements->points) || (position < 0))
  722. {
  723. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  724. }
  725. }
  726. else
  727. {
  728. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  729. }
  730. }
  731. #ifndef RAM_FOR_FLASH
  732. free(measCnt);
  733. #endif
  734. return position;
  735. }
  736. #endif
  737. #ifdef WHEEL
  738. /***************************************************************************//**
  739. * @brief Determine the position on a wheel
  740. * @param groupOfElements Pointer to wheel
  741. * @return result position on wheel or illegal value if no touch
  742. ******************************************************************************/
  743. uint16_t TI_CAPT_Wheel(const struct Sensor* groupOfElements)
  744. {
  745. uint8_t index;
  746. int16_t position;
  747. // allocate memory for measurement
  748. #ifndef RAM_FOR_FLASH
  749. uint16_t *measCnt;
  750. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  751. if(measCnt ==0)
  752. {
  753. while(1);
  754. }
  755. #endif
  756. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  757. //make measurement
  758. TI_CAPT_Custom(groupOfElements, measCnt);
  759. // Translate the EVNT flag from an element level EVNT to a sensor level EVNT.
  760. // The sensor must read at least 75% cumulative response before indicating a
  761. // touch.
  762. if(ctsStatusReg & EVNT)
  763. {
  764. index = Dominant_Element(groupOfElements, &measCnt[0]);
  765. // The index represents the element within the array with the highest return.
  766. //
  767. if(index == 0)
  768. {
  769. // Special case of 1st element in slider, add 1st, last, and 2nd
  770. position = measCnt[0] + measCnt[groupOfElements->numElements -1] + measCnt[1];
  771. }
  772. else if(index == (groupOfElements->numElements -1))
  773. {
  774. // Special case of Last element in slider, add last, 1st, and 2nd to last
  775. position = measCnt[index] + measCnt[0] + measCnt[index-1];
  776. }
  777. else
  778. {
  779. position = measCnt[index] + measCnt[index+1] + measCnt[index-1];
  780. }
  781. if(position > groupOfElements->sensorThreshold)
  782. {
  783. //index = Dominant_Element(groupOfElements, &measCnt[0]);
  784. // The index represents the element within the array with the highest return.
  785. //
  786. position = index*(groupOfElements->points/groupOfElements->numElements);
  787. position += (groupOfElements->points/groupOfElements->numElements)/2;
  788. if(index == 0)
  789. {
  790. // Special case of 1st element in slider, which only has one neighbor, measCnt[1]
  791. // measCnt is limited to maxResponse within dominantElement function
  792. position += (measCnt[1]*(groupOfElements->points/groupOfElements->numElements))/100;
  793. position -= (measCnt[groupOfElements->numElements -1]*(groupOfElements->points/groupOfElements->numElements))/100;
  794. if(position < 0)
  795. {
  796. position = position + (int16_t)groupOfElements->points;
  797. position++; // -1 goes to points
  798. }
  799. }
  800. else if(index == (groupOfElements->numElements -1))
  801. {
  802. // Special case of Last element in slider, which only has one neighbor, measCnt[x-1] or measCnt[numElements-1]
  803. // measCnt is limited to maxResponse within dominantElement function
  804. position += (measCnt[0]*(groupOfElements->points/groupOfElements->numElements))/100;
  805. position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
  806. if(position > groupOfElements->points)
  807. {
  808. position = position - (int16_t)groupOfElements->points;
  809. position--; // points+1 goes to 0
  810. }
  811. }
  812. else
  813. {
  814. position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100;
  815. position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
  816. }
  817. if((position > groupOfElements->points) || position < 0)
  818. {
  819. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  820. }
  821. }
  822. else
  823. {
  824. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  825. }
  826. }
  827. #ifndef RAM_FOR_FLASH
  828. free(measCnt);
  829. #endif
  830. return position;
  831. }
  832. #endif
  833. /** @} */
  834. /***************************************************************************//**
  835. * @defgroup CTS_support Support Group
  836. * @ingroup CTS_API
  837. ******************************************************************************/
  838. /***************************************************************************//**
  839. * @ingroup CTS_support
  840. * @brief Determine which element within a sensor has the largest response
  841. *
  842. * This function compares and normalizes the change in capacitance to
  843. * determine which element has the dominant response. The deltaCnt
  844. * values for each element that exceed the threshold are also
  845. * converted from a 'raw' measurement to a percentage of the maximum
  846. * response.
  847. * @param groupOfElements Pointer to buttons to be scanned
  848. * @param deltaCnt Address to where the measurements are to be written
  849. * @return result index to the element which is dominant
  850. ******************************************************************************/
  851. uint8_t Dominant_Element(const struct Sensor* groupOfElements, uint16_t* deltaCnt)
  852. {
  853. uint8_t i;
  854. uint16_t percentDelta=0;
  855. uint8_t dominantElement=0;
  856. for(i=0;i<groupOfElements->numElements;i++)
  857. {
  858. if(deltaCnt[i]>=(groupOfElements->arrayPtr[i])->threshold)
  859. {
  860. if(deltaCnt[i] > ((groupOfElements->arrayPtr[i])->maxResponse))
  861. {
  862. deltaCnt[i] = (groupOfElements->arrayPtr[i])->maxResponse;
  863. // limit response to the maximum
  864. }
  865. // (maxResponse - threshold) cannot exceed 655
  866. // 100*(delta - threshold) / (maxResponse - threshold)
  867. deltaCnt[i] = (100*(deltaCnt[i]
  868. -(groupOfElements->arrayPtr[i])->threshold))
  869. /((groupOfElements->arrayPtr[i])->maxResponse
  870. -(groupOfElements->arrayPtr[i])->threshold);
  871. if(deltaCnt[i] >= percentDelta)
  872. {
  873. //update percentDelta
  874. percentDelta = deltaCnt[i];
  875. dominantElement = i;
  876. }
  877. }
  878. else
  879. {
  880. deltaCnt[i] = 0;
  881. }
  882. } // end for loop
  883. return dominantElement;
  884. }
  885. #endif