-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.c
189 lines (146 loc) · 5.25 KB
/
main.c
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/multicore.h"
#include "pico/bootrom.h"
#include "pio_usb.h"
#include "tusb.h"
#include "bsp/board.h"
#include "hardware/uart.h"
#define UART_ID uart0
#define BAUD_RATE 9600
#define UART_TX_PIN 0
#define UART_RX_PIN 1
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
static void process_kbd_report(hid_keyboard_report_t const *report);
// core1: handle host events
void core1_main() {
sleep_ms(10);
// Use tuh_configure() to pass pio configuration to the host stack
// Note: tuh_configure() must be called before tuh_init()
// tuh_configure(rhport, 1 = Pico_PIO, 0 = rp2040 hw/native; config type; config)
pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG;
pio_cfg.pin_dp = 4; // DM = DP+1 (DP = D+ / DM = D-)
tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg);
// To run USB SOF interrupt in core1, init host stack for
// pio_usb (roothub port1) on core1
tuh_init(1);
while (true) {
tuh_task(); // tinyusb host task
}
}
// core0: handle device events
int main(void) {
board_init();
// default 125MHz is not appropreate. Sysclock should be multiple of 12MHz.
set_sys_clock_khz(120000, true);
// init serial
uart_init(UART_ID, BAUD_RATE);
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
sleep_ms(10);
multicore_reset_core1();
// all USB task run in core1
multicore_launch_core1(core1_main);
// turn on onboard led
board_led_write(true);
while (true) {
stdio_flush();
sleep_us(10);
}
return 0;
}
//--------------------------------------------------------------------+
// TinyUSB Callbacks
//--------------------------------------------------------------------+
// called after all tuh_hid_mount_cb
void tuh_mount_cb(uint8_t dev_addr)
{
// application set-up
printf("A device with address %d is mounted\r\n", dev_addr);
}
// called before all tuh_hid_unmount_cb
void tuh_umount_cb(uint8_t dev_addr)
{
// application tear-down
printf("A device with address %d is unmounted \r\n", dev_addr);
}
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) {
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
(void)desc_report;
(void)desc_len;
if(tuh_hid_interface_protocol(dev_addr, instance) == HID_ITF_PROTOCOL_KEYBOARD) {
if ( !tuh_hid_receive_report(dev_addr, instance) )
{
printf("Error: cannot request to receive report\r\n");
}
}
}
// Invoked when device with hid interface is un-mounted
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
// Invoked when received report from device via interrupt endpoint
// called on key press and key release
void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
{
printf("received report from HID device address = %d, instance = %d\r\n", dev_addr, instance);
(void) len;
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
switch (itf_protocol)
{
case HID_ITF_PROTOCOL_KEYBOARD:
printf("HID receive boot keyboard report\r\n");
process_kbd_report( (hid_keyboard_report_t const*) report );
break;
}
// continue to request to receive report
if ( !tuh_hid_receive_report(dev_addr, instance) )
{
printf("Error: cannot request to receive report\r\n");
}
}
//--------------------------------------------------------------------+
// Keyboard
//--------------------------------------------------------------------+
// look up new key in previous keys
static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode)
{
for(uint8_t i=0; i<6; i++)
{
if (report->keycode[i] == keycode) return true;
}
return false;
}
static void process_kbd_report(hid_keyboard_report_t const *report)
{
static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released
//------------- example code ignore control (non-printable) key affects -------------//
for(uint8_t i=0; i<6; i++)
{
if ( report->keycode[i] )
{
if ( find_key_in_report(&prev_report, report->keycode[i]) )
{
// exist in previous report means the current key is holding
}else
{
// not existed in previous report means the current key is pressed
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
putchar(ch);
putchar('\n');
if ( ch == '\r' ) putchar('\n'); // added new line for enter key
fflush(stdout); // flush right away, else nanolib will wait for newline
}
}
// TODO example skips key released
}
prev_report = *report;
}