/*
 * Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc.
 * Copyright 2016-2017 NXP
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o 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.
 *
 * o Neither the name of the copyright holder 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 HOLDER 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.
 */
#ifndef _NT_MATRIX_H_
#define _NT_MATRIX_H_

/**
 * \defgroup matrix Matrix Control
 * \ingroup controls
 *
 * Matrix enables the one or two finger position and gestures detection on the touchpad surface.
 *
 * The figure below shows a typical Matrix electrode placement.
 * \image html matrix.png "Matrix Electrodes"
 * \image latex matrix.png "Matrix Electrodes"
 *
 * \{
 */

#include "nt_controls.h"
#include "nt_types.h"

/** Matrix event types. */
enum nt_control_matrix_event {
    NT_MATRIX_RELEASE             = 1, /*!< Release event */
    NT_MATRIX_TOUCH               = 2, /*!< Touch event */
    NT_MATRIX_MOVEMENT            = 3, /*!< Movement event */
    NT_MATRIX_RELEASE_SET_GESTURE = 4, /*!< New unlock gesture is stored */
    NT_MATRIX_RELEASE_GET_GESTURE = 5, /*!< Stored unlock gesture is recognized */
    NT_MATRIX_GESTURE_TOO_LONG    = 6, /*!< Unlock gesture is too long */
    NT_MATRIX_GET_CONTROL_GESTURE = 7, /*!< Recognized control gesture */
};

/** Matrix control gesture event types. */
enum nt_control_matrix_control_gestures {
    NT_MATRIX_DOUBLE_TAP = 1, /*!< Double tap control gesture */
    NT_MATRIX_COVER      = 2, /*!< Covered control gesture */
    NT_MATRIX_SWIPE_UP   = 3, /*!< Swipe up control gesture */
    NT_MATRIX_SWIPE_DOWN = 4, /*!< Swipe down control gesture */
    NT_MATRIX_SWIPE_LEFT = 5, /*!< Swipe left control gesture */
    NT_MATRIX_SWIPE_RIGHT= 6, /*!< Swipe right control gesture */
};

/**
 *  The Matrix RAM structure used to store x and y axis data as group.
 */
typedef struct {
    uint16_t x;     /*!< x axis */
    uint16_t y;     /*!< y axis */
}nt_coordinates16_xy;

/**
 *  The Matrix RAM structure used to store x and y axis data of few points.
 */
typedef nt_coordinates16_xy nt_points16[2];

/**
 * Matrix event callback function pointer type.
 */
typedef void (* nt_control_matrix_callback)(const struct nt_control *control,
                                            enum nt_control_matrix_event event,
                                            nt_points16 *position,
                                            uint32_t index);

/**
 *  The Matrix RAM structure used to store x and y axis data as group.
 */
typedef struct {
    uint8_t x;     /*!< x axis */
    uint8_t y;     /*!< y axis */
}nt_coordinates8_xy;

/**
 *  The Matrix RAM structure used to store x and y axis data as group.
 */
typedef struct {
    uint64_t x;     /*!< x axis */
    uint64_t y;     /*!< y axis */
}nt_coordinates64_xy;

/**
 *  The Matrix RAM structure used to store x and y axis data of few points.
 */
typedef nt_coordinates64_xy nt_points64[2];

/**
 *  The main structure representing the Matrix Control.
 *
 *  An instance of this data type represents the Matrix Control. You must initialize all the members before
 *  registering the control in the system. This structure can be allocated in ROM.
 *
 */
struct nt_control_matrix {
    uint32_t double_tap_interval;      /*!< Max. time interval between taps for double tap. */
    uint16_t dissimilarity_max;        /*!< Maximum difference for unlock gesture recognition */
    uint8_t  touchpad_size_horizontal; /*!< Number of touchpad segments on x axis (horizontal segments). */
    uint8_t  touchpad_size_vertical;   /*!< Number of touchpad segments on y axis (vertical segments). */
    uint8_t  sensing_mode;             /*!< false value means touchpad is based on self-capacitance sensing mode,
                                            true value means touchpad is based on mutual-capacitance sensing mode */
    uint8_t  increase_resolution;      /*!< false value means default resolution, true value means that two the nearest
                                            touched electrodes create addition position value, it extends resolution
                                            according: new_resolution = 2 * default_resolution - 1 */
    uint8_t atan[5][5];
    nt_points64  gesture[];            /*!< Recorded gesture */
};

