Rework the code for hex-based protocol - #1
Conversation
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.
|
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.
|
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. |
Use a context manager to set up curses raw keyboard
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.