Forum: Mikrocontroller und Digitale Elektronik Mit dem Pi Pico ein Adapter von Db9 auf USB bauen


von Dany T. (projekt-hirnfrei)


Lesenswert?

Mahlzeit!

Um alte Joysticks vom C-64 oder Amiga auch am PC betreiben zu können 
baue ich mir gerade einen Adapter. Das funktioniert auch prinzipiell 
schon überraschend gut.

Es gibt jedoch ein paar Feinheiten, welche ich gerne noch ändern würde.

So verwende ich die "Adafruit TinyUSB" Library und arbeite in der 
ArduinoIDE mit C++. Wenn ich jetzt folgendes als Beschreibung für HID 
verwende funktioniert alles super:
1
uint8_t const desc_hid_report[] = 
2
{
3
  TUD_HID_REPORT_DESC_GAMEPAD()
4
};

Dann hat der Adapter aber angeblich 8 Achsen und 32 Buttons. Achse 0 und 
1 sowie Button 0 funktionieren und ich kann auch im Emulator problemlos 
damit spielen.

Ich würde aber gerne angeben, dass es 2 Achsen mit 1 Button sind. Dazu 
habe ich folgendes gebastelt:
1
uint8_t const desc_hid_report[] =
2
{
3
    0x05, 0x01,          // Usage Page (Generic Desktop)
4
    0x09, 0x05,          // Usage (Game Pad)
5
    0xA1, 0x01,          // Collection (Application)
6
7
    // X und Y Achsen
8
    0x09, 0x30,          // Usage (X)
9
    0x09, 0x31,          // Usage (Y)
10
    0x15, 0x81,          // Logical Minimum (-127)
11
    0x25, 0x7F,          // Logical Maximum (127)
12
    0x75, 0x08,          // Report Size (8)
13
    0x95, 0x02,          // Report Count (2)
14
    0x81, 0x02,          // Input (Data,Var,Abs)
15
16
    // Buttons (nur 1 Button)
17
    0x05, 0x09,          // Usage Page (Button)
18
    0x19, 0x01,          // Usage Minimum (Button 1)
19
    0x29, 0x01,          // Usage Maximum (Button 1)
20
    0x15, 0x00,          // Logical Minimum (0)
21
    0x25, 0x01,          // Logical Maximum (1)
22
    0x75, 0x01,          // Report Size (1)
23
    0x95, 0x01,          // Report Count (1)
24
    0x81, 0x02,          // Input (Data,Var,Abs)
25
26
    // Padding auf Bytegröße
27
    0x75, 0x07,          // Report Size (7)
28
    0x95, 0x01,          // Report Count (1)
29
    0x81, 0x03,          // Input (Const,Var,Abs)
30
31
    0xC0                 // End Collection
32
};

Dann bekomme ich auch 2 Achsen und 1 Button angezeigt. Allerdings 
funktionieren die dann nicht mehr. Ändere ich es wieder funktioniert es 
sofort. Also an der Verkabelung kann es nicht liegen.

Das wäre der eine Punkt. Der Andere wäre dann noch, derzeit wird der 
Adapter vom PC als "Raspberry Pi Pico" erkannt. Ist kein Beinbruch aber 
der kleine Monk in mir würde da gerne etwas individuelles angezeigt 
sehen. Nur scheint mir, dass die Bibliothek das nicht zulässt. Mein 
Versuch die Funktion zu überschreiben schlug leider fehl.

