/* This source file is part of the ATMEL QTouch Library Release 4.3.1 */
/* This file is prepared for Doxygen automatic documentation generation. */
/*! \file *********************************************************************
*
* \brief This file contains the QTouch Libary API interface for
* AVR 8-bit, AVR 32-bit and Atmel ARM QMatrix and QTouch method
* Capacitive Touch acquisition.
*
* - Compiler: IAR EWAVR/EWAVR32 and GNU GCC for AVR/AVR32
* IAR Workbench and GNU GCC for Atmel ARM.
* - Supported devices: Atmel AVR 8-bit, AVR 32-bit, Atmel ARM.
* - Userguide: QTouch Library User Guide - doc8207.pdf.
* - Support email: touch@atmel.com
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/
/* Copyright (c) 2010 Atmel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an Atmel
* AVR product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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
*
*/
#ifndef TOUCH_API_H
#define TOUCH_API_H
#include "../../touch.h"
/*----------------------------------------------------------------------------
nested include files
----------------------------------------------------------------------------*/
#if defined (__GNUC__) || defined (__ICCARM__) ||defined (__CC_ARM)
#include <stdint.h>
#endif
#if !defined (__CC_ARM)
#include <stdbool.h>
#endif
#include <stdlib.h>
#ifndef MAKE_BUILD
# ifdef _QMATRIX_
# if !(defined(__AVR32__) || defined(__ICCAVR32__))
# include "qm_asm_avr.h"
# else
# include "touch_qm_config32.h"
# endif
# elif defined _QTOUCH_
# if !(defined(__AVR32__) || defined(__ICCAVR32__))
# include "qt_asm_avr.h"
# endif
# else
# error /* please provide any one of the acquisition methods */
# endif
#endif
#ifdef __ICCAVR__
#include <intrinsics.h>
#endif /* (__ICCAVR__) */
/*----------------------------------------------------------------------------
Note: choice of library version
-----------------------------------------------------------------------------*/
/**
* QTouch libraries are supplied built with a range of charge times.
* Charge time is the duration in which charge is transferred from the AVR onto
* the measurement capacitor. Shorter charge times result in faster measurements,
* but may be too fast to completely transfer charge onto the measurement
* capacitor.
*
* The range of charge times lets the user choose a suitable version for the clock
* rate their chip is running at.
*
* To make capacitive measurements, a charge time on the order of 0.25us to 2.5us
* is typically required. The following table shows the charge times corresponding
* to a range of clock speeds.
*
* Clock speed (MHz) Cycle time (us) Suitable charge times
* ----------------- --------------- ---------------------
* 1 1 1~2 cycles (1us to 2us)
* 2 0.5 1~5 cycles (0.5us to 2.5us)
* 4 0.25 1~10 cycles (0.25us to 2.5us)
* 8 0.125 2~10 cycles (0.25us to 1.25us)
* 10 0.1 3~25 cycles (0.3us to 2.5us)
* 16 0.0625 4~25 cycles (0.25us to 1.5625s)
* 20 0.05 5~50 cycles (0.25us to 2.5us)
*/
/**
* Error Checking For the User Configuration Options Starts here.
*/
#ifdef _QMATRIX_
/**
* Info stored for each x line.
*
* For each X line, enter the port and pin it is on.
* For instance, if X3 is on PB1, the 4th entry would be
* FILL_OUT_X_LINE_INFO( 1,1 ), and PORT_X_1 is B
*/
#define FILL_OUT_X_LINE_INFO( port_num,x_bit ) {JOIN(burst_qm_, port_num) ,(TOUCH_DATA_T)( 1u << x_bit ), BURST_MASK_X_PORT_ ## port_num }
/**
* Info stored for each y line.
*
* For each Y line, enter the pin it is on.
* For instance, if Y2 is on PA5 and PF5, the 3th entry would be
* FILL_OUT_Y_LINE_INFO( 5 )
* NOTE: 1. The PORTs for YA and YB on which Y lines are going to
* be needs to be defined as PORT_YA and PORT_YB.
*
* Example: PORT_YA=A and PORT_YB=F in the case above.
*/
#if !(defined(__AVR32__) || defined(__ICCAVR32__))
//#define FILL_OUT_Y_LINE_INFO( bit ) { bit, (TOUCH_DATA_T)(1u<<bit) }
#define FILL_OUT_YA_LINE_INFO( bit ) { bit, (TOUCH_DATA_T)(1u<<bit) }
#define FILL_OUT_YB_LINE_INFO( bit ) { bit, (TOUCH_DATA_T)(1u<<bit) }
#else
#define FILL_OUT_YA_LINE_INFO( bit ) { bit, (TOUCH_DATA_T)(1u<<bit) }
#define FILL_OUT_YB_LINE_INFO( bit ) { bit, (TOUCH_DATA_T)(1u<<bit) }
#endif
/**
* Info stored for each ya line.
*
* For each YA line, enter the pin it is on.
* For instance, if Y2A is on PA5 , the 3th entry would be
* FILL_OUT_YA_LINE_INFO( 5 )
* NOTE: 1. The PORTs for YA and YB on which Y lines are going to
* be needs to be defined as PORT_YA and PORT_YB.
*
* Example: PORT_YA=A in the case above.
*/
//FWRAP: #define FILL_OUT_YA_LINE_INFO( bit ) { bit, (uint8_t)(1u<<bit) }
/**
* Info stored for each yb line.
*
* For each YB line, enter the pin it is on.
* For instance, if Y2B is on PF3, the 3th entry would be
* FILL_OUT_YB_LINE_INFO( 3 )
* NOTE: 1. The PORTs for YA and YB on which Y lines are going to
* be needs to be defined as PORT_YA and PORT_YB.
*
* Example: PORT_YB=F in the case above.
*/
//FWRAP: #define FILL_OUT_YB_LINE_INFO( bit ) { bit, (uint8_t)(1u<<bit) }
#ifndef MAKE_BUILD
//! Check necessary definitions.
#if (NUM_X_PORTS==1)
#if !defined(PORT_X_1) || !defined(PORT_YA) || !defined(PORT_YB) || !defined(QT_DELAY_CYCLES) || !defined(PORT_SMP) || !defined(SMP_BIT)
#error Need to define PORT_X_1, PORT_YA,PORT_YB,PORT_SMP,SMP_BIT and QT_DELAY_CYCLES before including the header file.
#endif
#elif(NUM_X_PORTS==2)
#if !defined(PORT_X_1)||!defined(PORT_X_2) || !defined(PORT_YA) || !defined(PORT_YB) || !defined(QT_DELAY_CYCLES) || !defined(PORT_SMP) || !defined(SMP_BIT)
#error Need to define PORT_X_1,PORT_X_2, PORT_YA,PORT_YB,PORT_SMP,SMP_BIT and QT_DELAY_CYCLES before including the header file.
#endif
#elif(NUM_X_PORTS==3)
#if !defined(PORT_X_1)||!defined(PORT_X_2) ||!defined(PORT_X_3)|| !defined(PORT_YA) || !defined(PORT_YB) || !defined(QT_DELAY_CYCLES) || !defined(PORT_SMP) || !defined(SMP_BIT)
#error Need to define PORT_X_1,PORT_X_2,PORT_X_3, PORT_YA,PORT_YB,PORT_SMP,SMP_BIT and QT_DELAY_CYCLES before including the header file.
#endif
#endif
#ifdef _ROTOR_SLIDER_
#if (QT_NUM_CHANNELS == 4u)
#if !(QT_MAX_NUM_ROTORS_SLIDERS == 1u)
#error QT_MAX_NUM_ROTORS_SLIDERS should be define as 1
#endif
#elif (QT_NUM_CHANNELS == 8u)
#if !(QT_MAX_NUM_ROTORS_SLIDERS == 2u)
#error QT_MAX_NUM_ROTORS_SLIDERS should be define as 2
#endif
#elif (QT_NUM_CHANNELS == 16u)
#if !((QT_MAX_NUM_ROTORS_SLIDERS == 2u) || (QT_MAX_NUM_ROTORS_SLIDERS == 4u))
#error QT_MAX_NUM_ROTORS_SLIDERS should be define as 2 or 4 based on library selected
#endif
#elif (QT_NUM_CHANNELS == 24u)
#if !((QT_MAX_NUM_ROTORS_SLIDERS == 3u))
#error QT_MAX_NUM_ROTORS_SLIDERS should be define as 3
#endif
#elif (QT_NUM_CHANNELS == 32u)
#if !(QT_MAX_NUM_ROTORS_SLIDERS == 4u)
#error QT_MAX_NUM_ROTORS_SLIDERS should be define as 4 based on library selected
#endif
#elif (QT_NUM_CHANNELS == 64u)
#if !((QT_MAX_NUM_ROTORS_SLIDERS == 4u) || (QT_MAX_NUM_ROTORS_SLIDERS == 8u))
#error QT_MAX_NUM_ROTORS_SLIDERS should be define as 4 or 8 based on library selected
#endif
#endif
#else
#if !(QT_MAX_NUM_ROTORS_SLIDERS == 0u)
#error QT_MAX_NUM_ROTORS_SLIDERS should be define as 0 Or _ROTOR_SLIDER_ Macro Needs to be define
#endif
#endif
#endif //! MAKE_BUILD.
#endif //! _QMATRIX_
/**
* Error Checking For the User Configuration Options ends here.
*/
/**
* WARNING! Do not edit below this line.
*/
/*----------------------------------------------------------------------------
macros
----------------------------------------------------------------------------*/
/**
* Utility macro for expanding port registers.
*/
#define JOIN( x, y ) x ## y
#define JOIN1( A, B, C ) A ## B ## C
/**
* Macro to build register writes for controlling ports. The intermediate
* JOIN macro is required for correct expansion of the args.
*/
#define REG( REGISTER, SIDE ) JOIN( REGISTER, SIDE )
#define CONCAT( A, B, C ) JOIN1( A, B, C )
/**
* The number of bytes required to report the maximum possible number of
* sensors.
*/
#define QT_NUM_SENSOR_STATE_BYTES ( ( QT_NUM_CHANNELS + 7u ) / 8u )
/**
* Status flags used with debug
*/
//! indicating no activity.
#define QTLIB_NO_ACTIVITY (uint16_t) 0x0000
//! indicating that at least one sensor is in detect.
#define QTLIB_IN_DETECT (uint16_t) 0x0001
//! indicating that at least one sensor haschanged ON/OFF state since last call to measure_sensors.
#define QTLIB_STATUS_CHANGE (uint16_t) 0x0002
//! indicating that at least one rotor slider has changed position since last call to measure_sensors.
#define QTLIB_ROTOR_SLIDER_POS_CHANGE (uint16_t) 0x0004
//! indicating that at least one reference value has changed since last call to measure_sensors.
#define QTLIB_CHANNEL_REF_CHANGE (uint16_t) 0x0008
//! indicating that reburst is needed to resolve in FILTERIN or FILTEROUT or RECALIBRATE state.
#define QTLIB_BURST_AGAIN (uint16_t) 0x0100
//! indicating that reburst is needed to resolve in CALIBRATION.
#define QTLIB_RESOLVE_CAL (uint16_t) 0x0200
//! indicating that reburst is needed to resolve in FILTERING.
#define QTLIB_RESOLVE_FILTERIN (uint16_t) 0x0400
//! indicating that reburst is needed to resolve in RECAL.
#define QTLIB_RESOLVE_DI (uint16_t) 0x0800
//! indicating that reburst is needed to resolve in RECAL.
#define QTLIB_RESOLVE_POS_RECAL (uint16_t) 0x1000
/*----------------------------------------------------------------------------
type definitions
----------------------------------------------------------------------------*/
#if defined (__ICCAVR__) || defined (__ICCAVR32__)
//! An signed 8-bit value.
typedef signed char int8_t;
//! An unsigned 8-bit value.
typedef unsigned char uint8_t;
//! An unsigned 16-bit value.
typedef unsigned short uint16_t;
//! A signed 16-bit value.
typedef short int16_t;
//! An unsigned 32-bit value.
typedef unsigned long uint32_t;
#endif
/**
* This part of the code below is used for library selection. This code will not be documented.
*/
#ifdef _QTOUCH_
#ifdef QTOUCH_STUDIO_MASKS
#define CALCULATE_MASKS NULL
#else
#define CALCULATE_MASKS calc_masks
#endif
#if defined (__AVR32__) || defined (__ICCAVR32__) || defined (_TOUCH_ARM_)
#if (QT_NUM_CHANNELS <= 8u && QT_NUM_CHANNELS != 0u)
#define TOUCH_DATA_T uint8_t
#elif (QT_NUM_CHANNELS > 8u && QT_NUM_CHANNELS <= 16u)
#define TOUCH_DATA_T uint16_t
#elif (QT_NUM_CHANNELS > 16u && QT_NUM_CHANNELS <= 32u)
#define TOUCH_DATA_T uint32_t
#else
#error 'The number of channels specified is not supported.'
#endif
#else
#define TOUCH_DATA_T uint8_t
#endif
#ifndef MAKE_BUILD
#if !(defined(__AVR32__) || defined(__ICCAVR32__)) || defined(_TOUCH_ARM_)
#if (QT_NUM_CHANNELS == 16u)
#ifndef _STATIC_PORT_PIN_CONF_
#define _STATIC_PORT_PIN_CONF_
#define QTOUCH_SNS_PORT_COUNT 2u
#endif
#else
#ifdef INTRABURST_1
#ifndef _STATIC_PORT_PIN_CONF_
#define _STATIC_PORT_PIN_CONF_
#define QTOUCH_SNS_PORT_COUNT 1u
#endif
#endif
#ifndef SNS1
#define SNS1 SNS
#endif
#ifndef SNSK1
#define SNSK1 SNSK
#endif
#endif
#else
#ifdef INTRABURST_1
#ifndef _STATIC_PORT_PIN_CONF_
#define _STATIC_PORT_PIN_CONF_
#define QTOUCH_SNS_PORT_COUNT 1u
#endif
#define SNS1 SNS
#define SNSK1 SNSK
#endif
#endif
#ifdef _ROTOR_SLIDER_
#if !defined(QT_MAX_NUM_ROTORS_SLIDERS)
#if (QT_NUM_CHANNELS == 4)
#define QT_MAX_NUM_ROTORS_SLIDERS 1
#elif (QT_NUM_CHANNELS == 8)
#define QT_MAX_NUM_ROTORS_SLIDERS 2
#elif (QT_NUM_CHANNELS == 12)
#define QT_MAX_NUM_ROTORS_SLIDERS 3
#elif (QT_NUM_CHANNELS == 16)
#define QT_MAX_NUM_ROTORS_SLIDERS 4
#elif (QT_NUM_CHANNELS == 32)
#define QT_MAX_NUM_ROTORS_SLIDERS 8
#endif
#endif
#else
#define QT_MAX_NUM_ROTORS_SLIDERS 0
#endif
#endif
#if !(defined(__AVR32__) || defined(__ICCAVR32__) || defined(_TOUCH_ARM_))
//! Macros for string concatenation.
//#define JOIN3( a, b, c, d, e ) burst_ ## a ## _ ## b ## _ ## c ## d ## _ ## e
#define JOIN4( a, b, c, d, e , f ) burst_ ## a ## _ ## b ## _ ## c ## d ## _ ## e ##_ ## f
//#define BURST_JOIN( static_flag, num_ports, intra1, intra2, pow_opt ) JOIN3( static_flag, num_ports, intra1, intra2, pow_opt )
#define BURST_JOIN( static_flag, num_ports, intra1, intra2, pow_opt, qtouch_pin_conf ) JOIN4( static_flag, num_ports, intra1, intra2, pow_opt, qtouch_pin_conf )
//! Build pointer to correct burst function.
#define BURST_FUNC_NAME BURST_JOIN( _STATIC_PORT_PIN_CONF_, QTOUCH_SNS_PORT_COUNT, INTRABURST_1, INTRABURST_2, _POWER_OPTIMIZATION_, QTOUCH_PIN_CONF )
//#define BURST_FUNC_NAME BURST_JOIN( _STATIC_PORT_PIN_CONF_, QTOUCH_SNS_PORT_COUNT, INTRABURST_1, INTRABURST_2, _POWER_OPTIMIZATION_ )
//! Burst function prototype. The code itself is stored in the touch library.
extern void BURST_FUNC_NAME (TOUCH_DATA_T mask_index);
//! Function pointer used for bursting.
extern void (*burst_proc) (TOUCH_DATA_T mask_index);
#else
#ifndef _STATIC_PORT_PIN_CONF_
/**
* Select SNS and SNSK port. Choosing the same port for both will
* configure intra-port bursting. Options are B,C, and D.
*/
#define QT_SNS_PORT SNS
#define QT_SNSK_PORT SNSK
//! Check necessary definitions.
#if !defined(QT_SNS_PORT) || !defined(QT_SNSK_PORT) || !defined(QT_DELAY_CYCLES)
#error Need to define QT_SNS_PORT, QT_SNSK_PORT, and QT_DELAY_CYCLES before including this header file.
#endif
//! Macros for string concatenation.
#define JOIN3( a, b, c ) burst_ ## a ## _ ## b ## c
#define BURST_JOIN( cycles, snsk, sns ) JOIN3( cycles, snsk, sns )
//! Build pointer to correct burst function.
#define BURST_FUNC_NAME BURST_JOIN( QT_DELAY_CYCLES, QT_SNSK_PORT , QT_SNS_PORT)
#else
//! static port pin configurability declarations.
#if (QTOUCH_SNS_PORT_COUNT > 0u)
//! first SNS - SNSK port pin pairing.
#define QT_SNS1_PORT SNS1
#define QT_SNSK1_PORT SNSK1
#if !defined(QT_SNS1_PORT) || !defined(QT_SNSK1_PORT) || !defined(QT_DELAY_CYCLES) || !defined(QT_NUM_CHANNELS) || \
!defined(QT_MAX_NUM_ROTORS_SLIDERS)
#error Need to define QT_SNS1_PORT, QT_SNSK1_PORT, QT_DELAY_CYCLES, QT_NUM_CHANNELS and QT_MAX_NUM_ROTORS_SLIDERS before including this header file.
#endif
#endif
#if (QTOUCH_SNS_PORT_COUNT > 1u) && !defined(_TOUCH_ARM_)
#error 'Maximum of only 1 SNS-SNSK port pairings are supported by the UC3 libraries.'
#elif (QTOUCH_SNS_PORT_COUNT == 0u)
#error 'Invalid QTOUCH_SNS_PORT_COUNT value.'
#endif /* QTOUCH_SNS_PORT_COUNT */
#if (QTOUCH_SNS_PORT_COUNT > 1u)
//! second SNS - SNSK port pin pairing.
#define QT_SNS2_PORT SNS2
#define QT_SNSK2_PORT SNSK2
#if !defined(QT_SNS2_PORT) || !defined(QT_SNSK2_PORT) || !defined(QT_DELAY_CYCLES) || !defined(QT_NUM_CHANNELS) || \
!defined(QT_MAX_NUM_ROTORS_SLIDERS)
#error Need to define QT_SNS2_PORT, QT_SNSK2_PORT, QT_DELAY_CYCLES, QT_NUM_CHANNELS and QT_MAX_NUM_ROTORS_SLIDERS before including this header file.
#endif
#endif
#if (QTOUCH_SNS_PORT_COUNT == 1u)
//! Macros for string concatenation.
#define JOIN3( a, b, c, d, z ) burst_ ## a ## _ ## b ## c
#define BURST_JOIN( cycles, snsk1, sns1, ch, rs ) JOIN3( cycles, snsk1, sns1, ch, rs )
//! Build pointer to correct burst function.
#define BURST_FUNC_NAME BURST_JOIN( QT_DELAY_CYCLES, QT_SNSK1_PORT , QT_SNS1_PORT, QT_NUM_CHANNELS, \
QT_MAX_NUM_ROTORS_SLIDERS)
#elif (QTOUCH_SNS_PORT_COUNT == 2u)
#if defined(_TOUCH_ARM_)
//! Macros for string concatenation.
#define JOIN3( a, b, c, e, f, d, z ) burst_ ## a ## _ ## b ## c ## _ ## e ## f
#define BURST_JOIN( cycles, snsk1, sns1, snsk2, sns2, ch, rs ) JOIN3( cycles, snsk1, sns1, snsk2, sns2, ch, rs )
//! Build pointer to correct burst function.
#define BURST_FUNC_NAME BURST_JOIN( QT_DELAY_CYCLES, QT_SNSK1_PORT , QT_SNS1_PORT, QT_SNSK2_PORT , QT_SNS2_PORT, QT_NUM_CHANNELS, \
QT_MAX_NUM_ROTORS_SLIDERS)
#endif
#else
#error 'Invalid QTOUCH_SNS_PORT_COUNT value.'
#endif
#endif
//! Burst function prototype. The code itself is stored in the touch library.
extern void BURST_FUNC_NAME (TOUCH_DATA_T mask_index);
//! Function pointer used for bursting.
extern void (*burst_proc) (TOUCH_DATA_T mask_index);
#endif
#endif
/**
* QMATRIX Start.
*/
#ifdef _QMATRIX_
// #ifdef __AVR32__
#if defined (__AVR32__) || defined (__ICCAVR32__)
#define TOUCH_DATA_T uint32_t
#else
#define TOUCH_DATA_T uint8_t
#endif
//! Macros for string concatenation.
#define BURST_JOIN(A,B) JOIN(A,B)
#if (NUM_X_PORTS ==1)
#define BURST_FUNC_1 BURST_JOIN(burst_qm_,PORT_NUM_1)
extern void BURST_FUNC_1 (uint8_t channel, TOUCH_DATA_T x_mask);
#elif (NUM_X_PORTS ==2)
#define BURST_FUNC_1 BURST_JOIN(burst_qm_,PORT_NUM_1)
extern void BURST_FUNC_1 (uint8_t channel, TOUCH_DATA_T x_mask);
#define BURST_FUNC_2 BURST_JOIN(burst_qm_,PORT_NUM_2)
extern void BURST_FUNC_2 (uint8_t channel, TOUCH_DATA_T x_mask);
#elif (NUM_X_PORTS ==3)
#define BURST_FUNC_1 BURST_JOIN(burst_qm_,PORT_NUM_1)
extern void BURST_FUNC_1 (uint8_t channel, TOUCH_DATA_T x_mask);
#define BURST_FUNC_2 BURST_JOIN(burst_qm_,PORT_NUM_2)
extern void BURST_FUNC_2 (uint8_t channel, TOUCH_DATA_T x_mask);
#define BURST_FUNC_3 BURST_JOIN(burst_qm_,PORT_NUM_3)
extern void BURST_FUNC_3 (uint8_t channel, TOUCH_DATA_T x_mask);
#endif
//! Function pointer used for bursting.
extern void (*burst_proc_qm) (uint8_t channel, TOUCH_DATA_T drive_mask);
//! pointer to function to be called for a channel.
typedef void (*PF_CHANNEL) (uint8_t channel);
//! pointer to function returning void.
typedef void (*PFV) (uint8_t channel, TOUCH_DATA_T line_mask);
//! info stored for each x line.
typedef struct tag_x_line_info_t
{
//! ptr to function to burst on this line.
PFV p_burst_function;
//! bit mask for driving/clamping this x line.
TOUCH_DATA_T mask;
//! index into array of burst masks.
TOUCH_DATA_T burst_mask_array_index;
}
x_line_info_t;
//! info stored for each y line.
typedef struct tag_y_line_info_t
{
//! which bit this y line is on.
TOUCH_DATA_T bit;
//! mask for y line.
TOUCH_DATA_T mask;
}
y_line_info_t;
//! enumeration of recognised burst masks.
typedef enum tag_burst_mask_t
{
BURST_MASK_YA, //! mask for ya lines.
BURST_MASK_YB, //! mask for yb lines.
BURST_MASK_X_PORT_1, //! mask for x lines on port1.
BURST_MASK_X_PORT_2, //! mask for x lines on port2.
BURST_MASK_X_PORT_3, //! mask for x lines on port3.
NUM_BURST_MASKS //! Total number of masks.
}
burst_mask_t;
/**
* The burst length on each QMatrix channel.
*
* Units: pulses
* Default value: 64 pulses
*/
extern uint8_t qt_burst_lengths[QT_NUM_CHANNELS];
#endif /* _QMATRIX_ */
/**
* QMATRIX End
*/
//! An unsigned 8-bit number setting a sensor detection threshold.
typedef uint8_t threshold_t;
//! Options for the sensor types available.
typedef enum tag_sensor_type_t
{
SENSOR_TYPE_UNASSIGNED,
SENSOR_TYPE_KEY,
SENSOR_TYPE_ROTOR,
SENSOR_TYPE_SLIDER
}
sensor_type_t;
/**
* Which AKS group, if any, a sensor is in.
*
* NO_AKS_GROUP = sensor is not in an AKS group, and cannot be suppressed.
* AKS_GROUP_x = sensor is in AKS group x.
*/
typedef enum tag_aks_group_t
{
NO_AKS_GROUP,
AKS_GROUP_1,
AKS_GROUP_2,
AKS_GROUP_3,
AKS_GROUP_4,
AKS_GROUP_5,
AKS_GROUP_6,
AKS_GROUP_7
}
aks_group_t;
//! The channel(s) in a sensor.
typedef enum tag_channel_t
{
#if (QT_NUM_CHANNELS > 0u)
CHANNEL_0,
CHANNEL_1,
CHANNEL_2,
CHANNEL_3
#endif
#if (QT_NUM_CHANNELS > 4u)
, CHANNEL_4,
CHANNEL_5,
CHANNEL_6,
CHANNEL_7
#endif
#if (QT_NUM_CHANNELS > 8u)
, CHANNEL_8,
CHANNEL_9,
CHANNEL_10,
CHANNEL_11
#endif
#if (QT_NUM_CHANNELS > 12u)
, CHANNEL_12,
CHANNEL_13,
CHANNEL_14,
CHANNEL_15
#endif
#if (QT_NUM_CHANNELS > 16u)
, CHANNEL_16,
CHANNEL_17,
CHANNEL_18,
CHANNEL_19,
CHANNEL_20,
CHANNEL_21,
CHANNEL_22,
CHANNEL_23
#endif
#if (QT_NUM_CHANNELS > 24u)
, CHANNEL_24,
CHANNEL_25,
CHANNEL_26,
CHANNEL_27,
CHANNEL_28,
CHANNEL_29,
CHANNEL_30,
CHANNEL_31
#endif
#if (QT_NUM_CHANNELS > 32u)
, CHANNEL_32,
CHANNEL_33,
CHANNEL_34,
CHANNEL_35,
CHANNEL_36,
CHANNEL_37,
CHANNEL_38,
CHANNEL_39,
CHANNEL_40,
CHANNEL_41,
CHANNEL_42,
CHANNEL_43,
CHANNEL_44,
CHANNEL_45,
CHANNEL_46,
CHANNEL_47,
CHANNEL_48,
CHANNEL_49,
CHANNEL_50,
CHANNEL_51,
CHANNEL_52,
CHANNEL_53,
CHANNEL_54,
CHANNEL_55
#endif
#if (QT_NUM_CHANNELS > 56u)
, CHANNEL_56,
CHANNEL_57,
CHANNEL_58,
CHANNEL_59,
CHANNEL_60,
CHANNEL_61,
CHANNEL_62,
CHANNEL_63
#endif
}
channel_t;
/**
* A sensor detection hysteresis value. This is expressed as a percentage of
* the sensor detection threshold.
*
* HYST_x = hysteresis value is x% of detection threshold value (rounded down).
* NB: a minimum value of 2 is used.
*
* Example: if detection threshold = 20, then:
* HYST_50 = 10 (50% of 20)
* HYST_25 = 5 (25% of 20)
* HYST_12_5 = 2 (12.5% of 20)
* HYST_6_25 = 2 (6.25% of 20 = 1, but value is hardlimited to 2)
*/
typedef enum tag_hysteresis_t
{
HYST_50,
HYST_25,
HYST_12_5,
HYST_6_25
}
hysteresis_t;
/**
* For rotors and sliders, the resolution of the reported angle or position.
*
* RES_x_BIT = rotor/slider reports x-bit values.
*
* Example: if slider resolution is RES_7_BIT, then reported positions are in
* the range 0..127.
*/
typedef enum tag_resolution_t
{
RES_1_BIT,
RES_2_BIT,
RES_3_BIT,
RES_4_BIT,
RES_5_BIT,
RES_6_BIT,
RES_7_BIT,
RES_8_BIT
}
resolution_t;
/**
* A sensor recalibration threshold. This is expressed as a percentage of the
* sensor detection threshold.
*
* RECAL_x = recalibration threshold is x% of detection threshold value
* (rounded down).
* NB: a minimum value of 4 is used.
*
* Example: if detection threshold = 40, then:
* RECAL_100 = 40 (100% of 40)
* RECAL_50 = 20 (50% of 40)
* RECAL_25 = 10 (25% of 40)
* RECAL_12_5 = 5 (12.5% of 40)
* RECAL_6_25 = 4 (6.25% of 40 = 2, but value is hardlimited to 4)
*/
typedef enum tag_recal_threshold_t
{
RECAL_100,
RECAL_50,
RECAL_25,
RECAL_12_5,
RECAL_6_25
}
recal_threshold_t;
//! The state of the library sensors.
typedef struct tag_qt_touch_status_t
{
/**
* The state (on/off) of the library sensors.
* Bit 'n' = state of sensor 'n'.
* Bit 0 = sensor_states[0] bit 0
* Bit 1 = sensor_states[0] bit 1
* ...
* Bit 7 = sensor_states[0] bit 7
* Bit 8 = sensor_states[1] bit 0
* Bit 9 = sensor_states[1] bit 1
* ... etc
* 0 = not in detect, 1 = in detect.
*/
uint8_t sensor_states[QT_NUM_SENSOR_STATE_BYTES];
/**
* Rotor angles or slider positions.
* These values are valid when sensor_states shows that the corresponding
* rotor or slider sensor is in detect.
*/
uint8_t rotor_slider_values[QT_MAX_NUM_ROTORS_SLIDERS];
}
qt_touch_status_t;
//! post processing configuration data that is received from the debug interface.
typedef struct tag_qt_touch_lib_config_data_t
{
//! Sensor recalibration threshold.
recal_threshold_t qt_recal_threshold;
//! Sensor detect integration (DI) limit.
uint8_t qt_di;
//! Sensor drift hold time.
uint8_t qt_drift_hold_time;
//! Sensor maximum on duration.
uint8_t qt_max_on_duration;
//! Sensor negative drift rate.
uint8_t qt_neg_drift_rate;
//! Sensor positive drift rate.
uint8_t qt_pos_drift_rate;
//! Positive recalibration delay.
uint8_t qt_pos_recal_delay;
}
qt_touch_lib_config_data_t;
//! measured touch data that is sent for the debugging and fine tunning.
typedef struct tag_qt_touch_lib_measure_data_t
{
//! measured signal on each channel.
uint16_t channel_signals[QT_NUM_CHANNELS];
//! reference signal for each channel.
uint16_t channel_references[QT_NUM_CHANNELS];
//! state of sensors.
qt_touch_status_t qt_touch_status;
}
qt_touch_lib_measure_data_t;
//! This will be used to get the library information from the library.
typedef struct qt_lib_sig_info_t
{
uint16_t lib_sig_lword;
uint16_t lib_sig_hword;
uint16_t library_version;
}
qt_lib_siginfo_t;
typedef struct tag_sensor_t
{
//! sensor state (calibrating, on, ...).
uint8_t state;
//! general purpose ctr: used for calibration, drifting, etc.
uint8_t general_counter;
//! DI ctr.
uint8_t ndil_counter;
//! sensor detection threshold.
uint8_t threshold;
/**
* sensor type, AKS group, positive recal flag, and hysteresis value
* bits 7..6: sensor type: 00: key
* 01: rotor
* 10: slider
* 11: reserved
* bits 5..3: AKS group (0..7): 0 = no AKS group
* bit 2 : positive recal flag
* bits 1..0: hysteresis
*/
uint8_t type_aks_pos_hyst;
/**
* sensor from and to channels
* keys: from channel = to channel
* rotors/sliders run between the from and to channels
* NB: only need to_channel for keys in rotors/sliders build
*/
uint8_t from_channel;
#ifdef _ROTOR_SLIDER_
uint8_t to_channel;
//! index into array of rotor/slider values.
uint8_t index;
#endif /* _ROTOR_SLIDER_ */
}
sensor_t;
/*----------------------------------------------------------------------------
extern variables
----------------------------------------------------------------------------*/
/**
* This configuration data structure parameters if needs to be changed will be
* changed in the qt_set_parameters function
*/
extern qt_touch_lib_config_data_t qt_config_data;
//! measurement data.
extern qt_touch_lib_measure_data_t qt_measure_data;
//! Get sensor delta values.
extern int16_t qt_get_sensor_delta (uint8_t sensor);
//! variable holding the status flags.
extern uint16_t lib_status_flags;
//! the library sensors.
extern sensor_t sensors[QT_NUM_CHANNELS];
//! timer period in msec.
extern uint16_t qt_measurement_period_msec;
/*----------------------------------------------------------------------------
api
----------------------------------------------------------------------------*/
/*! \brief This function is called after the library has made capacitive measurements,
* but before it has processed them. The user can use this hook to apply filter
* functions to the measured signal values.
*
*/
extern void (*qt_filter_callback) (void);
/*! \brief Get the library signature.
*
* \param qt_lib_siginfo_t: lib_sig_ptr=Pointer to the library signature structure
*/
extern void qt_get_library_sig (qt_lib_siginfo_t * lib_sig_ptr);
/*! \brief enable a key sensor.
*
* \param channel: which touch channel the key sensor uses
* \param aks_group: which AKS group (if any) the sensor is in
* \param detect_threshold: the sensor detection threshold
* \param detect_hysteresis: the sensor detection hysteresis value
*
* \note The sensor number corresponding to the key depends on the order in
* which sensors are enabled. The first sensor enabled is sensor 0, the
* second is sensor 1, and so on.
*
* The current state of the key (on or off) can be checked in
* qt_touch_status.sensor_states.
*/
extern void qt_enable_key (channel_t channel,
aks_group_t aks_group,
threshold_t detect_threshold,
hysteresis_t detect_hysteresis);
/*! \brief initialise touch sensing.
*
* \note Any sensors required must be enabled (using qt_enable_xxx()) before
* calling this function.
*
* This function calculates internal library variables and configures
* the touch channels, and must be called before qt_measure_sensors().
*/
#if defined( _QTOUCH_ )
#define qt_init_sensing( ) qt_init_sensing_with_burst( BURST_FUNC_NAME ,CALCULATE_MASKS)
extern void
qt_init_sensing_with_burst (void (*burst_function) (TOUCH_DATA_T mask_index),
void (*calculate_masks) (void));
extern void calc_masks (void);
#elif defined( _QMATRIX_ )
#define qt_init_sensing( ) qt_init_sensing_with_burst( )
extern void qt_init_sensing_with_burst ();
#endif
/*! \brief measure touch sensors.
*
* \param current_time_ms: the current time, in ms
* \return uint16_t: outputs the library status bits.
* \note This function performs a capacitive measurement on all enabled
* sensors. The measured signals for each sensor are then processed to
* check for user touches, releases, changes in rotor angle, changes in
* slider position, etc.
*
* The current state of all enabled sensors is reported in the
* qt_touch_status struct.
*
* Before calling this function, one or more sensors must have been
* enabled (using qt_enable_xxx()), and qt_init_sensing() must
* have been called.
*/
extern uint16_t qt_measure_sensors (uint16_t current_time_ms);
/*! \brief calibrate touch sensing.
*
* \note This function forces a calibration of all enabled sensors.
* This may be useful if, for instance, it is desired to globally
* recalibrate all sensors on a change in application operating mode.
*/
extern void qt_calibrate_sensing (void);
/*! \brief reset touch sensing.
*
* \note This function disables all enabled sensors, and returns all library
* variables (e.g., qt_di) to their default values.
*
* This may be useful if it is desired to dynamically reconfigure
* sensing. After calling this function, any required sensors must be
* re-enabled, and qt_init_sensing() must be called before
* qt_measure_channels() is called again.
*/
extern void qt_reset_sensing (void);
/*! \brief get the current delta on the specified sensor.
*
* \param sensor: sensor number for which to get the delta.
* \return int16_t: returns the delta on the specified sensor.
* \note This function is supplied as a functional replacement for the
* sensor_deltas[] array provided in earlier library versions.
*/
extern int16_t qt_get_sensor_delta (uint8_t sensor);
#ifdef _ROTOR_SLIDER_
/*! \brief enable a rotor sensor.
*
* \param from_channel: the first channel in the rotor sensor
* \param to_channel: the last channel in the rotor sensor
* \param aks_group: which AKS group (if any) the sensor is in
* \param detect_threshold: the sensor detection threshold
* \param detect_hysteresis: the sensor detection hysteresis value
* \param angle_resolution: the resolution of the reported angle value
* \param angle_hysteresis: the hysteresis of the reported angle value
* \note The sensor number corresponding to the rotor depends on the order in
* which sensors are enabled. The first sensor enabled is sensor 0, the
* second is sensor 1, and so on.
*
* The current state of the rotor (on or off) can be checked in
* qt_touch_status.sensor_states.
*
* The rotor value is in qt_touch_status.rotor_slider_values[]. Which
* array element is used depends on the order in which sensors are
* enabled. The first rotor or slider enabled will use
* and so on.
*
* The reported rotor value is valid when the rotor is on.
*/
extern void qt_enable_rotor (channel_t from_channel,
channel_t to_channel,
aks_group_t aks_group,
threshold_t detect_threshold,
hysteresis_t detect_hysteresis,
resolution_t angle_resolution,
uint8_t angle_hysteresis);
/*! \brief enable a slider sensor.
*
* \param from_channel: the first channel in the slider sensor
* \param to_channel: the last channel in the slider sensor
* \param aks_group: which AKS group (if any) the sensor is in
* \param detect_threshold: the sensor detection threshold
* \param detect_hysteresis: the sensor detection hysteresis value
* \param position_resolution: the resolution of the reported position value
* \param position_hysteresis: the hysteresis of the reported position value
* \note The sensor number corresponding to the slider depends on the order in
* which sensors are enabled. The first sensor enabled is sensor 0, the
* second is sensor 1, and so on.
*
* The current state of the slider (on or off) can be checked in
* qt_touch_status.sensor_states.
*
* The slider value is in qt_touch_status.rotor_slider_values[]. Which
* array element is used depends on the order in which sensors are
* enabled. The first rotor or slider enabled will use
* rotor_slider_values[0], the second will use rotor_slider_values[1],
* and so on.
*
* The reported slider value is valid when the rotor is on.
*/
extern void qt_enable_slider (channel_t from_channel,
channel_t to_channel,
aks_group_t aks_group,
threshold_t detect_threshold,
hysteresis_t detect_hysteresis,
resolution_t position_resolution,
uint8_t position_hysteresis);
#endif
#endif /* TOUCH_API_H */