-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboot.py
More file actions
77 lines (68 loc) · 3.47 KB
/
boot.py
File metadata and controls
77 lines (68 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# boot.py -- run on boot to configure USB and filesystem
# Put app code in main.py
import machine
import pyb
# Resources:
# hid spec (https://www.usb.org/sites/default/files/hid1_11.pdf)
# hid usages and descriptions (https://www.usb.org/sites/default/files/hut1_4.pdf)
#
# The structure goes prefix byte and then value bytes. The prefix is a description of the value bytes not a key like in a map.
# The prefix byte contains 4 bits for the tag, 2 bits for the type and 2 bits for the size, the prefix byte is followed by 0, 1, 2, or 4 value bytes
#
# size: 2 bit expression specifying the size of the value data in bytes
# 00 = 0 bytes
# 01 = 1 bytes
# 10 = 2 bytes
# 11 = 4 bytes (no way to represent 3 bytes)
#
# type: 2 bit expression identifying type of item
# 00 = Main
# 01 = Global
# 10 = Local
# 11 = Reserved
#
# Each type has it's own set of tags which can be found in section 6.2.2 of the hid spec eg. Input(which is a Main item tag) Main with a size of 2:
# 1000 0010 or in hex 0x82
GAMEPAD_REPORT_DESC = bytes([
0x05, 0x01, # Usage Page (Generic Desktop) [Global]
0x09, 0x05, # Usage (Gamepad) [Local]
0xA1, 0x01, # Collection (Application) [Main]
# Joysticks usage page is on generic desktop because the hid usages and descriptions says so Generic Desktop (0x01) has many "Usages" some of which are 0x30, 0x31, etc
0x05, 0x01, # Usage Page (Generic Desktop) [Global]
0x09, 0x30, # Usage (X) [Local]
0x09, 0x31, # Usage (Y) [Local]
0x09, 0x32, # Usage (Z) [Local]
0x09, 0x33, # Usage (Rx) [Local]
0x15, 0x00, # Logical Minimum (0) [Global]
0x26, 0xFF, 0x00, # Logical Maximum (255) [Global]
0x75, 0x08, # Report Size (8) [Global]
0x95, 0x04, # Report Count (4) [Global]
0x81, 0x02, # Input (Data, Variable, Absolute) [Main]
# → 4 axes × 8 bits = 4 bytes
# Buttons get their own dedicated Usage Page (0x09) rather than living under Generic Desktop
0x05, 0x09, # Usage Page (Button) [Global]
0x19, 0x01, # Usage Minimum (1) [Local]
0x29, 0x0C, # Usage Maximum (12) [Local]
0x15, 0x00, # Logical Minimum (0) [Global]
0x25, 0x01, # Logical Maximum (1) [Global]
0x75, 0x01, # Report Size (1) [Global]
0x95, 0x0C, # Report Count (12) [Global]
0x81, 0x02, # Input (Data, Variable, Absolute) [Main]
# → 12 buttons × 1 bit = 12 bits
# Padding because reports must be byte aligned
0x95, 0x01, # Report Count (1) [Global]
0x75, 0x04, # Report Size (4) [Global]
0x81, 0x01, # Input (Constant) [Main]
# → 1 × 4 bits padding (rounds up to full byte)
0xC0 # End Collection [Main]
])
# Configure USB with custom HID gamepad + serial port
pyb.usb_mode('VCP+HID', hid=(
0, # subclass
0, # protocol
64, # max packet length
10, # polling interval in ms
GAMEPAD_REPORT_DESC
))
# Run main.py after boot
pyb.main('main.py')