sketchbook.ino
#include "thumbstick.h"
// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 6; // switch to turn on and off mouse control
const int xAxis = A0; // joystick X axis pin
const int yAxis = A1; // joystick Y axis pin
class MenuListener {
public:
bool press();
void release(const int ms);
};
bool MenuListener::press() {
return true;
}
void MenuListener::release(const int ms) {
if (ms > 7000) {
// system reset
Serial.println("RESET");
} else if (ms > 3000) {
// extra
Serial.println("Extra");
} else {
// normal click release, take some action.
Serial.println("Select");
}
}
// Singleton instances
MenuListener menuListener = MenuListener();
ThumbstickButton button = ThumbstickButton(6, xAxis, yAxis, (PressButton)&menuListener.press, (ReleaseButton)&menuListener.release);
void setup() {
Serial.begin(115200);
}
void loop() {
if (button.pushed()) {
}
ThumbstickPosition p = button.position();
if (p.x != 0 || p.y != 0) {
char jxy[30];
sprintf(jxy, "%i,%i %i,%i\0", p.x, p.y, p.dx, p.dy);
Serial.println(jxy);
}
delay(5);
}
thumbstick.h
#include "Arduino.h"
typedef bool (*PressButton) ();
typedef void (*ReleaseButton) (const int ms);
class ThumbstickPosition {
public:
int x = 0;
int y = 0;
int dx = 0;
int dy = 0;
ThumbstickPosition();
ThumbstickPosition(const int x, const int y, const int dx, const int dy);
private:
bool motion = false;
};
class ThumbstickButton {
public:
ThumbstickButton(const int pin, const int xAxis, const int yAxis, PressButton btnPress, ReleaseButton btnRelease);
bool pushed();
unsigned long age();
ThumbstickPosition position();
private:
int pin;
int xAxis;
int yAxis;
unsigned long since = 0;
PressButton btnPress;
ReleaseButton btnRelease;
ThumbstickPosition positions[2];
bool pressed = false;
int8_t peek = 0;
int8_t current = 0;
int8_t previous = 0;
int8_t read();
int readAxis(int axis);
};
thumbstick.cpp
#include "thumbstick.h"
// parameters for reading the joystick:
const int range = 128; // output range of X or Y movement
const int threshold = 8; // resting threshold
ThumbstickPosition::ThumbstickPosition() {
}
ThumbstickPosition::ThumbstickPosition(const int x, const int y, const int dx, const int dy) {
this->x = x;
this->y = y;
this->dx = dx;
this->dy = dy;
}
ThumbstickButton::ThumbstickButton(const int pin, const int xAxis, const int yAxis, PressButton btnPress, ReleaseButton btnRelease) {
this->pin = pin;
this->xAxis = xAxis;
this->yAxis = yAxis;
this->btnPress = btnPress;
this->btnRelease = btnRelease;
pinMode(pin, INPUT_PULLUP); // the switch pin
}
unsigned long ThumbstickButton::age() {
return millis() - this->since;
}
int8_t ThumbstickButton::read() {
int8_t r = digitalRead(this->pin); // 1=up or 0=down.
if (r == this->peek) {
if (millis() - this->since > 40) {
this->previous = this->current;
this->current = r;
}
} else {
// state changed
this->peek = r;
if (this->current == LOW && r == HIGH) {
// button released
const int ms = millis() - this->since;
this->previous = this->current;
this->current = r;
this->pressed = false;
this->btnRelease(ms);
}
this->since = millis();
}
return this->current;
}
bool ThumbstickButton::pushed() {
if (this->read() == LOW) {
uint32_t lastPress = millis();
if (!this->pressed) {
return this->pressed = this->btnPress();
}
}
return false;
}
ThumbstickPosition ThumbstickButton::position() {
this->positions[1] = this->positions[0];
const int x = this->readAxis(xAxis);
const int y = this->readAxis(yAxis);
return this->positions[0] = ThumbstickPosition(x, y, x - this->positions[1].x, y - this->positions[1].y);
}
int ThumbstickButton::readAxis(int axis) {
/*
reads an axis (0 or 1 for x or y) and scales the analog input range to a range
from 0 to <range>
*/
// read the analog input:
int reading = analogRead(axis);
// map the reading from the analog input range to the output range:
reading = map(reading, 0, 1023, 0, range);
// if the output reading is outside from the rest position threshold, use it:
int distance = reading - (range / 2);
if (abs(distance) < threshold) {
return 0;
}
// return the distance for this axis:
return distance;
}