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

     1  // Package shifter is for 8bit shift register, most common are 74HC165 and 74165
     2  package shifter // import "tinygo.org/x/drivers/shifter"
     3  
     4  import (
     5  	"errors"
     6  	"machine"
     7  )
     8  
     9  const (
    10  	EIGHT_BITS     NumberBit = 8
    11  	SIXTEEN_BITS   NumberBit = 16
    12  	THIRTYTWO_BITS NumberBit = 32
    13  )
    14  
    15  type NumberBit int8
    16  
    17  // Device holds the Pins.
    18  type Device struct {
    19  	latch machine.Pin
    20  	clk   machine.Pin
    21  	out   machine.Pin
    22  	Pins  []ShiftPin
    23  	bits  NumberBit
    24  }
    25  
    26  // ShiftPin is the implementation of the ShiftPin interface.
    27  type ShiftPin struct {
    28  	pin     machine.Pin
    29  	d       *Device
    30  	pressed bool
    31  }
    32  
    33  // New returns a new shifter driver given the correct pins.
    34  func New(numBits NumberBit, latch, clk, out machine.Pin) Device {
    35  	return Device{
    36  		latch: latch,
    37  		clk:   clk,
    38  		out:   out,
    39  		Pins:  make([]ShiftPin, int(numBits)),
    40  		bits:  numBits,
    41  	}
    42  }
    43  
    44  // Configure here just for interface compatibility.
    45  func (d *Device) Configure() {
    46  	d.latch.Configure(machine.PinConfig{Mode: machine.PinOutput})
    47  	d.clk.Configure(machine.PinConfig{Mode: machine.PinOutput})
    48  	d.out.Configure(machine.PinConfig{Mode: machine.PinInput})
    49  	for i := 0; i < int(d.bits); i++ {
    50  		d.Pins[i] = d.GetShiftPin(i)
    51  	}
    52  }
    53  
    54  // GetShiftPin returns an ShiftPin for a specific input.
    55  func (d *Device) GetShiftPin(input int) ShiftPin {
    56  	return ShiftPin{pin: machine.Pin(input), d: d}
    57  }
    58  
    59  // Read8Input updates the internal pins' states and returns it as an uint8.
    60  func (d *Device) Read8Input() (uint8, error) {
    61  	if d.bits != EIGHT_BITS {
    62  		return 0, errors.New("wrong amount of registers")
    63  	}
    64  	return uint8(d.readInput(EIGHT_BITS)), nil
    65  }
    66  
    67  // Read16Input updates the internal pins' states and returns it as an uint16.
    68  func (d *Device) Read16Input() (uint16, error) {
    69  	if d.bits != SIXTEEN_BITS {
    70  		return 0, errors.New("wrong amount of registers")
    71  	}
    72  	return uint16(d.readInput(SIXTEEN_BITS)), nil
    73  }
    74  
    75  // Read32Input updates the internal pins' states and returns it as an uint32.
    76  func (d *Device) Read32Input() (uint32, error) {
    77  	if d.bits != THIRTYTWO_BITS {
    78  		return 0, errors.New("wrong amount of registers")
    79  	}
    80  	return d.readInput(THIRTYTWO_BITS), nil
    81  }
    82  
    83  // Get the pin's state for a specific ShiftPin.
    84  // Read{8|16|32}Input should be called before to update the state. Read{8|16|32}Input updates
    85  // all the pins, no need to call it for each pin individually.
    86  func (p ShiftPin) Get() bool {
    87  	return p.pressed
    88  }
    89  
    90  // Configure here just for interface compatibility.
    91  func (p ShiftPin) Configure() {
    92  }
    93  
    94  // readInput reads howMany bits from the shift register and updates the internal pins' states.
    95  func (d *Device) readInput(howMany NumberBit) uint32 {
    96  	d.latch.High()
    97  	var data uint32
    98  	for i := howMany - 1; i >= 0; i-- {
    99  		d.clk.Low()
   100  		if d.out.Get() {
   101  			data |= 1 << i
   102  			d.Pins[i].pressed = true
   103  		} else {
   104  			d.Pins[i].pressed = false
   105  		}
   106  		d.clk.High()
   107  	}
   108  	d.latch.Low()
   109  	return data
   110  }