Add rotary encoder support, simplify AddMuxButton interface. #3
40
Joystick.cpp
40
Joystick.cpp
|
@ -43,7 +43,28 @@ void Joystick::AddButton(uint8_t pin, ButtonType type, bool pullup) {
|
|||
_BuildButton(pin, type, pullup);
|
||||
}
|
||||
|
||||
void Joystick::AddMuxButton(uint8_t pin, uint8_t mux_id, uint8_t mux_channel, ButtonType type, bool pullup) {
|
||||
void Joystick::AddEncoder(uint8_t pin0, uint8_t pin1, ButtonType type, bool pullup) {
|
||||
switch (type) {
|
||||
case ENCODER_PULSED_SPLIT:
|
||||
// add an encoder button. _BuildButton() doesn't do everything we need, however...
|
||||
Button *button = _BuildButton(pin0, type, pullup);
|
||||
|
||||
// ... so we set up the encoder stuff here. button->pin and button->bouncer will be
|
||||
// ignored
|
||||
button->encoder_button = true;
|
||||
button->encoder = new Encoder(pin0, pin1);
|
||||
long last_enc = button->encoder->read();
|
||||
break;
|
||||
default:
|
||||
if (_debug) {
|
||||
Serial.print("DEBUG: Unhandled encoder type: ");
|
||||
Serial.println(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Joystick::AddMuxButton(uint8_t mux_id, uint8_t mux_channel, ButtonType type, bool pullup) {
|
||||
uint8_t pin = _mux[mux_id]->signalPin().pin;
|
||||
Button *button = _BuildButton(pin, type, pullup);
|
||||
button->mux = true;
|
||||
button->mux_id = mux_id;
|
||||
|
@ -62,7 +83,7 @@ Button* Joystick::_BuildButton(uint8_t pin, ButtonType type, bool pullup) {
|
|||
uint8_t increment = 1;
|
||||
button.vbutton0 = _virtual_buttons;
|
||||
|
||||
if (type == BUTTON_PULSED_DOUBLE_ACTION_SPLIT) {
|
||||
if (type & (BUTTON_PULSED_DOUBLE_ACTION_SPLIT | ENCODER_PULSED_SPLIT)) {
|
||||
increment = 2;
|
||||
button.vbutton1 = _virtual_buttons + 1;
|
||||
}
|
||||
|
@ -99,7 +120,11 @@ void Joystick::Update() {
|
|||
JoyReport oldReport = _joyReport;
|
||||
|
||||
for (uint8_t i = 0; i < _num_buttons; i++) {
|
||||
_UpdateButton(i);
|
||||
if (_buttons[i].type == ENCODER_PULSED_SPLIT) { // todo: make this check for any encoder type
|
||||
_UpdateEncoder(i);
|
||||
} else {
|
||||
_UpdateButton(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < _num_axes; i++) {
|
||||
|
@ -167,6 +192,7 @@ void Joystick::Write() {
|
|||
delay(250);
|
||||
}
|
||||
|
||||
// todo: bite the bullet and use inheritance here, this is getting out of hand
|
||||
void Joystick::_UpdateButton(uint8_t button_num) {
|
||||
Button *button = &_buttons[button_num];
|
||||
if (button->mux) {
|
||||
|
@ -212,6 +238,14 @@ void Joystick::_UpdateButton(uint8_t button_num) {
|
|||
}
|
||||
}
|
||||
|
||||
void Joystick::_UpdateEncoder(uint8_t index) {
|
||||
Button *button = &_buttons[index];
|
||||
long new_value = button->encoder->read();
|
||||
if (new_value > button->last_enc) PressButton(button->vbutton0);
|
||||
else if (new_value < button->last_enc) PressButton(button->vbutton1);
|
||||
button->last_enc = new_value;
|
||||
}
|
||||
|
||||
void Joystick::_UpdateAxis(uint8_t index) {
|
||||
if (_debug) Serial.println("STUB: Joystick::_UpdateAxis");
|
||||
}
|
||||
|
|
19
Joystick.h
19
Joystick.h
|
@ -1,9 +1,10 @@
|
|||
#ifndef _JOYSTICK_H_
|
||||
#define _JOYSTICK_H_
|
||||
|
||||
#include <Mux.h>
|
||||
#include <Arduino.h>
|
||||
#include <Bounce2.h>
|
||||
#include <Encoder.h>
|
||||
#include <Mux.h>
|
||||
|
||||
using namespace admux;
|
||||
|
||||
|
@ -27,7 +28,8 @@ enum ButtonType {
|
|||
BUTTON_PULSED = 0x2, // on button press, send an on signal followed immediately by an off signal.
|
||||
BUTTON_PULSED_DOUBLE_ACTION = 0x4, // Send a button press twice - once for press and once for release.
|
||||
BUTTON_PULSED_DOUBLE_ACTION_SPLIT = 0x8, // Send two separate button presses - one button on press, another on release.
|
||||
BUTTON_LATCHED_MOMENTARY = 0x10
|
||||
BUTTON_LATCHED_MOMENTARY = 0x10,
|
||||
ENCODER_PULSED_SPLIT = 0x20 // A rotary encoder that should be treated as two different pulsed/momentary buttons, one for each direction
|
||||
};
|
||||
|
||||
struct JoyReport {
|
||||
|
@ -43,10 +45,16 @@ struct Button {
|
|||
bool pressed = false; // only used by BUTTON_LATCHED_MOMENTARY
|
||||
bool inverted = false; // if true, send button press on release and vice versa.
|
||||
|
||||
// multiplexer button settings
|
||||
// todo: this should probably be abstracted out from this struct...
|
||||
bool mux;
|
||||
uint8_t mux_id;
|
||||
uint8_t mux_channel;
|
||||
|
||||
// encoder button settings
|
||||
bool encoder_button;
|
||||
Encoder* encoder;
|
||||
long last_enc;
|
||||
};
|
||||
|
||||
bool operator ==(JoyReport a, JoyReport b);
|
||||
|
@ -64,7 +72,9 @@ class Joystick {
|
|||
// If `pullup` is false, your button should connect the pin to VCC.
|
||||
// Mux parameters are ignored unless `mux` is true.
|
||||
void AddButton(uint8_t pin, ButtonType type, bool pullup=true);
|
||||
void AddMuxButton(uint8_t pin, uint8_t mux_id, uint8_t mux_channel, 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 pin0, uint8_t pin1, ButtonType type, bool pullup=true);
|
||||
void AddMuxButton(uint8_t mux_id, uint8_t mux_channel, ButtonType type, bool pullup=true);
|
||||
|
||||
// Add an analog axis to the joystick. THIS METHOD IS NOT CURRENTLY TESTED OR SUPPORTED. It might work, but probably not.
|
||||
void AddAxis(uint8_t pin);
|
||||
|
@ -83,6 +93,7 @@ class Joystick {
|
|||
|
||||
void _ReleasePulsedButtons();
|
||||
void _UpdateButton(uint8_t index);
|
||||
void _UpdateEncoder(uint8_t index);
|
||||
void _UpdateAxis(uint8_t index);
|
||||
|
||||
Button* _BuildButton(uint8_t pin, ButtonType type, bool pullup);
|
||||
|
@ -103,6 +114,6 @@ class Joystick {
|
|||
};
|
||||
|
||||
// Internal use only.
|
||||
#define _BUTTON_PULSED_TYPES (BUTTON_PULSED | BUTTON_PULSED_DOUBLE_ACTION | BUTTON_PULSED_DOUBLE_ACTION_SPLIT)
|
||||
#define _BUTTON_PULSED_TYPES (BUTTON_PULSED | BUTTON_PULSED_DOUBLE_ACTION | BUTTON_PULSED_DOUBLE_ACTION_SPLIT | ENCODER_PULSED_SPLIT)
|
||||
|
||||
#endif
|
||||
|
|
8
examples/full/Makefile
Normal file
8
examples/full/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}
|
38
examples/full/full.ino
Normal file
38
examples/full/full.ino
Normal file
|
@ -0,0 +1,38 @@
|
|||
// An example sketch using the joystick library.
|
||||
// This example includes every possible feature of the library.
|
||||
// It assumes an Arduino Nano and a 16-channel multiplexer.
|
||||
|
||||
#include <Joystick.h>
|
||||
#include <Mux.h>
|
||||
|
||||
using admux::Pinset;
|
||||
|
||||
bool debug = false;
|
||||
Joystick joystick(debug);
|
||||
|
||||
void setup() {
|
||||
joystick.AddButton(2, BUTTON_PASSTHRU); // this button will always transfer its current literal state to the computer
|
||||
|
||||
joystick.AddButton(3, BUTTON_LATCHED_MOMENTARY); // this button will start sending a buttonpress on one push, and keep it "held down" until it is pushed again.
|
||||
|
||||
joystick.AddButton(4, BUTTON_PULSED); // this button will send a buttonpress very briefly every time it is activated. Good for a toggle switch that shouldn't be "latched" in practice.
|
||||
|
||||
joystick.AddButton(5, BUTTON_PULSED_DOUBLE_ACTION); // like the above, but it sends its button press when toggled on *and* when toggled off
|
||||
|
||||
joystick.AddButton(6, BUTTON_PULSED_DOUBLE_ACTION_SPLIT); // again, similar to the above, but it sends two *different* button presses - 'on' will be one button, 'off' another.
|
||||
|
||||
joystick.AddEncoder(7, 8, ENCODER_PULSED_SPLIT); // a rotary encoder that will send 2 different buttonpresses - one when the encoder is turned clockwise, another when it is turned counterclockwise.
|
||||
|
||||
Pinset addr_pins = Pinset(10, 11, 12, 13);
|
||||
uint8_t mux_id = joystick.AddMux(9, addr_pins);
|
||||
|
||||
joystick.AddMuxButton(mux_id, 0, BUTTON_PASSTHRU);
|
||||
|
||||
// start up serial communication
|
||||
joystick.Init();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// check all the button states and send any changes
|
||||
joystick.Update();
|
||||
}
|
|
@ -32,14 +32,14 @@ void setup() {
|
|||
uint8_t mux = joystick.AddMux(A1, admux::Pinset(A2, A3, A4, A5), 4);
|
||||
|
||||
// now we can add the rest of the buttons
|
||||
joystick.AddMuxButton(A1, mux, 0, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(A1, mux, 1, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(A1, mux, 2, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(A1, mux, 3, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(A1, mux, 4, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(A1, mux, 5, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(A1, mux, 6, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(A1, mux, 7, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 0, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 1, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 2, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 3, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 4, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 5, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 6, BUTTON_PASSTHRU);
|
||||
joystick.AddMuxButton(mux, 7, BUTTON_PASSTHRU);
|
||||
|
||||
joystick.Init();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user