diff --git a/Makefile b/Makefile index 2b0e0e0..fc1a11c 100644 --- a/Makefile +++ b/Makefile @@ -65,6 +65,8 @@ smoke-test: @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go @md5sum ./build/test.hex + tinygo build -size short -o ./build/test.hex -target=pybadge ./examples/shifter/main.go + @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=microbit ./examples/sht3x/main.go @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=microbit ./examples/ssd1306/i2c_128x32/main.go diff --git a/README.md b/README.md index dfb239d..8fc96cf 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ The following 34 devices are supported. | [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C | | [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C | | [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI | +| [Shift register](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO | | [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/0_Datasheets/Humidity/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C | | [SSD1306 OLED display](https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf) | I2C / SPI | | [SSD1331 TFT color display](https://www.crystalfontz.com/controllers/SolomonSystech/SSD1331/381/) | SPI | diff --git a/examples/shifter/main.go b/examples/shifter/main.go new file mode 100644 index 0000000..7170387 --- /dev/null +++ b/examples/shifter/main.go @@ -0,0 +1,50 @@ +package main + +import ( + "machine" + "time" + + "tinygo.org/x/drivers/shifter" +) + +func main() { + buttons := shifter.New(shifter.EIGHT_BITS, machine.BUTTON_LATCH, machine.BUTTON_CLK, machine.BUTTON_OUT) + buttons.Configure() + + for { + // Slower + for i := 0; i < 8; i++ { + if buttons.Pins[i].Get() { + println("Button", i, "pressed") + } + } + + // Faster + pressed, _ := buttons.Read8Input() + if pressed&machine.BUTTON_LEFT_MASK > 0 { + println("Button LEFT pressed") + } + if pressed&machine.BUTTON_UP_MASK > 0 { + println("Button UP pressed") + } + if pressed&machine.BUTTON_DOWN_MASK > 0 { + println("Button DOWN pressed") + } + if pressed&machine.BUTTON_RIGHT_MASK > 0 { + println("Button RIGHT pressed") + } + if pressed&machine.BUTTON_SELECT_MASK > 0 { + println("Button SELECT pressed") + } + if pressed&machine.BUTTON_START_MASK > 0 { + println("Button START pressed") + } + if pressed&machine.BUTTON_A_MASK > 0 { + println("Button A pressed") + } + if pressed&machine.BUTTON_B_MASK > 0 { + println("Button B pressed") + } + time.Sleep(100 * time.Millisecond) + } +} diff --git a/shifter/shifter.go b/shifter/shifter.go new file mode 100644 index 0000000..30e90f3 --- /dev/null +++ b/shifter/shifter.go @@ -0,0 +1,104 @@ +// Package shifter is for 8bit shift register, most common are 74HC165 and 74165 +package shifter // import "tinygo.org/x/drivers/shifter" + +import ( + "errors" + "machine" +) + +const ( + EIGHT_BITS NumberBit = 8 + SIXTEEN_BITS NumberBit = 16 + THIRTYTWO_BITS NumberBit = 32 +) + +type NumberBit int8 + +// Device holds the Pins. +type Device struct { + latch machine.Pin + clk machine.Pin + out machine.Pin + Pins []ShiftPin + bits NumberBit +} + +// ShiftPin is the implementation of the ShiftPin interface. +type ShiftPin struct { + pin machine.Pin + d *Device +} + +// New returns a new thermistor driver given an ADC pin. +func New(numBits NumberBit, latch, clk, out machine.Pin) Device { + return Device{ + latch: latch, + clk: clk, + out: out, + Pins: make([]ShiftPin, int(numBits)), + bits: numBits, + } +} + +// Configure here just for interface compatibility. +func (d *Device) Configure() { + d.latch.Configure(machine.PinConfig{Mode: machine.PinOutput}) + d.clk.Configure(machine.PinConfig{Mode: machine.PinOutput}) + d.out.Configure(machine.PinConfig{Mode: machine.PinInput}) + for i := 0; i < int(d.bits); i++ { + d.Pins[i] = d.GetShiftPin(i) + } +} + +// GetShiftPin returns an ShiftPin for a specific input. +func (d *Device) GetShiftPin(input int) ShiftPin { + return ShiftPin{pin: machine.Pin(input), d: d} +} + +// Read8Input reads the 8 inputs and return an uint8 +func (d *Device) Read8Input() (uint8, error) { + if d.bits != EIGHT_BITS { + return 0, errors.New("wrong amount of registers") + } + return uint8(d.readInput(EIGHT_BITS)), nil +} + +// Read16Input reads the 16 inputs and return an uint16 +func (d *Device) Read16Input() (uint16, error) { + if d.bits != SIXTEEN_BITS { + return 0, errors.New("wrong amount of registers") + } + return uint16(d.readInput(SIXTEEN_BITS)), nil +} + +// Read32Input reads the 32 inputs and return an uint32 +func (d *Device) Read32Input() (uint32, error) { + if d.bits != THIRTYTWO_BITS { + return 0, errors.New("wrong amount of registers") + } + return d.readInput(THIRTYTWO_BITS), nil +} + +// Get the current reading for a specific ShiftPin. +func (p ShiftPin) Get() bool { + return (p.d.readInput(p.d.bits) & (1 << int(p.pin))) > 0 +} + +// Configure here just for interface compatibility. +func (p ShiftPin) Configure() { +} + +// readInput reads howMany bits from the shift register +func (d *Device) readInput(howMany NumberBit) uint32 { + d.latch.High() + var data uint32 + for i := howMany - 1; i >= 0; i-- { + d.clk.Low() + if d.out.Get() { + data |= 1 << i + } + d.clk.High() + } + d.latch.Low() + return data +}