PicoMiteVGAUSB: What gamepads are supported ?


Author Message
thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4200
Posted: 10:02am 05 Feb 2025      

  Mixtel90 said  Looks up the Buffalo pad on Amazon:

"Currently unavailable.
We don't know when or if this item will be back in stock."


It doesn't really matter, https://github.com/mdqinc/SDL_GameControllerDB/blob/master/gamecontrollerdb.txt contains SDL2 mappings for over 800 controllers ... there is no generic controller (my bad) ... for this to work either PicoMiteUSB has to have a similar mapping system or we are back to custom built controllers (great hobby project, lousy ergonomics) or someone has to buy a lot of the same controller, persuade Peter to support it and then re-sell it as the "standard" controller.

Best wishes,

Tom

javavi

Guru

Joined: 01/10/2023
Location: Ukraine
Posts: 402
Posted: 11:22am 05 Feb 2025      

Perhaps this library can help in this case with USB joysticks.

pico-hid-host

Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7341
Posted: 11:25am 05 Feb 2025      

The ergonomics don't have to be completely lousy. It depends on getting enough buttons/pads/whatever 3d printed or injection moulded. A reasonably acceptable "enclosure" for the hobbyist (not the serious gamer) can be two pieces of plastic/PCB with spacers and the control PCB sandwiched between them (or something along those lines). The thing is, you can't use an enclosure from even look-alike controllers as they differ internally and the cost of having "proper" enclosures made is prohibitive.

The actual controller electronics can be whatever we like. We control that. That's the (relatively) easy bit. :)  Just find a way to use the USB port on a RP2040-Zero to send data to the USB input on a bigger box. I've sent codes representing key presses using Circuit Python so something must be possible. In that case it just appears as a keyboard device. I would suggest that this *is* a generic controller. :) It sends W,A,S,D,Q,E etc. and can be programmable to work on any nationality of keyboard layout.

aFox
Regular Member

Joined: 28/02/2023
Location: Germany
Posts: 99
Posted: 01:13am 06 Feb 2025      

Hi

You can get a button reference by OliBasic.

Manual RFO-Basic 1.91:
https://gitlab.com/OliBasic/Main/-/blob/master/OliBasicXXIV/Documentation/RFO-Basic%20Manual%201.91%20De_Re_BASIC!.pdf

Fork of RFO-Basic 1.91 with a lot of enhancements, OliBasic 3.00+:
OliBasic

Inkey$ <svar>{{, <rawKeyEvent_svar>}, <utf-8_svar>}

Reports key taps for the a-z, 0-9, Space and the D-Pad keys. The key value is returned in <svar>.
The D-Pad keys are reported as "up", "down", "left", "right" and "go". If any key other than those have been tapped, the string "key nn" will be returned. Where nn will be the Android key code for that key.
If no key has been tapped, the "@" character is returned in <svar>.
Keep in mind, that soft keyboards send a limited character set. Characters like "°♤♡◇♧《》¡¿äöü" are only supported by USB or Bluetooth keyboards or other input devices like game pads in the case of this function.
Rapid key taps are buffered in case they come faster than the BASIC! program can process.
By rawKeyEvent you get an optional raw key event description with action, keyCode, scanCode, metaState, flags, repeatCount, eventTime, downTime, deviceId and source values.
As an option you get with <utf-8_svar> the UTF-8 character back.
If you want correct results use ONKEY…: interrupt handling instead a DO – UNTIL loop.
But do not use the command PAUSE if have a lot keystrokes in conjunction with key event handling.
Example

KEYDOWN.ON % The opposite is KEYDOWN.OFF
DO
UNTIL 0

ONKEYDOWN: %A Key Is Down interrupt
! The second string, raw key event parameter
INKEY$ mKey$, mKeyEvent$, mUniKeyEvent$
PRINT "Got "; mKey$, "  "; mKeyEvent$, mUniKeyEvent$
KEYDOWN.RESUME %Resumes execution at the point BASIC! program where
! the OnKeyDown: interrupt occured.

ONKEYPRESS: %Imo ONKEYUP points the fact better
INKEY$ mKey$, mKeyEvent$, mUniKeyEvent$
PRINT "Got "; mKey$, "  "; mKeyEvent$, mUniKeyEvent$
KEY.RESUME



Maybe you are also interested in:

