Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2snes2nes firmware not working with 2 NES pads simultaneously #2

Open
prosper00 opened this issue Feb 10, 2021 · 24 comments
Open

2snes2nes firmware not working with 2 NES pads simultaneously #2

prosper00 opened this issue Feb 10, 2021 · 24 comments
Assignees

Comments

@prosper00
Copy link

This is a fantastic little project!

I recently discovered the ch55x series in general and this project in particular. I built it up in an hour or so, flashed your 2SNES firmware, and everything worked perfectly the first time around. It was almost too easy :)

20210210_164335

@prosper00
Copy link
Author

prosper00 commented Feb 11, 2021

I spoke too soon. It enumerates correctly as having two gamepads, and, if either one of them is connected, it works correctly. Button presses register with the OS. BUT if BOTH pads are connected at the same time, only the second pad registers any activity.

I've eliminated electrical connection issues - both pads are seeing the same latch and clock signals, and VCC/GND. When I scope the pins, I see activity on each data line (p1.5 and p1.4) when a single pad is connected.

Next up, when I get some time, I'll hook up a logic analyzer and get some captures to see if there's any sort of timing issues

@prosper00 prosper00 changed the title Well done! Works great with 2x NES pads 2snes2nes firmware not working with 2 NES pads simultaneously Feb 11, 2021
@prosper00
Copy link
Author

prosper00 commented Feb 15, 2021

