LCOV - code coverage report
Current view: top level - src/AH/Hardware - ButtonMatrix.ipp (source / functions) Hit Total Coverage
Test: 169c36a3797bc662d84b5726f34a3f37d3c58247 Lines: 37 38 97.4 %
Date: 2024-11-09 15:32:27 Functions: 30 72 41.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.15