summaryrefslogtreecommitdiff
path: root/quantum/joystick.h
blob: 5a69ceac64a9f5b637223c75c880d40a3dc777ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/* Copyright 2022
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <stdbool.h>
#include <stdint.h>

#include "gpio.h"

/**
 * \file
 *
 * \defgroup joystick HID Joystick
 * \{
 */

#ifndef JOYSTICK_BUTTON_COUNT
#    define JOYSTICK_BUTTON_COUNT 8
#elif JOYSTICK_BUTTON_COUNT > 32
#    error Joystick feature only supports up to 32 buttons
#endif

#ifndef JOYSTICK_AXIS_COUNT
#    define JOYSTICK_AXIS_COUNT 2
#elif JOYSTICK_AXIS_COUNT > 6
#    error Joystick feature only supports up to 6 axes
#endif

#if JOYSTICK_AXIS_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0
#    error Joystick feature requires at least one axis or button
#endif

#ifndef JOYSTICK_AXIS_RESOLUTION
#    define JOYSTICK_AXIS_RESOLUTION 8
#elif JOYSTICK_AXIS_RESOLUTION < 8 || JOYSTICK_AXIS_RESOLUTION > 16
#    error JOYSTICK_AXIS_RESOLUTION must be between 8 and 16
#endif

#define JOYSTICK_MAX_VALUE ((1L << (JOYSTICK_AXIS_RESOLUTION - 1)) - 1)

// configure on input_pin of the joystick_axes array entry to NO_PIN
// to prevent it from being read from the ADC. This allows outputting forged axis value.
#define JOYSTICK_AXIS_VIRTUAL \
    { NO_PIN, 0, JOYSTICK_MAX_VALUE / 2, JOYSTICK_MAX_VALUE }
#define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) \
    { INPUT_PIN, LOW, REST, HIGH }

typedef struct {
    pin_t input_pin;

    // the AVR ADC offers 10 bit precision, with significant bits on the higher part
    uint16_t min_digit;
    uint16_t mid_digit;
    uint16_t max_digit;
} joystick_config_t;

extern joystick_config_t joystick_axes[JOYSTICK_AXIS_COUNT];

typedef struct {
    uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1];
    int16_t axes[JOYSTICK_AXIS_COUNT];
    bool    dirty;
} joystick_t;

extern joystick_t joystick_state;

/**
 * \brief Handle the initialization of the subsystem.
 */
void joystick_init(void);

/**
 * \brief Handle various subsystem background tasks.
 */
void joystick_task(void);

/**
 * \brief Send the joystick report to the host, if it has been marked as dirty.
 */
void joystick_flush(void);

/**
 * \brief Set the state of a button, and flush the report.
 *
 * \param button The index of the button to press, from 0 to 31.
 */
void register_joystick_button(uint8_t button);

/**
 * \brief Reset the state of a button, and flush the report.
 *
 * \param button The index of the button to release, from 0 to 31.
 */
void unregister_joystick_button(uint8_t button);

/**
 * \brief Sample and process the analog value of the given axis.
 *
 * \param axis The axis to read.
 *
 * \return A signed 16-bit integer, where 0 is the resting or mid point.
 */
int16_t joystick_read_axis(uint8_t axis);

/**
 * \brief Sample and process the all axis.
 */
void joystick_read_axes(void);

/**
 * \brief Set the value of the given axis.
 *
 * \param axis The axis to set the value of.
 * \param value The value to set.
 */
void joystick_set_axis(uint8_t axis, int16_t value);

/** \} */