tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/xpt2046/xpt2046.go (about) 1 // Package xpt2046 implements a driver for the XPT2046 resistive touch controller as packaged on the TFT_320QVT board 2 // 3 // Datasheet: http://grobotronics.com/images/datasheets/xpt2046-datasheet.pdf 4 package xpt2046 5 6 import ( 7 "machine" 8 "time" 9 10 "tinygo.org/x/drivers/touch" 11 ) 12 13 type Device struct { 14 t_clk machine.Pin 15 t_cs machine.Pin 16 t_din machine.Pin 17 t_dout machine.Pin 18 t_irq machine.Pin 19 20 precision uint8 21 } 22 23 type Config struct { 24 Precision uint8 25 } 26 27 func New(t_clk, t_cs, t_din, t_dout, t_irq machine.Pin) Device { 28 return Device{ 29 precision: 10, 30 t_clk: t_clk, 31 t_cs: t_cs, 32 t_din: t_din, 33 t_dout: t_dout, 34 t_irq: t_irq, 35 } 36 } 37 38 func (d *Device) Configure(config *Config) error { 39 40 if config.Precision == 0 { 41 d.precision = 10 42 } else { 43 d.precision = config.Precision 44 } 45 46 d.t_clk.Configure(machine.PinConfig{Mode: machine.PinOutput}) 47 d.t_cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) 48 d.t_din.Configure(machine.PinConfig{Mode: machine.PinOutput}) 49 50 d.t_dout.Configure(machine.PinConfig{Mode: machine.PinInput}) 51 d.t_irq.Configure(machine.PinConfig{Mode: machine.PinInput}) 52 53 d.t_clk.Low() 54 d.t_cs.High() 55 d.t_din.Low() 56 57 d.readRaw() //Set Powerdown mode to enable T_IRQ 58 59 return nil 60 } 61 62 func busSleep() { 63 time.Sleep(5 * time.Nanosecond) 64 } 65 66 func pulseHigh(p machine.Pin) { 67 p.High() 68 busSleep() 69 p.Low() 70 busSleep() 71 } 72 73 func (d *Device) writeCommand(data uint8) { 74 75 for count := uint8(0); count < 8; count++ { 76 d.t_din.Set((data & 0x80) != 0) 77 data <<= 1 78 pulseHigh(d.t_clk) 79 } 80 81 } 82 83 func (d *Device) readData() uint16 { 84 85 data := uint16(0) 86 87 for count := uint8(0); count < 12; count++ { 88 data <<= 1 89 pulseHigh(d.t_clk) 90 if d.t_dout.Get() { 91 data |= 1 92 } 93 } 94 pulseHigh(d.t_clk) //13 95 pulseHigh(d.t_clk) //14 96 pulseHigh(d.t_clk) //15 97 pulseHigh(d.t_clk) //16 98 99 return data 100 } 101 102 func (d *Device) ReadTouchPoint() touch.Point { 103 104 tx := uint32(0) 105 ty := uint32(0) 106 tz := uint32(0) 107 sampleCount := uint8(0) 108 109 d.t_cs.Low() 110 111 for ; sampleCount < d.precision && d.Touched(); sampleCount++ { 112 rx, ry, rz := d.readRaw() 113 tx += uint32(rx) 114 ty += uint32(ry) 115 tz += uint32(rz) 116 } 117 d.t_cs.High() 118 119 if sampleCount > 0 { 120 x := int(tx / uint32(sampleCount)) 121 y := int(ty / uint32(sampleCount)) 122 z := int(tz / uint32(sampleCount)) 123 return touch.Point{ 124 X: x, 125 Y: y, 126 Z: z, 127 } 128 } else { 129 return touch.Point{ 130 X: 0, 131 Y: 0, 132 Z: 0, 133 } 134 } 135 } 136 137 func (d *Device) Touched() bool { 138 avail := !d.t_irq.Get() 139 return avail 140 } 141 142 func (d *Device) readRaw() (int32, int32, int32) { 143 144 d.t_cs.Low() 145 146 //S = 1 --> Required Control bit 147 //A2-A0 = 001 --> Y-Position 148 //MODE = 0 --> 12 bit conversion 149 //SER/DFR = 0 --> Differential preferred for X,Y position 150 //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ 151 d.writeCommand(0x90) 152 ty := d.readData() 153 154 //S = 1 --> Required Control bit 155 //A2-A0 = 101 --> X-Position 156 //MODE = 0 --> 12 bit conversion 157 //SER/DFR = 0 --> Differential preferred for X,Y position 158 //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ 159 d.writeCommand(0xD0) 160 tx := d.readData() 161 162 //S = 1 --> Required Control bit 163 //A2-A0 = 011 --> Z1-position (pressure) 164 //MODE = 0 --> 12 bit conversion 165 //SER/DFR = 0 --> Differential preferred for pressure 166 //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ 167 d.writeCommand(0xB0) 168 tz1 := int32(d.readData()) 169 170 //S = 1 --> Required Control bit 171 //A2-A0 = 100 --> Z2-position (pressure) 172 //MODE = 0 --> 12 bit conversion 173 //SER/DFR = 0 --> Differential preferred for pressure 174 //PD1-PD0 = 00 --> Powerdown and enable PEN_IRQ 175 d.writeCommand(0xC0) 176 tz2 := int32(d.readData()) 177 178 tz := int32(0) 179 if tz1 != 0 { 180 //Touch pressure is proportional to the ratio of z2 to z1 and the x position. 181 tz = int32(tx) * ((tz2 << 12) / (tz1 << 12)) 182 } 183 184 d.t_cs.High() 185 186 //Scale X&Y to 16 bit for consistency across touch drivers 187 return int32(tx) << 4, int32(4096-ty) << 4, tz 188 }