#include "Joystick.h" #include bool operator ==(JoyReport a, JoyReport b){ for (uint8_t i=0; i < JOYSTICK_NUM_AXES; i++) { if (a.axis[i] != b.axis[i]) return false; } for (uint8_t i=0; i < JOYSTICK_NUM_BYTES; i++) { if (a.button[i] != b.button[i]) return false; } return true; } bool operator !=(JoyReport a, JoyReport b){ return !(a == b); } uint8_t _InvertSignal(uint8_t signal) { if (signal == HIGH) return LOW; else return HIGH; } Joystick::Joystick(bool debug) { _debug = debug; _num_buttons = 0; _num_axes = 0; _have_pulsed_button = false; for (uint8_t i=0; i < JOYSTICK_NUM_AXES; i++) { _joyReport.axis[i] = 0; } for (uint8_t i=0; i < JOYSTICK_NUM_BYTES; i++) { _joyReport.button[i] = 0; } } void Joystick::Init() { Serial.begin(115200); delay(100); if (_debug) Serial.println("DEBUG: Joystick library initialized."); } void Joystick::AddButton(uint8_t pin, ButtonType type, bool pullup) { if (pullup) pinMode(pin, INPUT_PULLUP); else pinMode(pin, INPUT); Button button; button.pin = pin; button.type = type; if (pullup) button.last_state = _InvertSignal(digitalRead(pin)); else button.last_state = digitalRead(pin); button.pullup = pullup; _buttons[_num_buttons] = button; _num_buttons++; if (type & _BUTTON_PULSED_TYPES) _have_pulsed_button = true; if (_debug) { Serial.print("Debug: added button of type "); Serial.print(type); Serial.print(" on digital pin "); Serial.println(pin); } } void Joystick::AddAxis(uint8_t pin) { _axes[_num_axes] = pin; _num_axes++; if (_debug) { Serial.print("Debug: added axis on analog pin "); Serial.println(pin); } } void Joystick::Update() { JoyReport oldReport = _joyReport; for (int i = 0; i < _num_buttons; i++) { _UpdateButton(_buttons[i], i); } for (int i = 0; i < _num_axes; i++) { _UpdateAxis(i); } if (_joyReport != oldReport) { Write(); if (_have_pulsed_button) { _ReleasePulsedButtons(); Write(); } } } void Joystick::SetAxis(uint8_t axis, int16_t value) { if (axis >= JOYSTICK_NUM_AXES) return; _joyReport.axis[axis] = value; if (_debug) Serial.println("DEBUG: Axis change recorded."); } void Joystick::PressButton(uint8_t button) { if (button >= JOYSTICK_NUM_BUTTONS) return; uint8_t byte = button / 8; uint8_t bit = button % 8; _joyReport.button[byte] |= 1 << bit; if (_debug) { Serial.print("DEBUG: Button press recorded for button "); Serial.println(button); } } void Joystick::ReleaseButton(uint8_t button) { if (button >= JOYSTICK_NUM_BUTTONS) return; uint8_t byte = button / 8; uint8_t bit = button % 8; _joyReport.button[byte] &= ~(1 << bit); if (_debug) { Serial.print("DEBUG: Button release recorded for button "); Serial.println(button); } } void Joystick::ReleaseAllButtons() { for (uint8_t i = 0; i < JOYSTICK_NUM_BYTES; i++) { _joyReport.button[i] = 0; } if (_debug) Serial.println("DEBUG: All-button release recorded."); } void Joystick::_ReleasePulsedButtons() { for (uint8_t i = 0; i < _num_buttons; i++) { if (_buttons[i].type & _BUTTON_PULSED_TYPES) ReleaseButton(i); } } void Joystick::Write() { if (!_debug) { Serial.write((uint8_t *)&_joyReport, sizeof(JoyReport)); } else { Serial.print("DEBUG: Writing data: "); for (uint8_t i=0; i < JOYSTICK_NUM_AXES; i++) { Serial.print(_joyReport.axis[i]); Serial.print(" "); } for (uint8_t i=0; i < JOYSTICK_NUM_BYTES; i++) { Serial.print(_joyReport.button[i]); Serial.print(" "); } Serial.println(); } delay(250); } void Joystick::_UpdateButton(Button& button, uint8_t index) { uint8_t value = digitalRead(button.pin); // Treat pullup-resistor inputs as basically backwards. if (button.pullup) value = _InvertSignal(value); switch (button.type) { case BUTTON_LATCHED: if (value == HIGH && button.last_state != HIGH) PressButton(index); else if (value == LOW && button.last_state != LOW) ReleaseButton(index); break; case BUTTON_PULSED: if (value == HIGH && button.last_state == LOW) PressButton(index); break; case BUTTON_PULSED_DOUBLE_ACTION: if (value != button.last_state) PressButton(index); break; default: if (_debug) { Serial.print("DEBUG: Unhandled button type: "); Serial.println(button.type); } } button.last_state = value; } void Joystick::_UpdateAxis(uint8_t index) { if (_debug) Serial.println("STUB: Joystick::_UpdateAxis"); }