Browse Source

move IOE_scan_development and unit_tests to examples, add examples/IOE_PCA9655E_development/

tags/v0.6.4
wolfv6 7 years ago
parent
commit
e9e74634a4
36 changed files with 326 additions and 358 deletions
  1. BIN
      IOE_scan_development/IOE_scan_development.ods
  2. BIN
      IOE_scan_development/openDrain_activeLow/back.JPG
  3. BIN
      IOE_scan_development/openDrain_activeLow/front.JPG
  4. 0
    69
      IOE_scan_development/openDrain_activeLow/openDrain_activeLow.ino
  5. BIN
      IOE_scan_development/source_activeHigh/DSCF0003.JPG
  6. BIN
      IOE_scan_development/source_activeHigh/DSCF0004.JPG
  7. 0
    69
      IOE_scan_development/source_activeHigh/source_activeHigh.ino
  8. BIN
      IOE_scan_development/source_activeLow/back.JPG
  9. BIN
      IOE_scan_development/source_activeLow/front.JPG
  10. 0
    68
      IOE_scan_development/source_activeLow/source_activeLow.ino
  11. 58
    0
      examples/IOE_PCA9655E_development/PCA9655E_1_write_read/PCA9655E_1_write_read.ino
  12. BIN
      examples/IOE_PCA9655E_development/PCA9655E_1_write_read/back.JPG
  13. BIN
      examples/IOE_PCA9655E_development/PCA9655E_1_write_read/front.JPG
  14. BIN
      examples/IOE_PCA9655E_development/PCA9655E_2_scan/DSCF0001.JPG
  15. BIN
      examples/IOE_PCA9655E_development/PCA9655E_2_scan/DSCF0002.JPG
  16. 56
    0
      examples/IOE_PCA9655E_development/PCA9655E_2_scan/PCA9655E_2_scan.ino
  17. 45
    0
      examples/IOE_PCA9655E_development/PCA9655E_3_scan_lib/PCA9655E_3_scan_lib.ino
  18. 86
    0
      examples/IOE_PCA9655E_development/PCA9655E_4_scan_loop/PCA9655E_4_scan_loop.ino
  19. BIN
      examples/IOE_PCA9655E_development/PCA9655E_5_keybrd/back.JPG
  20. BIN
      examples/IOE_PCA9655E_development/PCA9655E_5_keybrd/front.JPG
  21. 45
    22
      examples/IOE_PCA9655E_development/PCA9655E_5_keybrd/keybrd_PCA9655E.ino
  22. 8
    0
      examples/IOE_PCA9655E_development/README.md
  23. 1
    6
      examples/keybrd_MCP23018/keybrd_MCP23018.ino
  24. 5
    0
      src/LED_uC.cpp
  25. 2
    6
      src/LED_uC.h
  26. 0
    7
      src/Port_MCP23018.cpp
  27. 2
    2
      src/Port_PCA9655E.cpp
  28. 3
    5
      src/Row.h
  29. 7
    10
      src/Scanner_ShiftRegsReadStrobed.cpp
  30. 0
    1
      src/Scanner_ShiftRegsReadStrobed.h
  31. 6
    4
      tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino
  32. 2
    2
      tutorials/tutorial_10_writing_IOE_port_classes.md
  33. 0
    33
      unit_tests/PortMCP23018_write/PortMCP23018_write.ino
  34. BIN
      unit_tests/PortMCP23S17_read/PortMCP23S17_bb.JPG
  35. 0
    25
      unit_tests/PortMCP23S17_read/PortMCP23S17_read.ino
  36. 0
    29
      unit_tests/PortMCP23S17_write/PortMCP23S17_write.ino

BIN
IOE_scan_development/IOE_scan_development.ods View File


BIN
IOE_scan_development/openDrain_activeLow/back.JPG View File


BIN
IOE_scan_development/openDrain_activeLow/front.JPG View File


+ 0
- 69
IOE_scan_development/openDrain_activeLow/openDrain_activeLow.ino View File

