Skip to content

Commit dfad154

Browse files
Merge pull request sekigon-gonnoc#120 from sekigon-gonnoc/single-pio
Run on 1 PIO
2 parents 0f747aa + d1f050a commit dfad154

File tree

14 files changed

+682
-469
lines changed

14 files changed

+682
-469
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ Another sample program for split keyboard with QMK
3939

4040
## Resource Usage
4141

42-
- Two PIO
43-
- One PIO is for USB transmitter using 22 instruction and one state machine
44-
- Another PIO is for USB receiver using 31 instruction and two state machine
42+
43+
- 1 PIO, 3 state machines, 32 instructions
4544
- Two GPIO for D+/D- (Series 22ohm resitors are better)
4645
- 15KB ROM and RAM
4746
- (For Host) One 1ms repeating timer

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ add_subdirectory(${PICO_PIO_USB_DIR} pico_pio_usb)
1414
add_subdirectory(capture_hid_report)
1515
add_subdirectory(usb_device)
1616
add_subdirectory(host_hid_to_device_cdc)
17+
add_subdirectory(test_ll)

examples/test_ll/CMakeLists.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
set(target_name test_ll)
2+
add_executable(${target_name})
3+
4+
pico_enable_stdio_usb(${target_name} 1)
5+
6+
target_sources(${target_name} PRIVATE
7+
test_ll.c
8+
)
9+
10+
# print memory usage, enable all warnings
11+
target_link_options(${target_name} PRIVATE -Xlinker --print-memory-usage)
12+
target_compile_options(${target_name} PRIVATE -Wall -Wextra)
13+
14+
target_link_libraries(${target_name} PRIVATE pico_stdlib pico_multicore pico_pio_usb)
15+
pico_add_extra_outputs(${target_name})

