tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/touch/resistive/fourwire.go (about)

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