@@ -1,69 +0,0 @@
/* 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<uint8_t>(1)); //request one byte from GPIOA read
Serial.print("portA=");
Serial.println(Wire.read(), BIN); //prints portA=11101111
}
void loop() { }

BIN
IOE_scan_development/source_activeHigh/DSCF0003.JPG View File


BIN
IOE_scan_development/source_activeHigh/DSCF0004.JPG View File


+ 0
- 69
IOE_scan_development/source_activeHigh/source_activeHigh.ino View File

@@ -1,69 +0,0 @@
/* 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<uint8_t>(1)); //request one byte from GPIOA read
Serial.print("portA=");
Serial.println(Wire.read(), BIN); //prints portA=00010000
}
void loop() { }

BIN
IOE_scan_development/source_activeLow/back.JPG View File


BIN
IOE_scan_development/source_activeLow/front.JPG View File


+ 0
- 68
IOE_scan_development/source_activeLow/source_activeLow.ino View File

@@ -1,68 +0,0 @@
/* 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<uint8_t>(1)); //request one byte from GPIOA read
Serial.print("portA=");
Serial.println(Wire.read(), BIN); //prints portA=11101111
}
void loop() { }

+ 58
- 0
examples/IOE_PCA9655E_development/PCA9655E_1_write_read/PCA9655E_1_write_read.ino View File

@@ -0,0 +1,58 @@
/* PCA9655E_1_write_read.ino

set port 1 pins
read and print value of port 0
measure port 1 pin voltages with a multimeter

DESTINATION PIN PIN_NUMBER PIN DESTINATION
x INT 1 24 VDD Teensy LC 3.3V
SCL AD1 2 23 SDA Teensy LC 18
GND AD2 3 22 SCL Teensy LC 19
GND IO0_0 4 21 AD0 SCL
GND IO0_1 5 20 IO1_6 x
VDD IO0_2 6 19 IO1_5 x
VDD IO0_3 7 18 IO1_4 x
GND IO0_4 8 17 IO1_4 x
GND IO0_5 9 16 IO1_3 x
x IO0_6 10 15 IO1_2 x
x IO0_7 11 14 IO1_1 x
GND VSS 12 13 IO1_0 x
*/
#include "Wire.h"

const uint8_t ADDR = 0x18; //I2C address with AD2=GND AD1=SCL AD0=SCL
void setup()
{
delay(1000);
Serial.print("PCA9655E_read.ino");
Wire.begin();

//Configure port 1 to output
Wire.beginTransmission(ADDR);
Wire.write(7); //configure direction
Wire.write(0); //0=output
Wire.endTransmission();

Wire.beginTransmission(ADDR);
Wire.write(3); //command byte 3 = Output Port 1
Wire.write( 1<<2 | 1<<3); //1=high
Wire.endTransmission();

//Configure port 0 to input
Wire.beginTransmission(ADDR);
Wire.write(6); //command byte 6 = Configuration dir Port 0
Wire.write(~0); //1=input
Wire.endTransmission();
Wire.beginTransmission(ADDR);
Wire.write(0); //command byte 0 = Input Port 0
Wire.endTransmission(false); //PCA9655E needs false to send a restart

Wire.requestFrom(ADDR, 1u); //request one byte from input port

Serial.print(" port0_val= ");
uint8_t port0_val = Wire.read();
Serial.print(port0_val, BIN); //expect xx001100
}

void loop() { }

BIN
examples/IOE_PCA9655E_development/PCA9655E_1_write_read/back.JPG View File


BIN
examples/IOE_PCA9655E_development/PCA9655E_1_write_read/front.JPG View File


BIN
examples/IOE_PCA9655E_development/PCA9655E_2_scan/DSCF0001.JPG View File


BIN
examples/IOE_PCA9655E_development/PCA9655E_2_scan/DSCF0002.JPG View File


+ 56
- 0
examples/IOE_PCA9655E_development/PCA9655E_2_scan/PCA9655E_2_scan.ino View File

