Compare commits

..

2 Commits

4 changed files with 64 additions and 30 deletions

View File

@ -13,7 +13,8 @@ void Button::ReleaseButtons(Joystick* js) {
js->ReleaseButton(vbutton); js->ReleaseButton(vbutton);
} }
SwitchButton::SwitchButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux) : Button(vbutton) { // TODO: make analog_only work... how to handle that with debouncer?
SwitchButton::SwitchButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux, bool analog_only) : Button(vbutton) {
this->mux = mux; this->mux = mux;
uint8_t mode = INPUT; uint8_t mode = INPUT;
@ -32,6 +33,7 @@ SwitchButton::SwitchButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux)
bool SwitchButton::BouncerUpdate() { bool SwitchButton::BouncerUpdate() {
if (mux != NULL) { if (mux != NULL) {
mux->channel(channel_id); mux->channel(channel_id);
delayMicroseconds(500);
} }
return bouncer.update(); return bouncer.update();
@ -44,24 +46,25 @@ bool SwitchButton::On() {
} }
PassthruButton::PassthruButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux) : SwitchButton(pin, vbutton, pullup, mux) { PassthruButton::PassthruButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux, bool analog_only) : SwitchButton(pin, vbutton, pullup, mux, analog_only) {
this->type = BUTTON_PASSTHRU; this->type = BUTTON_PASSTHRU;
} }
void PassthruButton::Update(Joystick* js) { bool PassthruButton::Update(Joystick* js) {
if (!BouncerUpdate()) return; if (!BouncerUpdate()) return false;
if (On()) js->PressButton(vbutton); if (On()) js->PressButton(vbutton);
else js->ReleaseButton(vbutton); else js->ReleaseButton(vbutton);
return true;
} }
LatchedButton::LatchedButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux) : SwitchButton(pin, vbutton, pullup, mux) { LatchedButton::LatchedButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux, bool analog_only) : SwitchButton(pin, vbutton, pullup, mux, analog_only) {
this->type = BUTTON_LATCHED_MOMENTARY; this->type = BUTTON_LATCHED_MOMENTARY;
this->pressed = false; this->pressed = false;
} }
void LatchedButton::Update(Joystick* js) { bool LatchedButton::Update(Joystick* js) {
if (!BouncerUpdate()) return; if (!BouncerUpdate()) return false;
if (On()) { if (On()) {
if (!pressed) { if (!pressed) {
@ -72,10 +75,12 @@ void LatchedButton::Update(Joystick* js) {
pressed = false; pressed = false;
} }
} }
return true;
} }
PulsedButton::PulsedButton(uint8_t pin, uint8_t vbutton, bool double_action, bool split, bool pullup, Mux* mux) : SwitchButton(pin, vbutton, pullup, mux) { 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) {
if (double_action) { if (double_action) {
if (split) { if (split) {
this->type = BUTTON_PULSED_DOUBLE_ACTION_SPLIT; this->type = BUTTON_PULSED_DOUBLE_ACTION_SPLIT;
@ -88,8 +93,8 @@ PulsedButton::PulsedButton(uint8_t pin, uint8_t vbutton, bool double_action, boo
} }
} }
void PulsedButton::Update(Joystick* js) { bool PulsedButton::Update(Joystick* js) {
if (!BouncerUpdate()) return; if (!BouncerUpdate()) return false;
switch(type) { switch(type) {
case BUTTON_PULSED: case BUTTON_PULSED:
@ -103,6 +108,8 @@ void PulsedButton::Update(Joystick* js) {
else js->PressButton(vbutton2); else js->PressButton(vbutton2);
break; break;
} }
return true;
} }
void PulsedButton::ReleaseButtons(Joystick* js) { void PulsedButton::ReleaseButtons(Joystick* js) {
@ -119,11 +126,19 @@ EncoderButton::EncoderButton(uint8_t pin1, uint8_t pin2, uint8_t vbutton) : Butt
this->last_value = encoder->read(); this->last_value = encoder->read();
} }
void EncoderButton::Update(Joystick* js) { bool EncoderButton::Update(Joystick* js) {
bool changed = false;
long new_value = encoder->read(); long new_value = encoder->read();
if (new_value > last_value) js->PressButton(vbutton); if (new_value > last_value) {
else if (new_value < last_value) js->PressButton(vbutton2); js->PressButton(vbutton);
changed = true;
}
else if (new_value < last_value) {
js->PressButton(vbutton2);
changed = true;
}
last_value = new_value; last_value = new_value;
return changed;
} }
void EncoderButton::ReleaseButtons(Joystick* js) { void EncoderButton::ReleaseButtons(Joystick* js) {

View File

@ -25,7 +25,7 @@ enum ButtonType {
class Button { class Button {
public: public:
Button(uint8_t vbutton); Button(uint8_t vbutton);
virtual void Update(Joystick* js) = 0; virtual bool Update(Joystick* js) = 0;
virtual void ReleaseButtons(Joystick* js); virtual void ReleaseButtons(Joystick* js);
ButtonType type; ButtonType type;
@ -40,8 +40,7 @@ class Button {
// and the multiplexer logic will be automatically invoked by Update() // and the multiplexer logic will be automatically invoked by Update()
class SwitchButton : public Button { class SwitchButton : public Button {
public: public:
SwitchButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux); SwitchButton(uint8_t pin, uint8_t vbutton, bool pullup, Mux* mux, bool analog_only);
virtual void Update(Joystick* js) = 0;
bool BouncerUpdate(); // returns true if the pin's status has changed bool BouncerUpdate(); // returns true if the pin's status has changed
bool On(); bool On();
@ -54,14 +53,14 @@ class SwitchButton : public Button {
class PassthruButton : public SwitchButton { class PassthruButton : public SwitchButton {
public: public:
PassthruButton(uint8_t pin, uint8_t vbutton, bool pullup = true, Mux* mux = NULL); PassthruButton(uint8_t pin, uint8_t vbutton, bool pullup = true, Mux* mux = NULL, bool analog_only = false);
void Update(Joystick* js); bool Update(Joystick* js);
}; };
class LatchedButton : public SwitchButton { class LatchedButton : public SwitchButton {
public: public:
LatchedButton(uint8_t pin, uint8_t vbutton, bool pullup = true, Mux* mux = NULL); LatchedButton(uint8_t pin, uint8_t vbutton, bool pullup = true, Mux* mux = NULL, bool analog_only = false);
void Update(Joystick* js); bool Update(Joystick* js);
protected: protected:
bool pressed; bool pressed;
@ -69,8 +68,8 @@ class LatchedButton : public SwitchButton {
class PulsedButton : public SwitchButton { class PulsedButton : public SwitchButton {
public: public:
PulsedButton(uint8_t pin, uint8_t vbutton, bool double_action = false, bool split = false, bool pullup = true, Mux* mux = NULL); PulsedButton(uint8_t pin, uint8_t vbutton, bool double_action = false, bool split = false, bool pullup = true, Mux* mux = NULL, bool analog_only = false);
void Update(Joystick* js); bool Update(Joystick* js);
void ReleaseButtons(Joystick* js); void ReleaseButtons(Joystick* js);
protected: protected:
@ -82,7 +81,7 @@ class PulsedButton : public SwitchButton {
class EncoderButton : public Button { class EncoderButton : public Button {
public: public:
EncoderButton(uint8_t pin1, uint8_t pin2, uint8_t vbutton); EncoderButton(uint8_t pin1, uint8_t pin2, uint8_t vbutton);
void Update(Joystick* js); bool Update(Joystick* js);
void ReleaseButtons(Joystick* js); void ReleaseButtons(Joystick* js);
protected: protected:

View File

@ -2,6 +2,7 @@
#include "Button.h" #include "Button.h"
#include <Mux.h> #include <Mux.h>
#include <Arduino.h> #include <Arduino.h>
#include <stdio.h>
using namespace admux; using namespace admux;
@ -39,27 +40,36 @@ void Joystick::Init() {
delay(100); delay(100);
} }
void Joystick::AddButton(uint8_t pin, ButtonType type, bool pullup, Mux* mux) { void Joystick::AddButton(uint8_t pin, ButtonType type, bool pullup, Mux* mux, bool analog_only) {
Button *button; Button *button;
switch (type) { switch (type) {
case BUTTON_PASSTHRU: case BUTTON_PASSTHRU:
button = new PassthruButton(pin, _virtual_buttons, pullup, mux); button = new PassthruButton(pin, _virtual_buttons, pullup, mux, analog_only);
_virtual_buttons++; _virtual_buttons++;
break;
case BUTTON_PULSED: case BUTTON_PULSED:
button = new PulsedButton(pin, _virtual_buttons, false, false, pullup, mux); button = new PulsedButton(pin, _virtual_buttons, false, false, pullup, mux, analog_only);
_virtual_buttons++; _virtual_buttons++;
break;
case BUTTON_PULSED_DOUBLE_ACTION: case BUTTON_PULSED_DOUBLE_ACTION:
button = new PulsedButton(pin, _virtual_buttons, true, false, pullup, mux); button = new PulsedButton(pin, _virtual_buttons, true, false, pullup, mux, analog_only);
_virtual_buttons++; _virtual_buttons++;
break;
case BUTTON_PULSED_DOUBLE_ACTION_SPLIT: case BUTTON_PULSED_DOUBLE_ACTION_SPLIT:
button = new PulsedButton(pin, _virtual_buttons, true, true, pullup, mux); button = new PulsedButton(pin, _virtual_buttons, true, true, pullup, mux, analog_only);
_virtual_buttons += 2; _virtual_buttons += 2;
break;
default: default:
return; return;
} }
_buttons[_num_buttons] = button; _buttons[_num_buttons] = button;
_num_buttons++; _num_buttons++;
if (_debug) {
char buffer[100];
sprintf(buffer, "Added button %d of type %d", _num_buttons - 1, button->type);
Serial.println(buffer);
}
if (type & _BUTTON_PULSED_TYPES) _have_pulsed_button = true; if (type & _BUTTON_PULSED_TYPES) _have_pulsed_button = true;
} }
@ -90,7 +100,12 @@ 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++) {
_buttons[i]->Update(this); bool changed = _buttons[i]->Update(this);
if (changed && _debug) {
char buffer[25];
sprintf(buffer, "Button %d changed state.", i);
Serial.println(buffer);
}
} }
// TODO: implement this and also refactor it into a class or classes // TODO: implement this and also refactor it into a class or classes

View File

@ -38,7 +38,9 @@ class Joystick {
// Button types are documented in the ButtonType enum. // Button types are documented in the ButtonType enum.
// If `pullup` is true, your button should connect the pin to ground. (also be sure that your board supports INPUT_PULLUP on that pin) // If `pullup` is true, your button should connect the pin to ground. (also be sure that your board supports INPUT_PULLUP on that pin)
// If `pullup` is false, your button should connect the pin to VCC. // If `pullup` is false, your button should connect the pin to VCC.
void AddButton(uint8_t pin, ButtonType type, bool pullup=true, Mux* mux=NULL); // Setting `analogOnly` to true indicates your button *must* be read with analog code, such as the A6 and A7 pins
// on the Arduino Nano.
void AddButton(uint8_t pin, ButtonType type, bool pullup=true, Mux* mux=NULL, bool analog_only=false);
// Add a rotary encoder. ENCODER button types allow you to treat an encoder as a momentary button or an axis (TODO) // 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); void AddEncoder(uint8_t pin1, uint8_t pin2, ButtonType type);
@ -46,6 +48,8 @@ class Joystick {
// 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);
// These members should not be used by end users; todo: remember how friend classes work
void PressButton(uint8_t button); void PressButton(uint8_t button);
void ReleaseButton(uint8_t button); void ReleaseButton(uint8_t button);
@ -66,6 +70,7 @@ class Joystick {
uint8_t _num_axes; uint8_t _num_axes;
JoyReport _joyReport; JoyReport _joyReport;
bool _debug; bool _debug;
}; };