rename LED_IOE to LED_Port, update tutorials and sketches
@ -16,11 +16,12 @@ or [geekhack thread](https://geekhack.org/index.php?topic=83599.0).
|
||||
|
||||
Bug reports
|
||||
-----------
|
||||
A bug report is the first step in making the keybrd library work the way it's supposed to work.
|
||||
Submit bug reports to [GitHub issues](https://github.com/wolfv6/Keybrd/issues)
|
||||
A bug report is the first step in finding a bug.
|
||||
Once it is found, correcting it is usually relatively easy.
|
||||
Please submit bug reports to [GitHub issues](https://github.com/wolfv6/Keybrd/issues)
|
||||
or [geekhack thread](https://geekhack.org/index.php?topic=83599.0).
|
||||
|
||||
Please provide enough information so we can reproduce the bug behaviour!
|
||||
Provide enough information so we can reproduce the buggy behaviour!
|
||||
* Complete sketch (copy & paste, attachment, or a link to the code)
|
||||
* Screenshot or the exact text of error messages
|
||||
* Describe the observed behavior and explain which behavior you expected
|
||||
@ -48,20 +49,39 @@ Any project requires various kinds of contributions to succeed.
|
||||
A thriving project is more than a pile of code.
|
||||
It's the packaging, explanation, outreach, and empathy of maintainers that make a good project great.
|
||||
|
||||
User Contributions can be in the form of:
|
||||
* Blog - You have a fresh perspective of how the keybrd library works.
|
||||
This makes you the perfect person to write an introductory blog explaining the project.
|
||||
A healthy project needs the perspective of many people.
|
||||
* Documentation - Suggest a clarification, simplification, correction, or other improvement.
|
||||
### Beta testing
|
||||
keybrd library has been Alpha tested on the DodoHand keyboard, tutorial sketches, Teensy 2.0, and Teensy LC. What we need now are Beta testers:
|
||||
* use the tutorials (feedback from noobs is especially valuable)
|
||||
* use the keybrd library to implement your own keyboard design
|
||||
|
||||
Feedback from Beta testers will be used to make improvements to the keybrd library.
|
||||
|
||||
### Schematics
|
||||
The most glaring deficiency is the tutorials' lack of schematics.
|
||||
Schematics would be an improvement over the current photos.
|
||||
|
||||
Schematics are not my area of expertise. Use what ever you think would be the best solution for the tutorials:
|
||||
* schematics
|
||||
* breadboard drawings
|
||||
* Arduino simulation software
|
||||
|
||||
Contributions of tutorial schematics would benefit users new to the keybrd library.
|
||||
|
||||
### Documentation
|
||||
Suggest a clarification, simplification, correction, or other improvement.
|
||||
We need the perspective of people new to the project to see these things.
|
||||
Sometimes just changing a word or two makes a big difference.
|
||||
* [Current user contributions](https://geekhack.org/index.php?topic=83599.msg2223776#msg2223776) highlights contributions that are needed for the keybrd project's current stage of development.
|
||||
|
||||
Text file documentation style guide:
|
||||
* Use Markdown with a .md suffix.
|
||||
* "Underline" first-level (=) and second-level (-) headings (because easier to read in plain text).
|
||||
* Capitalize first letter of headings (no extra capitalization in headings).
|
||||
|
||||
### Blog
|
||||
You have a fresh perspective of how the keybrd library works.
|
||||
This makes you the perfect person to write an introductory blog explaining the project.
|
||||
A healthy project needs the perspective of many people.
|
||||
|
||||
Submitting a pull request
|
||||
-------------------------
|
||||
Pull request is the preferred way to contribute code and documentation.
|
||||
|
@ -27,6 +27,7 @@ Example minimal keybrd sketch
|
||||
-----------------------------
|
||||
A [minimal keybrd sketch](/tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino)
|
||||
is 40 lines of code for a 4-key keyboard.
|
||||
It scans a key matrix just like the big keyboards.
|
||||
The sketch is small because the keybrd library takes care of the low-level details.
|
||||
It runs the breadboard keyboard in this picture.
|
||||
|
||||
@ -34,9 +35,11 @@ It runs the breadboard keyboard in this picture.
|
||||
|
||||
Example complex keybrd sketch
|
||||
-----------------------------
|
||||
keybrd_DH and its instantiation files contain about 800 lines of code.
|
||||
It emulates the DataHand keyboard.
|
||||
The keybrd_DH sketch is a showcase of the keybrd library's capability.
|
||||
It emulates the DataHand keyboard, which has the most complex layout I know of.
|
||||
Its layout has 52 keys, 3 primary layers, 5 sub-layers, 2 matrices, 8 LEDs, and blinking LEDs.
|
||||
Most layouts are much simpler.
|
||||
keybrd_DH and its instantiation files contain about 800 lines of code.
|
||||
|
||||
[keybrd_DH_library_developer_guide.md](https://github.com/wolfv6/keybrd_DH/blob/master/doc/keybrd_DH_library_developer_guide.md)<br>
|
||||
[mainSketch.ino](https://github.com/wolfv6/keybrd_DH/blob/master/examples/keybrd_DH/mainSketch.cpp)<br>
|
||||
|
@ -11,6 +11,29 @@ Unreleased
|
||||
----------
|
||||
-->
|
||||
|
||||
0.6.0 (2016-09-28)
|
||||
------------------
|
||||
* Enhancements
|
||||
* Add Port_MCP23S17
|
||||
* Add Scanner_ShiftRegsPISOSingleRow and Scanner_ShiftRegsPISOMultiRow
|
||||
* Refine and update tutorials
|
||||
* Add tutorial_3cde_sublayer_keyboard.md
|
||||
* Add tutorial_4_connecting_split_keyboards.md
|
||||
* Add tutorial_4b_split_keyboard_with_shift_registers.md
|
||||
* Add tutorial_4c_split_keyboard_with_IOE.md
|
||||
* Add tutorial_5b_LED_on_IOE.md
|
||||
|
||||
* Backward incompatible changes
|
||||
* Move scanner instantiation from Row_* to sketch
|
||||
* Delete Row_uC and Row_IOE, and replace them with Row
|
||||
* Combine PortWrite_PCA9655E and PortRead_PCA9655E into Port_PCA9655E
|
||||
* Delete PortIOE, and move PortIOE variables to IOE port classes
|
||||
* Rename LED_PCA9655E to LED_Port
|
||||
* Rename Scanner_Port to Scanner_IOE
|
||||
* Rename Key_LayeredKeysArray to Key_LayeredKeys
|
||||
* Rename Code_Layered* to Key_Layered*
|
||||
* Rename object_*.h files to instantiations_*.h
|
||||
|
||||
0.5.0 (2016-07-22)
|
||||
------------------
|
||||
* Enhancements
|
||||
|
@ -24,8 +24,6 @@ Keybrd library class inheritance diagram
|
||||
Scanner_uC Scanner_IOE Scanner_ShiftRegsPISO
|
||||
|
||||
|
||||
PortIOE
|
||||
|
||||
PortInterface
|
||||
/ \
|
||||
Port_PCA9655E Port_MCP23S17 (one Port class for each IOE type)
|
||||
@ -33,7 +31,7 @@ Keybrd library class inheritance diagram
|
||||
|
||||
LEDInterface
|
||||
/ \
|
||||
LED_uC LED_IOE
|
||||
LED_uC LED_Port
|
||||
|
||||
|
||||
DebouncerInterface
|
||||
@ -118,7 +116,7 @@ Dependency diagram of example I/O expander matrix with LEDs
|
||||
/ | \ / \
|
||||
strobePin PortWrite PortRead Code Code_LEDLock
|
||||
| \ / \ |
|
||||
| PortIOE readPins LED_IOE
|
||||
| PortIOE readPins LED_Port
|
||||
\___________________________/ \
|
||||
pin
|
||||
|
||||
|
@ -115,36 +115,25 @@ Example keybrd sketches
|
||||
Example keybrd sketches are in the examples and tutorials directories.
|
||||
Extension libraries have their example sketches similarly located.
|
||||
|
||||
The example sketch names use the following conventions.
|
||||
|
||||
**keybrd_feature_version.ino**
|
||||
|
||||
where
|
||||
* **keybrd** is the library name e.g. keybrd, keybrd_DH
|
||||
* **feature** is a distinguishing feature of the keybrd sketch e.g. keyboard name, sound, layout
|
||||
* **version** is the sketch's version number (optional)
|
||||
|
||||
Active state and diode orientation
|
||||
----------------------------------
|
||||
Active state is set in the sketch by variables STROBE_ON and STROBE_OFF.
|
||||
Active state is set in the sketch by the scanner.
|
||||
The following instructions are for setting active state for a Scanner_uC class
|
||||
(Scanner_ShiftRegs74HC165 and Scanner_Port classes is similar).
|
||||
|
||||
For active low:
|
||||
* Orient diodes with cathode (banded end) towards the write pins (row)
|
||||
* Define strobe on and strobe off in the sketch like this:
|
||||
* Instantiate the scanner in the sketch with strobeOn LOW, like this:
|
||||
```
|
||||
const bool Scanner_uC::STROBE_ON = LOW;
|
||||
const bool Scanner_uC::STROBE_OFF = HIGH;
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
```
|
||||
|
||||
For active high:
|
||||
* Add an external 10k pull-down resistor to each read pin.
|
||||
* Orient diodes with cathode (banded end) towards the read pins.
|
||||
* Define strobe on and strobe off in the sketch like this:
|
||||
* Instantiate the scanner in the sketch with strobeOn HIGH, like this:
|
||||
```
|
||||
const bool Scanner_uC::STROBE_ON = HIGH;
|
||||
const bool Scanner_uC::STROBE_OFF = LOW;
|
||||
Scanner_uC scanner(HIGH, readPins, readPinCount);
|
||||
```
|
||||
|
||||
Troubleshooting check list
|
||||
|
@ -1,24 +0,0 @@
|
||||
#ifndef LED_IOE_H
|
||||
#define LED_IOE_H
|
||||
#include <Arduino.h>
|
||||
#include <inttypes.h>
|
||||
#include <Wire.h>
|
||||
#include <LEDInterface.h>
|
||||
#include <PortInterface.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 LEDInterface
|
||||
{
|
||||
private:
|
||||
PortInterface& refPort;
|
||||
const uint8_t pin; //bit pattern, 1 is IOE pin to LED
|
||||
|
||||
public:
|
||||
LED_IOE(PortInterface& refPort, const uint8_t pin)
|
||||
: refPort(refPort), pin(pin) {}
|
||||
virtual void on();
|
||||
virtual void off();
|
||||
};
|
||||
#endif
|
@ -1,11 +1,11 @@
|
||||
#include "LED_IOE.h"
|
||||
#include "LED_Port.h"
|
||||
|
||||
void LED_IOE::on()
|
||||
void LED_Port::on()
|
||||
{
|
||||
refPort.write(pin, HIGH);
|
||||
}
|
||||
|
||||
void LED_IOE::off()
|
||||
void LED_Port::off()
|
||||
{
|
||||
refPort.write(pin, LOW);
|
||||
}
|
28
src/LED_Port.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef LED_PORT_H
|
||||
#define LED_PORT_H
|
||||
#include <Arduino.h>
|
||||
#include <inttypes.h>
|
||||
#include <Wire.h>
|
||||
#include <LEDInterface.h>
|
||||
#include <PortInterface.h>
|
||||
|
||||
/* An LED_Port object is an I/O expander pin that is connected to an LED indicator light.
|
||||
|
||||
Example initialization:
|
||||
const uint8_t IOE_ADDR = 0x20;
|
||||
Port_MCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 );
|
||||
LED_Port LED_fn(portA, 1<<5);
|
||||
*/
|
||||
class LED_Port : public LEDInterface
|
||||
{
|
||||
private:
|
||||
PortInterface& refPort;
|
||||
const uint8_t pin; //bit pattern, 1 is IOE pin to LED
|
||||
|
||||
public:
|
||||
LED_Port(PortInterface& refPort, const uint8_t pin)
|
||||
: refPort(refPort), pin(pin) {}
|
||||
virtual void on();
|
||||
virtual void off();
|
||||
};
|
||||
#endif
|
@ -8,6 +8,9 @@
|
||||
|
||||
/* Basic LayerState with layer LED indictor lights.
|
||||
begin() should be called once to turn on LED for initial active layer.
|
||||
|
||||
If LED is on Scanner_IOE, LayerState_LED::begin() should be called after Scanner_IOE::begin()
|
||||
so that scanner's ports can turn on LayerState_LED's default-layer LED.
|
||||
*/
|
||||
class LayerState_LED : public LayerState
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ readPins parameter configures port's pins.
|
||||
Example instantiation:
|
||||
const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded
|
||||
Port_MCP23S17 portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs
|
||||
Port_MCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //first two pins are set to input for reading,
|
||||
Port_MCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //pin 0 and pin 1 are set to input for reading,
|
||||
//remaining pins can be used for LEDs
|
||||
|
||||
Diode orientation
|
||||
|
@ -22,7 +22,7 @@ Instantiation
|
||||
Example instantiation:
|
||||
const uint8_t IOE_ADDR = 0x20; //PCA9655E address, all 3 ADDR pins are grounded
|
||||
Port_PCA9655E portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs
|
||||
Port_PCA9655E portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //first two pins are set to input for reading,
|
||||
Port_PCA9655E portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //pin 0 and pin 1 are set to input for reading,
|
||||
//remaining pins can be used for LEDs
|
||||
|
||||
Diode orientation
|
||||
|
@ -2,13 +2,20 @@
|
||||
#define CONFIG_KEYBRD_H
|
||||
#include <inttypes.h>
|
||||
|
||||
/* 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.
|
||||
/* The maximum number of pins scanned by RowScanner depends on size of read_pins_t.
|
||||
By default, read_pins_t is set to uint32_t.
|
||||
If your 8-bit AVR (Teensy 2) is running low on memory, using a smaller type saves SRAM.
|
||||
Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing.
|
||||
*/
|
||||
|
||||
/* Use a read_pins_t size that covers all read pins of all Scanner objects i.e.
|
||||
read_pins_t is used in:
|
||||
Row bit patterns
|
||||
ScannerInterface::scan()
|
||||
Scanner_ShiftRegsPISO::scan()
|
||||
Scanner_uC::scan()
|
||||
DebouncerInterface::debounce()
|
||||
Debouncer_Samples::debounce()
|
||||
|
||||
Use a read_pins_t size that covers all read pins of all Scanner objects i.e.
|
||||
For Scanner_uC: read_pins_t bits >= Scanner_uC::readPinCount
|
||||
For Scanner_ShiftRegsPISO: read_pins_t bits >= Scanner_ShiftRegsPISO::byte_count * 8
|
||||
(For Scanner_IOE: I/O expanders are assumed to have 8 bits per port or less)
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef INSTANTIATIONS_SCANCODE_H
|
||||
#define INSTANTIATIONS_SCANCODE_H
|
||||
|
||||
/* Include this file in multiple-layer keybrd sketches.
|
||||
This file instandiates Code objects.
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef INSTANTIATIONS_SCANCODENOTSHIFTED_H
|
||||
#define INSTANTIATIONS_SCANCODENOTSHIFTED_H
|
||||
|
||||
/* This file instandiates Code_ScNS objects for multiple-layer keybrd sketches.
|
||||
The scancode is always sent in the unshifted state regardless of shift key position.
|
||||
Letters will still print as capital if CapsLck is on.
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 188 KiB After Width: | Height: | Size: 188 KiB |
@ -47,14 +47,15 @@ uint8_t readPins[] = {14, 15};
|
||||
uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
|
||||
/*
|
||||
The first parameter of the scanner constructor defines the logic level for the strobes.
|
||||
Scanner_uC constructor parameters are: strobeOn, readPins[], readPinCount.
|
||||
strobeOn defines the logic level for strobes, HIGH or LOW.
|
||||
"Active low" means that if a switch is pressed (active), the read pin is low.
|
||||
The scanner uses readPins, readPinCount to read the colums.
|
||||
The scanner uses readPins and readPinCount to read the colums.
|
||||
*/
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
/* HOW SCANNER OBJECTS WORK
|
||||
The scanner object strobes a row.
|
||||
The Scanner object strobes a row.
|
||||
If a key is pressed, the LOW strobe pulls that readPin LOW.
|
||||
Then the scanner reads its readPins.
|
||||
*/
|
||||
@ -76,11 +77,9 @@ Code_Sc s_2(KEY_2);
|
||||
Here we pack Code objects into Row objects.
|
||||
The Row objects names in this sketch start with a "row_" followed by a row number.
|
||||
|
||||
Row constructor has four parameters:
|
||||
1) scanner
|
||||
2) strobePin connected to the row.
|
||||
3) ptrsKeys[] containing all the Code objects of the row, one Code object per key.
|
||||
4) the number of keys in the row.
|
||||
Row constructor parameters are: scanner, strobePin, ptrsKeys[], keyCount.
|
||||
strobePin is the Arduino pin number connected to the row.
|
||||
ptrsKeys[] contains all the Code objects of the row, one Code object per key.
|
||||
*/
|
||||
Key* ptrsKeys_0[] = { &s_1, &s_2 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
@ -100,7 +99,7 @@ void setup()
|
||||
|
||||
/*
|
||||
loop() continually scans the matrix, one row at a time.
|
||||
Each row object strobes its strobePin and reads the readPins.
|
||||
Each Row object strobes its strobePin and reads the readPins.
|
||||
And when a key press is detected, the row sends the key's scancode.
|
||||
|
||||
scanDelay creates time intervals between matrix scans.
|
||||
|
Before Width: | Height: | Size: 336 KiB |
Before Width: | Height: | Size: 331 KiB |
Before Width: | Height: | Size: 322 KiB After Width: | Height: | Size: 322 KiB |
@ -10,10 +10,11 @@ This sketch:
|
||||
| **1** | fn | shift |
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
The keys in column 1 have two characters each, one character for each layer.
|
||||
Each element in a cell represents a scancode or layer code.
|
||||
The keys in row 0 have two characters each, one character for each layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Symbols '-' and '=' are on the fn layer.
|
||||
"fn" is a layer key. Holding the fn key down makes it the active layer.
|
||||
Releasing the fn key restores the normal layer.
|
||||
Letters 'a' and 'b' are on the normal layer. Symbols '-' and '=' are on the fn layer.
|
||||
*/
|
||||
// ################## GLOBAL ###################
|
||||
// ================= INCLUDES ==================
|
||||
@ -40,7 +41,7 @@ Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
// =================== CODES ===================
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
enum assigns layerId numbers to the layers.
|
||||
NORMAL=0 and FN=1. LayerState's default layerId is 0.
|
||||
NORMAL=0 and FN=1.
|
||||
*/
|
||||
enum layerIds { NORMAL, FN };
|
||||
|
||||
@ -50,12 +51,14 @@ layerState keeps track of the active layer.
|
||||
LayerState layerState;
|
||||
|
||||
/*
|
||||
The Code_LayerHold constructor has two parameters:
|
||||
1) the layerId that will be the active layer while the key is held down
|
||||
2) a LayerState that will keep track of the active layer
|
||||
When l_fn is pressed, it tells layerState to change the active layer to FN.
|
||||
Code_LayerHold constructor parameters are: layerId, LayerState.
|
||||
layerState is assigned to layer FN.
|
||||
layerState also has a default layer 0, which implicitly is layer NORMAL.
|
||||
|
||||
FN is the active layer while the key is held down.
|
||||
In this example, when l_fn is pressed, it tells layerState to change the active layer to FN.
|
||||
When l_fn is released, it tells layerState that layer FN is released,
|
||||
and layerState restores the active layer to NORMAL (sets active layer to the default layerId 0).
|
||||
and layerState restores the active layer to default layerId 0 (NORMAL).
|
||||
*/
|
||||
Code_LayerHold l_fn(FN, layerState);
|
||||
|
||||
@ -68,7 +71,7 @@ Code_Sc s_shift(MODIFIERKEY_LEFT_SHIFT);
|
||||
|
||||
/* =================== KEYS ====================
|
||||
Here we pack Codes into keys.
|
||||
The Key_LayeredKeys constructor takes one array of Code pointers - one Code object per layer.
|
||||
ptrsKeys_00[] contains all the Code objects of the key, one Code object per layer.
|
||||
|
||||
The Key object names in this sketch start with a "k_" followed by row-column coordinates.
|
||||
*/
|
||||
@ -90,13 +93,13 @@ The Code object then sends its scancode over USB.
|
||||
*/
|
||||
|
||||
/* =================== ROWS ====================
|
||||
Here we pack Key pointers into row objects.
|
||||
Here we pack Key pointers into Row objects.
|
||||
|
||||
Rows are composed of a Key-pointer array.
|
||||
Codes are a kind of Key that only have one layer.
|
||||
Thus rows can contain a mix of codes and multi-layered keys (subtype polymorphism).
|
||||
In this example, Key-pointer arrays contain both Code pointers (&s_shift and &l_fn)
|
||||
and Key pointers (&k_01 and &k_11).
|
||||
In this example, Key-pointer arrays contain both Code pointers (&l_fn and &s_shift)
|
||||
and Key pointers (&k_00 and &k_01).
|
||||
*/
|
||||
Key* const ptrsKeys_0[] = { &k_00, &k_01 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
|
@ -44,10 +44,10 @@ enum layerIds { ALPHA, SYM };
|
||||
LayerState layerState;
|
||||
|
||||
/*
|
||||
The Code_LayerLock constructor has two parameters:
|
||||
1) the layerId that becomes the active layer when the key is pressed
|
||||
2) a LayerState that will keep track of the active layer
|
||||
When l_normal is pressed, ALPHA becomes the active layer.
|
||||
Code_LayerLock constructor parameters are: layerId, LayerState.
|
||||
layerId becomes the active layer when the key is pressed.
|
||||
LayerState keeps track of the active layer.
|
||||
In this example, when l_normal is pressed, ALPHA becomes the active layer.
|
||||
When l_sym is pressed, SYM becomes the active layer.
|
||||
*/
|
||||
Code_LayerLock l_normal(ALPHA, layerState);
|
||||
|
BIN
tutorials/keybrd_3c_sublayerNull/front.JPG
Normal file
After Width: | Height: | Size: 136 KiB |
@ -1,7 +1,7 @@
|
||||
/* keybrd_3c_sublayerNull.ino
|
||||
|
||||
This sketch:
|
||||
is firmware for layout with 2 layers plus 1 sublayer.
|
||||
is firmware for layout with two layers plus one sublayer.
|
||||
runs on the first three columns of a breadboard keyboard
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
@ -35,18 +35,23 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
// =================== CODES ===================
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
One LayerState object manages all 3 layers.
|
||||
*/
|
||||
enum layerIds { ALPHA, SYM, NUM };
|
||||
|
||||
LayerState layerState;
|
||||
LayerState groupState;
|
||||
|
||||
Code_LayerLock l_normal(ALPHA, layerState);
|
||||
Code_LayerLock l_sym(SYM, layerState);
|
||||
Code_LayerHold l_num(NUM, layerState);
|
||||
/*
|
||||
groupState is assigned to layers ALPHA, SYM, and NUM.
|
||||
*/
|
||||
Code_LayerLock l_alpha(ALPHA, groupState);
|
||||
Code_LayerLock l_sym(SYM, groupState);
|
||||
Code_LayerHold l_num(NUM, groupState);
|
||||
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
/*
|
||||
groupState is assigned to Key_LayeredKeys.
|
||||
When a Key_LayeredKeys object is pressed, groupState returns the active layerId.
|
||||
Thus groupState manages a layer group delineated by all layers in Key_LayeredKeys objects.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = groupState;
|
||||
|
||||
// ---------------- SCAN CODES -----------------
|
||||
Code_Sc s_a(KEY_A);
|
||||
@ -61,12 +66,7 @@ Code_Sc s_1(KEY_1);
|
||||
Code_Null code_null;
|
||||
|
||||
/* =================== KEYS ====================
|
||||
When a Key_LayeredKeys is pressed, layerState returns the active layerId,
|
||||
which could be any of the layerIds in l_normal, l_sym, l_num.
|
||||
|
||||
The layout has one key with 3 layers, and two keys with 2 layers.
|
||||
But the layer scheme has 3 layers for all three keys.
|
||||
The extra layers are filled with duplicate codes and null codes.
|
||||
The layout's Num layer only covers the first key: s_1
|
||||
*/
|
||||
Key* const ptrsKeys_00[] = { &s_a, &s_minus, &s_1 };
|
||||
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||
@ -78,8 +78,8 @@ Key* const ptrsKeys_01[] = { &s_b, &s_equal, &s_equal };
|
||||
Key_LayeredKeys k_01(ptrsKeys_01);
|
||||
|
||||
/*
|
||||
code_null occupies layer 2. Class Code_Null doesn't do anything. It is useful for blank codes.
|
||||
Remember to fill all layers with codes.
|
||||
code_null occupies layer 2. Class Code_Null doesn't do anything.
|
||||
It is useful for blank codes. Remember to fill all layers of a Key_Layered object with codes.
|
||||
If the code_null were omitted from the array, dereferencing ptrsKeys_02[2] could cause a crash.
|
||||
*/
|
||||
Key* const ptrsKeys_02[] = { &s_c, &l_num, &code_null };
|
||||
@ -90,7 +90,7 @@ Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
||||
Key* const ptrsKeys_1[] = { &l_normal, &l_sym, &s_enter };
|
||||
Key* const ptrsKeys_1[] = { &l_alpha, &l_sym, &s_enter };
|
||||
uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1);
|
||||
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* keybrd_3d_sublayerNested.ino
|
||||
|
||||
This sketch:
|
||||
is firmware for layout with 2 layers plus 1 sublayer.
|
||||
is firmware for layout with two layers plus one sublayer.
|
||||
runs on the first three columns of a breadboard keyboard
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
@ -34,35 +34,47 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
// =================== CODES ===================
|
||||
// ----------------- LAYER CODE ----------------
|
||||
/* =================== CODES ===================
|
||||
Each LayerState object can manage one layer group. This sketch uses two LayerState objects.
|
||||
*/
|
||||
// ---------------- LAYER GROUP ----------------
|
||||
enum layers { ALPHA, SYM };
|
||||
|
||||
LayerState layerState;
|
||||
|
||||
Code_LayerLock l_normal(ALPHA, layerState);
|
||||
Code_LayerLock l_sym(SYM, layerState);
|
||||
/*
|
||||
groupState keeps track of a layer group's active layer.
|
||||
*/
|
||||
LayerState groupState;
|
||||
|
||||
/*
|
||||
Key_LayeredKeys are associated with layerState.
|
||||
groupState is assigned to layers ALPHA and SYM.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
Code_LayerLock l_alpha(ALPHA, groupState);
|
||||
Code_LayerLock l_sym(SYM, groupState);
|
||||
|
||||
/* ---------------- SUBLAYER CODE --------------
|
||||
Sublayers are implemented just like primary layers.
|
||||
/*
|
||||
groupState manages a layer group delineated by all layers that are in Key_LayeredKeys objects.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = groupState;
|
||||
|
||||
// --------------- LAYER SUBGROUP --------------
|
||||
enum subLayers { SUBSYM, SUBNUM };
|
||||
|
||||
LayerState sublayerState;
|
||||
|
||||
Code_LayerHold l_num(SUBNUM, sublayerState);
|
||||
/*
|
||||
subgroupState keeps track of a layer subgroup's active layer.
|
||||
*/
|
||||
LayerState subgroupState;
|
||||
|
||||
/*
|
||||
Key_LayeredKeys1 are associated with sublayerState.
|
||||
Key_LayeredKeys (in layer) and Key_LayeredKeys1 (in sublayer) classes are nearly identical,
|
||||
only the static refLayerState are different.
|
||||
subgroupState is assigned to layer SUBNUM.
|
||||
subgroupState also has a default layer 0, which implicitly is layer SUBSYM.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys1::refLayerState = sublayerState;
|
||||
Code_LayerHold l_num(SUBNUM, subgroupState);
|
||||
|
||||
/*
|
||||
Key_LayeredKeys and Key_LayeredKeys1 are identical classes with distinct static refLayerState.
|
||||
subgroupState manages a layer group delineated by all layers that are in Key_LayeredKeys1 objects.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys1::refLayerState = subgroupState;
|
||||
|
||||
// ---------------- SCAN CODES -----------------
|
||||
Code_Sc s_a(KEY_A);
|
||||
@ -76,17 +88,17 @@ Code_Sc s_enter(KEY_ENTER);
|
||||
Code_Sc s_1(KEY_1);
|
||||
|
||||
/* =================== KEYS ====================
|
||||
The key k_sub00 contains codes for layerIds SUBSYM and SUBNUM.
|
||||
k_sub00 contains codes for sub layers SUBSYM and SUBNUM.
|
||||
k_sub00 gets it's active layer from subgroupState.
|
||||
(The Num sublayer only has one key because small example. Usually sublayers have multiple keys.)
|
||||
*/
|
||||
Key* const ptrsKeys_sub00[] = { &s_minus, &s_1 };
|
||||
Key_LayeredKeys1 k_sub00(ptrsKeys_sub00);
|
||||
|
||||
/*
|
||||
k_sub00 is nested in k_00.
|
||||
The key k_00 contains code and key for layerIds ALPHA and SYM.
|
||||
Notice that k_sub00 is of type Key_LayeredKeys1, while k_00 is of type Key_LayeredKeys.
|
||||
k_sub00 and k_00 are associated with distinct LayerStates.
|
||||
k_00 contains code and key for layers ALPHA and SYM.
|
||||
k_00 gets it's active layer from groupState.
|
||||
k_sub00 is nested in layer SYM.
|
||||
*/
|
||||
Key* const ptrsKeys_00[] = { &s_a, &k_sub00 };
|
||||
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||
@ -102,7 +114,7 @@ Key* const ptrsKeys_0[] = { &k_00, &k_01, &k_02 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
||||
Key* const ptrsKeys_1[] = { &l_normal, &l_sym, &s_enter };
|
||||
Key* const ptrsKeys_1[] = { &l_alpha, &l_sym, &s_enter };
|
||||
uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1);
|
||||
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* keybrd_3e_sublayerNestedScSc.ino
|
||||
|
||||
This sketch:
|
||||
is firmware for layout 2 layers plus 1 sublayer.
|
||||
is firmware for layout two layers plus one sublayer.
|
||||
runs on the first three columns of a breadboard keyboard
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
@ -35,30 +35,30 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
|
||||
// =================== CODES ===================
|
||||
// ---------------- LAYER CODE -----------------
|
||||
// ---------------- LAYER GROUP ----------------
|
||||
enum layerIds { ALPHA, SYM };
|
||||
|
||||
LayerState layerState;
|
||||
LayerState groupState;
|
||||
|
||||
Code_LayerLock l_normal(ALPHA, layerState);
|
||||
Code_LayerLock l_sym(SYM, layerState);
|
||||
Code_LayerLock l_normal(ALPHA, groupState);
|
||||
Code_LayerLock l_sym(SYM, groupState);
|
||||
|
||||
/*
|
||||
Key_LayeredKeys are associated with layerState.
|
||||
groupState manages a layer group delineated by all layers that are in Key_LayeredKeys objects.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = layerState;
|
||||
LayerStateInterface& Key_LayeredKeys::refLayerState = groupState;
|
||||
|
||||
// ---------------- SUBLAYER CODE --------------
|
||||
// --------------- LAYER SUBGROUP --------------
|
||||
enum subLayers { SUBSYM, SUBNUM };
|
||||
|
||||
LayerState sublayerState;
|
||||
LayerState subgroupState;
|
||||
|
||||
Code_LayerHold l_num(SUBNUM, sublayerState);
|
||||
Code_LayerHold l_num(SUBNUM, subgroupState);
|
||||
|
||||
/*
|
||||
Key_LayeredScSc is associated with layerState.
|
||||
subgroupState manages a layer group delineated by all layers that are in Key_LayeredScSc objects.
|
||||
*/
|
||||
LayerStateInterface& Key_LayeredScSc::refLayerState = sublayerState;
|
||||
LayerStateInterface& Key_LayeredScSc::refLayerState = subgroupState;
|
||||
|
||||
// ---------------- SCAN CODES -----------------
|
||||
Code_Sc s_a(KEY_A);
|
||||
@ -72,16 +72,15 @@ Code_Sc s_enter(KEY_ENTER);
|
||||
Code_Sc s_1(KEY_1);
|
||||
|
||||
/* =================== KEYS ====================
|
||||
The key k_sub00 contains codes for layerIds SUBSYM and SUBNUM.
|
||||
Key_LayeredScSc takes two scancode arguments.
|
||||
(The Num sublayer only has one key because small example. Usually sublayers have multiple keys.)
|
||||
k_sub00 contains codes for sub layers SUBSYM and SUBNUM.
|
||||
k_sub00 gets it's active layer from subgroupState.
|
||||
*/
|
||||
Key_LayeredScSc sub_00(KEY_MINUS, KEY_1);
|
||||
|
||||
/*
|
||||
k_sub00 is nested in k_00.
|
||||
The key k_00 contains code and key for layerIds ALPHA and SYM.
|
||||
k_sub00 and k_00 are associated with distinct LayerStates.
|
||||
k_00 contains code and key for layers ALPHA and SYM.
|
||||
k_00 gets it's active layer from groupState.
|
||||
k_sub00 is nested in layer SYM.
|
||||
*/
|
||||
Key* const ptrsKeys_00[] = { &s_a, &sub_00 };
|
||||
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||
|
BIN
tutorials/keybrd_4b_split_keyboard_with_shift_registers/back.JPG
Normal file
After Width: | Height: | Size: 134 KiB |
After Width: | Height: | Size: 137 KiB |
After Width: | Height: | Size: 332 KiB |
BIN
tutorials/keybrd_4c_split_keyboard_with_IOE/back.JPG
Normal file
After Width: | Height: | Size: 121 KiB |
BIN
tutorials/keybrd_4c_split_keyboard_with_IOE/front.JPG
Normal file
After Width: | Height: | Size: 146 KiB |
@ -43,7 +43,7 @@ const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR p
|
||||
/*
|
||||
Normally all strobe pins are on one port, and all the read pins are on the other port.
|
||||
In this example, portB stobes the row while portA reads the colums.
|
||||
Port_MCP23S17 constructor parameters are: deviceAddr, portNum, readPins
|
||||
Port_MCP23S17 constructor parameters are: deviceAddr, portNum, readPins.
|
||||
readPins is a bit pattern, where 0=output, 1=input.
|
||||
In portA, the first two pins are set to input for reading.
|
||||
"<<" (bit shift left) and "|" (OR) are bitwise operators.
|
||||
@ -67,8 +67,7 @@ Code_Sc s_4(KEY_4);
|
||||
/* =================== ROWS ====================
|
||||
Left row names contain the letter 'L', while right row names conatain the letter 'R'.
|
||||
|
||||
The first parameteer of a Row constructor specifies the scanner.
|
||||
The second parameter of the Row constructor specifies the Row's strobePin.
|
||||
Row constructor parameters are: scanner, strobePin, ptrsKeys[], keyCount.
|
||||
strobePin has one of two formats:
|
||||
* if refScanner a Scanner_uC, then strobePin is an Arduino pin number connected to this row
|
||||
* otherwise strobePin is a bit pattern, 1 indicating an IC pin connected to the row
|
||||
|
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 182 KiB |
@ -39,28 +39,28 @@ In this example, the LED_uC objects are named after the states they indicate.
|
||||
*/
|
||||
LED_uC LED_normal(16);
|
||||
LED_uC LED_fn(17);
|
||||
LED_uC LED_CapsLck(21);
|
||||
LED_uC LED_capsLck(21);
|
||||
|
||||
// =================== CODES ===================
|
||||
/* ---------------- LAYER CODE -----------------
|
||||
LayerState_LED is similar to LayerState, introduced in keybrd_3a_multi-layerHold.ino, but with LEDs.
|
||||
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 };
|
||||
enum layerIds { NORMAL, FN };
|
||||
|
||||
LEDInterface* prtsLayerLEDs[] = { &LED_normal, &LED_fn }; //array index matches enum layerIds
|
||||
LEDInterface* prtsLayerLEDs[] = { &LED_normal, &LED_fn }; //enum layerIds align with array index
|
||||
LayerState_LED layerState(prtsLayerLEDs);
|
||||
|
||||
Code_LayerHold l_fn(FN, layerState);
|
||||
|
||||
/* ---------------- SCAN CODES -----------------
|
||||
When a Code_LEDLock object is pressed, it sends its scancode and updates the its LED.
|
||||
Scancodes can be one of KEY_CAPS_LOCK, KEY_SCROLL_LOCK, or KEY_NUM_LOCK.
|
||||
For example, when o_capsLock is pressed, it sends KEY_CAPS_LOCK scancode and updates LED_CapsLck.
|
||||
Scancodes can be one of: KEY_CAPS_LOCK, KEY_SCROLL_LOCK, or KEY_NUM_LOCK.
|
||||
For example, when o_capsLock is pressed, it sends KEY_CAPS_LOCK scancode and updates LED_capsLck.
|
||||
*/
|
||||
Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_CapsLck);
|
||||
Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_capsLck);
|
||||
|
||||
Code_Sc s_a(KEY_A);
|
||||
Code_Sc s_x(KEY_X);
|
||||
|
BIN
tutorials/keybrd_5b_LED_on_IOE/LEDs.JPG
Normal file
After Width: | Height: | Size: 334 KiB |
BIN
tutorials/keybrd_5b_LED_on_IOE/back.JPG
Normal file
After Width: | Height: | Size: 124 KiB |
BIN
tutorials/keybrd_5b_LED_on_IOE/front.JPG
Normal file
After Width: | Height: | Size: 146 KiB |
@ -2,8 +2,8 @@
|
||||
|
||||
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
|
||||
runs on a two-matrix breadboard keyboard
|
||||
modified keybrd_4c_split_keyboard_with_IOE.ino by adding LED_capsLck
|
||||
|
||||
This layout table shows left and right matrices:
|
||||
|
||||
@ -30,7 +30,7 @@ This layout table shows left and right matrices:
|
||||
//right matrix
|
||||
#include <Port_MCP23S17.h>
|
||||
#include <Scanner_IOE.h>
|
||||
#include <LED_IOE.h>
|
||||
#include <LED_Port.h>
|
||||
|
||||
// ============ SPEED CONFIGURATION ============
|
||||
ScanDelay scanDelay(9000);
|
||||
@ -43,7 +43,7 @@ const uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
|
||||
Scanner_uC scanner_L(LOW, readPins, readPinCount);
|
||||
|
||||
// ----------------- LEFT LEDs -----------------
|
||||
LED_uC LED_CapsLck(21);
|
||||
LED_uC LED_capsLck(21);
|
||||
|
||||
// --------------- RIGHT SCANNER ---------------
|
||||
const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded
|
||||
@ -52,13 +52,15 @@ Port_MCP23S17 portB(IOE_ADDR, 1, 0); //for strobe and LED
|
||||
|
||||
Scanner_IOE scanner_R(LOW, portB, portA);
|
||||
|
||||
// ---------------- RIGHT LEDs -----------------
|
||||
LED_IOE LED_normal(portA, 1<<5);
|
||||
LED_IOE LED_fn(portB, 1<<4);
|
||||
/* ---------------- RIGHT LEDs -----------------
|
||||
The LED_Port constructor parameters are a port and pin number that is connected to an LED.
|
||||
*/
|
||||
LED_Port LED_normal(portA, 1<<5);
|
||||
LED_Port LED_fn(portB, 1<<4);
|
||||
|
||||
// =================== CODES ===================
|
||||
// ---------------- LAYER CODE -----------------
|
||||
enum layers { NORMAL, FN };
|
||||
enum layerIds { NORMAL, FN };
|
||||
|
||||
LEDInterface* prtsLayerLEDs[] = { &LED_normal, &LED_fn }; //array index matches enum layerIds
|
||||
LayerState_LED layerState(prtsLayerLEDs);
|
||||
@ -82,7 +84,7 @@ Code_Sc s_minus(KEY_MINUS);
|
||||
Code_Sc s_equal(KEY_EQUAL);
|
||||
Code_Sc s_slash(KEY_SLASH);
|
||||
|
||||
Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_CapsLck);
|
||||
Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_capsLck);
|
||||
|
||||
// =================== KEYS ====================
|
||||
//row0
|
||||
@ -126,12 +128,15 @@ Key* ptrsKeys_R1[] = { &k_12, &k_13 };
|
||||
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 ####################
|
||||
/* ################### MAIN ####################
|
||||
LayerState_LED::begin() is called after Scanner_IOE::begin()
|
||||
so that scanner's ports can turn on LayerState_LED's default-layer LED.
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
Keyboard.begin();
|
||||
scanner_R.begin();
|
||||
layerState.begin();//must be after scanner begin for IOE ?? todo
|
||||
layerState.begin(); //call LayerState_LED::begin() after Scanner_IOE::begin()
|
||||
}
|
||||
|
||||
void loop()
|
||||
|
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
@ -1,51 +1,51 @@
|
||||
/* keybrd_6_active_high.ino
|
||||
|
||||
This sketch:
|
||||
is the tutorial 1 sketch with STROBE_ON/STROBE_OFF values swapped
|
||||
is active high 1-layer keyboard
|
||||
runs on the first two rows and columns of a active-high breadboard keyboard
|
||||
is keybrd_2_single-layer.ino modified to be active high
|
||||
requires two external pull-down resistors on the first two columns
|
||||
|
||||
| Layout | **0** | **1** |
|
||||
|:------:|-------|-------|
|
||||
| **0** | 1 | a |
|
||||
| **1** | b | c |
|
||||
| **0** | 1 | 2 |
|
||||
| **1** | a | b |
|
||||
*/
|
||||
|
||||
// ################## GLOBAL ###################
|
||||
// ================= INCLUDES ==================
|
||||
#include <ScanDelay.h>
|
||||
#include <Code_Sc.h>
|
||||
#include <Row_uC.h>
|
||||
#include <Row.h>
|
||||
#include <Scanner_uC.h>
|
||||
#include <ScanDelay.h>
|
||||
|
||||
// ============ SPEED CONFIGURATION ============
|
||||
ScanDelay scanDelay(9000);
|
||||
|
||||
/* ================ ACTIVE STATE ===============
|
||||
STROBE_ON and STROBE_OFF define the logic levels for the strobe.
|
||||
"Active high" means that if a switch is pressed (active), the read pin is high.
|
||||
To make this sketch active high, STROBE_ON should be HIGH.
|
||||
|
||||
Compared active low, STROBE_ON/STROBE_OFF values swapped.
|
||||
*/
|
||||
const bool Scanner_uC::STROBE_ON = HIGH; //set matrix for active high
|
||||
const bool Scanner_uC::STROBE_OFF = LOW;
|
||||
|
||||
// ================= 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 constructor parameters are: strobeOn, readPins[], readPinCount.
|
||||
strobeOn defines the logic level for strobes, HIGH or LOW.
|
||||
"Active high" means that if a switch is pressed (active), the read pin is high.
|
||||
*/
|
||||
Scanner_uC scanner(HIGH, readPins, readPinCount);
|
||||
|
||||
// =================== CODES ===================
|
||||
Code_Sc s_1(KEY_1);
|
||||
Code_Sc s_a(KEY_A);
|
||||
Code_Sc s_b(KEY_B);
|
||||
Code_Sc s_c(KEY_C);
|
||||
|
||||
Code_Sc s_1(KEY_1);
|
||||
Code_Sc s_2(KEY_2);
|
||||
|
||||
// =================== ROWS ====================
|
||||
Key* ptrsKeys_0[] = { &s_1, &s_a };
|
||||
Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0);
|
||||
Key* ptrsKeys_0[] = { &s_1, &s_2 };
|
||||
uint8_t keyCount_0 = sizeof(ptrsKeys_0)/sizeof(*ptrsKeys_0);
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
||||
Key* ptrsKeys_1[] = { &s_b, &s_c };
|
||||
Row_uC row_1(1, readPins, READ_PIN_COUNT, ptrsKeys_1);
|
||||
Key* ptrsKeys_1[] = { &s_a, &s_b };
|
||||
uint8_t keyCount_1 = sizeof(ptrsKeys_1)/sizeof(*ptrsKeys_1);
|
||||
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
|
||||
|
||||
// ################### MAIN ####################
|
||||
void setup()
|
||||
|
@ -4,8 +4,8 @@ The first two tutorials are intended to be read in sequence:
|
||||
* Tutorial 1 builds a breadboard keyboard and covers basic keyboard-hardware knowledge.
|
||||
* Tutorial 2 covers basic keybrd-sketch knowledge needed to understand the remaining tutorials.
|
||||
|
||||
Tutorials from 3 up can be read in any order.
|
||||
Tutorials 2 through 7 use the keyboard breadboard that was built in tutorial 1.
|
||||
Tutorials from 3 up can be read in any order.
|
||||
Tutorials from 8 up are advance topics about the keybrd library.
|
||||
|
||||
The tutorials assume the reader:
|
||||
|
@ -18,7 +18,7 @@ Compared to PCBs, breadboard keyboards make learning faster because:
|
||||
|
||||
Breadboard keyboards are useful for:
|
||||
* learning keyboard electronics - microcontroller, key matrix, diode, shift registers, I/O expander
|
||||
* learning the firmware development workflow
|
||||
* learning the keyboard-development workflow
|
||||
* prototyping circuits before making a PCB
|
||||
|
||||
Breadboard keyboard starter kit
|
||||
@ -62,7 +62,7 @@ Building a basic breadboard keyboard
|
||||
------------------------------------
|
||||
The basic breadboard keyboard has 4 switches.
|
||||
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/basic_breadboard_keyboard_front.JPG "basic breadboard keyboard")
|
||||
|
||||
A Teensy LC microcontroller is on the left.
|
||||
A key matrix with 4 switches is to the right.
|
||||
@ -75,7 +75,7 @@ Two bus strips are used as matrix rows.
|
||||
A jumper connects the top row to the microcontroller.
|
||||
A short wire connects the bottom row to the microcontroller.
|
||||
|
||||
Switch-diode pairs, in series, connect rows to columns.
|
||||
A switches and diodes connect rows to columns.
|
||||
|
||||
Tutorials 2 and 3 use the same basic breadboard keyboard pictured above.
|
||||
Tutorials 4, 5, and 6 add more components to the basic breadboard keyboard.
|
||||
@ -97,11 +97,11 @@ Breadboard keyboard assembly instructions:
|
||||
* Teensy LC is on the left
|
||||
* switch leads are oriented to connect diodes to columns (pictured below)
|
||||
* diode cut offs connect terminal strips into columns
|
||||
* diodes connect switches to rows; orient diodes with cathode (banded end) towards the row (blue bus)
|
||||
* diodes connect switches to rows; orient diodes with cathode (banded end) towards the rows (blue bus)
|
||||
|
||||
![switch orientation](keybrd_1_breadboard/switch_orientation.JPG "switch orientation")
|
||||
|
||||
![basic breadboard keyboard overhead](keybrd_1_breadboard/breadboard_keyboard_2x2_overhead.JPG "basic breadboard keyboard overhead")
|
||||
![basic breadboard keyboard overhead](keybrd_1_breadboard/basic_breadboard_keyboard_overhead.JPG "basic breadboard keyboard overhead")
|
||||
|
||||
3. Insert jumper wires to connect Arduino pins to the matrix rows and columns.
|
||||
* [Teensy LC pinout diagram](https://www.pjrc.com/teensy/card6a_rev2.png).
|
||||
@ -140,7 +140,8 @@ The breadboard keyboards in this series of tutorials do it the other way:
|
||||
|
||||
The keybrd library uses the word "strobe", which means powering one row for a very short time.
|
||||
Strobe pins are output pins connected to rows.
|
||||
One row at a time is strobed for the purpose of reading input pins.
|
||||
One row at a time is strobed.
|
||||
While a row is strobed, input pins connected to the columns sense which buttons are pressed.
|
||||
|
||||
Exercises
|
||||
---------
|
||||
|
@ -6,7 +6,7 @@ The sketch will run on the basic breadboard keyboard described in [tutorial_1_br
|
||||
|
||||
After reading the sketch you will be able to modify it to suite your own single-layer keyboard design.
|
||||
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/basic_breadboard_keyboard_front.JPG "basic breadboard keyboard")
|
||||
|
||||
Exercises
|
||||
---------
|
||||
|
@ -5,7 +5,7 @@ When you finish this tutorial you will be able to be able to modify a multi-laye
|
||||
Multi-layer nomenclature
|
||||
------------------------
|
||||
**[layers](http://deskthority.net/wiki/Layer)** - are key bindings provided by the keyboard firmware. For example,
|
||||
* The classic [IBM PC keyboard](http://en.wikipedia.org/wiki/IBM_PC_keyboard) has one layer.
|
||||
* The classic [IBM Model M keyboard](http://en.wikipedia.org/wiki/IBM_PC_keyboard) has one layer.
|
||||
* Many compact keyboards have an additional [Fn layer](http://en.wikipedia.org/wiki/Fn_key).
|
||||
* The [Neo layout](http://neo-layout.org/index_en.html) has 6 layers.
|
||||
|
||||
@ -13,30 +13,30 @@ Multi-layer nomenclature
|
||||
|
||||
**active layer** - is the layer currently used by the keyboard.
|
||||
|
||||
**default layer** - is the active layer when the keyboard starts up (in class LayerState, default layerId=0).
|
||||
**default layer** - is the active layer when the keyboard starts up.
|
||||
|
||||
**layer scheme** - is a system for changing the active layer while typing (a single-layer scheme does not change layers).
|
||||
|
||||
Code classes
|
||||
------------
|
||||
Code objects only have one scancode or code.
|
||||
Example single-layer Code classes include:
|
||||
* Code_Sc (used in keybrd_2_single-layer.ino)
|
||||
Code objects only have one scancode or one layer code.
|
||||
Example Code classes include:
|
||||
* Code_Sc
|
||||
* Code_ScS
|
||||
* Code_ScNS
|
||||
* Code_Shift
|
||||
* Code_LayerHold
|
||||
* Code_LayerLock
|
||||
|
||||
Single-layer keybrd sketches have one Code object per key.
|
||||
Multi-layer keybrd sketches have multiple Code objects per key, one code for each layer.
|
||||
Single-layer keys contain one Code object.
|
||||
Multi-layer keys contain multiple Code objects, one code for each layer.
|
||||
|
||||
A simple multi-layer keybrd sketch
|
||||
----------------------------------
|
||||
The [keybrd_3a_multi-layerHold.ino](keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino) sketch is for a simple two-layer keyboard.
|
||||
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
||||
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/basic_breadboard_keyboard_front.JPG "basic breadboard keyboard")
|
||||
|
||||
The sketch annotations explain how multi-layer keyboards work.
|
||||
The sketch uses three layer-scheme classes:
|
||||
@ -56,7 +56,7 @@ When a Code_Layer object is pressed, it tells LayerState to update the active la
|
||||
```
|
||||
class Code_Layer
|
||||
{
|
||||
int layerId;
|
||||
const int layerId;
|
||||
LayerState& refLayerState;
|
||||
press() { refLayerState.setActiveLayer(layerId); }
|
||||
};
|
||||
@ -73,8 +73,8 @@ class LayerState
|
||||
};
|
||||
```
|
||||
|
||||
**Key_LayeredKeys** objects contain an array of keys, one key for each layer.
|
||||
Key_LayeredKeys objects use layerIds as Key_LayeredKeys indexes.
|
||||
**Key_LayeredKeys** objects contain arrays of keys, one key for each layer.
|
||||
Key_LayeredKeys objects use layerIds as array indexes.
|
||||
When a Key_LayeredKeys object is pressed, it gets the active layerId from LayerState, and sends the corresponding key.
|
||||
```
|
||||
class Key_LayeredKeys
|
||||
@ -123,6 +123,58 @@ Key_Layered classes include:
|
||||
* Key_LayeredScSc (covered in next tutorial)
|
||||
* Key_LayeredCodeSc
|
||||
|
||||
The association between Codes, Keys, and Rows
|
||||
---------------------------------------------
|
||||
Codes, Keys, and Rows are associated by class compositions:
|
||||
|
||||
```
|
||||
Each Code object contains one scancode or one layercode.
|
||||
|
||||
Each Key contains either
|
||||
* one Code object (single-layer)
|
||||
* multiple Code objects (multi-layer)
|
||||
* Key object (key nested in key)
|
||||
|
||||
Each Row contains Key objects.
|
||||
```
|
||||
|
||||
You may have been wondering why Code pointers are in Key pointers arrays.
|
||||
You don't need to know the reasons to write a sketch.
|
||||
For the curious, two reasons are explained below.
|
||||
|
||||
1) Single-layer keys is the first reason you see Code pointers in a Key pointers array.
|
||||
Rows contain keys. The keys can be Single-layer or Multi-layer.
|
||||
Wrapping a code in a single-layer key before placing it a row is tedious.
|
||||
It is more convenient to place a code directly in a row.
|
||||
Codes are a kind of Key (polymorphism), so that rows can contain codes and keys.
|
||||
|
||||
From keybrd_3a_multi-layerHold.ino:
|
||||
|
||||
```
|
||||
Key* const ptrsKeys_0[] = { &k_00, &k_01 };
|
||||
Row row_0(scanner, 0, ptrsKeys_0, keyCount_0);
|
||||
|
||||
Key* const ptrsKeys_1[] = { &l_fn, &s_shift };
|
||||
Row row_1(scanner, 1, ptrsKeys_1, keyCount_1);
|
||||
```
|
||||
row0's ptrsKeys_0[] array contains pointers to Keys.
|
||||
row1's ptrsKeys_1[] array contains pointers to Codes.
|
||||
|
||||
2) Sublayers (nested keys) is the second reason you see Code pointers in a Key pointers array.
|
||||
Layered keys usually contain just codes. When nesting keys, layered keys contain keys.
|
||||
Codes are a kind of Key (polymorphism), so that layered keys can contain both codes and keys.
|
||||
|
||||
From keybrd_3d_sublayerNested.ino:
|
||||
|
||||
```
|
||||
Key* const ptrsKeys_sub00[] = { &s_minus, &s_1 };
|
||||
Key_LayeredKeys1 k_sub00(ptrsKeys_sub00);
|
||||
|
||||
Key* const ptrsKeys_00[] = { &s_a, &k_sub00 };
|
||||
Key_LayeredKeys k_00(ptrsKeys_00);
|
||||
```
|
||||
k_00's ptrsKeys_00[] array contains pointers to code s_a and key k_sub00.
|
||||
|
||||
Exercises
|
||||
---------
|
||||
1) Compile and run [keybrd_3a_multi-layerHold.ino](keybrd_3a_multi-layerHold/keybrd_3a_multi-layerHold.ino)
|
||||
|
@ -1,26 +1,20 @@
|
||||
Tutorial 3cde - sublayer keyboard
|
||||
=================================
|
||||
This tutorial assumes the reader understands the previous tutorial.
|
||||
This tutorial assumes you have read tutorial_3ab_multi-layer_keyboard.
|
||||
|
||||
When you finish this tutorial you will be able to be able to modify a multi-layer keybrd sketch to write your very own multi-layer keyboard firmware.
|
||||
When you finish this tutorial you will be able to be able to modify a multi-layer keybrd sketch.
|
||||
|
||||
Sublayer nomenclature
|
||||
---------------------
|
||||
These definitions are specific to the keybrd library.
|
||||
|
||||
**layer group** - is a group of layers that occupy the same keys.
|
||||
**layer group** - is a group of layers that occupy a group of keys.
|
||||
|
||||
**primary layer group** - is a layer group containing the default layer.
|
||||
**layer subgroup** - is a layer group nested in a layer of another layer group.
|
||||
|
||||
**sublayer group** - is a layer group nested in a layer of another layer group.
|
||||
|
||||
**primary layer** - is a layer within the primary layer group.
|
||||
|
||||
**sublayer** - is a layer within the sublayer group.
|
||||
|
||||
Layer scheme with a sublayer
|
||||
----------------------------
|
||||
This tutorial has 3 example sketches, all using this layout:
|
||||
Layout with a sublayer
|
||||
----------------------
|
||||
The next three example sketches all use this layout:
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
@ -28,92 +22,134 @@ This tutorial has 3 example sketches, all using this layout:
|
||||
| **1** | Alpha | Sym | Enter |
|
||||
|
||||
Each cell in the table's body represents a key.
|
||||
Bottom row keys have one layer.
|
||||
Top row keys have 2 or 3 layers.
|
||||
Each element in a cell represents a scancode or layer code.
|
||||
|
||||
Pressing the "Alpha" layer key locks the Alpha layer.
|
||||
Pressing the Alpha-layer key locks the Alpha layer.
|
||||
Letters 'a' 'b' 'c' are on the Alpha layer.
|
||||
|
||||
Pressing the "Sym" layer key locks the Sym layer.
|
||||
Pressing the Sym-layer key locks the Sym layer.
|
||||
Symbols '-' '=' and "Num" layer key are on the Sym layer.
|
||||
|
||||
If the keyboard is locked on the Sym layer, holding Num down makes Num the active layer.
|
||||
Releasing the Num key restores the Sym layer.
|
||||
If the keyboard is locked on the Sym layer, holding Num down makes it the active layer.
|
||||
Number '1' is on the Num sublayer.
|
||||
Releasing the Num key makes the locked layer active.
|
||||
|
||||
todo [pic of 3 col bb kb]
|
||||
Example sketches 3c, 3d, and 3e implement the above layout.
|
||||
Each sketch uses a different layer scheme.
|
||||
|
||||
Three example sketches implement the above layout using differently layer schemes.
|
||||
Which layer scheme is best depends on the layout.
|
||||
The sketches will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md) with a 3rd column added to pin 16:
|
||||
|
||||
Sketch 3c - one layer group
|
||||
---------------------------
|
||||
Refer to keybrd_3c_sublayerNull.ino
|
||||
![3-column breadboard keyboard](keybrd_3c_sublayerNull/front.JPG "3-column breadboard keyboard")
|
||||
|
||||
The top row has one layer group with 3 layers.
|
||||
Num layer is unused to the right of 1.
|
||||
Duplicate codes and null codes fill the unused space.
|
||||
It's a bit of a kludge, but can be simple if there is little unused space.
|
||||
|
||||
layerState contains the active layer for the layer group.
|
||||
|
||||
Sketch 3d - two layer groups
|
||||
Sketch 3c - two layer groups
|
||||
----------------------------
|
||||
Refer to keybrd_3d_sublayerNestedKeys.ino
|
||||
This layer scheme has two layer groups:
|
||||
|
||||
The top row has two layer groups.
|
||||
* NORMAL+SYM is the primary layer group. It covers the top-row keys.
|
||||
* SYM1+NUM1 is a sublayer group nested in the SYM layer. The subgroup covers the top-left key.
|
||||
| group_1 | **0** | **1** | **2** |
|
||||
|:-------:|:-----:|:-----:|:----------:|
|
||||
| **0** | a - 1 | b = = | c Num null | layer group with three layers: Alpha Sym Num
|
||||
| **1** | | | |
|
||||
|
||||
Two layer groups model the logic of the layout accurately
|
||||
(the previous example was a kluge because it only had one layer group).
|
||||
| group_0 | **0** | **1** | **2** |
|
||||
|:-------:|:-----:|:-----:|:-----:|
|
||||
| **0** | | | |
|
||||
| **1** | Alpha | Sym | Enter | layer group with a one layer
|
||||
|
||||
There should be one LayerState object for each layer group. In this example:
|
||||
* layerState contains the active layer for the primary layer group.
|
||||
* sublayerState contains the active layer for the sublayer group.
|
||||
group_1 covers the entire top row, therefore Num layer covers the entire top row.
|
||||
Meanwhile, the layout's Num layer only covers the first key.
|
||||
The unused num-layer space is filled with duplicate and null codes.
|
||||
A little filler is the simplest way in some situations.
|
||||
|
||||
The layer scheme is implemented in keybrd_3c_sublayerNull.ino
|
||||
|
||||
The null is not really needed because null is on the same key as Num layer code.
|
||||
And Num is the only layer code that can activate the Num layer.
|
||||
The null key would be needed if another Num key where added to the layout.
|
||||
|
||||
The next example sketch has three layer groups that fit the layout perfectly.
|
||||
|
||||
Sketch 3d - three layer groups
|
||||
------------------------------
|
||||
This layer scheme has three layer groups:
|
||||
|
||||
| group_2 | **0** | **1** | **2** |
|
||||
|:-------:|:-----:|:-----:|:-----:|
|
||||
| **0** | - 1 | | | layer subgroup with two layers: Sym Num
|
||||
| **1** | | | |
|
||||
|
||||
| group_1 | **0** | **1** | **2** |
|
||||
|:-------:|:---------:|:-----:|:-----:|
|
||||
| **0** | a group_2 | b = | c Num | layer group with two layers: Alpha Sym
|
||||
| **1** | | | |
|
||||
|
||||
| group_0 | **0** | **1** | **2** |
|
||||
|:-------:|:-----:|:-----:|:-----:|
|
||||
| **0** | | | |
|
||||
| **1** | Alpha | Sym | Enter | layer group with a one layer
|
||||
|
||||
The three layer groups model the logic of the layout accurately, without resorting to fillers.
|
||||
The layer scheme is implemented in keybrd_3d_sublayerNestedKeys.ino.
|
||||
|
||||
Sketch 3e - specialized layered keys
|
||||
------------------------------------
|
||||
Refer to keybrd_3e_sublayerNestedScSc.ino
|
||||
|
||||
Key_LayeredKeys constructor takes any number of code or key arguments.
|
||||
Key_LayeredScSc is more specialized. It's constructor takes exactly two scancode arguments.
|
||||
A Key_LayeredScSc object could be instantiated with Key_LayeredKeysArray.
|
||||
But using Key_LayeredScSc has advantages when a large sublayer group has two layers:
|
||||
* no array is created for the two scancodes
|
||||
* less clutter in sketch
|
||||
* save SRAM
|
||||
Key_LayeredScSc has advantages when a large layer group has two layers:
|
||||
* no array is created for the two scancodes, which means less clutter in the sketch
|
||||
* uses less SRAM
|
||||
|
||||
The layer scheme is implemented in keybrd_3e_sublayerNestedScSc.ino.
|
||||
It is similar to the previous sketch, but Key_LayeredKeysArray1 is replaced with Key_LayeredScSc.
|
||||
|
||||
Key_Layered classes include:
|
||||
* Key_LayeredKeys (any number of codes or keys)
|
||||
* Key_LayeredScSc (specialized for two scancodes)
|
||||
* Key_LayeredCodeSc (specialized for one code and one scancode)
|
||||
|
||||
Sublayer layer-key placement
|
||||
Subgroup layer-key placement
|
||||
----------------------------
|
||||
A layer key to a sublayer can be place in one of two places:
|
||||
* on layer the sublayer group is nested in (layout above has Num-layer key on Sym layer)
|
||||
* on a single-layer key (layout below has Num-layer key on bottom row) (some people would not call this arrangement a sublayer)
|
||||
A subgroup's layer key(s) can be placed in one of two ways.
|
||||
|
||||
1) A subgroup and it's layer key(s) on the same layer.
|
||||
|
||||
This layout has a '1' in the Num layer and the Num layer key on the Sym layer:
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Num |
|
||||
| **1** | Alpha | Sym | Enter |
|
||||
|
||||
This arrangement presents the Num layer as a "sublayer".
|
||||
|
||||
2) A subgroup with it's layer key(s) on single-layer key(s).
|
||||
|
||||
This layout has a '1' in the Num layer and the Num layer key on the bottom row:
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Ent |
|
||||
| **1** | Alpha | Sym | Num |
|
||||
|
||||
This arrangement presents the Num layer as just another layer that happens to cover fewer keys than Alpha and Sym layers.
|
||||
The top row is easily implemented in one layer group with duplicate keys filling the Num layer:
|
||||
|
||||
| group_1 | **0** | **1** | **2** |
|
||||
|:-------:|:-----:|:------:|:---------:|
|
||||
| **0** | a - 1 | b = = | c Ent Ent | layer group with three layers: Alpha Sym Num
|
||||
| **1** | | | |
|
||||
|
||||
Complex layerschemes
|
||||
--------------------
|
||||
The basic LayerState class used in the tutorials is sufficient for implementing many layer schemes.
|
||||
More complicated layer schemes would need custom LayerState classes, and possibly custom Code_Layer and Key_Layered classes as well.
|
||||
Any layer scheme can be implemented with the right custom layer classes.
|
||||
|
||||
[keybrd_DH](https://github.com/wolfv6/keybrd_DH) is an example of a complex layer scheme (it emulates the DataHand keyboard).
|
||||
The keybrd_DH sketch is a showcase of the keybrd library's capability.
|
||||
It's the most complex layer scheme I know of.
|
||||
Don't let the complexity scare you; most layer schemes are much simpler.
|
||||
[keybrd_DH](https://github.com/wolfv6/keybrd_DH) is an example of a complex layer scheme.
|
||||
It emulates the DataHand keyboard, which has the most complex layout I know of.
|
||||
Most layer schemes are much simpler.
|
||||
|
||||
Layer-scheme classes used by keybrd_DH are listed below.
|
||||
The layer scheme classes are organized into three categories, as is "Layer-scheme classes" in the previous tutorial.
|
||||
Most of the layer-scheme classes are custom classes, which reside in the keybrd_DH library.
|
||||
Most of the layer-scheme classes are custom classes which reside in the keybrd_DH library.
|
||||
|
||||
DH Code_Layer classes include:
|
||||
* Code_LayerLock
|
||||
@ -135,12 +171,22 @@ DH Key_Layered classes include:
|
||||
* Key_LayeredNumber
|
||||
* Key_LayeredNumber_00
|
||||
|
||||
|
||||
Exercises
|
||||
---------
|
||||
Modify keybrd_3e_sublayerNestedScSc.ino by adding the number '2' to the Num layer group.
|
||||
The layout is below.
|
||||
1) Modify keybrd_3e_sublayerNestedScSc.ino to match the following layout
|
||||
(add the number '2' to the Num layer):
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = 2 | c Num |
|
||||
| **1** | Alpha | Sym | Enter |
|
||||
|
||||
2) Modify keybrd_3c_sublayerNull.ino to match the following layout
|
||||
(this was described above in "Subgroup layer-key placement"):
|
||||
|
||||
| Layout | **0** | **1** | **2** |
|
||||
|:------:|:-----:|:-----:|:-----:|
|
||||
| **0** | a - 1 | b = | c Ent |
|
||||
| **1** | Alpha | Sym | Num |
|
||||
|
||||
|
@ -11,9 +11,9 @@ Two keybrd classes use AutoShift:
|
||||
|
||||
The [keybrd_3f_autoShift.ino](keybrd_3f_autoShift/keybrd_3f_autoShift.ino) sketch explains the AutoShift feature.
|
||||
It will run on the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
||||
After reading the sketch you too will be able to automatically shifted characters.
|
||||
After reading the sketch you too will be able to automatically shift characters.
|
||||
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/breadboard_keyboard_2x2.JPG "basic breadboard keyboard")
|
||||
![basic breadboard keyboard](keybrd_1_breadboard/basic_breadboard_keyboard_front.JPG "basic breadboard keyboard")
|
||||
|
||||
Exercises
|
||||
---------
|
||||
|
@ -10,7 +10,7 @@ The preferred connection method depends on the number of keys, number of availab
|
||||
## Split keyboard connections table
|
||||
|
||||
| connection type | controller pins | wire count | max keys |
|
||||
|:----------------------:|:---------------:|:----------:|:--------:|
|
||||
|------------------------|:---------------:|:----------:|:--------:|
|
||||
| just cable | 3 | 6 | 9 |
|
||||
| just cable | 3 | 7 | 12 |
|
||||
| just cable | 4 | 8 | 16 |
|
||||
@ -24,16 +24,18 @@ The preferred connection method depends on the number of keys, number of availab
|
||||
|
||||
Fewer wires makes a cable more flexible.
|
||||
A flexibility cable makes it easy to position the keyboard and route the cable.
|
||||
But if there are enough pins on the controller, just using a cable with more wires is simpler and costs less.
|
||||
But if there are enough pins on the controller, using just a cable with more wires is simpler and costs less.
|
||||
|
||||
I/O Expanders can power LEDs, while PISO shift registers can not.
|
||||
|
||||
I2C is a little slow if the I/O expander is scanning more than 4 rows.
|
||||
The keybrd_DH (DodoHand) sketch polls 5 rows over I2C at 7.5ms per keyboard scan.
|
||||
Which is acceptable, but faster would be nicer.
|
||||
|
||||
## Cables table
|
||||
|
||||
| connector name | wire count |
|
||||
|:-----------------------------------------------------:|:----------:|
|
||||
|-------------------------------------------------------|:----------:|
|
||||
| TRRS | 4 |
|
||||
| 6-pin mini-DIN connector (PS/2) | 4 |
|
||||
| USB 2 | 4 |
|
||||
@ -52,7 +54,7 @@ The 8-wire "GearIT Cat 6 Ethernet Flat Patch Cable 7 Feet" is very flexible.
|
||||
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.
|
||||
For prototyping on perfboards, consider a 0.1" header.
|
||||
|
||||
<br>
|
||||
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">keybrd tutorial</span> by <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd" property="cc:attributionName" rel="cc:attributionURL">Wolfram Volpi</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.<br />Permissions beyond the scope of this license may be available at <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd/issues/new" rel="cc:morePermissions">https://github.com/wolfv6/keybrd/issues/new</a>.
|
||||
|
@ -4,35 +4,34 @@ When you finish this tutorial you will be able to be able to modify a split keyb
|
||||
|
||||
Overview of split keyboard with shift registers
|
||||
------------------------------------------------
|
||||
Only the right matrix is shown. The left matrix is not needed and was omitted to reduce clutter.
|
||||
The breadboard in the following picture models a split keyboard.
|
||||
The green rectangle on the left is a Teensy LC micro controller.
|
||||
The black rectangles in the middle are two SN74HC165N shift registers daisy chained together.
|
||||
The micro controller and shift registers are connected via 5 jumper wires.
|
||||
|
||||
Only the right matrix is shown. The left matrix is not needed for this demonstration and was omitted to reduce clutter.
|
||||
|
||||
The right-matrix layout has 2 rows and 7 columns.
|
||||
Electronically, the matrix only has one row.
|
||||
Electronically, there is only one row of keys.
|
||||
Diodes are not needed because there is only one row.
|
||||
|
||||
The two black rectangles are SN74HC165N shift registers daisy chained together.
|
||||
Shift register details are in the SN74HC165N datasheet.
|
||||
|
||||
![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/shift_reg_front.JPG )
|
||||
![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/front.JPG "breadboard keyboard with shift_registers")
|
||||
|
||||
Building a split breadboard keyboard with shift registers
|
||||
---------------------------------------------------------
|
||||
Add components to the breadboard as shown in the picture.
|
||||
Refer to the SN74HC165N datasheet to locate its pins.
|
||||
|
||||
Each shift register has a small notch on one end to identify pin 1.
|
||||
In the picture, pin 1s are on the left end, towards the controller.
|
||||
In the picture, SN74HC165N pin 1s are on the left end, towards the controller.
|
||||
Shift registers are chained together by colored wires that lay flat on the breadboard.
|
||||
|
||||
Each shift register has 8 parallel input pins, 4 on each side.
|
||||
There are 14 keys, so 2 of the input pins are unused.
|
||||
Used input pins are connected to 10k pull-down resistor which are grounded (blue bus).
|
||||
Unused input pins are grounded (blue bus).
|
||||
|
||||
A decoupling capacitor between the power and ground wires prevents power disturbance.
|
||||
14 input pins and their keys are connected to 10k pull-down resistor which are grounded (blue bus).
|
||||
2 input pins are not used, they are grounded (blue bus).
|
||||
|
||||
Switches are connected to power (red bus) and shift register input pins (jumpers).
|
||||
|
||||
I apologize for not providing a schematic. This table should help you figure out the pictures:
|
||||
This table lists what gets connected to the 74HC165 pins:
|
||||
|
||||
```
|
||||
74HC165 left (lower half of breadboard)
|
||||
@ -59,6 +58,14 @@ SER 10 serial input blue wire to next QH
|
||||
|
||||
```
|
||||
|
||||
![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/overhead.JPG )
|
||||
|
||||
![breadboard keyboard with shift_registers](keybrd_4b_split_keyboard_with_shift_registers/back.JPG )
|
||||
|
||||
A decoupling capacitor between the power and ground wires suppresses noise.
|
||||
|
||||
I apologize for not providing a schematic.
|
||||
|
||||
Sketch for split keyboard with shift registers
|
||||
----------------------------------------------
|
||||
[keybrd_4b_split_keyboard_with_shift_registers.ino](keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino) is a simple sketch with two shift registers.
|
||||
@ -68,16 +75,5 @@ Exercises
|
||||
---------
|
||||
1. Guess what happens if an unused input pin is not grounded? Try it.
|
||||
|
||||
2. Add a left matrix to the controller.
|
||||
There is room between Teensy and the shift registers for a 1-column matrix.
|
||||
The bus strips are occupied by the right keys, so use terminal strips instead.
|
||||
Other wise it is similar to the 2-column matrix in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md).
|
||||
|
||||
The sketch already has code for both left and right matrix.
|
||||
Notice that the left matrix is active low, while the right matrix is active high.
|
||||
|
||||
<br>
|
||||
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">keybrd tutorial</span> by <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd" property="cc:attributionName" rel="cc:attributionURL">Wolfram Volpi</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.<br />Permissions beyond the scope of this license may be available at <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd/issues/new" rel="cc:morePermissions">https://github.com/wolfv6/keybrd/issues/new</a>.
|
||||
|
||||
## parts for breadboard_keyboard_supplies.ods
|
||||
|
||||
|
@ -1,22 +1,39 @@
|
||||
keybrd Tutorial 4 - split keyboard with I/O Expander
|
||||
keybrd Tutorial 4c - split keyboard with I/O Expander
|
||||
====================================================
|
||||
When you finish this tutorial you will be able to be able to modify a 2-matrix keybrd sketch to suite your own split keyboard design.
|
||||
|
||||
Overview of split keyboard with I/O Expander
|
||||
--------------------------------------------
|
||||
The breadboard in this picture models a split keyboard.
|
||||
![breadboard keyboard with 2 rows and 4 columns of keys](images/breadboard_keyboard_2x5_labeled.jpg "2x5 breadboard keyboard")
|
||||
The breadboard in the following picture models a split keyboard.
|
||||
The green rectangle on the left is a Teensy LC micro controller.
|
||||
The black rectangle on the right is a MCP23S17 I/O expander.
|
||||
|
||||
The breadboard's four bus strips are used as rows.
|
||||
The two ICs communicates via SPI protocol, where Teensy LC is the master and MCP23S17 is slave.
|
||||
The two ICs are connected via six jumper wires.
|
||||
|
||||
The breadboard's four bus strips are used as matrix rows.
|
||||
Two rows (blue buses) are connected to the microcontroller.
|
||||
Two rows (red buses) are connected to the I/O expander.
|
||||
|
||||
The I/O expander is a MCP23S17.
|
||||
It has a small notch on one end, which identifies pin 1.
|
||||
In the picture, pin 1 is on the left end.
|
||||
![breadboard keyboard with IOE](keybrd_4c_split_keyboard_with_IOE/front.JPG "breadboard keyboard with IOE")
|
||||
|
||||
The MCP23S17 communicates via SPI protocol, where Teensy LC is the master, and MCP23S17 is slave.
|
||||
The Teensy LC and MCP23S17 are connected via 6 jumper wires:
|
||||
Building a split keyboard with I/O Expander
|
||||
-------------------------------------------
|
||||
Starting with the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md), add parts as described above.
|
||||
Refer to the MCP23S17 datasheet to locate its pins.
|
||||
|
||||
In the picture, MCP23S17 pin 1 is on the left end, towards the controller.
|
||||
|
||||
The MCP23S17 I/O expander has two ports. Each port has eight pins.
|
||||
Port B is connected to the matrix's rows (red bus).
|
||||
Port A is connected to the matrix's columns (jumpers).
|
||||
|
||||
MCP23S17's device address is configured by hardware pins.
|
||||
All three address pins are grounded.
|
||||
|
||||
The MCP23S17's /RESET pin is connected to VDD.
|
||||
|
||||
This table lists the six wires connecting Teensy LC to MCP23S17:
|
||||
|
||||
|CONNECTION |Teensy LC|MCP23S17|
|
||||
|:------------------:|---------|--------|
|
||||
@ -27,21 +44,7 @@ The Teensy LC and MCP23S17 are connected via 6 jumper wires:
|
||||
|Master In, Slave Out| MISO0 | SO |
|
||||
|Chip Select | CS0 | /CS |
|
||||
|
||||
A decoupling capacitor suppresses high-frequency noise from the power supply.
|
||||
|
||||
MCP23S17's I/O expander address is configured by hardware pins.
|
||||
The MCP23S17 with all address pins grounded has an device address of 0x20.
|
||||
|
||||
The MCP23S17's /RESET pin is connected to VDD.
|
||||
|
||||
The MCP23S17 I/O expander has two ports. Each port has eight pins.
|
||||
Port B is connected to the matrix's rows.
|
||||
Port A is connected to the matrix's columns.
|
||||
|
||||
Building a split keyboard with I/O Expander
|
||||
-------------------------------------------
|
||||
Starting with the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md), add parts as described above.
|
||||
Refer to the MCP23S17 datasheet to locate its pins.
|
||||
A decoupling capacitor between the power and ground wires suppresses noise.
|
||||
|
||||
<!-- todo schematic with IOE power decoupling capacitor
|
||||
This schematic was written by consulting the I/O expander's datasheet and using the ?? tool. -->
|
||||
|
@ -1,7 +1,7 @@
|
||||
Tutorial 5a - indicator LEDs
|
||||
============================
|
||||
Keyboards often have LEDs to indicate CapsLock, NumLock, and other states.
|
||||
It's one of the first things we look at when a keyboard produces unexpected results.
|
||||
It's one of the first things we check when a keyboard produces unexpected results.
|
||||
|
||||
Adding LEDs to the basic breadboard keyboard
|
||||
--------------------------------------------
|
||||
@ -14,12 +14,11 @@ Each LED is in series with a 4.7k Ohm current limiting resistor.
|
||||
LED anodes (the longer lead) are powered by pins 16, 17, and 21.
|
||||
LED cathodes (the shorter lead) are connected to a grounded terminal strip.
|
||||
|
||||
!["LEDs"](keybrd_5_LEDs/LEDs_back.JPG "LEDs")
|
||||
!["back"](keybrd_5a_LED_on_uC/back.JPG "back")
|
||||
|
||||
keybrd sketch with LEDs
|
||||
-----------------------
|
||||
The [keybrd_5a_LED_on_uC.ino](keybrd_5a_LED_on_uC/keybrd_5a_LED_on_uC.ino) sketch will run on the above breadboard keyboard.
|
||||
As usual, the sketch annotations explain the code.
|
||||
|
||||
LED forward voltage
|
||||
-------------------
|
||||
@ -29,23 +28,22 @@ Forward voltage is published in the LED's datasheet.
|
||||
Most blue and green LEDs have about 3.3 forward voltage, which does not reliably illuminate on Teensy LC's 3.3 volts.
|
||||
Most red and yellow LEDs have around 2.2 forward voltage.
|
||||
So use red and yellow LEDs on Teensy LC.
|
||||
Low-current LEDs can go as low as 1.6 forward voltage.
|
||||
Some low-current LEDs have 1.6 forward voltage.
|
||||
|
||||
LED brightness
|
||||
--------------
|
||||
The amount of current (I) going through an LED is directly proportional to how bright it appears.
|
||||
The amount of current going through an LED is directly proportional to how bright it appears.
|
||||
By picking the correct resistor, you have full control over how bright the LED appears.
|
||||
|
||||
Lets see how much visual difference resistance makes.
|
||||
Replace an LED's 4.7k Ohm resistor with a 68 Ohm resistor.
|
||||
|
||||
Less resistance makes the LED brighter.
|
||||
Too little resistance will burn out the LED.
|
||||
The current supplied to an LED should always be limited by a resistor or some other device.
|
||||
|
||||
LED current limiting resistor values
|
||||
------------------------------------
|
||||
This formula calculates the minimum resistance for maximum LED brightness:
|
||||
In the section we will compute the minimum resistor value for maximum LED brightness.
|
||||
|
||||
This formula calculates the minimum resistance:
|
||||
```
|
||||
output-pin Supply Voltage Vs
|
||||
LED Forward Voltage Vf
|
||||
@ -53,10 +51,7 @@ Forward Current If
|
||||
|
||||
From Ohm's Law, minimum current limiting restiance R = (Vs - Vf) / If
|
||||
```
|
||||
|
||||
For Forward Current, use the smaller of:
|
||||
* Current capacity of output pin
|
||||
* Continuous Forward Current of LED
|
||||
Voltages and current capacities are published in datasheets and sometimes pinout diagrams.
|
||||
|
||||
Teensy LC output-pin capacities are:
|
||||
* four 20 mA pins (5, 16, 17, 21)
|
||||
@ -64,17 +59,18 @@ Teensy LC output-pin capacities are:
|
||||
* Teensy LC on-board LED is on pin 13.
|
||||
It has a current-limiting resistor on the board, and does not provide enough power for another LED.
|
||||
|
||||
Voltages and current capacities are published in datasheets and sometimes pinout diagrams.
|
||||
For Teensy LC 20 mA pin and the TT Electronics OVLLx8C7 LED:
|
||||
Continuous Forward Current of TT Electronics OVLLx8C7 red or yellow LED is 30 mA.
|
||||
|
||||
Plug the numbers into Ohm's Law:
|
||||
```
|
||||
output-pin Supply Voltage Vs = 3.3 volts
|
||||
LED Forward Voltage Vf = 2.2 volts
|
||||
|
||||
use the smaller of:
|
||||
max pin Current If = 20 mA
|
||||
max LED Current If = 30 mA
|
||||
For Forward Current, use the smaller of:
|
||||
current capacity of output pin If = 20 mA
|
||||
continuous Forward Current of LED If = 30 mA
|
||||
|
||||
minimum current limiting restiance R = (Vs - Vf) / If = 55 Ohms
|
||||
minimum current limiting restiance is R = (Vs - Vf) / If = 55 Ohms
|
||||
```
|
||||
Add a safety margin for resistor tolerances (1%, 2%, 5%, 10%), and round up to a standard value.
|
||||
http://www.rfcafe.com/references/electrical/resistor-values.htm
|
||||
@ -103,5 +99,9 @@ From your LED's datasheet, find:
|
||||
|
||||
Calculate the minimum resistance needed for your LED and Supply Voltage.
|
||||
|
||||
2) See how bright an LED can get.
|
||||
In the above breadboard keyboard, replace an LED's 4.7k Ohm resistor with a 68 Ohm resistor.
|
||||
Make sure use a controller pin with a 20mA capacity (Teensy LC pins 16, 17, 21 have a 20mA capacity).
|
||||
|
||||
<br>
|
||||
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">keybrd tutorial</span> by <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd" property="cc:attributionName" rel="cc:attributionURL">Wolfram Volpi</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.<br />Permissions beyond the scope of this license may be available at <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd/issues/new" rel="cc:morePermissions">https://github.com/wolfv6/keybrd/issues/new</a>.
|
||||
|
@ -7,16 +7,20 @@ and familiar with I/O expanders from tutorial_4c_split_keyboard_with_IOE.md.
|
||||
|
||||
Adding LEDs to the basic breadboard keyboard
|
||||
--------------------------------------------
|
||||
The breadboard keyboard modifies the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md)
|
||||
The breadboard keyboard modifies the split breadboard keyboard described in [tutorial_4c_split_keyboard_with_IOE.md](tutorial_4c_split_keyboard_with_IOE.md)
|
||||
|
||||
Add components to the breadboard as shown in the picture.
|
||||
|
||||
The two clear plastic cylinders are red and yellow LEDs.
|
||||
Each LED is in series with a 4.7k Ohm current limiting resistor.
|
||||
LED anodes (the longer lead) are powered by pins GPA6 and GPB6.
|
||||
LED anodes (the longer lead) are powered by pins GPA5 and GPB4.
|
||||
LED cathodes (the shorter lead) are connected to a grounded terminal strip.
|
||||
|
||||
!["LEDs"](keybrd_5_LEDs/LEDs_back.JPG "LEDs")
|
||||
!["front"](keybrd_5b_LED_on_IOE/front.JPG "front")
|
||||
|
||||
!["back"](keybrd_5b_LED_on_IOE/back.JPG "back")
|
||||
|
||||
!["LEDs"](keybrd_5b_LED_on_IOE/LEDs.JPG "LEDs")
|
||||
|
||||
keybrd sketch with LEDs on IOE
|
||||
------------------------------
|
||||
|
@ -1,7 +1,5 @@
|
||||
Tutorial 6 - Active high
|
||||
=========================
|
||||
This tutorial pulls together several concepts needed to understand active state in the context of a keyboard.
|
||||
Skip to the end of this tutorial if you just want to copy an active-high keyboard.
|
||||
========================
|
||||
|
||||
Pull-up resistors
|
||||
-----------------
|
||||
@ -10,29 +8,18 @@ Here is a [good tutorial on Pull-up Resistors](https://learn.sparkfun.com/tutori
|
||||
|
||||
Active low
|
||||
----------
|
||||
All the keyboards up to this point in the tutorial series have used active low with internal pull-up resistors.
|
||||
Most the keyboards up to this point in the tutorial series have used active low with internal pull-up resistors.
|
||||
|
||||
"Active low" means that if a switch is pressed (active state), the read pin is low.
|
||||
When the switch is released (inactive state), the pull-up resistor pulls the read pin high.
|
||||
|
||||
The following table traces the strobe current from left to right (0 is ground, 1 is power).
|
||||
If the switch is closed, the strobe current passes through the switch and pulls the read pin low.
|
||||
If the switch is open, the pull-up resistor pulls the read pin high.
|
||||
<br>
|
||||
|
||||
|Strobe pin on | Diode orientation | Switch position | Pull resistor | Read pin state |
|
||||
|:------------:|:------------------:|:---------------:|:-------------:|:---------------:|
|
||||
| 0 | cathode -:<- anode | close | 1 pull-up | 0 active low |
|
||||
| 0 | cathode -:<- anode | open | 1 pull-up | 1 inactive high |
|
||||
<br>
|
||||
Arduino boards have internal pull-up resistors, which saves on parts and labor compared to manually adding external pull resistors.
|
||||
|
||||
To make a keyboard active low:
|
||||
* Orient diodes with cathode (banded end) towards the write pins (row)
|
||||
* Define strobe on and strobe off in the sketch like this:
|
||||
To make a key matrix active low:
|
||||
* Orient diodes with cathode (banded end) towards the strobe pins (row)
|
||||
* Instantiate the scanner in the sketch with strobeOn LOW, like this:
|
||||
```
|
||||
const bool Scanner_uC::STROBE_ON = LOW;
|
||||
const bool Scanner_uC::STROBE_OFF = HIGH;
|
||||
Scanner_uC scanner(LOW, readPins, readPinCount);
|
||||
```
|
||||
|
||||
Active high
|
||||
@ -40,41 +27,28 @@ Active high
|
||||
"Active high" means that if a switch is pressed (active), the read pin is high.
|
||||
When the switch is released (inactive), the pull-down resistor pulls the read pin low.
|
||||
|
||||
The following table traces the strobe current from left to right (0 is ground, 1 is power).
|
||||
If the switch is closed, the strobe current passes through the switch and pulls the read pin high.
|
||||
If the switch is open, the pull-down resistor pulls the read pin low.
|
||||
<br>
|
||||
|
||||
|Strobe pin on | Diode orientation | Switch position | Pull resistor | Read pin state |
|
||||
|:------------:|:------------------:|:---------------:|:-------------:|:---------------:|
|
||||
| 1 | anode ->:- cathode | close | 0 pull-down | 1 active high |
|
||||
| 1 | anode ->:- cathode | open | 0 pull-down | 0 inactive low |
|
||||
<br>
|
||||
Arduino boards do not have internal pull-down resistors.
|
||||
If you want to use active low, you will have to add external pull-down resistors to the read pins.
|
||||
|
||||
To make a keyboard active high:
|
||||
* Add an external 10k pull-down resistor to each read pin
|
||||
To make a key matrix active high:
|
||||
* Add an external 10k Ohm pull-down resistor to each read pin
|
||||
* Orient diodes with cathode (banded end) towards the read pins
|
||||
* Define strobe on and off in the sketch like this:
|
||||
* Instantiate the scanner in the sketch with strobeOn HIGH, like this:
|
||||
```
|
||||
const bool Scanner_uC::STROBE_ON = HIGH;
|
||||
const bool Scanner_uC::STROBE_OFF = LOW;
|
||||
Scanner_uC scanner(HIGH, readPins, readPinCount);
|
||||
```
|
||||
|
||||
Making a breadboard keyboard active-high
|
||||
----------------------------------------
|
||||
This tutorial converts the basic breadboard keyboard from tutorial 1 to active high.
|
||||
By comparing the above tables, one can see what changes need to be made:
|
||||
* add external pull-down resistors to the read pins
|
||||
* flip the diodes so that the cathode (banded end) are towards the read pins
|
||||
* swap the STROBE_ON and STROBE_OFF values
|
||||
Make the following changes to the basic breadboard keyboard described in [tutorial_1_breadboard_keyboard.md](tutorial_1_breadboard_keyboard.md):
|
||||
* Add an external 10k Ohm pull-down resistor (red bus) to each read pin
|
||||
* Orient diodes with cathode (banded end) towards the read pins
|
||||
|
||||
The pull-down resistors plug into ground (red bus) and column read pins.
|
||||
![pull-down resistors](keybrd_6_active_high/back.JPG "pull-down resistors")
|
||||
|
||||
The [keybrd_6_active_highsketch.ino](keybrd_6_active_high/keybrd_6_active_high.ino) is the tutorial 1 sketch with STROBE_ON and STROBE_OFF values swapped.
|
||||
|
||||
![pull_down_resistors.JPG](keybrd_6_active_high/pull_down_resistors.JPG "Active-high diodes and pull-down resistors")
|
||||
keybrd sketch with active-high
|
||||
------------------------------
|
||||
The [keybrd_6_active_high.ino](keybrd_6_active_high/keybrd_6_active_high.ino) sketch will run on the above breadboard keyboard.
|
||||
|
||||
<br>
|
||||
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">keybrd tutorial</span> by <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd" property="cc:attributionName" rel="cc:attributionURL">Wolfram Volpi</a> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.<br />Permissions beyond the scope of this license may be available at <a xmlns:cc="https://creativecommons.org/ns" href="https://github.com/wolfv6/keybrd/issues/new" rel="cc:morePermissions">https://github.com/wolfv6/keybrd/issues/new</a>.
|
||||
|