@@ -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 <Debug.h> | |||
//IOE Ports | |||
#include "IOExpanderPort.h" | |||
#include <RowPort_MCP23018.h> | |||
#include <ColPort_MCP23018.h> | |||
//Codes | |||
#include <Code_Sc.h> | |||
//Matrix | |||
#include <Row_uC.h> | |||
#include <SPI.h> | |||
#include <Row_ShiftRegisters.h> | |||
// =============== 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(); | |||
} |
@@ -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 <Debug.h> | |||
//IOE Ports | |||
#include "IOExpanderPort.h" | |||
#include <RowPort_MCP23018.h> | |||
#include <ColPort_MCP23018.h> | |||
//Codes | |||
#include <Code_Sc.h> | |||
//Matrix | |||
#include <Row_uC.h> | |||
#include <SPI.h> | |||
#include <Row_ShiftRegisters.h> | |||
// =============== 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(""); | |||
} |
@@ -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; | |||
} | |||
@@ -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(); | |||
}; |
@@ -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); |