@@ -0,0 +1,56 @@
/* PCA9655E_2_scan.ino

power IO0_2 and read IO1_1 (similar to strobe and read on key matrix)

DESTINATION PIN PIN_NUMBER PIN DESTINATION
x INT 1 24 VDD Teensy LC 3.3V
SCL AD1 2 23 SDA Teensy LC 18
GND AD2 3 22 SCL Teensy LC 19
GND IO0_0 4 21 AD0 SCL
GND IO0_1 5 20 IO1_6 x
IO1_1 IO0_2 6 19 IO1_5 x
GND IO0_3 7 18 IO1_4 x
GND IO0_4 8 17 IO1_4 x
GND IO0_5 9 16 IO1_3 x
x IO0_6 10 15 IO1_2 x
x IO0_7 11 14 IO1_1 IO0_2
GND VSS 12 13 IO1_0 x
*/
#include "Wire.h"

const uint8_t ADDR = 0x18; //I2C address with AD2=GND AD1=SCL AD0=SCL
void setup()
{
delay(1000);
Serial.print("PCA9655E_read.ino");
Wire.begin();

//Configure port 1 to output
Wire.beginTransmission(ADDR);
Wire.write(7); //command byte 7 = Configuration dir Port 1
Wire.write(0); //0=output
Wire.endTransmission();

Wire.beginTransmission(ADDR);
Wire.write(3); //command byte 3 = Output Port 1
Wire.write( 1<<1 ); //1=high
Wire.endTransmission();

//Configure port 0 to input
Wire.beginTransmission(ADDR);
Wire.write(6); //command byte 6 = Configuration dir Port 0
Wire.write(~0); //1=input
Wire.endTransmission();
Wire.beginTransmission(ADDR);
Wire.write(0); //command byte 0 = Input Port 0
Wire.endTransmission(false); //PCA9655E needs false to send a restart

Wire.requestFrom(ADDR, 1u); //request one byte from input port

Serial.print(" port0_val= ");
uint8_t port0_val = Wire.read();
Serial.print(port0_val, BIN); //expect xx000100
}

void loop() { }

+ 45
- 0
examples/IOE_PCA9655E_development/PCA9655E_3_scan_lib/PCA9655E_3_scan_lib.ino View File

@@ -0,0 +1,45 @@
/* PCA9655E_3_scan_lib.ino
does same as PCA9655E_2_scan.ino, but using keybrd library classes
pictures in PCA9655E_2_scan/

set port 1 pins
read and print value of port 0
measure port 1 pin voltages with a multimeter

DESTINATION PIN PIN_NUMBER PIN DESTINATION
x INT 1 24 VDD Teensy LC 3.3V
SCL AD1 2 23 SDA Teensy LC 18
GND AD2 3 22 SCL Teensy LC 19
GND IO0_0 4 21 AD0 SCL
GND IO0_1 5 20 IO1_6 x
IO1_1 IO0_2 6 19 IO1_5 x
GND IO0_3 7 18 IO1_4 x
GND IO0_4 8 17 IO1_4 x
GND IO0_5 9 16 IO1_3 x
x IO0_6 10 15 IO1_2 x
x IO0_7 11 14 IO1_1 IO0_2 strobe pin
GND VSS 12 13 IO1_0 x
*/
#include <Port_PCA9655E.h>
#include <Scanner_IOE.h>

const uint8_t ADDR = 0x18; //I2C address with AD2=GND AD1=SCL AD0=SCL

Port_PCA9655E port0(ADDR, 0, ~0); //read all pins
Port_PCA9655E port1(ADDR, 1, 0); //for strobe

Scanner_IOE scanner_R(HIGH, port1, port0);

void setup()
{
delay(6000);
Keyboard.print("PCA9655E_scan.ino");

scanner_R.begin();

Keyboard.print(" port0_val= ");
uint8_t port0_val = scanner_R.scan(1<<1); //strobe pin 1
Keyboard.print(port0_val, BIN); //expect xx000100
}

void loop() { }

+ 86
- 0
examples/IOE_PCA9655E_development/PCA9655E_4_scan_loop/PCA9655E_4_scan_loop.ino View File

