From f633a08fdb055bb387b933b73737eeb32d5ceff7 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 15:19:23 -0600 Subject: [PATCH 01/17] First cut at merging SPI and non-SPI versions of the xpt2046 driver. --- xpt2046/xpt2046.go | 121 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 2 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index d1ef26902..2f64a3686 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -6,11 +6,12 @@ package xpt2046 import ( "machine" "time" - + "tinygo.org/x/drivers" "tinygo.org/x/drivers/touch" ) type Device struct { + bus drivers.SPI t_clk machine.Pin t_cs machine.Pin t_din machine.Pin @@ -35,6 +36,18 @@ func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { } } +func NewSPI(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { + t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) + t_irq.Configure(machine.PinConfig{Mode: machine.PinInput}) + + return Device{ + bus: bus, + precision: 10, + t_cs: t_cs, + t_irq: t_irq, + } +} + func (d *Device) Configure(config *Config) error { if config.Precision == 0 { @@ -59,6 +72,55 @@ func (d *Device) Configure(config *Config) error { return nil } +func (d *Device) Configure(config *Config) error { + + if config.Precision == 0 { + d.precision = 10 + } else { + d.precision = config.Precision + } + + d.t_cs.High() + + //S = 1 --> Required Control bit + //A2-A0 = 000 --> nothing + //MODE = 0 --> 12 bit conversion + //SER/DFR = 0 --> Differential preferred for pressure + //PD1-PD0 = 10 --> Powerdown and enable PEN_IRQ + d.Command(0x80) // make sure PD1 is cleared on start + + return nil +} + + +// Tx and Rx pulled from st7789, modified for xps2046 + +// Tx sends data to the touchpad +func (d *Device) Tx(data []byte, isCommand bool) { + d.t_cs.Low() + d.bus.Tx(data, nil) + d.t_cs.High() +} + +// Rx reads data from the touchpad +func (d *Device) Rx(command uint8, data []byte) { + cmd := make([]byte,len(data)) + cmd[0] = command + d.t_cs.Low() + d.bus.Tx(cmd,data) + d.t_cs.High() +} + +// Command sends a command to the touch screen. +func (d *Device) Command(command uint8) { + d.Tx([]byte{command}, true) +} + +// Data sends data to the touch screen. // XXX needed? +func (d *Device) Data(data uint8) { + d.Tx([]byte{data}, false) +} + func busSleep() { time.Sleep(5 * time.Nanosecond) } @@ -109,7 +171,11 @@ func (d *Device) ReadTouchPoint() touch.Point { d.t_cs.Low() for ; sampleCount < d.precision && d.Touched(); sampleCount++ { - rx, ry, rz := d.readRaw() + if d.SPI != nil { + rx, ry, rz := d.readRawSPI() + } else { + rx, ry, rz := d.readRaw() + } tx += uint32(rx) ty += uint32(ry) tz += uint32(rz) @@ -186,3 +252,54 @@ func (d *Device) readRaw() (int32, int32, int32) { //Scale X&Y to 16 bit for consistency across touch drivers return int32(tx) << 4, int32(4096-ty) << 4, tz } + + +func (d *Device) readRawSPI() (int32, int32, int32) { + + data := make([]byte,4) + + //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.Rx(0xD0,data) + tx := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[1], remaining 5 from top of data[2] + + //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.Rx(0x90,data) + ty := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[0], remaining 5 from top of data[1] + + //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.Rx(0xB0,data) + tz1 := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[0], remaining 5 from top of data[1] + + //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.Rx(0xC0,data) + tz2 := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[0], remaining 5 from top of data[1] + + 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)) + } + + //Scale X&Y to 16 bit for consistency across touch drivers + return int32(tx) << 4, int32(4096-ty) << 4, tz +} From e7949c19537d085cb2f68cad8d74d1102f2be771 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 15:32:33 -0600 Subject: [PATCH 02/17] Apparently we need to make this our 'own' module so we can import it. --- go.mod | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 737bc4db4..7106d4aef 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,5 @@ -module tinygo.org/x/drivers +// module tinygo.org/x/drivers +module github.com/gregoster/tinygo-drivers go 1.15 From 5278faae0a454d2e757801dafb73374157611441 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:14:20 -0600 Subject: [PATCH 03/17] SPI for xpt2046 too. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 044ab43df..4e4ccaf66 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ The following 90 devices are supported. | [Waveshare 4.2" e-paper B/W display](https://www.waveshare.com/w/upload/6/6a/4.2inch-e-paper-specification.pdf) | SPI | | [Waveshare GC9A01 TFT round display](https://www.waveshare.com/w/upload/5/5e/GC9A01A.pdf) | SPI | | [WS2812 RGB LED](https://cdn-shop.adafruit.com/datasheets/WS2812.pdf) | GPIO | -| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO | +| [XPT2046 touch controller](http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf) | GPIO / SPI | | [Semtech SX126x Lora](https://www.semtech.com/products/wireless-rf/lora-transceiv-ers/sx1261) | SPI | | [SSD1289 TFT color display](http://aitendo3.sakura.ne.jp/aitendo_data/product_img/lcd/tft2/M032C1289TP/3.2-SSD1289.pdf) | GPIO | From ce40cc1997e3069c45c33ccc369125dd88f97d07 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:22:59 -0600 Subject: [PATCH 04/17] Need ConfigureSPI --- xpt2046/xpt2046.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index 2f64a3686..d294f6626 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -72,7 +72,7 @@ func (d *Device) Configure(config *Config) error { return nil } -func (d *Device) Configure(config *Config) error { +func (d *Device) ConfigureSPI(config *Config) error { if config.Precision == 0 { d.precision = 10 From e85a575e19023dbd1cc966b37880fc02cf0163c2 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:26:38 -0600 Subject: [PATCH 05/17] declare rx, ry, rz. SPI->bus. --- xpt2046/xpt2046.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index d294f6626..bbea11052 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -166,15 +166,18 @@ func (d *Device) ReadTouchPoint() touch.Point { tx := uint32(0) ty := uint32(0) tz := uint32(0) + rx := uint32(0) + ry := uint32(0) + rz := uint32(0) sampleCount := uint8(0) d.t_cs.Low() for ; sampleCount < d.precision && d.Touched(); sampleCount++ { - if d.SPI != nil { - rx, ry, rz := d.readRawSPI() + if d.bus != nil { + rx, ry, rz = d.readRawSPI() } else { - rx, ry, rz := d.readRaw() + rx, ry, rz = d.readRaw() } tx += uint32(rx) ty += uint32(ry) From 3f5237dd523c5b353a8c8b645e228656996e5b11 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:36:09 -0600 Subject: [PATCH 06/17] uint32->int32 --- xpt2046/xpt2046.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index bbea11052..1b3544a0e 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -166,8 +166,8 @@ func (d *Device) ReadTouchPoint() touch.Point { tx := uint32(0) ty := uint32(0) tz := uint32(0) - rx := uint32(0) - ry := uint32(0) + rx := int32(0) + ry := int32(0) rz := uint32(0) sampleCount := uint8(0) From f84dbde0b0b039e29a2bf675e0a47896172daacb Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:37:10 -0600 Subject: [PATCH 07/17] Missed one on last commit --- xpt2046/xpt2046.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index 1b3544a0e..3da058919 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -168,7 +168,7 @@ func (d *Device) ReadTouchPoint() touch.Point { tz := uint32(0) rx := int32(0) ry := int32(0) - rz := uint32(0) + rz := int32(0) sampleCount := uint8(0) d.t_cs.Low() From 9dc6e5abd6543bc33ff62b4bb20bdb0d1480a2bc Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:41:58 -0600 Subject: [PATCH 08/17] Something isn't working now after the merge. This change shouldn't matter. --- xpt2046/xpt2046.go | 1 + 1 file changed, 1 insertion(+) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index 3da058919..e91098e15 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -27,6 +27,7 @@ type Config struct { func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { return Device{ + bus: nil, precision: 10, t_clk: t_clk, t_cs: t_cs, From df64bd02ba636ddb23001e197442ffeb984a2d13 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:43:55 -0600 Subject: [PATCH 09/17] Some stuff is GPIO-only... --- xpt2046/xpt2046.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index e91098e15..e098c81de 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -104,7 +104,8 @@ func (d *Device) Tx(data []byte, isCommand bool) { } // Rx reads data from the touchpad -func (d *Device) Rx(command uint8, data []byte) { +func (d *Device) Rx(command uint8, data []byte) { + // XXX only valid for SPI cmd := make([]byte,len(data)) cmd[0] = command d.t_cs.Low() @@ -114,11 +115,13 @@ func (d *Device) Rx(command uint8, data []byte) { // Command sends a command to the touch screen. func (d *Device) Command(command uint8) { + // XXX only valid for SPI d.Tx([]byte{command}, true) } // Data sends data to the touch screen. // XXX needed? func (d *Device) Data(data uint8) { + // XXX only valid for SPI d.Tx([]byte{data}, false) } @@ -172,7 +175,9 @@ func (d *Device) ReadTouchPoint() touch.Point { rz := int32(0) sampleCount := uint8(0) - d.t_cs.Low() + if d.bus == nil { + d.t_cs.Low() + } for ; sampleCount < d.precision && d.Touched(); sampleCount++ { if d.bus != nil { @@ -184,7 +189,9 @@ func (d *Device) ReadTouchPoint() touch.Point { ty += uint32(ry) tz += uint32(rz) } - d.t_cs.High() + if d.bus == nil { + d.t_cs.High() + } if sampleCount > 0 { x := int(tx / uint32(sampleCount)) From 28fab27cba155ef00d1ce1ea8f810e1f0254f39a Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:52:28 -0600 Subject: [PATCH 10/17] add missing sleep, and minor reorder. --- xpt2046/xpt2046.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index e098c81de..cc3810ed4 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -180,14 +180,17 @@ func (d *Device) ReadTouchPoint() touch.Point { } for ; sampleCount < d.precision && d.Touched(); sampleCount++ { - if d.bus != nil { - rx, ry, rz = d.readRawSPI() - } else { + if d.bus == nil { rx, ry, rz = d.readRaw() + } else { + rx, ry, rz = d.readRawSPI() } tx += uint32(rx) ty += uint32(ry) tz += uint32(rz) + if d.bus != nil { + time.Sleep(200*time.Microsecond) + } } if d.bus == nil { d.t_cs.High() From de1cc524a2c0945886e1d035792f652d649f9d0e Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 16:58:19 -0600 Subject: [PATCH 11/17] Ok... just go to the SPI-only version of the driver... something is wrong when loading the GPIO+SPI driver and my test program. --- xpt2046/xpt2046.go | 166 +++------------------------------------------ 1 file changed, 10 insertions(+), 156 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index cc3810ed4..a4e35d070 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -12,10 +12,10 @@ import ( type Device struct { bus drivers.SPI - t_clk machine.Pin + // t_clk machine.Pin - Using SPI t_cs machine.Pin - t_din machine.Pin - t_dout machine.Pin + // t_din machine.Pin - Using SPI + // t_dout machine.Pin - Using SPI t_irq machine.Pin precision uint8 @@ -25,22 +25,10 @@ type Config struct { Precision uint8 } -func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { - return Device{ - bus: nil, - precision: 10, - t_clk: t_clk, - t_cs: t_cs, - t_din: t_din, - t_dout: t_dout, - t_irq: t_irq, - } -} - -func NewSPI(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { +func New(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) t_irq.Configure(machine.PinConfig{Mode: machine.PinInput}) - + return Device{ bus: bus, precision: 10, @@ -57,30 +45,6 @@ func (d *Device) Configure(config *Config) error { 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 (d *Device) ConfigureSPI(config *Config) error { - - if config.Precision == 0 { - d.precision = 10 - } else { - d.precision = config.Precision - } - d.t_cs.High() //S = 1 --> Required Control bit @@ -93,7 +57,6 @@ func (d *Device) ConfigureSPI(config *Config) error { return nil } - // Tx and Rx pulled from st7789, modified for xps2046 // Tx sends data to the touchpad @@ -104,8 +67,7 @@ func (d *Device) Tx(data []byte, isCommand bool) { } // Rx reads data from the touchpad -func (d *Device) Rx(command uint8, data []byte) { - // XXX only valid for SPI +func (d *Device) Rx(command uint8, data []byte) { cmd := make([]byte,len(data)) cmd[0] = command d.t_cs.Low() @@ -115,87 +77,28 @@ func (d *Device) Rx(command uint8, data []byte) { // Command sends a command to the touch screen. func (d *Device) Command(command uint8) { - // XXX only valid for SPI d.Tx([]byte{command}, true) } // Data sends data to the touch screen. // XXX needed? func (d *Device) Data(data uint8) { - // XXX only valid for SPI d.Tx([]byte{data}, false) } -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) - rx := int32(0) - ry := int32(0) - rz := int32(0) sampleCount := uint8(0) - - if d.bus == nil { - d.t_cs.Low() - } - + for ; sampleCount < d.precision && d.Touched(); sampleCount++ { - if d.bus == nil { - rx, ry, rz = d.readRaw() - } else { - rx, ry, rz = d.readRawSPI() - } + rx, ry, rz := d.readRaw() tx += uint32(rx) ty += uint32(ry) tz += uint32(rz) - if d.bus != nil { - time.Sleep(200*time.Microsecond) - } - } - if d.bus == nil { - d.t_cs.High() + time.Sleep(200*time.Microsecond) } - if sampleCount > 0 { x := int(tx / uint32(sampleCount)) y := int(ty / uint32(sampleCount)) @@ -221,55 +124,6 @@ func (d *Device) Touched() bool { 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 -} - - -func (d *Device) readRawSPI() (int32, int32, int32) { - data := make([]byte,4) //S = 1 --> Required Control bit @@ -280,7 +134,7 @@ func (d *Device) readRawSPI() (int32, int32, int32) { d.Rx(0xD0,data) tx := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[1], remaining 5 from top of data[2] - + //S = 1 --> Required Control bit //A2-A0 = 001 --> Y-Position //MODE = 0 --> 12 bit conversion From fac5c6c3742a89a899116826691de5ab117f3517 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 17:03:26 -0600 Subject: [PATCH 12/17] go fmt --- xpt2046/xpt2046.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index a4e35d070..b7b36ea76 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -11,12 +11,12 @@ import ( ) type Device struct { - bus drivers.SPI + bus drivers.SPI // t_clk machine.Pin - Using SPI - t_cs machine.Pin + t_cs machine.Pin // t_din machine.Pin - Using SPI // t_dout machine.Pin - Using SPI - t_irq machine.Pin + t_irq machine.Pin precision uint8 } @@ -28,7 +28,7 @@ type Config struct { func New(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) t_irq.Configure(machine.PinConfig{Mode: machine.PinInput}) - + return Device{ bus: bus, precision: 10, @@ -68,10 +68,10 @@ func (d *Device) Tx(data []byte, isCommand bool) { // Rx reads data from the touchpad func (d *Device) Rx(command uint8, data []byte) { - cmd := make([]byte,len(data)) + cmd := make([]byte, len(data)) cmd[0] = command d.t_cs.Low() - d.bus.Tx(cmd,data) + d.bus.Tx(cmd, data) d.t_cs.High() } @@ -91,13 +91,13 @@ func (d *Device) ReadTouchPoint() touch.Point { ty := uint32(0) tz := uint32(0) sampleCount := uint8(0) - + for ; sampleCount < d.precision && d.Touched(); sampleCount++ { rx, ry, rz := d.readRaw() tx += uint32(rx) ty += uint32(ry) tz += uint32(rz) - time.Sleep(200*time.Microsecond) + time.Sleep(200 * time.Microsecond) } if sampleCount > 0 { x := int(tx / uint32(sampleCount)) @@ -124,7 +124,7 @@ func (d *Device) Touched() bool { func (d *Device) readRaw() (int32, int32, int32) { - data := make([]byte,4) + data := make([]byte, 4) //S = 1 --> Required Control bit //A2-A0 = 101 --> X-Position @@ -132,17 +132,17 @@ func (d *Device) readRaw() (int32, int32, int32) { //SER/DFR = 0 --> Differential preferred for X,Y position //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ - d.Rx(0xD0,data) - tx := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[1], remaining 5 from top of data[2] - + d.Rx(0xD0, data) + tx := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[1], remaining 5 from top of data[2] + //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.Rx(0x90,data) - ty := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[0], remaining 5 from top of data[1] + d.Rx(0x90, data) + ty := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[0], remaining 5 from top of data[1] //S = 1 --> Required Control bit //A2-A0 = 011 --> Z1-position (pressure) @@ -150,8 +150,8 @@ func (d *Device) readRaw() (int32, int32, int32) { //SER/DFR = 0 --> Differential preferred for pressure //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ - d.Rx(0xB0,data) - tz1 := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[0], remaining 5 from top of data[1] + d.Rx(0xB0, data) + tz1 := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[0], remaining 5 from top of data[1] //S = 1 --> Required Control bit //A2-A0 = 100 --> Z2-position (pressure) @@ -159,8 +159,8 @@ func (d *Device) readRaw() (int32, int32, int32) { //SER/DFR = 0 --> Differential preferred for pressure //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ - d.Rx(0xC0,data) - tz2 := int32((uint16(data[1])<<8 | uint16(data[2])) >>3) // 7 bits come from data[0], remaining 5 from top of data[1] + d.Rx(0xC0, data) + tz2 := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[0], remaining 5 from top of data[1] tz := int32(0) if tz1 != 0 { From e3880c5eeffe893c17fb62249651813ab94cad6a Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Sun, 23 Oct 2022 17:08:40 -0600 Subject: [PATCH 13/17] It would help if I used 'tinygo flash' instead of 'tinygo build' for testing. --- xpt2046/xpt2046.go | 162 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 153 insertions(+), 9 deletions(-) diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index b7b36ea76..bc9fb2099 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -11,12 +11,12 @@ import ( ) type Device struct { - bus drivers.SPI - // t_clk machine.Pin - Using SPI - t_cs machine.Pin - // t_din machine.Pin - Using SPI - // t_dout machine.Pin - Using SPI - t_irq machine.Pin + bus drivers.SPI + t_clk machine.Pin + t_cs machine.Pin + t_din machine.Pin + t_dout machine.Pin + t_irq machine.Pin precision uint8 } @@ -25,7 +25,19 @@ type Config struct { Precision uint8 } -func New(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { +func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { + return Device{ + bus: nil, + precision: 10, + t_clk: t_clk, + t_cs: t_cs, + t_din: t_din, + t_dout: t_dout, + t_irq: t_irq, + } +} + +func NewSPI(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) t_irq.Configure(machine.PinConfig{Mode: machine.PinInput}) @@ -45,6 +57,30 @@ func (d *Device) Configure(config *Config) error { 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 (d *Device) ConfigureSPI(config *Config) error { + + if config.Precision == 0 { + d.precision = 10 + } else { + d.precision = config.Precision + } + d.t_cs.High() //S = 1 --> Required Control bit @@ -68,6 +104,7 @@ func (d *Device) Tx(data []byte, isCommand bool) { // Rx reads data from the touchpad func (d *Device) Rx(command uint8, data []byte) { + // XXX only valid for SPI cmd := make([]byte, len(data)) cmd[0] = command d.t_cs.Low() @@ -77,28 +114,87 @@ func (d *Device) Rx(command uint8, data []byte) { // Command sends a command to the touch screen. func (d *Device) Command(command uint8) { + // XXX only valid for SPI d.Tx([]byte{command}, true) } // Data sends data to the touch screen. // XXX needed? func (d *Device) Data(data uint8) { + // XXX only valid for SPI d.Tx([]byte{data}, false) } +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) + rx := int32(0) + ry := int32(0) + rz := int32(0) sampleCount := uint8(0) + if d.bus == nil { + d.t_cs.Low() + } + for ; sampleCount < d.precision && d.Touched(); sampleCount++ { - rx, ry, rz := d.readRaw() + if d.bus == nil { + rx, ry, rz = d.readRaw() + } else { + rx, ry, rz = d.readRawSPI() + } tx += uint32(rx) ty += uint32(ry) tz += uint32(rz) - time.Sleep(200 * time.Microsecond) + if d.bus != nil { + time.Sleep(200 * time.Microsecond) + } } + if d.bus == nil { + d.t_cs.High() + } + if sampleCount > 0 { x := int(tx / uint32(sampleCount)) y := int(ty / uint32(sampleCount)) @@ -124,6 +220,54 @@ func (d *Device) Touched() bool { 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 +} + +func (d *Device) readRawSPI() (int32, int32, int32) { + data := make([]byte, 4) //S = 1 --> Required Control bit From 7f3ece7906644428ea554302240c47c8a9caf9cf Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Mon, 24 Oct 2022 21:55:39 -0600 Subject: [PATCH 14/17] Major cleanup. - add comments for functions - move pin configuration for t_cs and t_irq for SPI into ConfigureSPI() for consistency - replace the single use of Command() with Tx() - Command() and Data() arn't needed - isCommand isn't needed for Tx() - convert Tx->tx and Rx->rx --- go.mod | 1 + go.sum | 1 + xpt2046/xpt2046.go | 68 +++++++++++++++++++++++++++------------------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 7106d4aef..3f315ebb8 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/eclipse/paho.mqtt.golang v1.2.0 github.com/frankban/quicktest v1.10.2 golang.org/x/net v0.0.0-20210614182718-04defd469f4e + tinygo.org/x/drivers v0.19.0 tinygo.org/x/tinyfont v0.3.0 tinygo.org/x/tinyfs v0.2.0 tinygo.org/x/tinyterm v0.1.0 diff --git a/go.sum b/go.sum index 5a9b06e4e..2a924e640 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T tinygo.org/x/drivers v0.14.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI= tinygo.org/x/drivers v0.15.1/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI= tinygo.org/x/drivers v0.16.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI= +tinygo.org/x/drivers v0.19.0 h1:x/TIC8SFWeGViJvcYO1ATjgwSNF7hHN2ouAyjMUXI2Q= tinygo.org/x/drivers v0.19.0/go.mod h1:uJD/l1qWzxzLx+vcxaW0eY464N5RAgFi1zTVzASFdqI= tinygo.org/x/tinyfont v0.2.1/go.mod h1:eLqnYSrFRjt5STxWaMeOWJTzrKhXqpWw7nU3bPfKOAM= tinygo.org/x/tinyfont v0.3.0 h1:HIRLQoI3oc+2CMhPcfv+Ig88EcTImE/5npjqOnMD4lM= diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index bc9fb2099..54337a303 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -1,4 +1,5 @@ -// Package xpt2046 implements a driver for the XPT2046 resistive touch controller as packaged on the TFT_320QVT board +// Package xpt2046 implements a driver for the XPT2046 resistive touch controller +// as packaged on the TFT_320QVT board or a Waveshare Pico-ResTouch-LCD-2.8 board. // // Datasheet: http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf package xpt2046 @@ -10,6 +11,10 @@ import ( "tinygo.org/x/drivers/touch" ) +// This driver supports both GPIO and SPI interfaces for a given touch controller, +// but not at the same time. GPIO works fine unless t_clk, t_din, and t_dout +// are shared with another device and that device is expecting to use SPI over +// those pins. type Device struct { bus drivers.SPI t_clk machine.Pin @@ -21,10 +26,13 @@ type Device struct { precision uint8 } +// Simple configuration -- Precision indicates the number of samples +// averaged to produce X, Y, and Z (pressure) coordinates. type Config struct { Precision uint8 } +// Create a new GPIO-based device. SPI bus not used in this setup. func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { return Device{ bus: nil, @@ -37,10 +45,9 @@ func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { } } +// Create a new SPI-based device. GPIO not available for this instance +// when SPI is used. func NewSPI(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { - t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) - t_irq.Configure(machine.PinConfig{Mode: machine.PinInput}) - return Device{ bus: bus, precision: 10, @@ -49,6 +56,8 @@ func NewSPI(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { } } +// Configure a GPIO-based device. Sets up the Precision of the device +// and initializes the GPIO pins. func (d *Device) Configure(config *Config) error { if config.Precision == 0 { @@ -73,6 +82,9 @@ func (d *Device) Configure(config *Config) error { return nil } +// Configure a SPI-based device. Sets up the Precision of the device. +// Also initializes t_cs and t_irq. All of the other pins in Device are +// used by SPI. func (d *Device) ConfigureSPI(config *Config) error { if config.Precision == 0 { @@ -81,6 +93,9 @@ func (d *Device) ConfigureSPI(config *Config) error { d.precision = config.Precision } + d.t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) + d.t_irq.Configure(machine.PinConfig{Mode: machine.PinInput}) + d.t_cs.High() //S = 1 --> Required Control bit @@ -88,23 +103,21 @@ func (d *Device) ConfigureSPI(config *Config) error { //MODE = 0 --> 12 bit conversion //SER/DFR = 0 --> Differential preferred for pressure //PD1-PD0 = 10 --> Powerdown and enable PEN_IRQ - d.Command(0x80) // make sure PD1 is cleared on start - + d.tx([]byte{0x80}) // make sure PD1 is cleared on start return nil } -// Tx and Rx pulled from st7789, modified for xps2046 +// tx and rx pulled from st7789, modified for xps2046 -// Tx sends data to the touchpad -func (d *Device) Tx(data []byte, isCommand bool) { +// tx sends data to the touchpad. +func (d *Device) tx(data []byte) { d.t_cs.Low() d.bus.Tx(data, nil) d.t_cs.High() } -// Rx reads data from the touchpad -func (d *Device) Rx(command uint8, data []byte) { - // XXX only valid for SPI +// rx reads data from the touchpad. +func (d *Device) rx(command uint8, data []byte) { cmd := make([]byte, len(data)) cmd[0] = command d.t_cs.Low() @@ -112,22 +125,12 @@ func (d *Device) Rx(command uint8, data []byte) { d.t_cs.High() } -// Command sends a command to the touch screen. -func (d *Device) Command(command uint8) { - // XXX only valid for SPI - d.Tx([]byte{command}, true) -} - -// Data sends data to the touch screen. // XXX needed? -func (d *Device) Data(data uint8) { - // XXX only valid for SPI - d.Tx([]byte{data}, false) -} - +// Very short sleep for GPIO pulsing. func busSleep() { time.Sleep(5 * time.Nanosecond) } +// Pulse the given pin p high and then low. func pulseHigh(p machine.Pin) { p.High() busSleep() @@ -135,6 +138,7 @@ func pulseHigh(p machine.Pin) { busSleep() } +// Write a command to the touchscreen using GPIO. func (d *Device) writeCommand(data uint8) { for count := uint8(0); count < 8; count++ { @@ -145,6 +149,7 @@ func (d *Device) writeCommand(data uint8) { } +// Read whatever data is waiting on t_dout using GPIO. func (d *Device) readData() uint16 { data := uint16(0) @@ -164,6 +169,10 @@ func (d *Device) readData() uint16 { return data } +// Read the X, Y, and Z (pressure) coordinates of the point currently being +// touched on the screen. Works for both GPIO and SPI by calling the associated +// raw read routines. The device is queried at most d.precision times, with +// the resulting touch.Point having the average values for each of X, Y, and Z. func (d *Device) ReadTouchPoint() touch.Point { tx := uint32(0) @@ -213,11 +222,13 @@ func (d *Device) ReadTouchPoint() touch.Point { } } +// Touched() is true if the touch device senses a touch at the current moment. func (d *Device) Touched() bool { avail := !d.t_irq.Get() return avail } +// Read the current X, Y, and Z values using the GPIO interface. func (d *Device) readRaw() (int32, int32, int32) { d.t_cs.Low() @@ -266,6 +277,7 @@ func (d *Device) readRaw() (int32, int32, int32) { return int32(tx) << 4, int32(4096-ty) << 4, tz } +// Read the current X, Y, and Z values using the SPI interface. func (d *Device) readRawSPI() (int32, int32, int32) { data := make([]byte, 4) @@ -276,7 +288,7 @@ func (d *Device) readRawSPI() (int32, int32, int32) { //SER/DFR = 0 --> Differential preferred for X,Y position //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ - d.Rx(0xD0, data) + d.rx(0xD0, data) tx := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[1], remaining 5 from top of data[2] //S = 1 --> Required Control bit @@ -285,7 +297,7 @@ func (d *Device) readRawSPI() (int32, int32, int32) { //SER/DFR = 0 --> Differential preferred for X,Y position //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ - d.Rx(0x90, data) + d.rx(0x90, data) ty := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[0], remaining 5 from top of data[1] //S = 1 --> Required Control bit @@ -294,7 +306,7 @@ func (d *Device) readRawSPI() (int32, int32, int32) { //SER/DFR = 0 --> Differential preferred for pressure //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ - d.Rx(0xB0, data) + d.rx(0xB0, data) tz1 := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[0], remaining 5 from top of data[1] //S = 1 --> Required Control bit @@ -303,7 +315,7 @@ func (d *Device) readRawSPI() (int32, int32, int32) { //SER/DFR = 0 --> Differential preferred for pressure //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ - d.Rx(0xC0, data) + d.rx(0xC0, data) tz2 := int32((uint16(data[1])<<8 | uint16(data[2])) >> 3) // 7 bits come from data[0], remaining 5 from top of data[1] tz := int32(0) From 6ed861998e9a2e41995b04d59218757348bdfeee Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Mon, 24 Oct 2022 22:02:52 -0600 Subject: [PATCH 15/17] Add an example for SPI usage too. --- examples/xpt2046/mainspi.go | 116 ++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 examples/xpt2046/mainspi.go diff --git a/examples/xpt2046/mainspi.go b/examples/xpt2046/mainspi.go new file mode 100644 index 000000000..6d05fe2b5 --- /dev/null +++ b/examples/xpt2046/mainspi.go @@ -0,0 +1,116 @@ +package main + +import ( + "machine" + "image/color" + "time" + "strconv" + "tinygo.org/x/drivers" + "tinygo.org/x/drivers/st7789" + // "tinygo.org/x/drivers/xpt2046" + "github.com/gregoster/tinygo-drivers/xpt2046" + "tinygo.org/x/tinyfont" + "tinygo.org/x/tinyfont/freemono" +) + +func initSPI() drivers.SPI { + machine.SPI1.Configure(machine.SPIConfig{ + Frequency: 3000000, + Mode: 0, + }) + + return machine.SPI1 + +} + +func initDisplay(bus drivers.SPI) (drivers.Displayer, st7789.Device) { + + // https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8 + display := st7789.New(bus, + machine.GPIO15, // TFT_RESET - reset pin + machine.GPIO8, // TFT_DC - Data/Command + machine.GPIO9, // TFT_CS - Chip Select + machine.GPIO13) // TFT_LITE - Backlite pin + + + display.Configure(st7789.Config{ + Rotation: st7789.ROTATION_270, + RowOffset: 0, + FrameRate: st7789.FRAMERATE_60, + VSyncLines: st7789.MAX_VSYNC_SCANLINES, + Width: 240, + Height: 320, + }) + return &display, display +} + +func initTouch(bus drivers.SPI) xpt2046.Device { + // clk := machine.GPIO10 // TP_CLK + cs := machine.GPIO16 // TP_CS + // din := machine.GPIO11 // MOSI + // dout := machine.GPIO12 // MISO + irq := machine.GPIO17 // TP_IRQ + + touchScreen := xpt2046.New(bus, cs, irq) + + touchScreen.Configure(&xpt2046.Config{ + Precision: 10, //Maximum number of samples for a single ReadTouchPoint to improve accuracy. + }) + return touchScreen + +} + +func main() { + + SPI := initSPI() + + touchScreen := initTouch(SPI) + + display, _ := initDisplay(SPI) + width, height := display.Size() + + //white := color.RGBA{255, 255, 255, 255} + + // red := color.RGBA{255, 0, 0, 255} + blue := color.RGBA{0, 0, 255, 255} + green := color.RGBA{0, 255, 0, 255} + black := color.RGBA{0, 0, 0, 255} + // yellow := color.RGBA{255,255,0,255} + + tinyfont.WriteLine(display, &freemono.Regular9pt7b, 30, + 80,strconv.Itoa(int(width)) + "x" + strconv.Itoa(int(height)), green) + + prev := "" + + // tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0, 160, "HERE!", red) + // tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0, 200, strconv.Itoa(int(machine.SPI1.GetBaudRate())), red) + + for { + + + //Wait for a touch + for !touchScreen.Touched() { + time.Sleep(50 * time.Millisecond) + } + + if prev != "" { + tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0,180, prev, black) + } + + 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 + + //Example of scaling for a 240x320 display + + prev = strconv.Itoa(int((touch.X*240)>>16)) + "x" + strconv.Itoa(int(touch.Y*320)>>16) + tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0, 180, prev, blue) + + //Wait for touch to end + for touchScreen.Touched() { + time.Sleep(50 * time.Millisecond) + } + } + +} From 4ad5b423e99ee4b910be5776597ed2af01b03a46 Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Wed, 26 Oct 2022 18:41:27 -0600 Subject: [PATCH 16/17] Move examples into their own directories. --- examples/xpt2046/{ => gpio}/main.go | 0 examples/xpt2046/{mainspi.go => spi/main.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename examples/xpt2046/{ => gpio}/main.go (100%) rename examples/xpt2046/{mainspi.go => spi/main.go} (100%) diff --git a/examples/xpt2046/main.go b/examples/xpt2046/gpio/main.go similarity index 100% rename from examples/xpt2046/main.go rename to examples/xpt2046/gpio/main.go diff --git a/examples/xpt2046/mainspi.go b/examples/xpt2046/spi/main.go similarity index 100% rename from examples/xpt2046/mainspi.go rename to examples/xpt2046/spi/main.go From 817db4816f9c3d5c3b64c92aea0318266340e3cf Mon Sep 17 00:00:00 2001 From: Greg Oster Date: Wed, 26 Oct 2022 19:09:26 -0600 Subject: [PATCH 17/17] go fmt --- examples/xpt2046/spi/main.go | 84 ++++++++++++++++++------------------ xpt2046/xpt2046.go | 4 +- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/examples/xpt2046/spi/main.go b/examples/xpt2046/spi/main.go index 6d05fe2b5..b914e4dba 100644 --- a/examples/xpt2046/spi/main.go +++ b/examples/xpt2046/spi/main.go @@ -1,10 +1,10 @@ package main import ( - "machine" "image/color" - "time" + "machine" "strconv" + "time" "tinygo.org/x/drivers" "tinygo.org/x/drivers/st7789" // "tinygo.org/x/drivers/xpt2046" @@ -15,61 +15,60 @@ import ( func initSPI() drivers.SPI { machine.SPI1.Configure(machine.SPIConfig{ - Frequency: 3000000, - Mode: 0, - }) + Frequency: 3000000, + Mode: 0, + }) return machine.SPI1 } func initDisplay(bus drivers.SPI) (drivers.Displayer, st7789.Device) { - + // https://www.waveshare.com/wiki/Pico-ResTouch-LCD-2.8 - display := st7789.New(bus, - machine.GPIO15, // TFT_RESET - reset pin - machine.GPIO8, // TFT_DC - Data/Command + display := st7789.New(bus, + machine.GPIO15, // TFT_RESET - reset pin + machine.GPIO8, // TFT_DC - Data/Command machine.GPIO9, // TFT_CS - Chip Select - machine.GPIO13) // TFT_LITE - Backlite pin - + machine.GPIO13) // TFT_LITE - Backlite pin - display.Configure(st7789.Config{ + display.Configure(st7789.Config{ Rotation: st7789.ROTATION_270, - RowOffset: 0, - FrameRate: st7789.FRAMERATE_60, - VSyncLines: st7789.MAX_VSYNC_SCANLINES, + RowOffset: 0, + FrameRate: st7789.FRAMERATE_60, + VSyncLines: st7789.MAX_VSYNC_SCANLINES, Width: 240, Height: 320, - }) + }) return &display, display } func initTouch(bus drivers.SPI) xpt2046.Device { // clk := machine.GPIO10 // TP_CLK - cs := machine.GPIO16 // TP_CS - // din := machine.GPIO11 // MOSI - // dout := machine.GPIO12 // MISO - irq := machine.GPIO17 // TP_IRQ + cs := machine.GPIO16 // TP_CS + // din := machine.GPIO11 // MOSI + // dout := machine.GPIO12 // MISO + irq := machine.GPIO17 // TP_IRQ - touchScreen := xpt2046.New(bus, cs, irq) + touchScreen := xpt2046.New(bus, cs, irq) - touchScreen.Configure(&xpt2046.Config{ - Precision: 10, //Maximum number of samples for a single ReadTouchPoint to improve accuracy. - }) + touchScreen.Configure(&xpt2046.Config{ + Precision: 10, //Maximum number of samples for a single ReadTouchPoint to improve accuracy. + }) return touchScreen - + } func main() { SPI := initSPI() - + touchScreen := initTouch(SPI) display, _ := initDisplay(SPI) width, height := display.Size() - - //white := color.RGBA{255, 255, 255, 255} + + //white := color.RGBA{255, 255, 255, 255} // red := color.RGBA{255, 0, 0, 255} blue := color.RGBA{0, 0, 255, 255} @@ -78,39 +77,38 @@ func main() { // yellow := color.RGBA{255,255,0,255} tinyfont.WriteLine(display, &freemono.Regular9pt7b, 30, - 80,strconv.Itoa(int(width)) + "x" + strconv.Itoa(int(height)), green) - + 80, strconv.Itoa(int(width))+"x"+strconv.Itoa(int(height)), green) + prev := "" // tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0, 160, "HERE!", red) // tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0, 200, strconv.Itoa(int(machine.SPI1.GetBaudRate())), red) for { - - - //Wait for a touch + + //Wait for a touch for !touchScreen.Touched() { time.Sleep(50 * time.Millisecond) - } + } if prev != "" { - tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0,180, prev, black) + tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0, 180, prev, black) } 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 + //Z is 24 bit and is typically > 2000 for a touch + + //Example of scaling for a 240x320 display - //Example of scaling for a 240x320 display - prev = strconv.Itoa(int((touch.X*240)>>16)) + "x" + strconv.Itoa(int(touch.Y*320)>>16) tinyfont.WriteLine(display, &freemono.Regular9pt7b, 0, 180, prev, blue) - //Wait for touch to end - for touchScreen.Touched() { - time.Sleep(50 * time.Millisecond) - } + //Wait for touch to end + for touchScreen.Touched() { + time.Sleep(50 * time.Millisecond) + } } - + } diff --git a/xpt2046/xpt2046.go b/xpt2046/xpt2046.go index 54337a303..7d79e6582 100644 --- a/xpt2046/xpt2046.go +++ b/xpt2046/xpt2046.go @@ -46,7 +46,7 @@ func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { } // Create a new SPI-based device. GPIO not available for this instance -// when SPI is used. +// when SPI is used. func NewSPI(bus drivers.SPI, t_cs, t_irq machine.Pin) Device { return Device{ bus: bus, @@ -103,7 +103,7 @@ func (d *Device) ConfigureSPI(config *Config) error { //MODE = 0 --> 12 bit conversion //SER/DFR = 0 --> Differential preferred for pressure //PD1-PD0 = 10 --> Powerdown and enable PEN_IRQ - d.tx([]byte{0x80}) // make sure PD1 is cleared on start + d.tx([]byte{0x80}) // make sure PD1 is cleared on start return nil }