Archived
1
0

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

This commit is contained in:
wolfv6 2016-11-12 09:45:48 -07:00
parent a7bea464bf
commit e9e74634a4
36 changed files with 325 additions and 357 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 KiB

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() { }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 KiB

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() { }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 KiB

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() { }

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() { }

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

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() { }

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() { }

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

View File

@ -1,10 +1,26 @@
/* keybrd_PCA9655E.ino /* keybrd_PCA9655E.ino
keyboard layout is same as top-left keys of DH matrices:
Controller I/O expander Controller I/O expander
| Left | **0** | **1** | | Right | **0** | **1** | | Left | **0** | **1** | | Right | **2** | **3** |
|:-----:|-------|-------| |:-----:|-------|-------| |:-----:|-------|-------| |:-----:|-------|-------|
| **1** | 1 | 2 | | **1** | 3 | 4 | | **1** | q | w | | **1** | u | i |
| **0** | a | b | | **0** | c | d | | **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 ################### // ################## GLOBAL ###################
// ================= INCLUDES ================== // ================= INCLUDES ==================
@ -29,55 +45,62 @@ uint8_t readPinCount = sizeof(readPins)/sizeof(*readPins);
Scanner_uC scanner_L(HIGH, readPins, readPinCount); Scanner_uC scanner_L(HIGH, readPins, readPinCount);
// =============== RIGHT SCANNER =============== // =============== 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 | 1<<2 | 1<<3 | 1<<4 | 1<<5 ); //for read
Port_PCA9655E port0(IOE_ADDR, 0, 1<<0 | 1<<1 ); //for read Port_PCA9655E port1(IOE_ADDR, 1, 0); //for strobe
Scanner_IOE scanner_R(HIGH, port1, port0); Scanner_IOE scanner_R(HIGH, port1, port0);
// =================== CODES =================== // =================== CODES ===================
Code_Sc s_a(KEY_A); Code_Sc s_B(KEY_B);
Code_Sc s_b(KEY_B); Code_Sc s_I(KEY_I);
Code_Sc s_c(KEY_C); Code_Sc s_H(KEY_H);
Code_Sc s_d(KEY_D); 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_1(KEY_1);
Code_Sc s_2(KEY_2); Code_Sc s_leftBracket(KEY_LEFT_BRACE);
Code_Sc s_3(KEY_3);
Code_Sc s_4(KEY_4);
// =================== ROWS ==================== // =================== ROWS ====================
// ---------------- LEFT 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); uint8_t KEY_COUNT_L0 = sizeof(ptrsKeys_L0)/sizeof(*ptrsKeys_L0);
Row row_L0(scanner_L, 21, ptrsKeys_L0, KEY_COUNT_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); uint8_t KEY_COUNT_L1 = sizeof(ptrsKeys_L1)/sizeof(*ptrsKeys_L1);
Row row_L1(scanner_L, 20, ptrsKeys_L1, KEY_COUNT_L1); Row row_L1(scanner_L, 20, ptrsKeys_L1, KEY_COUNT_L1);
// ---------------- RIGHT ROWS ----------------- // ---------------- 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); uint8_t KEY_COUNT_R0 = sizeof(ptrsKeys_R0)/sizeof(*ptrsKeys_R0);
Row row_R0(scanner_R, 1<<0, ptrsKeys_R0, KEY_COUNT_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); uint8_t KEY_COUNT_R1 = sizeof(ptrsKeys_R1)/sizeof(*ptrsKeys_R1);
Row row_R1(scanner_R, 1<<1, ptrsKeys_R1, KEY_COUNT_R1); Row row_R1(scanner_R, 1<<1, ptrsKeys_R1, KEY_COUNT_R1);
/*
*/
// ################### MAIN #################### // ################### MAIN ####################
void setup() 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(); scanner_R.begin();
} }
void loop() void loop()
{ {
//left matrix //left matrix (commented because keys are not connected)
row_L0.process(); //row_L0.process();
row_L1.process(); //row_L1.process();
//right matrix //right matrix
row_R0.process(); row_R0.process();

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.

View File

@ -71,7 +71,7 @@ Code_Sc s_2(KEY_2);
Code_Sc s_3(KEY_3); Code_Sc s_3(KEY_3);
Code_Sc s_4(KEY_4); 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 ==================== /* =================== ROWS ====================
Left row names contain the letter 'L', while right row names conatain the letter 'R'. Left row names contain the letter 'L', while right row names conatain the letter 'R'.
@ -118,14 +118,9 @@ void loop()
//right matrix //right matrix
row_R0.process(); row_R0.process();
//Keyboard.println(" 0");
//delay(2000);
row_R1.process(); row_R1.process();
//Keyboard.println(" 1");
//delay(2000);
scanDelay.delay(); scanDelay.delay();
//Keyboard.println(" end loop");//todo
//debug.print_scans_per_second(); //debug.print_scans_per_second();
//debug.print_microseconds_per_scan(); //debug.print_microseconds_per_scan();
} }

View File

@ -1,5 +1,10 @@
#include "LED_uC.h" #include "LED_uC.h"
LED_uC::LED_uC(const uint8_t pin) : pin(pin)
{
pinMode(pin, OUTPUT);
}
void LED_uC::on() void LED_uC::on()
{ {
digitalWrite(pin, HIGH); digitalWrite(pin, HIGH);

View File

@ -9,13 +9,9 @@
class LED_uC: public LEDInterface class LED_uC: public LEDInterface
{ {
private: 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: public:
LED_uC(const uint8_t pin): pin(pin) LED_uC(const uint8_t pin);
{
pinMode(pin, OUTPUT);//todo move to .cpp file
}
virtual void on(); virtual void on();
virtual void off(); virtual void off();
}; };

View File

@ -1,5 +1,4 @@
#include "Port_MCP23018.h" #include "Port_MCP23018.h"
//todo add Port_MCP23018::write() like Port_MCP23S17::transer() ??
/* beginProtocol() is called from Scanner_IOE::begin(). Initiates I2C bus. /* beginProtocol() is called from Scanner_IOE::begin(). Initiates I2C bus.
@ -11,7 +10,6 @@ Longer wires require lower clock speeds.
void Port_MCP23018::beginProtocol() void Port_MCP23018::beginProtocol()
{ {
Wire.begin(); //initiate I2C bus to 100 kHz 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(). /* 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) if (logicLevel == LOW)
{ {
outputVal &= ~pin; //set pin output to low outputVal &= ~pin; //set pin output to low
//Keyboard.print(" low");
} }
else else
{ {
outputVal |= pin; //set pin output to high outputVal |= pin; //set pin output to high
//Keyboard.print(" high");
} }
//Keyboard.print(" outputVal=");//todo
//Keyboard.println(outputVal);
Wire.beginTransmission(deviceAddr); Wire.beginTransmission(deviceAddr);
Wire.write(portNum + 0x12); //GPIO Wire.write(portNum + 0x12); //GPIO
Wire.write(outputVal); Wire.write(outputVal);
Wire.endTransmission(); Wire.endTransmission();
//delay(4000);
} }
/* read() returns portState. /* read() returns portState.

View File

@ -15,12 +15,12 @@ void Port_PCA9655E::beginProtocol()
/* begin() is called from Scanner_IOE::begin(). /* begin() is called from Scanner_IOE::begin().
Configures read pins to input. 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) void Port_PCA9655E::begin(const uint8_t strobeOn)
{ {
Wire.beginTransmission(deviceAddr); 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.write(readPins); //0=output (for strobe and LED), 1=input (for read)
Wire.endTransmission(); Wire.endTransmission();
} }

View File

@ -11,12 +11,10 @@
/* /*
strobePin has one of two formats: 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. 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 1 indicating the I/O expander pin connected to this row
todo instantiation examples - here or in Scanner?
*/ */
class Row class Row
{ {
@ -31,7 +29,7 @@ class Row
protected: protected:
const uint8_t keyCount; //number of read pins const uint8_t keyCount; //number of read pins
//Debouncer_Samples debouncer; //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 read_pins_t debounced; //bit pattern, state of keys after debouncing, 1=pressed, 0=released
public: public:
Row(ScannerInterface& refScanner, const uint8_t strobePin, Row(ScannerInterface& refScanner, const uint8_t strobePin,

View File

@ -6,25 +6,20 @@ Scanner_ShiftRegsReadStrobed::Scanner_ShiftRegsReadStrobed(const bool activeStat
slaveSelect(slaveSelect), byte_count(byte_count) slaveSelect(slaveSelect), byte_count(byte_count)
{ {
pinMode(slaveSelect, OUTPUT); pinMode(slaveSelect, OUTPUT);
SPI.begin();
} }
/* init() is called once for each row from Row constructor. /* init() is called once for each row from Row constructor.
Configures controller to communicate with shift register matrix. 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) void Scanner_ShiftRegsReadStrobed::init(const uint8_t strobePin)
{ {
pinMode(strobePin, OUTPUT); 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. /* 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. strobePin is Arduino pin number connected to this row.
Bit patterns are 1 bit per key. 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 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 digitalWrite(strobePin, activeState); //strobe on
//SPI.beginTransaction( SPISettings(5000000, MSBFIRST, SPI_MODE0) ); //control SPI bus, 5 MHz //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(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); 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 digitalWrite(slaveSelect, LOW); //load parallel inputs to registers
//strobe off here still releases continuously
return readState; return readState;
} }

View File

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

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. "<<" (bit shift left) and "|" (OR) are bitwise operators.
Pin numbers to be read are to the right of "1<<" and delimited by "|". 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 portA(IOE_ADDR, 0, 1<<0 | 1<<1 ); //for read
Port_MCP23S17 portB(IOE_ADDR, 1, 0); Port_MCP23S17 portB(IOE_ADDR, 1, 0); //for strobe
Scanner_IOE scanner_R(LOW, portB, portA); Scanner_IOE scanner_R(LOW, portB, portA);
// =================== CODES =================== // =================== 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. Row constructor parameters are: scanner, strobePin, ptrsKeys[], keyCount.
strobePin has one of two formats: strobePin has one of two formats:
* if refScanner a Scanner_uC, then strobePin is an Arduino pin number connected to this row * if strobe pin is on uC (strobe for Scanner_uC or Scanner_ShiftRegsRead),
* otherwise strobePin is a bit pattern, 1 indicating an IC pin connected to the row 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 ------------------ /* ---------------- LEFT ROWS ------------------
The left rows have a Scanner_uC and Arduino pin numbers to strobe. The left rows have a Scanner_uC and Arduino pin numbers to strobe.

View File

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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

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() { }

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