/** An interface structure, which contains pointers to the entry points of the Matrix
 *  algorithms. A pointer to this structure must be assigned to any
 *  instance of the nt_control_matrix, to define the control behavior. */
extern const struct nt_control_interface nt_control_matrix_interface;

/**
 * \defgroup matrix_api Matrix Control API
 * \ingroup matrix
 *
 * These functions can be used to set or get the Matrix control properties.
 *
 * A common example defition of the Matrix control for all source code examples is as follows:
 * \code
 *  // definition of electrode array used by control (more info in electrodes)
 *  const struct nt_electrode  * const control_0_electrodes[] = {&electrode_0, &electrode_1,&electrode_2, &electrode_3,
 *    &electrode_4,&electrode_5,&electrode_6,&electrode_7,&electrode_8,&electrode_9,&electrode_10,&electrode_11, NULL};
 *
 *  const struct nt_control_matrix matrix_params =
 *  {
 *     .double_tap_interval     = 500,
 *     .dissimilarity_max       = 5,
 *     .touchpad_size_horizontal= 6,
 *     .touchpad_size_vertical  = 6,
 *     .sensing_mode            = false,
 *     .increase_resolution     = true,
 *     .gesture                 ={{{0x0BBAAA8877543323,0x0122344666688999},{0x0000000000000000,0x0000000000000000}},
 *                                {{0x000BAA9887764333,0x0009988766543321},{0x0000000000000000,0x0000000000000000}},
 *                                {{0x0000000022233578,0x0000000054332222},{0x0000000000000000,0x0000000000000000}},
 *                                {{0x0AAAAAAAAAA98887,0x0123456789888766},{0x0000000000000000,0x0000000000000000}}},
 *
 *  };
 *
 *  // Definition of matrix control
 *  const struct nt_control my_matrix_control =
 *  {
 *    .interface = &nt_control_matrix_control_interface,
 *    .electrodes = control_0_electrodes,
 *    .control_params.matrix = matrix_params,
 *  };
 *
 * \endcode
 * \{
 */

#ifdef __cplusplus
extern "C" {
#endif

/**
 * \brief Registers the Matrix event handler function.
 * \param control  Pointer to the control.
 * \param callback Address of function to be invoked.
 * \return none
 *
 * Register the specified callback function as the KeyPad event handler.
 * If the callback parameter is NULL, the callback is disabled.
 * Example:
 * \code
 *
 *  //Create the callback function for matrix
 *  static void my_matrix_cb(const struct nt_control *control,
 *                           enum nt_control_matrix_event event,
 *                           nt_points16 *position,
 *                           uint32_t index)
 *  {
 *    (void)control;
 *     char* event_names[] =
 *     {
 *      "NT_MATRIX_RELEASE            ",
 *      "NT_MATRIX_TOUCH              ",
 *      "NT_MATRIX_MOVEMENT           ",
 *      "NT_MATRIX_RELEASE_SET_GESTURE",
 *      "NT_MATRIX_RELEASE_GET_GESTURE",
 *      "NT_MATRIX_GESTURE_TOO_LONG   ",
 *      "NT_MATRIX_GET_CONTROL_GESTURE",
 *      };
 *
 *    printf("New matrix control event %s on key: %d.", event_names[event], index);
 *  }
 *
 *  // register the callback function for matrix
 *  nt_control_matrix_register_touch_callback(&my_matrix_control, my_matrix_touch_cb);
 * \endcode
 */
void nt_control_matrix_register_callback(const struct nt_control *control,
                                         nt_control_matrix_callback callback);


/** \} */ /* end of matrix_api group */
/** \} */ /* end of matrix group*/
#endif
