diff --git a/examples/keybrd_shift_register/keybrd_shift_register.ino b/examples/keybrd_shift_register/keybrd_shift_register.ino index 16bea9d..b331696 100644 --- a/examples/keybrd_shift_register/keybrd_shift_register.ino +++ b/examples/keybrd_shift_register/keybrd_shift_register.ino @@ -5,21 +5,23 @@ The keyboard hardware for this sketch has 4 shift registers, with every 4th input pin connected to a pull-down resistor and matrix column, also the 31st key. Unused input pins are not grounded, so add this line to RowScanner_SPIShiftRegisters::scan(): //clear unpowered pins (for testing on breadboard) - rowState &= 0b01010001000100010001000100010001; + rowState &= 0b11110001000100010001000100010001; //todo Layout -| Left |**0**|**1**| | Right |**0**|**1**|**2**|**3**|**4**|**5**|**6**|**7**|**8**| -|:-----:|-----|-----| |:-----:|-----|-----|-----|-----|-----|-----|-----|-----|-----| -| **0** | a | b | | **0** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -| **1** | c | d | | **1** | a | b | c | d | e | f | g | h | i | +| Left | **0**|**1**| | Right |**0**|**1**|**2**|**3**|**4**|**5**|**6**|**7**|**8**| +|:-----:|------|-----| |:-----:|-----|-----|-----|-----|-----|-----|-----|-----|-----| +| **0** |capLck| a | | **0** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | +| **1** | b | c | | **1** | a | b | c | d | e | f | g | h | i | */ // ################## GLOBAL ################### // ================= INCLUDES ================== #include #include +#include //Codes #include +#include //Matrix #include @@ -35,8 +37,27 @@ Debug debug; // ================= LEFT PINS ================= uint8_t readPins[] = {14, 15}; -uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins); +uint8_t KEY_COUNT = sizeof(readPins)/sizeof(*readPins); +// ==================== LEDs =================== +LED_PinNumber LED1(16); + +//sometimes OS takes 6 seconds to recongnize keyboard, LED blinks from the begining +void wait() +{ + for (uint8_t count = 0; count < 6; count++) + { + //print count + Keyboard.print(count); + Keyboard.print(F(" ")); + + //blink LED + LED1.on(); + delay(500); + LED1.off(); + delay(500); + } +} // =================== CODES =================== Code_Sc s_a(KEY_A); Code_Sc s_b(KEY_B); @@ -48,6 +69,13 @@ Code_Sc s_g(KEY_G); Code_Sc s_h(KEY_H); Code_Sc s_i(KEY_I); +Code_Sc s_u(KEY_U); +Code_Sc s_v(KEY_V); +Code_Sc s_w(KEY_W); +Code_Sc s_x(KEY_X); + +Code_Sc s_z(KEY_Z); + Code_Sc s_0(KEY_0); Code_Sc s_1(KEY_1); Code_Sc s_2(KEY_2); @@ -57,14 +85,15 @@ Code_Sc s_5(KEY_5); Code_Sc s_6(KEY_6); Code_Sc s_7(KEY_7); Code_Sc s_8(KEY_8); -Code_Sc s_z(KEY_Z); + +Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED1); // ================= LEFT ROWS ================= -Key* ptrsKeys_L0[] = { &s_a, &s_b }; -Row_uC row_L0(0, readPins, READ_PIN_COUNT, ptrsKeys_L0); +Key* ptrsKeys_L0[] = { &o_capsLock, &s_a }; +Row_uC row_L0(0, readPins, ptrsKeys_L0, KEY_COUNT); -Key* ptrsKeys_L1[] = { &s_c, &s_d }; -Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1); +Key* ptrsKeys_L1[] = { &s_b, &s_c }; +Row_uC row_L1(1, readPins, ptrsKeys_L1, KEY_COUNT); // ================= RIGHT ROWS ================ //typedef should be large in /home/wolfv/Documents/Arduino/keybrd_proj/keybrd/src/config_keybrd.h @@ -105,44 +134,25 @@ const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); */ -//prints 0 1 2 3 4 5 6 7 8, microseconds_per_scan=87 with SAMPLE_COUNT 4 +//prints 0 1 2 3 3 4 5 6, microseconds_per_scan=87 with SAMPLE_COUNT 4 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_7, &s_z, &s_8 }; //31-key limit because endRow + &s_6, &s_z, &s_z, &s_z, &s_3, &s_4, &s_5, &s_6 }; const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); Row_ShiftRegisters row_R0(8, ptrsKeys_R0, KEY_R0_COUNT); -//prints a b c d e f g h i +//prints a b c d u v w x 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_h, &s_z, &s_i }; //31-key limit because endRow + &s_g, &s_z, &s_z, &s_z, &s_u, &s_v, &s_w, &s_x }; const uint8_t KEY_R1_COUNT = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); Row_ShiftRegisters row_R1(9, ptrsKeys_R1, KEY_R1_COUNT); -const uint8_t LED_PIN = 16; //indicates wait - -//sometimes OS takes 6 seconds to recongnize keyboard, LED blinks from the begining -void wait() -{ - for (uint8_t count = 0; count < 6; count++) - { - //print count - Keyboard.print(count); - Keyboard.print(F(" ")); - - //blink LED - digitalWrite(LED_PIN, HIGH); - delay(900); - digitalWrite(LED_PIN, LOW); - delay(100); - } -} // ################### MAIN #################### void setup() { - pinMode (LED_PIN, OUTPUT); Keyboard.begin(); wait(); @@ -150,8 +160,7 @@ void setup() row_R0.begin(); row_R1.begin(); - Keyboard.print(F("keybrd_shift_reg.ino ")); - debug.print_free_RAM(); + Keyboard.println(F("keybrd_shift_reg.ino")); } void loop() diff --git a/src/Code_LEDLock.cpp b/src/Code_LEDLock.cpp index c5c502d..6a91533 100644 --- a/src/Code_LEDLock.cpp +++ b/src/Code_LEDLock.cpp @@ -59,7 +59,7 @@ This debug code prints "keyboard_leds=0" when scrollLock is pressed: */ if (keyboard_leds & USB_LED_bit) //if USB_LED_bit is set { - refLED.off(); //LED on-off seem inverted, but it works for active high + refLED.off(); //LED on-off seem inverted, but it works for active low and active high } else { diff --git a/src/ColPort_PCA9655E.cpp b/src/ColPort_PCA9655E.cpp index ed71571..19317d6 100644 --- a/src/ColPort_PCA9655E.cpp +++ b/src/ColPort_PCA9655E.cpp @@ -3,8 +3,7 @@ /* configures column port's configuration, input, and pins. */ -ColPort_PCA9655E::ColPort_PCA9655E -(IOExpanderPort& port, const uint8_t colPins) +ColPort_PCA9655E::ColPort_PCA9655E (IOExpanderPort& port, const uint8_t colPins) : ColPort(colPins), port(port), configurationByteCommand(port.num + 6), inputByteCommand(port.num) {} diff --git a/src/Debug.cpp b/src/Debug.cpp index e2e558b..62ea166 100644 --- a/src/Debug.cpp +++ b/src/Debug.cpp @@ -1,12 +1,4 @@ #include "Debug.h" -#include "getFreeSRAM.h" - -void Debug::print_free_RAM() -{ - delay(1000); //give OS time to find USB - Keyboard.print(F("Free SRAM = ")); - Keyboard.println( getFreeSRAM() ); -} void Debug::print_microseconds_per_scan() { diff --git a/src/Debug.h b/src/Debug.h index f047f12..4afe0d3 100644 --- a/src/Debug.h +++ b/src/Debug.h @@ -9,7 +9,6 @@ class Debug unsigned int scanCount = 0; public: - void print_free_RAM(); //print free SRAM, call this from setup() void print_microseconds_per_scan(); //print microseconds per scan every second void print_scans_per_second(); //print scans per second every second }; diff --git a/src/RowBase.cpp b/src/RowBase.cpp index 7b03575..be4690d 100644 --- a/src/RowBase.cpp +++ b/src/RowBase.cpp @@ -2,13 +2,12 @@ /* pressRelease() calls key's press() or release() function if it was pressed or released. Both parameters are bitwise. -rowEnd bit marks positioned immediatly after last key of row. */ void RowBase::pressRelease(const uint8_t KEY_COUNT, 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_mask_t rowMask; //bitwise, active col bit is 1 + read_pins_t rowMask; //bitwise, active col bit is 1 uint8_t col; //index for ptrsKeys[col] array //bit=1 if last debounced changed from 1 to 0, else bit=0 diff --git a/src/RowBase.h b/src/RowBase.h index 9a70dd4..e0102fc 100644 --- a/src/RowBase.h +++ b/src/RowBase.h @@ -14,7 +14,7 @@ class RowBase virtual void keyWasPressed(); protected: read_pins_t debounced; //bitwise, 1 means pressed, 0 means released - void pressRelease(const read_pins_mask_t rowEnd, const read_pins_t debouncedChanged); + void pressRelease(const uint8_t KEY_COUNT, const read_pins_t debouncedChanged); public: RowBase(Key *const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { } virtual void process()=0; diff --git a/src/RowScanner_PinsArray.cpp b/src/RowScanner_PinsArray.cpp index d51ce46..19742bf 100644 --- a/src/RowScanner_PinsArray.cpp +++ b/src/RowScanner_PinsArray.cpp @@ -28,10 +28,7 @@ RowScanner_PinsArray::RowScanner_PinsArray(const uint8_t STROBE_PIN, } /* scan() Strobes the row and reads the columns. -Sets rowEnd and returns rowState. -rowEnd is a bitwise row mask, one col per bit, where active col bit is 1. -At end of function, 1 bit marks place immediatly after last key of row. -rowEnd is a larger type than portMask so that it can not overflow. +Sets KEY_COUNT and returns rowState. https://www.arduino.cc/en/Tutorial/DigitalPins https://www.arduino.cc/en/Reference/PinMode @@ -39,10 +36,10 @@ 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 */ -read_pins_t RowScanner_PinsArray::scan(read_pins_mask_t& rowEnd) +read_pins_t RowScanner_PinsArray::scan(uint8_t& keyCount) { - read_pins_t rowState = 0; //bitwise - rowEnd = 1; + read_pins_t rowState = 0; //bitwise, one col per bit, 1 means key is pressed + read_pins_t rowMask = 1; //bitwise, one col per bit, active col bit is 1 //strobe row on if (ACTIVE_HIGH) @@ -60,9 +57,9 @@ read_pins_t RowScanner_PinsArray::scan(read_pins_mask_t& rowEnd) { if ( digitalRead(READ_PINS[i]) == ACTIVE_HIGH ) { - rowState |= rowEnd; + rowState |= rowMask; } - rowEnd <<= 1; + rowMask <<= 1; } //strobe row off @@ -75,5 +72,6 @@ read_pins_t RowScanner_PinsArray::scan(read_pins_mask_t& rowEnd) digitalWrite(STROBE_PIN, HIGH); } + keyCount = READ_PIN_COUNT; return rowState; } diff --git a/src/RowScanner_PinsArray.h b/src/RowScanner_PinsArray.h index ddb7e04..09f5a75 100644 --- a/src/RowScanner_PinsArray.h +++ b/src/RowScanner_PinsArray.h @@ -7,7 +7,6 @@ #include /* RowScanner_PinsArray class uses Arduino pin numbers (not port pin numbers). -The maximum keys per row is 31, because Arduino's largest type is 32 bits and rowEnd consumes the last bit. Constructor is in RowScanner_PinsArray.cpp */ class RowScanner_PinsArray @@ -19,9 +18,8 @@ class RowScanner_PinsArray const uint8_t READ_PIN_COUNT; //number of read pins public: RowScanner_PinsArray(const uint8_t STROBE_PIN, - const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT); - virtual read_pins_t scan(read_pins_mask_t& rowEnd); - //read_pins_t getRowState(read_pins_mask_t& rowEnd); + const uint8_t READ_PINS[], const uint8_t READ_PIN_COUNT); //todo rename READ_PIN_COUNT to KEY_COUNT ?? + virtual read_pins_t scan(uint8_t& KEY_COUNT); }; #endif diff --git a/src/RowScanner_PinsBitwise.cpp b/src/RowScanner_PinsBitwise.cpp index 6976f5e..b00a052 100644 --- a/src/RowScanner_PinsBitwise.cpp +++ b/src/RowScanner_PinsBitwise.cpp @@ -1,7 +1,6 @@ #include "RowScanner_PinsBitwise.h" /* Strobes the row and reads the columns. -Sets rowEnd and returns rowState. */ ColPort* const RowScanner_PinsBitwise::scan() { @@ -29,6 +28,5 @@ ColPort* const RowScanner_PinsBitwise::scan() refRowPort.setActivePinHigh(strobePin); } -// return getRowState(refColPort, rowEnd); return &refColPort; } diff --git a/src/RowScanner_SPIShiftRegisters.cpp b/src/RowScanner_SPIShiftRegisters.cpp index 730a259..994ebd1 100644 --- a/src/RowScanner_SPIShiftRegisters.cpp +++ b/src/RowScanner_SPIShiftRegisters.cpp @@ -2,7 +2,7 @@ //constructor RowScanner_SPIShiftRegisters::RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT) - : STROBE_PIN(STROBE_PIN), ROW_END(1 << KEY_COUNT), BYTE_COUNT(ceil (float(KEY_COUNT)/8)) + : STROBE_PIN(STROBE_PIN), BYTE_COUNT(ceil (float(KEY_COUNT)/8)), KEY_COUNT(KEY_COUNT) { //configure controller to communicate with shift register matrix pinMode(STROBE_PIN, OUTPUT); @@ -16,9 +16,9 @@ void RowScanner_SPIShiftRegisters::begin() } /* -Sets rowEnd and returns rowState. +Sets keyCount and returns rowState. */ -read_pins_t RowScanner_SPIShiftRegisters::scan(read_pins_mask_t& rowEnd) +read_pins_t RowScanner_SPIShiftRegisters::scan(uint8_t& keyCount) { read_pins_t rowState = 0; @@ -34,10 +34,10 @@ read_pins_t RowScanner_SPIShiftRegisters::scan(read_pins_mask_t& rowEnd) //strobe row off digitalWrite(STROBE_PIN, LOW); - rowEnd = ROW_END; + keyCount = KEY_COUNT; - //for testing breadboard, clear unpowered pins - rowState &= 0b01010001000100010001000100010001; //todo + //for testing on breadboard, clear unpowered pins + rowState &= 0b11110001000100010001000100010001; //todo return rowState; } diff --git a/src/RowScanner_SPIShiftRegisters.h b/src/RowScanner_SPIShiftRegisters.h index b6e9139..6b106eb 100644 --- a/src/RowScanner_SPIShiftRegisters.h +++ b/src/RowScanner_SPIShiftRegisters.h @@ -15,7 +15,6 @@ in sketch: call begin() from setup() Upto 4 shift registers can be in a daisy chained. -The maximum keys per row is 31, because Arduino's largest type is 32 bits and rowEnd consumes the last bit. The shift registers are active high: 10k pull-down resistors are grounded @@ -33,11 +32,11 @@ class RowScanner_SPIShiftRegisters private: static const uint8_t SHIFT_LOAD; //controller's pin number that is connected to shift register's SHIFT_LOAD pin const uint8_t STROBE_PIN; //Arduino pin number connected to this row - const read_pins_mask_t ROW_END; //bitwise, 1 bit marks positioned after last key of row const uint8_t BYTE_COUNT; //number of bytes to read from shift registers + uint8_t KEY_COUNT; public: RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, uint8_t KEY_COUNT); - virtual read_pins_t scan(read_pins_mask_t& rowEnd); + virtual read_pins_t scan(uint8_t& KEY_COUNT); void begin(); }; #endif diff --git a/src/Row_ShiftRegisters.cpp b/src/Row_ShiftRegisters.cpp index a0dc898..0e60540 100644 --- a/src/Row_ShiftRegisters.cpp +++ b/src/Row_ShiftRegisters.cpp @@ -4,12 +4,12 @@ void Row_ShiftRegisters::process() { //these variables are all bitwise, one bit per key read_pins_t rowState; //1 means pressed, 0 means released - read_pins_mask_t rowEnd; //1 bit marks positioned after last key of row + uint8_t keyCount; read_pins_t debouncedChanged; //1 means debounced changed - rowState = scanner.scan(rowEnd); + rowState = scanner.scan(keyCount); debouncedChanged = debouncer.debounce(rowState, debounced); - pressRelease(rowEnd, debouncedChanged); + pressRelease(keyCount, debouncedChanged); } void Row_ShiftRegisters::begin() diff --git a/src/Row_uC.cpp b/src/Row_uC.cpp index a147f06..bef7362 100644 --- a/src/Row_uC.cpp +++ b/src/Row_uC.cpp @@ -7,10 +7,20 @@ void Row_uC::process() { //these variables are all bitwise, one bit per key read_pins_t rowState; //1 means pressed, 0 means released - read_pins_mask_t rowEnd; //1 bit marks positioned after last key of row + uint8_t keyCount; read_pins_t debouncedChanged; //1 means debounced changed - rowState = scanner.scan(rowEnd); + rowState = scanner.scan(keyCount); +/* +Keyboard.print(" keyCount="); +Keyboard.print(keyCount); +Keyboard.print(" rowState="); +Keyboard.print(rowState); +*/ debouncedChanged = debouncer.debounce(rowState, debounced); - pressRelease(rowEnd, debouncedChanged); +/* +Keyboard.print(" debounced="); +Keyboard.print(debounced); +*/ + pressRelease(keyCount, debouncedChanged); } diff --git a/src/config_keybrd.h b/src/config_keybrd.h index f3d84cd..30f2c8f 100644 --- a/src/config_keybrd.h +++ b/src/config_keybrd.h @@ -2,8 +2,8 @@ #define CONFIG_KEYBRD_H #include -/* size of read_pins_t and read_pins_mask_t depends on the maximum number of pins scanned by RowScanner. -By default, read_pins_t and read_pins_mask_t are set to the largest type. +/* 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. Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing. */ @@ -13,17 +13,9 @@ Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing. For RowScanner_SPIShiftRegisters, RowScanner_SPIShiftRegisters::KEY_COUNT For RowScanner_PinsBitwise, cover the last 1 bit in RowScanner_PinsBitwise::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; - -/* read_pins_mask_t is only used for rowMask and rowEnd, which extends one bit beyond the last col pin. -uncomment typedef that covers one bit beyond the last col pin. -This could be the same typedef as read_pins_t, or the next larger typedef. -*/ -typedef uint8_t read_pins_mask_t; -//typedef uint16_t read_pins_mask_t; -//typedef uint32_t read_pins_mask_t; +typedef uint32_t read_pins_t; /* SAMPLE_COUNT = 4 is very reliable for a keyboard. Split keyboards with a long connecting wire or in environment with diff --git a/tutorials/images/bend_diodes_en_masse2.JPG b/tutorials/images/bend_diodes_en_masse2.JPG new file mode 100644 index 0000000..bcaded4 Binary files /dev/null and b/tutorials/images/bend_diodes_en_masse2.JPG differ diff --git a/tutorials/images/bend_diodes_en_masse3.JPG b/tutorials/images/bend_diodes_en_masse3.JPG new file mode 100644 index 0000000..52f4fba Binary files /dev/null and b/tutorials/images/bend_diodes_en_masse3.JPG differ diff --git a/tutorials/images/breadboard_keyboard_2x2_crossColumns.jpg b/tutorials/images/breadboard_keyboard_2x2_crossColumns.jpg new file mode 100644 index 0000000..2258983 Binary files /dev/null and b/tutorials/images/breadboard_keyboard_2x2_crossColumns.jpg differ