forked from mfulz_github/qmk_firmware
Merge branch 'hid_joystick' of git://github.com/a-chol/qmk_firmware into a-chol-hid_joystick
This commit is contained in:
commit
708bb4f55d
|
@ -516,3 +516,10 @@ ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes)
|
|||
OPT_DEFS += -DAUTO_SHIFT_MODIFIERS
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(JOYSTICK_ENABLE)), yes)
|
||||
OPT_DEFS += -DJOYSTICK_ENABLE
|
||||
SRC += $(QUANTUM_DIR)/process_keycode/process_joystick.c
|
||||
SRC += $(QUANTUM_DIR)/joystick.c
|
||||
SRC += analog.c
|
||||
endif
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
* [DIP Switch](feature_dip_switch.md)
|
||||
* [Encoders](feature_encoders.md)
|
||||
* [Haptic Feedback](feature_haptic_feedback.md)
|
||||
* [Joystick](feature_joystick.md)
|
||||
* [Proton C Conversion](proton_c_conversion.md)
|
||||
* [PS/2 Mouse](feature_ps2_mouse.md)
|
||||
* [Split Keyboard](feature_split_keyboard.md)
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
## Joystick
|
||||
|
||||
The keyboard can be made to be recognized as a joystick HID device by the operating system.
|
||||
|
||||
This is enabled by adding the following to `rules.mk`:
|
||||
|
||||
```makefile
|
||||
JOYSTICK_ENABLE = yes
|
||||
```
|
||||
|
||||
!> Joystick support is not currently available on V-USB devices.
|
||||
|
||||
The joystick feature provides two services:
|
||||
* reading analog input devices (eg. potentiometers)
|
||||
* sending gamepad HID reports
|
||||
|
||||
Both services can be used without the other, depending on whether you just want to read a device but not send gamepad reports (for volume control for instance)
|
||||
or send gamepad reports based on values computed by the keyboard.
|
||||
|
||||
### Analog Input
|
||||
|
||||
An analog device such as a potentiometer found on a gamepad's analog axes is based on a [voltage divider](https://en.wikipedia.org/wiki/Voltage_divider).
|
||||
It is composed of three connectors linked to the ground, the power input and power output (usually the middle one). The power output holds the voltage that varies based on the position of the cursor,
|
||||
which value will be read using your MCU's [ADC](https://en.wikipedia.org/wiki/Analog-to-digital_converter).
|
||||
Depending on which pins are already used by your keyboard's matrix, the rest of the circuit can get a little bit more complicated,
|
||||
feeding the power input and ground connection through pins and using diodes to avoid bad interactions with the matrix scanning procedures.
|
||||
|
||||
### Configuring the Joystick
|
||||
|
||||
By default, two axes and eight buttons are defined. This can be changed in your `config.h`:
|
||||
|
||||
```c
|
||||
// Max 32
|
||||
#define JOYSTICK_BUTTON_COUNT 16
|
||||
// Max 6: X, Y, Z, Rx, Ry, Rz
|
||||
#define JOYSTICK_AXES_COUNT 3
|
||||
```
|
||||
|
||||
When defining axes for your joystick, you have to provide a definition array. You can do this from your keymap.c file.
|
||||
A joystick will either be read from an input pin that allows the use of the ADC, or can be virtual, so that its value is provided by your code.
|
||||
You have to define an array of type ''joystick_config_t'' and of proper size.
|
||||
|
||||
There are three ways for your circuit to work with the ADC, that relies on the use of 1, 2 or 3 pins of the MCU:
|
||||
* 1 pin: your analog device is directly connected to your device GND and VCC. The only pin used is the ADC pin of your choice.
|
||||
* 2 pins: your analog device is powered through a pin that allows toggling it on or off. The other pin is used to read the input value through the ADC.
|
||||
* 3 pins: both the power input and ground are connected to pins that must be set to a proper state before reading and restored afterwards.
|
||||
|
||||
The configuration of each axis is performed using one of four macros:
|
||||
* `JOYSTICK_AXIS_VIRTUAL`: no ADC reading must be performed, that value will be provided by keyboard/keymap-level code
|
||||
* `JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH)`: a voltage will be read on the provided pin, which must be an ADC-capable pin.
|
||||
* `JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH)`: the provided `OUTPUT_PIN` will be set high before `INPUT_PIN` is read.
|
||||
* `JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH)`: the `OUTPUT_PIN` will be set high and `GROUND_PIN` will be set low before reading from `INPUT_PIN`.
|
||||
|
||||
In any case where an ADC reading takes place (when `INPUT_PIN` is provided), additional `LOW`, `REST` and `HIGH` parameters are used.
|
||||
These implement the calibration of the analog device by defining the range of read values that will be mapped to the lowest, resting position and highest possible value for the axis (-127 to 127).
|
||||
In practice, you have to provide the lowest/highest raw ADC reading, and the raw reading at resting position, when no deflection is applied. You can provide inverted `LOW` and `HIGH` to invert the axis.
|
||||
|
||||
For instance, an axes configuration can be defined in the following way:
|
||||
|
||||
```c
|
||||
//joystick config
|
||||
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {
|
||||
[0] = JOYSTICK_AXIS_IN_OUT_GROUND(A4, B0, A7, 900, 575, 285),
|
||||
[1] = JOYSTICK_AXIS_VIRTUAL
|
||||
};
|
||||
```
|
||||
|
||||
When the ADC reads 900 or higher, the returned axis value will be -127, whereas it will be 127 when the ADC reads 285 or lower. Zero is returned when 575 is read.
|
||||
|
||||
In this example, the first axis will be read from the `A4` pin while `B0` is set high and `A7` is set low, using `analogReadPin()`, whereas the second axis will not be read.
|
||||
|
||||
In order to give a value to the second axis, you can do so in any customizable entry point: as an action, in `process_record_user()` or in `matrix_scan_user()`, or even in `joystick_task()` which is called even when no key has been pressed.
|
||||
You assign a value by writing to `joystick_status.axes[axis_index]` a signed 8-bit value (ranging from -127 to 127). Then it is necessary to assign the flag `JS_UPDATED` to `joystick_status.status` in order for an updated HID report to be sent.
|
||||
|
||||
The following example writes two axes based on keypad presses, with `KC_P5` as a precision modifier:
|
||||
|
||||
```c
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
static uint8_t precision_val = 70;
|
||||
static uint8_t axesFlags = 0;
|
||||
enum axes {
|
||||
Precision = 1,
|
||||
Axis1High = 2,
|
||||
Axis1Low = 4,
|
||||
Axis2High = 8,
|
||||
Axis2Low = 16
|
||||
};
|
||||
#endif
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
switch(keycode) {
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
// virtual joystick
|
||||
# if JOYSTICK_AXES_COUNT > 1
|
||||
case KC_P8:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis2Low;
|
||||
} else {
|
||||
axesFlags &= ~Axis2Low;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
case KC_P2:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis2High;
|
||||
} else {
|
||||
axesFlags &= ~Axis2High;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
# endif
|
||||
case KC_P4:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis1Low;
|
||||
} else {
|
||||
axesFlags &= ~Axis1Low;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
case KC_P6:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Axis1High;
|
||||
} else {
|
||||
axesFlags &= ~Axis1High;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
case KC_P5:
|
||||
if (record->event.pressed) {
|
||||
axesFlags |= Precision;
|
||||
} else {
|
||||
axesFlags &= ~Precision;
|
||||
}
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Triggering Joystick Buttons
|
||||
|
||||
Joystick buttons are normal Quantum keycodes, defined as `JS_BUTTON0` to `JS_BUTTON31`, depending on the number of buttons you have configured.
|
||||
To trigger a joystick button, just add the corresponding keycode to your keymap.
|
|
@ -97,10 +97,11 @@ uint8_t pinToMux(pin_t pin) {
|
|||
#endif
|
||||
// clang-format on
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t adc_read(uint8_t mux) {
|
||||
uint8_t low;
|
||||
uint16_t low;
|
||||
|
||||
// Enable ADC and configure prescaler
|
||||
ADCSRA = _BV(ADEN) | ADC_PRESCALER;
|
||||
|
@ -128,5 +129,10 @@ int16_t adc_read(uint8_t mux) {
|
|||
// Must read LSB first
|
||||
low = ADCL;
|
||||
// Must read MSB only once!
|
||||
return (ADCH << 8) | low;
|
||||
low |= (ADCH << 8);
|
||||
|
||||
// turn off the ADC
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
|
||||
return low;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
#define JOYSTICK_AXES_COUNT 2
|
||||
#define JOYSTICK_BUTTON_COUNT 1
|
|
@ -0,0 +1,524 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file templates/halconf.h
|
||||
* @brief HAL configuration header.
|
||||
* @details HAL configuration file, this file allows to enable or disable the
|
||||
* various device drivers from your application. You may also use
|
||||
* this file in order to override the device drivers default settings.
|
||||
*
|
||||
* @addtogroup HAL_CONF
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HALCONF_H
|
||||
# define HALCONF_H
|
||||
|
||||
# define _CHIBIOS_HAL_CONF_
|
||||
# define _CHIBIOS_HAL_CONF_VER_7_0_
|
||||
|
||||
# include "mcuconf.h"
|
||||
|
||||
/**
|
||||
* @brief Enables the PAL subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_PAL TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the ADC subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_ADC TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the CAN subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_CAN FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the cryptographic subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_CRY) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_CRY FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the DAC subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_DAC TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the GPT subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_GPT TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the I2C subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_I2C TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the I2S subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_I2S FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the ICU subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_ICU FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the MAC subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_MAC FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the MMC_SPI subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_MMC_SPI FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the PWM subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_PWM TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the RTC subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_RTC FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SDC subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_SDC FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SERIAL subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_SERIAL FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SERIAL over USB subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_SERIAL_USB TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SIO subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_SIO) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_SIO FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the SPI subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_SPI FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the TRNG subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_TRNG) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_TRNG FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the UART subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_UART FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the USB subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_USB TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the WDG subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_WDG FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the WSPI subsystem.
|
||||
*/
|
||||
# if !defined(HAL_USE_WSPI) || defined(__DOXYGEN__)
|
||||
# define HAL_USE_WSPI FALSE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* PAL driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(PAL_USE_CALLBACKS) || defined(__DOXYGEN__)
|
||||
# define PAL_USE_CALLBACKS FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(PAL_USE_WAIT) || defined(__DOXYGEN__)
|
||||
# define PAL_USE_WAIT FALSE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* ADC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
|
||||
# define ADC_USE_WAIT TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
# define ADC_USE_MUTUAL_EXCLUSION TRUE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* CAN driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Sleep mode related APIs inclusion switch.
|
||||
*/
|
||||
# if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
|
||||
# define CAN_USE_SLEEP_MODE TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enforces the driver to use direct callbacks rather than OSAL events.
|
||||
*/
|
||||
# if !defined(CAN_ENFORCE_USE_CALLBACKS) || defined(__DOXYGEN__)
|
||||
# define CAN_ENFORCE_USE_CALLBACKS FALSE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* CRY driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables the SW fall-back of the cryptographic driver.
|
||||
* @details When enabled, this option, activates a fall-back software
|
||||
* implementation for algorithms not supported by the underlying
|
||||
* hardware.
|
||||
* @note Fall-back implementations may not be present for all algorithms.
|
||||
*/
|
||||
# if !defined(HAL_CRY_USE_FALLBACK) || defined(__DOXYGEN__)
|
||||
# define HAL_CRY_USE_FALLBACK FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Makes the driver forcibly use the fall-back implementations.
|
||||
*/
|
||||
# if !defined(HAL_CRY_ENFORCE_FALLBACK) || defined(__DOXYGEN__)
|
||||
# define HAL_CRY_ENFORCE_FALLBACK FALSE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* DAC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
|
||||
# define DAC_USE_WAIT TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p dacAcquireBus() and @p dacReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
# define DAC_USE_MUTUAL_EXCLUSION TRUE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* I2C driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables the mutual exclusion APIs on the I2C bus.
|
||||
*/
|
||||
# if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
# define I2C_USE_MUTUAL_EXCLUSION TRUE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* MAC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables the zero-copy API.
|
||||
*/
|
||||
# if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
|
||||
# define MAC_USE_ZERO_COPY FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables an event sources for incoming packets.
|
||||
*/
|
||||
# if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
|
||||
# define MAC_USE_EVENTS TRUE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* MMC_SPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @details If enabled this options inserts delays into the MMC waiting
|
||||
* routines releasing some extra CPU time for the threads with
|
||||
* lower priority, this may slow down the driver a bit however.
|
||||
* This option is recommended also if the SPI driver does not
|
||||
* use a DMA channel and heavily loads the CPU.
|
||||
*/
|
||||
# if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
|
||||
# define MMC_NICE_WAITING TRUE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SDC driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Number of initialization attempts before rejecting the card.
|
||||
* @note Attempts are performed at 10mS intervals.
|
||||
*/
|
||||
# if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
|
||||
# define SDC_INIT_RETRY 100
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Include support for MMC cards.
|
||||
* @note MMC support is not yet implemented so this option must be kept
|
||||
* at @p FALSE.
|
||||
*/
|
||||
# if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
|
||||
# define SDC_MMC_SUPPORT FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Delays insertions.
|
||||
* @details If enabled this options inserts delays into the MMC waiting
|
||||
* routines releasing some extra CPU time for the threads with
|
||||
* lower priority, this may slow down the driver a bit however.
|
||||
*/
|
||||
# if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
|
||||
# define SDC_NICE_WAITING TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief OCR initialization constant for V20 cards.
|
||||
*/
|
||||
# if !defined(SDC_INIT_OCR_V20) || defined(__DOXYGEN__)
|
||||
# define SDC_INIT_OCR_V20 0x50FF8000U
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief OCR initialization constant for non-V20 cards.
|
||||
*/
|
||||
# if !defined(SDC_INIT_OCR) || defined(__DOXYGEN__)
|
||||
# define SDC_INIT_OCR 0x80100000U
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SERIAL driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Default bit rate.
|
||||
* @details Configuration parameter, this is the baud rate selected for the
|
||||
* default configuration.
|
||||
*/
|
||||
# if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
|
||||
# define SERIAL_DEFAULT_BITRATE 38400
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Serial buffers size.
|
||||
* @details Configuration parameter, you can change the depth of the queue
|
||||
* buffers depending on the requirements of your application.
|
||||
* @note The default is 16 bytes for both the transmission and receive
|
||||
* buffers.
|
||||
*/
|
||||
# if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
# define SERIAL_BUFFERS_SIZE 16
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SERIAL_USB driver related setting. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Serial over USB buffers size.
|
||||
* @details Configuration parameter, the buffer size must be a multiple of
|
||||
* the USB data endpoint maximum packet size.
|
||||
* @note The default is 256 bytes for both the transmission and receive
|
||||
* buffers.
|
||||
*/
|
||||
# if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
# define SERIAL_USB_BUFFERS_SIZE 1
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Serial over USB number of buffers.
|
||||
* @note The default is 2 buffers.
|
||||
*/
|
||||
# if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__)
|
||||
# define SERIAL_USB_BUFFERS_NUMBER 2
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* SPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
|
||||
# define SPI_USE_WAIT TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables circular transfers APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(SPI_USE_CIRCULAR) || defined(__DOXYGEN__)
|
||||
# define SPI_USE_CIRCULAR FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
# define SPI_USE_MUTUAL_EXCLUSION TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Handling method for SPI CS line.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(SPI_SELECT_MODE) || defined(__DOXYGEN__)
|
||||
# define SPI_SELECT_MODE SPI_SELECT_MODE_PAD
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* UART driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(UART_USE_WAIT) || defined(__DOXYGEN__)
|
||||
# define UART_USE_WAIT FALSE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
# define UART_USE_MUTUAL_EXCLUSION FALSE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* USB driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
|
||||
# define USB_USE_WAIT TRUE
|
||||
# endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* WSPI driver related settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Enables synchronous APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__)
|
||||
# define WSPI_USE_WAIT TRUE
|
||||
# endif
|
||||
|
||||
/**
|
||||
* @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs.
|
||||
* @note Disabling this option saves both code and data space.
|
||||
*/
|
||||
# if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
|
||||
# define WSPI_USE_MUTUAL_EXCLUSION TRUE
|
||||
# endif
|
||||
|
||||
#endif /* HALCONF_H */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,25 @@
|
|||
#include QMK_KEYBOARD_H
|
||||
|
||||
#include "joystick.h"
|
||||
|
||||
#ifndef ADC_PIN
|
||||
# define ADC_PIN F6
|
||||
#endif
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
LAYOUT( JS_BUTTON0 )
|
||||
};
|
||||
|
||||
void matrix_scan_user() {
|
||||
int16_t val = (((uint32_t)timer_read()%5000 - 2500) * 255) / 5000;
|
||||
if (val != joystick_status.axes[1]) {
|
||||
joystick_status.axes[1] = val;
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
}
|
||||
}
|
||||
|
||||
//joystick config
|
||||
joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {
|
||||
[0] = JOYSTICK_AXIS_IN(ADC_PIN, 0, 512, 1023)
|
||||
, [1] = JOYSTICK_AXIS_VIRTUAL
|
||||
};
|
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MCUCONF_H
|
||||
#define MCUCONF_H
|
||||
|
||||
/*
|
||||
* STM32F3xx drivers configuration.
|
||||
* The following settings override the default settings present in
|
||||
* the various device driver implementation headers.
|
||||
* Note that the settings for each driver only have effect if the whole
|
||||
* driver is enabled in halconf.h.
|
||||
*
|
||||
* IRQ priorities:
|
||||
* 15...0 Lowest...Highest.
|
||||
*
|
||||
* DMA priorities:
|
||||
* 0...3 Lowest...Highest.
|
||||
*/
|
||||
|
||||
#define STM32F3xx_MCUCONF
|
||||
#define STM32F303_MCUCONF
|
||||
|
||||
/*
|
||||
* HAL driver system settings.
|
||||
*/
|
||||
#define STM32_NO_INIT FALSE
|
||||
#define STM32_PVD_ENABLE FALSE
|
||||
#define STM32_PLS STM32_PLS_LEV0
|
||||
#define STM32_HSI_ENABLED TRUE
|
||||
#define STM32_LSI_ENABLED TRUE
|
||||
#define STM32_HSE_ENABLED TRUE
|
||||
#define STM32_LSE_ENABLED FALSE
|
||||
#define STM32_SW STM32_SW_PLL
|
||||
#define STM32_PLLSRC STM32_PLLSRC_HSE
|
||||
#define STM32_PREDIV_VALUE 1
|
||||
#define STM32_PLLMUL_VALUE 9
|
||||
#define STM32_HPRE STM32_HPRE_DIV1
|
||||
#define STM32_PPRE1 STM32_PPRE1_DIV2
|
||||
#define STM32_PPRE2 STM32_PPRE2_DIV2
|
||||
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
|
||||
#define STM32_ADC12PRES STM32_ADC12PRES_DIV1
|
||||
#define STM32_ADC34PRES STM32_ADC34PRES_DIV1
|
||||
#define STM32_USART1SW STM32_USART1SW_PCLK
|
||||
#define STM32_USART2SW STM32_USART2SW_PCLK
|
||||
#define STM32_USART3SW STM32_USART3SW_PCLK
|
||||
#define STM32_UART4SW STM32_UART4SW_PCLK
|
||||
#define STM32_UART5SW STM32_UART5SW_PCLK
|
||||
#define STM32_I2C1SW STM32_I2C1SW_SYSCLK
|
||||
#define STM32_I2C2SW STM32_I2C2SW_SYSCLK
|
||||
#define STM32_TIM1SW STM32_TIM1SW_PCLK2
|
||||
#define STM32_TIM8SW STM32_TIM8SW_PCLK2
|
||||
#define STM32_RTCSEL STM32_RTCSEL_LSI
|
||||
#define STM32_USB_CLOCK_REQUIRED TRUE
|
||||
#define STM32_USBPRE STM32_USBPRE_DIV1P5
|
||||
|
||||
/*
|
||||
* IRQ system settings.
|
||||
*/
|
||||
#define STM32_IRQ_EXTI0_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI1_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI2_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI3_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI4_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI5_9_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI10_15_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI16_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI17_PRIORITY 15
|
||||
#define STM32_IRQ_EXTI18_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI19_PRIORITY 15
|
||||
#define STM32_IRQ_EXTI20_PRIORITY 15
|
||||
#define STM32_IRQ_EXTI21_22_29_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI30_32_PRIORITY 6
|
||||
#define STM32_IRQ_EXTI33_PRIORITY 6
|
||||
#define STM32_IRQ_TIM1_BRK_TIM15_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_UP_TIM16_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_TRGCO_TIM17_PRIORITY 7
|
||||
#define STM32_IRQ_TIM1_CC_PRIORITY 7
|
||||
|
||||
/*
|
||||
* ADC driver system settings.
|
||||
*/
|
||||
#define STM32_ADC_DUAL_MODE FALSE
|
||||
#define STM32_ADC_COMPACT_SAMPLES FALSE
|
||||
#define STM32_ADC_USE_ADC1 TRUE
|
||||
#define STM32_ADC_USE_ADC2 FALSE
|
||||
#define STM32_ADC_USE_ADC3 FALSE
|
||||
#define STM32_ADC_USE_ADC4 FALSE
|
||||
#define STM32_ADC_ADC1_DMA_STREAM STM32_DMA_STREAM_ID(1, 1)
|
||||
#define STM32_ADC_ADC2_DMA_STREAM STM32_DMA_STREAM_ID(2, 1)
|
||||
#define STM32_ADC_ADC3_DMA_STREAM STM32_DMA_STREAM_ID(2, 5)
|
||||
#define STM32_ADC_ADC4_DMA_STREAM STM32_DMA_STREAM_ID(2, 2)
|
||||
#define STM32_ADC_ADC1_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC2_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC3_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC4_DMA_PRIORITY 2
|
||||
#define STM32_ADC_ADC12_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC3_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC4_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC2_DMA_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC3_DMA_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC4_DMA_IRQ_PRIORITY 5
|
||||
#define STM32_ADC_ADC12_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
|
||||
#define STM32_ADC_ADC34_CLOCK_MODE ADC_CCR_CKMODE_AHB_DIV1
|
||||
|
||||
/*
|
||||
* CAN driver system settings.
|
||||
*/
|
||||
#define STM32_CAN_USE_CAN1 FALSE
|
||||
#define STM32_CAN_CAN1_IRQ_PRIORITY 11
|
||||
|
||||
/*
|
||||
* DAC driver system settings.
|
||||
*/
|
||||
#define STM32_DAC_DUAL_MODE FALSE
|
||||
#define STM32_DAC_USE_DAC1_CH1 TRUE
|
||||
#define STM32_DAC_USE_DAC1_CH2 TRUE
|
||||
#define STM32_DAC_DAC1_CH1_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH2_IRQ_PRIORITY 10
|
||||
#define STM32_DAC_DAC1_CH1_DMA_PRIORITY 2
|
||||
#define STM32_DAC_DAC1_CH2_DMA_PRIORITY 2
|
||||
|
||||
/*
|
||||
* GPT driver system settings.
|
||||
*/
|
||||
#define STM32_GPT_USE_TIM1 FALSE
|
||||
#define STM32_GPT_USE_TIM2 FALSE
|
||||
#define STM32_GPT_USE_TIM3 FALSE
|
||||
#define STM32_GPT_USE_TIM4 FALSE
|
||||
#define STM32_GPT_USE_TIM6 TRUE
|
||||
#define STM32_GPT_USE_TIM7 TRUE
|
||||
#define STM32_GPT_USE_TIM8 TRUE
|
||||
#define STM32_GPT_USE_TIM15 FALSE
|
||||
#define STM32_GPT_USE_TIM16 FALSE
|
||||
#define STM32_GPT_USE_TIM17 FALSE
|
||||
#define STM32_GPT_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM6_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM7_IRQ_PRIORITY 7
|
||||
#define STM32_GPT_TIM8_IRQ_PRIORITY 7
|
||||
|
||||
/*
|
||||
* I2C driver system settings.
|
||||
*/
|
||||
#define STM32_I2C_USE_I2C1 TRUE
|
||||
#define STM32_I2C_USE_I2C2 FALSE
|
||||
#define STM32_I2C_BUSY_TIMEOUT 50
|
||||
#define STM32_I2C_I2C1_IRQ_PRIORITY 10
|
||||
#define STM32_I2C_I2C2_IRQ_PRIORITY 10
|
||||
#define STM32_I2C_USE_DMA TRUE
|
||||
#define STM32_I2C_I2C1_DMA_PRIORITY 1
|
||||
#define STM32_I2C_I2C2_DMA_PRIORITY 1
|
||||
#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ICU driver system settings.
|
||||
*/
|
||||
#define STM32_ICU_USE_TIM1 FALSE
|
||||
#define STM32_ICU_USE_TIM2 FALSE
|
||||
#define STM32_ICU_USE_TIM3 FALSE
|
||||
#define STM32_ICU_USE_TIM4 FALSE
|
||||
#define STM32_ICU_USE_TIM8 FALSE
|
||||
#define STM32_ICU_USE_TIM15 FALSE
|
||||
#define STM32_ICU_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_ICU_TIM8_IRQ_PRIORITY 7
|
||||
|
||||
/*
|
||||
* PWM driver system settings.
|
||||
*/
|
||||
#define STM32_PWM_USE_ADVANCED FALSE
|
||||
#define STM32_PWM_USE_TIM1 FALSE
|
||||
#define STM32_PWM_USE_TIM2 FALSE
|
||||
#define STM32_PWM_USE_TIM3 TRUE
|
||||
#define STM32_PWM_USE_TIM4 TRUE
|
||||
#define STM32_PWM_USE_TIM8 FALSE
|
||||
#define STM32_PWM_USE_TIM15 FALSE
|
||||
#define STM32_PWM_USE_TIM16 FALSE
|
||||
#define STM32_PWM_USE_TIM17 FALSE
|
||||
#define STM32_PWM_TIM1_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM2_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM3_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM4_IRQ_PRIORITY 7
|
||||
#define STM32_PWM_TIM8_IRQ_PRIORITY 7
|
||||
|
||||
/*
|
||||
* RTC driver system settings.
|
||||
*/
|
||||
#define STM32_RTC_PRESA_VALUE 32
|
||||
#define STM32_RTC_PRESS_VALUE 1024
|
||||
#define STM32_RTC_CR_INIT 0
|
||||
#define STM32_RTC_TAMPCR_INIT 0
|
||||
|
||||
/*
|
||||
* SERIAL driver system settings.
|
||||
*/
|
||||
#define STM32_SERIAL_USE_USART1 FALSE
|
||||
#define STM32_SERIAL_USE_USART2
|
||||
#define STM32_SERIAL_USE_USART3 FALSE
|
||||
#define STM32_SERIAL_USE_UART4 FALSE
|
||||
#define STM32_SERIAL_USE_UART5 FALSE
|
||||
#define STM32_SERIAL_USART1_PRIORITY 12
|
||||
#define STM32_SERIAL_USART2_PRIORITY 12
|
||||
#define STM32_SERIAL_USART3_PRIORITY 12
|
||||
#define STM32_SERIAL_UART4_PRIORITY 12
|
||||
#define STM32_SERIAL_UART5_PRIORITY 12
|
||||
|
||||
/*
|
||||
* SPI driver system settings.
|
||||
*/
|
||||
#define STM32_SPI_USE_SPI1 FALSE
|
||||
#define STM32_SPI_USE_SPI2 FALSE
|
||||
#define STM32_SPI_USE_SPI3 FALSE
|
||||
#define STM32_SPI_SPI1_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI2_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI3_DMA_PRIORITY 1
|
||||
#define STM32_SPI_SPI1_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_SPI2_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_SPI3_IRQ_PRIORITY 10
|
||||
#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* ST driver system settings.
|
||||
*/
|
||||
#define STM32_ST_IRQ_PRIORITY 8
|
||||
#define STM32_ST_USE_TIMER 2
|
||||
|
||||
/*
|
||||
* UART driver system settings.
|
||||
*/
|
||||
#define STM32_UART_USE_USART1 FALSE
|
||||
#define STM32_UART_USE_USART2 FALSE
|
||||
#define STM32_UART_USE_USART3 FALSE
|
||||
#define STM32_UART_USART1_IRQ_PRIORITY 12
|
||||
#define STM32_UART_USART2_IRQ_PRIORITY 12
|
||||
#define STM32_UART_USART3_IRQ_PRIORITY 12
|
||||
#define STM32_UART_USART1_DMA_PRIORITY 0
|
||||
#define STM32_UART_USART2_DMA_PRIORITY 0
|
||||
#define STM32_UART_USART3_DMA_PRIORITY 0
|
||||
#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
|
||||
|
||||
/*
|
||||
* USB driver system settings.
|
||||
*/
|
||||
#define STM32_USB_USE_USB1 TRUE
|
||||
#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
|
||||
#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
|
||||
#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
|
||||
|
||||
/*
|
||||
* WDG driver system settings.
|
||||
*/
|
||||
#define STM32_WDG_USE_IWDG FALSE
|
||||
|
||||
#endif /* MCUCONF_H */
|
|
@ -0,0 +1 @@
|
|||
JOYSTICK_ENABLE = yes
|
|
@ -29,4 +29,4 @@
|
|||
|
||||
#define RGB_DI_PIN A0
|
||||
|
||||
#define ADC_PIN A0
|
||||
#define ADC_PIN A1
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
#include "joystick.h"
|
||||
|
||||
joystick_t joystick_status = {.buttons = {0},
|
||||
.axes =
|
||||
{
|
||||
#if JOYSTICK_AXES_COUNT > 0
|
||||
0
|
||||
#endif
|
||||
},
|
||||
.status = 0};
|
||||
|
||||
// array defining the reading of analog values for each axis
|
||||
__attribute__((weak)) joystick_config_t joystick_axes[JOYSTICK_AXES_COUNT] = {};
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef JOYSTICK_BUTTON_COUNT
|
||||
# define JOYSTICK_BUTTON_COUNT 8
|
||||
#endif
|
||||
|
||||
#ifndef JOYSTICK_AXES_COUNT
|
||||
# define JOYSTICK_AXES_COUNT 4
|
||||
#endif
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// configure on input_pin of the joystick_axes array entry to JS_VIRTUAL_AXIS
|
||||
// to prevent it from being read from the ADC. This allows outputing forged axis value.
|
||||
//
|
||||
#define JS_VIRTUAL_AXIS 0xFF
|
||||
|
||||
#define JOYSTICK_AXIS_VIRTUAL \
|
||||
{ JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, JS_VIRTUAL_AXIS, 0, 1023 }
|
||||
#define JOYSTICK_AXIS_IN(INPUT_PIN, LOW, REST, HIGH) \
|
||||
{ JS_VIRTUAL_AXIS, INPUT_PIN, JS_VIRTUAL_AXIS, LOW, REST, HIGH }
|
||||
#define JOYSTICK_AXIS_IN_OUT(INPUT_PIN, OUTPUT_PIN, LOW, REST, HIGH) \
|
||||
{ OUTPUT_PIN, INPUT_PIN, JS_VIRTUAL_AXIS, LOW, REST, HIGH }
|
||||
#define JOYSTICK_AXIS_IN_OUT_GROUND(INPUT_PIN, OUTPUT_PIN, GROUND_PIN, LOW, REST, HIGH) \
|
||||
{ OUTPUT_PIN, INPUT_PIN, GROUND_PIN, LOW, REST, HIGH }
|
||||
|
||||
typedef struct {
|
||||
pin_t output_pin;
|
||||
pin_t input_pin;
|
||||
pin_t ground_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_AXES_COUNT];
|
||||
|
||||
enum joystick_status { JS_INITIALIZED = 1, JS_UPDATED = 2 };
|
||||
|
||||
typedef struct {
|
||||
uint8_t buttons[JOYSTICK_BUTTON_COUNT / 8 + 1];
|
||||
|
||||
int16_t axes[JOYSTICK_AXES_COUNT];
|
||||
uint8_t status : 2;
|
||||
} joystick_t;
|
||||
|
||||
extern joystick_t joystick_status;
|
||||
|
||||
// to be implemented in the hid protocol library
|
||||
void send_joystick_packet(joystick_t *joystick);
|
|
@ -0,0 +1,168 @@
|
|||
#include "joystick.h"
|
||||
#include "process_joystick.h"
|
||||
|
||||
#include "analog.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
bool process_joystick(uint16_t keycode, keyrecord_t *record) {
|
||||
if (process_joystick_buttons(keycode, record) && (joystick_status.status & JS_UPDATED) > 0) {
|
||||
send_joystick_packet(&joystick_status);
|
||||
joystick_status.status &= ~JS_UPDATED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void joystick_task(void) {
|
||||
if (process_joystick_analogread() && (joystick_status.status & JS_UPDATED)) {
|
||||
send_joystick_packet(&joystick_status);
|
||||
joystick_status.status &= ~JS_UPDATED;
|
||||
}
|
||||
}
|
||||
|
||||
bool process_joystick_buttons(uint16_t keycode, keyrecord_t *record) {
|
||||
if (keycode < JS_BUTTON0 || keycode > JS_BUTTON_MAX) {
|
||||
return true;
|
||||
} else {
|
||||
if (record->event.pressed) {
|
||||
joystick_status.buttons[(keycode - JS_BUTTON0) / 8] |= 1 << (keycode % 8);
|
||||
} else {
|
||||
joystick_status.buttons[(keycode - JS_BUTTON0) / 8] &= ~(1 << (keycode % 8));
|
||||
}
|
||||
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t savePinState(pin_t pin) {
|
||||
#ifdef __AVR__
|
||||
uint8_t pinNumber = pin & 0xF;
|
||||
return ((PORTx_ADDRESS(pin) >> pinNumber) & 0x1) << 1 | ((DDRx_ADDRESS(pin) >> pinNumber) & 0x1);
|
||||
#elif defined(PROTOCOL_CHIBIOS)
|
||||
/*
|
||||
The pin configuration is backed up in the following format :
|
||||
bit 15 9 8 7 6 5 4 3 2 1 0
|
||||
|unused|ODR|IDR|PUPDR|OSPEEDR|OTYPER|MODER|
|
||||
*/
|
||||
return (( PAL_PORT(pin)->MODER >> (2*PAL_PAD(pin))) & 0x3)
|
||||
| (((PAL_PORT(pin)->OTYPER >> (1*PAL_PAD(pin))) & 0x1) << 2)
|
||||
| (((PAL_PORT(pin)->OSPEEDR >> (2*PAL_PAD(pin))) & 0x3) << 3)
|
||||
| (((PAL_PORT(pin)->PUPDR >> (2*PAL_PAD(pin))) & 0x3) << 5)
|
||||
| (((PAL_PORT(pin)->IDR >> (1*PAL_PAD(pin))) & 0x1) << 7)
|
||||
| (((PAL_PORT(pin)->ODR >> (1*PAL_PAD(pin))) & 0x1) << 8);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void restorePinState(pin_t pin, uint16_t restoreState) {
|
||||
#if defined(PROTOCOL_LUFA)
|
||||
uint8_t pinNumber = pin & 0xF;
|
||||
PORTx_ADDRESS(pin) = (PORTx_ADDRESS(pin) & ~_BV(pinNumber)) | (((restoreState >> 1) & 0x1) << pinNumber);
|
||||
DDRx_ADDRESS(pin) = (DDRx_ADDRESS(pin) & ~_BV(pinNumber)) | ((restoreState & 0x1) << pinNumber);
|
||||
#elif defined(PROTOCOL_CHIBIOS)
|
||||
PAL_PORT(pin)->MODER = (PAL_PORT(pin)->MODER & ~(0x3<< (2*PAL_PAD(pin)))) | (restoreState & 0x3) << (2*PAL_PAD(pin));
|
||||
PAL_PORT(pin)->OTYPER = (PAL_PORT(pin)->OTYPER & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>2) & 0x1) << (1*PAL_PAD(pin));
|
||||
PAL_PORT(pin)->OSPEEDR= (PAL_PORT(pin)->OSPEEDR & ~(0x3<< (2*PAL_PAD(pin)))) | ((restoreState>>3) & 0x3) << (2*PAL_PAD(pin));
|
||||
PAL_PORT(pin)->PUPDR = (PAL_PORT(pin)->PUPDR & ~(0x3<< (2*PAL_PAD(pin)))) | ((restoreState>>5) & 0x3) << (2*PAL_PAD(pin));
|
||||
PAL_PORT(pin)->IDR = (PAL_PORT(pin)->IDR & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>7) & 0x1) << (1*PAL_PAD(pin));
|
||||
PAL_PORT(pin)->ODR = (PAL_PORT(pin)->ODR & ~(0x1<< (1*PAL_PAD(pin)))) | ((restoreState>>8) & 0x1) << (1*PAL_PAD(pin));
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool process_joystick_analogread() { return process_joystick_analogread_quantum(); }
|
||||
|
||||
bool process_joystick_analogread_quantum() {
|
||||
#if JOYSTICK_AXES_COUNT > 0
|
||||
for (int axis_index = 0; axis_index < JOYSTICK_AXES_COUNT; ++axis_index) {
|
||||
if (joystick_axes[axis_index].input_pin == JS_VIRTUAL_AXIS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// save previous input pin status as well
|
||||
uint16_t inputSavedState = savePinState(joystick_axes[axis_index].input_pin);
|
||||
|
||||
// disable pull-up resistor
|
||||
writePinLow(joystick_axes[axis_index].input_pin);
|
||||
|
||||
// if pin was a pull-up input, we need to uncharge it by turning it low
|
||||
// before making it a low input
|
||||
setPinOutput(joystick_axes[axis_index].input_pin);
|
||||
|
||||
wait_us(10);
|
||||
|
||||
// save and apply output pin status
|
||||
uint16_t outputSavedState = 0;
|
||||
if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
|
||||
// save previous output pin status
|
||||
outputSavedState = savePinState(joystick_axes[axis_index].output_pin);
|
||||
|
||||
setPinOutput(joystick_axes[axis_index].output_pin);
|
||||
writePinHigh(joystick_axes[axis_index].output_pin);
|
||||
}
|
||||
|
||||
uint16_t groundSavedState = 0;
|
||||
if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
|
||||
// save previous output pin status
|
||||
groundSavedState = savePinState(joystick_axes[axis_index].ground_pin);
|
||||
|
||||
setPinOutput(joystick_axes[axis_index].ground_pin);
|
||||
writePinLow(joystick_axes[axis_index].ground_pin);
|
||||
}
|
||||
|
||||
wait_us(10);
|
||||
|
||||
setPinInput(joystick_axes[axis_index].input_pin);
|
||||
|
||||
wait_us(10);
|
||||
|
||||
# if defined(__AVR__) || defined(PROTOCOL_CHIBIOS)
|
||||
int16_t axis_val = analogReadPin(joystick_axes[axis_index].input_pin);
|
||||
# else
|
||||
// default to resting position
|
||||
int16_t axis_val = joystick_axes[axis_index].mid_digit;
|
||||
# endif
|
||||
|
||||
//test the converted value against the lower range
|
||||
int32_t ref = joystick_axes[axis_index].mid_digit;
|
||||
int32_t range = joystick_axes[axis_index].min_digit;
|
||||
int32_t ranged_val = ((axis_val - ref) * -127) / (range - ref) ;
|
||||
|
||||
if (ranged_val > 0) {
|
||||
//the value is in the higher range
|
||||
range = joystick_axes[axis_index].max_digit;
|
||||
ranged_val = ((axis_val - ref) * 127) / (range - ref);
|
||||
}
|
||||
|
||||
//clamp the result in the valid range
|
||||
ranged_val = ranged_val < -127 ? -127 : ranged_val;
|
||||
ranged_val = ranged_val > 127 ? 127 : ranged_val;
|
||||
|
||||
if (ranged_val != joystick_status.axes[axis_index]) {
|
||||
joystick_status.axes[axis_index] = ranged_val;
|
||||
joystick_status.status |= JS_UPDATED;
|
||||
}
|
||||
|
||||
// restore output, ground and input status
|
||||
if (joystick_axes[axis_index].output_pin != JS_VIRTUAL_AXIS) {
|
||||
restorePinState(joystick_axes[axis_index].output_pin, outputSavedState);
|
||||
}
|
||||
if (joystick_axes[axis_index].ground_pin != JS_VIRTUAL_AXIS) {
|
||||
restorePinState(joystick_axes[axis_index].ground_pin, groundSavedState);
|
||||
}
|
||||
|
||||
restorePinState(joystick_axes[axis_index].input_pin, inputSavedState);
|
||||
}
|
||||
|
||||
#endif
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "quantum.h"
|
||||
|
||||
bool process_joystick(uint16_t keycode, keyrecord_t *record);
|
||||
|
||||
void joystick_task(void);
|
||||
|
||||
bool process_joystick_analogread(void);
|
||||
bool process_joystick_analogread_quantum(void);
|
|
@ -280,6 +280,9 @@ bool process_record_quantum(keyrecord_t *record) {
|
|||
#endif
|
||||
#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
|
||||
process_rgb(keycode, record) &&
|
||||
#endif
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
process_joystick(keycode, record) &&
|
||||
#endif
|
||||
true)) {
|
||||
return false;
|
||||
|
|
|
@ -142,6 +142,10 @@ extern layer_state_t layer_state;
|
|||
# include "process_magic.h"
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
# include "process_joystick.h"
|
||||
#endif
|
||||
|
||||
#ifdef GRAVE_ESC_ENABLE
|
||||
# include "process_grave_esc.h"
|
||||
#endif
|
||||
|
|
|
@ -512,6 +512,41 @@ enum quantum_keycodes {
|
|||
DYN_MACRO_PLAY1,
|
||||
DYN_MACRO_PLAY2,
|
||||
|
||||
JS_BUTTON0,
|
||||
JS_BUTTON_MIN = JS_BUTTON0,
|
||||
JS_BUTTON1,
|
||||
JS_BUTTON2,
|
||||
JS_BUTTON3,
|
||||
JS_BUTTON4,
|
||||
JS_BUTTON5,
|
||||
JS_BUTTON6,
|
||||
JS_BUTTON7,
|
||||
JS_BUTTON8,
|
||||
JS_BUTTON9,
|
||||
JS_BUTTON10,
|
||||
JS_BUTTON11,
|
||||
JS_BUTTON12,
|
||||
JS_BUTTON13,
|
||||
JS_BUTTON14,
|
||||
JS_BUTTON15,
|
||||
JS_BUTTON16,
|
||||
JS_BUTTON17,
|
||||
JS_BUTTON18,
|
||||
JS_BUTTON19,
|
||||
JS_BUTTON20,
|
||||
JS_BUTTON21,
|
||||
JS_BUTTON22,
|
||||
JS_BUTTON23,
|
||||
JS_BUTTON24,
|
||||
JS_BUTTON25,
|
||||
JS_BUTTON26,
|
||||
JS_BUTTON27,
|
||||
JS_BUTTON28,
|
||||
JS_BUTTON29,
|
||||
JS_BUTTON30,
|
||||
JS_BUTTON31,
|
||||
JS_BUTTON_MAX = JS_BUTTON31,
|
||||
|
||||
// always leave at the end
|
||||
SAFE_RANGE
|
||||
};
|
||||
|
|
|
@ -71,6 +71,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#ifdef MIDI_ENABLE
|
||||
# include "process_midi.h"
|
||||
#endif
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
# include "process_joystick.h"
|
||||
#endif
|
||||
#ifdef HD44780_ENABLE
|
||||
# include "hd44780.h"
|
||||
#endif
|
||||
|
@ -403,6 +406,10 @@ MATRIX_LOOP_END:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
joystick_task();
|
||||
#endif
|
||||
|
||||
// update LED
|
||||
if (led_status != host_keyboard_leds()) {
|
||||
led_status = host_keyboard_leds();
|
||||
|
|
|
@ -29,7 +29,8 @@ enum hid_report_ids {
|
|||
REPORT_ID_MOUSE,
|
||||
REPORT_ID_SYSTEM,
|
||||
REPORT_ID_CONSUMER,
|
||||
REPORT_ID_NKRO
|
||||
REPORT_ID_NKRO,
|
||||
REPORT_ID_JOYSTICK
|
||||
};
|
||||
|
||||
/* Mouse buttons */
|
||||
|
@ -186,6 +187,16 @@ typedef struct {
|
|||
int8_t h;
|
||||
} __attribute__((packed)) report_mouse_t;
|
||||
|
||||
typedef struct {
|
||||
#if JOYSTICK_AXES_COUNT > 0
|
||||
int8_t axes[JOYSTICK_AXES_COUNT];
|
||||
#endif
|
||||
|
||||
#if JOYSTICK_BUTTON_COUNT > 0
|
||||
uint8_t buttons[(JOYSTICK_BUTTON_COUNT - 1) / 8 + 1];
|
||||
#endif
|
||||
} __attribute__((packed)) joystick_report_t;
|
||||
|
||||
/* keycode to system usage */
|
||||
static inline uint16_t KEYCODE2SYSTEM(uint8_t key) {
|
||||
switch (key) {
|
||||
|
|
|
@ -47,6 +47,10 @@
|
|||
extern keymap_config_t keymap_config;
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
# include "joystick.h"
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------------
|
||||
* Global interface variables and declarations
|
||||
* ---------------------------------------------------------
|
||||
|
@ -246,6 +250,9 @@ typedef struct {
|
|||
#endif
|
||||
#ifdef VIRTSER_ENABLE
|
||||
usb_driver_config_t serial_driver;
|
||||
#endif
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
usb_driver_config_t joystick_driver;
|
||||
#endif
|
||||
};
|
||||
usb_driver_config_t array[0];
|
||||
|
@ -283,6 +290,14 @@ static usb_driver_configs_t drivers = {
|
|||
# define CDC_OUT_MODE USB_EP_MODE_TYPE_BULK
|
||||
.serial_driver = QMK_USB_DRIVER_CONFIG(CDC, CDC_NOTIFICATION_EPNUM, false),
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
# define JOYSTICK_IN_CAPACITY 4
|
||||
# define JOYSTICK_OUT_CAPACITY 4
|
||||
# define JOYSTICK_IN_MODE USB_EP_MODE_TYPE_BULK
|
||||
# define JOYSTICK_OUT_MODE USB_EP_MODE_TYPE_BULK
|
||||
.joystick_driver = QMK_USB_DRIVER_CONFIG(JOYSTICK, 0, false),
|
||||
#endif
|
||||
};
|
||||
|
||||
#define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t))
|
||||
|
@ -870,3 +885,57 @@ void virtser_task(void) {
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
|
||||
void send_joystick_packet(joystick_t *joystick) {
|
||||
joystick_report_t rep = {
|
||||
# if JOYSTICK_AXES_COUNT > 0
|
||||
.axes = {joystick->axes[0],
|
||||
|
||||
# if JOYSTICK_AXES_COUNT >= 2
|
||||
joystick->axes[1],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 3
|
||||
joystick->axes[2],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 4
|
||||
joystick->axes[3],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 5
|
||||
joystick->axes[4],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 6
|
||||
joystick->axes[5],
|
||||
# endif
|
||||
},
|
||||
# endif // JOYSTICK_AXES_COUNT>0
|
||||
|
||||
# if JOYSTICK_BUTTON_COUNT > 0
|
||||
.buttons = {joystick->buttons[0],
|
||||
|
||||
# if JOYSTICK_BUTTON_COUNT > 8
|
||||
joystick->buttons[1],
|
||||
# endif
|
||||
# if JOYSTICK_BUTTON_COUNT > 16
|
||||
joystick->buttons[2],
|
||||
# endif
|
||||
# if JOYSTICK_BUTTON_COUNT > 24
|
||||
joystick->buttons[3],
|
||||
# endif
|
||||
}
|
||||
# endif // JOYSTICK_BUTTON_COUNT>0
|
||||
};
|
||||
|
||||
// chnWrite(&drivers.joystick_driver.driver, (uint8_t *)&rep, sizeof(rep));
|
||||
osalSysLock();
|
||||
if (usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
|
||||
osalSysUnlock();
|
||||
return;
|
||||
}
|
||||
|
||||
usbStartTransmitI(&USB_DRIVER, JOYSTICK_IN_EPNUM, (uint8_t *)&rep, sizeof(joystick_report_t));
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -85,6 +85,10 @@ extern keymap_config_t keymap_config;
|
|||
# include "raw_hid.h"
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
# include "joystick.h"
|
||||
#endif
|
||||
|
||||
uint8_t keyboard_idle = 0;
|
||||
/* 0: Boot Protocol, 1: Report Protocol(default) */
|
||||
uint8_t keyboard_protocol = 1;
|
||||
|
@ -263,6 +267,66 @@ static void Console_Task(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Joystick
|
||||
******************************************************************************/
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
void send_joystick_packet(joystick_t *joystick) {
|
||||
uint8_t timeout = 255;
|
||||
|
||||
joystick_report_t r = {
|
||||
# if JOYSTICK_AXES_COUNT > 0
|
||||
.axes = {joystick->axes[0],
|
||||
|
||||
# if JOYSTICK_AXES_COUNT >= 2
|
||||
joystick->axes[1],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 3
|
||||
joystick->axes[2],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 4
|
||||
joystick->axes[3],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 5
|
||||
joystick->axes[4],
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 6
|
||||
joystick->axes[5],
|
||||
# endif
|
||||
},
|
||||
# endif // JOYSTICK_AXES_COUNT>0
|
||||
|
||||
# if JOYSTICK_BUTTON_COUNT > 0
|
||||
.buttons = {joystick->buttons[0],
|
||||
|
||||
# if JOYSTICK_BUTTON_COUNT > 8
|
||||
joystick->buttons[1],
|
||||
# endif
|
||||
# if JOYSTICK_BUTTON_COUNT > 16
|
||||
joystick->buttons[2],
|
||||
# endif
|
||||
# if JOYSTICK_BUTTON_COUNT > 24
|
||||
joystick->buttons[3],
|
||||
# endif
|
||||
}
|
||||
# endif // JOYSTICK_BUTTON_COUNT>0
|
||||
};
|
||||
|
||||
/* Select the Joystick Report Endpoint */
|
||||
Endpoint_SelectEndpoint(JOYSTICK_IN_EPNUM);
|
||||
|
||||
/* Check if write ready for a polling interval around 10ms */
|
||||
while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);
|
||||
if (!Endpoint_IsReadWriteAllowed()) return;
|
||||
|
||||
/* Write Joystick Report Data */
|
||||
Endpoint_Write_Stream_LE(&r, sizeof(joystick_report_t), NULL);
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* USB Events
|
||||
******************************************************************************/
|
||||
|
@ -410,6 +474,9 @@ void EVENT_USB_Device_ConfigurationChanged(void) {
|
|||
ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_OUT_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
ConfigSuccess &= Endpoint_ConfigureEndpoint(CDC_IN_EPADDR, EP_TYPE_BULK, CDC_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
ConfigSuccess &= ENDPOINT_CONFIG(JOYSTICK_IN_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN, JOYSTICK_EPSIZE, ENDPOINT_BANK_SINGLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* FIXME: Expose this table in the docs somehow
|
||||
|
|
|
@ -278,6 +278,63 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
# if JOYSTICK_AXES_COUNT == 0 && JOYSTICK_BUTTON_COUNT == 0
|
||||
# error Need at least one axis or button for joystick
|
||||
# endif
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM JoystickReport[] = {
|
||||
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
|
||||
HID_RI_USAGE(8, 0x04), // Joystick
|
||||
HID_RI_COLLECTION(8, 0x01), // Application
|
||||
HID_RI_COLLECTION(8, 0x00), // Physical
|
||||
HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop
|
||||
# if JOYSTICK_AXES_COUNT >= 1
|
||||
HID_RI_USAGE(8, 0x30), // X
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 2
|
||||
HID_RI_USAGE(8, 0x31), // Y
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 3
|
||||
HID_RI_USAGE(8, 0x32), // Z
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 4
|
||||
HID_RI_USAGE(8, 0x33), // Rx
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 5
|
||||
HID_RI_USAGE(8, 0x34), // Ry
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 6
|
||||
HID_RI_USAGE(8, 0x35), // Rz
|
||||
# endif
|
||||
# if JOYSTICK_AXES_COUNT >= 1
|
||||
HID_RI_LOGICAL_MINIMUM(8, -127),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 127),
|
||||
HID_RI_REPORT_COUNT(8, JOYSTICK_AXES_COUNT),
|
||||
HID_RI_REPORT_SIZE(8, 0x08),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
# endif
|
||||
|
||||
# if JOYSTICK_BUTTON_COUNT >= 1
|
||||
HID_RI_USAGE_PAGE(8, 0x09), // Button
|
||||
HID_RI_USAGE_MINIMUM(8, 0x01),
|
||||
HID_RI_USAGE_MAXIMUM(8, JOYSTICK_BUTTON_COUNT),
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0x01),
|
||||
HID_RI_REPORT_COUNT(8, JOYSTICK_BUTTON_COUNT),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
|
||||
|
||||
# if (JOYSTICK_BUTTON_COUNT % 8) != 0
|
||||
HID_RI_REPORT_COUNT(8, 8 - (JOYSTICK_BUTTON_COUNT % 8)),
|
||||
HID_RI_REPORT_SIZE(8, 0x01),
|
||||
HID_RI_INPUT(8, HID_IOF_CONSTANT),
|
||||
# endif
|
||||
# endif
|
||||
HID_RI_END_COLLECTION(0),
|
||||
HID_RI_END_COLLECTION(0)
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Device descriptor
|
||||
*/
|
||||
|
@ -287,7 +344,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = {
|
|||
.Type = DTYPE_Device
|
||||
},
|
||||
.USBSpecification = VERSION_BCD(1, 1, 0),
|
||||
|
||||
|
||||
#if VIRTSER_ENABLE
|
||||
.Class = USB_CSCP_IADDeviceClass,
|
||||
.SubClass = USB_CSCP_IADDeviceSubclass,
|
||||
|
@ -812,6 +869,46 @@ const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor = {
|
|||
.PollingIntervalMS = 0x05
|
||||
},
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Joystick
|
||||
*/
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
.Joystick_Interface = {
|
||||
.Header = {
|
||||
.Size = sizeof(USB_Descriptor_Interface_t),
|
||||
.Type = DTYPE_Interface
|
||||
},
|
||||
.InterfaceNumber = JOYSTICK_INTERFACE,
|
||||
.AlternateSetting = 0x00,
|
||||
.TotalEndpoints = 1,
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
.Joystick_HID = {
|
||||
.Header = {
|
||||
.Size = sizeof(USB_HID_Descriptor_HID_t),
|
||||
.Type = HID_DTYPE_HID
|
||||
},
|
||||
.HIDSpec = VERSION_BCD(1, 1, 1),
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(JoystickReport)
|
||||
},
|
||||
.Joystick_INEndpoint = {
|
||||
.Header = {
|
||||
.Size = sizeof(USB_Descriptor_Endpoint_t),
|
||||
.Type = DTYPE_Endpoint
|
||||
},
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | JOYSTICK_IN_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = JOYSTICK_EPSIZE,
|
||||
.PollingIntervalMS = USB_POLLING_INTERVAL_MS
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -944,6 +1041,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
|
|||
|
||||
break;
|
||||
#endif
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
case JOYSTICK_INTERFACE:
|
||||
Address = &ConfigurationDescriptor.Joystick_HID;
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -988,6 +1091,12 @@ uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const
|
|||
|
||||
break;
|
||||
#endif
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
case JOYSTICK_INTERFACE:
|
||||
Address = &JoystickReport;
|
||||
Size = sizeof(JoystickReport);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -123,6 +123,13 @@ typedef struct {
|
|||
USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
|
||||
USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
// Joystick HID Interface
|
||||
USB_Descriptor_Interface_t Joystick_Interface;
|
||||
USB_HID_Descriptor_HID_t Joystick_HID;
|
||||
USB_Descriptor_Endpoint_t Joystick_INEndpoint;
|
||||
#endif
|
||||
} USB_Descriptor_Configuration_t;
|
||||
|
||||
/*
|
||||
|
@ -164,6 +171,9 @@ enum usb_interfaces {
|
|||
CDI_INTERFACE,
|
||||
#endif
|
||||
|
||||
#if defined(JOYSTICK_ENABLE)
|
||||
JOYSTICK_INTERFACE,
|
||||
#endif
|
||||
TOTAL_INTERFACES
|
||||
};
|
||||
|
||||
|
@ -224,6 +234,10 @@ enum usb_endpoints {
|
|||
# define CDC_IN_EPADDR (ENDPOINT_DIR_IN | CDC_IN_EPNUM)
|
||||
# define CDC_OUT_EPADDR (ENDPOINT_DIR_OUT | CDC_OUT_EPNUM)
|
||||
#endif
|
||||
#ifdef JOYSTICK_ENABLE
|
||||
JOYSTICK_IN_EPNUM = NEXT_EPNUM,
|
||||
JOYSTICK_OUT_EPNUM = NEXT_EPNUM,
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef PROTOCOL_LUFA
|
||||
|
@ -248,6 +262,7 @@ enum usb_endpoints {
|
|||
#define MIDI_STREAM_EPSIZE 64
|
||||
#define CDC_NOTIFICATION_EPSIZE 8
|
||||
#define CDC_EPSIZE 16
|
||||
#define JOYSTICK_EPSIZE 8
|
||||
|
||||
uint16_t get_usb_descriptor(const uint16_t wValue, const uint16_t wIndex, const void** const DescriptorAddress);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue