mirror of
https://github.com/qmk/qmk_firmware
synced 2025-01-06 15:01:39 +00:00
Merge 7f6580ebdfcc324b35c0f9bf0ecf15b5b529682f into 5eb60827d5ba65c7f56307390a499bec75dfea8b
This commit is contained in:
@ -121,7 +121,7 @@ ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
|
||||
MOUSE_ENABLE := yes
|
||||
endif
|
||||
|
||||
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick azoteq_iqs5xx cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3320 pmw3360 pmw3389 pimoroni_trackball custom
|
||||
VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick azoteq_iqs5xx cirque_pinnacle_i2c cirque_pinnacle_spi paw3204 pmw3320 pmw3360 pmw3389 pimoroni_trackball spacemouse_module custom
|
||||
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
|
||||
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),)
|
||||
$(call CATASTROPHIC_ERROR,Invalid POINTING_DEVICE_DRIVER,POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type)
|
||||
@ -155,6 +155,8 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
|
||||
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device_gestures.c
|
||||
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pimoroni_trackball)
|
||||
I2C_DRIVER_REQUIRED = yes
|
||||
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), spacemouse_module)
|
||||
UART_DRIVER_REQUIRED = yes
|
||||
else ifneq ($(filter $(strip $(POINTING_DEVICE_DRIVER)),pmw3360 pmw3389),)
|
||||
SPI_DRIVER_REQUIRED = yes
|
||||
SRC += drivers/sensors/pmw33xx_common.c
|
||||
|
@ -368,6 +368,34 @@ report_mouse_t pointing_device_task_kb(report_mouse_t mouse_report) {
|
||||
|
||||
```
|
||||
|
||||
### SpaceMouse Module (UART)
|
||||
|
||||
To use the SpaceMouse module to control the pointer, add this to your `rules.mk`
|
||||
|
||||
```make
|
||||
POINTING_DEVICE_DRIVER = spacemouse_module
|
||||
```
|
||||
|
||||
The SpaceMouse Module is a UART driven sensor, with 6 axes of motion.
|
||||
|
||||
| Setting (`config.h`) | Description | Default |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------- | ------------- |
|
||||
| `SPACEMOUSE_USE_TILT_AXIS` | Uses the tilt axes for movement rather than the shift axes. | _not_defined_ |
|
||||
|
||||
|
||||
By default, not all of the axes are utilized. If you would like to use more of them, you can do so by using this custom function, which translates the data from the SpaceMouse Module to the pointing device report.
|
||||
|
||||
```c
|
||||
void spacemouse_module_handle_axes(spacemouse_data_t *spacemouse_data, report_mouse_t* mouse_report) {
|
||||
mouse_report->x = CONSTRAIN_HID_XY(spacemouse_data->x);
|
||||
mouse_report->y = CONSTRAIN_HID_XY(spacemouse_data->y);
|
||||
mouse_report->h = CONSTRAIN_HID(spacemouse_data->b);
|
||||
mouse_report->v = CONSTRAIN_HID(spacemouse_data->c);
|
||||
|
||||
mouse_report->buttons = pointing_device_handle_buttons(mouse_report->buttons, (space_mouse_data->z < -10), KC_BTN1);
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Driver
|
||||
|
||||
If you have a sensor type that isn't supported above, a custom option is available by adding the following to your `rules.mk`
|
||||
|
164
drivers/sensors/spacemouse_module.c
Normal file
164
drivers/sensors/spacemouse_module.c
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright 2023 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "spacemouse_module.h"
|
||||
#include "pointing_device_internal.h"
|
||||
#include "uart.h"
|
||||
|
||||
// datasheet available at https://3dconnexion.com/cn/wp-content/uploads/2020/02/HW-Spec-3DX-700039_Rev001_serial.pdf
|
||||
|
||||
/* Datasheet UART settings specify:
|
||||
* baud rate: 38400
|
||||
* data bits: 8
|
||||
* parity: none
|
||||
* stop bits: 1
|
||||
* data rate: max 100/s
|
||||
*/
|
||||
|
||||
#define SPACEMOUSE_BAUD_RATE 38400
|
||||
#define SPACEMOUSE_AXIS_COUNT 6
|
||||
#define SPACEMOUSE_LENGTH_DATA (2 * SPACEMOUSE_AXIS_COUNT)
|
||||
#define SPACEMOUSE_INPUT_OFFSET (8192)
|
||||
|
||||
|
||||
const pointing_device_driver_t pointing_device_driver = {
|
||||
.init = spacemouse_init,
|
||||
.get_report = spacemouse_get_report,
|
||||
.set_cpi = NULL,
|
||||
.get_cpi = NULL
|
||||
};
|
||||
|
||||
static bool spacemouse_present = false;
|
||||
|
||||
enum spacemouse_commands {
|
||||
SPACEMOUSE_CMD_REQUEST_DATA = 0xAC,
|
||||
SPACEMOUSE_CMD_SET_ZERO_POSITION = 0xAD,
|
||||
SPACEMOUSE_CMD_AUTO_DATA_ON = 0xAE,
|
||||
SPACEMOUSE_CMD_AUTO_DATA_OFF = 0xAF,
|
||||
SPACEMOUSE_CMD_END = 0x8D,
|
||||
SPACEMOUSE_DATA_REQUEST_START = 0x96,
|
||||
};
|
||||
|
||||
bool spacemouse_send_command(uint8_t cmd) {
|
||||
uart_write(cmd);
|
||||
uint8_t buf[2];
|
||||
uart_receive(buf, 2);
|
||||
return (buf[0] == cmd && buf[1] == SPACEMOUSE_CMD_END);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the zero position of the module
|
||||
*
|
||||
* @return true command ran successfully
|
||||
* @return false command failed
|
||||
*/
|
||||
bool spacemouse_cmd_set_zero_position(void) {
|
||||
return spacemouse_send_command(SPACEMOUSE_CMD_SET_ZERO_POSITION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts automatic transmission of data, at 30ms invervals
|
||||
* Automatic data transmission happens at 30 ms intervals, we don't need need the stream command,
|
||||
* but it is here for completeness, in case somebody wants to implement it elsewhere.
|
||||
*
|
||||
* @return true command ran successfully
|
||||
* @return false command failed
|
||||
*/
|
||||
bool spacemouse_cmd_enable_stream(void) {
|
||||
return spacemouse_send_command(SPACEMOUSE_CMD_AUTO_DATA_ON);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops automatic transmission of data, at 30ms invervals
|
||||
*
|
||||
* @return true command ran successfully
|
||||
* @return false command failed
|
||||
*/
|
||||
bool spacemouse_cmd_disable_stream(void) {
|
||||
return spacemouse_send_command(SPACEMOUSE_CMD_AUTO_DATA_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize UART connection and send command to zero out starting position.
|
||||
*
|
||||
*/
|
||||
void spacemouse_init(void) {
|
||||
uart_init(SPACEMOUSE_BAUD_RATE);
|
||||
// position is zeroed out during device start, but re-zero it out to ensure that the
|
||||
// device is present and working properly.
|
||||
spacemouse_present = spacemouse_cmd_set_zero_position();
|
||||
}
|
||||
|
||||
spacemouse_data_t spacemouse_get_data(void) {
|
||||
spacemouse_data_t data = {0};
|
||||
uint8_t retry_attempts = 0, index = 0, payload[SPACEMOUSE_LENGTH_DATA + SPACEMOUSE_LENGTH_CHECKSUM] = {0};
|
||||
uint16_t checksum = 0, checksum_received = 0;
|
||||
bool has_started = false;
|
||||
uart_write(SPACEMOUSE_CMD_REQUEST_DATA);
|
||||
while (retry_attempts <= 15) {
|
||||
uint8_t buf = uart_read();
|
||||
if (buf == SPACEMOUSE_DATA_REQUEST_START) {
|
||||
has_started = true;
|
||||
checksum = buf;
|
||||
retry_attempts = 0;
|
||||
continue;
|
||||
} else if (has_started) {
|
||||
if (buf == SPACEMOUSE_CMD_END) {
|
||||
break;
|
||||
} else {
|
||||
if (index >= SPACEMOUSE_LENGTH_DATA) {
|
||||
if (index == SPACEMOUSE_LENGTH_DATA) {
|
||||
checksum_received = buf << 7;
|
||||
} else {
|
||||
checksum_received += buf;
|
||||
}
|
||||
} else {
|
||||
payload[index] = buf;
|
||||
checksum += buf;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
retry_attempts++;
|
||||
};
|
||||
|
||||
checksum &= 0x3FFF;
|
||||
|
||||
if (has_started) {
|
||||
if (checksum_received == checksum) {
|
||||
data.x = (int16_t)((payload[0] << 7) + payload[1]) - SPACEMOUSE_INPUT_OFFSET;
|
||||
data.z = (int16_t)((payload[2] << 7) + payload[3]) - SPACEMOUSE_INPUT_OFFSET;
|
||||
data.y = (int16_t)((payload[4] << 7) + payload[5]) - SPACEMOUSE_INPUT_OFFSET;
|
||||
data.tilt_y = (int16_t)((payload[6] << 7) + payload[7]) - SPACEMOUSE_INPUT_OFFSET;
|
||||
data.twist = (int16_t)((payload[8] << 7) + payload[9]) - SPACEMOUSE_INPUT_OFFSET;
|
||||
data.tilt_x = (int16_t)((payload[10] << 7) + payload[11]) - SPACEMOUSE_INPUT_OFFSET;
|
||||
} else {
|
||||
pd_dprintf("Space Mouse Checksum error: 0x%04x != 0x%04x \n", checksum_received, checksum);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
__attribute__((weak)) void spacemouse_module_handle_axes(spacemouse_data_t* spacemouse_data, report_mouse_t* mouse_report) {
|
||||
# ifdef SPACEMOUSE_USE_TILT_AXIS
|
||||
mouse_report->x = CONSTRAIN_HID_XY(spacemouse_data->tilt_x);
|
||||
mouse_report->y = CONSTRAIN_HID_XY(spacemouse_data->tilt_y);
|
||||
# else
|
||||
mouse_report->x = CONSTRAIN_HID_XY(spacemouse_data->x);
|
||||
mouse_report->y = CONSTRAIN_HID_XY(spacemouse_data->y);
|
||||
# endif
|
||||
}
|
||||
|
||||
report_mouse_t spacemouse_get_report(report_mouse_t mouse_report) {
|
||||
if (spacemouse_present) {
|
||||
spacemouse_data_t data = spacemouse_get_data();
|
||||
|
||||
if (data.x || data.y || data.z || data.twist || data.tilt_x || data.tilt_y) {
|
||||
pd_dprintf("Raw ] X: %d, Y: %d, Z: %d, twist: %d, tilt X: %d, tilt Y: %d\n", data.x, data.y, data.z, data.twist, data.tilt_x, data.tilt_y);
|
||||
}
|
||||
spacemouse_module_handle_axes(&data, &mouse_report);
|
||||
}
|
||||
return mouse_report;
|
||||
}
|
22
drivers/sensors/spacemouse_module.h
Normal file
22
drivers/sensors/spacemouse_module.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2023 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "pointing_device.h"
|
||||
|
||||
typedef struct {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
int16_t twist;
|
||||
int16_t tilt_x;
|
||||
int16_t tilt_y;
|
||||
} spacemouse_data_t;
|
||||
|
||||
bool spacemouse_send_command(uint8_t cmd);
|
||||
void spacemouse_init(void);
|
||||
spacemouse_data_t spacemouse_get_data(void);
|
||||
report_mouse_t spacemouse_get_report(report_mouse_t mouse_report);
|
@ -73,6 +73,8 @@ typedef struct {
|
||||
# include "spi_master.h"
|
||||
# include "drivers/sensors/pmw33xx_common.h"
|
||||
# define POINTING_DEVICE_MOTION_PIN_ACTIVE_LOW
|
||||
#elif defined(POINTING_DEVICE_DRIVER_spacemouse_module)
|
||||
# include "drivers/sensors/spacemouse_module.h"
|
||||
#else
|
||||
void pointing_device_driver_init(void);
|
||||
report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report);
|
||||
|
Reference in New Issue
Block a user