diff --git a/examples/keybrd_shift_register/keybrd_shift_reg.ino b/examples/keybrd_shift_register/keybrd_shift_reg.ino new file mode 100644 index 0000000..b30318d --- /dev/null +++ b/examples/keybrd_shift_register/keybrd_shift_reg.ino @@ -0,0 +1,161 @@ +/* keybrd_shift_reg.ino +this works on Teensy LC 1*bb, active low and active high + +| Layout | **0** | **1** | +|:------:|-------|-------| +| **0** | a | b | +| **1** | c | d | +*/ +// ################## GLOBAL ################### +// ================= INCLUDES ================== +#include + +//IOE Ports +#include "IOExpanderPort.h" +#include +#include + +//Codes +#include + +//Matrix +#include +#include +#include + +// =============== CONFIGURATION =============== +const unsigned int RowBase::DELAY_MICROSECONDS = 500; //500 + +//activeLow has diode cathode (band) on row +//activeHigh has diode cathode (band) on col, and pull down resistors on cols +//0=active low, 1= active high +const bool RowScanner_PinsArray::ACTIVE_HIGH = 0; + +Debug debug; + +// ================= LEFT PINS ================= +uint8_t readPins[] = {14, 15}; +uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins); + +// =================== CODES =================== +Code_Sc s_a(KEY_A); +Code_Sc s_b(KEY_B); +Code_Sc s_c(KEY_C); +Code_Sc s_d(KEY_D); +Code_Sc s_e(KEY_E); +Code_Sc s_f(KEY_F); +Code_Sc s_g(KEY_G); +Code_Sc s_h(KEY_H); +Code_Sc s_i(KEY_I); + +Code_Sc s_0(KEY_0); +Code_Sc s_1(KEY_1); +Code_Sc s_2(KEY_2); +Code_Sc s_3(KEY_3); +Code_Sc s_4(KEY_4); +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); + +// ================= LEFT ROWS ================= +Key* ptrsKeys_L0[] = { &s_a, &s_b }; +Row_uC row_L0(0, readPins, READ_PIN_COUNT, ptrsKeys_L0); + +Key* ptrsKeys_L1[] = { &s_c, &s_d }; +Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1); + +// ================= RIGHT ROWS ================ +//typedef should be large in /home/wolfv/Documents/Arduino/keybrd_proj/keybrd/src/config_keybrd.h +//Row_ShiftRegisters(STROBE_PIN, SHIFT_LOAD, ptrsKeys[], KEY_COUNT) +//the s_z are place holders and should not print +/* +//BYTE_COUNT 1, prints 0 1 +Key* ptrsKeys_R0[] = { &s_0, &s_a, &s_b, &s_c, &s_1, &s_d, &s_e, &s_f }; +const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); +Row_ShiftRegisters row_R0(8, 10, ptrsKeys_R0, KEY_R0_COUNT); +*/ +/* +//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 KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); +Row_ShiftRegisters row_R0(8, 10, ptrsKeys_R0, KEY_R0_COUNT); +*/ +/* +//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 KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); +Row_ShiftRegisters row_R0(8, 10, ptrsKeys_R0, KEY_R0_COUNT); +*/ +/* +//prints 0 1 2 3 4 5 +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 KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); +Row_ShiftRegisters row_R0(8, 10, ptrsKeys_R0, KEY_R0_COUNT); +*/ + +//prints 0 1 2 3 4 5 6 7 8 +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 +const uint8_t KEY_R0_COUNT = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); +Row_ShiftRegisters row_R0(8, 10, ptrsKeys_R0, KEY_R0_COUNT); + +//unresponsive +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 +const uint8_t KEY_R1_COUNT = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); +Row_ShiftRegisters row_R1(9, 10, 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(); + SPI.begin(); + + wait(); + row_R0.begin(); + row_R1.begin(); + Keyboard.print(F("keybrd_shift_reg.ino ")); + debug.print_free_RAM(); +} + +void loop() +{ + row_L0.process(); + row_L1.process(); + + row_R0.process(); + row_R1.process(); + +//delay(100); +//Keyboard.println(""); +//debug.print_microseconds_per_scan(); +} diff --git a/examples/keybrd_shift_register/keybrd_shift_reg_works1.no b/examples/keybrd_shift_register/keybrd_shift_reg_works1.no new file mode 100644 index 0000000..0dc3c55 --- /dev/null +++ b/examples/keybrd_shift_register/keybrd_shift_reg_works1.no @@ -0,0 +1,136 @@ +/* this works on Teensy LC 1*bb, active low and active high + +| Layout | **0** | **1** | +|:------:|-------|-------| +| **0** | a | b | +| **1** | c | d | +*/ +// ################## GLOBAL ################### +// ================= INCLUDES ================== +#include + +//IOE Ports +#include "IOExpanderPort.h" +#include +#include + +//Codes +#include + +//Matrix +#include +#include +#include + +// =============== CONFIGURATION =============== +const unsigned int RowBase::DELAY_MICROSECONDS = 500; + +//activeLow has diode cathode (band) on row +//activeHigh has diode cathode (band) on col, and pull down resistors on cols +//0=active low, 1= active high +const bool RowScanner_PinsArray::activeHigh = 0; + +Debug debug; + +// ================ LEFT PORTS ================= +uint8_t readPins[] = {14, 15}; +uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins); + +// =================== CODES =================== +Code_Sc s_a(KEY_A); +Code_Sc s_b(KEY_B); +Code_Sc s_c(KEY_C); +Code_Sc s_d(KEY_D); + +Code_Sc s_0(KEY_0); +Code_Sc s_1(KEY_1); +Code_Sc s_2(KEY_2); +Code_Sc s_3(KEY_3); +Code_Sc s_4(KEY_4); +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); + +// ================= LEFT ROWS ================= +Key* ptrsKeys_L0[] = { &s_a, &s_b }; +Row_uC row_L0(0, readPins, READ_PIN_COUNT, ptrsKeys_L0); + +Key* ptrsKeys_L1[] = { &s_c, &s_d }; +Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1); + +// ================= RIGHT ROWS ================ +// typedef should be large in /home/wolfv/Documents/Arduino/keybrd_proj/keybrd/src/config_keybrd.h + +/* +//prints 0 4 +Key* ptrsKeys_R[] = { &s_0, &s_1, &s_2, &s_3, + &s_4, &s_5, &s_6, &s_7 }; //the most that 8-bit send() can handle +const uint8_t KEY_COUNT = sizeof(ptrsKeys_R)/sizeof(*ptrsKeys_R); +Row_ShiftRegisters row_R(9, 1, ptrsKeys_R, KEY_COUNT); // (SS, BYTE_COUNT,,) +*/ +/* +//prints 0 4 8 +Key* ptrsKeys_R[] = { &s_0, &s_z, &s_z, &s_z, + &s_4, &s_z, &s_z, &s_z, + &s_8, &s_z, &s_z, &s_z }; //the s_z are place holders and should not print +const uint8_t KEY_COUNT = sizeof(ptrsKeys_R)/sizeof(*ptrsKeys_R); +Row_ShiftRegisters row_R(9, 2, ptrsKeys_R, KEY_COUNT); +*/ + +//prints 0 4 8 c +Key* ptrsKeys_R[] = { &s_0, &s_z, &s_z, &s_z, + &s_4, &s_z, &s_z, &s_z, + &s_8, &s_z, &s_z, &s_z, + &s_c, &s_z, &s_z, &s_z }; //the s_z are place holders and should not print +const uint8_t KEY_COUNT = sizeof(ptrsKeys_R)/sizeof(*ptrsKeys_R); +Row_ShiftRegisters row_R(9, 2, ptrsKeys_R, KEY_COUNT); + +const uint8_t LED_PIN = 16; + +void wait() +{ + static uint8_t count = 0; + + //print count + Keyboard.print(count); + Keyboard.print(F(" ")); + count++; + + //blink LED + digitalWrite(LED_PIN, HIGH); + delay(900); + digitalWrite(LED_PIN, LOW); + delay(100); +} +// ################### MAIN #################### +void setup() +{ + pinMode (LED_PIN, OUTPUT); + Keyboard.begin(); + wait(); //0 + SPI.begin(); + wait(); //1 + row_R.begin(); + wait(); //2 + wait(); //3 + wait(); //4 + wait(); //5 sometimes OS takes 6 seconds to recongnize keyboard, LED blinks from the begining + Keyboard.print(F("keybrd_shift_reg.ino ")); + debug.print_free_RAM(); +} + +void loop() +{ + row_L0.process(); + row_L1.process(); + + row_R.process(); + + //row_R0.process(); + //row_R1.process(); + +//delay(100); +//Keyboard.println(""); +} diff --git a/src/RowScanner_SPIShiftRegisters.cpp b/src/RowScanner_SPIShiftRegisters.cpp index 9379a39..94a1e66 100644 --- a/src/RowScanner_SPIShiftRegisters.cpp +++ b/src/RowScanner_SPIShiftRegisters.cpp @@ -5,9 +5,9 @@ void RowScanner_SPIShiftRegisters::begin() //configure row pinMode(STROBE_PIN, OUTPUT); - //todo there is only one slave, is select needed? - pinMode (SHIFT_LOAD, OUTPUT); - digitalWrite (SHIFT_LOAD, HIGH); + //initialize shift register's shift/load pin + pinMode(SHIFT_LOAD, OUTPUT); + digitalWrite(SHIFT_LOAD, HIGH); } /* @@ -18,18 +18,27 @@ read_pins_t RowScanner_SPIShiftRegisters::scan(read_pins_mask_t& rowEnd) read_pins_t rowState = 0; //strobe row on - digitalWrite(STROBE_PIN, LOW); + digitalWrite(STROBE_PIN, HIGH); delayMicroseconds(3); //time to stablize voltage //read all the column pins - digitalWrite(SHIFT_LOAD, LOW); //load parallel inputs to the register - digitalWrite(SHIFT_LOAD, HIGH); //shift the data toward a serial output + digitalWrite(SHIFT_LOAD, LOW); //load parallel inputs to the register + digitalWrite(SHIFT_LOAD, HIGH); //shift the data toward a serial output SPI.transfer(&rowState, BYTE_COUNT); //strobe row off - digitalWrite(STROBE_PIN, HIGH); + digitalWrite(STROBE_PIN, LOW); rowEnd = 1 << KEY_COUNT; + + //clear unpowered pins (for testing bb) todo + if (BYTE_COUNT == 1) rowState &= 0b00010001; + if (BYTE_COUNT == 2) rowState &= 0b0001000100010001; + if (BYTE_COUNT == 3) rowState &= 0b000100010001000100010001; + if (BYTE_COUNT == 4) rowState &= 0b01010001000100010001000100010001; //also 31st key + +//Keyboard.print(" ");//todo +//Keyboard.print(rowState); //why does rowState change to 1 for both rows? (row pin 8 is unplugged) return rowState; } diff --git a/src/RowScanner_SPIShiftRegisters.h b/src/RowScanner_SPIShiftRegisters.h index fd045e9..7489f19 100644 --- a/src/RowScanner_SPIShiftRegisters.h +++ b/src/RowScanner_SPIShiftRegisters.h @@ -10,6 +10,22 @@ /* RowScanner_SPIShiftRegisters reads all shift registers in a daisy chain. The maximum keys per row is 31, because Arduino's largest type is 32 bits and rowEnd consumes the last bit. //todo delete: Assumes only one row of shift registers is connected (no Slave Select). + +For active low: + 10k pull-up resistor are connected to power + connect controller's MISO pin to shift register's /QH pin + in sketch, const bool RowScanner_PinsArray::ACTIVE_HIGH = 0; + +For active high: + 10k pull-down resistors are grounded + connect controller's MISO pin to shift register's QH pin + in sketch, const bool RowScanner_PinsArray::ACTIVE_HIGH = 1; + +shift registers 74HC165 Parallel-In-Serial-Out (PISO) are Daisy chained + +The maximum keys per row is 31, because Arduino's largest type is 32 bits and rowEnd consumes the last bit. +call begin() from setup() + */ class RowScanner_SPIShiftRegisters : public RowScannerInterface { @@ -17,13 +33,13 @@ class RowScanner_SPIShiftRegisters : public RowScannerInterface //todo static const bool ACTIVE_HIGH; //logic level of strobe pin: 0=activeLow, 1=activeHigh const uint8_t STROBE_PIN; //Arduino pin number connected to this row const uint8_t SHIFT_LOAD; //controller's pin number that is connected to shift register's SHIFT_LOAD pin - const uint8_t BYTE_COUNT; //number of bytes to read from shift registers const uint8_t KEY_COUNT; //number of keys in row + const uint8_t BYTE_COUNT; //number of bytes to read from shift registers public: RowScanner_SPIShiftRegisters(const uint8_t STROBE_PIN, const uint8_t SHIFT_LOAD, - uint8_t BYTE_COUNT, uint8_t KEY_COUNT) + uint8_t KEY_COUNT) : STROBE_PIN(STROBE_PIN), SHIFT_LOAD(SHIFT_LOAD), - BYTE_COUNT(BYTE_COUNT), KEY_COUNT(KEY_COUNT) {} + KEY_COUNT(KEY_COUNT), BYTE_COUNT(ceil (float(KEY_COUNT)/8)) {} virtual read_pins_t scan(read_pins_mask_t& rowEnd); void begin(); }; diff --git a/src/Row_ShiftRegisters.h b/src/Row_ShiftRegisters.h index cf244ad..890a996 100644 --- a/src/Row_ShiftRegisters.h +++ b/src/Row_ShiftRegisters.h @@ -31,9 +31,9 @@ class Row_ShiftRegisters : public RowBase Debouncer_4Samples debouncer; //Debouncer_Not debouncer; //todo test public: - Row_ShiftRegisters(const uint8_t STROBE_PIN, const uint8_t SHIFT_LOAD, uint8_t BYTE_COUNT, + Row_ShiftRegisters(const uint8_t STROBE_PIN, const uint8_t SHIFT_LOAD, Key *const ptrsKeys[], uint8_t KEY_COUNT) - : RowBase(ptrsKeys), scanner(STROBE_PIN, SHIFT_LOAD, BYTE_COUNT, KEY_COUNT) { } + : RowBase(ptrsKeys), scanner(STROBE_PIN, SHIFT_LOAD, KEY_COUNT) { } void begin(); read_pins_t scan(read_pins_mask_t& rowEnd); read_pins_t debounce(const read_pins_t rowState, read_pins_t& debounced);