From 84408279de57b09f6eb7fc001c4dd64c4d255f43 Mon Sep 17 00:00:00 2001 From: Nerzal Date: Mon, 22 Mar 2021 15:25:43 +0100 Subject: [PATCH] add 4x4 keypad driver (#226) add 4x4 keypad driver --- Makefile | 4 +- README.md | 1 + examples/keypad4x4/main.go | 38 +++++++++++++ keypad4x4/keypad4x4.go | 107 +++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 examples/keypad4x4/main.go create mode 100644 keypad4x4/keypad4x4.go diff --git a/Makefile b/Makefile index 5289a8c..f073712 100644 --- a/Makefile +++ b/Makefile @@ -169,11 +169,13 @@ endif @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=feather-m0 ./examples/dht/main.go @md5sum ./build/test.hex + tinygo build -size short -o ./build/test.hex -target=arduino ./examples/keypad4x4/main.go + @md5sum ./build/test.hex DRIVERS = $(wildcard */) NOTESTS = build examples flash semihosting pcd8544 shiftregister st7789 microphone mcp3008 gps microbitmatrix \ hcsr04 ssd1331 ws2812 thermistor apa102 easystepper ssd1351 ili9341 wifinina shifter hub75 \ - hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht max72xx + hd44780 buzzer ssd1306 espat l9110x st7735 bmi160 l293x dht keypad4x4 max72xx TESTS = $(filter-out $(addsuffix /%,$(NOTESTS)),$(DRIVERS)) unit-test: diff --git a/README.md b/README.md index efcb5e7..34398ff 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ The following 58 devices are supported. | [HD44780 LCD controller](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) | GPIO/I2C | | [HUB75 RGB led matrix](https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf) | SPI | | [ILI9341 TFT color display](https://cdn-shop.adafruit.com/datasheets/ILI9341.pdf) | SPI | +| [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO | | [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM | | [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM | | [LIS2MDL magnetometer](https://www.st.com/resource/en/datasheet/lis2mdl.pdf) | I2C | diff --git a/examples/keypad4x4/main.go b/examples/keypad4x4/main.go new file mode 100644 index 0000000..e02215c --- /dev/null +++ b/examples/keypad4x4/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "machine" + + "tinygo.org/x/drivers/keypad4x4" +) + +func main() { + mapping := map[uint8]string{ + 1: "1", + 2: "2", + 3: "3", + 4: "A", + 5: "4", + 6: "5", + 7: "6", + 8: "B", + 9: "7", + 10: "8", + 11: "9", + 12: "C", + 13: "*", + 14: "0", + 15: "#", + 16: "D", + } + + keypadDevice := keypad4x4.NewDevice(machine.D2, machine.D3, machine.D4, machine.D5, machine.D6, machine.D7, machine.D8, machine.D9) + keypadDevice.Configure() + + for { + key := keypadDevice.GetKey() + if key != keypad4x4.NoKeyPressed { + println("Button: ", mapping[key]) + } + } +} diff --git a/keypad4x4/keypad4x4.go b/keypad4x4/keypad4x4.go new file mode 100644 index 0000000..f4adafb --- /dev/null +++ b/keypad4x4/keypad4x4.go @@ -0,0 +1,107 @@ +package keypad4x4 + +import ( + "machine" +) + +// NoKeyPressed is used, when no key was pressed +const NoKeyPressed = 255 + +// Device is used as 4x4 keypad driver +type Device interface { + Configure() + GetKey() uint8 + GetIndices() (int, int) +} + +// device is a driver for 4x4 keypads +type device struct { + inputEnabled bool + lastColumn int + lastRow int + columns [4]machine.Pin + rows [4]machine.Pin + mapping [4][4]uint8 +} + +// takes r4 -r1 pins and c4 - c1 pins +func NewDevice(r4, r3, r2, r1, c4, c3, c2, c1 machine.Pin) Device { + result := &device{} + result.columns = [4]machine.Pin{c4, c3, c2, c1} + result.rows = [4]machine.Pin{r4, r3, r2, r1} + + return result +} + +// Configure sets the column pins as input and the row pins as output +func (keypad *device) Configure() { + inputConfig := machine.PinConfig{Mode: machine.PinInputPullup} + for i := range keypad.columns { + keypad.columns[i].Configure(inputConfig) + } + + outputConfig := machine.PinConfig{Mode: machine.PinOutput} + for i := range keypad.rows { + keypad.rows[i].Configure(outputConfig) + keypad.rows[i].High() + } + + keypad.mapping = [4][4]uint8{ + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {8, 9, 10, 11}, + {12, 13, 14, 15}, + } + + keypad.inputEnabled = true + keypad.lastColumn = -1 + keypad.lastRow = -1 +} + +// GetKey returns the code for the given key. +// The codes start with 0 at the upper left end of the keypad and end with 15 at the lower right end of the keypad +// Example: +// 0 1 2 3 +// 4 5 6 7 +// 8 9 10 11 +// 12 13 14 15 +// returns 255 for no keyPressed +func (keypad *device) GetKey() uint8 { + row, column := keypad.GetIndices() + if row == -1 && column == -1 { + return NoKeyPressed + } + + return keypad.mapping[row][column] +} + +// GetIndices returns the position of the pressed key +func (keypad *device) GetIndices() (int, int) { + for rowIndex, rowPin := range keypad.rows { + rowPin.Low() + + for columnIndex := range keypad.columns { + columnPin := keypad.columns[columnIndex] + + if !columnPin.Get() && keypad.inputEnabled { + keypad.inputEnabled = false + + keypad.lastColumn = columnIndex + keypad.lastRow = rowIndex + + return keypad.lastRow, keypad.lastColumn + } + + if columnPin.Get() && + columnIndex == keypad.lastColumn && + rowIndex == keypad.lastRow && + !keypad.inputEnabled { + keypad.inputEnabled = true + } + } + + rowPin.High() + } + + return -1, -1 +}