@@ -0,0 +1,86 @@
/* PCA9655E_4_scan_loop.ino
does same as PCA9655E_2_scan.ino, but using keybrd library classes
pictures in PCA9655E_2_scan/

set port 1 pins
read and print value of port 0
measure port 1 pin voltages with a multimeter

DESTINATION PIN PIN_NUMBER PIN DESTINATION
x INT 1 24 VDD Teensy LC 3.3V
SCL AD1 2 23 SDA Teensy LC 18
GND AD2 3 22 SCL Teensy LC 19
GND IO0_0 4 21 AD0 SCL
GND IO0_1 5 20 IO1_6 x
IO1_1 IO0_2 6 19 IO1_5 x
GND IO0_3 7 18 IO1_4 x
GND IO0_4 8 17 IO1_4 x
GND IO0_5 9 16 IO1_3 x
x IO0_6 10 15 IO1_2 x
x IO0_7 11 14 IO1_1 IO0_2 strobe pin
GND VSS 12 13 IO1_0 x
*/
#include <Port_PCA9655E.h>
#include <Scanner_IOE.h>

const uint8_t ADDR = 0x18; //I2C address with AD2=GND AD1=SCL AD0=SCL

Port_PCA9655E port0(ADDR, 0, ~0); //read all pins
Port_PCA9655E port1(ADDR, 1, 0); //for strobe

Scanner_IOE scanner_R(HIGH, port1, port0);

void setup()
{
delay(6000);
Keyboard.println("PCA9655E_scan_loop.ino");

scanner_R.begin();
}

uint8_t port0_val; //bit pattern
uint8_t errorCount = 0;
int loopCount = 0;
int wait = 0; //delayMicroseconds

void status()
{
Keyboard.print(" loopCount=");
Keyboard.print(loopCount);
Keyboard.print(" wait=");
Keyboard.println(wait);
};

void loop()
{
port0_val = scanner_R.scan(1<<1); //strobe pin 1
if ( (B00111111 & port0_val) != B00000100 ) //expect xx000100, where xx float
{
Keyboard.print("port0_val=");
Keyboard.print(port0_val, BIN);
errorCount++;
status();
}

loopCount++;
if (loopCount > 32000 || errorCount > 10)
{
Keyboard.print("stop errorCount=");
Keyboard.print(errorCount);
status();
while(1);
}

if (loopCount % 1000 == 0)
{
Keyboard.print(" progress");
status();
}

if (loopCount > 22000)
{
wait++; //test other delays
}

delayMicroseconds(wait);
}

BIN
examples/IOE_PCA9655E_development/PCA9655E_5_keybrd/back.JPG View File


BIN
examples/IOE_PCA9655E_development/PCA9655E_5_keybrd/front.JPG View File


examples/keybrd_PCA9655E/keybrd_PCA9655E.ino → examples/IOE_PCA9655E_development/PCA9655E_5_keybrd/keybrd_PCA9655E.ino View File

@@ -1,10 +1,26 @@
/* keybrd_PCA9655E.ino
keyboard layout is same as top-left keys of DH matrices:

Controller I/O expander
| Left | **0** | **1** | | Right | **0** | **1** |
| Left | **0** | **1** | | Right | **2** | **3** |
|:-----:|-------|-------| |:-----:|-------|-------|
| **1** | 1 | 2 | | **1** | 3 | 4 |
| **0** | a | b | | **0** | c | d |
| **1** | q | w | | **1** | u | i |
| **0** | [ | b | | **0** | h | y |

PCA9655E pin assignments are compatible with this sketch and keybrd_DH.ino
DESTINATION PIN PIN_NUMBER PIN DESTINATION
x INT 1 24 VDD Teensy LC 3.3V
SCL AD1 2 23 SDA Teensy LC 18
GND AD2 3 22 SCL Teensy LC 19
GND IO0_0 4 21 AD0 SCL
GND IO0_1 5 20 IO1_6 x
col2 IO0_2 6 19 IO1_5 x
col3 IO0_3 7 18 IO1_4 x
GND IO0_4 8 17 IO1_4 x
GND IO0_5 9 16 IO1_3 x
x IO0_6 10 15 IO1_2 x
x IO0_7 11 14 IO1_1 row1
GND VSS 12 13 IO1_0 row2
*/
// ################## GLOBAL ###################
// ================= INCLUDES ==================
@@ -29,55 +45,62 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
Scanner_uC scanner_L(HIGH, readPins, readPinCount);

