joystick.h (3972B)
1 /* Copyright 2022 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 2 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #pragma once 18 19 #include <stdbool.h> 20 #include <stdint.h> 21 22 #include "gpio.h" 23 24 /** 25 * \file 26 * 27 * \defgroup joystick HID Joystick 28 * \{ 29 */ 30 31 #ifndef JOYSTICK_BUTTON_COUNT 32 # define JOYSTICK_BUTTON_COUNT 8 33 #elif JOYSTICK_BUTTON_COUNT > 32 34 # error Joystick feature only supports up to 32 buttons 35 #endif 36 37 #ifndef JOYSTICK_AXIS_COUNT 38 # define JOYSTICK_AXIS_COUNT 2 39 #elif JOYSTICK_AXIS_COUNT > 6 40 # error Joystick feature only supports up to 6 axes 41 #endif 42 43 #if JOYSTICK_AXIS_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0 44 # error Joystick feature requires at least one axis or button 45 #endif 46 47 #ifndef JOYSTICK_AXIS_RESOLUTION 48 # define JOYSTICK_AXIS_RESOLUTION 8 49 #elif JOYSTICK_AXIS_RESOLUTION < 8 || JOYSTICK_AXIS_RESOLUTION > 16 50 # error JOYSTICK_AXIS_RESOLUTION must be between 8 and 16 51 #endif 52 53 #define JOYSTICK_MAX_VALUE ((1L << (JOYSTICK_AXIS_RESOLUTION - 1)) - 1) 54 55 #define JOYSTICK_HAT_CENTER -1 56 #define JOYSTICK_HAT_NORTH 0 57 #define JOYSTICK_HAT_NORTHEAST 1 58 #define JOYSTICK_HAT_EAST 2 59 #define JOYSTICK_HAT_SOUTHEAST 3 60 #define JOYSTICK_HAT_SOUTH 4 61 #define JOYSTICK_HAT_SOUTHWEST 5 62 #define JOYSTICK_HAT_WEST 6 63 #define JOYSTICK_HAT_NORTHWEST 7 64 65 // configure on input_pin of the joystick_axes array entry to NO_PIN 66 // to prevent it from being read from the ADC. This allows outputting forged axis value. 67 #define JOYSTICK_AXIS_VIRTUAL {NO_PIN, 0, JOYSTICK_MAX_VALUE / 2, JOYSTICK_MAX_VALUE} 68 #define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) {INPUT_PIN, LOW, REST, HIGH} 69 70 typedef struct { 71 pin_t input_pin; 72 73 // the AVR ADC offers 10 bit precision, with significant bits on the higher part 74 uint16_t min_digit; 75 uint16_t mid_digit; 76 uint16_t max_digit; 77 } joystick_config_t; 78 79 extern joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT]; 80 81 typedef struct { 82 uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1]; 83 int16_t axes[JOYSTICK_AXIS_COUNT]; 84 #ifdef JOYSTICK_HAS_HAT 85 int8_t hat; 86 #endif 87 bool dirty; 88 } joystick_t; 89 90 extern joystick_t joystick_state; 91 92 /** 93 * \brief Handle the initialization of the subsystem. 94 */ 95 void joystick_init(void); 96 97 /** 98 * \brief Handle various subsystem background tasks. 99 */ 100 void joystick_task(void); 101 102 /** 103 * \brief Send the joystick report to the host, if it has been marked as dirty. 104 */ 105 void joystick_flush(void); 106 107 /** 108 * \brief Set the state of a button, and flush the report. 109 * 110 * \param button The index of the button to press, from 0 to 31. 111 */ 112 void register_joystick_button(uint8_t button); 113 114 /** 115 * \brief Reset the state of a button, and flush the report. 116 * 117 * \param button The index of the button to release, from 0 to 31. 118 */ 119 void unregister_joystick_button(uint8_t button); 120 121 /** 122 * \brief Sample and process the analog value of the given axis. 123 * 124 * \param axis The axis to read. 125 * 126 * \return A signed 16-bit integer, where 0 is the resting or mid point. 127 */ 128 int16_t joystick_read_axis(uint8_t axis); 129 130 /** 131 * \brief Sample and process the all axis. 132 */ 133 void joystick_read_axes(void); 134 135 /** 136 * \brief Set the value of the given axis. 137 * 138 * \param axis The axis to set the value of. 139 * \param value The value to set. 140 */ 141 void joystick_set_axis(uint8_t axis, int16_t value); 142 143 /** 144 * \brief Set the position of the hat switch. 145 * 146 * \param value The hat switch position to set. 147 */ 148 void joystick_set_hat(int8_t value); 149 150 /** \} */