Enable strong rumble for 8BitDo Switch mode
This commit is contained in:
parent
fd23842327
commit
8351cb1d15
5 changed files with 214 additions and 7 deletions
|
|
@ -259,10 +259,10 @@ index 0265f93..5c0f2bb 100644
|
|||
return (psmove_instance_t*)&d->parser_data[0];
|
||||
}
|
||||
diff --git a/src/components/bluepad32/parser/uni_hid_parser_switch.c b/src/components/bluepad32/parser/uni_hid_parser_switch.c
|
||||
index 599fc35..c72f056 100644
|
||||
index 599fc35..9f073b4 100644
|
||||
--- a/src/components/bluepad32/parser/uni_hid_parser_switch.c
|
||||
+++ b/src/components/bluepad32/parser/uni_hid_parser_switch.c
|
||||
@@ -51,7 +51,8 @@ static const int16_t DEFAULT_ACCEL_OFFSET = 0;
|
||||
@@ -51,13 +51,15 @@ static const int16_t DEFAULT_ACCEL_OFFSET = 0;
|
||||
static const int16_t DEFAULT_ACCEL_SCALE = 16384;
|
||||
static const int16_t DEFAULT_GYRO_OFFSET = 0;
|
||||
static const int16_t DEFAULT_GYRO_SCALE = 13371;
|
||||
|
|
@ -272,7 +272,97 @@ index 599fc35..c72f056 100644
|
|||
|
||||
#define SWITCH_FACTORY_IMU_CAL_DATA_SIZE 24
|
||||
static const uint16_t SWITCH_FACTORY_IMU_CAL_DATA_ADDR = 0x6020;
|
||||
@@ -823,19 +824,26 @@ static void parse_imu(uni_hid_device_t* d, const struct switch_imu_data_s* r) {
|
||||
|
||||
#define SWITCH_DUMP_ROM_DATA_SIZE 24 // Max size is 24
|
||||
#define SWITCH_SETUP_TIMEOUT_MS 800
|
||||
+#define SWITCH_RUMBLE_REFRESH_MS 40
|
||||
#if ENABLE_SPI_FLASH_DUMP
|
||||
static const uint32_t SWITCH_DUMP_ROM_DATA_ADDR_START = 0x20000;
|
||||
static const uint32_t SWITCH_DUMP_ROM_DATA_ADDR_END = 0x30000;
|
||||
@@ -72,6 +74,7 @@ enum switch_state {
|
||||
STATE_READ_FACTORY_IMU_CALIBRATION, // Factory IMU calibration info
|
||||
STATE_SET_FULL_REPORT, // Request report 0x30
|
||||
STATE_ENABLE_IMU, // Enable/Disable gyro/accel
|
||||
+ STATE_ENABLE_RUMBLE, // Enable controller vibration
|
||||
STATE_DUMP_FLASH, // Dump SPI Flash memory
|
||||
STATE_UPDATE_LED, // Update LEDs
|
||||
STATE_READY, // Gamepad setup ready!
|
||||
@@ -111,6 +114,7 @@ enum switch_subcmd {
|
||||
SUBCMD_SPI_FLASH_READ = 0x10,
|
||||
SUBCMD_SET_PLAYER_LEDS = 0x30,
|
||||
SUBCMD_ENABLE_IMU = 0x40,
|
||||
+ SUBCMD_ENABLE_RUMBLE = 0x48,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@@ -137,6 +141,7 @@ typedef struct switch_instance_s {
|
||||
// Although technically, we can use one timer for delay and duration, easier to debug/maintain if we have two.
|
||||
btstack_timer_source_t rumble_timer_duration;
|
||||
btstack_timer_source_t rumble_timer_delayed_start;
|
||||
+ btstack_timer_source_t rumble_timer_refresh;
|
||||
switch_state_rumble_t rumble_state;
|
||||
|
||||
btstack_timer_source_t setup_timer;
|
||||
@@ -322,6 +327,7 @@ static void fsm_read_user_stick_calibration(struct uni_hid_device_s* d);
|
||||
static void fsm_read_factory_imu_calibration(struct uni_hid_device_s* d);
|
||||
static void fsm_set_full_report(struct uni_hid_device_s* d);
|
||||
static void fsm_enable_imu(struct uni_hid_device_s* d);
|
||||
+static void fsm_enable_rumble(struct uni_hid_device_s* d);
|
||||
static void fsm_update_led(struct uni_hid_device_s* d);
|
||||
static void fsm_ready(struct uni_hid_device_s* d);
|
||||
static void process_reply_read_spi_dump(struct uni_hid_device_s* d, const uint8_t* data, int len);
|
||||
@@ -333,11 +339,16 @@ static void process_reply_set_report_mode(struct uni_hid_device_s* d, const stru
|
||||
static void process_reply_spi_flash_read(struct uni_hid_device_s* d, const struct switch_report_21_s* r, int len);
|
||||
static void process_reply_set_player_leds(struct uni_hid_device_s* d, const struct switch_report_21_s* r, int len);
|
||||
static void process_reply_enable_imu(struct uni_hid_device_s* d, const struct switch_report_21_s* r, int len);
|
||||
+static void process_reply_enable_rumble(struct uni_hid_device_s* d, const struct switch_report_21_s* r, int len);
|
||||
static int32_t calibrate_axis(int32_t v, switch_cal_stick_t cal);
|
||||
static void set_led(uni_hid_device_t* d, uint8_t leds);
|
||||
static void on_switch_set_rumble_on(btstack_timer_source_t* ts);
|
||||
static void on_switch_set_rumble_off(btstack_timer_source_t* ts);
|
||||
+static void on_switch_refresh_rumble(btstack_timer_source_t* ts);
|
||||
static void switch_stop_rumble_now(uni_hid_device_t* d);
|
||||
+static void switch_send_dual_rumble_now(uni_hid_device_t* d,
|
||||
+ uint8_t weak_magnitude,
|
||||
+ uint8_t strong_magnitude);
|
||||
static void switch_play_dual_rumble_now(uni_hid_device_t* d,
|
||||
uint16_t duration_ms,
|
||||
uint8_t weak_magnitude,
|
||||
@@ -451,6 +462,10 @@ static void process_fsm(struct uni_hid_device_s* d) {
|
||||
break;
|
||||
case STATE_ENABLE_IMU:
|
||||
logd("STATE_ENABLE_IMU\n");
|
||||
+ fsm_enable_rumble(d);
|
||||
+ break;
|
||||
+ case STATE_ENABLE_RUMBLE:
|
||||
+ logd("STATE_ENABLE_RUMBLE\n");
|
||||
fsm_dump_rom(d);
|
||||
break;
|
||||
case STATE_DUMP_FLASH:
|
||||
@@ -725,6 +740,12 @@ static void process_reply_enable_imu(struct uni_hid_device_s* d, const struct sw
|
||||
ARG_UNUSED(r);
|
||||
ARG_UNUSED(len);
|
||||
}
|
||||
+static void process_reply_enable_rumble(struct uni_hid_device_s* d, const struct switch_report_21_s* r, int len) {
|
||||
+ ARG_UNUSED(d);
|
||||
+ ARG_UNUSED(r);
|
||||
+ ARG_UNUSED(len);
|
||||
+}
|
||||
+
|
||||
|
||||
// Process 0x21 input report: SWITCH_INPUT_SUBCMD_REPLY
|
||||
static void process_input_subcmd_reply(struct uni_hid_device_s* d, const uint8_t* report, int len) {
|
||||
@@ -752,6 +773,9 @@ static void process_input_subcmd_reply(struct uni_hid_device_s* d, const uint8_t
|
||||
case SUBCMD_ENABLE_IMU:
|
||||
process_reply_enable_imu(d, r, len);
|
||||
break;
|
||||
+ case SUBCMD_ENABLE_RUMBLE:
|
||||
+ process_reply_enable_rumble(d, r, len);
|
||||
+ break;
|
||||
default:
|
||||
loge("Switch: Error, unexpected subcmd_id=0x%02x in report 0x21\n", r->subcmd_id);
|
||||
break;
|
||||
@@ -823,19 +847,26 @@ static void parse_imu(uni_hid_device_t* d, const struct switch_imu_data_s* r) {
|
||||
switch_instance_t* ins = get_switch_instance(d);
|
||||
uni_controller_t* ctl = &d->controller;
|
||||
|
||||
|
|
@ -308,7 +398,7 @@ index 599fc35..c72f056 100644
|
|||
if (ins->controller_type == SWITCH_CONTROLLER_TYPE_JCR) {
|
||||
accel[1] = -accel[1];
|
||||
accel[2] = -accel[2];
|
||||
@@ -843,10 +851,13 @@ static void parse_imu(uni_hid_device_t* d, const struct switch_imu_data_s* r) {
|
||||
@@ -843,10 +874,13 @@ static void parse_imu(uni_hid_device_t* d, const struct switch_imu_data_s* r) {
|
||||
gyro[2] = -gyro[2];
|
||||
}
|
||||
|
||||
|
|
@ -326,6 +416,121 @@ index 599fc35..c72f056 100644
|
|||
}
|
||||
|
||||
// Process 0x30 input report: SWITCH_INPUT_IMU_DATA
|
||||
@@ -1172,6 +1206,18 @@ static void fsm_enable_imu(struct uni_hid_device_s* d) {
|
||||
req->data[0] = (ins->mode == SWITCH_MODE_IMU);
|
||||
send_subcmd(d, req, sizeof(out));
|
||||
}
|
||||
+static void fsm_enable_rumble(struct uni_hid_device_s* d) {
|
||||
+ switch_instance_t* ins = get_switch_instance(d);
|
||||
+ ins->state = STATE_ENABLE_RUMBLE;
|
||||
+
|
||||
+ uint8_t out[sizeof(struct switch_subcmd_request) + 1] = {0};
|
||||
+ struct switch_subcmd_request* req = (struct switch_subcmd_request*)&out[0];
|
||||
+ req->report_id = OUTPUT_RUMBLE_AND_SUBCMD;
|
||||
+ req->subcmd_id = SUBCMD_ENABLE_RUMBLE;
|
||||
+ req->data[0] = 0x01;
|
||||
+ send_subcmd(d, req, sizeof(out));
|
||||
+}
|
||||
+
|
||||
|
||||
static void fsm_update_led(struct uni_hid_device_s* d) {
|
||||
switch_instance_t* ins = get_switch_instance(d);
|
||||
@@ -1203,6 +1249,10 @@ static struct switch_rumble_freq_data find_rumble_freq(uint16_t freq) {
|
||||
return rumble_freqs[i];
|
||||
}
|
||||
|
||||
+static uint16_t switch_magnitude_to_amp(uint8_t magnitude) {
|
||||
+ return (uint16_t)(((uint32_t)magnitude * 1003 + 127) / 255);
|
||||
+}
|
||||
+
|
||||
static struct switch_rumble_amp_data find_rumble_amp(uint16_t amp) {
|
||||
unsigned int i = 0;
|
||||
if (amp > rumble_amps[0].amp) {
|
||||
@@ -1259,6 +1309,7 @@ void uni_hid_parser_switch_play_dual_rumble(struct uni_hid_device_s* d,
|
||||
break;
|
||||
case SWITCH_STATE_RUMBLE_IN_PROGRESS:
|
||||
btstack_run_loop_remove_timer(&ins->rumble_timer_duration);
|
||||
+ btstack_run_loop_remove_timer(&ins->rumble_timer_refresh);
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
@@ -1366,6 +1417,7 @@ static void switch_stop_rumble_now(uni_hid_device_t* d) {
|
||||
|
||||
// No need to protect it with a mutex since it runs in the same main thread
|
||||
assert(ins->rumble_state == SWITCH_STATE_RUMBLE_IN_PROGRESS);
|
||||
+ btstack_run_loop_remove_timer(&ins->rumble_timer_refresh);
|
||||
ins->rumble_state = SWITCH_STATE_RUMBLE_DISABLED;
|
||||
|
||||
struct switch_subcmd_request req = {0};
|
||||
@@ -1379,6 +1431,22 @@ static void switch_stop_rumble_now(uni_hid_device_t* d) {
|
||||
send_subcmd(d, (struct switch_subcmd_request*)&req, sizeof(req) - 1);
|
||||
}
|
||||
|
||||
+static void switch_send_dual_rumble_now(uni_hid_device_t* d,
|
||||
+ uint8_t weak_magnitude,
|
||||
+ uint8_t strong_magnitude) {
|
||||
+ struct switch_subcmd_request req = {
|
||||
+ .report_id = OUTPUT_RUMBLE_ONLY,
|
||||
+ };
|
||||
+ // Fixed frequencies match the standard Switch LRA envelope and the
|
||||
+ // 8BitDo Switch-mode implementation. Magnitudes control amplitude only.
|
||||
+ switch_encode_rumble(req.rumble_left, 453, 135,
|
||||
+ switch_magnitude_to_amp(weak_magnitude));
|
||||
+ switch_encode_rumble(req.rumble_right, 453, 99,
|
||||
+ switch_magnitude_to_amp(strong_magnitude));
|
||||
+ // Rumble request don't include the last byte of "switch_subcmd_request": subcmd_id
|
||||
+ send_subcmd(d, &req, sizeof(req) - 1);
|
||||
+}
|
||||
+
|
||||
static void switch_play_dual_rumble_now(uni_hid_device_t* d,
|
||||
uint16_t duration_ms,
|
||||
uint8_t weak_magnitude,
|
||||
@@ -1391,14 +1459,17 @@ static void switch_play_dual_rumble_now(uni_hid_device_t* d,
|
||||
return;
|
||||
}
|
||||
|
||||
- struct switch_subcmd_request req = {
|
||||
- .report_id = OUTPUT_RUMBLE_ONLY,
|
||||
- };
|
||||
- switch_encode_rumble(req.rumble_left, weak_magnitude << 2, weak_magnitude, 500);
|
||||
- switch_encode_rumble(req.rumble_right, strong_magnitude << 2, strong_magnitude, 500);
|
||||
+ ins->rumble_weak_magnitude = weak_magnitude;
|
||||
+ ins->rumble_strong_magnitude = strong_magnitude;
|
||||
+ switch_send_dual_rumble_now(d, weak_magnitude, strong_magnitude);
|
||||
|
||||
- // Rumble request don't include the last byte of "switch_subcmd_request": subcmd_id
|
||||
- send_subcmd(d, &req, sizeof(req) - 1);
|
||||
+ // Refresh active rumble for Switch-compatible controllers that do not
|
||||
+ // retain a single output packet, including 8BitDo Switch mode.
|
||||
+ ins->rumble_timer_refresh.process = &on_switch_refresh_rumble;
|
||||
+ ins->rumble_timer_refresh.context = d;
|
||||
+ btstack_run_loop_set_timer(&ins->rumble_timer_refresh,
|
||||
+ SWITCH_RUMBLE_REFRESH_MS);
|
||||
+ btstack_run_loop_add_timer(&ins->rumble_timer_refresh);
|
||||
|
||||
// Set timer to turn off rumble
|
||||
ins->rumble_timer_duration.process = &on_switch_set_rumble_off;
|
||||
@@ -1414,6 +1485,20 @@ static void on_switch_set_rumble_on(btstack_timer_source_t* ts) {
|
||||
|
||||
switch_play_dual_rumble_now(d, ins->rumble_duration_ms, ins->rumble_weak_magnitude, ins->rumble_strong_magnitude);
|
||||
}
|
||||
+static void on_switch_refresh_rumble(btstack_timer_source_t* ts) {
|
||||
+ uni_hid_device_t* d = btstack_run_loop_get_timer_context(ts);
|
||||
+ switch_instance_t* ins = get_switch_instance(d);
|
||||
+ if (ins->rumble_state != SWITCH_STATE_RUMBLE_IN_PROGRESS) {
|
||||
+ return;
|
||||
+ }
|
||||
+ switch_send_dual_rumble_now(
|
||||
+ d, (uint8_t)ins->rumble_weak_magnitude,
|
||||
+ (uint8_t)ins->rumble_strong_magnitude);
|
||||
+ btstack_run_loop_set_timer(&ins->rumble_timer_refresh,
|
||||
+ SWITCH_RUMBLE_REFRESH_MS);
|
||||
+ btstack_run_loop_add_timer(&ins->rumble_timer_refresh);
|
||||
+}
|
||||
+
|
||||
|
||||
static void on_switch_set_rumble_off(btstack_timer_source_t* ts) {
|
||||
uni_hid_device_t* d = btstack_run_loop_get_timer_context(ts);
|
||||
diff --git a/src/components/bluepad32/parser/uni_hid_parser_wii.c b/src/components/bluepad32/parser/uni_hid_parser_wii.c
|
||||
index be2103e..4819639 100644
|
||||
--- a/src/components/bluepad32/parser/uni_hid_parser_wii.c
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue