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

/* --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--*/
/*!
* @file CTS_Layer.c
*
* @brief This source file contains the API calls and one support function.
*
* @par Project:
* MSP430 Capacitive Touch Library
*
* @par Developed using:
* CCS Version : 5.4.0.00048, w/support for GCC extensions (--gcc)
* \n IAR Version : 5.51.6 [Kickstart]
*
* @author C. Sterzik
* @author T. Hwang
*
* @version 1.2
* Updated HALs for new devices.
*
* @par Supported API Calls:
* - TI_CAPT_Init_Baseline()
* - TI_CAPT_Update_Baseline()
* - TI_CAPT_Reset_Tracking()
* - TI_CAPT_Update_Tracking_DOI()
* - TI_CAPT_Update_Tracking_Rate()
* - TI_CAPT_Raw()
* - TI_CAPT_Custom()
* - TI_CAPT_Button()
* - TI_CAPT_Buttons()
* - TI_CAPT_Slider()
* - TI_CAPT_Wheel()
*/
#include "CTS_Layer.h"
/*! @defgroup GLOBAL_VARS Global Variables
* @{
*/
#ifdef TOTAL_NUMBER_OF_ELEMENTS
/*!
* The baseline tracking variables
*/
uint16_t baseCnt[TOTAL_NUMBER_OF_ELEMENTS];
#ifdef RAM_FOR_FLASH
/*!
* The current measurement variables
*/
uint16_t measCnt[MAXIMUM_NUMBER_OF_ELEMENTS_PER_SENSOR];
#endif
/*!
* The Status Register
*/
uint16_t ctsStatusReg = (DOI_INC+TRADOI_FAST+TRIDOI_SLOW);
#endif
/*!
* @}
*/
/** @defgroup CTS_API API Group
* @{
*/
/***************************************************************************//**
* @brief Measure the capacitance of each element within the Sensor
*
* This function selects the appropriate HAL to perform the capacitance
* measurement based upon the halDefinition found in the sensor
* structure.
* The order of the elements within the Sensor structure is arbitrary
* but must be consistent between the application and configuration.
* The first element in the array (counts) corresponds to the first
* element within the Sensor structure.
* @param groupOfElements Pointer to Sensor structure to be measured
* @param counts Address to where the measurements are to be written
* @return none
******************************************************************************/
void TI_CAPT_Raw(const struct Sensor* groupOfElements, uint16_t * counts)
{
#ifdef RO_CSIO_TA2_WDTA
if(groupOfElements->halDefinition == RO_CSIO_TA2_WDTA)
{
TI_CTS_RO_CSIO_TA2_WDTA_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_CSIO_TA2_TA3
if(groupOfElements->halDefinition == RO_CSIO_TA2_TA3)
{
TI_CTS_RO_CSIO_TA2_TA3_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_CSIO_TA2_TA3
if(groupOfElements->halDefinition == fRO_CSIO_TA2_TA3)
{
TI_CTS_fRO_CSIO_TA2_TA3_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_COMPB_TB0_WDTA
if(groupOfElements->halDefinition == RO_COMPB_TB0_WDTA)
{
TI_CTS_RO_COMPB_TB0_WDTA_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_PINOSC_TA0_TA1
if(groupOfElements->halDefinition == RO_PINOSC_TA0_TA1)
{
TI_CTS_RO_PINOSC_TA0_TA1_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_PINOSC_TA0_TA1
if(groupOfElements->halDefinition == fRO_PINOSC_TA0_TA1)
{
TI_CTS_fRO_PINOSC_TA0_TA1_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_COMPAp_TA0_WDTp
if(groupOfElements->halDefinition == RO_COMPAp_TA0_WDTp)
{
TI_CTS_RO_COMPAp_TA0_WDTp_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_COMPAp_TA0_SW
if(groupOfElements->halDefinition == fRO_COMPAp_TA0_SW)
{
TI_CTS_fRO_COMPAp_TA0_SW_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_COMPAp_SW_TA0
if(groupOfElements->halDefinition == fRO_COMPAp_SW_TA0)
{
TI_CTS_fRO_COMPAp_SW_TA0_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_COMPAp_TA1_WDTp
if(groupOfElements->halDefinition == RO_COMPAp_TA1_WDTp)
{
TI_CTS_RO_COMPAp_TA1_WDTp_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_COMPAp_TA1_SW
if(groupOfElements->halDefinition == fRO_COMPAp_TA1_SW)
{
TI_CTS_fRO_COMPAp_TA1_SW_HAL(groupOfElements, counts);
}
#endif
#ifdef RC_PAIR_TA0
if(groupOfElements->halDefinition == RC_PAIR_TA0)
{
TI_CTS_RC_PAIR_TA0_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_PINOSC_TA0_WDTp
if(groupOfElements->halDefinition == RO_PINOSC_TA0_WDTp)
{
TI_CTS_RO_PINOSC_TA0_WDTp_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_PINOSC_TA0
if(groupOfElements->halDefinition == RO_PINOSC_TA0)
{
TI_CTS_RO_PINOSC_TA0_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_PINOSC_TA0_SW
if(groupOfElements->halDefinition == fRO_PINOSC_TA0_SW)
{
TI_CTS_fRO_PINOSC_TA0_SW_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_COMPB_TA0_WDTA
if(groupOfElements->halDefinition == RO_COMPB_TA0_WDTA)
{
TI_CTS_RO_COMPB_TA0_WDTA_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_COMPB_TA0_SW
if(groupOfElements->halDefinition == fRO_COMPB_TA0_SW)
{
TI_CTS_fRO_COMPB_TA0_SW_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_COMPB_TA1_WDTA
if(groupOfElements->halDefinition == RO_COMPB_TA1_WDTA)
{
TI_CTS_RO_COMPB_TA1_WDTA_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_COMPB_TA1_SW
if(groupOfElements->halDefinition == fRO_COMPB_TA1_SW)
{
TI_CTS_fRO_COMPB_TA1_SW_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_COMPB_TA1_TA0
if(groupOfElements->halDefinition == RO_COMPB_TA1_TA0)
{
TI_CTS_RO_COMPB_TA1_TA0_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_COMPB_TA1_TA0
if(groupOfElements->halDefinition == fRO_COMPB_TA1_TA0)
{
TI_CTS_fRO_COMPB_TA1_TA0_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_PINOSC_TA1_WDTp
if(groupOfElements->halDefinition == RO_PINOSC_TA1_WDTp)
{
TI_CTS_RO_PINOSC_TA1_WDTp_HAL(groupOfElements, counts);
}
#endif
#ifdef RO_PINOSC_TA1_TB0
if(groupOfElements->halDefinition == RO_PINOSC_TA1_TB0)
{
TI_CTS_RO_PINOSC_TA1_TB0_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_PINOSC_TA1_TA0
if(groupOfElements->halDefinition == fRO_PINOSC_TA1_TA0)
{
TI_CTS_fRO_PINOSC_TA1_TA0_HAL(groupOfElements, counts);
}
#endif
#ifdef fRO_PINOSC_TA1_TB0
if(groupOfElements->halDefinition == fRO_PINOSC_TA1_TB0)
{
TI_CTS_fRO_PINOSC_TA1_TB0_HAL(groupOfElements, counts);
}
#endif
}
#ifdef TOTAL_NUMBER_OF_ELEMENTS
/***************************************************************************//**
* @brief Make a single capacitance meausrment to initialize baseline tracking
* @param groupOfElements Pointer to Sensor structure to be measured
* @return none
******************************************************************************/
void TI_CAPT_Init_Baseline(const struct Sensor* groupOfElements)
{
TI_CAPT_Raw(groupOfElements, &baseCnt[groupOfElements->baseOffset]);
}
/***************************************************************************//**
* @brief Update baseline tracking by averaging several measurements
* @param groupOfElements Pointer to Sensor structure to be measured
* @param numberOfAverages Number of measurements to be averaged
* @return none
******************************************************************************/
void TI_CAPT_Update_Baseline(const struct Sensor* groupOfElements, uint8_t numberOfAverages)
{
uint8_t i,j;
#ifndef RAM_FOR_FLASH
uint16_t *measCnt;
measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
if(measCnt ==0)
{
while(1);
}
#endif
for(j=0; j < numberOfAverages; j++)
{
for(i=0; i < groupOfElements->numElements; i++)
{
TI_CAPT_Raw(groupOfElements, measCnt);
baseCnt[i+groupOfElements->baseOffset]
= measCnt[i]/2 + baseCnt[i+groupOfElements->baseOffset]/2;
}
}
#ifndef RAM_FOR_FLASH
free(measCnt);
#endif
}
/***************************************************************************//**
* @brief Reset the Baseline Tracking algorithm to the default state
* @param none
* @return none
******************************************************************************/
void TI_CAPT_Reset_Tracking(void)
{
ctsStatusReg = (DOI_INC+TRADOI_FAST+TRIDOI_SLOW);
}
/***************************************************************************//**
* @brief Update the Baseline Tracking algorithm Direction of Interest
* @param direction Direction of increasing or decreasing capacitance
* @return none
******************************************************************************/
void TI_CAPT_Update_Tracking_DOI(uint8_t direction)
{
if(direction)
{
ctsStatusReg |= DOI_INC;
}
else
{
ctsStatusReg &= ~DOI_INC;
}
}
/***************************************************************************//**
* @brief Update the baseling tracking algorithm tracking rates
* @param rate Rate of tracking changes in and against direction of intrest
* @return none
******************************************************************************/
void TI_CAPT_Update_Tracking_Rate(uint8_t rate)
{
ctsStatusReg &= ~(TRIDOI_FAST+TRADOI_VSLOW); // clear fields
ctsStatusReg |= (rate & 0xF0); // update fields
}
/***************************************************************************//**
* @brief Measure the change in capacitance of the Sensor
*
* This function measures the change in capacitance of each element
* within a sensor and updates the baseline tracking in the event that
* no change exceeds the detection threshold.
* The order of the elements within the Sensor structure is arbitrary
* but must be consistent between the application and configuration.
* The first element in the array (deltaCnt) corresponds to the first
* element within the Sensor structure.
* @param groupOfElements Pointer to Sensor structure to be measured
* @param deltaCnt Address to where the measurements are to be written
* @return none
******************************************************************************/
void TI_CAPT_Custom(const struct Sensor* groupOfElements, uint16_t * deltaCnt)
{
uint8_t j;
uint16_t tempCnt, remainder;
ctsStatusReg &= ~ EVNT;
TI_CAPT_Raw(groupOfElements, &deltaCnt[0]); // measure group of sensors
for (j = 0; j < (groupOfElements->numElements); j++)
{
tempCnt = deltaCnt[j];
if(deltaCnt[j])
{
if(((ctsStatusReg & DOI_MASK)
&& (groupOfElements->halDefinition & RO_MASK))
||
((!(ctsStatusReg & DOI_MASK))
&& (!(groupOfElements->halDefinition & RO_MASK))))
{
/*
* Interested in a decrease in counts. Either the decrease
* represents an increase in capacitance (a touch) with the
* RO method, or the decrease represents a decrease in capacitance
* (release) with the fRO or RC methods.
*/
if(baseCnt[j+groupOfElements->baseOffset] < deltaCnt[j])
{
/*
* The measured value is greater than the baseline therefore
* no detection logic is needed. The measured value is
* preserved in tempCnt and is used for baseline updates.
*/
deltaCnt[j] = 0;
if(((groupOfElements->arrayPtr[j])->threshold)
&&
(baseCnt[j+groupOfElements->baseOffset]
+((groupOfElements->arrayPtr[j])->threshold/2) < tempCnt))
{
/*
* When the threshold is valid (non-calibration state),
* limit the measurement to the baseline + threshold/2.
*/
tempCnt = baseCnt[j+groupOfElements->baseOffset]
+((groupOfElements->arrayPtr[j])->threshold)/2;
}
}
else
{
/*
* deltaCnt now represents the magnitude of change relative to
* the baseline.
*/
deltaCnt[j] = baseCnt[j+groupOfElements->baseOffset]
- deltaCnt[j];
}
}
if(((!(ctsStatusReg & DOI_MASK))
&& (groupOfElements->halDefinition & RO_MASK))
||
((ctsStatusReg & DOI_MASK)
&& (!(groupOfElements->halDefinition & RO_MASK))))
{
/*
* Interested in an increase in counts. Either the increase
* represents a decrease in capacitance (a release) with the
* RO method, or the increase represents a increase in capacitance
* (touch) with the fRO or RC methods.
*/
if(baseCnt[j+groupOfElements->baseOffset] > deltaCnt[j])
{
/*
* The measured value is less than the baseline therefore
* no detection logic is needed. The measured value is
* preserved in tempCnt and is used for baseline updates.
*/
deltaCnt[j] = 0;
if(((groupOfElements->arrayPtr[j])->threshold)
&&
(baseCnt[j+groupOfElements->baseOffset]
-((groupOfElements->arrayPtr[j])->threshold/2) > tempCnt))
{
/*
* When the threshold is valid (non-calibration state),
* limit the measurement to the baseline - threshold/2.
*/
tempCnt = baseCnt[j+groupOfElements->baseOffset]
-((groupOfElements->arrayPtr[j])->threshold)/2;
}
}
else
{
/*
* deltaCnt now represents the magnitude of change relative to
* the baseline.
*/
deltaCnt[j] = deltaCnt[j]
- baseCnt[j+groupOfElements->baseOffset];
}
}
// This section updates the baseline capacitance************************
if (deltaCnt[j]==0)
{ // if delta counts is 0, then the change in capacitance was opposite
// the direction of interest. The baseCnt[i] is updated with the
// saved tempCnt value for the current index value 'i'.
remainder = 0;
switch ((ctsStatusReg & TRADOI_VSLOW))
{
case TRADOI_FAST://Fast
tempCnt = tempCnt/2;
baseCnt[j+groupOfElements->baseOffset]
= (baseCnt[j+groupOfElements->baseOffset]/2);
break;
case TRADOI_MED://Medium
tempCnt = tempCnt/4;
baseCnt[j+groupOfElements->baseOffset]
= 3*(baseCnt[j+groupOfElements->baseOffset]/4);
break;
case TRADOI_SLOW://slow
/* Calculate remainder associated with (x + 63*y)/64 */
remainder = 0x003F & baseCnt[j+groupOfElements->baseOffset];
remainder = remainder * 63;
remainder += 0x003F & tempCnt;
remainder = remainder >> 6;
tempCnt = tempCnt/64;
baseCnt[j+groupOfElements->baseOffset]
= 63*(baseCnt[j+groupOfElements->baseOffset]/64);
break;
case TRADOI_VSLOW://very slow
/* Calculate remainder associated with (x+127*y)/128 */
remainder = 0x007F & baseCnt[j+groupOfElements->baseOffset];
remainder = remainder * 127;
remainder += 0x007F & tempCnt;
remainder = remainder >> 7;
tempCnt = tempCnt/128;
baseCnt[j+groupOfElements->baseOffset]
= 127*(baseCnt[j+groupOfElements->baseOffset]/128);
break;
}
/* Base_Capacitance = (Measured_Capacitance/Z)
+ Y*(Base_Capacitance/Z) */
tempCnt += remainder;
baseCnt[j+groupOfElements->baseOffset] += tempCnt;
/* In the case that DOI is set and */
if(groupOfElements->halDefinition & RO_MASK)
{
/* If the RO_MASK is set then the direction of interest is
* decreasing (counts decrease with capacitance) and therefore
* movement against the direction of interest would be an
* increase: increment.
*/
baseCnt[j+groupOfElements->baseOffset]++;
}
else
{
/* RO_MASK is not set and therefore a decrease is against
* the direction of interest: decrement
*/
baseCnt[j+groupOfElements->baseOffset]--;
}
}
/* deltaCnt is either 0, less than threshold, or greater than
threshold, never negative. */
else if(deltaCnt[j]<(groupOfElements->arrayPtr[j])->threshold
&& !(ctsStatusReg & PAST_EVNT))
{ //if delta counts is positive but less than threshold,
remainder = 1;
switch ((ctsStatusReg & TRIDOI_FAST))
{
case TRIDOI_VSLOW:
tempCnt = 0;
break;
case TRIDOI_SLOW://slow
remainder = 2;
tempCnt = 0;
break;
case TRIDOI_MED://medium
tempCnt = tempCnt/4;
baseCnt[j+groupOfElements->baseOffset] = 3*(baseCnt[j+groupOfElements->baseOffset]/4);
break;
case TRIDOI_FAST://fast
tempCnt = tempCnt/2;
baseCnt[j+groupOfElements->baseOffset] = (baseCnt[j+groupOfElements->baseOffset]/2);
break;
}
/*
* Base_Capacitance = (Measured_Capacitance/Z) +
* Y*(Base_Capacitance/Z)
*/
baseCnt[j+groupOfElements->baseOffset] += tempCnt;
if(groupOfElements->halDefinition & RO_MASK)
{
/* If the RO_MASK is set then the direction of interest is
* decreasing (counts decrease with capacitance) and
* therefore movement in the direction of interest would
* be a decrease: decrement.
*/
baseCnt[j+groupOfElements->baseOffset]-= remainder;
}
else
{
/* RO_MASK is not set and therefore an increase is in the
* direction of interest: increment
*/
baseCnt[j+groupOfElements->baseOffset]+= remainder;
}
}
//if delta counts above the threshold, event has occurred
else if(deltaCnt[j]>=(groupOfElements->arrayPtr[j])->threshold)
{
ctsStatusReg |= EVNT;
ctsStatusReg |= PAST_EVNT;
}
}
}// end of for-loop
if(!(ctsStatusReg & EVNT))
{
ctsStatusReg &= ~PAST_EVNT;
}
}
/***************************************************************************//**
* @brief Determine if a button is being pressed
* @param groupOfElements Pointer to button to be scanned
* @return result Indication if button is (1) or is not (0) being pressed
******************************************************************************/
uint8_t TI_CAPT_Button(const struct Sensor * groupOfElements)
{
uint8_t result = 0;
#ifndef RAM_FOR_FLASH
uint16_t *measCnt;
measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
if(measCnt ==0)
{
while(1);
}
#endif
TI_CAPT_Custom(groupOfElements, measCnt);
#ifndef RAM_FOR_FLASH
free(measCnt);
#endif
if(ctsStatusReg & EVNT)
{
result = 1;
}
return result;
}
/***************************************************************************//**
* @brief Determine which button if any is being pressed
* @param groupOfElements Pointer to buttons to be scanned
* @return result pointer to element (button) being pressed or 0 none
******************************************************************************/
const struct Element *TI_CAPT_Buttons(const struct Sensor *groupOfElements)
{
uint8_t index;
#ifndef RAM_FOR_FLASH
uint16_t *measCnt;
measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
if(measCnt ==0)
{
while(1);
}
#endif
TI_CAPT_Custom(groupOfElements, measCnt);
if(ctsStatusReg & EVNT)
{
index = Dominant_Element(groupOfElements, measCnt);
//ctsStatusReg &= ~EVNT;
index++;
}
else
{
index = 0;
}
#ifndef RAM_FOR_FLASH
free(measCnt);
#endif
if(index)
{
return groupOfElements->arrayPtr[index-1];
}
return 0;
}
#ifdef SLIDER
/***************************************************************************//**
* @brief Determine the position on a slider
* @param groupOfElements Pointer to slider
* @return result position on slider or illegal value if no touch
******************************************************************************/
uint16_t TI_CAPT_Slider(const struct Sensor* groupOfElements)
{
uint8_t index;
int16_t position;
// allocate memory for measurement
#ifndef RAM_FOR_FLASH
uint16_t *measCnt;
measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
if(measCnt ==0)
{
while(1);
}
#endif
position = ILLEGAL_SLIDER_WHEEL_POSITION;
//make measurement
TI_CAPT_Custom(groupOfElements, measCnt);
// Use EVNT flag to determine if slider was touched.
// The EVNT flag is a global variable and managed within the TI_CAPT_Custom
// function.
if(ctsStatusReg & EVNT)
{
index = Dominant_Element(groupOfElements, &measCnt[0]);
// The index represents the element within the array with the highest
// return.
if(index == 0)
{
// Special case of 1st element in slider, add 1st, last, and 2nd
position = measCnt[0] + measCnt[1];
}
else if(index == (groupOfElements->numElements -1))
{
// Special case of Last element in slider, add last,
// 1st, and 2nd to last
position = measCnt[groupOfElements->numElements -1]
+ measCnt[groupOfElements->numElements -2];
}
else
{
position = measCnt[index] + measCnt[index+1] + measCnt[index-1];
}
// Determine if sensor threshold criteria is met
if(position >= groupOfElements->sensorThreshold)
{
// calculate position
position = index
*(groupOfElements->points
/groupOfElements->numElements);
position += (groupOfElements->points/groupOfElements->numElements)
/2;
if(index == 0)
{
// Special case of 1st element in slider, which only has one
// neighbor, measCnt[1]. measCnt is limited to maxResponse
// within dominantElement function
if(measCnt[1])
{
position += (measCnt[1]
*(groupOfElements->points
/groupOfElements->numElements))/100;
}
else
{
/* Calculate position based upon measCnt[0] */
position = (measCnt[0]
*(groupOfElements->points
/groupOfElements->numElements)/2)/100;
}
}
else if(index == (groupOfElements->numElements -1))
{
// Special case of Last element in slider, which only has one
// neighbor, measCnt[x-1] or measCnt[numElements-1]
if(measCnt[index-1])
{
position -= (measCnt[index-1]
*(groupOfElements->points
/groupOfElements->numElements))/100;
}
else
{
position = groupOfElements->points;
position -= (measCnt[index]
*(groupOfElements->points
/groupOfElements->numElements)/2)/100;
}
}
else
{
position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100;
position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
}
if((position > groupOfElements->points) || (position < 0))
{
position = ILLEGAL_SLIDER_WHEEL_POSITION;
}
}
else
{
position = ILLEGAL_SLIDER_WHEEL_POSITION;
}
}
#ifndef RAM_FOR_FLASH
free(measCnt);
#endif
return position;
}
#endif
#ifdef WHEEL
/***************************************************************************//**
* @brief Determine the position on a wheel
* @param groupOfElements Pointer to wheel
* @return result position on wheel or illegal value if no touch
******************************************************************************/
uint16_t TI_CAPT_Wheel(const struct Sensor* groupOfElements)
{
uint8_t index;
int16_t position;
// allocate memory for measurement
#ifndef RAM_FOR_FLASH
uint16_t *measCnt;
measCnt = (uint16_t *)malloc(groupOfElements->numElements * sizeof(uint16_t));
if(measCnt ==0)
{
while(1);
}
#endif
position = ILLEGAL_SLIDER_WHEEL_POSITION;
//make measurement
TI_CAPT_Custom(groupOfElements, measCnt);
// Translate the EVNT flag from an element level EVNT to a sensor level EVNT.
// The sensor must read at least 75% cumulative response before indicating a
// touch.
if(ctsStatusReg & EVNT)
{
index = Dominant_Element(groupOfElements, &measCnt[0]);
// The index represents the element within the array with the highest return.
//
if(index == 0)
{
// Special case of 1st element in slider, add 1st, last, and 2nd
position = measCnt[0] + measCnt[groupOfElements->numElements -1] + measCnt[1];
}
else if(index == (groupOfElements->numElements -1))
{
// Special case of Last element in slider, add last, 1st, and 2nd to last
position = measCnt[index] + measCnt[0] + measCnt[index-1];
}
else
{
position = measCnt[index] + measCnt[index+1] + measCnt[index-1];
}
if(position > groupOfElements->sensorThreshold)
{
//index = Dominant_Element(groupOfElements, &measCnt[0]);
// The index represents the element within the array with the highest return.
//
position = index*(groupOfElements->points/groupOfElements->numElements);
position += (groupOfElements->points/groupOfElements->numElements)/2;
if(index == 0)
{
// Special case of 1st element in slider, which only has one neighbor, measCnt[1]
// measCnt is limited to maxResponse within dominantElement function
position += (measCnt[1]*(groupOfElements->points/groupOfElements->numElements))/100;
position -= (measCnt[groupOfElements->numElements -1]*(groupOfElements->points/groupOfElements->numElements))/100;
if(position < 0)
{
position = position + (int16_t)groupOfElements->points;
position++; // -1 goes to points
}
}
else if(index == (groupOfElements->numElements -1))
{
// Special case of Last element in slider, which only has one neighbor, measCnt[x-1] or measCnt[numElements-1]
// measCnt is limited to maxResponse within dominantElement function
position += (measCnt[0]*(groupOfElements->points/groupOfElements->numElements))/100;
position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
if(position > groupOfElements->points)
{
position = position - (int16_t)groupOfElements->points;
position--; // points+1 goes to 0
}
}
else
{
position += (measCnt[index+1]*(groupOfElements->points/groupOfElements->numElements))/100;
position -= (measCnt[index-1]*(groupOfElements->points/groupOfElements->numElements))/100;
}
if((position > groupOfElements->points) || position < 0)
{
position = ILLEGAL_SLIDER_WHEEL_POSITION;
}
}
else
{
position = ILLEGAL_SLIDER_WHEEL_POSITION;
}
}
#ifndef RAM_FOR_FLASH
free(measCnt);
#endif
return position;
}
#endif
/** @} */
/***************************************************************************//**
* @defgroup CTS_support Support Group
* @ingroup CTS_API
******************************************************************************/
/***************************************************************************//**
* @ingroup CTS_support
* @brief Determine which element within a sensor has the largest response
*
* This function compares and normalizes the change in capacitance to
* determine which element has the dominant response. The deltaCnt
* values for each element that exceed the threshold are also
* converted from a 'raw' measurement to a percentage of the maximum
* response.
* @param groupOfElements Pointer to buttons to be scanned
* @param deltaCnt Address to where the measurements are to be written
* @return result index to the element which is dominant
******************************************************************************/
uint8_t Dominant_Element(const struct Sensor* groupOfElements, uint16_t* deltaCnt)
{
uint8_t i;
uint16_t percentDelta=0;
uint8_t dominantElement=0;
for(i=0;i<groupOfElements->numElements;i++)
{
if(deltaCnt[i]>=(groupOfElements->arrayPtr[i])->threshold)
{
if(deltaCnt[i] > ((groupOfElements->arrayPtr[i])->maxResponse))
{
deltaCnt[i] = (groupOfElements->arrayPtr[i])->maxResponse;
// limit response to the maximum
}
// (maxResponse - threshold) cannot exceed 655
// 100*(delta - threshold) / (maxResponse - threshold)
deltaCnt[i] = (100*(deltaCnt[i]
-(groupOfElements->arrayPtr[i])->threshold))
/((groupOfElements->arrayPtr[i])->maxResponse
-(groupOfElements->arrayPtr[i])->threshold);
if(deltaCnt[i] >= percentDelta)
{
//update percentDelta
percentDelta = deltaCnt[i];
dominantElement = i;
}
}
else
{
deltaCnt[i] = 0;
}
} // end for loop
return dominantElement;
}
#endif