diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6cb267f..af65f4d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,8 +4,8 @@ We'd love for you to contribute to the keybrd project. Improvement suggestions ----------------------- -We need to know what improvements to the keybrd library would help you create your keyboard design. -Before requesting an improvement, please check [planned_features list](doc/planned_features.md) +We need to know what keybrd library improvements would help you create keyboard designs. +Before requesting an improvement, please check the [planned_features list](doc/planned_features.md). Submit improvement suggestions to [GitHub issues](https://github.com/wolfv6/Keybrd/issues) or [geekhack thread](https://geekhack.org/index.php?topic=83599.0). @@ -16,8 +16,8 @@ or [geekhack thread](https://geekhack.org/index.php?topic=83599.0). Bug reports ----------- -A bug report is the first step in finding a bug. -Once it is found, correcting it is usually relatively easy. +Submitting a bug report is the first step in fixing a bug. +Once it is found, correcting a bug 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). @@ -33,7 +33,7 @@ Provide enough information so we can reproduce the buggy behaviour! Code contributions ------------------ -Unsure where to begin contributing to keybrd code? +Unsure of where to begin contributing to keybrd code? You can start by looking through the improvement suggestions, bug reports, and [planned_features](doc/planned_features.md). Git commit message style guide: @@ -49,18 +49,57 @@ 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. -### 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 +### keybrd tutorials usability survey +We want feedback on keybrd tutorial usability from real users (feedback from noobs is especially valuable). +Please take the survey after completing a tutorial. +Answer the questions you feel like answering, or make up your own questions. -Feedback from Beta testers will be used to make improvements to the keybrd library. +* How easy was it to find the relevant tutorial? + +* Which tutorial did you read? + +* Did the tutorial provide complete information? + +* What other tutorial topics would be useful? + +* Are you satisfied with the tutorial? + +* Other comments or suggestions. + +Post the completed Q & A on [geekhack thread](https://geekhack.org/index.php?topic=83599.0) with a heading "Tutorial usability survey". +If you prefer your answers remain confidential, pm the completed Q & A to [wolfv](https://geekhack.org/index.php?action=pm;sa=send;u=25471). + +Usability survey results will be used to make improvements to the tutorials. + +### keybrd library usability survey +We want feedback on keybrd library usability from real users. +Please fill the survey after using the keybrd library to implement a keyboard design. +Answer the questions you feel like answering, or make up your own questions. + +* How easy was it to find relevant information? + +* Did the User guide provide complete information? + +* What other keyboard firmware have you used? + +* What pros and cons did you find compared to other keyboard firmware? + +* Did you publish your keyboard firmware? If so, please provide a link. + +* Are you satisfied with the keybrd library? + +* Other comments or suggestions. + +Post the completed Q & A on [geekhack thread](https://geekhack.org/index.php?topic=83599.0) with a heading "keybrd library usability survey". +If you prefer your answers remain confidential, pm the completed Q & A to [wolfv](https://geekhack.org/index.php?action=pm;sa=send;u=25471). + +Usability survey results 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 would be easier to read than the current photos. -Schematics are not my area of expertise. Use what ever you think would be the best solution for the tutorials: +Schematics are not my area of expertise. Use what ever would be the best solution for the tutorials: * schematics * breadboard drawings * Arduino simulation software @@ -71,12 +110,29 @@ Contributions of tutorial schematics would benefit users new to the keybrd libra 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. +Please submit improvement and errata to [GitHub issues](https://github.com/wolfv6/Keybrd/issues) +or [geekhack thread](https://geekhack.org/index.php?topic=83599.0). 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). +### Write a sketch for a keyboard that is popular with Arduino-compatible controllers +Write a keybrd sketch for a keyboard that is popular with Arduino-compatible controllers. +* You should own the keyboard so you can test the firmware +* The keyboard should have an Arduino compatible controller (e.g. ErgoDox and Phantom use Teensy 2.0) +* The layout should be a plain baseline layout (QWERTY) + +Other owners of that model keyboard can then easily modify and compile the sketch on Arduino IDE. + +The README should have: +* brief description of the electronics +* link to a hardware page +* list any firmware deficiencies + +Follow the "Publish" instructions in tutorial_8c_sharing_your_keybrd_sketch.md + ### 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. @@ -85,5 +141,7 @@ A healthy project needs the perspective of many people. Submitting a pull request ------------------------- Pull request is the preferred way to contribute code and documentation. -If you want to contribute some other way, please make a request in the [GitHub issues](https://github.com/wolfv6/Keybrd/issues). +If you want to contribute some other way, please make a request in +[GitHub issues](https://github.com/wolfv6/Keybrd/issues) +or [geekhack thread](https://geekhack.org/index.php?topic=83599.0). diff --git a/IOE_scan_development/IOE_scan_development.ods b/IOE_scan_development/IOE_scan_development.ods new file mode 100644 index 0000000..7683b83 Binary files /dev/null and b/IOE_scan_development/IOE_scan_development.ods differ diff --git a/IOE_scan_development/openDrain_activeLow/back.JPG b/IOE_scan_development/openDrain_activeLow/back.JPG new file mode 100644 index 0000000..48304c3 Binary files /dev/null and b/IOE_scan_development/openDrain_activeLow/back.JPG differ diff --git a/IOE_scan_development/openDrain_activeLow/front.JPG b/IOE_scan_development/openDrain_activeLow/front.JPG new file mode 100644 index 0000000..c1997ff Binary files /dev/null and b/IOE_scan_development/openDrain_activeLow/front.JPG differ diff --git a/IOE_scan_development/openDrain_activeLow/openDrain_activeLow.ino b/IOE_scan_development/openDrain_activeLow/openDrain_activeLow.ino new file mode 100644 index 0000000..2fcf51b --- /dev/null +++ b/IOE_scan_development/openDrain_activeLow/openDrain_activeLow.ino @@ -0,0 +1,69 @@ +/* simulate one scan of a key martix, on open-drain active-low I/O expander + +BREADBOARD SETUP ******************************* + Teensy LC connected to MCP23018 I/O expander via I2C + 4.7k Ohm pullup resistors on SDA and SCL + use volt meter to measure pin voltages + MCP23018 has open-drain outputs (open-drain can only sink current) + +MCP23018 PIN DIAGRAM *************************** + write port B read port A + GND VSS 1 28 NC + NC 2 27 GPA7 + jumper0 GPB0 3 26 GPA6 + GPB1 4 25 GPA5 + GPB2 5 24 GPA4 jumper4 + GPB3 6 23 GPA3 + jumper4 GPB4 7 22 GPA2 + GPB5 8 21 GPA1 + GPB6 9 20 GPA0 jumper0 + GPB7 10 19 INTA + power VDD 11 18 INTB + SCL SCL 12 17 NC + SDA SDA 13 16 RESET power + NC 14 15 ADDR GND +*/ +#include "Wire.h" + +const uint8_t ADDR = 0x20; //MCP23018 I2C address with ADDR pin grounded + +void setup() +{ + delay(1000); //time for Serial print to work + +// ================= configure ================ + Serial.print("config "); + Wire.begin(); + + Wire.beginTransmission(ADDR); + Wire.write(0x01); //IODIRB Configure + Wire.write(0); //as output + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x00); //IODIRA Configuration + Wire.write(~0); //as input + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x0C); //GPPUA pull-up + Wire.write(~0); //pull-up enabled + Wire.endTransmission(); + +// =================== scan =================== + Serial.println("scan"); + + Wire.beginTransmission(ADDR); + Wire.write(0x13); //GPIOB output + Wire.write(B00001111); //pins 0-3 off, pins 4-7 sink on (strobe, LED on) + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x12); //GPIOA (immediately before requestFrom) + Wire.endTransmission(); + + Wire.requestFrom(ADDR, static_cast(1)); //request one byte from GPIOA read + Serial.print("portA="); + Serial.println(Wire.read(), BIN); //prints portA=11101111 +} +void loop() { } diff --git a/IOE_scan_development/source_activeHigh/DSCF0003.JPG b/IOE_scan_development/source_activeHigh/DSCF0003.JPG new file mode 100644 index 0000000..d7d5891 Binary files /dev/null and b/IOE_scan_development/source_activeHigh/DSCF0003.JPG differ diff --git a/IOE_scan_development/source_activeHigh/DSCF0004.JPG b/IOE_scan_development/source_activeHigh/DSCF0004.JPG new file mode 100644 index 0000000..f7e8867 Binary files /dev/null and b/IOE_scan_development/source_activeHigh/DSCF0004.JPG differ diff --git a/IOE_scan_development/source_activeHigh/source_activeHigh.ino b/IOE_scan_development/source_activeHigh/source_activeHigh.ino new file mode 100644 index 0000000..d87abcd --- /dev/null +++ b/IOE_scan_development/source_activeHigh/source_activeHigh.ino @@ -0,0 +1,69 @@ +/* simulate one scan of a key martix, on source active-high I/O expander + +BREADBOARD SETUP ******************************* + Teensy LC connected to MCP23017 I/O expander via I2C + 10k Ohm external pulldown resistors on port A + 4.7k Ohm pullup resistors on SDA and SCL + use volt meter to measure pin voltages + +MCP23017 PIN DIAGRAM *************************** + write port B read port A + jumper0 GPB0 1 26 GPA7 pulldown + GPB1 2 25 GPA6 pulldown + GPB2 3 24 GPA5 pulldown + GPB3 4 23 GPA4 pulldown jumper4 + jumper4 GPB4 5 22 GPA3 pulldown + GPB5 6 21 GPA2 pulldown + GPB6 7 20 GPA1 pulldown + GPB7 8 19 GPA0 pulldown jumper0 + power VDD 9 18 INTA + GND VSS 10 28 INTB + NC 11 27 RESET power + SCL SCL 12 17 A2 gnd + SDA SDA 13 16 A1 gnd + NC 14 15 A0 gnd +*/ +#include "Wire.h" + +const uint8_t ADDR = 0x20; //MCP23017 I2C address with all ADDR pins grounded + +void setup() +{ + delay(1000); //time for Serial print to work + +// ================= configure ================ + Serial.print("config "); + Wire.begin(); + + Wire.beginTransmission(ADDR); + Wire.write(0x01); //IODIRB Configure + Wire.write(0); //as output + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x00); //IODIRA Configuration + Wire.write(~0); //as input + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x0C); //GPPUA pull-up + Wire.write(0); //pull-up disabled + Wire.endTransmission(); + +// =================== scan =================== + Serial.println("scan"); + + Wire.beginTransmission(ADDR); + Wire.write(0x13); //GPIOB output + Wire.write(B11110000); //pins 0-3 ground, pins 4-7 power (strobe, LED on) + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x12); //GPIOA (immediately before requestFrom) + Wire.endTransmission(); + + Wire.requestFrom(ADDR, static_cast(1)); //request one byte from GPIOA read + Serial.print("portA="); + Serial.println(Wire.read(), BIN); //prints portA=00010000 +} +void loop() { } diff --git a/IOE_scan_development/source_activeLow/back.JPG b/IOE_scan_development/source_activeLow/back.JPG new file mode 100644 index 0000000..8b75e70 Binary files /dev/null and b/IOE_scan_development/source_activeLow/back.JPG differ diff --git a/IOE_scan_development/source_activeLow/front.JPG b/IOE_scan_development/source_activeLow/front.JPG new file mode 100644 index 0000000..5f6bc96 Binary files /dev/null and b/IOE_scan_development/source_activeLow/front.JPG differ diff --git a/IOE_scan_development/source_activeLow/source_activeLow.ino b/IOE_scan_development/source_activeLow/source_activeLow.ino new file mode 100644 index 0000000..40b0a1a --- /dev/null +++ b/IOE_scan_development/source_activeLow/source_activeLow.ino @@ -0,0 +1,68 @@ +/* simulate one scan of a key martix, on source active-low I/O expander + +BREADBOARD SETUP ******************************* + Teensy LC connected to MCP23017 I/O expander via I2C + 4.7k Ohm pullup resistors on SDA and SCL + use volt meter to measure pin voltages + +MCP23017 PIN DIAGRAM *************************** + write port B read port A + jumper0 GPB0 1 26 GPA7 + GPB1 2 25 GPA6 + GPB2 3 24 GPA5 + GPB3 4 23 GPA4 jumper4 + jumper4 GPB4 5 22 GPA3 + GPB5 6 21 GPA2 + GPB6 7 20 GPA1 + GPB7 8 19 GPA0 jumper0 + power VDD 9 18 INTA + GND VSS 10 28 INTB + NC 11 27 RESET power + SCL SCL 12 17 A2 gnd + SDA SDA 13 16 A1 gnd + NC 14 15 A0 gnd +*/ +#include "Wire.h" + +const uint8_t ADDR = 0x20; //MCP23017 I2C address with all ADDR pins grounded + +void setup() +{ + delay(1000); //time for Serial print to work + +// ================= configure ================ + Serial.print("config "); + Wire.begin(); + + Wire.beginTransmission(ADDR); + Wire.write(0x01); //IODIRB Configure + Wire.write(0); //as output + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x00); //IODIRA Configuration + Wire.write(~0); //as input + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x0C); //GPPUA pull-up + Wire.write(~0); //pull-up enabled + Wire.endTransmission(); + +// =================== scan =================== + Serial.println("scan"); + + Wire.beginTransmission(ADDR); + Wire.write(0x13); //GPIOB output + Wire.write(B00001111); //pins 0-3 power (strobe, LED on), pins 4-7 ground + Wire.endTransmission(); + + Wire.beginTransmission(ADDR); + Wire.write(0x12); //GPIOA (immediately before requestFrom) + Wire.endTransmission(); + + Wire.requestFrom(ADDR, static_cast(1)); //request one byte from GPIOA read + Serial.print("portA="); + Serial.println(Wire.read(), BIN); //prints portA=11101111 +} +void loop() { } diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md index 76bb423..eae14c6 100644 --- a/doc/CHANGELOG.md +++ b/doc/CHANGELOG.md @@ -6,11 +6,6 @@ This project adheres to [Semantic Versioning 2.0.0](http://semver.org/). keybrd version 0.x.x is for initial development. keybrd version 1.0.0 will be released when the public API is stable. -< !-- -Unreleased ----------- ---> - 0.6.0 (2016-09-28) ------------------ * Enhancements diff --git a/doc/PLANNED_FEATURES.md b/doc/PLANNED_FEATURES.md index 45007f6..7e5b99a 100644 --- a/doc/PLANNED_FEATURES.md +++ b/doc/PLANNED_FEATURES.md @@ -2,14 +2,12 @@ planned_features is a view of where the keybrd project is headed. Top priority ------------ -* Beta testing -* Add breadboard keyboard schematics to tutorials +* User testing Medium priority --------------- -* Add matrix-to-layout mapping array (to decouple key matrix from layout) -* Add tutorial_4b_split_keyboard_with_shift_registers +* Add matrix-to-layout mapping (to decouple key matrix from layout) +* Add breadboard keyboard schematics to tutorials Low priority ------------ -* Add MCP23S18 I/O expander with Serial Peripheral Interface (SPI) diff --git a/examples/keybrd_MCP23018/keybrd_MCP23018.ino b/examples/keybrd_MCP23018/keybrd_MCP23018.ino new file mode 100644 index 0000000..903ac60 --- /dev/null +++ b/examples/keybrd_MCP23018/keybrd_MCP23018.ino @@ -0,0 +1,131 @@ +/* keybrd_MCP23018.ino + +This sketch: + is a simple 1-layer keyboard + runs on two matrices of a breadboard keyboard + + Controller I/O expander +| Left | **0** | **1** | | Right | **0** | **1** | +|-------|-------|-------| |-------|-------|-------| +| **1** | 1 | 2 | | **1** | 3 | 4 | +| **0** | a | b | | **0** | c | d | +*/ +// ################## GLOBAL ################### +// ================= INCLUDES ================== +#include +#include +#include +#include + +//left matrix +#include + +//right matrix +#include +#include +#include + +// ============ SPEED CONFIGURATION ============ +ScanDelay scanDelay(9000); + +/* ================ LEFT SCANNER =============== +Left matrix rows work the same as the ones in keybrd_2_single-layer.ino +*/ +uint8_t readPins[] = {14, 15}; +const uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); + +Scanner_uC scanner_L(LOW, readPins, readPinCount); + +/* =============== RIGHT SCANNER =============== +The right matrix is scanned by an I/O expander. +The MCP23018 address is set by grounding or powering pins. +*/ +const uint8_t IOE_ADDR = 0x20; //MCP23018 address pin grounded + +/* +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_MCP23018 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. +Pin numbers to be read are delimited by "|" and to the right of "1<<". +*/ +Port_MCP23018 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //read pins 0, 1 +Port_MCP23018 portB(IOE_ADDR, 1, 0); +Scanner_IOE scanner_R(LOW, portB, portA); + +/* ================= RIGHT LED ================= +The LED_Port constructor parameters are a port and pin number that is connected to an LED. +*/ +LED_Port LED_capsLck(portA, 1<<7); + +// =================== 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_Sc s_4(KEY_4); + +Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_capsLck);//todo was testing LED, restore s_4 when done + +/* =================== ROWS ==================== +Left row names contain the letter 'L', while right row names conatain the letter 'R'. + +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 +*/ +/* ---------------- LEFT ROWS ------------------ +The left rows have a Scanner_uC and Arduino pin numbers to strobe. +*/ +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 ----------------- +The right rows have a Scanner_IOE and pin bits to strobe. +*/ +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(); +//Keyboard.println(" 0"); +//delay(2000); + row_R1.process(); +//Keyboard.println(" 1"); +//delay(2000); + + scanDelay.delay(); +//Keyboard.println(" end loop");//todo + //debug.print_scans_per_second(); + //debug.print_microseconds_per_scan(); +} diff --git a/src/LED_shiftRegs.cpp b/src/LED_shiftRegs.cpp new file mode 100644 index 0000000..fada75e --- /dev/null +++ b/src/LED_shiftRegs.cpp @@ -0,0 +1,33 @@ +#include "LED_shiftRegs.h" + +/* constructor +*/ +LED_shiftRegs::LED_shiftRegs(const uint8_t slaveSelect, const uint8_t pin) + :slaveSelect(slaveSelect), pin(pin) +{ + pinMode(slaveSelect, OUTPUT); +} + +/* begin() should be called once from sketch setup(). +Initializes shift register's shift/load pin. +*/ +void LED_shiftRegs::begin() +{ + SPI.begin(); + digitalWrite(slaveSelect, HIGH); +} + +//todo preserve other LED values, similar to Port_PCA9655E outputVal +void LED_shiftRegs::on() +{ + digitalWrite(slaveSelect, LOW); + SPI.transfer(pin); + digitalWrite (slaveSelect, HIGH); +} + +void LED_shiftRegs::off() +{ + digitalWrite(slaveSelect, LOW); + SPI.transfer(0); + digitalWrite (slaveSelect, HIGH); +} diff --git a/src/LED_shiftRegs.h b/src/LED_shiftRegs.h new file mode 100644 index 0000000..1fc3fc2 --- /dev/null +++ b/src/LED_shiftRegs.h @@ -0,0 +1,22 @@ +#ifndef LED_SHIFTREGS_H +#define LED_SHIFTREGS_H +#include +#include +#include +#include + +/* A LED_shiftRegs turns LED on and off. +shift register RCLK pin a.k.a. SS or ST +*/ +class LED_shiftRegs: public LEDInterface +{ + private: + const uint8_t slaveSelect;//controller pin number connected to shift register RCLK + const uint8_t pin; //bit pattern, shift register pin that is connected to an LED + public: + LED_shiftRegs(const uint8_t slaveSelect, const uint8_t pin); + void begin(); + virtual void on(); + virtual void off(); +}; +#endif diff --git a/src/LED_uC.h b/src/LED_uC.h index 3b89ae4..f66598d 100644 --- a/src/LED_uC.h +++ b/src/LED_uC.h @@ -14,7 +14,7 @@ class LED_uC: public LEDInterface public: LED_uC(const uint8_t pin): pin(pin) { - pinMode(pin, OUTPUT); + pinMode(pin, OUTPUT);//todo move to .cpp file } virtual void on(); virtual void off(); diff --git a/src/Port_MCP23018.cpp b/src/Port_MCP23018.cpp new file mode 100644 index 0000000..8275b26 --- /dev/null +++ b/src/Port_MCP23018.cpp @@ -0,0 +1,83 @@ +#include "Port_MCP23018.h" +//todo add Port_MCP23018::write() like Port_MCP23S17::transer() ?? + +/* beginProtocol() is called from Scanner_IOE::begin(). Initiates I2C bus. + +MCP23018 supports I2C SCL Clock Frequencies: 100 kHz, 400 kHz, 1000 kHz (Datasheet page 1 & 6) +The electrical limitation to bus speed is bus capacitance and the length of the wires involved. +Longer wires require lower clock speeds. + http://playground.arduino.cc/Main/WireLibraryDetailedReference > Wire.setclock() +*/ +void Port_MCP23018::beginProtocol() +{ + Wire.begin(); //initiate I2C bus to 100 kHz + //Wire.setClock(400000L); //set I2C bus to 400 kHz (have not tested 400 kHz) +} + +/* begin() is called from Scanner_IOE::begin(). +Configures port's IODIR and GPPU. +*/ +void Port_MCP23018::begin(const uint8_t strobeOn) +{ + uint8_t pullUp; //bits, GPPU 0=pull-up disabled, 1=pull-up enabled + + if (strobeOn == LOW) //if active low + { + pullUp = readPins; //0=pull-up disabled (for LED), 1=pull-up enabled (for read) + } + else //if active high + { + pullUp = 0; //0=pull-up disabled (for external pull-down resistors) + } + + Wire.beginTransmission(deviceAddr); + Wire.write(portNum); //IODIR + Wire.write(readPins); //0=output (for strobe and LED), 1=input (for read) + Wire.endTransmission(); + + Wire.beginTransmission(deviceAddr); + Wire.write(portNum + 0x0C); //GPPU + Wire.write(pullUp); + Wire.endTransmission(); +} + +/* write() sets pin output to logicLevel. +pin is bit pattern, where pin being strobed is 1. +logicLevel is HIGH or LOW. +write() does not overwrite the other pins. +*/ +void Port_MCP23018::write(const uint8_t pin, const bool logicLevel) +{ + if (logicLevel == LOW) + { + outputVal &= ~pin; //set pin output to low +//Keyboard.print(" low"); + } + else + { + outputVal |= pin; //set pin output to high +//Keyboard.print(" high"); + } + +//Keyboard.print(" outputVal=");//todo +//Keyboard.println(outputVal); + Wire.beginTransmission(deviceAddr); + Wire.write(portNum + 0x12); //GPIO + Wire.write(outputVal); + Wire.endTransmission(); +//delay(4000); +} + +/* read() returns portState. +Only portState bits of readPins are valid. +*/ +uint8_t Port_MCP23018::read() +{ + Wire.beginTransmission(deviceAddr); + Wire.write(portNum + 0x12); //GPIO + Wire.endTransmission(false); //MCP23018 needs false to send a restart ??really? + + Wire.requestFrom(deviceAddr, 1u); //request one byte from input port + + return Wire.read(); +} diff --git a/src/Port_MCP23018.h b/src/Port_MCP23018.h new file mode 100644 index 0000000..a58f8aa --- /dev/null +++ b/src/Port_MCP23018.h @@ -0,0 +1,48 @@ +#ifndef PORT_MCP23018_H +#define PORT_MCP23018_H +#include +#include +#include +#include + +/* +write pins are connected to matrix Row (strobe pin) or LED. +readPins are connected to matrix column to read which keys are pressed. + +MCP23018 has open-drain outputs (open-drain can only sink current). If LEDs are used, connect: + LED anodes (the longer lead) to power + LED cathodes (the shorter lead) to GPIO pin + +Instantiation + ------------ +Example instantiation: + const uint8_t IOE_ADDR = 0x20; //MCP23018 address pin grounded + Port_MCP23018 portB(IOE_ADDR, 1, 0); //all pins are set to output for strobes and LEDs + Port_MCP23018 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 + ---------------- +Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation + +MCP23018 data sheet + ---------------- + http://ww1.microchip.com/downloads/en/DeviceDoc/22103a.pdf +*/ + +class Port_MCP23018 : public PortInterface +{ + private: + const uint8_t deviceAddr; + const uint8_t portNum; //port identification number, 0=A, 1=B + uint8_t outputVal; //bit pattern for strobe and LEDs + const uint8_t readPins; //bit pattern, IODIR 0=output, 1=input + public: + Port_MCP23018(const uint8_t deviceAddr, const uint8_t portNum, const uint8_t readPins) + : deviceAddr(deviceAddr), portNum(portNum), outputVal(0), readPins(readPins) {} + void beginProtocol(); + void begin(const uint8_t strobeOn); + virtual void write(const uint8_t pin, const bool logicLevel); + virtual uint8_t read(); +}; +#endif diff --git a/src/Port_MCP23S17.cpp b/src/Port_MCP23S17.cpp index cda2c35..5717d79 100644 --- a/src/Port_MCP23S17.cpp +++ b/src/Port_MCP23S17.cpp @@ -22,7 +22,7 @@ uint8_t Port_MCP23S17::transfer(const uint8_t command, const uint8_t registerAdd return portState; } -/* begin() is called from Scanner_IOE::begin(). Initiates SPI bus. +/* beginProtocol() is called from Scanner_IOE::begin(). Initiates SPI bus. */ void Port_MCP23S17::beginProtocol() { @@ -39,13 +39,13 @@ void Port_MCP23S17::begin(const uint8_t strobeOn) { uint8_t pullUp; //bits, GPPU 0=pull-up disabled, 1=pull-up enabled - if (strobeOn == LOW) //if active low, use internal pull-up resistors + if (strobeOn == LOW) //if active low { - pullUp = readPins; + pullUp = readPins; //0=pull-up disabled (for LED), 1=pull-up enabled (for read) } - else //active high requires external pull-down resistors + else //if active high { - pullUp = 0; + pullUp = 0; //0=pull-up disabled (for external pull-down resistors) } transfer(deviceAddr << 1, portNum, readPins); //configure IODIR diff --git a/src/Port_PCA9655E.cpp b/src/Port_PCA9655E.cpp index bb450f1..4bb2a63 100644 --- a/src/Port_PCA9655E.cpp +++ b/src/Port_PCA9655E.cpp @@ -1,6 +1,6 @@ #include "Port_PCA9655E.h" -/* begin() is called from Scanner_IOE::begin(). Initiates I2C bus. +/* beginProtocol() is called from Scanner_IOE::begin(). Initiates I2C bus. PCA9655E supports I2C SCL Clock Frequencies: 100 kHz, 400 kHz, 1000 kHz (Datasheet page 1 & 6) The electrical limitation to bus speed is bus capacitance and the length of the wires involved. diff --git a/src/Scanner_ShiftRegsPISOMultiRow.cpp b/src/Scanner_ShiftRegsPISOMultiRow.cpp index 6255a87..f37bc46 100644 --- a/src/Scanner_ShiftRegsPISOMultiRow.cpp +++ b/src/Scanner_ShiftRegsPISOMultiRow.cpp @@ -16,6 +16,7 @@ Configures controller to communicate with shift register matrix. void Scanner_ShiftRegsPISOMultiRow::init(const uint8_t strobePin) { pinMode(strobePin, OUTPUT); + //digitalWrite(strobePin, strobeOff);//todo is this needed? } /* begin() should be called once from sketch setup(). @@ -23,7 +24,7 @@ Initializes shift register's shift/load pin. */ void Scanner_ShiftRegsPISOMultiRow::begin() { - digitalWrite(slaveSelect, HIGH); + SPI.begin(); } /* scan() strobes the row's strobePin and returns state of the shift register's input pins. @@ -34,16 +35,25 @@ read_pins_t Scanner_ShiftRegsPISOMultiRow::scan(const uint8_t strobePin) { read_pins_t readState = 0; //bits, 1 means key is pressed, 0 means released - //strobe row on + //strobe on digitalWrite(strobePin, strobeOn); - delayMicroseconds(3); //time to stablize voltage + + //SPI.beginTransaction( SPISettings(5000000, MSBFIRST, SPI_MODE0) ); //control SPI bus, 5 MHz + //digitalWrite(slaveSelect, LOW); //assert slave + + delayMicroseconds(3); //time to stabilize photo-transistor todo needed? + delayMicroseconds(50); //todo for sr2_LEDs_strobe.ino //read all the column pins - digitalWrite(slaveSelect, LOW); //load parallel inputs to the register digitalWrite(slaveSelect, HIGH); //shift the data toward a serial output - SPI.transfer(&readState, byte_count); - //strobe row off + SPI.transfer(&readState, byte_count); + digitalWrite(slaveSelect, LOW); //load parallel inputs to registers + + //digitalWrite(slaveSelect, HIGH); //de-assert slave + //SPI.endTransaction(); + + //strobe off digitalWrite(strobePin, strobeOff); return readState; diff --git a/src/Scanner_ShiftRegsPISOMultiRow.h b/src/Scanner_ShiftRegsPISOMultiRow.h index be37bc5..b7999eb 100644 --- a/src/Scanner_ShiftRegsPISOMultiRow.h +++ b/src/Scanner_ShiftRegsPISOMultiRow.h @@ -9,7 +9,7 @@ /* Scanner_ShiftRegsPISOMultiRow reads shift registers. This was tested on 74HC165 shift registers, which are Parallel-In-Serial-Out (PISO). -Upto 4 shift registers can be in a daisy chained for a total of 32 read pins. +Shift registers can be daisy chained for a total of 32 read pins. Example instantiation: Scanner_ShiftRegsPISOMultiRow scanner_R(HIGH, SS, 4); @@ -18,7 +18,6 @@ There are three Scanner_ShiftRegsPISOMultiRow parameters. "strobeOn" paramter is active state HIGH or LOW. "slaveSelect" paramter can be any controller pin connected to shift register's SHIFT-LOAD pin. -slaveSelect pin SS (Arduino pin 10) has the fastest scan. "byte_count" is the number of bytes to read from shift registers (1 to 4). byte_count should cover all the row's keys: @@ -26,7 +25,7 @@ byte_count should cover all the row's keys: Hardware setup: Each row needs to be connected to a strobe pin from the controller. -Switche and diode in series are connected to shift-register parallel-input pins and strobed row. +Switch and diode in series, connect shift-register parallel-input pins to strobed row. For active low: Shift-register parallel-input pins need 10k Ohm pull-up resistors powered. diff --git a/src/Scanner_ShiftRegsPISOSingleRow.cpp b/src/Scanner_ShiftRegsPISOSingleRow.cpp index 60e31dc..c8d8bcc 100644 --- a/src/Scanner_ShiftRegsPISOSingleRow.cpp +++ b/src/Scanner_ShiftRegsPISOSingleRow.cpp @@ -1,6 +1,7 @@ #include "Scanner_ShiftRegsPISOSingleRow.h" /* constructor +Parameter strobeOn is not used. */ Scanner_ShiftRegsPISOSingleRow::Scanner_ShiftRegsPISOSingleRow(const bool strobeOn, const uint8_t slaveSelect, const uint8_t byte_count) @@ -26,6 +27,7 @@ void Scanner_ShiftRegsPISOSingleRow::begin() } /* scan() returns state of the shift register's input pins. +Parameter strobePin is not used. No strobe pin is needed, the shift register is wired so the strobe is effectivley always "on". Bit patterns are 1 bit per key. */ diff --git a/src/Scanner_ShiftRegsPISOSingleRow.h b/src/Scanner_ShiftRegsPISOSingleRow.h index fe75f22..44f0204 100644 --- a/src/Scanner_ShiftRegsPISOSingleRow.h +++ b/src/Scanner_ShiftRegsPISOSingleRow.h @@ -22,7 +22,6 @@ There are three Scanner_ShiftRegsPISOSingleRow parameters. "strobeOn" paramter is ignored, but should be active state HIGH or LOW required by ScannerInterface. "slaveSelect" paramter can be any controller pin connected to shift register's SHIFT-LOAD pin. -slaveSelect pin SS (Arduino pin 10) has the fastest scan. "byte_count" is the number of bytes to read from shift registers (1 to 4). byte_count should cover all the row's keys: @@ -30,7 +29,8 @@ byte_count should cover all the row's keys: Hardware setup: There is only one row, and it is permanently active. -Switches are connected to shift-register parallel-input pins (diodes are not needed) and row. +Switches are connected to shift-register parallel-input pins and row. +Diodes are not needed because there is only one row. For active low: Shift-register parallel-input pins need 10k Ohm pull-up resistors powered. diff --git a/tutorials/keybrd_3a_multi-layerHold/front.JPG b/tutorials/keybrd_3a_multi-layerHold/front.JPG deleted file mode 100644 index a5c28d5..0000000 Binary files a/tutorials/keybrd_3a_multi-layerHold/front.JPG and /dev/null differ diff --git a/tutorials/keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino b/tutorials/keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino index 0a34fd7..e1de8ab 100644 --- a/tutorials/keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino +++ b/tutorials/keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino @@ -3,7 +3,7 @@ Tested on Teensy LC and two 74HC165 shift registers. Controller Two shift registers daisy chained | Left |**0**| | Right |**0**|**1**|**2**|**3**|**4**|**5**|**6**| -|:-----:|-----| |:-----:|-----|-----|-----|-----|-----|-----|-----| +|-------|-----| |-------|-----|-----|-----|-----|-----|-----|-----| | **0** | x | | **0** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | | **1** | y | | **1** | a | b | c | d | e | f | g | */ @@ -49,10 +49,8 @@ uint8_t readPinCount_L = sizeof(readPins_L)/sizeof(*readPins_L); Scanner_uC scanner_L(LOW, readPins_L, readPinCount_L); //active LOW -/* --------------- RIGHT SCANNER --------------- -use slaveSelect pin SS (Arduino pin 10) for fastest scan -*/ -Scanner_ShiftRegsPISOSingleRow scanner_R(HIGH, SS, 2); //active HIGH +// --------------- RIGHT SCANNER --------------- +Scanner_ShiftRegsPISOSingleRow scanner_R(HIGH, 10, 2); //active HIGH // =================== ROWS ==================== // ----------------- LEFT ROWS ----------------- diff --git a/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino b/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino index 1c94621..b31afad 100644 --- a/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino +++ b/tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino @@ -6,7 +6,7 @@ This sketch: Controller I/O expander | Left | **0** | **1** | | Right | **0** | **1** | -|:-----:|-------|-------|-|:-----:|-------|-------| +|-------|-------|-------| |-------|-------|-------| | **1** | 1 | 2 | | **1** | 3 | 4 | | **0** | a | b | | **0** | c | d | */ diff --git a/tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino b/tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino index 7030e02..dfb42a5 100644 --- a/tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino +++ b/tutorials/keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino @@ -1,7 +1,7 @@ /* keybrd_5b_LED_on_IOE.ino This sketch: - is a simple 1-layer keyboard with CapsLck indicator LED on I/O expander + is a simple 1-layer keyboard with indicator LED on controller and 2 LEDs on I/O expander runs on a two-matrix breadboard keyboard modified keybrd_4c_split_keyboard_with_IOE.ino by adding LED_capsLck @@ -10,8 +10,8 @@ This layout table shows left and right matrices: Controller I/O expander | Left | **0** | **1** | | Right | **0** | **1** | |:-----:|-------|-------|-|:-----:|-------|-------| -| **1** |CapsLck| a 1 | | **1** | b 2 | c 3 | -| **0** | fn | x = | | **0** | y - | z / | +| **0** |CapsLck| a 1 | | **1** | b 2 | c 3 | +| **1** | fn | x = | | **0** | y - | z / | */ // ################## GLOBAL ################### // ================= INCLUDES ================== @@ -35,7 +35,7 @@ This layout table shows left and right matrices: // ============ SPEED CONFIGURATION ============ ScanDelay scanDelay(9000); -// ==================== IC ===================== +// ==================== ICs ==================== // ---------------- LEFT SCANNER --------------- uint8_t readPins[] = {14, 15}; const uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins); @@ -47,8 +47,8 @@ LED_uC LED_capsLck(21); // --------------- RIGHT SCANNER --------------- const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded -Port_MCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //for read and LED -Port_MCP23S17 portB(IOE_ADDR, 1, 0); //for strobe and LED +Port_MCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //for read +Port_MCP23S17 portB(IOE_ADDR, 1, 0); //for strobe Scanner_IOE scanner_R(LOW, portB, portA); diff --git a/tutorials/tutorial_1_breadboard_keyboard.md b/tutorials/tutorial_1_breadboard_keyboard.md index d2f9198..a00d8ad 100644 --- a/tutorials/tutorial_1_breadboard_keyboard.md +++ b/tutorials/tutorial_1_breadboard_keyboard.md @@ -43,21 +43,21 @@ These are explained in [How to Use a Breadboard](https://learn.sparkfun.com/tuto Electrostatic discharge (ESD) safety ------------------------------------ -Static electricity can damage a microcontroller in ways that are hard to trouble shoot. +Static electricity can damage a ICs in ways that are hard to trouble shoot. -I live in a desert on a carpeted floor and get zapped by door knobs regularly. -Here is the ESD precaution I take whenever I handle a microcontroller: +Here is a ESD precaution for handling ICs: 1. Touch the bare metal on the back of my desktop computer (its grounded). -2. Then touch the metal USB connector case on the microcontroller. - -Anti-static mat or anti-static wristband are also effective. -Being tethered by an anti-static wristband can be inconvenient (wireless antistatic wrist straps are a scam). +2. Then touch the IC or circuit (if its a micro-controller, touch the metal USB connector case). +I take these ESD precaution because I live in a dry environment on a carpeted floor. Not everyone needs to take ESD precautions: * http://forum.arduino.cc/index.php?topic=4643.0 * https://forums.adafruit.com/viewtopic.php?f=8&t=12128 +Anti-static mat or anti-static wristband are also effective. +But being tethered by an anti-static wristband can be inconvenient (wireless antistatic wrist straps are a scam). + Building a basic breadboard keyboard ------------------------------------ The basic breadboard keyboard has 4 switches. diff --git a/tutorials/tutorial_2_single-layer_keyboard.md b/tutorials/tutorial_2_single-layer_keyboard.md index 2094cb6..e87763e 100644 --- a/tutorials/tutorial_2_single-layer_keyboard.md +++ b/tutorials/tutorial_2_single-layer_keyboard.md @@ -20,7 +20,9 @@ The scanner should have enough readPins to cover all the keys of the longest row | Layout |**0**|**1**|**2**| |:------:|:---:|:---:|:---:| | **0** | 1 | 2 | 3 | -| **1** | a | b | +| **1** | a | b | | + +[keybrd tutorials usability survey](../CONTRIBUTING.md##keybrd-tutorials-usability-survey)
Creative Commons License
keybrd tutorial by Wolfram Volpi is licensed under a Creative Commons Attribution 4.0 International License.
Permissions beyond the scope of this license may be available at https://github.com/wolfv6/keybrd/issues/new. diff --git a/tutorials/tutorial_4_connecting_split_keyboards.md b/tutorials/tutorial_4_connecting_split_keyboards.md index 975e8b9..c42d811 100644 --- a/tutorials/tutorial_4_connecting_split_keyboards.md +++ b/tutorials/tutorial_4_connecting_split_keyboards.md @@ -28,9 +28,10 @@ But if there are enough pins on the controller, using just a cable with more wir 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. +I2C is fast enough for scanning up to 5 rows. +SPI is much faster, but requires 2 additional wires. + +More scanning options are reviewed at http://www.openmusiclabs.com/learning/digital/input-matrix-scanning/ ## Cables table @@ -52,7 +53,7 @@ There are also wireless options if you don't mind adding complexity and maintain 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. +All the modular connector cables are available in the flat form factor. For prototyping on perfboards, consider a 0.1" header. diff --git a/tutorials/tutorial_4b_split_keyboard_with_shift_registers.md b/tutorials/tutorial_4b_split_keyboard_with_shift_registers.md index 0dc4623..f223ede 100644 --- a/tutorials/tutorial_4b_split_keyboard_with_shift_registers.md +++ b/tutorials/tutorial_4b_split_keyboard_with_shift_registers.md @@ -36,7 +36,7 @@ This table lists what gets connected to the 74HC165 pins: **74HC165 left (lower half of breadboard)** |NAME |PIN#|DESCRIPTION |TO TEENSY LC PIN#|CHAIN | -|--------|:--:|--------------------|-----------------|-----------| +|:-------|:--:|:-------------------|:----------------|:----------| |SH/LD |1 |shift or load input |CS0 10 |green wire | |CLK |2 |clock input |SCK0 13 |yellow wire| | D4 |3 |parallel input | | | @@ -49,7 +49,7 @@ This table lists what gets connected to the 74HC165 pins: **74HC165 right (upper half of breadboard)** |NAME |PIN#|DESCRIPTION |TO TEENSY LC PIN#|CHAIN | -|--------|:--:|--------------------|-----------------|-------------------------| +|:-------|:--:|:-------------------|:----------------|:------------------------| |VCC |16 |power pin |3.3V |red wire | |CLK INH |15 |clock inhibit | |blue bus | | D3 |14 |parallel input | | | diff --git a/tutorials/tutorial_4c_split_keyboard_with_IOE.md b/tutorials/tutorial_4c_split_keyboard_with_IOE.md index f9c5394..9b88a63 100644 --- a/tutorials/tutorial_4c_split_keyboard_with_IOE.md +++ b/tutorials/tutorial_4c_split_keyboard_with_IOE.md @@ -17,6 +17,31 @@ Two rows (red buses) are connected to the I/O expander. ![breadboard keyboard with IOE](keybrd_4c_split_keyboard_with_IOE/front.JPG "breadboard keyboard with IOE") +I/O expanders +------------- +The MCP23S17 I/O expander has two ports with 8 I/O pins each. +I/O expander input/output pins are connected to a switch matrix. +Port B strobes one row at a time. +Port A reads the columns. + +SPI and I2C communication protocols +----------------------------------- +SPI and I2C are popular communication protocols. +Either one can be used to connect split keyboards. + +I2C is fast enough for scanning up to 5 rows. +The keybrd_DH (DodoHand) sketch polls 5 rows over I2C at 7.5ms per keyboard scan. + +SPI is much faster, but requires 2 additional wires. +Use SPI if your key matrix has more then 5 rows. + +| connection type | controller pins | wire count | +|------------------------|:---------------:|:----------:| +| I/O expander SPI | 4 | 6 | +| I/O expander I2C | 2 | 4 | + +The example in this tutorial uses the SPI protocol. + 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. diff --git a/tutorials/tutorial_5a_LED_on_uC.md b/tutorials/tutorial_5a_LED_on_uC.md index b19641f..f35091b 100644 --- a/tutorials/tutorial_5a_LED_on_uC.md +++ b/tutorials/tutorial_5a_LED_on_uC.md @@ -39,7 +39,7 @@ 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 +LED current-limiting resistor values ------------------------------------ In the section we will compute the minimum resistor value for maximum LED brightness. diff --git a/tutorials/tutorial_5b_LED_on_IOE.md b/tutorials/tutorial_5b_LED_on_IOE.md index 5b1ffc1..d988838 100644 --- a/tutorials/tutorial_5b_LED_on_IOE.md +++ b/tutorials/tutorial_5b_LED_on_IOE.md @@ -26,7 +26,7 @@ keybrd sketch with LEDs on IOE ------------------------------ The [keybrd_5b_LED_on_IOE.ino](keybrd_5b_LED_on_IOE/keybrd_5b_LED_on_IOE.ino) sketch will run on the above breadboard keyboard. -The sketch features: +The sketch demonstrates: * multiple layers * split keyboard * LED on controller diff --git a/unit_tests/PortMCP23018_write/PortMCP23018_write.ino b/unit_tests/PortMCP23018_write/PortMCP23018_write.ino new file mode 100644 index 0000000..72281b8 --- /dev/null +++ b/unit_tests/PortMCP23018_write/PortMCP23018_write.ino @@ -0,0 +1,33 @@ +/* unit test for Port_MCP23018 +Picture of hardware is in unit_tests/PortMCP23018_read/PortMCP23018_bb.JPG todo +The setup is an MCP23018 I/O expander on a Teensy LC controller. +MCP23018 port-A GPIO pins are not connected to anything. +Port-A GPIO-pin ouputs alternate between 0 and 3.3 volts. +volt meter between pin A1 and power because + MCP23018 has open-drain outputs (open-drain can only sink current) + +Use a volt meter to measure port-A GPIO-pin outputs or red LED. +*/ +#include "Port_MCP23018.h" + +const uint8_t IOE_ADDR = 0x20; //MCP23018 address ADDR pin grounded +Port_MCP23018 portA(IOE_ADDR, 0, 0); + +void setup() +{ + delay(6000); + Keyboard.println("PortMCP23018_write.ino"); + portA.beginProtocol(); + portA.begin(LOW); //HIGH or LOW, not matter if readPins=0 +} + +void loop() +{ + portA.write(~0, HIGH); //set all GPIOA pins HIGH + Keyboard.print("+"); + delay(2000); + + portA.write(~0, LOW); //set all GPIOA pins LOW + Keyboard.print("0"); + delay(2000); +} diff --git a/unit_tests/PortMCP23S17_read/PortMCP23S17_read.ino b/unit_tests/PortMCP23S17_read/PortMCP23S17_read.ino index 65ef54d..87bdea4 100644 --- a/unit_tests/PortMCP23S17_read/PortMCP23S17_read.ino +++ b/unit_tests/PortMCP23S17_read/PortMCP23S17_read.ino @@ -2,28 +2,24 @@ Picture of hardware is in unit_tests/PortMCP23S17_read/PortMCP23S17_bb.JPG The setup is an MCP23S17 I/O expander on a Teensy LC controller. MCP23S17 port-B pins are alternately grounded and energized. -portBState is a bitwise reading of port B. output is: 10101010 */ -#include "PortIOE.h" -#include "PortMCP23S17.h" +#include "Port_MCP23S17.h" -const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded -PortIOE portB(1); - -PortMCP23S17 portBRead(portB, ~0); +const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins grounded +Port_MCP23S17 portB(IOE_ADDR, 1, ~0); //read all pins void setup() { - uint8_t portBState; //bit pattern + uint8_t BitPattern; //reading of port B delay(6000); - portBRead.begin(HIGH); //HIGH or LOW, not matter + portB.begin(HIGH); //HIGH or LOW, does not matter - portBState = portBRead.read(); - Keyboard.print("portBState = "); - Keyboard.println(portBState, BIN); //prints 10101010 + BitPattern = portB.read(); + Keyboard.print("BitPattern = "); + Keyboard.println(BitPattern, BIN); //prints 10101010 } void loop() { } diff --git a/unit_tests/PortMCP23S17_write/PortMCP23S17_write.ino b/unit_tests/PortMCP23S17_write/PortMCP23S17_write.ino index 2bb4307..35d83ee 100644 --- a/unit_tests/PortMCP23S17_write/PortMCP23S17_write.ino +++ b/unit_tests/PortMCP23S17_write/PortMCP23S17_write.ino @@ -1,34 +1,29 @@ -/* unit test for PortMCP23S17 +/* unit test for Port_MCP23S17 Picture of hardware is in unit_tests/PortMCP23S17_read/PortMCP23S17_bb.JPG The setup is an MCP23S17 I/O expander on a Teensy LC controller. MCP23S17 port-A GPIO pins are not connected to anything. Port-A GPIO-pin ouputs alternate between 0 and 3.3 volts. -Use a volt meter to measure port-A GPIO-pin outputs. -OR low-voltage LED, with forward voltage less than 2 volts. +Use a volt meter to measure port-A GPIO-pin outputs or red LED. */ -#include "PortIOE.h" -#include "PortMCP23S17.h" +#include "Port_MCP23S17.h" -const uint8_t PortIOE::DEVICE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded -PortIOE portA(0); - -PortMCP23S17 portAWrite(portA, 0); //PortAWrite needed for begin() - -//const uint8_t GPIOA = 0x12; //LEDs are on port A +const uint8_t IOE_ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins grounded +Port_MCP23S17 portA(IOE_ADDR , 0, 0); //PortAWrite needed for begin() void setup() { delay(6000); - portAWrite.begin(LOW); //HIGH or LOW, not matter if readPins=0 - Keyboard.print("start writing"); + Keyboard.println("start setup"); + portA.begin(LOW); //HIGH or LOW, not matter if readPins=0 + Keyboard.println("start loop"); } void loop() { - portAWrite.write(~0, HIGH); //set all GPIOA pins HIGH + portA.write(~0, HIGH); //set all GPIOA pins HIGH delay(2000); - portAWrite.write(~0, LOW); //set all GPIOA pins LOW + portA.write(~0, LOW); //set all GPIOA pins LOW delay(2000); }