-
Notifications
You must be signed in to change notification settings - Fork 183
/
fourwire.go
124 lines (93 loc) · 3.34 KB
/
fourwire.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package resistive
import (
"machine"
"tinygo.org/x/drivers/touch"
)
// FourWire represents a resistive touchscreen with a four-wire interface as
// described in http://ww1.microchip.com/downloads/en/Appnotes/doc8091.pdf
type FourWire struct {
yp machine.ADC
ym machine.ADC
xp machine.ADC
xm machine.ADC
readSamples int
}
// FourWireConfig is passed to the Configure method. All of the pins must be
// specified for this to be a valid configuration. ReadSamples is optional, and
// if not set with default to 2.
type FourWireConfig struct {
// Y+ pin, must be capable of analog reads
YP machine.Pin
// Y- pin, must be capable of analog reads
YM machine.Pin
// X+ pin, must be capable of analog reads
XP machine.Pin
// X- pin, must be capable of analog reads
XM machine.Pin
// If set, each call to ReadTouchPoint() will sample the X, Y, and Z values
// and average them. This can help smooth out spurious readings, for example
// ones that result from the capacitance of a TFT under the touchscreen
ReadSamples int
}
// Configure should be called once before starting to read the device
func (res *FourWire) Configure(config *FourWireConfig) error {
res.yp = machine.ADC{Pin: config.YP}
res.ym = machine.ADC{Pin: config.YM}
res.xp = machine.ADC{Pin: config.XP}
res.xm = machine.ADC{Pin: config.XM}
if config.ReadSamples < 1 {
res.readSamples = 2
} else {
res.readSamples = config.ReadSamples
}
return nil
}
// ReadTouchPoint reads a single touch.Point from the device. If the device
// was configured with ReadSamples > 1, each value will be sampled that many
// times and averaged to smooth over spurious results of the analog reads.
func (res *FourWire) ReadTouchPoint() (p touch.Point) {
p.X = int(sample(res.ReadX, res.readSamples))
p.Y = int(sample(res.ReadY, res.readSamples))
p.Z = int(sample(res.ReadZ, res.readSamples))
return
}
// sample the results of the provided function and average the results
func sample(fn func() uint16, numSamples int) (v uint16) {
sum := 0
for n := 0; n < numSamples; n++ {
sum += int(fn())
}
return uint16(sum / numSamples)
}
// ReadX reads the "raw" X-value on a 16-bit scale without multiple sampling
func (res *FourWire) ReadX() uint16 {
res.ym.Pin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
res.xp.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
res.xp.Pin.High()
res.xm.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
res.xm.Pin.Low()
res.yp.Configure(machine.ADCConfig{})
return 0xFFFF - res.yp.Get()
}
// ReadY reads the "raw" Y-value on a 16-bit scale without multiple sampling
func (res *FourWire) ReadY() uint16 {
res.xm.Pin.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
res.yp.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
res.yp.Pin.High()
res.ym.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
res.ym.Pin.Low()
res.xp.Configure(machine.ADCConfig{})
return 0xFFFF - res.xp.Get()
}
// ReadZ reads the "raw" Z-value on a 16-bit scale without multiple sampling
func (res *FourWire) ReadZ() uint16 {
res.xp.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
res.xp.Pin.Low()
res.ym.Pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
res.ym.Pin.High()
res.xm.Configure(machine.ADCConfig{})
res.yp.Configure(machine.ADCConfig{})
z1 := res.xm.Get()
z2 := res.yp.Get()
return 0xFFFF - (z2 - z1)
}