Compare commits
2 Commits
564f4b2b57
...
346e612f65
Author | SHA1 | Date | |
---|---|---|---|
346e612f65 | |||
09043919de |
40
Joystick.cpp
40
Joystick.cpp
|
@ -43,7 +43,28 @@ void Joystick::AddButton(uint8_t pin, ButtonType type, bool pullup) {
|
||||||
_BuildButton(pin, type, 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 *button = _BuildButton(pin, type, pullup);
|
||||||
button->mux = true;
|
button->mux = true;
|
||||||
button->mux_id = mux_id;
|
button->mux_id = mux_id;
|
||||||
|
@ -62,7 +83,7 @@ Button* Joystick::_BuildButton(uint8_t pin, ButtonType type, bool pullup) {
|
||||||
uint8_t increment = 1;
|
uint8_t increment = 1;
|
||||||
button.vbutton0 = _virtual_buttons;
|
button.vbutton0 = _virtual_buttons;
|
||||||
|
|
||||||
if (type == BUTTON_PULSED_DOUBLE_ACTION_SPLIT) {
|
if (type & (BUTTON_PULSED_DOUBLE_ACTION_SPLIT | ENCODER_PULSED_SPLIT)) {
|
||||||
increment = 2;
|
increment = 2;
|
||||||
button.vbutton1 = _virtual_buttons + 1;
|
button.vbutton1 = _virtual_buttons + 1;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +120,11 @@ void Joystick::Update() {
|
||||||
JoyReport oldReport = _joyReport;
|
JoyReport oldReport = _joyReport;
|
||||||
|
|
||||||
for (uint8_t i = 0; i < _num_buttons; i++) {
|
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++) {
|
for (uint8_t i = 0; i < _num_axes; i++) {
|
||||||
|
@ -167,6 +192,7 @@ void Joystick::Write() {
|
||||||
delay(250);
|
delay(250);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: bite the bullet and use inheritance here, this is getting out of hand
|
||||||
void Joystick::_UpdateButton(uint8_t button_num) {
|
void Joystick::_UpdateButton(uint8_t button_num) {
|
||||||
Button *button = &_buttons[button_num];
|
Button *button = &_buttons[button_num];
|
||||||
if (button->mux) {
|
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) {
|
void Joystick::_UpdateAxis(uint8_t index) {
|
||||||
if (_debug) Serial.println("STUB: Joystick::_UpdateAxis");
|
if (_debug) Serial.println("STUB: Joystick::_UpdateAxis");
|
||||||
}
|
}
|
||||||
|
|
19
Joystick.h
19
Joystick.h
|
@ -1,9 +1,10 @@
|
||||||
#ifndef _JOYSTICK_H_
|
#ifndef _JOYSTICK_H_
|
||||||
#define _JOYSTICK_H_
|
#define _JOYSTICK_H_
|
||||||
|
|
||||||
#include <Mux.h>
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Bounce2.h>
|
#include <Bounce2.h>
|
||||||
|
#include <Encoder.h>
|
||||||
|
#include <Mux.h>
|
||||||
|
|
||||||
using namespace admux;
|
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 = 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 = 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_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 {
|
struct JoyReport {
|
||||||
|
@ -43,10 +45,16 @@ struct Button {
|
||||||
bool pressed = false; // only used by BUTTON_LATCHED_MOMENTARY
|
bool pressed = false; // only used by BUTTON_LATCHED_MOMENTARY
|
||||||
bool inverted = false; // if true, send button press on release and vice versa.
|
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...
|
// todo: this should probably be abstracted out from this struct...
|
||||||
bool mux;
|
bool mux;
|
||||||
uint8_t mux_id;
|
uint8_t mux_id;
|
||||||
uint8_t mux_channel;
|
uint8_t mux_channel;
|
||||||
|
|
||||||
|
// encoder button settings
|
||||||
|
bool encoder_button;
|
||||||
|
Encoder* encoder;
|
||||||
|
long last_enc;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator ==(JoyReport a, JoyReport b);
|
bool operator ==(JoyReport a, JoyReport b);
|
||||||
|
@ -64,7 +72,9 @@ class Joystick {
|
||||||
// If `pullup` is false, your button should connect the pin to VCC.
|
// If `pullup` is false, your button should connect the pin to VCC.
|
||||||
// Mux parameters are ignored unless `mux` is true.
|
// Mux parameters are ignored unless `mux` is true.
|
||||||
void AddButton(uint8_t pin, ButtonType type, bool pullup=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.
|
// 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);
|
void AddAxis(uint8_t pin);
|
||||||
|
@ -83,6 +93,7 @@ class Joystick {
|
||||||
|
|
||||||
void _ReleasePulsedButtons();
|
void _ReleasePulsedButtons();
|
||||||
void _UpdateButton(uint8_t index);
|
void _UpdateButton(uint8_t index);
|
||||||
|
void _UpdateEncoder(uint8_t index);
|
||||||
void _UpdateAxis(uint8_t index);
|
void _UpdateAxis(uint8_t index);
|
||||||
|
|
||||||
Button* _BuildButton(uint8_t pin, ButtonType type, bool pullup);
|
Button* _BuildButton(uint8_t pin, ButtonType type, bool pullup);
|
||||||
|
@ -103,6 +114,6 @@ class Joystick {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Internal use only.
|
// 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
|
#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);
|
uint8_t mux = joystick.AddMux(A1, admux::Pinset(A2, A3, A4, A5), 4);
|
||||||
|
|
||||||
// now we can add the rest of the buttons
|
// now we can add the rest of the buttons
|
||||||
joystick.AddMuxButton(A1, mux, 0, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 0, BUTTON_PASSTHRU);
|
||||||
joystick.AddMuxButton(A1, mux, 1, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 1, BUTTON_PASSTHRU);
|
||||||
joystick.AddMuxButton(A1, mux, 2, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 2, BUTTON_PASSTHRU);
|
||||||
joystick.AddMuxButton(A1, mux, 3, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 3, BUTTON_PASSTHRU);
|
||||||
joystick.AddMuxButton(A1, mux, 4, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 4, BUTTON_PASSTHRU);
|
||||||
joystick.AddMuxButton(A1, mux, 5, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 5, BUTTON_PASSTHRU);
|
||||||
joystick.AddMuxButton(A1, mux, 6, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 6, BUTTON_PASSTHRU);
|
||||||
joystick.AddMuxButton(A1, mux, 7, BUTTON_PASSTHRU);
|
joystick.AddMuxButton(mux, 7, BUTTON_PASSTHRU);
|
||||||
|
|
||||||
joystick.Init();
|
joystick.Init();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user