VinDuv / switch-arduino-controller

Nintendo Switch controller emulator using an Arduino, with Pokémon Sword/Shield automation scripts.
MIT License
59 stars 15 forks source link

USB interface does not seem to be working #4

Open p2lab opened 2 years ago

p2lab commented 2 years ago

USB interface does not seem to be working. I was able to compile the project successfully and flashed both .hex to each ATmega. Verification (avrdude) was OK. I read flash content manually to make sure it was flashed properly as well. Everything seems fine but it does nothing on my Nintendo Switch. I was thinking maybe it's not compatible with latest NSwitch version? Mine is currently on 13.2.0 (btw, I tried to connecting the Arduino to both USB ports on the side and the one on the back)

VinDuv commented 2 years ago

That’s weird, my Switch is up to date (13.2.0) and it works. Note that the Switch will not detect the controller until it registers itself; the current code only does this when you push the button you connected between pins 12 and ground on your Arduino. You also need to be on the Switch’s home menu when doing that.

p2lab commented 2 years ago

I'm on home menu when I push the button but nothing happens. Is there some sort of video tutorial? Just to check if there's something I'm missing. Also, TX and RX LEDs won't light up, only L LED is blinking. I mentioned in my previous post but just to be clear, it works with the Switch docked, right?

VinDuv commented 2 years ago

Yes, the Switch needs to be docked. Here is what should happen:

  1. You plug the Arduino. L blinks rapidly, TX and RX are off.
  2. You press and release the pushbutton (Nothing happens on the press, only the release)
  3. L stops blinking
  4. The controller setup is performed
  5. L blinks slowly, TX and RX are on

From your description, it looks like the Arduino doesn’t register the pushbutton being pressed. Maybe there’s a problem with it? You can try replacing it with a piece of wire to temporarily bridge pins 12 and GND.

p2lab commented 2 years ago

I bridged pin12 and GND as you suggested but I still get the same. L doesn't blink "rapidly" tho, the sequence goes like: ON during t_0 seconds, OFF during t_0 seconds, ON during t_0 seconds, OFF during t_1 seconds, being t_1 > t_0 (haven't measured exactly these times but I can tell just by looking at it), then start the sequence again.

Not sure if it's worth mentioning this but NSwitch is always kept in airplane mode (Bluetooth ON, NFC OFF, WiFi OFF), there are some updates I don't want to install so I keep it like that. As far as I'm aware, this shouldn't affect USB connections but just in case. Also, I always leave Joy-Cons plugged to the NSwitch and use the Pro controller, which is always connected via Bluetooth when testing this.

Since bridging these pin12 and GND doesn't seem to affect L LED (it keeps blinking), I suppose it's stuck at count_button_presses(100, 100); (line 46, swsh.c)? Since init_led_button() seems to be working? Not sure about beep() since I don't have a buzzer atm.

VinDuv commented 2 years ago

L doesn't blink "rapidly" tho, the sequence goes like: ON during t_0 seconds, OFF during t_0 seconds, ON during t_0 seconds, OFF during t_1 seconds, being t_1 > t_0 (haven't measured exactly these times but I can tell just by looking at it), then start the sequence again.

OK, this makes more sense. L blinking N times, stopping, and blinking again indicates that the main µC (ATmega328P) has encountered an error condition and has entered “panic mode” by calling the panic function. In panic mode, pressing the button will do nothing. The number of times the LED blinks indicates the value that was passed to the panic function; in your case it blinks twice, which means panic(2) is called; automation.c calls panic(2) at lines 86 and 164 to indicate that an invalid character has been received from the USB µC (ATmega16U2). This could be caused by:

NSwitch is always kept in airplane mode (Bluetooth ON, NFC OFF, WiFi OFF)

I tried it on my Switch (by undocking it, putting it in airplane mode, re-docking it and reconnecting the pro controller) and it didn’t have any effect on the operation of the Arduino.

Also, I always leave Joy-Cons plugged to the NSwitch and use the Pro controller, which is always connected via Bluetooth when testing this.

Same here.

p2lab commented 2 years ago

Some issue with the USB µC; try connecting it to your computer instead of the Switch and check that it’s recognized as a “POKKEN CONTROLLER”.

This is what I got with lsusb: Bus 001 Device 004: ID 0f0d:0092 Hori Co., Ltd POKKEN CONTROLLER

Some timing issue at startup; I had this problem in the past and fixed it by increasing the startup delay of the USB µC. If that’s the case, pressing the reset button on the Arduino should force a re-sync and make it work.

