Line data Source code
1 : #include "ButtonMatrix.hpp" 2 : #include <AH/Hardware/ExtendedInputOutput/ExtendedInputOutput.hpp> 3 : #include <string.h> 4 : 5 : BEGIN_AH_NAMESPACE 6 : 7 : using namespace ExtIO; 8 : 9 : template <uint8_t nb_rows, uint8_t nb_cols> 10 9 : ButtonMatrix<nb_rows, nb_cols>::ButtonMatrix(const PinList<nb_rows> &rowPins, 11 : const PinList<nb_cols> &colPins) 12 18 : : rowPins(rowPins), colPins(colPins) { 13 9 : memset(prevStates, 0xFF, sizeof(prevStates)); 14 9 : } 15 : 16 : template <uint8_t nb_rows, uint8_t nb_cols> 17 10 : void ButtonMatrix<nb_rows, nb_cols>::update() { 18 10 : unsigned long now = millis(); 19 : // only update 25 ms after previous change (crude software debounce). 20 : // Edit this in Settings/Settings.hpp 21 10 : if (now - prevRefresh < BUTTON_DEBOUNCE_TIME) 22 0 : return; 23 : 24 40 : for (size_t row = 0; row < nb_rows; row++) { // scan through all rows 25 30 : pinMode(rowPins[row], OUTPUT); // make the current row Lo-Z 0V 26 90 : for (size_t col = 0; col < nb_cols; col++) { // scan through all columns 27 60 : bool state = digitalRead(colPins[col]); // read the state 28 60 : if (state != getPrevState(col, row)) { 29 : // if the state changed since last time 30 : // execute the handler 31 10 : onButtonChanged(row, col, state); 32 10 : setPrevState(col, row, state); // remember the state 33 10 : prevRefresh = now; 34 10 : } 35 60 : } 36 30 : pinMode(rowPins[row], INPUT); // make the current row Hi-Z again 37 30 : } 38 10 : } 39 : 40 : template <uint8_t nb_rows, uint8_t nb_cols> 41 3 : void ButtonMatrix<nb_rows, nb_cols>::begin() { 42 : // make all columns input pins and enable 43 : // the internal pull-up resistors 44 9 : for (const pin_t &colPin : colPins) 45 6 : pinMode(colPin, INPUT_PULLUP); 46 : // make all rows Hi-Z 47 12 : for (const pin_t &rowPin : rowPins) 48 9 : pinMode(rowPin, INPUT); 49 3 : } 50 : 51 : template <uint8_t nb_rows, uint8_t nb_cols> 52 70 : inline uint8_t ButtonMatrix<nb_rows, nb_cols>::positionToBits(uint8_t col, 53 : uint8_t row) { 54 : // map from a 2D array of bits to a flat array of bits 55 70 : return col * nb_rows + row; 56 : } 57 : 58 : template <uint8_t nb_rows, uint8_t nb_cols> 59 70 : inline uint8_t ButtonMatrix<nb_rows, nb_cols>::bitsToIndex(uint8_t bits) { 60 70 : return bits >> 3; // bits / 8 61 : } 62 : 63 : template <uint8_t nb_rows, uint8_t nb_cols> 64 70 : inline uint8_t ButtonMatrix<nb_rows, nb_cols>::bitsToBitmask(uint8_t bits) { 65 70 : return 1 << (bits & 7); // bits % 8 66 : } 67 : 68 : template <uint8_t nb_rows, uint8_t nb_cols> 69 60 : bool ButtonMatrix<nb_rows, nb_cols>::getPrevState(uint8_t col, uint8_t row) { 70 60 : uint8_t bits = positionToBits(col, row); 71 120 : return !!(prevStates[bitsToIndex(bits)] & bitsToBitmask(bits)); 72 60 : } 73 : 74 : template <uint8_t nb_rows, uint8_t nb_cols> 75 10 : void ButtonMatrix<nb_rows, nb_cols>::setPrevState(uint8_t col, uint8_t row, 76 : bool state) { 77 10 : uint8_t bits = positionToBits(col, row); 78 10 : if (state) 79 5 : prevStates[bitsToIndex(bits)] |= bitsToBitmask(bits); 80 : else 81 5 : prevStates[bitsToIndex(bits)] &= ~bitsToBitmask(bits); 82 19 : } 83 : 84 : END_AH_NAMESPACE