Commit graph

62 commits

Author SHA1 Message Date
30e22c210c
fix(firmware): zero SPI IMU calibration origins to prevent phantom rotation
The Switch applies its stored SPI calibration when interpreting IMU data:
  gyro_dps = (raw - spi_origin) * 936 / coeff

The firmware had real hardware offsets as calibration origins:
  gyro_origin = (9, -22, -95)  accel_origin = (-29, -199, 493)

A real Pro Controller sensor reads those values at rest, so the Switch
subtracts them to get zero. But our bridge already removes hardware bias
via gyro bias calibration and sends near-zero counts when still.

The Switch was then applying a second origin correction:
  gyro_z=2 → (2 - (-95)) * 0.070 = 6.79 dps constant yaw rotation

This caused the character to spin horizontally even when holding the
controller perfectly still.

Fix: zero all calibration origins. The bridge handles bias correction;
the Switch must not apply a second offset on top.
2026-03-16 17:22:52 -06:00
9d33bc4be7
fix(bridge): fix gyro bias calibration corruption and zero-accel startup
Two bugs causing constant camera drift and jarring first-frame behaviour:

1. Bias calibration was immediately collecting samples at launch, while the
   user is still typing / setting down the controller. This polluted the bias
   estimate (observed: by=-0.073 rad/s vs true ~-0.009 rad/s), causing a
   permanent ~4 deg/s camera drift even when the controller is held still.
   Fix: reject samples with gyro magnitude >= 0.5 rad/s (motion threshold)
   during the calibration window so only truly still samples count. Also add
   a return-early so no IMU is sent to the Pico until bias is locked.

2. last_accel initialised to (0,0,0), but the first gyro event fires before
   the first accel event. The Pico received accel=(0,0,0) on the first sample
   instead of the expected ~4096 counts on the gravity axis.
   Fix: default last_accel to (0.0, 9.80665, 0.0) — gravity on SDL Y axis,
   which is correct for a Pro Controller held in normal gaming position.
2026-03-16 17:16:49 -06:00
12dc3d58ee
chore: add raw SDL3 IMU diagnostic tool 2026-03-16 17:05:56 -06:00
5c18c75d33 feat(bridge): migrate to SDL3 and fix controller hotplug issues
- Migrate all SDL2 GameController API calls to SDL3 Gamepad equivalents
- Fix PermissionError on controller reconnect by closing UART handle before
  releasing port back to pool (Windows holds COM ports exclusively)
- Add DisplayIndexAllocator so controllers get stable display indices (0, 0, 0)
  instead of incrementing SDL instance IDs (1, 2, 3) on each reconnect
- Button mapping now uses SDL3 positional constants (SOUTH/EAST/WEST/NORTH)
  which works correctly for all controller types without USE_BUTTON_LABELS hint

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-16 16:54:58 -06:00
3f6bf3dee2 chore: replace pysdl2 with PySDL3 for SDL3 sensor support
SDL3 includes a dedicated 8BitDo HIDAPI driver with native gyro/accel sensor support, which SDL2 lacked.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-16 16:54:45 -06:00
e13ba506cf
chore: add uv lockfile for reproducible dependency resolution 2026-03-16 12:19:36 -06:00
91c619691d
chore: update README with IMU/motion controls documentation 2026-03-16 12:00:49 -06:00
bd973253a6
fix(bridge): reverse SDL axis remapping to recover Nintendo-native IMU axes
SDL's hidapi_switch.c SendSensorUpdate() remaps Nintendo's raw sensor axes
to match PlayStation convention before emitting SDL sensor events:
  SDL_X = -Nintendo_Y, SDL_Y = +Nintendo_Z, SDL_Z = -Nintendo_X

This commit reverses that transform so the values sent to the Pico are in
Nintendo's native coordinate frame:
  Nintendo_X_raw = -SDL_Z
  Nintendo_Y_raw = -SDL_X
  Nintendo_Z_raw = +SDL_Y