Device.USB <bundlePointer_nvar>
Returns the parameters of plugged in USB devices.
Following keys are supported  "_DeviceId", "_VendorId", "_ProductId",  "_DeviceClass", "_InterfaceClass0", "_DeviceSubclassId", "_DeviceName", "_SerialNumber", "_ManufacturerName", "_ProductName", "_UsbInterface", "_Driver" and "_AllAsString".
The keys "_SerialNumber", "_ManufacturerName" and "_ProductName" are available on Android 5+.
Starting on Android 10+ a permission has to be granted for each USB device. Is a dialog canceled or after five seconds not confirmed the property enumeration is skipped.
Example:

DEVICE.USB bp
BUNDLE.KEYS bp, lp
LIST.SIZE lp, n
FOR i = 1 TO n
  BUNDLE.GB bp, int$(i), pUSB
  BUNDLE.GET pUSB, "_AllAsString", aAS$
  PRINT aAS$
NEXT

See also USB command group

Try to plug in your Pico boards or other µC boards and compare.

Android on Raspberry Pi

Gregor
Edited 2025-02-06 11:40 by aFox

thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4200
Posted: 10:46am 12 Feb 2025      

Hi Peter,

Thanks for the updated firmware:

Here is the output from my "iBuffalo SNES Controller":
USB channel: 3
VID        : 0x0583
PID        : 0x2060
None       : (8  bytes) 81 81 00 00 00 00 00 00
Up         : (8  bytes) 81 00 00 00 00 00 00 00
Down       : (8  bytes) 81 FF 00 00 00 00 00 00
Left       : (8  bytes) 00 81 00 00 00 00 00 00
Right      : (8  bytes) FF 81 00 00 00 00 00 00
A          : (8  bytes) 81 81 01 00 00 00 00 00
B          : (8  bytes) 81 81 02 00 00 00 00 00
X          : (8  bytes) 80 81 04 00 00 00 00 00
Y          : (8  bytes) 81 81 08 00 00 00 00 00
L1         : (8  bytes) 81 81 10 00 00 00 00 00
R1         : (8  bytes) 81 81 20 00 00 00 00 00


Here is the output from my PiHut branded "Retro Controller":
USB channel: 3
VID        : 0x0079
PID        : 0x0011
None       : (8  bytes) 01 7F 7F 7F 7F 0F 00 00
Up         : (8  bytes) 01 7F 7F 7F 00 0F 00 00
Down       : (8  bytes) 01 7F 7F 7F FF 0F 00 00
Left       : (8  bytes) 01 7F 7F 00 7F 0F 00 00
Right      : (8  bytes) 01 7F 7F FF 00 0F 00 00
A          : (8  bytes) 01 7F 7F 7F 7F 2F 00 00
B          : (8  bytes) 01 7F 7F 7F 7F 4F 00 00
X          : (8  bytes) 01 7F 7F 7F 7F 1F 00 00
Y          : (8  bytes) 01 7F 7F 7F 7F 8F 00 00
L1         : (8  bytes) 01 7F 7F 7F 7F 0F 01 00
R1         : (8  bytes) 01 7F 7F 7F 7F 0F 02 00


And here is the over-engineered program that generated the output:
' Copyright (c) 2025 Thomas Hugo Williams
' License MIT <https://opensource.org/licenses/MIT>
' For PicoMiteUSB variants

Option Base 0
Option Default None
Option Explicit On

Const BUTTONS = "None Up Down Left Right A B X Y L1 R1"
Dim channel% = 0, filename$ = "", test% = 0

process_args()

Open filename$ For Output As #1

If test% Then write("** TEST DATA **", 1)
write("USB channel: " + Str$(channel%), 1)
write("Out file   : " + filename$, 0)
write("VID        : " + read_usb_vid$(), 1)
write("PID        : " + read_usb_pid$(), 1)
write("", 0)

Dim b$, i% = 1
Do
 b$ = Field$(BUTTONS, i%, " ")
 If b$ = "" Then Exit Do
 Do While Inkey$ <> "" : Loop
 If b$ = "None" Then
   write("Hold down NO BUTTONS then press a key", 0)
 Else
   write("Hold down [" + b$ + "] then press a key", 0)
 EndIf
 Do While Inkey$ = "" : Loop
 write(str.rpad$(b$, 11) + ": " + read_usb_raw_data$(), 1)
 Inc i%
Loop

Close #1
End

