#ifndef _JOYSTICK_H_ #define _JOYSTICK_H_ #include #include #include using namespace admux; // If you're using the arduino-big-joystick firmware, these numbers can't be // changed. If you're writing your own Report Descriptor, tune these to match by // defining them *before* you include Joystick.h. #ifndef JOYSTICK_NUM_AXES #define JOYSTICK_NUM_AXES 8 #endif #ifndef JOYSTICK_NUM_BUTTONS #define JOYSTICK_NUM_BUTTONS 40 #endif #define JOYSTICK_NUM_BYTES (JOYSTICK_NUM_BUTTONS+7)/8 #ifndef MAX_MUX #define MAX_MUX 3 #endif enum ButtonType { BUTTON_PASSTHRU = 0x1, // always use the (debounced) absolute state of the input 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 }; struct JoyReport { int16_t axis[JOYSTICK_NUM_AXES]; uint8_t button[JOYSTICK_NUM_BYTES]; }; struct Button { ButtonType type; Bounce bouncer; uint8_t vbutton0; uint8_t vbutton1; // only used by BUTTON_PULSED_DOUBLE_ACTION_SPLIT bool pressed = false; // only used by BUTTON_LATCHED_MOMENTARY bool inverted = false; // if true, send button press on release and vice versa. // todo: this should probably be abstracted out from this struct... bool mux; uint8_t mux_id; uint8_t mux_channel; }; bool operator ==(JoyReport a, JoyReport b); bool operator !=(JoyReport a, JoyReport b); class Joystick { public: Joystick(bool debug=false); void Init(); void Update(); // Add a button to the joystick. // 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 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, bool mux=false, uint8_t mux_id = 0; uint8_t mux_channel = 0); // 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); // Add control for a multiplexer. To add a button that's connected via the multiplexer, // pass the mux's signal pin as the pin parameter to AddButton(), along with the mux* parameters. // mux_id is the array index of the mux (in the order you added them via AddMux()) uint8_t AddMux(uint8_t signal_pin, uint8_t addr_pins[], uint8_t addr_width); private: void SetAxis(uint8_t axis, int16_t value); void PressButton(uint8_t button); void ReleaseButton(uint8_t button); void ReleaseAllButtons(); void Write(); void _ReleasePulsedButtons(); void _UpdateButton(uint8_t index); void _UpdateAxis(uint8_t index); Button _buttons[JOYSTICK_NUM_BUTTONS]; uint8_t _num_buttons; uint8_t _virtual_buttons; // a single user-defined button can have multiple virtual buttons. bool _have_pulsed_button; uint8_t _axes[JOYSTICK_NUM_AXES]; uint8_t _num_axes; JoyReport _joyReport; bool _debug; Mux _mux[MAX_MUX]; uint8_t _num_mux; }; // Internal use only. #define _BUTTON_PULSED_TYPES (BUTTON_PULSED | BUTTON_PULSED_DOUBLE_ACTION | BUTTON_PULSED_DOUBLE_ACTION_SPLIT) #endif