Browse Source

document row files

tags/v0.5.0
wolfv6 7 years ago
parent
commit
147154f040

+ 10
- 11
doc/keybrd_library_developer_guide.md View File

@@ -204,16 +204,15 @@ Example Code_Layered class names:
## Style guide
Following the style guide makes it easier for the next programmer to understand your code.
* For class names, see above section "Class naming conventions"
* For member names, use camelCase starting with lowercase letter.
* For class names, see above section "Class naming conventions".
* Member names use camelCase starting with lowercase letter.
* Use constants rather than macros, except for header guards.
* For constant names that could be macros, use ALL_CAPS_AND_UNDERSCORE.
* **ITEM_COUNT** is a constant number of items.
* **itemCount** is a variable number of items.
* Use header guards CLASS_NAME_H.
* Prefix pointer name with "ptr" e.g. ptrRow = &row;
* Name arrays using the plural of element name e.g. Row* const = ptrsRows { &row0, &row1 };
* Pass arrays using array notation rather than pointer notation. Use
* Global const names and static const names use ALL_CAPS_AND_UNDERSCORE.
* Macros use ALL_CAPS_AND_UNDERSCORE and have _MACRO suffix e.g. SAMPLE_COUNT_MACRO
* Header guards have _H suffix e.g. #ifndef FILE_NAME_H
* Pointer names are prefixed with "ptr" e.g. ptrRow = &row;
* Arrays names use the plural of element name e.g. Row* const = ptrsRows { &row0, &row1 };
* Pass arrays using array notation rather than pointer notation:
```
void printArray(char[] array);
not
@@ -222,8 +221,8 @@ Following the style guide makes it easier for the next programmer to understand
* In constructor's initialization list, use same names for fields and constructor parameters.
* Do not use new or malloc (making memory leaks impossible).
* Document class interface in .h file, above the class declaration.
* Code should be self-documenting. The only comments should be things that may need clarification. A simple function with a good name needs no comment.
* Code is automatically formated before being pushed to the keybrd repository.
* Code should be self-documenting. A simple function with a good name needs no comment.
* Code is automatically formatted before being pushed to the keybrd repository.
The [astyle_cpp](astyle_cpp) file specifies the format:
* Allman style indentation
* indent 4 spaces

+ 11
- 12
examples/keybrd_shift_register/keybrd_shift_register.ino View File

@@ -17,7 +17,8 @@ Unused input pins are not grounded, so add this line to Scanner_ShiftRegs74HC165
// ================= INCLUDES ==================
#include <Debug.h>
#include <ScanDelay.h>
#include <LED_PinNumber.h>
#include <LED_uC.h>
#include <SPI.h>

//Codes
#include <Code_Sc.h>
@@ -25,7 +26,6 @@ Unused input pins are not grounded, so add this line to Scanner_ShiftRegs74HC165

//Matrix
#include <Row_uC.h>
#include <SPI.h>
#include <Row_ShiftRegisters.h>

// =============== CONFIGURATION ===============
@@ -48,7 +48,7 @@ uint8_t readPins[] = {14, 15};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);

// ==================== LEDs ===================
LED_PinNumber LED1(16);
LED_uC LED1(16);

//sometimes OS takes 6 seconds to recongnize keyboard, LED blinks from the begining
void wait()
@@ -111,26 +111,26 @@ Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1);
/*
//prints 0 1
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z };
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row_ShiftRegisters row_R0(8, READ_PIN_COUNT_R0, ptrsKeys_R0);

//prints a b
Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z };
const uint8_t READ_PIN_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1);
uint8_t READ_PIN_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1);
Row_ShiftRegisters row_R1(9, READ_PIN_COUNT_R1, ptrsKeys_R1);
*/
/*
//prints 0 1 2
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z };
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row_ShiftRegisters row_R0(8, READ_PIN_COUNT_R0, ptrsKeys_R0);
*/
/*
//prints 0 1 2 3
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z };
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row_ShiftRegisters row_R0(8, READ_PIN_COUNT_R0, ptrsKeys_R0);
*/
/*
@@ -138,7 +138,7 @@ Row_ShiftRegisters row_R0(8, READ_PIN_COUNT_R0, ptrsKeys_R0);
Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z,
&s_4, &s_z, &s_z, &s_z, &s_5, &s_z, &s_z, &s_z };
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row_ShiftRegisters row_R0(8, READ_PIN_COUNT_R0, ptrsKeys_R0);
*/

@@ -147,7 +147,7 @@ Key* ptrsKeys_R0[] = { &s_0, &s_z, &s_z, &s_z, &s_1, &s_z, &s_z, &s_z,
&s_2, &s_z, &s_z, &s_z, &s_3, &s_z, &s_z, &s_z,
&s_4, &s_z, &s_z, &s_z, &s_5, &s_z, &s_z, &s_z,
&s_6, &s_z, &s_z, &s_z, &s_3, &s_4, &s_5, &s_6 };
const uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
uint8_t READ_PIN_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row_ShiftRegisters row_R0(0, READ_PIN_COUNT_R0, ptrsKeys_R0);

//prints a b c d u v w x
@@ -155,19 +155,18 @@ Key* ptrsKeys_R1[] = { &s_a, &s_z, &s_z, &s_z, &s_b, &s_z, &s_z, &s_z,
&s_c, &s_z, &s_z, &s_z, &s_d, &s_z, &s_z, &s_z,
&s_e, &s_z, &s_z, &s_z, &s_f, &s_z, &s_z, &s_z,
&s_g, &s_z, &s_z, &s_z, &s_u, &s_v, &s_w, &s_x };
const uint8_t READ_PIN_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1);
uint8_t READ_PIN_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1);
Row_ShiftRegisters row_R1(1, READ_PIN_COUNT_R1, ptrsKeys_R1);

// ################### MAIN ####################
void setup()
{
Keyboard.begin();

wait();
SPI.begin();
row_R0.begin();
row_R1.begin();

wait();
Keyboard.println(F("keybrd_shift_reg.ino"));
}


+ 3
- 2
src/Debouncer_Samples.h View File

@@ -1,5 +1,6 @@
#ifndef DEBOUNCER_4SAMPLES_H
#define DEBOUNCER_4SAMPLES_H
#ifndef DEBOUNCER_SAMPLES_H
#define DEBOUNCER_SAMPLES_H

#include <Arduino.h>
#include <inttypes.h>
#include <config_keybrd.h>

+ 3
- 3
src/Row.cpp View File

@@ -1,13 +1,13 @@
#include "Row.h"
/*
send() calls key's press() or release() function if it was pressed or released.
send() calls key's press() or release() function if key was pressed or released.
Both parameters are bitwise.
*/
void Row::send(const uint8_t readPinCount, const read_pins_t debouncedChanged)
{
read_pins_t isFallingEdge; //bitwise, 1 means falling edge
read_pins_t isRisingEdge; //bitwise, 1 means rising edge
read_pins_t readMask; //bitwise, active read bit is 1
read_pins_t readMask; //bitwise, active bit is 1
uint8_t i; //index for ptrsKeys[i] array
//bit=1 if last debounced changed from 1 to 0, else bit=0
@@ -34,5 +34,5 @@ void Row::send(const uint8_t readPinCount, const read_pins_t debouncedChanged)
void Row::keyWasPressed()
{
//empty in Row class. To unstick sticky keys, override keyWasPressed() in derived class.
//empty in Row class. To unstick sticky keys, override keyWasPressed() in derived Row class.
}

+ 3
- 1
src/Row.h View File

@@ -1,5 +1,6 @@
#ifndef ROW_H
#define ROW_H
#include <Arduino.h>
#include <inttypes.h>
#include <config_keybrd.h>
@@ -13,7 +14,8 @@ class Row
Key *const *const ptrsKeys; //array of Key pointers
virtual void keyWasPressed();
protected:
read_pins_t debounced; //bitwise, 1 means pressed, 0 means released
read_pins_t debounced; //bitwise state of keys after debouncing
// 1 means pressed, 0 means released
void send(const uint8_t readPinCount, const read_pins_t debouncedChanged);
public:
Row(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { }

+ 12
- 8
src/Row_ShiftRegisters.cpp View File

@@ -1,17 +1,21 @@
#include "Row_ShiftRegisters.h"

/* Call begin() once in sketch setup()
*/
void Row_ShiftRegisters::begin()
{
scanner.begin();
}

/* process() scans the row and calls any newly pressed or released keys.
Bitwise variables are 1 bit per key.
*/
void Row_ShiftRegisters::process()
{
//these variables are all bitwise, one bit per key
read_pins_t readState; //1 means pressed, 0 means released
read_pins_t debouncedChanged; //1 means debounced changed
read_pins_t readState; //bitwise, 1 means key is pressed, 0 means released
read_pins_t debouncedChanged; //bitwise, 1 means debounced changed

readState = scanner.scan();
debouncedChanged = debouncer.debounce(readState, debounced);
send(READ_PIN_COUNT, debouncedChanged);
}

void Row_ShiftRegisters::begin()
{
scanner.begin();
}

+ 19
- 12
src/Row_ShiftRegisters.h View File

@@ -4,35 +4,42 @@
#include <Row.h>
#include <Scanner_ShiftRegs74HC165.h>
#include <Debouncer_Samples.h>
//#include <Debouncer_Not.h>

/* Row_DH_IOE is a row connected to an Input/Output Expander.
/* Row_ShiftRegisters is a row connected to shift registers.

Instantiation
-------------
Definition of DELAY_MICROSECONDS is explained in Row.cpp.
Example instantiation of a row:
Example instantiation of a Row_ShiftRegisters:

const unsigned int Row::DELAY_MICROSECONDS = 1000;
todo
const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10;
const bool Scanner_ShiftRegs74HC165::STROBE_ON = LOW; //logic level of strobe on, active low
const bool Scanner_ShiftRegs74HC165::STROBE_OFF = HIGH; //logic level of strobe off

Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02, &k_03, &k_04, &k_05 };
Row_ShiftRegisters row_0(uint8_t BYTE_COUNT, ptrsKeys_0);
uint8_t READ_PIN_COUNT_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
Row_ShiftRegisters row_0(1, READ_PIN_COUNT_0, ptrsKeys_0);

call begin() from sketch setup():
void setup()
{
Keyboard.begin();
SPI.begin();
row_0.begin();
}

Number of pins in colPort0 should equal number of keys in ptrsKeys_0[] array.
if a pin is missing, a key will be unresposive
if a Key pointer is missing, the keyboard will fail in an unprdictable way
READ_PIN_COUNT should equal number of keys in ptrsKeys_0[] array.
if READ_PIN_COUNT is too small, a key will be unresposive
if READ_PIN_COUNT is too large, the keyboard will fail in an unpredictable way
*/
class Row_ShiftRegisters : public Row
{
private:
Scanner_ShiftRegs74HC165 scanner;
Debouncer_Samples debouncer;
//Debouncer_Not debouncer; //passed test
const uint8_t READ_PIN_COUNT; //number of read pins
public:
Row_ShiftRegisters(const uint8_t STROBE_PIN, uint8_t READ_PIN_COUNT, Key *const ptrsKeys[])
Row_ShiftRegisters(const uint8_t STROBE_PIN, const uint8_t READ_PIN_COUNT, Key *const ptrsKeys[])
: Row(ptrsKeys), scanner(STROBE_PIN, READ_PIN_COUNT), READ_PIN_COUNT(READ_PIN_COUNT) { }
void begin();
void process();

+ 4
- 5
src/Row_uC.cpp View File

@@ -1,13 +1,12 @@
#include "Row_uC.h"

/*
process() scans the row and calls any newly pressed or released keys.
/* process() scans the row and calls any newly pressed or released keys.
Bitwise variables are 1 bit per key.
*/
void Row_uC::process()
{
//these variables are all bitwise, one bit per key
read_pins_t readState; //1 means pressed, 0 means released
read_pins_t debouncedChanged; //1 means debounced changed
read_pins_t readState; //bitwise, 1 means key is pressed, 0 means released
read_pins_t debouncedChanged; //bitwise, 1 means debounced changed

readState = scanner.scan();
debouncedChanged = debouncer.debounce(readState, debounced);

+ 4
- 5
src/Row_uC.h View File

@@ -10,10 +10,9 @@
Instantiation
-------------
Definition of DELAY_MICROSECONDS is explained in Row.cpp.
Example instantiation of a row:
Example instantiation of a Row_uC:

const unsigned int Row::DELAY_MICROSECONDS = 1000;
const bool Scanner_uC::STROBE_ON = LOW; //logic level of strobe on
const bool Scanner_uC::STROBE_ON = LOW; //logic level of strobe on, active low
const bool Scanner_uC::STROBE_OFF = HIGH; //logic level of strobe off

const uint8_t readPins[] = {0,1,2,3,7,8};
@@ -24,14 +23,14 @@ Example instantiation of a row:

Number of readPins should equal number of keys in ptrsKeys_0[] array.
if a readPins is missing, a key will be unresposive
if a Key pointer is missing, the keyboard will fail in an unprdictable way
if a Key pointer is missing, the keyboard will fail in an unpredictable way
*/
class Row_uC : public Row
{
private:
Scanner_uC scanner;
Debouncer_Samples debouncer;
const uint8_t READ_PIN_COUNT; //number of read pins
const uint8_t READ_PIN_COUNT;
public:
Row_uC(const uint8_t strobePin, const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT,
Key *const ptrsKeys[])

+ 6
- 6
src/Scanner_Port.cpp View File

@@ -1,21 +1,21 @@
#include "Scanner_Port.h"
/*
Strobes the row and reads the columns.

/* scan() strobes the row's STROBE_PIN and retuns state of port's input pins.
Bitwise variables are 1 bit per key.
*/
uint8_t Scanner_Port::scan()
{
uint8_t readState;
uint8_t readState; //bitwise, 1 means key is pressed, 0 means released

//strobe row on
//strobe on
refPortWrite.write(STROBE_PIN, STROBE_ON);
delayMicroseconds(3); //time to stablize voltage

//read the port pins
readState = refPortRead.read();

//strobe row off
//strobe off
refPortWrite.write(STROBE_PIN, STROBE_OFF);
//return refPortRead.getPortState();
return readState;
}

+ 6
- 4
src/Scanner_Port.h View File

@@ -1,21 +1,23 @@
#ifndef SCANNER_PORT_H
#define SCANNER_PORT_H

#include <Arduino.h>
#include <inttypes.h>
#include <PortWrite.h>
#include <PortRead.h>

/* Scanner_Port uses bit manipulation to read all pins of one port.
The ports are normally from an I/O Expander, but could also be ports from an AVR uC.
The maximum keys per row is 8, because ports have a maximum of 8 pins each.
*/
class Scanner_Port
{
private:
static const bool STROBE_ON; //HIGH or LOW logic level of strobe on, active state
static const bool STROBE_OFF; //logic level of strobe off, complement of STROBE_ON
PortWrite& refPortWrite; //this row's IC port
const uint8_t STROBE_PIN; //bitwise, 1 indicates IC pin connected to this row
PortRead& refPortRead;
static const bool STROBE_OFF; //logic level of strobe off, complement of STROBE_ON
PortWrite& refPortWrite; //the IC port containing the STROBE_PIN
const uint8_t STROBE_PIN; //bitwise, 1 indicates IC pin connected to this row
PortRead& refPortRead; //the IC's read port
public:
Scanner_Port(PortWrite &refPortWrite, const uint8_t STROBE_PIN, PortRead& refPortRead)
: refPortWrite(refPortWrite), STROBE_PIN(STROBE_PIN), refPortRead(refPortRead) {}

+ 4
- 4
src/Scanner_ShiftRegs74HC165.cpp View File

@@ -15,12 +15,12 @@ void Scanner_ShiftRegs74HC165::begin()
digitalWrite(SHIFT_LOAD, HIGH);
}

/*
returns readState.
/* scan() strobes the row's STROBE_PIN and retuns state of the shift register's input pins.
Bitwise variables are 1 bit per key.
*/
read_pins_t Scanner_ShiftRegs74HC165::scan()
{
read_pins_t readState = 0;
read_pins_t readState = 0; //bitwise, 1 means key is pressed, 0 means released

//strobe row on
digitalWrite(STROBE_PIN, STROBE_ON);
@@ -35,7 +35,7 @@ read_pins_t Scanner_ShiftRegs74HC165::scan()
digitalWrite(STROBE_PIN, STROBE_OFF);

//for testing on breadboard, clear unpowered pins
readState &= 0b11110001000100010001000100010001; //todo
readState &= 0b11110001000100010001000100010001; //todo delete this line

return readState;
}

+ 5
- 8
src/Scanner_ShiftRegs74HC165.h View File

@@ -1,5 +1,6 @@
#ifndef ROWSCANNER_SHIFTREGS74HC165_H
#define ROWSCANNER_SHIFTREGS74HC165_H

#include <Arduino.h>
#include <inttypes.h>
#include <config_keybrd.h>
@@ -8,12 +9,8 @@
#include <PortRead.h>

/* Scanner_ShiftRegs74HC165 reads shift registers.
shift registers 74HC165 is Parallel-In-Serial-Out (PISO)
Upto 4 shift registers can be in a daisy chained.

In sketch:
const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10;
call begin() from setup()
shift registers 74HC165 are Parallel-In-Serial-Out (PISO)
Upto 4 shift registers can be in a daisy chained for a total of 32 read pins.

For active low:
const bool Scanner_ShiftRegs74HC165::STROBE_ON = LOW;
@@ -27,7 +24,7 @@ For active high:
//shift register parallel input pins have 10k pull-down resistors grounded
//controller's MISO pin is connected to shift register's serial output (QH) pin

In addition, each row needs to be connected to a strobe pin from controller.
In addition, each row needs to be connected to a strobe pin from the controller.

todo move this to tutorial
The shift register needs 5 wires.
@@ -45,7 +42,7 @@ class Scanner_ShiftRegs74HC165
const uint8_t STROBE_PIN; //Arduino pin number connected to this row
const uint8_t BYTE_COUNT; //number of bytes to read from shift registers
public:
Scanner_ShiftRegs74HC165(const uint8_t STROBE_PIN, uint8_t READ_PIN_COUNT);
Scanner_ShiftRegs74HC165(const uint8_t STROBE_PIN, const uint8_t READ_PIN_COUNT);
virtual read_pins_t scan();
void begin();
};

+ 14
- 13
src/Scanner_uC.cpp View File

@@ -1,5 +1,13 @@
#include "Scanner_uC.h"

/* Scanner_uC functions call Arduino's Digital Pins functions
https://www.arduino.cc/en/Tutorial/DigitalPins
https://www.arduino.cc/en/Reference/PinMode
https://www.arduino.cc/en/Reference/DigitalWrite
https://www.arduino.cc/en/Reference/DigitalRead
https://www.arduino.cc/en/Reference/Constants > Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT
*/

/* constructor
*/
Scanner_uC::Scanner_uC(const uint8_t STROBE_PIN,
@@ -13,9 +21,9 @@ Scanner_uC::Scanner_uC(const uint8_t STROBE_PIN,

if (STROBE_ON == LOW) //if active low
{
mode = INPUT_PULLUP; //uses internal pull-up resistor
mode = INPUT_PULLUP; //use internal pull-up resistor
}
else
else //if active high
{
mode = INPUT; //requires external pull-down resistor
}
@@ -27,19 +35,13 @@ Scanner_uC::Scanner_uC(const uint8_t STROBE_PIN,
}
}

/* scan() Strobes the row and reads the columns.
Sets READ_PIN_COUNT and returns readState.

https://www.arduino.cc/en/Tutorial/DigitalPins
https://www.arduino.cc/en/Reference/PinMode
https://www.arduino.cc/en/Reference/DigitalWrite
https://www.arduino.cc/en/Reference/DigitalRead
https://www.arduino.cc/en/Reference/Constants > Digital Pins modes: INPUT, INPUT_PULLUP, and OUTPUT
/* scan() strobes the row's STROBE_PIN and retuns state of READ_PINS.
Bitwise variables are 1 bit per key.
*/
read_pins_t Scanner_uC::scan()
{
read_pins_t readState = 0; //bitwise, one col per bit, 1 means key is pressed
read_pins_t readMask = 1; //bitwise, one col per bit, active col bit is 1
read_pins_t readState = 0; //bitwise, 1 means key is pressed, 0 means released
read_pins_t readMask = 1; //bitwise, active bit is 1

//strobe row on
digitalWrite(STROBE_PIN, STROBE_ON);
@@ -58,6 +60,5 @@ read_pins_t Scanner_uC::scan()
//strobe row off
digitalWrite(STROBE_PIN, STROBE_OFF);

// readPinCount = READ_PIN_COUNT;
return readState;
}

+ 1
- 0
src/Scanner_uC.h View File

@@ -1,5 +1,6 @@
#ifndef SCANNER_UC_H
#define SCANNER_UC_H

#include <Arduino.h>
#include <inttypes.h>
#include <config_keybrd.h>

+ 6
- 6
src/config_keybrd.h View File

@@ -4,23 +4,23 @@

/* size of read_pins_t depends on the maximum number of pins scanned by RowScanner.
By default, read_pins_t is set to the largest type.
If your 8-bit AVR is running low on memory, using a smaller type saves SRAM.
If your 8-bit AVR (Teensy 2) is running low on memory, using a smaller type saves SRAM.
Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing.
*/

/* Uncomment a typedef read_pins_t size that covers all col pins of all RowScanner objects i.e.
/* Use a read_pins_t size that covers all read pins of all RowScanner objects i.e.
For Scanner_uC, Scanner_uC::READ_PIN_COUNT
For Scanner_ShiftRegs74HC165, Scanner_ShiftRegs74HC165::READ_PIN_COUNT
For Scanner_Port, cover the last 1 bit in Scanner_Port::strobePin
*/
typedef uint8_t read_pins_t;
//typedef uint8_t read_pins_t;
//typedef uint16_t read_pins_t;
//typedef uint32_t read_pins_t;
typedef uint32_t read_pins_t;

/* SAMPLE_COUNT = 4 is very reliable for a keyboard.
/* SAMPLE_COUNT is used in Debouncer_Samples.h
SAMPLE_COUNT = 4 is very reliable for a keyboard.
Split keyboards with a long connecting wire or in environment with
strong electromagnetic interference (EMI) may need a larger SAMPLE_COUNT for reliability.
SAMPLE_COUNT is used in Debouncer_Samples.h
*/
#define SAMPLE_COUNT 4 //number of consecutive equal bits needed to change a debounced bit