Hier kommt dann der ganze Code, falls ich sonst wo einen Fehler gemacht 
habe.
1
#include <Adafruit_TinyUSB.h>
2
3
int up = 10;
4
int down = 11;
5
int left = 12;
6
int right = 13;
7
int button = 14;
8
9
uint8_t const desc_hid_report[] =
10
{
11
    0x05, 0x01,          // Usage Page (Generic Desktop)
12
    0x09, 0x05,          // Usage (Game Pad)
13
    0xA1, 0x01,          // Collection (Application)
14
15
    // X und Y Achsen
16
    0x09, 0x30,          // Usage (X)
17
    0x09, 0x31,          // Usage (Y)
18
    0x15, 0x81,          // Logical Minimum (-127)
19
    0x25, 0x7F,          // Logical Maximum (127)
20
    0x75, 0x08,          // Report Size (8)
21
    0x95, 0x02,          // Report Count (2)
22
    0x81, 0x02,          // Input (Data,Var,Abs)
23
24
    // Buttons (nur 1 Button)
25
    0x05, 0x09,          // Usage Page (Button)
26
    0x19, 0x01,          // Usage Minimum (Button 1)
27
    0x29, 0x01,          // Usage Maximum (Button 1)
28
    0x15, 0x00,          // Logical Minimum (0)
29
    0x25, 0x01,          // Logical Maximum (1)
30
    0x75, 0x01,          // Report Size (1)
31
    0x95, 0x01,          // Report Count (1)
32
    0x81, 0x02,          // Input (Data,Var,Abs)
33
34
    // Padding auf Bytegröße
35
    0x75, 0x07,          // Report Size (7)
36
    0x95, 0x01,          // Report Count (1)
37
    0x81, 0x03,          // Input (Const,Var,Abs)
38
39
    0xC0                 // End Collection
40
};
41
42
Adafruit_USBD_HID usb_hid;
43
44
hid_gamepad_report_t gp;
45
46
void setup() 
47
{
48
  if(!TinyUSBDevice.isInitialized()) TinyUSBDevice.begin(0);
49
  
50
  usb_hid.setPollInterval(2);
51
  usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
52
  usb_hid.begin();
53
54
  pinMode(up, INPUT_PULLUP);
55
  pinMode(down, INPUT_PULLUP);
56
  pinMode(left, INPUT_PULLUP);
57
  pinMode(right, INPUT_PULLUP);
58
  pinMode(button, INPUT_PULLUP);
59
}
60
61
void loop() 
62
{
63
  if(!TinyUSBDevice.mounted()) 
64
  {
65
    return;
66
  }
67
68
  gp.x = 0;
69
  gp.y = 0;
70
  gp.buttons = 0;
71
  if(digitalRead(up) == LOW) gp.y = -127;
72
  if(digitalRead(down) == LOW) gp.y = 127;
73
  if(digitalRead(left) == LOW) gp.x = -127;
74
  if(digitalRead(right) == LOW) gp.x = 127;
75
  if(digitalRead(button) == LOW) gp.buttons = (1U << 0);
76
77
  usb_hid.sendReport(0, &gp, sizeof(gp));
78
79
  delay(10);
80
}

von Norbert (der_norbert)


Lesenswert?

Dany T. schrieb:
> hid_gamepad_report_t gp;

Passt die Struktur denn zu deinem veränderten ›desc_hid_report‹?

Die sollte nun nur noch drei Bytes haben, zweimal int8_t und einmal 
uint8_t.
Und von dem Letzten wird nur ein Bit verwendet.

: Bearbeitet durch User
von Dany T. (projekt-hirnfrei)


Lesenswert?

Norbert schrieb:
> Passt die Struktur denn zu deinem veränderten ›desc_hid_report‹?

Die hat natürlich nicht gestimmt. Vielen Dank für den Hinweis, jetzt 
funktioniert es! 2 Achsen und 1 Button und die werden auch einwandfrei 
gelesen.

von Crazy Harry (crazy_h)


Lesenswert?

Früher mal gab es bei PCs einen Joystickanschluss bzw. zwei (SubD15) und 
daran konnte man je einen analogen Joystick mit 2 Achsen und 2 Tasten 
anschliessen. Willst du an so einen Anschluss einen digitalen Joysteick 
anschliessen?

von Harald K. (kirnbichler)


Lesenswert?

Nee, der hat sich einen Adapter von Digital-Joystick auf USB-HID 
gebastelt. Das ist die für derartige Dinge zuständige USB-Geräteklasse.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.