text: /*! \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-2013 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
  
  /**
   * \defgroup group_common_services_qtouch QTouch Library for AVR & AVR32 devices
   *
   * This is the QTouch Library for AVR and AVR32 devices that consists of
   * one api header file(touch_api.h) and respective pre-compiled libraries.
   * All projects using these libraries must also provide the required header file(touch_qt_config.h)
   * used to configure the library.
   * For more information on the Qtouch Library, check www.atmel.com/qtouchlib.
   *
   * \{
   */
  
  /*----------------------------------------------------------------------------
                              nested include files
  ----------------------------------------------------------------------------*/
  #include "parts.h"
  
  #if (MEGA)
  #include "touch_config.h"
  #endif
  
  #if defined (__GNUC__) || defined (__ICCARM__) ||defined (__CC_ARM)
  #include <stdint.h>
  #endif
  
  #if !defined (__CC_ARM)
  #include <stdbool.h>
  #endif
  
  #include <stdlib.h>
  
  #if (MEGA)
  #ifndef MAKE_BUILD
  #ifdef _QMATRIX_
  #include "qm_asm_avr.h"
  #endif /* _QMATRIX_ */
  #endif /* MAKE_BUILD */
  #else /* MEGA */
  #ifndef MAKE_BUILD
  #ifdef _QMATRIX_
  #if !(defined(__AVR32__) || defined(__ICCAVR32__))
  #include "touch_qm_config.h"
  #else
  #include "touch_qm_config32.h"
  #endif
  #elif defined _QTOUCH_
  #include "touch_qt_config.h"
  #endif 
  #endif /* MAKE_BUILD*/
  
  #endif /* MEGA */
  
  #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.
    */
  #define FILL_OUT_Y_LINE_INFO( bit ) { bit, (TOUCH_DATA_T)(1u<<bit) }
  
  /**
    * 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.
    */
  #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.
    */
  #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.
    */
  #if !(MEGA)
  
  /**
    * Total ticks per msec.
    * TICKS_PER_MS = (CLK_FREQ/TIMER_PRESCALER)*(1/1000)
    */
  #define TICKS_PER_MS                500u
  
  /**
    * Initialization values for the Qtouch library parameters.
    */
  
  /**
    * Sensor detect integration (DI) limit.
    * Default value: 4.
    */
  #define DEF_QT_DI                      25u
  
  /**
    * Sensor negative drift rate.
    *
    * Units: 200ms
    * Default value: 20 (4 seconds per LSB).
    */
  #define DEF_QT_NEG_DRIFT_RATE          20	/* 4s per LSB */
  
  /**
    * Sensor positive drift rate.
    *
    * Units: 200ms
    * Default value: 5 (1 second per LSB).
    */
  #define DEF_QT_POS_DRIFT_RATE          5	/* 1s per LSB */
  
  /**
    * Sensor drift hold time.
    *
    * Units: 200ms
    * Default value: 20 (hold off drifting for 4 seconds after leaving detect).
    */
  #define DEF_QT_DRIFT_HOLD_TIME         20	/* 4s */
  
  /**
    * Sensor maximum on duration.
    *
    * Units: 200ms (e.g., 150 = recalibrate after 30s). 0 = no recalibration.
    * Default value: 0 (recalibration disabled).
    */
  #define DEF_QT_MAX_ON_DURATION         0	/* disabled */
  
  /**
    * Sensor recalibration threshold.
    *
    * Default: RECAL_50 (recalibration threshold = 50% of detection threshold).
    */
  #define DEF_QT_RECAL_THRESHOLD         RECAL_50	/* recal threshold = 50% of detect */
  
  /**
    * Positive recalibration delay.
    *
    * Default: 3
    */
  #define DEF_QT_POS_RECAL_DELAY         3u
  
  /**
    * WARNING! Do not edit below this line.
    */
  #endif
  /**
    * 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 (__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 = 0,
    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.
        */
  #if !(QT_MAX_NUM_ROTORS_SLIDERS == 0u)
    uint8_t rotor_slider_values[QT_MAX_NUM_ROTORS_SLIDERS];
  #endif
  }
  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;
  //! 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; // set in touch.c
  
  /*----------------------------------------------------------------------------
                                  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 */
  