Browse Source

add MCP23S17 port files

tags/v0.6.0
wolfv6 7 years ago
parent
commit
caa29dec63

+ 6
- 3
CONTRIBUTING.md View File

@@ -7,8 +7,9 @@ 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)
Submit improvement suggestions to [GitHub issues](https://github.com/wolfv6/Keybrd/issues).
* The issue title should start with "suggestion:" followed by a descriptive title
Submit improvement suggestions to [GitHub issues](https://github.com/wolfv6/Keybrd/issues)
or [geekhack thread](https://geekhack.org/index.php?topic=83599.0).
<!-- * The issue title should start with "suggestion:" followed by a descriptive title -->
* Provide a use case
* Explain why the improvement is useful
* Site other product examples where this improvement exists
@@ -16,6 +17,8 @@ Submit improvement suggestions to [GitHub issues](https://github.com/wolfv6/Keyb
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)
or [geekhack thread](https://geekhack.org/index.php?topic=83599.0).
Please provide enough information so we can reproduce the bug behaviour!
* Complete sketch (copy & paste, attachment, or a link to the code)
@@ -52,7 +55,7 @@ A healthy project needs the perspective of many people.
* 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.0) highlights contributions that are needed for the keybrd project's current stage of development.
* [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.

+ 18
- 18
doc/keybrd_library_developer_guide.md View File

@@ -27,7 +27,7 @@ Row_Ext::keyWasPressed() overrides Row::keyWasPressed() which is used to unstick
Row_Ext_uC and Row_Ext_ShiftRegisters are a custom classes composed of stock keybrd library classes.<br>
Row_Ext_uC uses Scanner_uC to scan the primary matrix.<br>
Row_Ext_ShiftRegisters uses Scanner_ShiftRegs74HC165 to scan the secondary matrix.
Row_Ext_ShiftRegisters uses Scanner_ShiftRegs74HC165 to scan the peripheral matrix.
Class inheritance diagram
```
@@ -68,7 +68,7 @@ Keybrd library class inheritance diagram
```
________ Row ___________
/ | \
Row_uC Row_ShiftRegisters Row_IOE (to be added)
Row_uC Row_ShiftRegisters Row_IOE (todo to be added)
Scanner_uC Scanner_Port Scanner_ShiftRegs74HC165
@@ -78,7 +78,7 @@ Keybrd library class inheritance diagram
PortWrite
|
PortWrite_PCA9655E (one PortWrite class for each IOE type)
PortWrite_PCA9655E (one PortWrite class for each IOE type)
PortRead
|
@@ -115,9 +115,9 @@ Keybrd library class inheritance diagram
| | |
| Code_LayeredScSc Code_LayeredCodeSc
|
|__________________________________________
\ \ \ \
Code_Sc Code_Shift Code_AutoShift Code_LEDLock
|_________________________________________________________
\ \ \ \ \
Code_Sc Code_Shift Code_AutoShift Code_LEDLock Code_Null
/ \
Code_ScS Code_ScNS
@@ -149,7 +149,7 @@ Dependency diagram of example multi-layer keyboard with layer LEDs
```
Dependency diagram of example secondary matrix with shift registers
Dependency diagram of example peripheral matrix with shift registers
```
Row_ShiftRegisters[1..*]
/ \ \
@@ -159,17 +159,17 @@ Dependency diagram of example secondary matrix with shift registers
```
Dependency diagram of example secondary matrix with I/O Expander and LEDs
Dependency diagram of example peripheral matrix with I/O Expander and LEDs
```
___ Row_IOE[1..*] _________
/ \ \
_ Scanner_Port[1] _ Debouncer[1] Keys[1..*] __
/ | \ | \
PortWrite[1] RowPin[1] PortRead[1] Code[1..*] Code_LEDLock[1..*]
\ / \ |
\ / ColPins[1..*] LED[1]
\ /
PortIOE[0..*]
_____ Row_IOE[1..*] _________
/ \ \
__ Scanner_Port[1] __ Debouncer[1] Keys[1..*] __
/ | \ | \
PortWrite[1] strobePin[1] PortRead[1] Code[1..*] Code_LEDLock[1..*]
\ / \ |
\ / ColPins[1..*] LED[1]
\ /
PortIOE[0..*]
```
@@ -243,7 +243,7 @@ Following the style guide makes it easier for the next programmer to understand
Trace of keybrd scan
--------------------
Arduino does not have a debugger.
So here is the next best thing; a list of functions in the order that they are called.
So here is a list of functions in the order that they are called.
The trace is of a one-row single-layer keybrd scan.
Refer to it like a table of contents while reading the keybrd library.

+ 1
- 1
src/PortRead.h View File

@@ -13,7 +13,7 @@ Details are in config_key.h
class PortRead
{
protected:
const uint8_t readPins; //bitwise pin configuration, 1 means read column
const uint8_t readPins; //bitwise pin configuration, 1 means read pin
public:
PortRead(const uint8_t readPins): readPins(readPins) {}
virtual uint8_t read()=0;

+ 23
- 0
src/PortRead_MCP23S17.cpp View File

@@ -0,0 +1,23 @@
#include "PortRead_MCP23S17.h"
/*
PortRead_MCP23S17::begin() is not needed because port direction is already configured to input by default.
SPI bus is configured in PortWrite_MCP23S17::begin().
*/
/*
returns port value
*/
uint8_t PortRead_MCP23S17::read()
{
uint8_t portState; //bit wise
//slower clock
digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(port.ADDR << 1 | 1); //read command
SPI.transfer(port.num + 0x12); //register address to read data from
portState = SPI.transfer(0); //save the data (0 is dummy data to send)
digitalWrite(SS, HIGH); //disable Slave Select
return portState;
}

+ 42
- 0
src/PortRead_MCP23S17.h View File

@@ -0,0 +1,42 @@
#ifndef PORTREAD_MCP23S17_H
#define PORTREAD_MCP23S17_H
#include <Arduino.h>
#include <inttypes.h>
#include <SPI.h>
#include <PortRead.h>
#include "PortIOE.h"
/* One MCP23S17 I/O expander port connected to matrix columns.
MCP23S17 does not have internal pull-up resistors (PCA9535E does).
Instantiation
------------
readPins parameter is port's bitwise pin configuration
1=configure as input (for pins connected to column)
0=configure as output (for LED or not connected to a column)
Example instantiation for column port 0, with pins 2 and 3 connected to columns:
PortIOE port0(0, 0);
PortRead_MCP23S17 colPort0(port0, 2<<0 | 1<<3 );
Example instantiation for column port 1, with pins 2 and 3 connected to columns:
PortIOE port1(1, 0);
PortRead_MCP23S17 colPort1(port1, 2<<0 | 1<<3 );
readPins are read from pin 0 on up.
*/
class PortRead_MCP23S17 : public PortRead
{
private:
PortIOE& port;
public:
/*
todo not all PortRead_ classes need a readPins
move PortRead::readPins from PortRead to PortRead_PCA9655E
remove PortRead(0) initialization from this constructor
*/
//The constructor initialization list is in .cpp
PortRead_MCP23S17(PortIOE& port) : PortRead(0), port(port) {}
virtual uint8_t read();
};
#endif

+ 50
- 0
src/PortWrite_MCP23S17.cpp View File

@@ -0,0 +1,50 @@
#include "PortWrite_MCP23S17.h"
void PortWrite_MCP23S17::writePort(const uint8_t registerAddr, const uint8_t data)
{
//slower clock
//SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //control SPI bus todo move to begin()
digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(port.ADDR << 1); //write command
SPI.transfer(registerAddr); //register address to write data to
SPI.transfer(data); //data
digitalWrite(SS, HIGH); //disable Slave Select
//SPI.endTransaction(); //release the SPI bus
}
/*
If PortRead_MCP23S17 is instantiated on the same port, do NOT use PortWrite_MCP23S17::begin().
Otherwise readPins could be overwritten.
Output pins can be used for strobe pins and LEDs.
SPI.endTransaction() is not called because keyboard only has one SPI device, so no need to release the SPI bus
*/
void PortWrite_MCP23S17::begin()
{
pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output
digitalWrite(SS, HIGH); //disable Slave Select
SPI.begin();
SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //control SPI bus
writePort(port.num, 0); //configure port direction (port.num) to output (0)
}
/*
pin is bitwise, where pin being strobed is 1.
strobe is HIGH or LOW (for active high or active low).
port.outputVal can be shared by LEDs.
The functions does not reset the other pins so that they can be used for LEDs.
*/
void PortWrite_MCP23S17::write(const uint8_t pin, const bool strobe)
{
if (strobe == LOW) //if active low
{
port.outputVal &= ~pin; //set pin output to low
}
else //if active high
{
port.outputVal |= pin; //set pin output to high
}
writePort(port.num + 0x12, port.outputVal); //set GPIO port pins for stobe and LEDs
}

+ 46
- 0
src/PortWrite_MCP23S17.h View File

@@ -0,0 +1,46 @@
#ifndef PORTWRITE_MCP23S17_H
#define PORTWRITE_MCP23S17_H
#include <Arduino.h>
#include <inttypes.h>
#include <SPI.h>
#include <PortWrite.h>
#include "PortIOE.h"
/* One MCP23S17 I/O expander port connected to matrix rows.
MCP23S17 does not have internal pull-up resistors (PCA9535E does).
begin() configures column port's configuration and output.
This should normally be called once in sketch's setup().
If PortRead_MCP23S17 is instantiated on the same port, do NOT use PortWrite_MCP23S17::begin().
Otherwise readPins could be overwritten.
Instantiation
------------
Example instantiation for row port 0:
PortIOE port0(0, 0);
PortWrite_MCP23S17 rowPort0(port0);
Example instantiation for row port 1:
PortIOE port1(1, 0);
PortWrite_MCP23S17 rowPort1(port1);
Diode orientation
----------------
Diode orientation is explained in keybrd_library_user_guide.md > Diode orientation
MCP23S17 data sheet
----------------
http://www.onsemi.com/pub_link/Collateral/MCP23S17-D.PDF
*/
class PortWrite_MCP23S17 : public PortWrite
{
private:
PortIOE& port;
void writePort(const uint8_t registerAddr, const uint8_t data);
public:
PortWrite_MCP23S17(PortIOE& port) : port(port) {}
void begin();
virtual void write(const uint8_t pin, const bool level);
};
#endif

+ 1
- 2
src/Row.h View File

@@ -14,8 +14,7 @@ class Row
Key *const *const ptrsKeys; //array of Key pointers
virtual void keyWasPressed();
protected:
read_pins_t debounced; //bitwise state of keys after debouncing
// 1 means pressed, 0 means released
read_pins_t debounced; //bitwise state of keys after debouncing, 1=pressed, 0=released
void send(const uint8_t readPinCount, const read_pins_t debouncedChanged);
public:
Row(Key* const ptrsKeys[]) : ptrsKeys(ptrsKeys), debounced(0) { }

+ 12
- 0
src/Row_IOE.cpp View File

@@ -0,0 +1,12 @@
#include "Row_IOE.h"

void Row_IOE::process()
{
//these variables are all bitwise, one bit per key
uint8_t readState; //1 means pressed, 0 means released
uint8_t debouncedChanged; //1 means debounced changed

readState = scanner.scan();
debouncedChanged = debouncer.debounce(readState, debounced);
send(readPinCount, debouncedChanged);
}

+ 26
- 0
src/Row_IOE.h View File

@@ -0,0 +1,26 @@
#ifndef ROW_IOE_H
#define ROW_IOE_H

#include <Row.h>
#include <Scanner_Port.h>
#include <Debouncer_Samples.h>
class PortWrite;
class PortRead;

/* Row_IOE is a row connected to an Input/Output Expander.
Configuration and Instantiation instructions are in keybrd/src/Row_IOE.h
*/
class Row_IOE : public Row
{
private:
Scanner_Port scanner;
Debouncer_Samples debouncer;
const uint8_t readPinCount; //number of read pins
public:
Row_IOE(PortWrite& refPortWrite, const uint8_t strobePin,
PortRead& refPortRead, const uint8_t readPinCount, Key *const ptrsKeys[])
: Row(ptrsKeys), scanner(refPortWrite, strobePin, refPortRead),
readPinCount(readPinCount) { }
void process();
};
#endif

+ 1
- 1
src/Scanner_ShiftRegs74HC165.h View File

@@ -13,7 +13,7 @@ shift registers 74HC165 are Parallel-In-Serial-Out (PISO)
Upto 4 shift registers can be in a daisy chained for a total of 32 read pins.

For active low:
Shift register parallel input pins have 10k pull-down resistors powered
Shift register parallel input pins have 10k pull-up resistors powered
Orient diodes with cathode (banded end) towards the write pins (row)
Controller's MISO pin is connected to shift register's complementary serial output (/QH) pin
Use these two lines in the sketch:

BIN
tutorials/breadboard_keyboard_supplies.ods View File


+ 1
- 1
tutorials/keybrd_1_breadboard/keybrd_1_breadboard.ino View File

@@ -32,7 +32,7 @@ Code_Sc s_c(KEY_C);
Key* ptrsKeys_0[] = { &s_1, &s_a };
Row_uC row_0(0, readPins, READ_PIN_COUNT, ptrsKeys_0);

Key* ptrsKeys_1[] = { &s_b, &s_c };
Key* ptrsKeys_1[] = { &s_b, &s_c };
Row_uC row_1(1, readPins, READ_PIN_COUNT, ptrsKeys_1);

// ################### MAIN ####################

+ 96
- 0
tutorials/keybrd_4b_split_keyboard_with_shift_registers/keybrd_4b_split_keyboard_with_shift_registers.ino View File

@@ -0,0 +1,96 @@
/* tutorial_4a_split_keyboard_with_shift_registers.ino
Tested on Teensy LC and two 74HC165 shift registers.

The right matrix has 2 shift registers daisy chained.

Layout Layout
| Left |**0** | Right |**0**|**1**|**2**|**3**|**4**|**5**|**6**|**7**|
|:-----:|-----| |:-----:|-----|-----|-----|-----|-----|-----|-----|-----|
| **0** | x | | **0** | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| **1** | y | | **1** | a | b | c | d | e | f | g | h |
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
#include <ScanDelay.h>
#include <Code_Sc.h>

//Left matrix
#include <Row_uC.h>

//Right matrix
#include <SPI.h>
#include <Row_ShiftRegisters.h>

// =============== CONFIGURATION ===============
ScanDelay scanDelay(9000);

// =================== CODES ===================
Code_Sc s_a(KEY_A);
Code_Sc s_b(KEY_B);
Code_Sc s_c(KEY_C);
Code_Sc s_d(KEY_D);
Code_Sc s_e(KEY_E);
Code_Sc s_f(KEY_F);
Code_Sc s_g(KEY_G);

Code_Sc s_x(KEY_X);
Code_Sc s_y(KEY_Y);

Code_Sc s_0(KEY_0);
Code_Sc s_1(KEY_1);
Code_Sc s_2(KEY_2);
Code_Sc s_3(KEY_3);
Code_Sc s_4(KEY_4);
Code_Sc s_5(KEY_5);
Code_Sc s_6(KEY_6);

// =============== LEFT MATRIX =================
//set left matrix for active low
const bool Scanner_uC::STROBE_ON = LOW;
const bool Scanner_uC::STROBE_OFF = HIGH;

//column pin
uint8_t readPins[] = {14};
uint8_t READ_PIN_COUNT = sizeof(readPins)/sizeof(*readPins);

//rows
Key* ptrsKeys_L0[] = { &s_x };
Row_uC row_L0(0, readPins, READ_PIN_COUNT, ptrsKeys_L0);

Key* ptrsKeys_L1[] = { &s_y };
Row_uC row_L1(1, readPins, READ_PIN_COUNT, ptrsKeys_L1);

// =============== RIGHT MATRIX ================
//set matrix to active high
const bool Scanner_ShiftRegs74HC165::STROBE_ON = HIGH;
const bool Scanner_ShiftRegs74HC165::STROBE_OFF = LOW;

//chip select pin
const uint8_t Scanner_ShiftRegs74HC165::SHIFT_LOAD = 10;

//rows
Key* ptrsKeys_R0[] = { &s_6, &s_5, &s_4, &s_3, //shift regiser on right
&s_c, &s_d, &s_e, &s_f,
&s_2, &s_1, &s_0, &s_g, //shift regiser on left
&s_a, &s_b }; //unused input pins are grounded
Row_ShiftRegisters row_R0(0, sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0), ptrsKeys_R0);

// ################### MAIN ####################
void setup()
{
Keyboard.begin();
SPI.begin();
row_R0.begin();
}

void loop()
{
//left matrix
row_L0.process();
row_L1.process();

//right matrix
row_R0.process();

scanDelay.delay();
}

+ 105
- 0
tutorials/keybrd_4c_split_with_IOE/keybrd_4c_split_with_IOE.ino View File

@@ -0,0 +1,105 @@
/* keybrd_4c_split_with_IOE_annotated.ino

| Left | **0** | **1** | | Right | **0** | **1** |
|:-----:|-------|-------| |:-----:|-------|-------|
| **0** | a | b | | **0** | 1 | 2 |
| **1** | shift | c | | **1** | 3 | shift |

| Left | **0** | **1** | | Right | **0** | **1** | todo
|:-----:|-------|-------| |:-----:|-------|-------|
| **1** | 1 | 2 | | **1** | 3 | 4 |
| **0** | a | b | | **0** | c | d |
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
#include <ScanDelay.h>
#include <Code_Sc.h>

//left matrix
#include <Row_uC.h>

//right matrix
#include <Row_IOE.h>
#include <PortIOE.h>
#include <PortWrite_MCP23S17.h>
#include <PortRead_MCP23S17.h>

// ============ SPEED CONFIGURATION ============
ScanDelay scanDelay(9000);

// ================ LEFT MATRIX ================
// ---------------- ACTIVE STATE ---------------
const bool Scanner_uC::STROBE_ON = LOW; //active low
const bool Scanner_uC::STROBE_OFF = HIGH;

// ------------------- PINS --------------------
uint8_t readPins[] = {14, 15};

// ================ RIGHT MATRIX ===============
const bool Scanner_Port::STROBE_ON = HIGH; //active high
const bool Scanner_Port::STROBE_OFF = LOW;

const uint8_t PortIOE::ADDR = 0x18;

// ------------------ PORT 1 -------------------
PortIOE port1_R(1, 0);
PortWrite_MCP23S17 portWrite1_R(port1_R);

// ------------------ PORT 0 -------------------
PortIOE port0_R(0, 0);
PortWrite_MCP23S17 portWrite0_R(port0_R);
PortRead_MCP23S17 portRead0_R(port0_R, 1<<0 | 1<<1 );

// =================== CODES ===================
Code_Sc s_shiftL(MODIFIERKEY_LEFT_SHIFT);
Code_Sc s_shiftR(MODIFIERKEY_RIGHT_SHIFT);

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);
Code_Sc s_3(KEY_3);

// =================== ROWS ====================
// ---------------- LEFT ROWS ------------------
Key* ptrsKeys_L0[] = { &s_a, &s_b };
const uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0);
Row_uC row_L0(0, readPins, KEY_COUNT_L0, ptrsKeys_L0);

Key* ptrsKeys_L1[] = { &s_c, &s_shiftL };
const uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1);
Row_uC row_L1(1, readPins, KEY_COUNT_L1, ptrsKeys_L1);

// ---------------- RIGHT ROWS -----------------
Key* ptrsKeys_R0[] = { &s_1, &s_2 };
const uint8_t KEY_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row_IOE row_R0(portWrite1_R, 1<<0, portRead0_R, KEY_COUNT_R0, ptrsKeys_R0);

Key* ptrsKeys_R1[] = { &s_3, &s_shiftR };
const uint8_t KEY_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1);
Row_IOE row_R1(portWrite1_R, 1<<1, portRead0_R, KEY_COUNT_R1, ptrsKeys_R1);

// ################### MAIN ####################
void setup()
{
Keyboard.begin();
Wire.begin(); //Wire.begin() must be called before port begin()
portWrite1_R.begin();
portRead0_R.begin();
}

void loop()
{
//left matrix
row_L0.process();
row_L1.process();

//right matrix
row_R0.process();
row_R1.process();

scanDelay.delay();
//debug.print_scans_per_second();
//debug.print_microseconds_per_scan();
}

+ 32
- 13
tutorials/tutorial_10_writing_IOE_Port_classes.md View File

@@ -1,19 +1,38 @@
Tutorial 10 - writing IOE Port classes
===========================================
Tutorial 10 - writing new IOE Port classes
==========================================
Port classes are the keybrd library's interface to I/O expander ports.

To write your own Port class:
To write a new Port class:

1. Get a copy of the I/O expander datasheet.
2. Study other keybrd Port classes.

For example, the keybrd_DH library uses these keybrd classes for its PCA9655E I/O expander:
* PortWrite_PCA9655E
* PortRead_PCA9655E
* LED_PCA9655E

Debugging I/O expander code is hard because SPI or I2C protocol adds a level of indirection.
If you haven't written Arduino code for an I/O expander before, learn from an Arduiono I/O expander tutorial before attempting it here.
1. Get a copy of the I/O expander's datasheet.
2. An I/O expander will use one of two communication protocols: [http://www.byteparadigm.com/applications/introduction-to-i2c-and-spi-protocols/](SPI or I2C).
Refer to the [Arduino SPI](https://www.arduino.cc/en/Reference/SPI)
or [Arduino Wire (I2C)](https://www.arduino.cc/en/Reference/Wire) library
3. Get familiar with your I/O expander.
Different I/O expanders use different commands (a.k.a. operation codes).
Refer to your I/O expander's datasheet for read and write commands.
Search for Arduino sketch examples containing your I/O expander
([sumotoy](https://github.com/sumotoy/gpio_expander) has a large gpio expander library).
Write very simple read and write examples for your I/O expander.
Simple SPI I/O expander examples:
todo link, pictures
/home/wolfv/Documents/Arduino/demo/IOE_MCP23S17_read/
/home/wolfv/Documents/Arduino/demo/IOE_MCP23S17_write/
Simple I2C I/O expander examples:
todo link, pictures
read
write
4. Study other keybrd Port classes.
Port classes for SPI MCP23S17 I/O expander:
*todo
*
*
Port classes for I2C PCA9655E I/O expander:
* PortWrite_PCA9655E todo link
* PortRead_PCA9655E
* LED_PCA9655E
5. Write similar Port classes for your I/O expander.
Debugging I/O expander code is hard because SPI or I2C protocol adds a level of indirection.

<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>.

tutorials/tutorial_8b_creating_and_publishing_your_own_keybrd_extension_library.md → tutorials/tutorial_8b_sharing_your_keybrd_extension_library.md View File

@@ -1,12 +1,12 @@
Tutorial 8b - creating and publishing your own keybrd extension library
=======================================================================
Tutorial 8b - sharing your keybrd extension library
===================================================
Publishing and listing your keybrd extension library allows others to find and install your library.
The keybrd extension library name should start with "keybrd_" so that it is easy for other people to find.

There are two ways to publish and list an Arduino library.

Publishing anywhere with listing on Arduino Playground LibraryList
------------------------------------------------------------------
Publish anywhere and list on Arduino Playground
-----------------------------------------------
Publishing your keybrd extension library with the following directory structure makes it easy for others to understand.

keybrd_MyKeyboard/
@@ -25,16 +25,13 @@ Publishing your keybrd extension library with the following directory structure
instantiations_codes.h
instantiations_rows.h

When your ready to list your keybrd extension library, go to the [Arduino Playground keybrd page](http://playground.arduino.cc/Main/keybrd).
When your ready to list your keybrd extension library,
add a link and short description of your keybrd extension library to the [Arduino Playground keybrd page](http://playground.arduino.cc/Main/keybrd) under "keybrd extension libraries".
Arduino playground is a wiki.
Links on how to edit the wiki are on the bottom left under "Participate".

You can also add a picture of a keyboard that uses your keybrd extension library.
Uploading files to the Playground is not allowed for standard users.
So if you want to add a picture, it will need to be hosted somewhere else.

Publishing on GitHub with listing on Arduino Library-Manager and Arduino Playground LibraryList
-----------------------------------------------------------------------------------------------
Publish on GitHub and list on Arduino Library-Manager and Arduino Playground
----------------------------------------------------------------------------
The advantage of using GitHub is that users can submit pull requests.
The advantage of using Arduino Library-Manager is that users can easily find and install your library through the Arduino IDE.

@@ -78,14 +75,11 @@ Example library.properties file:
Instructions for listing a library on Arduino Library Manager are at:
https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ

After it has been accepted into the Arduino IDE Library Manager, add your keybrd extension library to the [Arduino Playground keybrd page](http://playground.arduino.cc/Main/keybrd).
After it has been accepted into the Arduino IDE Library Manager,
add a link and short description of your keybrd extension library to the [Arduino Playground keybrd page](http://playground.arduino.cc/Main/keybrd) under "keybrd extension libraries".
Arduino playground is a wiki.
Links on how to edit the wiki are on the bottom left under "Participate".

You can also add a picture of a keyboard that uses your keybrd extension library.
Uploading files to the Playground is not allowed for standard users.
So if you want to add a picture, it will need to be hosted somewhere else.

To publish a new release of a library that is already listed on Arduino Library Manager

1. Update the version in your library.properties file:

+ 17
- 0
tutorials/tutorial_8c_sharing_your_keybrd_sketch.md View File

@@ -0,0 +1,17 @@
Tutorial 8c - sharing your keybrd sketch
========================================
keybrd sketches that use a keybrd extension library should be published in the extension library's examples directory.
keybrd sketches that do not use a keybrd extension library can be published anywhere.

Publishing and listing your keybrd sketch allows others to find your sketch.

Publish anywhere and list on Arduino Playground
-----------------------------------------------
Publish your sketch anywhere. Some free places are:
* GitHub repository
* [GitHub Gist](https://help.github.com/categories/gists/)
* [geekhack Making Stuff Together!](https://geekhack.org/index.php?board=117.0)

Then add a link and short description of your keybrd sketch to the [Arduino Playground keybrd page](http://playground.arduino.cc/Main/keybrd) under "keybrd sketches".
Arduino playground is a wiki.
Links on how to edit the wiki are on the bottom left under "Participate".

+ 42
- 0
unit_tests/MCP23S17_read/MCP23S17_read.ino View File

@@ -0,0 +1,42 @@
/* this works
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

posted on http://arduino.stackexchange.com/questions/tagged/spi
http://arduino.stackexchange.com/questions/28792/reading-an-mcp23s17-i-o-expander-port-with-the-arduino-spi-library
*/
#include <SPI.h>

const uint8_t ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded
const uint8_t OPCODE_READ = (ADDR << 1 | 0x01); //MCP23S17 opcode read has LSB set

const uint8_t IODIRB = 0x01;
const uint8_t GPIOB = 0x13;

uint8_t portBState = 0; //bit wise

void setup()
{
Serial.begin(9600);
delay(1000);

pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output
digitalWrite(SS, HIGH); //disable Slave Select
SPI.begin();

//IODIRB register is already configured to input by default

SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //gain control of SPI bus
digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(OPCODE_READ); //read command
SPI.transfer(GPIOB); //register address to read data from
portBState = SPI.transfer(0); //save the data (0 is dummy data to send)
digitalWrite(SS, HIGH); //disable Slave Select
SPI.endTransaction(); //release the SPI bus

Serial.println(portBState, BIN); //should print 10101010
}

void loop() { }

+ 54
- 0
unit_tests/MCP23S17_write/MCP23S17_write.ino View File

@@ -0,0 +1,54 @@
/* this works with volt meter (MCP23S17 on 3.3v does not output enough power for LEDs)
LED lights w/o resistor, not light with 56 ohm resistor
blink LED on MCP23S17 port A pin
from Example 41.1 - Microchip MCP23017 with Arduino
http://tronixstuff.com/tutorials > chapter 41
http://tronixstuff.com/2011/08/26/tutorial-maximising-your-arduinos-io-ports/
John Boxall | CC by-sa-nc
from http://69.5.26.215/forum/?id=10945&page=3 #35
modified to test MCP23S17 (SPI) using syntax from
http://arduino.stackexchange.com/questions/16348/how-do-you-use-spi-on-an-arduino
>

SPISettings from http://arduino.stackexchange.com/questions/14191/mcp23s17-programming-iodirx-register-works-in-loop-but-not-in-setup
*/
#include <SPI.h>

const uint8_t ADDR = 0x20; //MCP23S17 address, all ADDR pins are grounded
const uint8_t OPCODE_WRITE = (ADDR << 1); //MCP23S17 opcode write has LSB clear

const uint8_t IODIRA = 0x00; //LEDs are on port A
const uint8_t GPIOA = 0x12;

uint8_t LED_state = 0; //bit wise

void IOEWrite(const uint8_t registerAddr, const uint8_t data)
{
SPI.beginTransaction(SPISettings (SPI_CLOCK_DIV8, MSBFIRST, SPI_MODE0)); //slower clock
digitalWrite(SS, LOW); //enable Slave Select
SPI.transfer(OPCODE_WRITE); //write command
SPI.transfer(registerAddr); //register address to write data to
SPI.transfer(data); //data
digitalWrite(SS, HIGH); //disable Slave Select
SPI.endTransaction(); //release the SPI bus
}

void setup()
{
Serial.begin(9600);

pinMode(SS, OUTPUT); //configure controller's Slave Select pin to output
digitalWrite(SS, HIGH); //disable Slave Select
SPI.begin();

IOEWrite(IODIRA, 0x00); //configure IODIRA register to output
}

void loop()
{
IOEWrite(GPIOA, LED_state); //set all GPIOA pins

delay(2000);
//Serial.println(LED_state, BIN); //prints alternating 0 and 11111111
LED_state = ~LED_state; //toggle LED on/off
}

+ 32
- 0
unit_tests/PortRead_MCP23S17/PortRead_MCP23S17.ino View File

@@ -0,0 +1,32 @@
/* unit test for PortRead_MCP23S17
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

posted on http://arduino.stackexchange.com/questions/tagged/spi
http://arduino.stackexchange.com/questions/28792/reading-an-mcp23s17-i-o-expander-port-with-the-arduino-spi-library
*/
#include "PortIOE.h"
#include "PortRead_MCP23S17.h"
#include "PortWrite_MCP23S17.h"

const uint8_t PortIOE::ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded
PortIOE portB(1, 0);

PortRead_MCP23S17 portBRead(portB);
PortWrite_MCP23S17 portBWrite(portB); //PortBWrite needed for begin()

void setup()
{
uint8_t portBState; //bit wise

delay(6000);
portBWrite.begin();

portBState = portBRead.read();
Keyboard.print("portBState = ");
Keyboard.println(portBState, BIN); //should print 10101010
}

void loop() { }

+ 35
- 0
unit_tests/PortWrite_MCP23S17/PortWrite_MCP23S17.ino View File

@@ -0,0 +1,35 @@
/* unit test for PortRead_MCP23S17
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 ouputs.
MCP23S17 on 3.3v does not output enough power to reliable light LEDs
LED lights w/o resistor
LED not light with 56 ohm resistor
*/
#include "PortIOE.h"
#include "PortWrite_MCP23S17.h"

const uint8_t PortIOE::ADDR = 0x20; //MCP23S17 address, all 3 ADDR pins are grounded
PortIOE portA(0, 0);

PortWrite_MCP23S17 portAWrite(portA); //PortAWrite needed for begin()

const uint8_t GPIOA = 0x12; //LEDs are on port A

void setup()
{
delay(6000);
portAWrite.begin();
//Keyboard.print("start blinking");
}

void loop()
{
portAWrite.write(~0, HIGH); //set all GPIOA pins HIGH
delay(2000);

portAWrite.write(~0, LOW); //set all GPIOA pins LOW
delay(2000);
}