// =============== RIGHT SCANNER ===============
const uint8_t IOE_ADDR = 0x18;
const uint8_t IOE_ADDR = 0x18; //AD2=GND AD1=SCL AD0=SCL

Port_PCA9655E port1(IOE_ADDR, 1, 0); //for strobe
Port_PCA9655E port0(IOE_ADDR, 0, 1<<0 | 1<<1 ); //for read
Port_PCA9655E port0(IOE_ADDR, 0, 1<<0 | 1<<1 | 1<<2 | 1<<3 | 1<<4 | 1<<5 ); //for read
Port_PCA9655E port1(IOE_ADDR, 1, 0); //for strobe

Scanner_IOE scanner_R(HIGH, port1, port0);

// =================== 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_B(KEY_B);
Code_Sc s_I(KEY_I);
Code_Sc s_H(KEY_H);
Code_Sc s_Q(KEY_Q);
Code_Sc s_W(KEY_W);
Code_Sc s_U(KEY_U);
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_leftBracket(KEY_LEFT_BRACE);

// =================== ROWS ====================
// ---------------- LEFT ROWS ------------------
Key* ptrsKeys_L0[] = { &s_1, &s_2 };
Key* ptrsKeys_L0[] = { &s_Q, &s_W };
uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0);
Row row_L0(scanner_L, 21, ptrsKeys_L0, KEY_COUNT_L0);

Key* ptrsKeys_L1[] = { &s_a, &s_b };
Key* ptrsKeys_L1[] = { &s_leftBracket, &s_B };
uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1);
Row row_L1(scanner_L, 20, ptrsKeys_L1, KEY_COUNT_L1);

// ---------------- RIGHT ROWS -----------------
Key* ptrsKeys_R0[] = { &s_3, &s_4 };
Key* ptrsKeys_R0[] = { &s_0, &s_1, &s_U, &s_I };
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 };
Key* ptrsKeys_R1[] = { &s_0, &s_1, &s_H, &s_Y };
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();
delay(6000);
Keyboard.print("keybrd_PCA9655E.ino ");

//Keyboard.begin(); not needed ?? it's in DH mainSketch.cpp and keybrd_4c_split_keyboard_with_IOE.ino
scanner_R.begin();
}