I connected up the logic analyzer, and saw.... exactly what I expected to see. Both pads are getting the CLK and Latch signals, and both are reporting back data correctly on their respective pins. Latch pulse goes high, and both pads immediately start sending data. The clock toggles 16 times (though the pads only send 8-clocks worth of data, seeing as they're NES pads and not SNES). You can see from the trace that gamepad 1 IS sending data back, however, these presses aren't making it back to the OS (not shown here, but gamepad 2 does work, and does register with the OS)

Screenshot at 2021-02-18 13-07-15

Only the 2nd device reports anything back to the USB host (PC). Will set up wireshark to snoop the USB traffic next; (my logic analyzer isn't fast enough to do USB.), just once I figure out how to use wireshark :)

@ishiyakazuo
Copy link
Owner

Sorry, just noticed activity on this project! I'll do some digging myself. To be honest, I'm trying to recall if I've tested it with multiple pads connected... I know I tested it by just holding the data line low on the other ports at one point to see them react... I'm really a little puzzled, since there's nothing for it to "know" in terms of the controller being plugged in.

I suspect it's not a USB issue, probably has to do with the autodetection routine or something.

What do you mean by "I see activity on each data line (p1.5 and p1.4) when a single pad is connected"? That's weird, because the data line is just an input to the MCU in that case. Are you sure that's not just your logic analyzer picking up some noise from adjacent lines?

Come to think of it, I know that I've gotten this working with 2 SNES controllers, because I built this for my arcade cabinet, and to simplify the wiring, I wired each player's inputs to a 16-bit shift register and then to this board... though I can't remember for sure if I used the 2 player or 4 player firmware on that one. I'll check and get back to you. This could be a quirk of two NES controllers -- I've never tested out the NES code path. It's pretty much as-is from the original code from Raphnet.

@ishiyakazuo ishiyakazuo self-assigned this Apr 2, 2021
@ishiyakazuo
Copy link
Owner

Well, I went to go check it out and my arcade panel seems to be acting up... guess I know what I'm doing this weekend. I'll also see what I can do about wiring up "NES" pads to see what I find there. It seems to be flashed with old firmware, and Windows 10 is complaining (I was doing most of my testing under Linux, so I may have gotten it to the point where Linux worked, flashed it, and never re-flashed it when I fixed the Windows issue), so I'll try flashing the latest 2 port firmware on it this weekend (since it's only got 2 controllers attached anyway), and report back. I'm relatively sure I did test it with 2 active ports, so I'm really puzzled by this. It might be a few more days before I can spend much time on it (need to set up my testing rig again and the compiler and programming setup, etc.), but I'll see what I can do to get to the bottom of this on my end.

@prosper00
Copy link
Author

I kinda shelved this for a while, while i read up on the usb protocol, so i haven't played with this much recently

@ishiyakazuo
Copy link
Owner

Once I get everything set up, I'll see what I find. I don't know if I have any CH552T chips on hand -- I'm wondering if there's something involved with those. (Though there's actually one controller type I would like to support, and the CH55xG parts don't have enough I/O, so maybe I need to fix that...)

@prosper00
Copy link
Author

Hm. I might have some 'G' chips, but they could be 554's... I'll have to check my stash

@ishiyakazuo
Copy link
Owner

Did you build the code or take my prebuilt binaries, by any chance? It seems the prebuilt binaries may have been out of date. I've rebuilt them -- if you did just load the binaries, can you give the latest a try and see if that improves anything? If not, I'll dig further into it.

@ishiyakazuo
Copy link
Owner

I reproduced your issue. Seems like the most recent controller opened by the OS works, but the others freeze up. Thanks for opening this ticket. I'll give this some attention.

@prosper00
Copy link
Author

I built my own, in any case

@ishiyakazuo
Copy link
Owner

OK, thanks. I seem to recall running into this same issue earlier in the development, and I'd thought I had it taken care of, but I guess not. All of the binaries I uploaded act the same (in Linux -- the oldest one doesn't work in Windows).
I did some debug today, took some captures in Wireshark, and what appears to be happening is that the host is, at some point, asking multiple endpoints for data, and only the most recent request ever comes back with data, so the host says "Well, OK, then I guess never mind the other ones that stopped talking to me" (obviously the problem is that the device isn't providing responses to both requests somewhat independently). It just sits there waiting for a response that it never gets from the CH55x, so now I need to figure out how to get multiple endpoints to respond... I'm sure it's something goofy I'm doing.

@ishiyakazuo
Copy link
Owner

So as soon as I posted that, I tried one thing and it seems to have made a difference... at least sort of. I can use both controllers now, though the second controller seems to be less responsive than the first. I'm puzzled as to why that would be, since there's nothing inherently favoring one over the other in the code, as far as I can tell. If you grab the latest main.c, you can give this version a shot on your end and see if it makes any difference for you. I'll still mess with this some more, because I'm a little bit puzzled as to why the controllers aren't equally responsive.

@prosper00
Copy link
Author

Cool. Will do, tomorrow.

I'm still really new to usb, so, I'm looking forward to playing with your code.

@prosper00
Copy link
Author

I'm really new at USB, but, couldnt you use a single top level collection in your descriptor setup, and then send multiple reports with unique reportid's on a single HID device, rather than implementing each gamepad as its own endpoint?

@ishiyakazuo
Copy link
Owner

I believe that's what Raphael's original code did on the AVR MCUs, but the problem with that is that it doesn't show up as multiple controllers in every OS then. By having independent endpoints, the OS is somewhat forced to see them as multiple controllers.
I suppose I can make an alternate version and implement the original version on CH55x -- it wouldn't be hard to do. I was really hoping to have any OS see each controller independently without the need for driver hacks, like the original 4nes4snes needed in Linux.

@prosper00
Copy link
Author

prosper00 commented Apr 5, 2021

Oh, yeah, i see something about linux needing some sort of 'HID_QUIRK_MULTI_INPUT' hack defined.... Good to know, thanks for the comment

@prosper00
Copy link
Author

prosper00 commented Apr 5, 2021

Still not working for me. Ubuntu 20.10.
With 2 pads connected:
/dev/js0 - reports correctly, UNTIL I open /dev/js1. js1 reports correctly, but js0 now no longer reports anything.

(this happens with your binary, and with one I built myself. Oddly enough, the two binaries are slightly different in size, though that could be just down to compiler versions)

@ishiyakazuo
Copy link
Owner

Yep, that's what was happening to me in Linux Mint 20 (and Windows 10) as well.
With the binary on mine, /dev/js1 works unreliably. I suspect that it's probably sometimes responding with data, and other times not. It could be that the performance is just not really there to handle more than one controller reliably with this approach, and maybe I do need to go to the HID_QUIRK_MULTI_INPUT hack method... that would be very disappointing, as that was one of the main drivers of me porting this code to the CH55x.
I'll plan to write a version that is based on the original 4nes4snes for CH55x some time. I'm not exactly sure when it will happen, but I'm also no USB expert, so it might be more expedient than me trying to debug this problem...

@prosper00
Copy link
Author

I know almost nothing about USB, but I've been doing a bunch of reading. It's why I bought these chips - to play, and to learn.

Though I wouldn't suspect performance limitations. This shouldn't be a very demanding application. I'm wondering if there might be a memory (RAM) issue somewhere. The 8051 has a wacky memory model.

I might take a crack at writing my own 2NES to USB adapter from the ground up... eventually...

@ishiyakazuo
Copy link
Owner

That's certainly an option, and I'd be interested to see the results! You might also want to look at the original 4nes4snes project from Raphnet ( https://github.com/raphnet/4nes4snes ) -- his code does what you described before, as I recall. I spent some time parameterizing the code such that the number of controllers is configurable, since he had a number of hard-coded descriptors, etc., but his code is pretty legible and easy to follow. Mine might be a bit less so, due to the parameterization. I just don't like the idea of copy/paste. (In theory, I suspect mine could support > 4 controllers if I went back to his approach... maybe I'll re-add support for 5, to make a USB version of the SNES multitap using the CH55x.)

@ishiyakazuo
Copy link
Owner

OK, so after some experiments, I've found that you're correct -- it's not a performance issue of the CH55x. It seems to me that something is happening such that it's "forgetting" to send the data back. I set the request interval to every 40ms instead of 2ms, and the same thing happens. I see in Wireshark that the host asks for one controller, and then even 10ms later, it asks for another controller's data, and it only sends the last one requested. So there's something at the logical level that's getting confused here.
I'm thoroughly puzzled as to what's going on here. Staring at my code, I'm not seeing anything that can account for it.

@prosper00
Copy link
Author

probably something subtle like an off-by-one index or something. I'll look through it myself, though, I'm totally new to the CH55x/8051 AND to USB, so, probably won't be of much help :)

@ishiyakazuo
Copy link
Owner

I don't think that accounts for the thing I'm seeing... it seems like the CH55x is just giving up on replying to all but the last request when multiple requests are issued. I'm starting to think it could be a bug in the chip.
Attached is a small segment of packets I captured in Wireshark. There's something really weird here, because you can see that the messages are being sent 32ms apart (this was when I was seeing if it was a performance issue). Packet #5 is where I switched to testing another controller port. At that point, you can see that the host sent a request, saying "send me your data in 32ms" (the "Interval" value tells the USB Device after how long to respond). In this case, the CH551 responded 22ms later from that endpoint, but 32ms after the request from the OTHER endpoint. So it's like the CH551 remembered that it was supposed to respond in 32ms, but lost track of which endpoint it was supposed to respond from!
WiresharkSnippet
If I hadn't seen the device actually kinda sorta work the other day on multiple ports at once (which could be a fluke that is host timing dependent), I'd probably be ready to throw my hands up and give up right now, but this is the sort of goofy thing that intrigues me. I'm wondering if anyone else has managed to get this to operate properly... I'm going to have to start hunting for a CH55x expert.

@ishiyakazuo
Copy link
Owner

OK, so I went back and reviewed Raph's original code, and noticed that his code did some things to arbitrate the USB messages coming in. I tried to do that, with varying success. I checked in some code, which isn't perfect, but does seem to work OK with 2 controllers, as long as both controllers are enabled by the application. Until then, neither works properly. There's something with the signaling that comes from the host that I need to figure out how to properly support to not want to provide responses for deactivated controllers, because then the MCU gets hung up waiting for that one to be read from the host. In any case, you can give this one a spin and see what you think -- I checked in the code for it. I do intend to try and figure out this last piece, though, so don't close this ticket yet...

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

No branches or pull requests

2 participants