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

     1  // Package mcp3008 implements a driver for the MCP3008 Analog to Digital Converter.
     2  //
     3  // Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf
     4  package mcp3008 // import "tinygo.org/x/drivers/mcp3008"
     5  
     6  import (
     7  	"errors"
     8  	"machine"
     9  
    10  	"tinygo.org/x/drivers"
    11  )
    12  
    13  // Device wraps MCP3008 SPI ADC.
    14  type Device struct {
    15  	bus drivers.SPI
    16  	cs  machine.Pin
    17  	tx  []byte
    18  	rx  []byte
    19  	CH0 ADCPin
    20  	CH1 ADCPin
    21  	CH2 ADCPin
    22  	CH3 ADCPin
    23  	CH4 ADCPin
    24  	CH5 ADCPin
    25  	CH6 ADCPin
    26  	CH7 ADCPin
    27  }
    28  
    29  // ADCPin is the implementation of the ADConverter interface.
    30  type ADCPin struct {
    31  	machine.Pin
    32  	d *Device
    33  }
    34  
    35  // New returns a new MCP3008 driver. Pass in a fully configured SPI bus.
    36  func New(b drivers.SPI, csPin machine.Pin) *Device {
    37  	d := &Device{bus: b,
    38  		cs: csPin,
    39  		tx: make([]byte, 3),
    40  		rx: make([]byte, 3),
    41  	}
    42  
    43  	// setup all channels
    44  	d.CH0 = d.GetADC(0)
    45  	d.CH1 = d.GetADC(1)
    46  	d.CH2 = d.GetADC(2)
    47  	d.CH3 = d.GetADC(3)
    48  	d.CH4 = d.GetADC(4)
    49  	d.CH5 = d.GetADC(5)
    50  	d.CH6 = d.GetADC(6)
    51  	d.CH7 = d.GetADC(7)
    52  
    53  	return d
    54  }
    55  
    56  // Configure sets up the device for communication
    57  func (d *Device) Configure() {
    58  	d.cs.Configure(machine.PinConfig{Mode: machine.PinOutput})
    59  }
    60  
    61  // Read analog data from channel
    62  func (d *Device) Read(ch int) (uint16, error) {
    63  	if ch < 0 || ch > 7 {
    64  		return 0, errors.New("invalid channel for MCP3008 Read")
    65  	}
    66  
    67  	return d.GetADC(ch).Get(), nil
    68  }
    69  
    70  // GetADC returns an ADC for a specific channel.
    71  func (d *Device) GetADC(ch int) ADCPin {
    72  	return ADCPin{machine.Pin(ch), d}
    73  }
    74  
    75  // Get the current reading for a specific ADCPin.
    76  func (p ADCPin) Get() uint16 {
    77  	p.d.tx[0] = 0x01
    78  	p.d.tx[1] = byte(8+p.Pin) << 4
    79  	p.d.tx[2] = 0x00
    80  
    81  	p.d.cs.Low()
    82  	p.d.bus.Tx(p.d.tx, p.d.rx)
    83  
    84  	// scale result to 16bit value like other ADCs
    85  	result := uint16((p.d.rx[1]&0x3))<<(8+6) + uint16(p.d.rx[2])<<6
    86  	p.d.cs.High()
    87  
    88  	return result
    89  }
    90  
    91  // Configure here just for interface compatibility.
    92  func (p ADCPin) Configure() {
    93  }