Skip to content

Commit f4e94b8

Browse files
authored
Merge pull request #25 from nekomona/esb-fifo
Fix data FIFO for esb to hid buffering
2 parents ae3119d + 6ef34f5 commit f4e94b8

File tree

1 file changed

+69
-31
lines changed

1 file changed

+69
-31
lines changed

src/hid.c

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,21 @@ static struct tracker_report {
3434
.data = {0}
3535
};;
3636

37-
uint8_t reports[MAX_TRACKERS * sizeof(report)];
38-
uint8_t report_count = 0;
39-
uint8_t report_sent = 0;
37+
struct tracker_report reports[MAX_TRACKERS];
38+
atomic_t report_write_index = 0;
39+
atomic_t report_read_index = 0;
40+
// read_index == write_index -> empty fifo
41+
// (write_index + 1) % MAX_TRACKERS == read_index -> full fifo
4042

4143
static bool configured;
4244
static const struct device *hdev;
4345
static ATOMIC_DEFINE(hid_ep_in_busy, 1);
4446

4547
#define HID_EP_BUSY_FLAG 0
4648
#define REPORT_PERIOD K_MSEC(1) // streaming reports
49+
#define HID_EP_REPORT_COUNT 4
50+
51+
struct tracker_report ep_report_buffer[HID_EP_REPORT_COUNT];
4752

4853
LOG_MODULE_REGISTER(hid_event, LOG_LEVEL_INF);
4954

@@ -80,30 +85,45 @@ static void send_report(struct k_work *work)
8085
{
8186
if (!usb_enabled) return;
8287
if (!stored_trackers) return;
83-
if (report_count == 0 && k_uptime_get() - 100 < last_registration_sent) return; // send registrations only every 100ms
88+
89+
// Get current FIFO status atomically
90+
size_t write_idx = (size_t)atomic_get(&report_write_index);
91+
size_t read_idx = (size_t)atomic_get(&report_read_index);
92+
93+
if (write_idx == read_idx && k_uptime_get() - 100 < last_registration_sent) {
94+
return; // send registrations only every 100ms
95+
}
96+
8497
int ret, wrote;
8598

8699
last_registration_sent = k_uptime_get();
87100

88101
if (!atomic_test_and_set_bit(hid_ep_in_busy, HID_EP_BUSY_FLAG)) {
89-
// TODO: this really sucks, how can i send as much or as little as i want instead??
90-
// for (int i = report_count; i < 4; i++) memcpy(&reports[sizeof(report) * (report_sent+i)], &reports[sizeof(report) * report_sent], sizeof(report)); // just duplicate first entry a bunch, this will definitely cause problems
91-
// cycle through devices and send associated address for server to register
92-
for (int i = report_count; i < 4; i++) {
93-
packet_device_addr(&reports[sizeof(report) * (report_sent + i)], sent_device_addr);
94-
sent_device_addr++;
95-
sent_device_addr %= stored_trackers;
102+
// Calculate how many reports we have available
103+
int available_reports = write_idx - read_idx;
104+
if (available_reports < 0) available_reports += MAX_TRACKERS;
105+
size_t reports_to_send = (size_t)((available_reports > HID_EP_REPORT_COUNT) ? HID_EP_REPORT_COUNT : available_reports);
106+
107+
int epind;
108+
// Copy existing data to buffer
109+
for (epind = 0; epind < reports_to_send; epind++) {
110+
ep_report_buffer[epind] = reports[read_idx];
111+
epind++;
112+
read_idx++;
113+
if (read_idx == MAX_TRACKERS) read_idx = 0;
114+
atomic_set(&report_read_index, read_idx);
96115
}
97-
// ret = hid_int_ep_write(hdev, &reports, sizeof(report) * report_count, &wrote);
98-
ret = hid_int_ep_write(hdev, &reports[sizeof(report) * report_sent], sizeof(report) * 4, &wrote);
99-
if (report_count > 4) {
100-
dropped_reports += report_count - 4;
101-
if (dropped_reports > max_dropped_reports) max_dropped_reports = dropped_reports;
116+
117+
// Pad remaining report slots with device addr
118+
for (; epind < HID_EP_REPORT_COUNT; epind++) {
119+
if (stored_trackers > 0) {
120+
packet_device_addr(ep_report_buffer[epind].data, sent_device_addr);
121+
sent_device_addr = (sent_device_addr + 1) % stored_trackers;
122+
}
102123
}
103-
report_sent += report_count;
104-
report_sent += 3; // this is a hack to make sure the ep isnt reading the same bits as trackers write to
105-
if (report_sent > MAX_TRACKERS / 2) report_sent = 0; // an attempt to make ringbuffer so the ep isnt reading the same bits as trackers write to // TODO: might be too small!
106-
report_count = 0;
124+
125+
ret = hid_int_ep_write(hdev, (uint8_t *)ep_report_buffer, sizeof(report) * HID_EP_REPORT_COUNT, &wrote);
126+
107127
if (ret != 0) {
108128
/*
109129
* Do nothing and wait until host has reset the device
@@ -332,20 +352,38 @@ void hid_write_packet_n(uint8_t *data, uint8_t rssi)
332352
}
333353
#endif
334354

335-
memcpy(&report.data, data, 16); // all data can be passed through
355+
memcpy(&report.data, data, sizeof(report)); // all data can be passed through
336356
if (data[0] != 1 && data[0] != 4) // packet 1 and 4 are full precision quat and accel/mag, no room for rssi
337357
report.data[15] = rssi;
338-
// TODO: this sucks
339-
for (int i = 0; i < report_count; i++) // replace existing entry instead
340-
{
341-
if (reports[sizeof(report) * (report_sent + i) + 1] == report.data[1])
342-
{
343-
memcpy(&reports[sizeof(report) * (report_sent + i)], &report, sizeof(report));
344-
return;
358+
// Get current FIFO status atomically
359+
size_t write_idx = (size_t)atomic_get(&report_write_index);
360+
size_t read_idx = (size_t)atomic_get(&report_read_index);
361+
362+
// Try to replace existing entry for the same tracker first
363+
if (write_idx != read_idx) {
364+
// Start from read point + 1 to avoid hitting the entry being used
365+
size_t check_index = read_idx + 1;
366+
if (check_index == MAX_TRACKERS) check_index = 0;
367+
368+
while (check_index != write_idx) {
369+
if (reports[check_index].data[1] == data[1]) {
370+
// Replace existing entry
371+
reports[check_index] = report;
372+
return;
373+
}
374+
check_index = check_index + 1;
375+
if (check_index == MAX_TRACKERS) check_index = 0;
345376
}
346377
}
347-
if (report_count > 100) // overflow
378+
if (write_idx + 1 == read_idx || (write_idx == MAX_TRACKERS-1 && read_idx == 0)) { // overflow
379+
dropped_reports ++;
348380
return;
349-
memcpy(&reports[sizeof(report) * (report_sent + report_count)], &report, sizeof(report));
350-
report_count++;
381+
}
382+
// Write new packet into FIFO
383+
reports[write_idx] = report;
384+
385+
// Update write index atomically
386+
write_idx ++;
387+
if (write_idx == MAX_TRACKERS) write_idx = 0;
388+
atomic_set(&report_write_index, write_idx);
351389
}

0 commit comments

Comments
 (0)