examples/test_ll/test_ll.c

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
2+
#include <stdio.h>
3+
#include <string.h>
4+
#include <strings.h>
5+
6+
#include "hardware/gpio.h"
7+
#include "hardware/sync.h"
8+
#include "pico/stdlib.h"
9+
#include "pico/time.h"
10+
#include "pico/bootrom.h"
11+
#include "pico/types.h"
12+
#include "pio_usb.h"
13+
#include "pio_usb_configuration.h"
14+
#include "pio_usb_ll.h"
15+
#include "usb_definitions.h"
16+
#include "usb_rx.pio.h"
17+
18+
pio_usb_configuration_t pio_usb_config = PIO_USB_DEFAULT_CONFIG;
19+
20+
static bool do_test(pio_port_t *pp);
21+
22+
int main() {
23+
// default 125MHz is not appropreate. Sysclock should be multiple of 12MHz.
24+
set_sys_clock_khz(120000, true);
25+
26+
stdio_init_all();
27+
28+
sleep_ms(1000);
29+
30+
printf("start\n");
31+
32+
pio_usb_config.alarm_pool = NULL;
33+
pio_usb_config.skip_alarm_pool = true;
34+
pio_usb_config.pin_dp = 0;
35+
pio_usb_host_init(&pio_usb_config);
36+
if (pio_usb_host_add_port(4, PIO_USB_PINOUT_DMDP) != 0) {
37+
printf("Failed to add root port\n");
38+
}
39+
pio_port_t *pp = PIO_USB_PIO_PORT(0);
40+
41+
while (1) {
42+
printf("\n[b]: Jump to bootloader, [others]: Execute tests\n");
43+
char c=0;
44+
scanf("%c", &c);
45+
46+
if (c == 'b') {
47+
reset_usb_boot(1 << PICO_DEFAULT_LED_PIN, 0);
48+
}
49+
50+
{
51+
printf("\nTest1: FS, 1\n");
52+
53+
root_port_t *root = PIO_USB_ROOT_PORT(0);
54+
gpio_pull_up(root->pin_dp);
55+
gpio_pull_down(root->pin_dm);
56+
root->is_fullspeed = true;
57+
root->initialized = true;
58+
root->connected = true;
59+
root->suspended = false;
60+
61+
uint32_t irq = save_and_disable_interrupts();
62+
pio_usb_host_frame();
63+
restore_interrupts(irq);
64+
65+
printf("%s\n", do_test(pp) ? "[OK]" : "[NG]");
66+
67+
root->connected = false;
68+
}
69+
70+
{
71+
printf("\nTest2: FS, 2\n");
72+
73+
root_port_t *root = PIO_USB_ROOT_PORT(1);
74+
gpio_pull_up(root->pin_dp);
75+
gpio_pull_down(root->pin_dm);
76+
root->is_fullspeed = true;
77+
root->initialized = true;
78+
root->connected = true;
79+
root->suspended = false;
80+
81+
uint32_t irq = save_and_disable_interrupts();
82+
pio_usb_host_frame();
83+
restore_interrupts(irq);
84+
85+
printf("%s\n", do_test(pp) ? "[OK]" : "[NG]");
86+
87+
root->connected = false;
88+
}
89+
90+
{
91+
printf("\nTest3: LS, 1\n");
92+
93+
root_port_t *root = PIO_USB_ROOT_PORT(0);
94+
gpio_pull_down(root->pin_dp);
95+
gpio_pull_up(root->pin_dm);
96+
root->is_fullspeed = false;
97+
root->initialized = true;
98+
root->connected = true;
99+
root->suspended = false;
100+
101+
uint32_t irq = save_and_disable_interrupts();
102+
pio_usb_host_frame();
103+
restore_interrupts(irq);
104+
105+
printf("%s\n", do_test(pp) ? "[OK]" : "[NG]");
106+
107+
root->connected = false;
108+
}
109+
110+
{
111+
printf("\nTest4: LS, 2\n");
112+
113+
root_port_t *root = PIO_USB_ROOT_PORT(1);
114+
gpio_pull_down(root->pin_dp);
115+
gpio_pull_up(root->pin_dm);
116+
root->is_fullspeed = false;
117+
root->initialized = true;
118+
root->connected = true;
119+
root->suspended = false;
120+
121+
uint32_t irq = save_and_disable_interrupts();
122+
pio_usb_host_frame();
123+
restore_interrupts(irq);
124+
125+
printf("%s\n", do_test(pp) ? "[OK]" : "[NG]");
126+
127+
root->connected = false;
128+
}
129+
130+
{
131+
printf("\nTest 5: Software Encode Speed\n");
132+
uint8_t buffer[64];
133+
uint8_t encoded_data[64 * 2 * 7 / 6 + 2];
134+
for (size_t i = 0; i < sizeof(buffer); i++) {
135+
buffer[i] = i;
136+
}
137+
138+
absolute_time_t start = get_absolute_time();
139+
for (int i = 0; i < 1000; i++) {
140+
pio_usb_ll_encode_tx_data(buffer, sizeof(buffer), encoded_data);
141+
}
142+
absolute_time_t end = get_absolute_time();
143+
int64_t diff = absolute_time_diff_us(start, end);
144+
printf("%f us (64bytes packet)", diff / 1000.0f);
145+
}
146+
}
147+
}
148+
149+
static bool do_test(pio_port_t *pp) {
150+
bool success = true;
151+
152+
// Prepare transfer data
153+
uint8_t test_data[] = {0x80, 0xff, 0x00, 0x83};
154+
endpoint_t *ep = PIO_USB_ENDPOINT(0);
155+
ep->has_transfer = false;
156+
ep->is_tx = true;
157+
ep->size = 32;
158+
pio_usb_ll_transfer_start(ep, test_data, sizeof(test_data));
159+
160+
// Start receiver
161+
pio_usb_bus_prepare_receive(pp);
162+
pio_usb_bus_start_receive(pp);
163+
164+
uint32_t irq = save_and_disable_interrupts();
165+
// Start transmitter
166+
pio_usb_bus_usb_transfer(pp, ep->buffer, ep->encoded_data_len);
167+
restore_interrupts(irq);
168+
169+
// Check received data
170+
uint8_t received[sizeof(test_data) + 4];
171+
memset(received, 0, sizeof(received));
172+
uint8_t received_cnt = 0;
173+
174+
while (pio_sm_get_rx_fifo_level(pp->pio_usb_rx, pp->sm_rx)) {
175+
if (received_cnt >= sizeof(received)) {
176+
printf("\t[NG] Invalid size\n");
177+
success = false;
178+
break;
179+
}
180+
received[received_cnt++] = pio_sm_get(pp->pio_usb_rx, pp->sm_rx) >> 24;
181+
}
182+
183+
for (size_t i = 0; i < sizeof(received); i++) {
184+
printf("%02x ", received[i]);
185+
}
186+
printf("\n");
187+
188+
for (size_t i = 0; i < sizeof(test_data); i++) {
189+
if (test_data[i] != received[i + 2]) {
190+
printf("\t[NG] Invalid data at %d. Expect: %02x, Received: %02x\n", i,
191+
test_data[i], received[i + 2]);
192+
success = false;
193+
}
194+
}
195+
196+
ep->has_transfer = false;
197+
198+
return success;
199+
}

0 commit comments

Comments
 (0)