/*
 * FT6336U Capacitive Touch Screen Driver
 * I2C Interface
 * 
 * Based on FT6336U datasheet for 4.0" TFT Module
 */

#ifndef FT6336U_H
#define FT6336U_H

#include "pico/stdlib.h"
#include "hardware/i2c.h"

#ifdef __cplusplus
extern "C" {
#endif

// FT6336U I2C Address
#define FT6336U_ADDR 0x38

// FT6336U Registers
#define FT6336U_REG_DEVICE_MODE     0x00
#define FT6336U_REG_GESTURE_ID      0x01
#define FT6336U_REG_TD_STATUS       0x02  // Number of touch points

#define FT6336U_REG_P1_XH           0x03
#define FT6336U_REG_P1_XL           0x04
#define FT6336U_REG_P1_YH           0x05
#define FT6336U_REG_P1_YL           0x06
#define FT6336U_REG_P1_WEIGHT       0x07
#define FT6336U_REG_P1_MISC         0x08

#define FT6336U_REG_P2_XH           0x09
#define FT6336U_REG_P2_XL           0x0A
#define FT6336U_REG_P2_YH           0x0B
#define FT6336U_REG_P2_YL           0x0C
#define FT6336U_REG_P2_WEIGHT       0x0D
#define FT6336U_REG_P2_MISC         0x0E

// Gesture parameter registers (for tuning gesture detection)
#define FT6336U_REG_RADIAN_VALUE        0x91  // Gesture angle threshold
#define FT6336U_REG_OFFSET_LEFT_RIGHT   0x92  // Horizontal gesture offset
#define FT6336U_REG_OFFSET_UP_DOWN      0x93  // Vertical gesture offset
#define FT6336U_REG_DISTANCE_LEFT_RIGHT 0x94  // Horizontal distance threshold
#define FT6336U_REG_DISTANCE_UP_DOWN    0x95  // Vertical distance threshold
#define FT6336U_REG_DISTANCE_ZOOM       0x96  // Zoom gesture distance

#define FT6336U_REG_CTRL            0x86  // Control mode register
#define FT6336U_REG_CHIPID          0xA3  // Chip ID (should read 0x64)
#define FT6336U_REG_G_MODE          0xA4  // Interrupt mode (polling or trigger)
#define FT6336U_REG_POWER_MODE      0xA5  // Power mode
#define FT6336U_REG_FIRMID          0xA6
#define FT6336U_REG_VENDID          0xA8

// CTRL_MODE values
#define FT6336U_CTRL_KEEP_ACTIVE_MODE       0x00  // Stay in active mode (better for interrupts)
#define FT6336U_CTRL_SWITCH_TO_MONITOR      0x01  // Auto-enter monitor mode (lower power)

// G_MODE values
#define FT6336U_G_MODE_POLLING      0x00
#define FT6336U_G_MODE_TRIGGER      0x01

// Touch event types
#define FT6336U_EVENT_PRESS_DOWN    0x00
#define FT6336U_EVENT_LIFT_UP       0x01
#define FT6336U_EVENT_CONTACT       0x02
#define FT6336U_EVENT_NO_EVENT      0x03

// Maximum touch points supported
#define FT6336U_MAX_TOUCH_POINTS    2

// Touch point structure
typedef struct {
    uint16_t x;
    uint16_t y;
    uint8_t event;    // Press down, lift up, contact, no event
    uint8_t id;       // Touch point ID
    uint8_t weight;   // Touch pressure/area (0-255)
    uint8_t misc;     // Touch area (0-15, upper nibble of MISC register)
} ft6336u_touch_point_t;

// Touch data structure
typedef struct {
    uint8_t touch_count;
    ft6336u_touch_point_t points[FT6336U_MAX_TOUCH_POINTS];
    uint8_t gesture;
} ft6336u_touch_data_t;

// Configuration structure
typedef struct {
    i2c_inst_t *i2c;
    uint gpio_sda;
    uint gpio_scl;
    uint gpio_rst;
    uint gpio_int;
    uint16_t screen_width;
    uint16_t screen_height;
    bool swap_xy;          // Swap X and Y coordinates
    bool invert_x;         // Invert X coordinate
    bool invert_y;         // Invert Y coordinate
} ft6336u_config_t;

/**
 * Initialize the FT6336U touch controller
 * @param config Configuration structure
 * @return true if successful, false otherwise
 */
bool ft6336u_init(const ft6336u_config_t *config);

/**
 * Read touch data from the controller
 * @param data Pointer to touch data structure to fill
 * @return true if successful, false otherwise
 */
bool ft6336u_read_touch(ft6336u_touch_data_t *data);

/**
 * Check if screen is currently being touched
 * @return true if touched, false otherwise
 */
bool ft6336u_is_touched(void);

/**
 * Get the chip ID (should be 0x64 for FT6336U)
 * @return Chip ID or 0xFF on error
 */
uint8_t ft6336u_get_chip_id(void);

/**
 * Get the firmware version
 * @return Firmware version or 0xFF on error
 */
uint8_t ft6336u_get_firmware_version(void);

/**
 * Set up interrupt on INT pin
 * @param callback Function to call on touch interrupt
 */
void ft6336u_set_interrupt_callback(void (*callback)(uint gpio, uint32_t events));

/**
 * Test I2C bus communication
 * @return true if I2C is responding correctly
 */
bool ft6336u_test_i2c(void);

/**
 * Set G_MODE register (polling vs trigger mode)
 * @param mode 0 for polling mode, 1 for trigger mode
 * @return true if successful
 */
bool ft6336u_set_g_mode(uint8_t mode);

/**
 * Get current G_MODE setting
 * @return Current G_MODE value or 0xFF on error
 */
uint8_t ft6336u_get_g_mode(void);

/**
 * Get current power mode
 * @return Current power mode or 0xFF on error  
 */
uint8_t ft6336u_get_power_mode(void);

/**
 * Set CTRL mode (active vs monitor mode)
 * @param mode FT6336U_CTRL_KEEP_ACTIVE_MODE or FT6336U_CTRL_SWITCH_TO_MONITOR
 * @return true if successful
 */
bool ft6336u_set_ctrl_mode(uint8_t mode);

/**
 * Get current CTRL mode
 * @return Current CTRL mode or 0xFF on error
 */
uint8_t ft6336u_get_ctrl_mode(void);

/**
 * Read the INT pin state directly
 * @return true if HIGH (no touch), false if LOW (touch active)
 * Note: In trigger mode, INT pin is active LOW
 */
bool ft6336u_get_int_pin_state(void);

// Gesture parameter configuration (for tuning gesture detection)
/**
 * Get/Set radian value (gesture angle threshold)
 */
uint8_t ft6336u_get_radian_value(void);
bool ft6336u_set_radian_value(uint8_t value);

/**
 * Get/Set horizontal gesture offset
 */
uint8_t ft6336u_get_offset_left_right(void);
bool ft6336u_set_offset_left_right(uint8_t value);

/**
 * Get/Set vertical gesture offset
 */
uint8_t ft6336u_get_offset_up_down(void);
bool ft6336u_set_offset_up_down(uint8_t value);

/**
 * Get/Set horizontal distance threshold for gestures
 */
uint8_t ft6336u_get_distance_left_right(void);
bool ft6336u_set_distance_left_right(uint8_t value);

/**
 * Get/Set vertical distance threshold for gestures
 */
uint8_t ft6336u_get_distance_up_down(void);
bool ft6336u_set_distance_up_down(uint8_t value);

/**
 * Get/Set zoom gesture distance threshold
 */
uint8_t ft6336u_get_distance_zoom(void);
bool ft6336u_set_distance_zoom(uint8_t value);

#ifdef __cplusplus
}
#endif

#endif // FT6336U_H
