Capacitive Touch Screen (GT911) for SKR SE BX (#21843)
Co-authored-by: Msq001 <alansayyeah@gmail.com> Co-authored-by: Scott Lahteine <github@thinkyhead.com>
This commit is contained in:
		
				
					committed by
					
						
						Scott Lahteine
					
				
			
			
				
	
			
			
			
						parent
						
							f3e199fcd2
						
					
				
				
					commit
					ac11c689f7
				
			@@ -22,7 +22,7 @@
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
 | 
			
		||||
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
 | 
			
		||||
 | 
			
		||||
#include "xpt2046.h"
 | 
			
		||||
#include <SPI.h>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										202
									
								
								Marlin/src/HAL/STM32/tft/gt911.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								Marlin/src/HAL/STM32/tft/gt911.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | 
			
		||||
 *
 | 
			
		||||
 * Based on Sprinter and grbl.
 | 
			
		||||
 * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if ENABLED(TFT_TOUCH_DEVICE_GT911)
 | 
			
		||||
 | 
			
		||||
#include "gt911.h"
 | 
			
		||||
#include "pinconfig.h"
 | 
			
		||||
 | 
			
		||||
SW_IIC::SW_IIC(uint16_t sda, uint16_t scl) {
 | 
			
		||||
  scl_pin = scl;
 | 
			
		||||
  sda_pin = sda;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Software I2C hardware io init
 | 
			
		||||
void SW_IIC::init() {
 | 
			
		||||
  OUT_WRITE(scl_pin, HIGH);
 | 
			
		||||
  OUT_WRITE(sda_pin, HIGH);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Software I2C start signal
 | 
			
		||||
void SW_IIC::start() {
 | 
			
		||||
  write_sda(HIGH); // SDA = 1
 | 
			
		||||
  write_scl(HIGH); // SCL = 1
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
  write_sda(LOW); // SDA = 0
 | 
			
		||||
  iic_delay(1);
 | 
			
		||||
  write_scl(LOW); // SCL = 0  // keep SCL low, avoid false stop caused by level jump caused by SDA switching IN/OUT
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Software I2C stop signal
 | 
			
		||||
void SW_IIC::stop() {
 | 
			
		||||
  write_scl(LOW); // SCL = 0
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
  write_sda(LOW); // SDA = 0
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
  write_scl(HIGH); // SCL = 1
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
  write_sda(HIGH); // SDA = 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Software I2C sends ACK or NACK signal
 | 
			
		||||
void SW_IIC::send_ack(bool ack) {
 | 
			
		||||
  write_sda(ack ? LOW : HIGH); // SDA = !ack
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
  write_scl(HIGH); // SCL = 1
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
  write_scl(LOW); // SCL = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Software I2C read ACK or NACK signal
 | 
			
		||||
bool SW_IIC::read_ack() {
 | 
			
		||||
  bool error = 0;
 | 
			
		||||
  set_sda_in();
 | 
			
		||||
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
 | 
			
		||||
  write_scl(HIGH); // SCL = 1
 | 
			
		||||
  error = read_sda();
 | 
			
		||||
 | 
			
		||||
  iic_delay(2);
 | 
			
		||||
 | 
			
		||||
  write_scl(LOW);  // SCL = 0
 | 
			
		||||
 | 
			
		||||
  set_sda_out();
 | 
			
		||||
  return error;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SW_IIC::send_byte(uint8_t txd) {
 | 
			
		||||
  LOOP_L_N(i, 8) {
 | 
			
		||||
    write_sda(txd & 0x80); // write data bit
 | 
			
		||||
    txd <<= 1;
 | 
			
		||||
    iic_delay(1);
 | 
			
		||||
    write_scl(HIGH); // SCL = 1
 | 
			
		||||
    iic_delay(2);
 | 
			
		||||
    write_scl(LOW); // SCL = 0
 | 
			
		||||
    iic_delay(1);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  read_ack();  // wait ack
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t SW_IIC::read_byte(bool ack) {
 | 
			
		||||
  uint8_t data = 0;
 | 
			
		||||
 | 
			
		||||
  set_sda_in();
 | 
			
		||||
  LOOP_L_N(i, 8) {
 | 
			
		||||
    write_scl(HIGH); // SCL = 1
 | 
			
		||||
    iic_delay(1);
 | 
			
		||||
    data <<= 1;
 | 
			
		||||
    if (read_sda()) data++;
 | 
			
		||||
    write_scl(LOW); // SCL = 0
 | 
			
		||||
    iic_delay(2);
 | 
			
		||||
  }
 | 
			
		||||
  set_sda_out();
 | 
			
		||||
 | 
			
		||||
  send_ack(ack);
 | 
			
		||||
 | 
			
		||||
  return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GT911_REG_MAP GT911::reg;
 | 
			
		||||
SW_IIC GT911::sw_iic = SW_IIC(GT911_SW_I2C_SDA_PIN, GT911_SW_I2C_SCL_PIN);
 | 
			
		||||
 | 
			
		||||
void GT911::write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len) {
 | 
			
		||||
  sw_iic.start();
 | 
			
		||||
  sw_iic.send_byte(gt911_slave_address);  // Set IIC Slave address
 | 
			
		||||
  LOOP_L_N(i, reg_len) {  // Set reg address
 | 
			
		||||
    uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
 | 
			
		||||
    sw_iic.send_byte(r);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  LOOP_L_N(i, w_len) {  // Write data to reg
 | 
			
		||||
    sw_iic.send_byte(w_data[i]);
 | 
			
		||||
  }
 | 
			
		||||
  sw_iic.stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GT911::read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len) {
 | 
			
		||||
  sw_iic.start();
 | 
			
		||||
  sw_iic.send_byte(gt911_slave_address);  // Set IIC Slave address
 | 
			
		||||
  LOOP_L_N(i, reg_len) {  // Set reg address
 | 
			
		||||
    uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
 | 
			
		||||
    sw_iic.send_byte(r);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  sw_iic.start();
 | 
			
		||||
  sw_iic.send_byte(gt911_slave_address + 1);  // Set read mode
 | 
			
		||||
 | 
			
		||||
  LOOP_L_N(i, r_len) {
 | 
			
		||||
    r_data[i] = sw_iic.read_byte(1);  // Read data from reg
 | 
			
		||||
  }
 | 
			
		||||
  sw_iic.stop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GT911::Init() {
 | 
			
		||||
  OUT_WRITE(GT911_RST_PIN, LOW);
 | 
			
		||||
  OUT_WRITE(GT911_INT_PIN, LOW);
 | 
			
		||||
  delay(20);
 | 
			
		||||
  WRITE(GT911_RST_PIN, HIGH);
 | 
			
		||||
  SET_INPUT(GT911_INT_PIN);
 | 
			
		||||
 | 
			
		||||
  sw_iic.init();
 | 
			
		||||
 | 
			
		||||
  uint8_t clear_reg = 0x0000;
 | 
			
		||||
  write_reg(0x814E, 2, &clear_reg, 2); // Reset to 0 for start
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) {
 | 
			
		||||
  read_reg(0x814E, 2, ®.REG.status, 1);
 | 
			
		||||
 | 
			
		||||
  if (reg.REG.status & 0x80) {
 | 
			
		||||
    uint8_t clear_reg = 0x00;
 | 
			
		||||
    write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
 | 
			
		||||
    read_reg(0x8150, 2, reg.map + 2, 8 * (reg.REG.status & 0x0F));
 | 
			
		||||
 | 
			
		||||
    // First touch point
 | 
			
		||||
    *x = ((reg.REG.point[0].xh & 0x0F) << 8) | reg.REG.point[0].xl;
 | 
			
		||||
    *y = ((reg.REG.point[0].yh & 0x0F) << 8) | reg.REG.point[0].yl;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GT911::getPoint(int16_t *x, int16_t *y) {
 | 
			
		||||
  static bool touched = 0;
 | 
			
		||||
  static int16_t read_x = 0, read_y = 0;
 | 
			
		||||
  static millis_t next_time = 0;
 | 
			
		||||
 | 
			
		||||
  if (ELAPSED(millis(), next_time)) {
 | 
			
		||||
    touched = getFirstTouchPoint(&read_x, &read_y);
 | 
			
		||||
    next_time = millis() + 20;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  *x = read_x;
 | 
			
		||||
  *y = read_y;
 | 
			
		||||
  return touched;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TFT_TOUCH_DEVICE_GT911
 | 
			
		||||
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
 | 
			
		||||
							
								
								
									
										120
									
								
								Marlin/src/HAL/STM32/tft/gt911.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								Marlin/src/HAL/STM32/tft/gt911.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Marlin 3D Printer Firmware
 | 
			
		||||
 * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
 | 
			
		||||
 *
 | 
			
		||||
 * Based on Sprinter and grbl.
 | 
			
		||||
 * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#define GT911_SLAVE_ADDRESS   0xBA
 | 
			
		||||
 | 
			
		||||
#if !PIN_EXISTS(GT911_RST)
 | 
			
		||||
  #error "GT911_RST_PIN is not defined."
 | 
			
		||||
#elif !PIN_EXISTS(GT911_INT)
 | 
			
		||||
  #error "GT911_INT_PIN is not defined."
 | 
			
		||||
#elif !PIN_EXISTS(GT911_SW_I2C_SCL)
 | 
			
		||||
  #error "GT911_SW_I2C_SCL_PIN is not defined."
 | 
			
		||||
#elif !PIN_EXISTS(GT911_SW_I2C_SDA)
 | 
			
		||||
  #error "GT911_SW_I2C_SDA_PIN is not defined."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class SW_IIC {
 | 
			
		||||
  private:
 | 
			
		||||
    uint16_t scl_pin;
 | 
			
		||||
    uint16_t sda_pin;
 | 
			
		||||
    void write_scl(bool level)
 | 
			
		||||
    {
 | 
			
		||||
      WRITE(scl_pin, level);
 | 
			
		||||
    }
 | 
			
		||||
    void write_sda(bool level)
 | 
			
		||||
    {
 | 
			
		||||
      WRITE(sda_pin, level);
 | 
			
		||||
    }
 | 
			
		||||
    bool read_sda()
 | 
			
		||||
    {
 | 
			
		||||
      return READ(sda_pin);
 | 
			
		||||
    }
 | 
			
		||||
    void set_sda_out()
 | 
			
		||||
    {
 | 
			
		||||
      SET_OUTPUT(sda_pin);
 | 
			
		||||
    }
 | 
			
		||||
    void set_sda_in()
 | 
			
		||||
    {
 | 
			
		||||
      SET_INPUT_PULLUP(sda_pin);
 | 
			
		||||
    }
 | 
			
		||||
    static void iic_delay(uint8_t t)
 | 
			
		||||
    {
 | 
			
		||||
      delayMicroseconds(t);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    SW_IIC(uint16_t sda, uint16_t scl);
 | 
			
		||||
    // setSCL/SDA have to be called before begin()
 | 
			
		||||
    void setSCL(uint16_t scl)
 | 
			
		||||
    {
 | 
			
		||||
      scl_pin = scl;
 | 
			
		||||
    };
 | 
			
		||||
    void setSDA(uint16_t sda)
 | 
			
		||||
    {
 | 
			
		||||
      sda_pin = sda;
 | 
			
		||||
    };
 | 
			
		||||
    void init();                // Initialize the IO port of IIC
 | 
			
		||||
    void start();               // Send IIC start signal
 | 
			
		||||
    void stop();                // Send IIC stop signal
 | 
			
		||||
    void send_byte(uint8_t txd); // IIC sends a byte
 | 
			
		||||
    uint8_t read_byte(bool ack); // IIC reads a byte
 | 
			
		||||
    void send_ack(bool ack);            // IIC sends ACK or NACK signal
 | 
			
		||||
    bool read_ack();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct __attribute__((__packed__)) {
 | 
			
		||||
  uint8_t xl;
 | 
			
		||||
  uint8_t xh;
 | 
			
		||||
  uint8_t yl;
 | 
			
		||||
  uint8_t yh;
 | 
			
		||||
  uint8_t sizel;
 | 
			
		||||
  uint8_t sizeh;
 | 
			
		||||
  uint8_t reserved;
 | 
			
		||||
  uint8_t track_id;
 | 
			
		||||
} GT911_POINT;
 | 
			
		||||
 | 
			
		||||
typedef union __attribute__((__packed__)) {
 | 
			
		||||
  uint8_t map[42];
 | 
			
		||||
  struct {
 | 
			
		||||
    uint8_t status;    // 0x814E
 | 
			
		||||
    uint8_t track_id;  // 0x814F
 | 
			
		||||
 | 
			
		||||
    GT911_POINT point[5]; // [0]:0x8150 - 0x8157 / [1]:0x8158 - 0x815F / [2]:0x8160 - 0x8167 / [3]:0x8168 - 0x816F / [4]:0x8170 - 0x8177
 | 
			
		||||
 } REG;
 | 
			
		||||
} GT911_REG_MAP;
 | 
			
		||||
 | 
			
		||||
class GT911 {
 | 
			
		||||
  private:
 | 
			
		||||
    static const uint8_t gt911_slave_address = GT911_SLAVE_ADDRESS;
 | 
			
		||||
    static GT911_REG_MAP reg;
 | 
			
		||||
    static SW_IIC sw_iic;
 | 
			
		||||
    static void write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len);
 | 
			
		||||
    static void read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len);
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    static void Init();
 | 
			
		||||
    static bool getFirstTouchPoint(int16_t *x, int16_t *y);
 | 
			
		||||
    static bool getPoint(int16_t *x, int16_t *y);
 | 
			
		||||
};
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
 | 
			
		||||
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
 | 
			
		||||
 | 
			
		||||
#include "xpt2046.h"
 | 
			
		||||
#include "pinconfig.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@
 | 
			
		||||
 | 
			
		||||
#include "../../../inc/MarlinConfig.h"
 | 
			
		||||
 | 
			
		||||
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
 | 
			
		||||
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
 | 
			
		||||
 | 
			
		||||
#include "xpt2046.h"
 | 
			
		||||
#include <SPI.h>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user