Skip to content

Rework the code for hex-based protocol - #1

Merged
Phroon merged 9 commits into
Phroon:masterfrom
ali1234:master
Sep 4, 2018
Merged

Rework the code for hex-based protocol#1
Phroon merged 9 commits into
Phroon:masterfrom
ali1234:master

Conversation

@ali1234

@ali1234 ali1234 commented Aug 31, 2018

Copy link
Copy Markdown

This changes Joystick.c to use hex strings which halves the amount of data transmitted. It also refactors the interrupt service routine to be more robust, by using a circular buffer to minimize time spent inside the ISR. This code is stable at 115200 baud.

The new protocol is implemented on PC side by bridge.py which needs pysdl2 and python 3. The PC
side software is not fully implemented: hat and a couple of buttons are not available (the missing buttons are double mapped so some PC buttons trigger two Switch buttons, hat is not implemented at all.)

See individual commit messages for details.

Use "make flash" to write the firmware. Target type is taken from
the makefile variable.
This implements a hex message protocol with the following structure:

2 hex chars: hat state
4 hex chars: button state
2 hex chars: lx
2 hex chars: ly
2 hex chars: rx
2 hex chars: ry
terminated with \n or \n (or both).

For a total of 15 bytes per message.

Upper or lower case hex characters are accepted. Non-hex characters
will be completely ignored.

Early or late termination will cause the whole message up to this
point to be dropped.

The button state is big endian, ie the high byte comes first. The rest
is identical to the HID report format, except hex encoded.

Parsing code has been moved out of the ISR and replaced by a circular
buffer to avoid overruns.

The code will never send back a response on serial unless there is
an overrun, then it will send "X".

This code is stable at 115200 bps.
This code is incomplete. It uses the SDL Game Controller subsystem
which is easy to use because it makes all controllers look like
an XBOX 360 controller. Unfortunately it doesn't have enough buttons
for every switch button.

See "./bridge.py --help" for usage. You can specify the controller
by number or name, and set the port and baudrate. The default baud
rate matches the one in Joystick.c as of this commit. The other
defaults should work if you have only one controller.

Rather than sending an update for every event, this sends an update
every ~5 msec (subject to python timing inaccuracy). It seems very
responsive compared to previous versions.

In order to get the full joystick mapping working the code should
be modified to use SDL_Joystick instead of SDL_GameController
however this code will be joystick-specific as there is no standard
mapping for SDL_Joystick.
@ali1234

ali1234 commented Aug 31, 2018

Copy link
Copy Markdown
Author

PS I tested this on a Minimus 32 development board. It is ATMEGA32U2. It should be fully compatible as only the flash size is different and I made the code smaller. :)

I don't have either a Switch or a PS3 controller so I tested it by connecting the Switch side back to my PC and with a Classic Xbox controller. I used a CP2102 USB to serial cable for comms (Adafruit branded, not a Chinese fake one...)

Each time the Arduino revieves a transfer request on the IN end
point, write 'U' to the serial port. The bridge waits for 'U' after
sending an update.

This synchronizes the flow of information from the PC to the switch
such that it should only send one controller update each time the
Switch polls for information on USB.

This is not guaranteed to be related to frames at all because the
USB host controller chip will be running independent of the main
CPU.
Return the hex encoded state so it can be sent or written to a file.
Use "-P replay.txt" to record a replay and "-R replay.txt" to play back.
This will show how often the bridge is sending a state update. On
PC it sends 250 updates per second ie 4 msec interrupt interval.
@ali1234

ali1234 commented Sep 4, 2018

Copy link
Copy Markdown
Author

The most recent commits synchronize controller updates with the switch USB interrupt transfers. Each time the switch polls the IN endpoint for controller data the Arduino will send "U" on serial. bridge.py will wait for this message on serial before sending another controller state.

There is also additional debugging: a message will be printed if an overrun is detected and the number of controller updates per second will be displayed.

Finally a basic record and playback feature is implemented. Use "./bridge.py -R file.txt" to record and "./bridge.py -P file.txt" to play it back.

@Phroon
Phroon merged commit beda8a8 into Phroon:master Sep 4, 2018
ali1234 pushed a commit to ali1234/switch-controller that referenced this pull request Sep 7, 2018
Use a context manager to set up curses raw keyboard
@aelzeiny aelzeiny mentioned this pull request Jun 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants