Rework example code, fix bugs and get to compiling state. Also introduce missing logic for the Matrix code to keep track of what column is active.
This commit is contained in:
parent
8ebc1a5523
commit
690afdbce5
14
Button.cpp
14
Button.cpp
|
@ -32,9 +32,9 @@ LatchedButton::LatchedButton(uint8_t vbutton, Reader* reader) : Button(vbutton,
|
|||
}
|
||||
|
||||
bool LatchedButton::Update(Joystick* js) {
|
||||
if (!BouncerUpdate()) return false;
|
||||
if (!reader->Update()) return false;
|
||||
|
||||
if (On()) {
|
||||
if (reader->On()) {
|
||||
if (!pressed) {
|
||||
js->PressButton(vbutton);
|
||||
pressed = true;
|
||||
|
@ -48,7 +48,7 @@ bool LatchedButton::Update(Joystick* js) {
|
|||
}
|
||||
|
||||
|
||||
PulsedButton::PulsedButton(uint8_t pin, uint8_t vbutton, bool double_action, bool split, bool pullup, Mux* mux, bool analog_only) : SwitchButton(pin, vbutton, pullup, mux, analog_only) {
|
||||
PulsedButton::PulsedButton(uint8_t vbutton, Reader* reader, bool double_action, bool split) : Button(vbutton, reader) {
|
||||
this->release_time1 = 0;
|
||||
this->release_time2 = 0;
|
||||
if (double_action) {
|
||||
|
@ -74,18 +74,18 @@ bool PulsedButton::Update(Joystick* js) {
|
|||
release_time2 = 0;
|
||||
}
|
||||
|
||||
if (!BouncerUpdate()) return false;
|
||||
if (!reader->Update()) return false;
|
||||
|
||||
switch(type) {
|
||||
case BUTTON_PULSED:
|
||||
if (On()) js->PressButton(vbutton);
|
||||
if (reader->On()) js->PressButton(vbutton);
|
||||
break;
|
||||
case BUTTON_PULSED_DOUBLE_ACTION:
|
||||
js->PressButton(vbutton);
|
||||
release_time1 = millis() + 250;
|
||||
break;
|
||||
case BUTTON_PULSED_DOUBLE_ACTION_SPLIT:
|
||||
if (On()) {
|
||||
if (reader->On()) {
|
||||
js->PressButton(vbutton);
|
||||
release_time1 = millis() + 250;
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ bool PulsedButton::Update(Joystick* js) {
|
|||
}
|
||||
|
||||
|
||||
EncoderButton::EncoderButton(uint8_t pin1, uint8_t pin2, uint8_t vbutton) : Button(vbutton) {
|
||||
EncoderButton::EncoderButton(uint8_t pin1, uint8_t pin2, uint8_t vbutton) : Button(vbutton, NULL) {
|
||||
this->type = ENCODER_PULSED_SPLIT;
|
||||
this->vbutton2 = vbutton + 1;
|
||||
this->encoder = new Encoder(pin1, pin2);
|
||||
|
|
|
@ -48,8 +48,8 @@ void Joystick::AddMuxButton(uint8_t channel, Mux* mux, ButtonType type, bool pul
|
|||
_addButton(type, new MuxReader(channel, mux, pullup));
|
||||
}
|
||||
|
||||
void Joystick::AddMatrixButton(uint8_t row, uint8_t col, ButtonType type, bool pullup) {
|
||||
_addButton(type, new MatrixReader(row, col, pullup));
|
||||
void Joystick::AddMatrixButton(uint8_t row, uint8_t col, Matrix* matrix, ButtonType type, bool pullup) {
|
||||
_addButton(type, new MatrixReader(row, col, matrix, pullup));
|
||||
}
|
||||
|
||||
void Joystick::AddEncoder(uint8_t pin1, uint8_t pin2, ButtonType type) {
|
||||
|
@ -147,6 +147,7 @@ void Joystick::_UpdateAxis(uint8_t index) {
|
|||
}
|
||||
|
||||
void Joystick::_addButton(ButtonType type, Reader* reader) {
|
||||
Button* button;
|
||||
switch (type) {
|
||||
case BUTTON_PASSTHRU:
|
||||
button = new PassthruButton(_virtual_buttons, reader);
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#define _JOYSTICK_H_
|
||||
|
||||
#include "Button.h"
|
||||
#include "Matrix.h"
|
||||
#include <Arduino.h>
|
||||
#include <Bounce2.h>
|
||||
#include <Mux.h>
|
||||
|
||||
using namespace admux;
|
||||
|
@ -41,7 +41,7 @@ class Joystick {
|
|||
// on the Arduino Nano.
|
||||
void AddButton(uint8_t pin, ButtonType type, bool pullup=true);
|
||||
void AddMuxButton(uint8_t channel, Mux* mux, ButtonType type, bool pullup=true);
|
||||
void AddMatrixButton(uint8_t row, uint8_t col, ButtonType type, bool pullup=true);
|
||||
void AddMatrixButton(uint8_t row, uint8_t col, Matrix* matrix, ButtonType type, bool pullup=true);
|
||||
|
||||
// Add a rotary encoder. ENCODER button types allow you to treat an encoder as a momentary button or an axis (TODO)
|
||||
void AddEncoder(uint8_t pin1, uint8_t pin2, ButtonType type);
|
||||
|
|
39
Matrix.cpp
Normal file
39
Matrix.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include "Matrix.h"
|
||||
|
||||
Matrix::Matrix(uint8_t* columns, bool inverted) {
|
||||
this->columns = columns;
|
||||
this->num_columns = sizeof(columns);
|
||||
this->active_pin = num_columns;
|
||||
this->inverted = inverted;
|
||||
|
||||
for (uint8_t i = 0; i < num_columns; i++) {
|
||||
pinMode(columns[i], OUTPUT);
|
||||
if (inverted) digitalWrite(columns[i], HIGH);
|
||||
else digitalWrite(columns[i], LOW);
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix::Activate(uint8_t column) {
|
||||
if (column > num_columns) return; // TODO: throw an error here?
|
||||
|
||||
uint8_t pin = columns[column];
|
||||
if (pin == active_pin) return;
|
||||
|
||||
if (active_pin != num_columns) {
|
||||
_disable(active_pin);
|
||||
}
|
||||
|
||||
_enable(pin);
|
||||
active_pin = pin;
|
||||
delayMicroseconds(10); // allow ample time for signal to propagate
|
||||
}
|
||||
|
||||
void Matrix::_enable(uint8_t pin) {
|
||||
if (inverted) digitalWrite(pin, LOW);
|
||||
else digitalWrite(pin, HIGH);
|
||||
}
|
||||
|
||||
void Matrix::_disable(uint8_t pin) {
|
||||
if (inverted) digitalWrite(pin, HIGH);
|
||||
else digitalWrite(pin, LOW);
|
||||
}
|
24
Matrix.h
Normal file
24
Matrix.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
// A state-keeping class used with MatrixReader. Keeps track of which column is active,
|
||||
// switches between them.
|
||||
|
||||
#ifndef _MATRIX_H_
|
||||
#define _MATRIX_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
class Matrix {
|
||||
public:
|
||||
Matrix(uint8_t *columns, bool inverted=true);
|
||||
void Activate(uint8_t column);
|
||||
|
||||
private:
|
||||
void _enable(uint8_t pin);
|
||||
void _disable(uint8_t pin);
|
||||
|
||||
uint8_t* columns;
|
||||
uint8_t active_pin;
|
||||
uint8_t num_columns;
|
||||
bool inverted;
|
||||
};
|
||||
|
||||
#endif
|
15
Reader.cpp
15
Reader.cpp
|
@ -1,8 +1,5 @@
|
|||
#include "Reader.h"
|
||||
|
||||
#include <Mux.h>
|
||||
#include <Bounce2.h>
|
||||
|
||||
|
||||
Reader::Reader(bool inverted) {
|
||||
this->inverted = inverted;
|
||||
|
@ -22,7 +19,7 @@ uint8_t Reader::getMode(bool pullup) {
|
|||
|
||||
DirectReader::DirectReader(uint8_t pin, bool inverted) : Reader(inverted) {
|
||||
uint8_t mode = getMode(inverted);
|
||||
this->bouncer.attach(pin)
|
||||
this->bouncer.attach(pin);
|
||||
}
|
||||
|
||||
bool DirectReader::Update() {
|
||||
|
@ -42,20 +39,16 @@ bool MuxReader::Update() {
|
|||
}
|
||||
|
||||
|
||||
MatrixReader::MatrixReader(uint8_t row, uint8_t col, bool inverted) : Reader(inverted) {
|
||||
MatrixReader::MatrixReader(uint8_t row, uint8_t col, Matrix* matrix, bool inverted) : Reader(inverted) {
|
||||
uint8_t mode = getMode(inverted);
|
||||
this->bouncer.attach(row, mode);
|
||||
this->col = col;
|
||||
this->matrix = matrix;
|
||||
}
|
||||
|
||||
bool MatrixReader::Update() {
|
||||
digitalWrite(col, LOW);
|
||||
delayMicroseconds(10);
|
||||
|
||||
matrix->Activate(col);
|
||||
bool changed = bouncer.update();
|
||||
|
||||
digitalWrite(col, HIGH);
|
||||
delayMicroseconds(10);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
|
14
Reader.h
14
Reader.h
|
@ -4,9 +4,13 @@
|
|||
#ifndef _READER_H_
|
||||
#define _READER_H_
|
||||
|
||||
#include "Matrix.h"
|
||||
#include <Arduino.h>
|
||||
#include <Bounce2.h>
|
||||
#include <Mux.h>
|
||||
|
||||
using namespace admux;
|
||||
|
||||
// The abstract base class - a very simple interface
|
||||
class Reader {
|
||||
public:
|
||||
|
@ -24,7 +28,7 @@ class Reader {
|
|||
|
||||
|
||||
// A standard reader; the button is connected directly to a switch
|
||||
class DirectReader {
|
||||
class DirectReader : public Reader {
|
||||
public:
|
||||
DirectReader(uint8_t pin, bool inverted = true);
|
||||
bool Update();
|
||||
|
@ -33,27 +37,29 @@ class DirectReader {
|
|||
|
||||
|
||||
// The button is connected to a Multiplexer channel
|
||||
class MuxReader {
|
||||
class MuxReader : public Reader {
|
||||
public:
|
||||
MuxReader(uint8_t channel, Mux* mux, bool inverted = true);
|
||||
bool Update();
|
||||
bool On();
|
||||
|
||||
protected:
|
||||
uint8_t channel;
|
||||
Mux * mux;
|
||||
};
|
||||
|
||||
|
||||
// The button is connected via a scan matrix
|
||||
// "row" should always be the input, with "col" the selecter.
|
||||
class MatrixReader {
|
||||
class MatrixReader : public Reader {
|
||||
public:
|
||||
MatrixReader(uint8_t row, uint8_t col, bool inverted = true);
|
||||
MatrixReader(uint8_t row, uint8_t col, Matrix* matrix, bool inverted = true);
|
||||
bool Update();
|
||||
bool On();
|
||||
|
||||
protected:
|
||||
uint8_t col;
|
||||
Matrix* matrix;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
97
example/example.ino
Normal file
97
example/example.ino
Normal file
|
@ -0,0 +1,97 @@
|
|||
// An example sketch using the joystick library, demonstrating recommended usage
|
||||
// of all features.
|
||||
|
||||
#include <Joystick.h>
|
||||
#include <Matrix.h>
|
||||
#include <Mux.h>
|
||||
|
||||
using namespace admux;
|
||||
|
||||
// Always use defines to match your pins to their logical wiring
|
||||
|
||||
// pins 2 and 3 are attached to a rotary encoder
|
||||
#define ENCODER 2,3
|
||||
|
||||
// these buttons are attached directly to Arduino input pins
|
||||
#define BTN1 4
|
||||
#define BTN2 5
|
||||
#define BTN3 6
|
||||
#define BTN4 7
|
||||
|
||||
// pins 8-13 are attached to a 3x3 scanning input matrix. Pins 8-10 are the row pins, 11-13 are the column pins
|
||||
// However, note that the column pins are 0-indexed; the actual pins are defined in the Matrix object later.
|
||||
#define MATRIX1 8,0
|
||||
#define MATRIX2 9,0
|
||||
#define MATRIX3 10,0
|
||||
#define MATRIX4 8,1
|
||||
#define MATRIX5 9,1
|
||||
#define MATRIX6 10,1
|
||||
#define MATRIX7 8,2
|
||||
#define MATRIX8 9,2
|
||||
#define MATRIX9 10,2
|
||||
|
||||
// A multiplexer is attached to pins A1-A5
|
||||
#define MUX_SIG A1 // the multiplexer's signal pin is on Analog 1
|
||||
#define MUX_ADDR A2,A3,A4,A5 // the multiplexer's address pins are A2-A5, in that order
|
||||
|
||||
// These are 3 buttons attached to the multiplexer channels
|
||||
#define MUX_BTN1 0
|
||||
#define MUX_BTN2 1
|
||||
#define MUX_BTN3 2
|
||||
|
||||
|
||||
bool debug = false;
|
||||
Joystick js(debug);
|
||||
|
||||
void setup() {
|
||||
js.AddEncoder(ENCODER, ENCODER_PULSED_SPLIT);
|
||||
|
||||
// Different types of button programming are available. BUTTON_PASSTHRU simply passes on the button's
|
||||
// real state, and will be the most common, but you can also change how the button works in software like so...
|
||||
|
||||
// With BUTTON_PULSED, no matter how long the button stays held down, it will only send a button press for 250ms
|
||||
// then deactivate until pressed again.
|
||||
js.AddButton(BTN1, BUTTON_PULSED);
|
||||
|
||||
// BUTTON_PULSED_DOUBLE_ACTION does the same thing, but sends a *second* 250ms press when the button is deactivated
|
||||
// This is great for an on-off toggle switch that should send an "event" in both directions.
|
||||
js.AddButton(BTN2, BUTTON_PULSED_DOUBLE_ACTION);
|
||||
|
||||
// BUTTON_PULSED_DOUBLE_ACTION_SPLIT is just like the above, but it sends *different* button presses for the "on"
|
||||
// and "off" states.
|
||||
js.AddButton(BTN3, BUTTON_PULSED_DOUBLE_ACTION_SPLIT);
|
||||
|
||||
// BUTTON_LATCHED_MOMENTARY lets you turn a momentary pushbutton into a toggle switch.
|
||||
// One press will "press and hold" the button. The next press releases the button.
|
||||
js.AddButton(BTN4, BUTTON_LATCHED_MOMENTARY);
|
||||
|
||||
// One way to get more room for inputs is to use a scan matrix.
|
||||
// See http://blog.komar.be/how-to-make-a-keyboard-the-matrix/ for a very detailed discussion of how these work.
|
||||
// This is a 3x3 example, so we can get 9 buttons out of 6 inputs.
|
||||
// For faster read results, always add buttons so that buttons with the same *column* are grouped together.
|
||||
uint8_t cols[] = {11, 12, 13};
|
||||
Matrix* matrix = new Matrix(cols);
|
||||
js.AddMatrixButton(MATRIX1, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX2, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX3, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX4, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX5, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX6, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX7, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX8, matrix, BUTTON_PASSTHRU);
|
||||
js.AddMatrixButton(MATRIX9, matrix, BUTTON_PASSTHRU);
|
||||
|
||||
// another way to get more room for our inputs, this code adds a 16-channel multiplexer.
|
||||
// It only attaches 3 buttons, but could attach up to channel 15.
|
||||
Mux* mux = new Mux(Pin(MUX_SIG, INPUT_PULLUP, PinType::Digital), Pinset(MUX_ADDR));
|
||||
js.AddMuxButton(MUX_BTN1, mux, BUTTON_PASSTHRU);
|
||||
js.AddMuxButton(MUX_BTN2, mux, BUTTON_PASSTHRU);
|
||||
js.AddMuxButton(MUX_BTN3, mux, BUTTON_PASSTHRU);
|
||||
|
||||
js.Init();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check all the button states and send any changes
|
||||
js.Update();
|
||||
}
|
8
example/obsolete/multiplexer/Makefile
Normal file
8
example/obsolete/multiplexer/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
TARGET_BOARD=arduino:avr:uno
|
||||
COM_PORT=/dev/ttyACM0
|
||||
|
||||
build:
|
||||
arduino-cli compile -b ${TARGET_BOARD}
|
||||
|
||||
upload:
|
||||
arduino-cli upload -b ${TARGET_BOARD} -p ${COM_PORT}
|
Loading…
Reference in New Issue
Block a user