diff --git a/src/LED_IOE.cpp b/src/LED_IOE.cpp new file mode 100644 index 0000000..b5fde59 --- /dev/null +++ b/src/LED_IOE.cpp @@ -0,0 +1,11 @@ +#include "LED_IOE.h" + +void LED_IOE::on() +{ + refPort.write(pin, HIGH); +} + +void LED_IOE::off() +{ + refPort.write(pin, LOW); +} diff --git a/src/LED_IOE.h b/src/LED_IOE.h new file mode 100644 index 0000000..3297f73 --- /dev/null +++ b/src/LED_IOE.h @@ -0,0 +1,24 @@ +#ifndef LED_IOE_H +#define LED_IOE_H +#include +#include +#include +#include +#include + +/* A LED_IOE object is an I/O expander pin that is connected to an LED indicator light. +Input/Ouput Direction configuration are set to ouput in PortWrite_*.begin() and PortRead_*.begin(). todo PortRead_*?? +*/ +class LED_IOE: public LED +{ + private: + PortWriteInterface& refPort; + const uint8_t pin; //bit pattern, 1 is IOE pin to LED + + public: + LED_IOE(PortWriteInterface& refPort, const uint8_t pin) + : refPort(refPort), pin(pin) {} + virtual void on(); + virtual void off(); +}; +#endif diff --git a/src/PortReadInterface.h b/src/PortReadInterface.h index c2c3cfd..bee3b6c 100644 --- a/src/PortReadInterface.h +++ b/src/PortReadInterface.h @@ -5,9 +5,6 @@ /* Port classes are the keybrd library's interface to microcontroller ports or I/O expander ports. - -If your 8-bit AVR (Teensy 2) is running low on memory, using a smaller read_pins_t type saves SRAM. -Details are in config_key.h */ class PortReadInterface { diff --git a/src/PortRead_MCP23S17.cpp b/src/PortRead_MCP23S17.cpp index 3807061..f5caa63 100644 --- a/src/PortRead_MCP23S17.cpp +++ b/src/PortRead_MCP23S17.cpp @@ -5,7 +5,7 @@ Configures read pins to input with pullup enabled. */ void PortRead_MCP23S17::begin(const uint8_t strobeOn) { - if (strobeOn == LOW) //if active low + if (strobeOn == LOW) //if active low, use internal pull-up resistors { pullUp = readPins; } @@ -19,8 +19,7 @@ void PortRead_MCP23S17::begin(const uint8_t strobeOn) //0=pull-up disabled, 1=pull-up enabled } -/* read() returns portState. -Only portState bits of readPins are valid. +/* read() returns portState. Only portState pins with pull resistors are valid. */ uint8_t PortRead_MCP23S17::read() { diff --git a/src/PortWriteInterface.h b/src/PortWriteInterface.h index 4b80bd0..a46026d 100644 --- a/src/PortWriteInterface.h +++ b/src/PortWriteInterface.h @@ -5,9 +5,6 @@ /* Port classes are the keybrd library's interface to microcontroller ports or I/O expander ports. - -If your 8-bit AVR (Teensy 2) is running low on memory, using a smaller read_pins_t type saves SRAM. -Details are in config_key.h */ class PortWriteInterface { diff --git a/tutorials/breadboard_keyboard_supplies.ods b/tutorials/breadboard_keyboard_supplies.ods index b185ce4..b3b4408 100644 Binary files a/tutorials/breadboard_keyboard_supplies.ods and b/tutorials/breadboard_keyboard_supplies.ods differ diff --git a/tutorials/keybrd_3a_multi-layerHold/DSCF0001.JPG b/tutorials/keybrd_3a_multi-layerHold/DSCF0001.JPG new file mode 100644 index 0000000..a5c28d5 Binary files /dev/null and b/tutorials/keybrd_3a_multi-layerHold/DSCF0001.JPG differ diff --git a/tutorials/keybrd_3a_multi-layerHold/DSCF0002.JPG b/tutorials/keybrd_3a_multi-layerHold/DSCF0002.JPG new file mode 100644 index 0000000..0b2f0b7 Binary files /dev/null and b/tutorials/keybrd_3a_multi-layerHold/DSCF0002.JPG differ diff --git a/tutorials/keybrd_3a_multi-layerHold/DSCF0003.JPG b/tutorials/keybrd_3a_multi-layerHold/DSCF0003.JPG new file mode 100644 index 0000000..324b606 Binary files /dev/null and b/tutorials/keybrd_3a_multi-layerHold/DSCF0003.JPG differ diff --git a/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino b/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino index 746a0eb..7049eec 100644 --- a/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino +++ b/tutorials/keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino @@ -42,7 +42,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount); enum assigns layerId numbers to the layers. NORMAL=0 and FN=1. LayerState's default layerId is 0. */ -enum layers { NORMAL, FN }; +enum layerIds { NORMAL, FN }; /* layerState keeps track of the active layer. diff --git a/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino b/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino index 78d13e1..0da26a1 100644 --- a/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino +++ b/tutorials/keybrd_3b_multi-layerLock/keybrd_3b_multi-layerLock.ino @@ -39,7 +39,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount); // =================== CODES =================== // ---------------- LAYER CODE ----------------- -enum layers { ALPHA, SYM }; +enum layerIds { ALPHA, SYM }; LayerState layerState; diff --git a/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino b/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino index d88796d..7d0a999 100644 --- a/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino +++ b/tutorials/keybrd_3c_sublayerNull/keybrd_3c_sublayerNull.ino @@ -38,7 +38,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount); /* ---------------- LAYER CODE ----------------- One LayerState object manages all 3 layers. */ -enum layers { ALPHA, SYM, NUM }; +enum layerIds { ALPHA, SYM, NUM }; LayerState layerState; diff --git a/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino b/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino index 5d59c1f..3fe1dd8 100644 --- a/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino +++ b/tutorials/keybrd_3e_sublayerNestedScSc/keybrd_3e_sublayerNestedScSc.ino @@ -36,7 +36,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount); // =================== CODES =================== // ---------------- LAYER CODE ----------------- -enum layers { ALPHA, SYM }; +enum layerIds { ALPHA, SYM }; LayerState layerState; diff --git a/tutorials/keybrd_3f_autoShift/keybrd_3f_autoShift.ino b/tutorials/keybrd_3f_autoShift/keybrd_3f_autoShift.ino index 14d6cdd..bab06b2 100644 --- a/tutorials/keybrd_3f_autoShift/keybrd_3f_autoShift.ino +++ b/tutorials/keybrd_3f_autoShift/keybrd_3f_autoShift.ino @@ -40,7 +40,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount); // =================== CODES =================== // ---------------- LAYER CODE ----------------- -enum layers { NORMAL, FN }; +enum layerIds { NORMAL, FN }; LayerState layerState; Code_LayerHold l_fn(FN, layerState); diff --git a/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino b/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino index bb56566..d504d6d 100644 --- a/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino +++ b/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino @@ -61,7 +61,6 @@ port_B is assigned port identification number 1. port_B is assigned to portWrite. */ PortIOE port_B(1); -//PortWrite_MCP23S17 portWrite(port_B); //for LEDs todo PortWrite_MCP23S17 portWrite(port_B); Scanner_IOE scanner_R(LOW, portWrite, portRead); diff --git a/tutorials/keybrd_5_LEDs/keybrd_5_LEDs.ino b/tutorials/keybrd_5_LEDs/keybrd_5_LEDs.ino index 1c53435..9c81d13 100644 --- a/tutorials/keybrd_5_LEDs/keybrd_5_LEDs.ino +++ b/tutorials/keybrd_5_LEDs/keybrd_5_LEDs.ino @@ -19,42 +19,38 @@ This sketch: #include #include -#include +#include +#include #include #include // ============ SPEED CONFIGURATION ============ ScanDelay scanDelay(9000); -// ================ ACTIVE STATE =============== -const bool Scanner_uC::STROBE_ON = LOW; -const bool Scanner_uC::STROBE_OFF = HIGH; - -// ================= PINS ================= +// ================== SCANNER ================== uint8_t readPins[] = {14, 15}; -uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins); +uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); + +Scanner_uC scanner(LOW, readPins, readPinCount); /* ==================== LEDs =================== The LED_uC constructor parameter is for an Aduino pin number that is connected to an LED. -LED objects are passed to other objects that want to turn the LED on or off. In this example, the LED_uC objects are named after the states they indicate. - -The prtsLayerLEDs[] array contains one LED per layer, it is used to indicate the current layer. */ LED_uC LED_normal(16); LED_uC LED_fn(17); LED_uC LED_CapsLck(21); -LED* prtsLayerLEDs[] = { &LED_normal, &LED_fn }; - // =================== CODES =================== /* ---------------- LAYER CODE ----------------- -LayerState_LED is similar to LayerState, introduced in keybrd_3a_multi-layer.ino, but with LEDs. -The LayerState_LED turns on the LED of the current layer. -The active layer is used as an index to dereference the prtsLayerLEDs[] array. +LayerState_LED is similar to LayerState, introduced in keybrd_3a_multi-layerHold.ino, but with LEDs. +The LayerState_LED turns on the LED of the active layer. +The prtsLayerLEDs[] array contains one LED per layer. +The active layerId is used as an index to dereference the prtsLayerLEDs[] array. */ enum layers { NORMAL, FN }; +LED* prtsLayerLEDs[] = { &LED_normal, &LED_fn }; //array index matches enum layerIds LayerState_LED layerState(prtsLayerLEDs); Code_LayerHold l_fn(FN, layerState); @@ -82,13 +78,15 @@ LayerStateInterface& Key_LayeredKeys::refLayerState = layerState; // =================== ROWS ==================== Key* const ptrsKeys_0[] = { &o_capsLock, &k_01 }; -Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0); +uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0); +Row row_0(scanner, 0, ptrsKeys_0, keyCount_0); Key* const ptrsKeys_1[] = { &l_fn, &k_11 }; -Row_uC row_1(1, readPins, READ_PIN_COUNT, ptrsKeys_1); +uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1); +Row row_1(scanner, 1, ptrsKeys_1, keyCount_1); /* ################### MAIN #################### -layerState.begin() turns on the LED of the initial active layer. +layerState.begin() turns on the LED of the default layer. */ void setup() { diff --git a/tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino b/tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino new file mode 100644 index 0000000..a329815 --- /dev/null +++ b/tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino @@ -0,0 +1,112 @@ +/* keybrd_5b_LED_on_IOE.ino + +This sketch: + is a simple 1-layer keyboard with CapsLck indicator LED on I/O expander + runs on two matrices of a breadboard keyboard + modified keybrd_4c_split_keyboard_with_IOE.ino by adding LED_CapsLck + +This layout table shows left and right matrices: + +| Left | **0** | **1** | | Right | **0** | **1** | +|:-----:|-------|-------|-|:-----:|-------|-------| +| **1** | 1 | 2 | | **1** | 3 |CapsLck| +| **0** | a | b | | **0** | c | d | +*/ +// ################## GLOBAL ################### +// ================= INCLUDES ================== +#include +#include +#include +#include + +//left matrix +#include + +//right matrix +#include +#include +#include +#include +#include + +// ============ SPEED CONFIGURATION ============ +ScanDelay scanDelay(9000); + +// ================ LEFT SCANNER =============== +uint8_t readPins[] = {14, 15}; +const uint8_t READPIN_COUNT = sizeof(readPins)/sizeof(*readPins); + +Scanner_uC scanner_L(LOW, readPins, READPIN_COUNT); + +// =============== RIGHT SCANNER =============== +const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address with all 3 ADDR pins are grounded + +PortIOE port_A(0); +PortRead_MCP23S17 portRead(port_A, 1<<0 | 1<<1 ); +PortWrite_MCP23S17 portWriteA(port_A); //for LED +//todo portWriteA(port_A) instantiation would not be needed if PortRead_MCP23S17 had write() +// consider moving PortWrite_MCP23S17::write to Port_MCP23S17 (parent) +// and passing portRead to LED_IOE +// same for PCA9655E + +PortIOE port_B(1); +PortWrite_MCP23S17 portWrite(port_B); + +Scanner_IOE scanner_R(LOW, portWrite, portRead); + +// ================ RIGHT LEDs ================= +LED_IOE LED_CapsLck(portWriteA, 1<<6); //tested LED on port A (read) +//LED_IOE LED_CapsLck(portWrite, 1<<6);//tested LED on port B (write) + +// =================== 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_1(KEY_1); +Code_Sc s_2(KEY_2); +Code_Sc s_3(KEY_3); + +Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_CapsLck); + +// =================== ROWS ==================== +// ---------------- LEFT ROWS ------------------ +Key* ptrsKeys_L0[] = { &s_1, &s_2 }; +const uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0); +Row row_L0(scanner_L, 0, ptrsKeys_L0, KEY_COUNT_L0); + +Key* ptrsKeys_L1[] = { &s_a, &s_b }; +const uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1); +Row row_L1(scanner_L, 1, ptrsKeys_L1, KEY_COUNT_L1); + +// ---------------- RIGHT ROWS ----------------- +Key* ptrsKeys_R0[] = { &s_3, &o_capsLock }; +const uint8_t KEY_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0); +Row row_R0(scanner_R, 1<<0, ptrsKeys_R0, KEY_COUNT_R0); + +Key* ptrsKeys_R1[] = { &s_c, &s_d }; +const uint8_t KEY_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1); +Row row_R1(scanner_R, 1<<1, ptrsKeys_R1, KEY_COUNT_R1); + +// ################### MAIN #################### +void setup() +{ + Keyboard.begin(); + scanner_R.begin(); +} + +void loop() +{ + //left matrix + row_L0.process(); + row_L1.process(); + + //right matrix + row_R0.process(); + row_R1.process(); + + scanDelay.delay(); + //debug.print_scans_per_second(); + //debug.print_microseconds_per_scan(); +} diff --git a/tutorials/tutorial_4a_connecting_split_keyboards.md b/tutorials/tutorial_4_connecting_split_keyboards.md similarity index 89% rename from tutorials/tutorial_4a_connecting_split_keyboards.md rename to tutorials/tutorial_4_connecting_split_keyboards.md index 391982c..8561dbd 100644 --- a/tutorials/tutorial_4a_connecting_split_keyboards.md +++ b/tutorials/tutorial_4_connecting_split_keyboards.md @@ -1,4 +1,4 @@ -keybrd Tutorial 4a - Connecting split keyboards +keybrd Tutorial 4 - Connecting split keyboards =============================================== Split keyboards have left and right parts: * one keyboard half contains the controller and USB port. @@ -11,10 +11,10 @@ The preferred connection method depends on the number of keys, number of availab | connection type | controller pins | wire count | max keys | |:----------------------:|:---------------:|:----------:|:--------:| -| just cable | 6 | 6 | 9 | -| just cable | 7 | 7 | 12 | -| just cable | 8 | 8 | 16 | -| just cable | 9 | 9 | 20 | +| just cable | 3 | 6 | 9 | +| just cable | 3 | 7 | 12 | +| just cable | 4 | 8 | 16 | +| just cable | 4 | 9 | 20 | | | | | | | 2 PISO shift registers | 3 | 5 | 16 | | 3 PISO shift registers | 3 | 5 | 24 | @@ -49,7 +49,7 @@ There are hundreds of other connectors listed at http://pinouts.ru/ There are also wireless options if you don't mind adding complexity and maintaining a battery. The 8-wire "GearIT Cat 6 Ethernet Flat Patch Cable 7 Feet" is very flexible. -It's available at Walmart if you want to feel the merchandise before you buy. +It's available at Walmart (9/19/16) if you want to feel the merchandise before you buy. All the modular connectors are flat. For prototyping on perfboards, consider a 0.1” header.