/** * @file STMPE610.c */ /********************* * INCLUDES *********************/ #include "stmpe610.h" #include "esp_system.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #include "tp_spi.h" #include /********************* * DEFINES *********************/ #define TAG "STMPE610: " /********************** * TYPEDEFS **********************/ /********************** * STATIC PROTOTYPES **********************/ static void write_8bit_reg(uint8_t reg, uint8_t val); static uint16_t read_16bit_reg(uint8_t reg); static uint8_t read_8bit_reg(uint8_t reg); static void read_data(int16_t *x, int16_t *y, uint8_t *z); static bool buffer_empty(); static void adjust_data(int16_t * x, int16_t * y); /********************** * STATIC VARIABLES **********************/ /********************** * MACROS **********************/ /********************** * GLOBAL FUNCTIONS **********************/ /** * Initialize the STMPE610 */ void stmpe610_init(void) { uint8_t u8; uint16_t u16; LV_LOG_INFO(TAG, "Initialization."); // Get the initial SPI configuration //u8 = read_8bit_reg(STMPE_SPI_CFG); //LV_LOG_INFO(TAG, "SPI_CFG = 0x%x", u8); // Attempt a software reset write_8bit_reg(STMPE_SYS_CTRL1, STMPE_SYS_CTRL1_RESET); vTaskDelay(10 / portTICK_RATE_MS); // Reset the SPI configuration, making sure auto-increment is set u8 = read_8bit_reg(STMPE_SPI_CFG); write_8bit_reg(STMPE_SPI_CFG, u8 | STMPE_SPI_CFG_AA); u8 = read_8bit_reg(STMPE_SPI_CFG); LV_LOG_INFO(TAG, "SPI_CFG = 0x%x", u8); // Verify SPI communication u16 = read_16bit_reg(STMPE_CHIP_ID); if (u16 != 0x811) { LV_LOG_ERROR(TAG, "Incorrect version: 0x%x", u16); } write_8bit_reg(STMPE_SYS_CTRL2, 0x00); // Disable clocks write_8bit_reg(STMPE_TSC_CTRL, 0); // Disable to allow writing write_8bit_reg(STMPE_TSC_CTRL, STEMP_TSC_CTRL_TRACK_0 | STMPE_TSC_CTRL_XYZ | STMPE_TSC_CTRL_EN); write_8bit_reg(STMPE_TSC_CFG, STMPE_TSC_CFG_4SAMPLE | STMPE_TSC_CFG_DELAY_1MS | STMPE_TSC_CFG_SETTLE_1MS); write_8bit_reg(STMPE_TSC_FRACTION_Z, 0x7); write_8bit_reg(STMPE_TSC_I_DRIVE, STMPE_TSC_I_DRIVE_50MA); write_8bit_reg(STMPE_SYS_CTRL2, 0x04); // GPIO clock off, TSC clock on, ADC clock on write_8bit_reg(STMPE_ADC_CTRL1, STMPE_ADC_CTRL1_12BIT | STMPE_ADC_CTRL1_80CLK); write_8bit_reg(STMPE_ADC_CTRL2, STMPE_ADC_CTRL2_3_25MHZ); write_8bit_reg(STMPE_GPIO_ALT_FUNCT, 0x00); // Disable GPIO write_8bit_reg(STMPE_FIFO_TH, 1); // Set FIFO threshold write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); // Assert FIFO reset write_8bit_reg(STMPE_FIFO_STA, 0); // Deassert FIFO reset write_8bit_reg(STMPE_INT_EN, 0x00); // No interrupts write_8bit_reg(STMPE_INT_STA, 0xFF); // reset all ints } /** * Get the current position and state of the touchpad * @param data store the read data here * @return false: because no more data to be read */ bool stmpe610_read(lv_indev_drv_t * drv, lv_indev_data_t * data) { static int16_t last_x = 0; static int16_t last_y = 0; bool valid = true; int c = 0; int16_t x = 0; int16_t y = 0; uint8_t z; if ((read_8bit_reg(STMPE_TSC_CTRL) & STMPE_TSC_TOUCHED) == STMPE_TSC_TOUCHED) { // Making sure that we read all data and return the latest point while (!buffer_empty()) { read_data(&x, &y, &z); c++; } if (c > 0) { //LV_LOG_INFO(TAG, "%d: %d %d %d", c, x, y, z); adjust_data(&x, &y); last_x = x; last_y = y; //LV_LOG_INFO(TAG, " ==> %d %d", x, y); } z = read_8bit_reg(STMPE_INT_STA); // Clear interrupts z = read_8bit_reg(STMPE_FIFO_STA); if ((z & STMPE_FIFO_STA_OFLOW) == STMPE_FIFO_STA_OFLOW) { // Clear the FIFO if we discover an overflow write_8bit_reg(STMPE_FIFO_STA, STMPE_FIFO_STA_RESET); write_8bit_reg(STMPE_FIFO_STA, 0); // unreset LV_LOG_ERROR(TAG, "Fifo overflow"); } } if (c == 0) { x = last_x; y = last_y; valid = false; } data->point.x = (int16_t) x; data->point.y = (int16_t) y; data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR; return false; } /********************** * STATIC FUNCTIONS **********************/ static void write_8bit_reg(uint8_t reg, uint8_t val) { uint8_t data_send[2]; data_send[0] = reg; data_send[1] = val; tp_spi_write_reg(data_send, 2); } static uint16_t read_16bit_reg(uint8_t reg) { uint8_t data_recv[2]; tp_spi_read_reg(0x80 | reg, data_recv, 2); return data_recv[0] << 8 | data_recv[1]; } static uint8_t read_8bit_reg(uint8_t reg) { uint8_t data_recv; tp_spi_read_reg(0x80 | reg, &data_recv, 1); return data_recv; } static void read_data(int16_t *x, int16_t *y, uint8_t *z) { *x = read_16bit_reg(STMPE_TSC_DATA_X); *y = read_16bit_reg(STMPE_TSC_DATA_Y); *z = read_8bit_reg(STMPE_TSC_DATA_Z); } static bool buffer_empty() { return ((read_8bit_reg(STMPE_FIFO_STA) & STMPE_FIFO_STA_EMPTY) == STMPE_FIFO_STA_EMPTY); } static void adjust_data(int16_t * x, int16_t * y) { #if STMPE610_XY_SWAP != 0 int16_t swap_tmp; swap_tmp = *x; *x = *y; *y = swap_tmp; #endif if((*x) > STMPE610_X_MIN)(*x) -= STMPE610_X_MIN; else(*x) = 0; if((*y) > STMPE610_Y_MIN)(*y) -= STMPE610_Y_MIN; else(*y) = 0; (*x) = (uint32_t)((uint32_t)(*x) * LV_HOR_RES) / (STMPE610_X_MAX - STMPE610_X_MIN); (*y) = (uint32_t)((uint32_t)(*y) * LV_VER_RES) / (STMPE610_Y_MAX - STMPE610_Y_MIN); #if STMPE610_X_INV != 0 (*x) = LV_HOR_RES - (*x); #endif #if STMPE610_Y_INV != 0 (*y) = LV_VER_RES - (*y); #endif }