Same mapping for gyro (bias subtraction happens before axis reversal).
Confirmed from SDL3 hidapi_switch.c source (SDL2 uses same SDL3 backend).
2026-03-16 12:00:44 -06:00
22da7bce8f
chore: add IMU diagnostic tool
- Add tools/read_pro_imu.py from gyrov3 branch
- Reads raw 0x30 HID reports from Switch Pro Controller / Pico
- Lazy pyhidapi import with helpful error message when missing
- Supports --list, --count, --plot, --save-prefix flags
2026-03-16 11:50:46 -06:00
d81e8f90c0
feat(bridge): add SDL sensor reading and gyro bias calibration
- Add initialize_controller_sensors() for SDL accel/gyro enable
- Add handle_sensor_update() with direct axis passthrough (no remapping)
- Add gyro bias calibration (200 samples, zero gyro until locked)
- Add IMU sample FIFO with pop-to-report before UART send
- Add --debug-imu, --no-imu, --gyro-scale CLI flags
2026-03-16 11:50:40 -06:00
0db04be858
feat(firmware): add IMU data structures and UART v2 parser
- Add SwitchImuSample struct and IMU fields to SwitchInputState
- Add fill_imu_report_data() to pack samples into imuData[36]
- Rewrite switch_pro_apply_uart_packet() for v2 with checksum validation
- Enlarge poll_uart_frames() buffer to 64 bytes for variable-length frames
- Clear imu_sample_count after each USB report send (prevent stale IMU)
2026-03-16 11:50:32 -06:00
2604ff274b
feat(uart): add v2 protocol with IMU sample support
- Add UART_PROTOCOL_VERSION=2, IMUSample dataclass, conversion constants
- Rewrite SwitchReport.to_bytes() for versioned v2 framing with checksum
- Add ACCEL_LSB_PER_G=4096, GYRO_LSB_PER_RAD_S=818.5, MS2_PER_G constants
- Add SENSOR_ACCEL/SENSOR_GYRO SDL type constants with fallback
- Add protocol round-trip tests (8 tests, all passing)
2026-03-16 11:50:25 -06:00
ae65251cb4 Fix controllers 2026-01-10 23:19:32 -07:00
b04a6d29ca
Add license 2025-12-14 14:47:49 -07:00
e41a1746ba
Add references 2025-12-14 14:08:03 -07:00
22cfe62c41
Add gyro branch ref 2025-12-14 14:04:28 -07:00
ef10552e19
Touch up readme, fix build.py 2025-12-14 13:31:11 -07:00
11b397df20
Add firmware and readme for building firmware 2025-12-14 13:23:20 -07:00
81f281e93f
Update readme 2025-12-14 13:10:39 -07:00
b6553fc305
Rearrange python code 2025-12-08 19:36:01 -07:00
53f07b5a6f
Add reference to GP2040-CE repo 2025-12-08 19:27:30 -07:00
ef3b08352c
Remove autotest 2025-12-08 19:20:24 -07:00
6a8bf6c27f Add manufacturer 2025-12-06 11:53:36 -07:00
5779599000 Add build.py 2025-12-06 11:41:53 -07:00
jojomawswan
aef37123fd Refactor 2025-12-01 13:29:04 -07:00
jojomawswan
1cb7075180 Make example work and redo some library code 2025-12-01 12:45:13 -07:00
jojomawswan
abdda5a7c4 Add pyproject.toml 2025-11-29 22:43:02 -07:00
jojomawswan
3a9f707e9b Add docs 2025-11-29 21:51:00 -07:00
jojomawswan
c37bcc2ce4 Add swapping hotkey 2025-11-29 21:03:34 -07:00
jojomawswan
8e740d4fff Add zeroing ability 2025-11-29 20:54:15 -07:00
80528ff39e
Make more sane search 2025-11-25 17:57:14 -07:00
5ce26f2181
Tighten serial detection for linux 2025-11-25 17:51:21 -07:00
6191333abb
Remove rust 2025-11-25 16:24:42 -07:00
ac5fc7be44
add requirements.txt 2025-11-25 11:37:09 -07:00
396d8ba33d
Refactor into lib 2025-11-25 06:23:01 -07:00
491a35888a
Build with colors :) 2025-11-24 22:40:51 -07:00
2835249614
Add GUID based selection 2025-11-23 10:08:59 -07:00
215e7f8bde
Docs and connection 2025-11-23 09:58:07 -07:00
954b47253c
Fix hotplugging 2025-11-23 09:48:30 -07:00
dca3e0f9d1
README update 2025-11-23 09:33:08 -07:00
4b7dbc4fbd
Comments 2025-11-23 09:31:43 -07:00
963c19c5d6
Refactor 2025-11-23 09:27:16 -07:00
jojomawswan
25212d870b Make stuff work in windows 2025-11-22 18:37:54 -07:00
jojomawswan
f8f7cc4d08 Types 2025-11-22 11:08:24 -07:00
900c5b89f0
Add include for controllers 2025-11-22 10:12:30 -07:00
702b96eaa5
Add abxy swapping 2025-11-22 09:27:40 -07:00
3a4ca98fa9
Add hints for pro controller 2025-11-22 09:24:13 -07:00
bd21dc5ea6
Uart opening warning 2025-11-22 08:22:25 -07:00
92abe29340
Add include filter 2025-11-21 15:59:37 -07:00
fd9f86a182
Add filtering 2025-11-21 15:49:39 -07:00