Skip to content

Commit 2ab6b49

Browse files
committed
Add cst820 driver
1 parent 2a6c2e0 commit 2ab6b49

File tree

3 files changed

+308
-1
lines changed

3 files changed

+308
-1
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ _____________________________________________
135135

136136
### Supported Touch IC's
137137
* CST816S
138+
* CST820
138139
* FT5x06
139140
* FT5x16
140141
* FT5x26

Diff for: api_drivers/common_api_drivers/indev/cst816s.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def __init__(
206206
print('FW Version:', hex(self._rx_buf[0]))
207207

208208
if chip_id != _ChipIDValue:
209-
raise RuntimeError(f'Incorrect chip id ({hex(_ChipIDValue)})')
209+
raise RuntimeError(f'Incorrect chip id ({hex(chip_id)} expected: {hex(_ChipIDValue)})')
210210

211211
self._write_reg(_IrqCtl, _EnTouch | _EnChange)
212212

Diff for: api_drivers/common_api_drivers/indev/cst820.py

+306
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
# Based on cst816s, Copyright (c) 2024 - 2025 Kevin G. Schlosser
2+
3+
from micropython import const # NOQA
4+
import pointer_framework
5+
import time
6+
import machine # NOQA
7+
8+
9+
I2C_ADDR = 0x15
10+
BITS = 8
11+
12+
# 0x00: No gesture
13+
# 0x01: Swipe up
14+
# 0x02: Swipe down
15+
# 0x03: Swipe left
16+
# 0x04: Swipe right
17+
# 0x05: Single click
18+
# 0x0B: Double click
19+
# 0x0C: Long press
20+
_GestureID = const(0x01)
21+
22+
# 0: No finger
23+
# 1: 1 finger
24+
_FingerNum = const(0x02)
25+
26+
# & 0xF << 8
27+
_XposH = const(0x03)
28+
_XposL = const(0x04)
29+
30+
# & 0xF << 8
31+
_YposH = const(0x05)
32+
_YposL = const(0x06)
33+
34+
_RegisterVersion = const(0x15)
35+
36+
_BPC0H = const(0xB0)
37+
_BPC0L = const(0xB1)
38+
39+
_BPC1H = const(0xB2)
40+
_BPC1L = const(0xB3)
41+
42+
_ChipID = const(0xA7)
43+
_ChipIDValue = const(0xB7) # 0xB5=cst816s, 0xB7=cst820
44+
45+
_ProjID = const(0xA8)
46+
_FwVersion = const(0xA9)
47+
48+
49+
# ===============================
50+
_MotionMask = const(0xEC)
51+
52+
# Enables continuous left and right sliding
53+
_EnConLR = const(0x04)
54+
# Enables continuous up and down sliding
55+
_EnConUD = const(0x02)
56+
# Enable double-click action
57+
_EnDClick = const(0x01)
58+
# ===============================
59+
60+
# Interrupt low pulse output width.
61+
# Unit 0.1ms, optional value: 1~200. The default value is 10.
62+
_IrqPluseWidth = const(0xED)
63+
64+
# Normal fast detection cycle.
65+
# This value affects LpAutoWakeTime and AutoSleepTime.
66+
# Unit 10ms, optional value: 1~30. The default value is 1.
67+
_NorScanPer = const(0xEE)
68+
69+
# Gesture detection sliding partition angle control. Angle=tan(c)*10
70+
# c is the angle based on the positive direction of the x-axis.
71+
_MotionSlAngle = const(0xEF)
72+
73+
_LpScanRaw1H = const(0xF0)
74+
_LpScanRaw1L = const(0xF1)
75+
_LpScanRaw2H = const(0xF2)
76+
_LpScanRaw2L = const(0xF3)
77+
78+
# Automatic recalibration period in low power consumption.
79+
# Unit: 1 minute, optional value: 1 to 5. The default value is 5.
80+
_LpAutoWakeTime = const(0xF4)
81+
82+
83+
# Low power scan wake-up threshold. The smaller the value,
84+
# the more sensitive it is.
85+
# Optional values: 1 to 255. The default value is 48.
86+
_LpScanTH = const(0xF5)
87+
88+
# Low power scan range. The larger the value, the more sensitive it is,
89+
# and the higher the power consumption is.
90+
# Optional values: 0, 1, 2, 3. The default value is 3.
91+
_LpScanWin = const(0xF6)
92+
93+
# Low power scan frequency. The smaller the value, the more sensitive it is.
94+
# Optional values: 1 to 255. The default value is 7.
95+
_LpScanFreq = const(0xF7)
96+
97+
# Low power scan current. The smaller the value, the more sensitive it is.
98+
# Optional values: 1 to 255.
99+
_LpScanIdac = const(0xF8)
100+
101+
102+
# Automatically enters low power mode when there is no touch within x seconds.
103+
# Unit: 1S, default value: 2S.
104+
_AutoSleepTime = const(0xF9)
105+
106+
# ===============================
107+
_IrqCtl = const(0xFA)
108+
# Interrupt pin test, automatically sends low pulses periodically after enabling
109+
_EnTest = const(0x80)
110+
# Sends low pulses periodically when touch is detected.
111+
_EnTouch = const(0x40)
112+
# Sends low pulses when touch state changes are detected.
113+
_EnChange = const(0x20)
114+
# Sends low pulses when gestures are detected.
115+
_EnMotion = const(0x10)
116+
# Long press gesture only sends one low pulse signal.
117+
_OnceWLP = const(0x01)
118+
# ===============================
119+
120+
121+
# Automatically reset when there is touch but no valid gesture within x seconds.
122+
# Unit: 1S. This function is not enabled when it is 0. The default value is 5.
123+
_AutoReset = const(0xFB)
124+
125+
# Automatically reset after long pressing for x seconds.
126+
# Unit: 1S. This function is not enabled when it is 0. The default value is 10.
127+
_LongPressTime = const(0xFC)
128+
129+
# ===============================
130+
_IOCtl = const(0xFD)
131+
132+
# The master controller realizes the soft reset function
133+
# of the touch screen by pulling down the IRQ pin.
134+
# 0: Disable soft reset.
135+
# 1: Enable soft reset.
136+
_SOFT_RST = const(0x04)
137+
138+
# IIC pin drive mode, the default is resistor pull-up.
139+
# 0: Resistor pull-up
140+
# 1: OD
141+
_IIC_OD = const(0x02)
142+
143+
# IIC and IRQ pin level selection, the default is VDD level.
144+
# 0: VDD
145+
# 1: 1.8V
146+
_En1v8 = const(0x01)
147+
# ===============================
148+
149+
# The default value is 0, enabling automatic entry into low power mode.
150+
# When the value is non-zero, automatic entry into low power mode is disabled.
151+
# 0: enabled
152+
# 1: disabled
153+
_DisAutoSleep = const(0xFE)
154+
155+
156+
class CST816S(pointer_framework.PointerDriver):
157+
158+
def _read_reg(self, reg):
159+
self._tx_buf[0] = reg
160+
self._rx_buf[0] = 0x00
161+
162+
self._device.write_readinto(self._tx_mv[:1], self._rx_mv[:1])
163+
164+
def _write_reg(self, reg, value):
165+
self._tx_buf[0] = reg
166+
self._tx_buf[1] = value
167+
self._device.write(self._tx_mv[:2])
168+
169+
def __init__(
170+
self,
171+
device,
172+
reset_pin=None,
173+
touch_cal=None,
174+
startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, # NOQA
175+
debug=False
176+
):
177+
self._tx_buf = bytearray(2)
178+
self._tx_mv = memoryview(self._tx_buf)
179+
self._rx_buf = bytearray(1)
180+
self._rx_mv = memoryview(self._rx_buf)
181+
182+
self._device = device
183+
184+
if not isinstance(reset_pin, int):
185+
self._reset_pin = reset_pin
186+
else:
187+
self._reset_pin = machine.Pin(reset_pin, machine.Pin.OUT)
188+
189+
if self._reset_pin:
190+
self._reset_pin.value(1)
191+
192+
self.hw_reset()
193+
self.auto_sleep = False
194+
195+
self._read_reg(_ChipID)
196+
print('Chip ID:', hex(self._rx_buf[0]))
197+
chip_id = self._rx_buf[0]
198+
199+
self._read_reg(_RegisterVersion)
200+
print('Touch version:', self._rx_buf[0])
201+
202+
self._read_reg(_ProjID)
203+
print('Proj ID:', hex(self._rx_buf[0]))
204+
205+
self._read_reg(_FwVersion)
206+
print('FW Version:', hex(self._rx_buf[0]))
207+
208+
if chip_id != _ChipIDValue:
209+
raise RuntimeError(f'Incorrect chip id ({hex(chip_id)} expected: {hex(_ChipIDValue)})')
210+
211+
self._write_reg(_IrqCtl, _EnTouch | _EnChange)
212+
213+
super().__init__(
214+
touch_cal=touch_cal, startup_rotation=startup_rotation, debug=debug
215+
)
216+
217+
@property
218+
def wake_up_threshold(self):
219+
self._read_reg(_LpScanTH)
220+
return 256 - self._rx_buf[0]
221+
222+
@wake_up_threshold.setter
223+
def wake_up_threshold(self, value):
224+
if value < 1:
225+
value = 1
226+
elif value > 255:
227+
value = 255
228+
229+
self._write_reg(_LpScanTH, 256 - value)
230+
231+
@property
232+
def wake_up_scan_frequency(self):
233+
self._read_reg(_LpScanFreq)
234+
return 256 - self._rx_buf[0]
235+
236+
@wake_up_scan_frequency.setter
237+
def wake_up_scan_frequency(self, value):
238+
if value < 1:
239+
value = 1
240+
elif value > 255:
241+
value = 255
242+
243+
self._write_reg(_LpScanFreq, 256 - value)
244+
245+
@property
246+
def auto_sleep_timeout(self):
247+
self._read_reg(_AutoSleepTime)
248+
return self._rx_buf[0]
249+
250+
@auto_sleep_timeout.setter
251+
def auto_sleep_timeout(self, value):
252+
if value < 1:
253+
value = 1
254+
elif value > 255:
255+
value = 255
256+
257+
self._write_reg(_AutoSleepTime, value)
258+
259+
def wake_up(self):
260+
auto_sleep = self.auto_sleep
261+
262+
self._write_reg(_DisAutoSleep, 0x00)
263+
time.sleep_ms(10) # NOQA
264+
self._write_reg(_DisAutoSleep, 0x01)
265+
time.sleep_ms(50) # NOQA
266+
self._write_reg(_DisAutoSleep, 0x01)
267+
time.sleep_ms(50) # NOQA
268+
self._write_reg(_DisAutoSleep, int(not auto_sleep))
269+
270+
@property
271+
def auto_sleep(self):
272+
self._read_reg(_DisAutoSleep)
273+
return self._rx_buf[0] == 0x00
274+
275+
@auto_sleep.setter
276+
def auto_sleep(self, en):
277+
if en:
278+
self._write_reg(_DisAutoSleep, 0x00)
279+
else:
280+
self._write_reg(_DisAutoSleep, 0x01)
281+
282+
def hw_reset(self):
283+
if self._reset_pin is None:
284+
return
285+
286+
self._reset_pin(0)
287+
time.sleep_ms(1) # NOQA
288+
self._reset_pin(1)
289+
time.sleep_ms(50) # NOQA
290+
291+
def _get_coords(self):
292+
self._read_reg(_FingerNum)
293+
if self._rx_buf[0] == 0:
294+
return None
295+
296+
self._read_reg(_XposH)
297+
x = (self._rx_buf[0] & 0x0F) << 8
298+
self._read_reg(_XposL)
299+
x |= self._rx_buf[0]
300+
301+
self._read_reg(_YposH)
302+
y = (self._rx_buf[0] & 0x0F) << 8
303+
self._read_reg(_YposL)
304+
y |= self._rx_buf[0]
305+
306+
return self.PRESSED, x, y

0 commit comments

Comments
 (0)