@@ -155,9 +155,11 @@ void setup() | |||
void loop() | |||
{ | |||
//left matrix | |||
row_L0.process(); | |||
row_L1.process(); | |||
//right matrix | |||
row_R0.process(); | |||
row_R1.process(); | |||
@@ -1,17 +0,0 @@ | |||
#include "ColPort_AVR.h" | |||
/* | |||
configures column port's DDRx and PORTx. | |||
*/ | |||
ColPort_AVR::ColPort_AVR(volatile unsigned char& DDRx, volatile unsigned char& PORTx, | |||
volatile unsigned char& PINx, const uint8_t colPins) | |||
: ColPort(colPins), DDR(DDRx = ~colPins), PORT(PORTx = colPins), PIN(PINx) | |||
{} | |||
/* | |||
Saves all port-pin values to portState. | |||
*/ | |||
void ColPort_AVR::read() | |||
{ | |||
portState = PIN; | |||
} |
@@ -1,41 +0,0 @@ | |||
#ifndef COLPORT_AVR_H | |||
#define COLPORT_AVR_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <ColPort.h> | |||
/* One AVR microcontroller port connected to matrix columns. | |||
Instantiation | |||
------------ | |||
The constructor configures column's DDRx and PORTx. | |||
The 'x' in parameters DDRx, PORTx, and PINx should all be the same letter. | |||
colPins 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 on column port B, with pins 2 and 3 connected to columns: | |||
ColPort_AVR colPortB(DDRB, PORTB, PINB, 1<<2 | 1<<3 ); | |||
colPins are read from pin 0 on up. | |||
Diode orientation | |||
---------------- | |||
Rows, columns, and diode orientation are explained in Matrix.h | |||
*/ | |||
class ColPort_AVR : public ColPort | |||
{ | |||
private: | |||
const volatile unsigned char& DDR; //Data Direction Register, Direction: 0=Input | |||
const volatile unsigned char& PORT; //PORT register | |||
const volatile unsigned char& PIN; //PIN read register | |||
public: | |||
//The constructor initialization list is in .cpp | |||
ColPort_AVR(volatile unsigned char& DDRx, volatile unsigned char& PORTx, | |||
volatile unsigned char& PINx, const uint8_t colPins); | |||
//read port and store result in portState | |||
virtual void read(); | |||
}; | |||
#endif |
@@ -1,42 +0,0 @@ | |||
#include "ColPort_MCP23018.h" | |||
/* | |||
configures column port's IODIR, GPIO, and GPPU. | |||
*/ | |||
ColPort_MCP23018::ColPort_MCP23018(IOExpanderPort& port, const uint8_t colPins) | |||
: ColPort(colPins), port(port), IODIR(port.num), GPIO(port.num + 0x12), GPPU(port.num + 0x0C) | |||
{} | |||
void ColPort_MCP23018::begin(uint8_t activeHigh) | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(IODIR); | |||
Wire.write(colPins); //0=configure as output (for LED), 1=configure as input (for read) | |||
Wire.endTransmission(); | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(GPPU); | |||
if (activeHigh) | |||
{ | |||
Wire.write(0); //0=pull-up disabled for activeHigh //todo not tested yet | |||
} | |||
else | |||
{ | |||
Wire.write(colPins); //0=pull-up disabled (for LED), 1=pull-up enabled (for read) | |||
} | |||
Wire.endTransmission(); | |||
} | |||
/* | |||
Saves all port-pin values to portState. | |||
*/ | |||
void ColPort_MCP23018::read() | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(GPIO); //GPIO immediately before requestFrom | |||
Wire.endTransmission(); | |||
Wire.requestFrom(port.ADDR, 1u); //request one byte from input port | |||
portState = Wire.read(); | |||
} |
@@ -1,46 +0,0 @@ | |||
#ifndef COLPORT_MCP23018_H | |||
#define COLPORT_MCP23018_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <ColPort.h> | |||
#include "IOExpanderPort.h" | |||
/* One MCP23018 I/O expander port connected to matrix columns. | |||
Instantiation | |||
------------ | |||
colPins parameter is port's bitwise pin configuration | |||
1=configure as input (for read) | |||
0=configure as output (for LED or not connected to a column) | |||
example instantiation for column port A, with pins 2 and 3 connected to columnss: | |||
IOExpanderPort portA(0, ~0); | |||
ColPort_MCP23018 colPortA(portA, 1<<2 | 1<<3 ); | |||
example instantiation for column port B, with pins 2 and 3 connected to columns: | |||
IOExpanderPort portB(1, ~0); | |||
ColPort_MCP23018 colPortB(portB, 1<<2 | 1<<3 ); | |||
colPins are read from pin 0 on up. | |||
Diode orientation | |||
---------------- | |||
Rows, columns, and diode orientation are explained in Matrix.h | |||
*/ | |||
class ColPort_MCP23018 : public ColPort | |||
{ | |||
private: | |||
IOExpanderPort& port; | |||
const uint8_t IODIR; //Input/Ouput Direction register | |||
const uint8_t GPIO; //General Purpose Input/Ouput register | |||
const uint8_t GPPU; //General Purpose Pullup register | |||
public: | |||
//The constructor initialization list is in .cpp | |||
ColPort_MCP23018(IOExpanderPort& port, const uint8_t colPins); | |||
void begin(uint8_t activeHigh); | |||
//read port and store result in portState | |||
virtual void read(); | |||
}; | |||
#endif |
@@ -1,11 +0,0 @@ | |||
#include "LED_AVR.h" | |||
void LED_AVR::on() | |||
{ | |||
PORT |= pin; //set pin high | |||
} | |||
void LED_AVR::off() | |||
{ | |||
PORT &= ~pin; //set pin low | |||
} |
@@ -1,21 +0,0 @@ | |||
#ifndef LED_AVR_H | |||
#define LED_AVR_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <LED.h> | |||
/* A LED_AVR object is an AVR pin that is used to power an LED on and off. | |||
DDRx Data Direction Register is configured as output in RowPort_AVR constructor. | |||
*/ | |||
class LED_AVR: public LED | |||
{ | |||
private: | |||
volatile unsigned char& PORT; | |||
const uint8_t pin; //bitwise pin to LED | |||
public: | |||
LED_AVR(volatile unsigned char& PORTx, const uint8_t pin): PORT(PORTx), pin(pin) {} | |||
virtual void on(); | |||
virtual void off(); | |||
}; | |||
#endif |
@@ -1,17 +0,0 @@ | |||
#include "LED_MCP23018.h" | |||
void LED_MCP23018::on() | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(GPIO); | |||
Wire.write(port.outputVal &= ~pin); //set pin low (sink) | |||
Wire.endTransmission(); | |||
} | |||
void LED_MCP23018::off() | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(GPIO); | |||
Wire.write(port.outputVal |= pin); //set pin high (sink off) | |||
Wire.endTransmission(); | |||
} |
@@ -1,35 +0,0 @@ | |||
#ifndef LED_MCP23018_H | |||
#define LED_MCP23018_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <LED.h> | |||
#include "IOExpanderPort.h" | |||
/* Class LED_MCP23018 uses a MCP23018 I/O expander pin to turn a LED on and off. | |||
Connect the LED in series with the resistor: | |||
determin resistor value needed (Internet search: LED resistor value) | |||
Connect the LED's (-) ground to the AVR output pin | |||
connect LED's (+) to power | |||
Never connect a LED directly from ground to power. Doing so would destroy the LED. | |||
MCP23018 ouput is open drain. The output acts like a switch to ground. | |||
It cannot produce a high signal by itself. | |||
*/ | |||
class LED_MCP23018: public LED | |||
{ | |||
private: | |||
IOExpanderPort& port; | |||
const uint8_t GPIO; //General Purpose Input/Ouput register address | |||
const uint8_t pin; //bitwise pin to LED | |||
public: | |||
LED_MCP23018(IOExpanderPort& port, const uint8_t pin) | |||
: port(port), GPIO(port.num + 0x12), pin(pin) {} | |||
virtual void on(); | |||
virtual void off(); | |||
}; | |||
#endif |
@@ -1,12 +0,0 @@ | |||
#include "Matrix.h" | |||
/* | |||
scan every row of matrix one time | |||
*/ | |||
void Matrix::scan() | |||
{ | |||
for (uint8_t i=0; i < rowCount; i++) | |||
{ | |||
ptrsRows[i]->process(); | |||
} | |||
} |
@@ -1,38 +0,0 @@ | |||
#ifndef MATRIX_H | |||
#define MATRIX_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include "RowBase.h" | |||
/* | |||
Diode orientation | |||
---------------- | |||
A keyboard's physically matrix is composed of rows and columns. | |||
The rows and columns are physically connected to the keys. | |||
The rows and columns are distinguishable by diode orientation (not horizontal/vertical). | |||
For active low diode orientation is: | |||
cathodes on rows | |||
anodes on columns | |||
For active high diode orientation is reversed: | |||
anodes on rows | |||
cathodes on columns | |||
Pull-down resistors | |||
------------------- | |||
If Matrix uses active low, IC requires one pull-up resistor on each ColPort::colPins. | |||
If Matrix uses active high, IC requires one pull-down resistor on each ColPort::colPins. | |||
External pull-down resistors should have a value between 10k Ohms and 2.2k Ohms. | |||
*/ | |||
class Matrix | |||
{ | |||
private: | |||
RowBase *const *const ptrsRows; //array of row pointers | |||
const uint8_t rowCount; | |||
public: | |||
Matrix( RowBase *const ptrsRows[], const uint8_t rowCount) | |||
: ptrsRows(ptrsRows), rowCount(rowCount) {} | |||
void scan(); | |||
}; | |||
#endif |
@@ -1,34 +0,0 @@ | |||
#include "RowPort_AVR_Optic.h" | |||
/* | |||
configures row port's DDRx and PORTx pins as output. | |||
*/ | |||
RowPort_AVR_Optic::RowPort_AVR_Optic | |||
(volatile unsigned char& DDRx, volatile unsigned char& PORTx) | |||
: DDR(DDRx = ~0), PORT(PORTx) | |||
{} | |||
/* | |||
activePin is a port mask, where active pin is 1. | |||
*/ | |||
void RowPort_AVR_Optic::setActivePinLow(const uint8_t activePin) | |||
{ | |||
PORT &= ~activePin; | |||
} | |||
/* | |||
activePin is port mask, where active pin is 1. | |||
The delayMicroseconds() is for DodoHand keyboard's optic switches. | |||
Strobe needs to be turned on for >= 300µs before the columns are read. | |||
During this time the state of the columns are settling into their actual values. | |||
Seems to be necessary in order to allow the phototransistors to turn completely off. | |||
(delay is not need for I/O expander because time between I2C Transmissions) | |||
(Teensy2 ATMEGA32U4 16 MHz is a 0.0625 µs period) | |||
*/ | |||
void RowPort_AVR_Optic::setActivePinHigh(const uint8_t activePin) | |||
{ | |||
//strobe row on | |||
PORT |= activePin; | |||
delayMicroseconds(300); //wait for the column value to stabilize after strobe | |||
} |
@@ -1,40 +0,0 @@ | |||
#ifndef ROWPORT_AVR_OPTIC_H | |||
#define ROWPORT_AVR_OPTIC_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <RowPort.h> | |||
/* One AVR microcontroller port connected to matrix rows. | |||
setActivePinHigh() has a delay to allow phototransistors time to sense strobe | |||
(DodoHand has optic switches with phototransistors). | |||
Instantiation | |||
------------ | |||
The constructor configures all pins of port as output (for strobe pins and LED). | |||
The 'x' in parameters DDRx, PORTx, and PINx should all be the same letter. | |||
Example instantiation for row port F: | |||
RowPort_AVR_Optic rowPortF(DDRF, PORTF); | |||
Diode orientation | |||
---------------- | |||
Rows, columns, and diode orientation are explained in Matrix.h | |||
*/ | |||
class RowPort_AVR_Optic : public RowPort | |||
{ | |||
private: | |||
const volatile unsigned char& DDR; //Data Direction Register | |||
protected: | |||
volatile unsigned char& PORT; //PORT register | |||
public: | |||
//The constructor initialization list is in .cpp | |||
RowPort_AVR_Optic(volatile unsigned char& DDRx, volatile unsigned char& PORTx); | |||
virtual void setActivePinLow(const uint8_t activePin); //activePin is a port mask | |||
virtual void setActivePinHigh(const uint8_t activePin); | |||
}; | |||
#endif |
@@ -1,40 +0,0 @@ | |||
#include "RowPort_MCP23018.h" | |||
/* | |||
configures column port's IODIR, GPIO. | |||
*/ | |||
RowPort_MCP23018::RowPort_MCP23018(IOExpanderPort& port) | |||
: port(port), IODIR(port.num), GPIO(port.num + 0x12) | |||
{} | |||
void RowPort_MCP23018::begin() | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(IODIR); | |||
Wire.write(0); //0=configure as output (for strobe pins and LED pins) | |||
Wire.endTransmission(); | |||
} | |||
/* | |||
sets activePin pin output to low. | |||
activePin is port mask, where active-low pin is 1. | |||
*/ | |||
void RowPort_MCP23018::setActivePinLow(const uint8_t activePin) | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(GPIO); | |||
Wire.write(port.outputVal &= ~activePin); | |||
Wire.endTransmission(); | |||
} | |||
/* | |||
sets activePin pin output to high, does not reset the other pins because they might be used by LEDs. | |||
activePin is port mask, where active-high pin is 1. | |||
*/ | |||
void RowPort_MCP23018::setActivePinHigh(const uint8_t activePin) | |||
{ | |||
Wire.beginTransmission(port.ADDR); | |||
Wire.write(GPIO); | |||
Wire.write(port.outputVal |= activePin); | |||
Wire.endTransmission(); | |||
} |
@@ -1,46 +0,0 @@ | |||
#ifndef ROWPORT_MCP23018_H | |||
#define ROWPORT_MCP23018_H | |||
#include <Arduino.h> | |||
#include <inttypes.h> | |||
#include <Wire.h> | |||
#include <RowPort.h> | |||
#include "IOExpanderPort.h" | |||
/* One MCP23018 I/O expander port connected to matrix rows. | |||
begin() configures column port's IODIR, GPIO. | |||
This should normally be called only once. | |||
Instantiation | |||
------------ | |||
Example instantiation for row port A: | |||
IOExpanderPort portA(0, ~0); | |||
RowPort_MCP23018 rowPortA(portA); | |||
Example instantiation for row port B: | |||
IOExpanderPort portB(1, ~0); | |||
RowPort_MCP23018 rowPortB(portB); | |||
Diode orientation | |||
---------------- | |||
Rows, columns, and diode orientation are explained in Matrix.h | |||
MCP23018 data sheet | |||
------------------ | |||
http://ww1.microchip.com/downloads/en/DeviceDoc/22103a.pdf | |||
*/ | |||
class RowPort_MCP23018 : public RowPort | |||
{ | |||
private: | |||
IOExpanderPort& port; | |||
const uint8_t IODIR; //Input/Ouput Direction register address | |||
const uint8_t GPIO; //General Purpose Input/Ouput register address | |||
public: | |||
//The constructor initialization list is in .cpp | |||
RowPort_MCP23018(IOExpanderPort& port); | |||
void begin(); | |||
virtual void setActivePinLow(const uint8_t activePin); //activePin is a port mask | |||
virtual void setActivePinHigh(const uint8_t activePin); | |||
}; | |||
#endif |
@@ -13,17 +13,17 @@ Using smaller types on a 32-bit uC (Teensy LC) would accomplish nothing. | |||
For RowScanner_SPIShiftRegisters, RowScanner_SPIShiftRegisters::KEY_COUNT | |||
For RowScanner_PinsBitwise, cover the last 1 bit in RowScanner_PinsBitwise::strobePin | |||
*/ | |||
//typedef uint8_t read_pins_t; | |||
typedef uint8_t read_pins_t; | |||
//typedef uint16_t read_pins_t; | |||
typedef uint32_t read_pins_t; | |||
//typedef uint32_t read_pins_t; | |||
/* read_pins_mask_t is only used for rowMask and rowEnd, which extends one bit beyond the last col pin. | |||
uncomment typedef that covers one bit beyond the last col pin. | |||
This could be the same typedef as read_pins_t, or the next larger typedef. | |||
*/ | |||
//typedef uint8_t read_pins_mask_t; | |||
typedef uint8_t read_pins_mask_t; | |||
//typedef uint16_t read_pins_mask_t; | |||
typedef uint32_t read_pins_mask_t; | |||
//typedef uint32_t read_pins_mask_t; | |||
/* SAMPLE_COUNT = 4 is very reliable for a keyboard. | |||
Split keyboards with a long connecting wire or in environment with |