#include "hardware/gpio.h" #include "keypad.hpp" Keypad::Keypad(uint *rows, uint *cols, char chars[4][4]) : rows{rows}, cols{cols} { initCharArray(chars); init(); } /* * Get pressed key. */ char Keypad::getKey() { int column_index = pressedColumn(); int row_index; if(column_index < 0) return '\0'; pullPinsDown(cols); for(int i = 0; i < KEYPAD_LEN; ++i) { gpio_put(rows[i], 1); int row_state = gpio_get(rows[i]); int column_state = gpio_get(cols[column_index]); if(row_state & column_state) { row_index = i; break; } } restartPins(); return chars[row_index][column_index]; } /* * See if a key is pressed. * All columns are pulled up, so if a key is pressed, * its corresponding column should be pulled down. */ bool Keypad::keyPressed() { return pressedColumn() < 0; } /* * Copy the char matrix passed to the constructor to * the object's chars attribute. */ void Keypad::initCharArray(char chars[4][4]) { for(int i = 0; i < KEYPAD_LEN; ++i) { for(int j = 0; j < KEYPAD_LEN; ++j) this->chars[i][j] = chars[i][j]; } } /* * Initialize the GPIO pins that will be used by the * keypad. * row pins: pulled low and set as outputs. * column pins: pulled high and set as inputs. */ void Keypad::init() { for (int i = 0; i < KEYPAD_LEN; ++i) { gpio_init(rows[i]); gpio_init(cols[i]); gpio_set_dir(rows[i], OUT); gpio_set_dir(cols[i], IN); gpio_pull_down(rows[i]); gpio_pull_up(cols[i]); } } /* * Get the column that's being pressed. * If no column is getting pressed (i.e, no button * is getting pressed) return -1, otherwise return * the index of the column being pressed. */ uint Keypad::pressedColumn() { for (int i = 0; i < KEYPAD_LEN; ++i) { if(!gpio_get(cols[i])) return i; } return -1; } /* * Pull every GPIO pin in pins down. */ void Keypad::pullPinsDown(uint *pins) { for(int i = 0; i < KEYPAD_LEN; ++i) gpio_pull_down(pins[i]); } /* * Leave the state of pins as it was before reading. * (Columns pulled up, rows pulled down); */ void Keypad::restartPins() { for(int i = 0; i < KEYPAD_LEN; ++i) { gpio_pull_up(cols[i]); gpio_put(rows[i], 0); } }