Sub process_args()
 Local arg$, i% = 1
 Do
   arg$ = Field$(Mm.CmdLine$, i%, " ")
   If arg$ = "" Then
     Exit Do
   ElseIf InStr(arg$, "-f=") = 1 Then
     filename$ = Mid$(arg$, Len("-f=") + 1)
   ElseIf InStr(arg$, "--file=") = 1 Then
     filename$ = Mid$(arg$, Len("--file=") + 1)
   ElseIf InStr(arg$, "-c=") = 1 Then
     channel% = Val(Mid$(arg$, Len("-c=") + 1))
     If Not channel% Then Error "Invalid channel: " + arg$
   ElseIf InStr(arg$, "--channel=") = 1 Then
     channel% = Val(Mid$(arg$, Len("--channel=") + 1))
     If Not channel% Then Error "Invalid channel: " + arg$
   ElseIf arg$ = "-t" Or arg$ = "--test" Then
     test% = 1
   Else
     Error "Unknown command line argument: " + arg$
   EndIf
   Inc i%
 Loop

 If channel% = 0 Then
   Do
     Line Input "Channel (1-4) ? ", arg$
     channel% = Val(arg$)
     If channel% > 0 And channel% < 5 Then  Exit Do
   Loop
 EndIf

 If filename$ = "" Then
   Line Input "Filename 'usb-query.out' ? ", filename$
   If filename$ = "" Then filename$ = "usb-query.out"
 EndIf
End Sub

Function read_usb_vid$()
 Const vid% = Choice(test%, Int(Rnd() * &hFFFF), Mm.Info(Usb Vid channel%))
 read_usb_vid$ = "0x" + Hex$(vid%, 4)
End Function

Function read_usb_pid$()
 Const pid% = Choice(test%, Int(Rnd() * &hFFFF), Mm.Info(Usb Pid channel%))
 read_usb_pid$ = "0x" + Hex$(pid%, 4)
End Function

Function read_usb_raw_data$()
 Local raw$, i%
 If test% Then
   For i% = 1 To Int(Rnd() * 16)
     Cat raw$, Chr$(Int(Rnd() * 256))
   Next
 Else
   raw$ = Device(Gamepad channel%, Raw)
 EndIf
 read_usb_raw_data$ = "(" + str.rpad$(Str$(Len(raw$)), 2) + " bytes)"
 For i% = 1 To Len(raw$)
   Cat read_usb_raw_data$, " " + Hex$(Asc(Mid$(raw$, i%, 1)), 2)
 Next
End Function

Sub write(s$, to_file%)
 Print s$
 If to_file% Then Print #1, s$
End Sub

Function str.rpad$(s$, x%)
 str.rpad$ = s$
 If Len(s$) < x% Then str.rpad$ = s$ + Space$(x% - Len(s$))
End Function


Best wishes,

Tom
Edited 2025-02-12 20:48 by thwill

matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9805
Posted: 11:39am 12 Feb 2025      

What about the other buttons? select/start/clear/turbo on the ibuff
select/start on the PiHut?

thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4200
Posted: 11:43am 12 Feb 2025      

  matherp said  What about the other buttons? select/start/clear/turbo on the ibuff
select/start on the PiHut?


I'm an idiot aren't I ... sorry, will be tomorrow - D'Oh!

Tom

matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9805
Posted: 07:10pm 12 Feb 2025      

Tom

If you are willing please modify your program to produce the following output - properly filled in. I'll modify my code to interpret it.

  Quote   {.vid=0x79, .pid=0x11,
.b_R={0,0}, .b_START={0,0}, .b_HOME={0,0}, .b_SELECT={0,0}, .b_L={0,0},
.b_DOWN={0,0}, .b_RIGHT={0,0}, .b_UP={0,0}, .b_LEFT={0,0},
.b_R2={0,0}, .b_X={0,0}, .b_A={0,0}, .b_Y={0,0}, .b_B={0,0},
.b_L2={0,0}, .b_TOUCH={0,0}
},


This will be used as an initialiser line for a constant array of the following structure. Then we can ask everyone with any sort of gamepad to run your program and I can add the support with a trivial edit

struct s_Buttons {
int8_t index; // which report element relates to this bit set to -1 if bit not used
// code can be a bit number 0-7 for positive if pressed
// 128-135 for negative if pressed
// 64 for value less than 64 if pressed
// 192 for value greater than 192 if pressed
uint8_t code ;
};
struct s_Gamepad {
uint8_t vid;
uint8_t pid;
struct s_Buttons b_R;
struct s_Buttons b_START;
struct s_Buttons b_HOME;
struct s_Buttons b_SELECT;
struct s_Buttons b_L;
struct s_Buttons b_DOWN;
struct s_Buttons b_RIGHT;
struct s_Buttons b_UP;
struct s_Buttons b_LEFT;
struct s_Buttons b_R2;
struct s_Buttons b_X;
struct s_Buttons b_A;
struct s_Buttons b_Y;
struct s_Buttons b_B;
struct s_Buttons b_L2;
struct s_Buttons b_TOUCH;
};

