From f392640c73298948e44976684270613df08949db Mon Sep 17 00:00:00 2001 From: Rutherther Date: Sat, 21 Dec 2024 21:32:05 +0100 Subject: [PATCH] feat: allow skipping queue for larger memory moves --- firmware/include/usb_device_cdc.h | 9 ++- firmware/src/main.c | 91 +++++++++++++++++++++++++------ firmware/src/usb_device_cdc.c | 26 ++++++++- 3 files changed, 104 insertions(+), 22 deletions(-) diff --git a/firmware/include/usb_device_cdc.h b/firmware/include/usb_device_cdc.h index 4414f3a..b03e241 100644 --- a/firmware/include/usb_device_cdc.h +++ b/firmware/include/usb_device_cdc.h @@ -96,7 +96,8 @@ typedef struct { } usb_cdc_call_management_functional_decriptor_t; _Static_assert(sizeof(usb_cdc_call_management_functional_decriptor_t) == 5, "Size check"); -typedef void (*cdc_receive_callback_t)(usb_device_t* device, uint16_t count); +typedef uint16_t (*cdc_receive_callback_t)(usb_device_t* device, uint8_t* data, uint16_t count); +typedef uint8_t* (*cdc_receive_location_callback_t)(usb_device_t* device, uint16_t count); /* typedef enum { */ /* CDC_STATE_NONE, */ @@ -116,7 +117,8 @@ typedef struct { uint8_t functional_descriptors_count; usb_cdc_functional_descriptor_header_t** functional_descriptors; - cdc_receive_callback_t callback; + cdc_receive_callback_t receive_callback; + cdc_receive_location_callback_t receive_location_callback; // Internal state. queue_t* rx_buffer; @@ -143,6 +145,9 @@ void cdc_acm_configure(usb_device_t *device, uint16_t rx_queue_size); void cdc_data_set_receive_callback(usb_device_t *device, cdc_receive_callback_t callback); +void cdc_data_set_receive_location_callback(usb_device_t *device, + cdc_receive_location_callback_t callback); + int32_t cdc_data_send_blocking(usb_device_t *device, uint8_t *data, uint16_t size); int32_t cdc_data_send(usb_device_t* device, uint8_t* data, uint16_t size); diff --git a/firmware/src/main.c b/firmware/src/main.c index a6c23ff..e02e705 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -21,6 +21,8 @@ pin_t wkup; pin_t led1; exti_t exti_wkup; +uint8_t* global_framebuffer; + void init_fmc(fmc_t *fmc) { @@ -239,7 +241,7 @@ usb_device_t* init_usb() void *usb_dev = usb_device_init(USB_OTG_HS1, &USB_CLASS_CDC_ACM, 0x1234, 0x1111, u"Frantisek Bohacek", u"Display", 1, NULL); - cdc_acm_configure(usb_dev, 512 * 8); // 8 full packets maximum + cdc_acm_configure(usb_dev, 512 * 8); // 8 full packets maximum size usb_device_setup(usb_dev); return usb_dev; @@ -450,6 +452,9 @@ pixel_rgb888_t* init_display(display_t* display, fmc_t* fmc) void app_loop(usb_device_t* usb_dev, display_t* display, pixel_rgb888_t* framebuffer); +uint16_t cdc_receive_callback(usb_device_t* device, uint8_t* data, uint16_t count); +uint8_t* cdc_receive_location_callback(usb_device_t* device, uint16_t count); + void main() { fmc_t fmc; @@ -490,21 +495,70 @@ void main() app_loop(usb_dev, &display, framebuffer); } +bool image_command_handling = false; +bool image_command_handled = false; +uint8_t* framebuffer_ptr; +uint32_t read_count; +#define TOTAL_PIXEL_BYTES DISPLAY_WIDTH * DISPLAY_HEIGHT * 3 + +uint16_t cdc_receive_callback(usb_device_t *device, uint8_t *data, + uint16_t count) { + + if (!image_command_handling && data[0] == 'i') { + framebuffer_ptr = global_framebuffer; + read_count = 0; + image_command_handling = true; + + for (uint16_t i = 0; i < count - 1; i++) { + framebuffer_ptr[i] = data[i + 1]; + } + framebuffer_ptr += count - 1; + read_count += count - 1; + return count; + } + + return 0; +} + +uint8_t* cdc_receive_location_callback(usb_device_t *device, uint16_t count) { + if (!image_command_handling) { + return NULL; + } + + uint8_t* ptr = framebuffer_ptr; + framebuffer_ptr += count; + read_count += count; + + if (read_count >= TOTAL_PIXEL_BYTES) { + image_command_handling = false; + image_command_handled = true; + } + + return framebuffer_ptr; +} + void app_loop(usb_device_t* usb_dev, display_t* display, pixel_rgb888_t* framebuffer) { - uint8_t data[1024]; + global_framebuffer = (uint8_t*)framebuffer; + + cdc_data_set_receive_callback(usb_dev, cdc_receive_callback); + cdc_data_set_receive_location_callback(usb_dev, cdc_receive_location_callback); + + uint8_t data[16]; bool handling_cmd = false; uint8_t cmd; uint32_t pos = 0; - uint32_t max_size = 1; display_refresh(display); while (1) { - uint16_t received = cdc_data_receive(usb_dev, data, max_size); + uint16_t received = cdc_data_receive(usb_dev, data, 1); - max_size = 1; + if (image_command_handled) { + display_refresh(display); + image_command_handled = false; + } if (received == 0) { continue; @@ -563,24 +617,27 @@ void app_loop(usb_device_t* usb_dev, display_t* display, pixel_rgb888_t* framebu } display_refresh(display); break; - case 'i': - handling_cmd = true; - max_size = 1024; + case 'i': { + uint8_t* framebuffer_ptr = (uint8_t*)framebuffer; + uint32_t bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * 3; - for (uint16_t i = 0; i < received; i++) { - if (pos > 0) { - ((uint8_t *)framebuffer)[pos - 1] = data[i]; + pos = 0; + + while (pos < bytes) { + uint32_t max = bytes - pos; + if (max > 65535) { + max = 65535; } - pos++; - } - if (pos >= DISPLAY_WIDTH * DISPLAY_HEIGHT * 3) { - handling_cmd = false; - display_refresh(display); - max_size = 1; + uint16_t received = cdc_data_receive(usb_dev, framebuffer_ptr, max); + pos += received; + framebuffer_ptr += received; } + + display_refresh(display); break; } + } } } diff --git a/firmware/src/usb_device_cdc.c b/firmware/src/usb_device_cdc.c index 7361157..1e9ce82 100644 --- a/firmware/src/usb_device_cdc.c +++ b/firmware/src/usb_device_cdc.c @@ -585,14 +585,28 @@ void usb_device_cdc_enable_endpoint_maybe(usb_device_t* device, usb_device_cdc_t void usb_device_cdc_received_data_callback(usb_device_t *device, packet_info_t *packet) { usb_device_cdc_t* cdc = (usb_device_cdc_t*)device->class; - uint8_t data[4*MAX_PACKET_SIZE]; + uint8_t data[2*MAX_PACKET_SIZE]; uint16_t len = packet->byte_count; volatile uint32_t* fifo = &device->fifos[packet->endpoint_num].data[0]; if (packet->packet_status == PACKET_OUT_DATA_PACKET_RCVD) { - // TODO: could be optimized until pointer has to wrap + if (cdc->receive_location_callback != NULL) { + uint8_t* receive_location = cdc->receive_location_callback(device, len); + if (receive_location != NULL) { + usb_generic_read(receive_location, len, fifo); + return; + } + } + usb_generic_read(data, len, fifo); + + if (cdc->receive_callback != NULL) { + uint16_t app_read = cdc->receive_callback(device, data, len); + len -= app_read; + } + + // TODO: could be optimized until pointer has to wrap if (queue_space(cdc->rx_buffer) < len) { cdc->lost_data += len - queue_space(cdc->rx_buffer); } @@ -624,7 +638,13 @@ void usb_device_cdc_nyet_callback(usb_device_t *device, uint8_t endpoint) { void cdc_data_set_receive_callback(usb_device_t *device, cdc_receive_callback_t callback) { usb_device_cdc_t* cdc = (usb_device_cdc_t*)device->class; - cdc->callback = callback; + cdc->receive_callback = callback; +} + +void cdc_data_set_receive_location_callback(usb_device_t *device, + cdc_receive_location_callback_t callback) { + usb_device_cdc_t* cdc = (usb_device_cdc_t*)device->class; + cdc->receive_location_callback = callback; } int32_t cdc_data_send_blocking(usb_device_t *device, uint8_t *data, uint16_t size) { -- 2.48.1