mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-21 06:59:00 +00:00
XPT2046 Touch driver (#350)
Co-authored-by: Steven Pearson <steven.pearson.78@gmail.com>
This commit is contained in:
@@ -215,12 +215,14 @@ endif
|
|||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
|
tinygo build -size short -o ./build/test.elf -target=wioterminal ./examples/axp192/m5stack-core2-blinky/
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
|
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/xpt2046/main.go
|
||||||
|
@md5sum ./build/test.uf2
|
||||||
|
|
||||||
DRIVERS = $(wildcard */)
|
DRIVERS = $(wildcard */)
|
||||||
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \
|
||||||
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
|
hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \
|
||||||
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx p1am tone tm1637 \
|
hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx p1am tone tm1637 \
|
||||||
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192
|
pcf8563 mcp2515 servo sdcard rtl8720dn image cmd i2csoft hts221 lps22hb apds9960 axp192 xpt2046
|
||||||
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS))
|
||||||
|
|
||||||
unit-test:
|
unit-test:
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ The following 74 devices are supported.
|
|||||||
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
|
| [Waveshare 2.13" e-paper display](https://www.waveshare.com/w/upload/e/e6/2.13inch_e-Paper_Datasheet.pdf) | SPI |
|
||||||
| [Waveshare 4.2" e-paper B/W display](https://www.waveshare.com/w/upload/6/6a/4.2inch-e-paper-specification.pdf) | SPI |
|
| [Waveshare 4.2" e-paper B/W display](https://www.waveshare.com/w/upload/6/6a/4.2inch-e-paper-specification.pdf) | SPI |
|
||||||
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
|
| [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO |
|
||||||
|
| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO |
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/xpt2046"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
clk := machine.GPIO0
|
||||||
|
cs := machine.GPIO1
|
||||||
|
din := machine.GPIO2
|
||||||
|
dout := machine.GPIO3
|
||||||
|
irq := machine.GPIO4
|
||||||
|
|
||||||
|
touchScreen := xpt2046.New(clk, cs, din, dout, irq)
|
||||||
|
|
||||||
|
touchScreen.Configure(&xpt2046.Config{
|
||||||
|
Precision: 10, //Maximum number of samples for a single ReadTouchPoint to improve accuracy.
|
||||||
|
})
|
||||||
|
|
||||||
|
for {
|
||||||
|
|
||||||
|
//Wait for a touch
|
||||||
|
for !touchScreen.Touched() {
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
touch := touchScreen.ReadTouchPoint()
|
||||||
|
//X and Y are 16 bit with 12 bit resolution and need to be scaled for the display size
|
||||||
|
//Z is 24 bit and is typically > 2000 for a touch
|
||||||
|
println("touch:", touch.X, touch.Y, touch.Z)
|
||||||
|
//Example of scaling for a 240x320 display
|
||||||
|
println("screen:", (touch.X*240)>>16, (touch.Y*320)>>16)
|
||||||
|
|
||||||
|
//Wait for touch to end
|
||||||
|
for touchScreen.Touched() {
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
// Package xpt2046 implements a driver for the XPT2046 resistive touch controller as packaged on the TFT_320QVT board
|
||||||
|
//
|
||||||
|
// Datasheet: http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf
|
||||||
|
package xpt2046
|
||||||
|
|
||||||
|
import (
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/touch"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Device struct {
|
||||||
|
t_clk machine.Pin
|
||||||
|
t_cs machine.Pin
|
||||||
|
t_din machine.Pin
|
||||||
|
t_dout machine.Pin
|
||||||
|
t_irq machine.Pin
|
||||||
|
|
||||||
|
precision uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Precision uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device {
|
||||||
|
return Device{
|
||||||
|
precision: 10,
|
||||||
|
t_clk: t_clk,
|
||||||
|
t_cs: t_cs,
|
||||||
|
t_din: t_din,
|
||||||
|
t_dout: t_dout,
|
||||||
|
t_irq: t_irq,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) Configure(config *Config) error {
|
||||||
|
|
||||||
|
if config.Precision == 0 {
|
||||||
|
d.precision = 10
|
||||||
|
} else {
|
||||||
|
d.precision = config.Precision
|
||||||
|
}
|
||||||
|
|
||||||
|
d.t_clk.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
d.t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
d.t_din.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
|
||||||
|
d.t_dout.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||||
|
d.t_irq.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||||
|
|
||||||
|
d.t_clk.Low()
|
||||||
|
d.t_cs.High()
|
||||||
|
d.t_din.Low()
|
||||||
|
|
||||||
|
d.readRaw() //Set Powerdown mode to enable T_IRQ
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func busSleep() {
|
||||||
|
time.Sleep(5 * time.Nanosecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pulseHigh(p machine.Pin) {
|
||||||
|
p.High()
|
||||||
|
busSleep()
|
||||||
|
p.Low()
|
||||||
|
busSleep()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) writeCommand(data uint8) {
|
||||||
|
|
||||||
|
for count := uint8(0); count < 8; count++ {
|
||||||
|
d.t_din.Set((data & 0x80) != 0)
|
||||||
|
data <<= 1
|
||||||
|
pulseHigh(d.t_clk)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) readData() uint16 {
|
||||||
|
|
||||||
|
data := uint16(0)
|
||||||
|
|
||||||
|
for count := uint8(0); count < 12; count++ {
|
||||||
|
data <<= 1
|
||||||
|
pulseHigh(d.t_clk)
|
||||||
|
if d.t_dout.Get() {
|
||||||
|
data |= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pulseHigh(d.t_clk) //13
|
||||||
|
pulseHigh(d.t_clk) //14
|
||||||
|
pulseHigh(d.t_clk) //15
|
||||||
|
pulseHigh(d.t_clk) //16
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) ReadTouchPoint() touch.Point {
|
||||||
|
|
||||||
|
tx := uint32(0)
|
||||||
|
ty := uint32(0)
|
||||||
|
tz := uint32(0)
|
||||||
|
sampleCount := uint8(0)
|
||||||
|
|
||||||
|
d.t_cs.Low()
|
||||||
|
|
||||||
|
for ; sampleCount < d.precision && d.Touched(); sampleCount++ {
|
||||||
|
rx, ry, rz := d.readRaw()
|
||||||
|
tx += uint32(rx)
|
||||||
|
ty += uint32(ry)
|
||||||
|
tz += uint32(rz)
|
||||||
|
}
|
||||||
|
d.t_cs.High()
|
||||||
|
|
||||||
|
if sampleCount > 0 {
|
||||||
|
x := int(tx / uint32(sampleCount))
|
||||||
|
y := int(ty / uint32(sampleCount))
|
||||||
|
z := int(tz / uint32(sampleCount))
|
||||||
|
return touch.Point{
|
||||||
|
X: x,
|
||||||
|
Y: y,
|
||||||
|
Z: z,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return touch.Point{
|
||||||
|
X: 0,
|
||||||
|
Y: 0,
|
||||||
|
Z: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) Touched() bool {
|
||||||
|
avail := !d.t_irq.Get()
|
||||||
|
return avail
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Device) readRaw() (int32, int32, int32) {
|
||||||
|
|
||||||
|
d.t_cs.Low()
|
||||||
|
|
||||||
|
//S = 1 --> Required Control bit
|
||||||
|
//A2-A0 = 001 --> Y-Position
|
||||||
|
//MODE = 0 --> 12 bit conversion
|
||||||
|
//SER/DFR = 0 --> Differential preferred for X,Y position
|
||||||
|
//PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ
|
||||||
|
d.writeCommand(0x90)
|
||||||
|
ty := d.readData()
|
||||||
|
|
||||||
|
//S = 1 --> Required Control bit
|
||||||
|
//A2-A0 = 101 --> X-Position
|
||||||
|
//MODE = 0 --> 12 bit conversion
|
||||||
|
//SER/DFR = 0 --> Differential preferred for X,Y position
|
||||||
|
//PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ
|
||||||
|
d.writeCommand(0xD0)
|
||||||
|
tx := d.readData()
|
||||||
|
|
||||||
|
//S = 1 --> Required Control bit
|
||||||
|
//A2-A0 = 011 --> Z1-position (pressure)
|
||||||
|
//MODE = 0 --> 12 bit conversion
|
||||||
|
//SER/DFR = 0 --> Differential preferred for pressure
|
||||||
|
//PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ
|
||||||
|
d.writeCommand(0xB0)
|
||||||
|
tz1 := int32(d.readData())
|
||||||
|
|
||||||
|
//S = 1 --> Required Control bit
|
||||||
|
//A2-A0 = 100 --> Z2-position (pressure)
|
||||||
|
//MODE = 0 --> 12 bit conversion
|
||||||
|
//SER/DFR = 0 --> Differential preferred for pressure
|
||||||
|
//PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ
|
||||||
|
d.writeCommand(0xC0)
|
||||||
|
tz2 := int32(d.readData())
|
||||||
|
|
||||||
|
tz := int32(0)
|
||||||
|
if tz1 != 0 {
|
||||||
|
//Touch pressure is proportional to the ratio of z2 to z1 and the x position.
|
||||||
|
tz = int32(tx) * ((tz2 << 12) / (tz1 << 12))
|
||||||
|
}
|
||||||
|
|
||||||
|
d.t_cs.High()
|
||||||
|
|
||||||
|
//Scale X&Y to 16 bit for consistency across touch drivers
|
||||||
|
return int32(tx) << 4, int32(4096-ty) << 4, tz
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user