void loop()
{
//left matrix
row_L0.process();
row_L1.process();
//left matrix (commented because keys are not connected)
//row_L0.process();
//row_L1.process();

//right matrix
row_R0.process();

+ 8
- 0
examples/IOE_PCA9655E_development/README.md View File

@@ -0,0 +1,8 @@
The series of sketches in this folder where used to develope the Port_PCA9655E class.
The folder numbers are ordered from fundamental to practical.

Each sketch was tested on a breadboard. Breadboards hold:
* Teensy LC controller
* PCA9655E I/O expander

Pictures of the breadboard are in the folders.

+ 1
- 6
examples/keybrd_MCP23018/keybrd_MCP23018.ino View File

@@ -71,7 +71,7 @@ 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
Code_LEDLock o_capsLock(KEY_CAPS_LOCK, LED_capsLck);//was testing LED, restore s_4 when done

/* =================== ROWS ====================
Left row names contain the letter 'L', while right row names conatain the letter 'R'.
@@ -118,14 +118,9 @@ void loop()

//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();
}

+ 5
- 0
src/LED_uC.cpp View File

@@ -1,5 +1,10 @@
#include "LED_uC.h"

LED_uC::LED_uC(const uint8_t pin) : pin(pin)
{
pinMode(pin, OUTPUT);
}

void LED_uC::on()
{
digitalWrite(pin, HIGH);

+ 2
- 6
src/LED_uC.h View File

@@ -9,13 +9,9 @@
class LED_uC: public LEDInterface
{
private:
const uint8_t pin; //Aduino pin that is connected to an LED
const uint8_t pin; //Aduino pin number connected to an LED
public:
LED_uC(const uint8_t pin): pin(pin)
{
pinMode(pin, OUTPUT);//todo move to .cpp file
}
LED_uC(const uint8_t pin);
virtual void on();
virtual void off();
};

+ 0
- 7
src/Port_MCP23018.cpp View File

@@ -1,5 +1,4 @@
#include "Port_MCP23018.h"
//todo add Port_MCP23018::write() like Port_MCP23S17::transer() ??
/* beginProtocol() is called from Scanner_IOE::begin(). Initiates I2C bus.
@@ -11,7 +10,6 @@ Longer wires require lower clock speeds.
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().
@@ -51,21 +49,16 @@ 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.

+ 2
- 2
src/Port_PCA9655E.cpp View File

@@ -15,12 +15,12 @@ void Port_PCA9655E::beginProtocol()
/* begin() is called from Scanner_IOE::begin().
Configures read pins to input.
strobeOn is not used because PCA9655E has no pull-up resistors.
strobeOn is not used because PCA9655E has no internal pull-up resistors.
*/
void Port_PCA9655E::begin(const uint8_t strobeOn)
{
Wire.beginTransmission(deviceAddr);
Wire.write(portNum + 6); //configuration byte command
Wire.write(portNum + 6); //configure direction
Wire.write(readPins); //0=output (for strobe and LED), 1=input (for read)
Wire.endTransmission();
}

+ 3
- 5
src/Row.h View File

@@ -11,12 +11,10 @@
/*
strobePin has one of two formats:
1. if strobe pin is on uC (Scanner_uC or Scanner_ShiftRegsRead),
* if strobe pin is on uC (strobe for Scanner_uC or Scanner_ShiftRegsRead),
then strobePin is an Arduino pin number connected to this row.
2. if strobe pin is on I/O expander (Scanner_IOE), then strobePin is bit pattern,
* if strobe pin is on I/O expander (strobe for Scanner_IOE), then strobePin is bit pattern,
1 indicating the I/O expander pin connected to this row
todo instantiation examples - here or in Scanner?
*/
class Row
{
@@ -31,7 +29,7 @@ class Row
protected:
const uint8_t keyCount; //number of read pins
//Debouncer_Samples debouncer;
Debouncer_Not debouncer; //todo
Debouncer_Not debouncer; //todo restore Debouncer_Samples after testing
read_pins_t debounced; //bit pattern, state of keys after debouncing, 1=pressed, 0=released
public:
Row(ScannerInterface& refScanner, const uint8_t strobePin,

+ 7
- 10
src/Scanner_ShiftRegsReadStrobed.cpp View File

@@ -6,25 +6,20 @@ Scanner_ShiftRegsReadStrobed::Scanner_ShiftRegsReadStrobed(const bool activeStat
slaveSelect(slaveSelect), byte_count(byte_count)
{
pinMode(slaveSelect, OUTPUT);
SPI.begin();
}

/* init() is called once for each row from Row constructor.
Configures controller to communicate with shift register matrix.

slaveSelect initialize not needed, only affects first scan, which is before USB is detected by OS.
digitalWrite(slaveSelect, HIGH);
*/
void Scanner_ShiftRegsReadStrobed::init(const uint8_t strobePin)
{
pinMode(strobePin, OUTPUT);
}

/* begin() should be called once from sketch setup().
Initializes shift register's shift/load pin.
*/
void Scanner_ShiftRegsReadStrobed::begin()
{
digitalWrite(slaveSelect, HIGH); //initialize ??only needed for first scan
SPI.begin(); //todo move this to constructor or init()
}

/* scan() strobes the row's strobePin and returns state of the shift register's input pins.
strobePin is Arduino pin number connected to this row.
Bit patterns are 1 bit per key.
@@ -44,6 +39,7 @@ read_pins_t Scanner_ShiftRegsReadStrobed::scan(const uint8_t strobePin)
{
read_pins_t readState = 0; //bits, 1 means key is pressed, 0 means released

//strobe off here NOT release continuously
digitalWrite(strobePin, activeState); //strobe on

//SPI.beginTransaction( SPISettings(5000000, MSBFIRST, SPI_MODE0) ); //control SPI bus, 5 MHz
@@ -53,7 +49,7 @@ read_pins_t Scanner_ShiftRegsReadStrobed::scan(const uint8_t strobePin)

digitalWrite(slaveSelect, HIGH); //shift the data toward a serial output

digitalWrite(strobePin, !activeState); //strobe off to preserv IR LED life
digitalWrite(strobePin, !activeState); //strobe off to preserve IR LED life

SPI.transfer(&readState, byte_count);

@@ -61,6 +57,7 @@ read_pins_t Scanner_ShiftRegsReadStrobed::scan(const uint8_t strobePin)

digitalWrite(slaveSelect, LOW); //load parallel inputs to registers

//strobe off here still releases continuously
return readState;
}


+ 0
- 1
src/Scanner_ShiftRegsReadStrobed.h View File

@@ -55,7 +55,6 @@ class Scanner_ShiftRegsReadStrobed : public ScannerInterface
Scanner_ShiftRegsReadStrobed(const bool activeState,
const uint8_t slaveSelect, const uint8_t byte_count);
virtual void init(const uint8_t strobePin);
virtual void begin();
virtual read_pins_t scan(const uint8_t strobePin);
};
#endif

+ 6
- 4
tutorials/keybrd_4c_split_keyboard_with_IOE/keybrd_4c_split_keyboard_with_IOE.ino View File

@@ -49,8 +49,8 @@ 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 to the right of "1<<" and delimited by "|".
*/
Port_MCP23S17 portA(IOE_ADDR, 0, 1<<0 | 1<<1 );
Port_MCP23S17 portB(IOE_ADDR, 1, 0);
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);

// =================== CODES ===================
@@ -69,8 +69,10 @@ Left row names contain the letter 'L', while right row names conatain the letter

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
* if strobe pin is on uC (strobe for Scanner_uC or Scanner_ShiftRegsRead),
then strobePin is an Arduino pin number connected to this row.
* if strobe pin is on I/O expander (strobe for Scanner_IOE), then strobePin is bit pattern,
1 indicating the I/O expander pin connected to this row
*/
/* ---------------- LEFT ROWS ------------------
The left rows have a Scanner_uC and Arduino pin numbers to strobe.

+ 2
- 2
tutorials/tutorial_10_writing_IOE_port_classes.md View File

@@ -19,8 +19,8 @@ Steps to writing a new port class:
5. Study other keybrd port classes.
* SPI I/O expander port classes: Port_MCP23S17
* I2C I/O expander port classes: Port_PCA9655E
6. Write the port classes for your I/O expander.
Debugging I/O expander code is hard because SPI or I2C protocol adds a level of indirection.
6. Write the port classes for your I/O expander. Debugging I/O expander code is hard because
SPI or I2C protocol, expander configuration, and expander commands.

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

+ 0
- 33
unit_tests/PortMCP23018_write/PortMCP23018_write.ino View File

@@ -1,33 +0,0 @@
/* 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);
}

BIN
unit_tests/PortMCP23S17_read/PortMCP23S17_bb.JPG View File


+ 0
- 25
unit_tests/PortMCP23S17_read/PortMCP23S17_read.ino View File

@@ -1,25 +0,0 @@
/* unit test for PortMCP23S17
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.
output is: 10101010
*/

#include "Port_MCP23S17.h"

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 BitPattern; //reading of port B

delay(6000);
portB.begin(HIGH); //HIGH or LOW, does not matter

BitPattern = portB.read();
Keyboard.print("BitPattern = ");
Keyboard.println(BitPattern, BIN); //prints 10101010
}

void loop() { }

+ 0
- 29
unit_tests/PortMCP23S17_write/PortMCP23S17_write.ino View File

@@ -1,29 +0,0 @@
/* 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 red LED.
*/
#include "Port_MCP23S17.h"

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);
Keyboard.println("start setup");
portA.begin(LOW); //HIGH or LOW, not matter if readPins=0
Keyboard.println("start loop");
}

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

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