@@ -0,0 +1,11 @@ | |||
#include "LED_IOE.h" | |||
void LED_IOE::on() | |||
{ | |||
refPort.write(pin, HIGH); | |||
} | |||
void LED_IOE::off() | |||
{ | |||
refPort.write(pin, LOW); | |||
} |
@@ -0,0 +1,24 @@ | |||
#ifndef LED_IOE_H | |||
#define LED_IOE_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <LED.h> | |||
#include <PortWriteInterface.h> | |||
/* 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 |
@@ -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 | |||
{ |
@@ -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() | |||
{ |
@@ -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 | |||
{ |
@@ -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. |
@@ -39,7 +39,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount); | |||
// =================== CODES =================== | |||
// ---------------- LAYER CODE ----------------- | |||
enum layers { ALPHA, SYM }; | |||
enum layerIds { ALPHA, SYM }; | |||
LayerState layerState; | |||
@@ -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; | |||
@@ -36,7 +36,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount); | |||
// =================== CODES =================== | |||
// ---------------- LAYER CODE ----------------- | |||
enum layers { ALPHA, SYM }; | |||
enum layerIds { ALPHA, SYM }; | |||
LayerState layerState; | |||
@@ -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); |
@@ -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); |
@@ -19,42 +19,38 @@ This sketch: | |||
#include <Code_LayerHold.h> | |||
#include <Key_LayeredKeys.h> | |||
#include <Row_uC.h> | |||
#include <Row.h> | |||
#include <Scanner_uC.h> | |||
#include <ScanDelay.h> | |||
#include <LED_uC.h> | |||
// ============ 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() | |||
{ |
@@ -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 <ScanDelay.h> | |||
#include <Code_LEDLock.h> | |||
#include <Code_Sc.h> | |||
#include <Row.h> | |||
//left matrix | |||
#include <Scanner_uC.h> | |||
//right matrix | |||
#include <PortIOE.h> | |||
#include <PortWrite_MCP23S17.h> | |||
#include <PortRead_MCP23S17.h> | |||
#include <Scanner_IOE.h> | |||
#include <LED_IOE.h> | |||
// ============ 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(); | |||
} |
@@ -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. |