Pressed the reset button and L started blinking rapidly this time. Then I tried pushing the button and L turned off (and never turned on again unless I press reset button) but no controller setup was performed.

EDIT: also tried bridging the pins together just in case but same result

VinDuv commented 2 years ago

Bus 001 Device 004: ID 0f0d:0092 Hori Co., Ltd POKKEN CONTROLLER

Looks fine; I guess USB configuration is working, at least.

Pressed the reset button and L started blinking rapidly this time.

Okay, that means the serial port communication between the µCs seem to be working, but not at startup. Maybe try increasing the startup delay a bit (maybe 11 -> 21 in usb-iface.c:63 and 12 -> 22 in automation.c:51) and see if that fixes it.

Then I tried pushing the button and L turned off (and never turned on again unless I press reset button)

This means the main µC started the automation sequence (which means the button press was correctly recognized), but stopped because the “give me more data” message from the USB µC was not received. It can be caused by either a communication issue between the two µCs (unlikely since reset works, but maybe there is a problem when more data is sent?), or the USB µC not receiving controller report requests from the Switch (and thus not requesting more data from the main µC).

The following patch may help debugging the issue:

diff --git a/src/usb-iface/usb-iface.c b/src/usb-iface/usb-iface.c
index c4f118a..9d30077 100644
--- a/src/usb-iface/usb-iface.c
+++ b/src/usb-iface/usb-iface.c
@@ -160,6 +160,7 @@ void refresh_and_send_controller_data(void)

        send_count += 1;
        if (send_count == 5) {
+               LEDs_ToggleLEDs(LEDMASK_TX);
                send_count = 0;
        }
 }
@@ -180,6 +181,7 @@ bool refresh_controller_data(void)

        /* Refresh the controller data */
        if (recv_buffer_count == DATA_SIZE) {
+               LEDs_ToggleLEDs(LEDMASK_RX);
                uint8_t magic_data = recv_buffer[MAGIC_INDEX];

                if ((magic_data & MAGIC_MASK) == MAGIC_VALUE) {
@@ -194,7 +196,7 @@ bool refresh_controller_data(void)
                                new_led_state |= LEDMASK_RX;
                        }

-                       LEDs_SetAllLEDs(new_led_state);
+                       //LEDs_SetAllLEDs(new_led_state);

                        /* Don’t copy the magic byte to the controller data, leave it 0 */
                        memcpy(out_data, recv_buffer, DATA_SIZE - 1);

It changes the TX/RX LEDs to do the following:

I have noticed that for some reason, my Arduino’s main µC works but does not accept being reprogrammed. This means that unfortunately I may not be able to help you debug this issue further until I buy a new one.

p2lab commented 2 years ago

Okay, that means the serial port communication between the µCs seem to be working, but not at startup. Maybe try increasing the startup delay a bit (maybe 11 -> 21 in usb-iface.c:63 and 12 -> 22 in automation.c:51) and see if that fixes it.

Tried that but I still have to press reset.

The following patch may help debugging the issue:

Also tried that but TX/RX never blinked. You mentioned RX should toggle at each reset and stay still until I press the button but I didn't see that happening

I'm always a bit paranoid about not correctly programming the ATmega16U2 so I double checked it by reading flash content and comparing it with the newly generated HEX file (even though that's what avrdude does).

EDIT: tried the same with my PC (I mean, the patch). Here, I get different results every time I disconnect and connect the Arduino to the PC: Sometimes TX and RX LED turn on at the same time, sometimes only RX LED turns on. But on Switch, they're both off.

VinDuv commented 2 years ago

I just got a new Arduino Uno R3; after flashing it, it works on my Switch. So I have absolutely no idea why it’s not working in your case. Just for reference, both of my Arduino Uno R3 look like this (the earlier one has slightly different markings but the same components): arduino

Another thing you could try is to build and flash the standalone USB interface, with:

make STANDALONE_USB_IFACE=1 clean flash-usb-iface

Then go to the Controllers > Change Grip/Order page on the Switch, and plug the Arduino. The virtual controller should register itself, navigate to All Software, and navigate to the right. This will work regardless of the state of the main µC.

Just to be sure, I’m attaching to this message the usb-iface.hex file for the standalone USB interface. It should hopefully be identical to the one built on your side.

usb-iface.hex.gz

p2lab commented 2 years ago

Just to be sure, I’m attaching to this message the usb-iface.hex file for the standalone USB interface. It should hopefully be identical to the one built on your side.

For some reason I don't know, I can't seem to build the same exact file as the one you provided. Anyway, I tried flashing the one you posted and did all the steps but still does not work. I guess I'm giving up :( thanks for the help!