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.

747 lines
29 KiB

5 years ago
  1. /*******************************************************************************
  2. * CTS_HAL.c - defines functions called by application as well as
  3. * functions for information processing
  4. *
  5. * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * Neither the name of Texas Instruments Incorporated nor the names of
  20. * its contributors may be used to endorse or promote products derived
  21. * from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  26. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  27. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  28. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  29. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  30. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  32. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  33. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. ******************************************************************************/
  36. /***************************************************************************//**
  37. * @file CTS_HAL.c
  38. *
  39. * @brief
  40. *
  41. * @par Project:
  42. * MSP430 Capacitive Touch Library
  43. *
  44. * @par Developed using:
  45. * IAR Version : 5.10.6 [Kickstart] (5.10.6.30180)
  46. * CCS Version : 4.2.1.00004, w/support for GCC extensions (--gcc)
  47. *
  48. * @version 1.0.0 Initial Release
  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_Update_Baseline()
  57. * - TI_CAPT_Raw()
  58. * - TI_CAPT_Custom()
  59. * - TI_CAPT_Button()
  60. * - TI_CAPT_Buttons()
  61. * - TI_CAPT_Slider()
  62. * - TI_CAPT_Wheel()
  63. ******************************************************************************/
  64. #include "CTS_Layer.h"
  65. #include <stdlib.h>
  66. // Global variables for sensing
  67. #ifdef TOTAL_NUMBER_OF_ELEMENTS
  68. uint16_t baseCnt[TOTAL_NUMBER_OF_ELEMENTS];
  69. #ifdef RAM_FOR_FLASH
  70. uint16_t measCnt[MAXIMUM_NUMBER_OF_ELEMENTS_PER_SENSOR];
  71. #endif
  72. uint16_t ctsStatusReg = (DOI_INC+TRADOI_FAST+TRIDOI_SLOW);
  73. #endif
  74. /***************************************************************************//**
  75. * @addtogroup CTS_API
  76. * @{
  77. ******************************************************************************/
  78. /***************************************************************************//**
  79. * @brief Measure the capacitance of each element within the Sensor
  80. *
  81. * This function selects the appropriate HAL to perform the capacitance
  82. * measurement based upon the halDefinition found in the sensor
  83. * structure.
  84. * The order of the elements within the Sensor structure is arbitrary
  85. * but must be consistent between the application and configuration.
  86. * The first element in the array (counts) corresponds to the first
  87. * element within the Sensor structure.
  88. * @param groupOfElements Pointer to Sensor structure to be measured
  89. * @param counts Address to where the measurements are to be written
  90. * @return none
  91. ******************************************************************************/
  92. void TI_CAPT_Raw(const struct Sensor* groupOfElements, uint16_t * counts)
  93. {
  94. #ifdef RO_COMPAp_TA0_WDTp
  95. if(groupOfElements->halDefinition == RO_COMPAp_TA0_WDTp)
  96. {
  97. TI_CTS_RO_COMPAp_TA0_WDTp_HAL(groupOfElements, counts);
  98. }
  99. #endif
  100. #ifdef fRO_COMPAp_TA0_SW
  101. if(groupOfElements->halDefinition == fRO_COMPAp_TA0_SW)
  102. {
  103. TI_CTS_fRO_COMPAp_TA0_SW_HAL(groupOfElements, counts);
  104. }
  105. #endif
  106. #ifdef fRO_COMPAp_SW_TA0
  107. if(groupOfElements->halDefinition == fRO_COMPAp_SW_TA0)
  108. {
  109. TI_CTS_fRO_COMPAp_SW_TA0_HAL(groupOfElements, counts);
  110. }
  111. #endif
  112. #ifdef RO_COMPAp_TA1_WDTp
  113. if(groupOfElements->halDefinition == RO_COMPAp_TA1_WDTp)
  114. {
  115. TI_CTS_RO_COMPAp_TA1_WDTp_HAL(groupOfElements, counts);
  116. }
  117. #endif
  118. #ifdef fRO_COMPAp_TA1_SW
  119. if(groupOfElements->halDefinition == fRO_COMPAp_TA1_SW)
  120. {
  121. TI_CTS_fRO_COMPAp_TA1_SW_HAL(groupOfElements, counts);
  122. }
  123. #endif
  124. #ifdef RC_PAIR_TA0
  125. if(groupOfElements->halDefinition == RC_PAIR_TA0)
  126. {
  127. TI_CTS_RC_PAIR_TA0_HAL(groupOfElements, counts); // Measure all sensors
  128. }
  129. #endif
  130. #ifdef RO_PINOSC_TA0_WDTp
  131. if(groupOfElements->halDefinition == RO_PINOSC_TA0_WDTp)
  132. {
  133. TI_CTS_RO_PINOSC_TA0_WDTp_HAL(groupOfElements, counts);
  134. }
  135. #endif
  136. #ifdef RO_PINOSC_TA0
  137. if(groupOfElements->halDefinition == RO_PINOSC_TA0)
  138. {
  139. TI_CTS_RO_PINOSC_TA0_HAL(groupOfElements, counts);
  140. }
  141. #endif
  142. #ifdef fRO_PINOSC_TA0_SW
  143. if(groupOfElements->halDefinition == fRO_PINOSC_TA0_SW)
  144. {
  145. TI_CTS_fRO_PINOSC_TA0_SW_HAL(groupOfElements, counts); // Measure all sensors
  146. }
  147. #endif
  148. #ifdef RO_COMPB_TA0_WDTA
  149. if(groupOfElements->halDefinition == RO_COMPB_TA0_WDTA)
  150. {
  151. TI_CTS_RO_COMPB_TA0_WDTA_HAL(groupOfElements, counts);
  152. }
  153. #endif
  154. #ifdef fRO_COMPB_TA0_SW
  155. if(groupOfElements->halDefinition == fRO_COMPB_TA0_SW)
  156. {
  157. TI_CTS_fRO_COMPB_TA0_SW_HAL(groupOfElements, counts);
  158. }
  159. #endif
  160. #ifdef RO_COMPB_TA1_WDTA
  161. if(groupOfElements->halDefinition == RO_COMPB_TA1_WDTA)
  162. {
  163. TI_CTS_RO_COMPB_TA1_WDTA_HAL(groupOfElements, counts);
  164. }
  165. #endif
  166. #ifdef fRO_COMPB_TA1_SW
  167. if(groupOfElements->halDefinition == fRO_COMPB_TA1_SW)
  168. {
  169. TI_CTS_fRO_COMPB_TA1_SW_HAL(groupOfElements, counts);
  170. }
  171. #endif
  172. }
  173. #ifdef TOTAL_NUMBER_OF_ELEMENTS
  174. /***************************************************************************//**
  175. * @brief Make a single capacitance meausrment to initialize baseline tracking
  176. * @param groupOfElements Pointer to Sensor structure to be measured
  177. * @return none
  178. ******************************************************************************/
  179. void TI_CAPT_Init_Baseline(const struct Sensor* groupOfElements)
  180. {
  181. TI_CAPT_Raw(groupOfElements, &baseCnt[groupOfElements->baseOffset]);
  182. }
  183. /***************************************************************************//**
  184. * @brief Update baseline tracking by averaging several measurements
  185. * @param groupOfElements Pointer to Sensor structure to be measured
  186. * @param numberofAverages Number of measurements to be averaged
  187. * @return none
  188. ******************************************************************************/
  189. void TI_CAPT_Update_Baseline(const struct Sensor* groupOfElements, uint8_t numberOfAverages)
  190. {
  191. uint8_t i,j;
  192. #ifndef RAM_FOR_FLASH
  193. uint16_t *measCnt;
  194. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  195. if(measCnt ==0)
  196. {
  197. while(1);
  198. }
  199. #endif
  200. for(j=0; j < numberOfAverages; j++)
  201. {
  202. for(i=0; i < groupOfElements->numElements; i++)
  203. {
  204. TI_CAPT_Raw(groupOfElements, measCnt);
  205. baseCnt[i+groupOfElements->baseOffset] = measCnt[i]/2 + baseCnt[i+groupOfElements->baseOffset]/2;
  206. }
  207. }
  208. #ifndef RAM_FOR_FLASH
  209. free(measCnt);
  210. #endif
  211. }
  212. /***************************************************************************//**
  213. * @brief Reset the Baseline Tracking algorithm to the default state
  214. * @param none
  215. * @return none
  216. ******************************************************************************/
  217. void TI_CAPT_Reset_Tracking(void)
  218. {
  219. ctsStatusReg = (DOI_INC+TRADOI_FAST+TRIDOI_SLOW);
  220. }
  221. /***************************************************************************//**
  222. * @brief Update the Baseline Tracking algorithm Direction of Interest
  223. * @param direction Direction of increasing or decreasing capacitance
  224. * @return none
  225. ******************************************************************************/
  226. void TI_CAPT_Update_Tracking_DOI(uint8_t direction)
  227. {
  228. if(direction)
  229. {
  230. ctsStatusReg |= DOI_INC;
  231. }
  232. else
  233. {
  234. ctsStatusReg &= ~DOI_INC;
  235. }
  236. }
  237. /***************************************************************************//**
  238. * @brief Update the baseling tracking algorithm tracking rates
  239. * @param rate Rate of tracking changes in and against direction of intrest
  240. * @return none
  241. ******************************************************************************/
  242. void TI_CAPT_Update_Tracking_Rate(uint8_t rate)
  243. {
  244. ctsStatusReg &= ~(TRIDOI_FAST+TRADOI_VSLOW); // clear fields
  245. ctsStatusReg |= (rate & 0xF0); // update fields
  246. }
  247. /***************************************************************************//**
  248. * @brief Measure the change in capacitance of the Sensor
  249. *
  250. * This function measures the change in capacitance of each element
  251. * within a sensor and updates the baseline tracking in the event that
  252. * no change exceeds the detection threshold.
  253. * The order of the elements within the Sensor structure is arbitrary
  254. * but must be consistent between the application and configuration.
  255. * The first element in the array (deltaCnt) corresponds to the first
  256. * element within the Sensor structure.
  257. * @param groupOfElements Pointer to Sensor structure to be measured
  258. * @param deltaCnt Address to where the measurements are to be written
  259. * @return none
  260. ******************************************************************************/
  261. void TI_CAPT_Custom(const struct Sensor* groupOfElements, uint16_t * deltaCnt)
  262. {
  263. uint8_t j;
  264. uint16_t tempCnt;
  265. ctsStatusReg &= ~ EVNT;
  266. // This section calculates the delta counts*************************************
  267. //******************************************************************************
  268. TI_CAPT_Raw(groupOfElements, &deltaCnt[0]); // measure group of sensors
  269. for (j = 0; j < (groupOfElements->numElements); j++)
  270. {
  271. tempCnt = deltaCnt[j];
  272. if(((ctsStatusReg & DOI_MASK) && (groupOfElements->halDefinition & RO_MASK))
  273. ||
  274. ((!(ctsStatusReg & DOI_MASK)) && (!(groupOfElements->halDefinition & RO_MASK))))
  275. {
  276. // RO method, interested in an increase in capacitance
  277. if(baseCnt[j+groupOfElements->baseOffset] < deltaCnt[j])
  278. {
  279. // If capacitance decreases, then measCnt is greater than base
  280. // , set delta to zero
  281. deltaCnt[j] = 0;
  282. // Limit the change in the opposite direction to the threshold
  283. if(((groupOfElements->arrayPtr[j])->threshold)
  284. &&
  285. (baseCnt[j+groupOfElements->baseOffset]+(groupOfElements->arrayPtr[j])->threshold < tempCnt))
  286. {
  287. tempCnt = baseCnt[j+groupOfElements->baseOffset]+(groupOfElements->arrayPtr[j])->threshold;
  288. }
  289. }
  290. else
  291. {
  292. // change occuring in our DOI, save result
  293. deltaCnt[j] = baseCnt[j+groupOfElements->baseOffset]-deltaCnt[j];
  294. }
  295. }
  296. if(((!(ctsStatusReg & DOI_MASK)) && (groupOfElements->halDefinition & RO_MASK))
  297. ||
  298. ((ctsStatusReg & DOI_MASK) && (!(groupOfElements->halDefinition & RO_MASK))))
  299. {
  300. // RO method: interested in a decrease in capactiance
  301. // measCnt is greater than baseCnt
  302. if(baseCnt[j+groupOfElements->baseOffset] > deltaCnt[j])
  303. {
  304. // If capacitance increases, set delta to zero
  305. deltaCnt[j] = 0;
  306. // Limit the change in the opposite direction to the threshold
  307. if(((groupOfElements->arrayPtr[j])->threshold)
  308. &&
  309. (baseCnt[j+groupOfElements->baseOffset] > tempCnt+(groupOfElements->arrayPtr[j])->threshold))
  310. {
  311. tempCnt = baseCnt[j+groupOfElements->baseOffset]-(groupOfElements->arrayPtr[j])->threshold;
  312. }
  313. }
  314. else
  315. {
  316. // change occuring in our DOI
  317. deltaCnt[j] = deltaCnt[j] - baseCnt[j+groupOfElements->baseOffset];
  318. }
  319. }
  320. // This section updates the baseline capacitance****************************
  321. //**************************************************************************
  322. if (deltaCnt[j]==0)
  323. { // if delta counts is 0, then the change in capacitance was opposite the
  324. // direction of interest. The baseCnt[i] is updated with the saved
  325. // measCnt value for the current index value 'i'.
  326. switch ((ctsStatusReg & TRADOI_VSLOW))
  327. {
  328. case TRADOI_FAST://Fast
  329. tempCnt = tempCnt/2;
  330. baseCnt[j+groupOfElements->baseOffset] = (baseCnt[j+groupOfElements->baseOffset]/2);
  331. break;
  332. case TRADOI_MED://Medium
  333. tempCnt = tempCnt/4;
  334. baseCnt[j+groupOfElements->baseOffset] = 3*(baseCnt[j+groupOfElements->baseOffset]/4);
  335. break;
  336. case TRADOI_SLOW://slow
  337. tempCnt = tempCnt/64;
  338. baseCnt[j+groupOfElements->baseOffset] = 63*(baseCnt[j+groupOfElements->baseOffset]/64);
  339. break;
  340. case TRADOI_VSLOW://very slow
  341. tempCnt = tempCnt/128;
  342. baseCnt[j+groupOfElements->baseOffset] = 127*(baseCnt[j+groupOfElements->baseOffset]/128);
  343. break;
  344. }
  345. // set X, Y & Z, then perform calculation for baseline tracking:
  346. // Base_Capacitance = X*(Measured_Capacitance/Z) + Y*(Base_Capacitance/Z)
  347. baseCnt[j+groupOfElements->baseOffset] = (tempCnt)+(baseCnt[j+groupOfElements->baseOffset]);
  348. }
  349. // delta counts are either 0, less than threshold, or greater than threshold
  350. // never negative
  351. else if(deltaCnt[j]<(groupOfElements->arrayPtr[j])->threshold && !(ctsStatusReg & PAST_EVNT))
  352. { //if delta counts is positive but less than threshold,
  353. switch ((ctsStatusReg & TRIDOI_FAST))
  354. {
  355. case TRIDOI_VSLOW://very slow
  356. if(deltaCnt[j] > 15)
  357. {
  358. if(tempCnt < baseCnt[j+groupOfElements->baseOffset])
  359. {
  360. baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] - 1;
  361. }
  362. else
  363. {
  364. baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] + 1;
  365. }
  366. }
  367. tempCnt = 0;
  368. break;
  369. case TRIDOI_SLOW://slow
  370. if(tempCnt < baseCnt[j+groupOfElements->baseOffset])
  371. {
  372. baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] - 1;
  373. }
  374. else
  375. {
  376. baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] + 1;
  377. }
  378. tempCnt = 0;
  379. break;
  380. case TRIDOI_MED://medium
  381. tempCnt = tempCnt/4;
  382. baseCnt[j+groupOfElements->baseOffset] = 3*(baseCnt[j+groupOfElements->baseOffset]/4);
  383. break;
  384. case TRIDOI_FAST://fast
  385. tempCnt = tempCnt/2;
  386. baseCnt[j+groupOfElements->baseOffset] = (baseCnt[j+groupOfElements->baseOffset]/2);
  387. break;
  388. }
  389. // set X, Y & Z, then perform calculation for baseline tracking:
  390. // Base_Capacitance = X*(Measured_Capacitance/Z) + Y*(Base_Capacitance/Z)
  391. baseCnt[j+groupOfElements->baseOffset] = (tempCnt)+(baseCnt[j+groupOfElements->baseOffset]);
  392. }
  393. //if delta counts above the threshold, event has occurred
  394. else if(deltaCnt[j]>=(groupOfElements->arrayPtr[j])->threshold)
  395. {
  396. ctsStatusReg |= EVNT;
  397. ctsStatusReg |= PAST_EVNT;
  398. }
  399. }// end of for-loop
  400. if(!(ctsStatusReg & EVNT))
  401. {
  402. ctsStatusReg &= ~PAST_EVNT;
  403. }
  404. }
  405. /***************************************************************************//**
  406. * @brief Determine if a button is being pressed
  407. * @param groupOfElements Pointer to button to be scanned
  408. * @return result Indication if button is (1) or is not (0) being pressed
  409. ******************************************************************************/
  410. uint8_t TI_CAPT_Button(const struct Sensor * groupOfElements)
  411. {
  412. uint8_t result = 0;
  413. #ifndef RAM_FOR_FLASH
  414. uint16_t *measCnt;
  415. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  416. if(measCnt ==0)
  417. {
  418. while(1);
  419. }
  420. #endif
  421. TI_CAPT_Custom(groupOfElements, measCnt);
  422. #ifndef RAM_FOR_FLASH
  423. free(measCnt);
  424. #endif
  425. if(ctsStatusReg & EVNT)
  426. {
  427. result = 1;
  428. }
  429. return result;
  430. }
  431. /***************************************************************************//**
  432. * @brief Determine which button if any is being pressed
  433. * @param groupOfElements Pointer to buttons to be scanned
  434. * @return result pointer to element (button) being pressed or 0 none
  435. ******************************************************************************/
  436. const struct Element *TI_CAPT_Buttons(const struct Sensor *groupOfElements)
  437. {
  438. uint8_t index;
  439. #ifndef RAM_FOR_FLASH
  440. uint16_t *measCnt;
  441. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  442. if(measCnt ==0)
  443. {
  444. while(1);
  445. }
  446. #endif
  447. TI_CAPT_Custom(groupOfElements, measCnt);
  448. if(ctsStatusReg & EVNT)
  449. {
  450. index = Dominant_Element(groupOfElements, measCnt);
  451. //ctsStatusReg &= ~EVNT;
  452. index++;
  453. }
  454. else
  455. {
  456. index = 0;
  457. }
  458. #ifndef RAM_FOR_FLASH
  459. free(measCnt);
  460. #endif
  461. if(index)
  462. {
  463. return groupOfElements->arrayPtr[index-1];
  464. }
  465. return 0;
  466. }
  467. #ifdef SLIDER
  468. /***************************************************************************//**
  469. * @brief Determine the position on a slider
  470. * @param groupOfElements Pointer to slider
  471. * @return result position on slider or illegal value if no touch
  472. ******************************************************************************/
  473. uint16_t TI_CAPT_Slider(const struct Sensor* groupOfElements)
  474. {
  475. uint8_t index;
  476. int16_t position;
  477. // allocate memory for measurement
  478. #ifndef RAM_FOR_FLASH
  479. uint16_t *measCnt;
  480. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  481. if(measCnt ==0)
  482. {
  483. while(1);
  484. }
  485. #endif
  486. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  487. //make measurement
  488. TI_CAPT_Custom(groupOfElements, measCnt);
  489. // Use EVNT flag to determine if slider was touched.
  490. // The EVNT flag is a global variable and managed within the TI_CAPT_Custom function.
  491. if(ctsStatusReg & EVNT)
  492. {
  493. index = Dominant_Element(groupOfElements, &measCnt[0]);
  494. // The index represents the element within the array with the highest return.
  495. if(index == 0)
  496. {
  497. // Special case of 1st element in slider, add 1st, last, and 2nd
  498. position = measCnt[0] + measCnt[1];
  499. }
  500. else if(index == (groupOfElements->numElements -1))
  501. {
  502. // Special case of Last element in slider, add last, 1st, and 2nd to last
  503. position = measCnt[groupOfElements->numElements -1] + measCnt[groupOfElements->numElements -2];
  504. }
  505. else
  506. {
  507. position = measCnt[index] + measCnt[index+1] + measCnt[index-1];
  508. }
  509. // Determine if sensor threshold criteria is met
  510. if(position > groupOfElements->sensorThreshold)
  511. {
  512. // calculate position
  513. position = index*(groupOfElements->points/groupOfElements->numElements);
  514. position += (groupOfElements->points/groupOfElements->numElements)/2;
  515. if(index == 0)
  516. {
  517. // Special case of 1st element in slider, which only has one
  518. // neighbor, measCnt[1]. measCnt is limited to maxResponse
  519. // within dominantElement function
  520. if(measCnt[1])
  521. {
  522. position += (measCnt[1]*(groupOfElements->points/groupOfElements->numElements))/100;
  523. }
  524. else
  525. {
  526. position = (measCnt[0]*(groupOfElements->points/groupOfElements->numElements)/2)/100;
  527. }
  528. }
  529. else if(index == (groupOfElements->numElements -1))
  530. {
  531. // Special case of Last element in slider, which only has one
  532. // neighbor, measCnt[x-1] or measCnt[numElements-1]
  533. if(measCnt[index-1])
  534. {
  535. position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
  536. }
  537. else
  538. {
  539. position = groupOfElements->points;
  540. position -= (measCnt[index]*(groupOfElements->points/groupOfElements->numElements)/2)/100;
  541. }
  542. }
  543. else
  544. {
  545. position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100;
  546. position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
  547. }
  548. if((position > groupOfElements->points) || (position < 0))
  549. {
  550. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  551. }
  552. }
  553. else
  554. {
  555. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  556. }
  557. }
  558. #ifndef RAM_FOR_FLASH
  559. free(measCnt);
  560. #endif
  561. return position;
  562. }
  563. #endif
  564. #ifdef WHEEL
  565. /***************************************************************************//**
  566. * @brief Determine the position on a wheel
  567. * @param groupOfElements Pointer to wheel
  568. * @return result position on wheel or illegal value if no touch
  569. ******************************************************************************/
  570. uint16_t TI_CAPT_Wheel(const struct Sensor* groupOfElements)
  571. {
  572. uint8_t index;
  573. int16_t position;
  574. // allocate memory for measurement
  575. #ifndef RAM_FOR_FLASH
  576. uint16_t *measCnt;
  577. measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
  578. if(measCnt ==0)
  579. {
  580. while(1);
  581. }
  582. #endif
  583. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  584. //make measurement
  585. TI_CAPT_Custom(groupOfElements, measCnt);
  586. // Translate the EVNT flag from an element level EVNT to a sensor level EVNT.
  587. // The sensor must read at least 75% cumulative response before indicating a
  588. // touch.
  589. if(ctsStatusReg & EVNT)
  590. {
  591. index = Dominant_Element(groupOfElements, &measCnt[0]);
  592. // The index represents the element within the array with the highest return.
  593. //
  594. if(index == 0)
  595. {
  596. // Special case of 1st element in slider, add 1st, last, and 2nd
  597. position = measCnt[0] + measCnt[groupOfElements->numElements -1] + measCnt[1];
  598. }
  599. else if(index == (groupOfElements->numElements -1))
  600. {
  601. // Special case of Last element in slider, add last, 1st, and 2nd to last
  602. position = measCnt[index] + measCnt[0] + measCnt[index-1];
  603. }
  604. else
  605. {
  606. position = measCnt[index] + measCnt[index+1] + measCnt[index-1];
  607. }
  608. if(position > groupOfElements->sensorThreshold)
  609. {
  610. //index = Dominant_Element(groupOfElements, &measCnt[0]);
  611. // The index represents the element within the array with the highest return.
  612. //
  613. position = index*(groupOfElements->points/groupOfElements->numElements);
  614. position += (groupOfElements->points/groupOfElements->numElements)/2;
  615. if(index == 0)
  616. {
  617. // Special case of 1st element in slider, which only has one neighbor, measCnt[1]
  618. // measCnt is limited to maxResponse within dominantElement function
  619. position += (measCnt[1]*(groupOfElements->points/groupOfElements->numElements))/100;
  620. position -= (measCnt[groupOfElements->numElements -1]*(groupOfElements->points/groupOfElements->numElements))/100;
  621. if(position < 0)
  622. {
  623. position = position + (int16_t)groupOfElements->points;
  624. }
  625. }
  626. else if(index == (groupOfElements->numElements -1))
  627. {
  628. // Special case of Last element in slider, which only has one neighbor, measCnt[x-1] or measCnt[numElements-1]
  629. // measCnt is limited to maxResponse within dominantElement function
  630. position += (measCnt[0]*(groupOfElements->points/groupOfElements->numElements))/100;
  631. position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
  632. if(position > (groupOfElements->points -1))
  633. {
  634. position = position - (int16_t)groupOfElements->points;
  635. }
  636. }
  637. else
  638. {
  639. position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100;
  640. position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
  641. }
  642. if((position > groupOfElements->points) || position < 0)
  643. {
  644. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  645. }
  646. }
  647. else
  648. {
  649. position = ILLEGAL_SLIDER_WHEEL_POSITION;
  650. }
  651. }
  652. #ifndef RAM_FOR_FLASH
  653. free(measCnt);
  654. #endif
  655. return position;
  656. }
  657. #endif
  658. /***************************************************************************//**
  659. * @}
  660. ******************************************************************************/
  661. /***************************************************************************//**
  662. * @defgroup CTS_support
  663. * @ingroup CTS_API
  664. ******************************************************************************/
  665. /***************************************************************************//**
  666. * @ingroup CTS_support
  667. * @brief Determine which element within a sensor has the largest response
  668. *
  669. * This function compares and normalizes the change in capacitance to
  670. * determine which element has the dominant response. The deltaCnt
  671. * values for each element that exceed the threshold are also
  672. * converted from a 'raw' measurement to a percentage of the maximum
  673. * response.
  674. * @param groupOfElements Pointer to buttons to be scanned
  675. * @param deltaCnt Address to where the measurements are to be written
  676. * @return result index to the element which is dominant
  677. ******************************************************************************/
  678. uint8_t Dominant_Element(const struct Sensor* groupOfElements, uint16_t* deltaCnt)
  679. {
  680. uint8_t i;
  681. uint16_t percentDelta=0;
  682. uint8_t dominantElement=0;
  683. for(i=0;i<groupOfElements->numElements;i++)
  684. {
  685. if(deltaCnt[i]>=(groupOfElements->arrayPtr[i])->threshold)
  686. {
  687. if(deltaCnt[i] > ((groupOfElements->arrayPtr[i])->maxResponse))
  688. {
  689. deltaCnt[i] = (groupOfElements->arrayPtr[i])->maxResponse;
  690. // limit response to the maximum
  691. }
  692. // (maxResponse - threshold) cannot exceed 655
  693. // 100*(delta - threshold) / (maxResponse - threshold)
  694. deltaCnt[i] = (100*(deltaCnt[i]-(groupOfElements->arrayPtr[i])->threshold))/((groupOfElements->arrayPtr[i])->maxResponse - (groupOfElements->arrayPtr[i])->threshold);
  695. if(deltaCnt[i] > percentDelta)
  696. {
  697. //update percentDelta
  698. percentDelta = deltaCnt[i];
  699. dominantElement = i;
  700. }
  701. }
  702. else
  703. {
  704. deltaCnt[i] = 0;
  705. }
  706. } // end for loop
  707. return dominantElement;
  708. }
  709. #endif