add MCP23S17 port files
This commit is contained in:
parent
997942555d
commit
caa29dec63
@ -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.
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
src/PortRead_MCP23S17.cpp
Normal file
23
src/PortRead_MCP23S17.cpp
Normal 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
src/PortRead_MCP23S17.h
Normal file
42
src/PortRead_MCP23S17.h
Normal 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
src/PortWrite_MCP23S17.cpp
Normal file
50
src/PortWrite_MCP23S17.cpp
Normal 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
src/PortWrite_MCP23S17.h
Normal file
46
src/PortWrite_MCP23S17.h
Normal 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
|
@ -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
src/Row_IOE.cpp
Normal file
12
src/Row_IOE.cpp
Normal 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
src/Row_IOE.h
Normal file
26
src/Row_IOE.h
Normal 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
|
@ -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:
|
||||
|
Binary file not shown.
@ -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 ####################
|
||||
|
@ -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
tutorials/keybrd_4c_split_with_IOE/keybrd_4c_split_with_IOE.ino
Normal file
105
tutorials/keybrd_4c_split_with_IOE/keybrd_4c_split_with_IOE.ino
Normal 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();
|
||||
}
|
@ -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>.
|
||||
|
@ -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
tutorials/tutorial_8c_sharing_your_keybrd_sketch.md
Normal file
17
tutorials/tutorial_8c_sharing_your_keybrd_sketch.md
Normal 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
unit_tests/MCP23S17_read/MCP23S17_read.ino
Normal file
42
unit_tests/MCP23S17_read/MCP23S17_read.ino
Normal 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
unit_tests/MCP23S17_write/MCP23S17_write.ino
Normal file
54
unit_tests/MCP23S17_write/MCP23S17_write.ino
Normal 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
unit_tests/PortRead_MCP23S17/PortRead_MCP23S17.ino
Normal file
32
unit_tests/PortRead_MCP23S17/PortRead_MCP23S17.ino
Normal 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
unit_tests/PortWrite_MCP23S17/PortWrite_MCP23S17.ino
Normal file
35
unit_tests/PortWrite_MCP23S17/PortWrite_MCP23S17.ino
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user