Skip to content

Commit ac11c68

Browse files
bigtreetechMsq001thinkyhead
committed
Capacitive Touch Screen (GT911) for SKR SE BX (#21843)
Co-authored-by: Msq001 <[email protected]> Co-authored-by: Scott Lahteine <[email protected]>
1 parent f3e199f commit ac11c68

File tree

14 files changed

+425
-62
lines changed

14 files changed

+425
-62
lines changed

Marlin/Configuration.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2571,7 +2571,7 @@
25712571
//#define DWIN_CREALITY_LCD
25722572

25732573
//
2574-
// ADS7843/XPT2046 ADC Touchscreen such as ILI9341 2.8
2574+
// Touch Screen Settings
25752575
//
25762576
//#define TOUCH_SCREEN
25772577
#if ENABLED(TOUCH_SCREEN)

Marlin/src/HAL/LPC1768/tft/xpt2046.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
#include "../../../inc/MarlinConfig.h"
2424

25-
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
25+
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
2626

2727
#include "xpt2046.h"
2828
#include <SPI.h>

Marlin/src/HAL/STM32/tft/gt911.cpp

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
/**
2+
* Marlin 3D Printer Firmware
3+
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4+
*
5+
* Based on Sprinter and grbl.
6+
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
23+
24+
#include "../../../inc/MarlinConfig.h"
25+
26+
#if ENABLED(TFT_TOUCH_DEVICE_GT911)
27+
28+
#include "gt911.h"
29+
#include "pinconfig.h"
30+
31+
SW_IIC::SW_IIC(uint16_t sda, uint16_t scl) {
32+
scl_pin = scl;
33+
sda_pin = sda;
34+
}
35+
36+
// Software I2C hardware io init
37+
void SW_IIC::init() {
38+
OUT_WRITE(scl_pin, HIGH);
39+
OUT_WRITE(sda_pin, HIGH);
40+
}
41+
42+
// Software I2C start signal
43+
void SW_IIC::start() {
44+
write_sda(HIGH); // SDA = 1
45+
write_scl(HIGH); // SCL = 1
46+
iic_delay(2);
47+
write_sda(LOW); // SDA = 0
48+
iic_delay(1);
49+
write_scl(LOW); // SCL = 0 // keep SCL low, avoid false stop caused by level jump caused by SDA switching IN/OUT
50+
}
51+
52+
// Software I2C stop signal
53+
void SW_IIC::stop() {
54+
write_scl(LOW); // SCL = 0
55+
iic_delay(2);
56+
write_sda(LOW); // SDA = 0
57+
iic_delay(2);
58+
write_scl(HIGH); // SCL = 1
59+
iic_delay(2);
60+
write_sda(HIGH); // SDA = 1
61+
}
62+
63+
// Software I2C sends ACK or NACK signal
64+
void SW_IIC::send_ack(bool ack) {
65+
write_sda(ack ? LOW : HIGH); // SDA = !ack
66+
iic_delay(2);
67+
write_scl(HIGH); // SCL = 1
68+
iic_delay(2);
69+
write_scl(LOW); // SCL = 0
70+
}
71+
72+
// Software I2C read ACK or NACK signal
73+
bool SW_IIC::read_ack() {
74+
bool error = 0;
75+
set_sda_in();
76+
77+
iic_delay(2);
78+
79+
write_scl(HIGH); // SCL = 1
80+
error = read_sda();
81+
82+
iic_delay(2);
83+
84+
write_scl(LOW); // SCL = 0
85+
86+
set_sda_out();
87+
return error;
88+
}
89+
90+
void SW_IIC::send_byte(uint8_t txd) {
91+
LOOP_L_N(i, 8) {
92+
write_sda(txd & 0x80); // write data bit
93+
txd <<= 1;
94+
iic_delay(1);
95+
write_scl(HIGH); // SCL = 1
96+
iic_delay(2);
97+
write_scl(LOW); // SCL = 0
98+
iic_delay(1);
99+
}
100+
101+
read_ack(); // wait ack
102+
}
103+
104+
uint8_t SW_IIC::read_byte(bool ack) {
105+
uint8_t data = 0;
106+
107+
set_sda_in();
108+
LOOP_L_N(i, 8) {
109+
write_scl(HIGH); // SCL = 1
110+
iic_delay(1);
111+
data <<= 1;
112+
if (read_sda()) data++;
113+
write_scl(LOW); // SCL = 0
114+
iic_delay(2);
115+
}
116+
set_sda_out();
117+
118+
send_ack(ack);
119+
120+
return data;
121+
}
122+
123+
GT911_REG_MAP GT911::reg;
124+
SW_IIC GT911::sw_iic = SW_IIC(GT911_SW_I2C_SDA_PIN, GT911_SW_I2C_SCL_PIN);
125+
126+
void GT911::write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len) {
127+
sw_iic.start();
128+
sw_iic.send_byte(gt911_slave_address); // Set IIC Slave address
129+
LOOP_L_N(i, reg_len) { // Set reg address
130+
uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
131+
sw_iic.send_byte(r);
132+
}
133+
134+
LOOP_L_N(i, w_len) { // Write data to reg
135+
sw_iic.send_byte(w_data[i]);
136+
}
137+
sw_iic.stop();
138+
}
139+
140+
void GT911::read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len) {
141+
sw_iic.start();
142+
sw_iic.send_byte(gt911_slave_address); // Set IIC Slave address
143+
LOOP_L_N(i, reg_len) { // Set reg address
144+
uint8_t r = (reg >> (8 * (reg_len - 1 - i))) & 0xFF;
145+
sw_iic.send_byte(r);
146+
}
147+
148+
sw_iic.start();
149+
sw_iic.send_byte(gt911_slave_address + 1); // Set read mode
150+
151+
LOOP_L_N(i, r_len) {
152+
r_data[i] = sw_iic.read_byte(1); // Read data from reg
153+
}
154+
sw_iic.stop();
155+
}
156+
157+
void GT911::Init() {
158+
OUT_WRITE(GT911_RST_PIN, LOW);
159+
OUT_WRITE(GT911_INT_PIN, LOW);
160+
delay(20);
161+
WRITE(GT911_RST_PIN, HIGH);
162+
SET_INPUT(GT911_INT_PIN);
163+
164+
sw_iic.init();
165+
166+
uint8_t clear_reg = 0x0000;
167+
write_reg(0x814E, 2, &clear_reg, 2); // Reset to 0 for start
168+
}
169+
170+
bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) {
171+
read_reg(0x814E, 2, &reg.REG.status, 1);
172+
173+
if (reg.REG.status & 0x80) {
174+
uint8_t clear_reg = 0x00;
175+
write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start
176+
read_reg(0x8150, 2, reg.map + 2, 8 * (reg.REG.status & 0x0F));
177+
178+
// First touch point
179+
*x = ((reg.REG.point[0].xh & 0x0F) << 8) | reg.REG.point[0].xl;
180+
*y = ((reg.REG.point[0].yh & 0x0F) << 8) | reg.REG.point[0].yl;
181+
return true;
182+
}
183+
return false;
184+
}
185+
186+
bool GT911::getPoint(int16_t *x, int16_t *y) {
187+
static bool touched = 0;
188+
static int16_t read_x = 0, read_y = 0;
189+
static millis_t next_time = 0;
190+
191+
if (ELAPSED(millis(), next_time)) {
192+
touched = getFirstTouchPoint(&read_x, &read_y);
193+
next_time = millis() + 20;
194+
}
195+
196+
*x = read_x;
197+
*y = read_y;
198+
return touched;
199+
}
200+
201+
#endif // TFT_TOUCH_DEVICE_GT911
202+
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC

Marlin/src/HAL/STM32/tft/gt911.h

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* Marlin 3D Printer Firmware
3+
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4+
*
5+
* Based on Sprinter and grbl.
6+
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*
21+
*/
22+
#pragma once
23+
24+
#include "../../../inc/MarlinConfig.h"
25+
26+
#define GT911_SLAVE_ADDRESS 0xBA
27+
28+
#if !PIN_EXISTS(GT911_RST)
29+
#error "GT911_RST_PIN is not defined."
30+
#elif !PIN_EXISTS(GT911_INT)
31+
#error "GT911_INT_PIN is not defined."
32+
#elif !PIN_EXISTS(GT911_SW_I2C_SCL)
33+
#error "GT911_SW_I2C_SCL_PIN is not defined."
34+
#elif !PIN_EXISTS(GT911_SW_I2C_SDA)
35+
#error "GT911_SW_I2C_SDA_PIN is not defined."
36+
#endif
37+
38+
class SW_IIC {
39+
private:
40+
uint16_t scl_pin;
41+
uint16_t sda_pin;
42+
void write_scl(bool level)
43+
{
44+
WRITE(scl_pin, level);
45+
}
46+
void write_sda(bool level)
47+
{
48+
WRITE(sda_pin, level);
49+
}
50+
bool read_sda()
51+
{
52+
return READ(sda_pin);
53+
}
54+
void set_sda_out()
55+
{
56+
SET_OUTPUT(sda_pin);
57+
}
58+
void set_sda_in()
59+
{
60+
SET_INPUT_PULLUP(sda_pin);
61+
}
62+
static void iic_delay(uint8_t t)
63+
{
64+
delayMicroseconds(t);
65+
}
66+
67+
public:
68+
SW_IIC(uint16_t sda, uint16_t scl);
69+
// setSCL/SDA have to be called before begin()
70+
void setSCL(uint16_t scl)
71+
{
72+
scl_pin = scl;
73+
};
74+
void setSDA(uint16_t sda)
75+
{
76+
sda_pin = sda;
77+
};
78+
void init(); // Initialize the IO port of IIC
79+
void start(); // Send IIC start signal
80+
void stop(); // Send IIC stop signal
81+
void send_byte(uint8_t txd); // IIC sends a byte
82+
uint8_t read_byte(bool ack); // IIC reads a byte
83+
void send_ack(bool ack); // IIC sends ACK or NACK signal
84+
bool read_ack();
85+
};
86+
87+
typedef struct __attribute__((__packed__)) {
88+
uint8_t xl;
89+
uint8_t xh;
90+
uint8_t yl;
91+
uint8_t yh;
92+
uint8_t sizel;
93+
uint8_t sizeh;
94+
uint8_t reserved;
95+
uint8_t track_id;
96+
} GT911_POINT;
97+
98+
typedef union __attribute__((__packed__)) {
99+
uint8_t map[42];
100+
struct {
101+
uint8_t status; // 0x814E
102+
uint8_t track_id; // 0x814F
103+
104+
GT911_POINT point[5]; // [0]:0x8150 - 0x8157 / [1]:0x8158 - 0x815F / [2]:0x8160 - 0x8167 / [3]:0x8168 - 0x816F / [4]:0x8170 - 0x8177
105+
} REG;
106+
} GT911_REG_MAP;
107+
108+
class GT911 {
109+
private:
110+
static const uint8_t gt911_slave_address = GT911_SLAVE_ADDRESS;
111+
static GT911_REG_MAP reg;
112+
static SW_IIC sw_iic;
113+
static void write_reg(uint16_t reg, uint8_t reg_len, uint8_t* w_data, uint8_t w_len);
114+
static void read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_len);
115+
116+
public:
117+
static void Init();
118+
static bool getFirstTouchPoint(int16_t *x, int16_t *y);
119+
static bool getPoint(int16_t *x, int16_t *y);
120+
};

Marlin/src/HAL/STM32/tft/xpt2046.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
#include "../../../inc/MarlinConfig.h"
2525

26-
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
26+
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
2727

2828
#include "xpt2046.h"
2929
#include "pinconfig.h"

Marlin/src/HAL/STM32F1/tft/xpt2046.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
#include "../../../inc/MarlinConfig.h"
2424

25-
#if HAS_TFT_XPT2046 || HAS_TOUCH_BUTTONS
25+
#if HAS_TFT_XPT2046 || HAS_RES_TOUCH_BUTTONS
2626

2727
#include "xpt2046.h"
2828
#include <SPI.h>

0 commit comments

Comments
 (0)