Parallax Propeller2 USB driver - the MashUp

Getting started: keyboard & mouse
Login

Getting started: keyboard & mouse

Status: validated live (Unifying receiver, composite keyboard+mouse, including across hot detach/re-attach).

What you need

pnut-ts -d -I <path-to>/src -D USB_HID my_kbd.spin2

The smallest program

#IFDEF USB_HID
#PRAGMA EXPORTDEF USB_HID
#ENDIF

CON
  _clkfreq = 200_000_000

OBJ
  usb : "usb_app"

PUB main() | c
  usb.begin(16)
  if usb.await_kbd(5000)                    ' blocks up to 5 s, scanning -
    debug("keyboard ready")                 ' late attachers still arrive

  repeat
    if usb.kbd_poll()                       ' ~1 ms; false = no new report
      c := usb.kbd_char()                   ' best-effort ASCII (mods applied)
      if c
        debug(zstr_(@c))
    if usb.mouse_ready()
      if usb.mouse_poll()
        debug("mouse dx=", sdec_(usb.mouse_dx()), " dy=", sdec_(usb.mouse_dy()), " b=", ubin_(usb.mouse_buttons()))
    usb.poll()                              ' hot-plug: unplug/replug just works
    waitms(8)

What bring-up actually does

  1. usb.begin(16) enumerates the bus and binds keyboard and mouse by interface boot protocol — a composite receiver's keyboard interface (protocol 1) and mouse interface (protocol 2) get their own endpoints, so both work at once.
  2. Each bound interface is switched to boot protocol: a fixed report layout (8-byte keyboard, 3+ byte mouse) that every keyboard and mouse supports — no descriptor parsing needed on this plane.
  3. kbd_poll() / mouse_poll() each fetch one interrupt-IN report, poll-once (~1 ms idle cost, NAK just means "no change").
  4. Raw access when you want it: kbd_mods() (modifier bits) and kbd_key(i) (up to 6 HID usage codes) under the ASCII convenience of kbd_char().

Troubleshooting

Symptom Likely cause
Keyboard never binds It may be low-speed — behind a hub the log says leaf is LOW-SPEED ... ticket 1210 and the HID example prints a RESULT1 confirmation; direct-attached it looks like a dead bus (1190). Use a full-speed keyboard (receiver / gaming keyboard); check the roster with dev_count()/dev_vid().
Keys repeat oddly / missed Poll at least every ~16 ms; set_int_interval() can pace polling against SOF frames if you poll faster.
Gamepad grabbed as keyboard Build with -D USB_JOY too — pads are recognized by descriptor and routed to joy_* (joystick guide).
Unifying receiver binds but keys are wrong / missing The receiver lists a report-only (protocol 0) DJ iface first, then boot kbd (1) and mouse (2). The host keeps four HID ifaces and binds only protocol 1 as the keyboard. Protocol 0 is never a boot keyboard — polling it delivers the real key plus a second HID++/consumer report (field: s then 9).

Next