Edited 2025-02-13 05:13 by matherp

thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4200
Posted: 09:46am 13 Feb 2025      

  matherp said  Tom

If you are willing please modify your program to produce the following output - properly filled in. I'll modify my code to interpret it.


Hi Peter, yes I can make that modification, though it's too involved to sneak into my work day at the moment so it may well not be until Sunday.

Note that I'm fairly certain VID and PID are 16-bit, not 8-bit.

Whilst building some support for "common" gamepads (though I'm not sure which ones those are) into the firmware makes sense, there are 100s of the bl**dy things. Perhaps you should consider adding the ability for the firmware to read user-supplied definitions from A:/.gamepad or something similar ?

Best wishes,

Tom

PhenixRising
Guru

Joined: 07/11/2023
Location: United Kingdom
Posts: 1092
Posted: 09:57am 13 Feb 2025      

  thwill said  there are 100s of the bl**dy things.


Seems like justification to borrow an idea and have a reliable source?

matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9805
Posted: 10:23am 13 Feb 2025      

  Quote  so it may well not be until Sunday.

No problem. I can't test my code until I get home Tuesday as I haven't got any sort of gamepad to test against here.

  Quote  Note that I'm fairly certain VID and PID are 16-bit, not 8-bit.

Yes: corrected structures

  Quote  struct s_Buttons {
uint8_t index; // which report element relates to this bit set to 0xFF if bit not used
// code can be a bit number 0-7 for positive if pressed
// 128-135 for negative if pressed
// 64 for value less than 64 if pressed
// 192 for value greater than 192 if pressed
uint8_t code ;
};
struct s_Gamepad {
uint16_t vid;
uint16_t pid;
struct s_Buttons b_R;
struct s_Buttons b_START;
struct s_Buttons b_HOME;
struct s_Buttons b_SELECT;
struct s_Buttons b_L;
struct s_Buttons b_DOWN;
struct s_Buttons b_RIGHT;
struct s_Buttons b_UP;
struct s_Buttons b_LEFT;
struct s_Buttons b_R2;
struct s_Buttons b_X;
struct s_Buttons b_A;
struct s_Buttons b_Y;
struct s_Buttons b_B;
struct s_Buttons b_L2;
struct s_Buttons b_TOUCH;
};

Edited 2025-02-13 20:24 by matherp

Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 7341
Posted: 10:45am 13 Feb 2025      

lol
  Quote  there are 100s of the bl**dy things.


Exactly my reasoning for having a controller of our own.  :)

There will *never* be a reliable source for these as long as manufacturers are responsible for producing both the consoles and the controllers. They will always introduce something else and, if you are really, really lucky, keep some compatibility with some of their older products. Not too old as that would dissuade people from buying new controllers for their old consoles. Those will be quietly dropped without telling anyone. The first anyone will know is when they buy a new controller and it won't work. Any list of codes will be out of date as soon as a new controller (even third party ones) comes out. Call me cynical if you like, but that's business.

thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4200
Posted: 10:55am 13 Feb 2025      

I think Peter is on the correct track, a software facade can be implemented with a number of gamepad mappings hard-coded and (if he accepts my suggestion) an extension mechanism so others can be provided by the user. It's how Linux and Windows handle it.

YMMV,

Tom

thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4200
Posted: 01:31pm 16 Feb 2025      

Peter,

What should happen when a byte transitions from 0x7F => 0xFF ? Presumably that's treated as a single bit being set and you want a 7 ?

But if a byte transitions from 0x7F => 0x00 then that should return a 64 ?

I ask because this is what down & up do on my PiHut controller and I suspect those are meant to be treated as 8 bit values, 255 (down), 127 (none), 0 (up).

EDIT: I suppose given knowledge of the transitions for up and down I can make an educated guess, i.e. if either transition changes more than one bit then I should be returning 64 or 192 ?

Tom
Edited 2025-02-16 23:33 by thwill

matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9805
Posted: 05:13pm 16 Feb 2025      

For buttons with an index value normally around 0x80, if greater than 192 return 192 if less than 64 return 64.

thwill

Guru

Joined: 16/09/2019
Location: United Kingdom
Posts: 4200
Posted: 10:46am 17 Feb 2025      

Thanks Peter, I didn't quite make it this weekend and I'm travelling without toys this week. Please leave it with me and I should get it done next weekend.

Best wishes,

Tom