Testing out the PPD42 Air Quality Sensor, with an MSP430 Launchpad and graphing the data with GNUplot.
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

/*******************************************************************************
* CTS_HAL.c - defines functions called by application as well as
* functions for information processing
*
* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
*
* 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.
*
******************************************************************************/
/***************************************************************************//**
* @file CTS_HAL.c
*
* @brief
*
* @par Project:
* MSP430 Capacitive Touch Library
*
* @par Developed using:
* IAR Version : 5.10.6 [Kickstart] (5.10.6.30180)
* CCS Version : 4.2.1.00004, w/support for GCC extensions (--gcc)
*
* @version 1.0.0 Initial Release
*
* @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_Update_Baseline()
* - TI_CAPT_Raw()
* - TI_CAPT_Custom()
* - TI_CAPT_Button()
* - TI_CAPT_Buttons()
* - TI_CAPT_Slider()
* - TI_CAPT_Wheel()
******************************************************************************/
#include "CTS_Layer.h"
#include <stdlib.h>
// Global variables for sensing
#ifdef TOTAL_NUMBER_OF_ELEMENTS
uint16_t baseCnt[TOTAL_NUMBER_OF_ELEMENTS];
#ifdef RAM_FOR_FLASH
uint16_t measCnt[MAXIMUM_NUMBER_OF_ELEMENTS_PER_SENSOR];
#endif
uint16_t ctsStatusReg = (DOI_INC+TRADOI_FAST+TRIDOI_SLOW);
#endif
/***************************************************************************//**
* @addtogroup CTS_API
* @{
******************************************************************************/
/***************************************************************************//**
* @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_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); // Measure all sensors
}
#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); // Measure all sensors
}
#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 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;
ctsStatusReg &= ~ EVNT;
// This section calculates the delta counts*************************************
//******************************************************************************
TI_CAPT_Raw(groupOfElements, &deltaCnt[0]); // measure group of sensors
for (j = 0; j < (groupOfElements->numElements); j++)
{
tempCnt = deltaCnt[j];
if(((ctsStatusReg & DOI_MASK) && (groupOfElements->halDefinition & RO_MASK))
||
((!(ctsStatusReg & DOI_MASK)) && (!(groupOfElements->halDefinition & RO_MASK))))
{
// RO method, interested in an increase in capacitance
if(baseCnt[j+groupOfElements->baseOffset] < deltaCnt[j])
{
// If capacitance decreases, then measCnt is greater than base
// , set delta to zero
deltaCnt[j] = 0;
// Limit the change in the opposite direction to the threshold
if(((groupOfElements->arrayPtr[j])->threshold)
&&
(baseCnt[j+groupOfElements->baseOffset]+(groupOfElements->arrayPtr[j])->threshold < tempCnt))
{
tempCnt = baseCnt[j+groupOfElements->baseOffset]+(groupOfElements->arrayPtr[j])->threshold;
}
}
else
{
// change occuring in our DOI, save result
deltaCnt[j] = baseCnt[j+groupOfElements->baseOffset]-deltaCnt[j];
}
}
if(((!(ctsStatusReg & DOI_MASK)) && (groupOfElements->halDefinition & RO_MASK))
||
((ctsStatusReg & DOI_MASK) && (!(groupOfElements->halDefinition & RO_MASK))))
{
// RO method: interested in a decrease in capactiance
// measCnt is greater than baseCnt
if(baseCnt[j+groupOfElements->baseOffset] > deltaCnt[j])
{
// If capacitance increases, set delta to zero
deltaCnt[j] = 0;
// Limit the change in the opposite direction to the threshold
if(((groupOfElements->arrayPtr[j])->threshold)
&&
(baseCnt[j+groupOfElements->baseOffset] > tempCnt+(groupOfElements->arrayPtr[j])->threshold))
{
tempCnt = baseCnt[j+groupOfElements->baseOffset]-(groupOfElements->arrayPtr[j])->threshold;
}
}
else
{
// change occuring in our DOI
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
// measCnt value for the current index value 'i'.
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
tempCnt = tempCnt/64;
baseCnt[j+groupOfElements->baseOffset] = 63*(baseCnt[j+groupOfElements->baseOffset]/64);
break;
case TRADOI_VSLOW://very slow
tempCnt = tempCnt/128;
baseCnt[j+groupOfElements->baseOffset] = 127*(baseCnt[j+groupOfElements->baseOffset]/128);
break;
}
// set X, Y & Z, then perform calculation for baseline tracking:
// Base_Capacitance = X*(Measured_Capacitance/Z) + Y*(Base_Capacitance/Z)
baseCnt[j+groupOfElements->baseOffset] = (tempCnt)+(baseCnt[j+groupOfElements->baseOffset]);
}
// delta counts are 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,
switch ((ctsStatusReg & TRIDOI_FAST))
{
case TRIDOI_VSLOW://very slow
if(deltaCnt[j] > 15)
{
if(tempCnt < baseCnt[j+groupOfElements->baseOffset])
{
baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] - 1;
}
else
{
baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] + 1;
}
}
tempCnt = 0;
break;
case TRIDOI_SLOW://slow
if(tempCnt < baseCnt[j+groupOfElements->baseOffset])
{
baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] - 1;
}
else
{
baseCnt[j+groupOfElements->baseOffset] = baseCnt[j+groupOfElements->baseOffset] + 1;
}
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;
}
// set X, Y & Z, then perform calculation for baseline tracking:
// Base_Capacitance = X*(Measured_Capacitance/Z) + Y*(Base_Capacitance/Z)
baseCnt[j+groupOfElements->baseOffset] = (tempCnt)+(baseCnt[j+groupOfElements->baseOffset]);
}
//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
{
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;
}
}
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 -1))
{
position = position - (int16_t)groupOfElements->points;
}
}
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
* @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