From de3cb4dba7f0dbff5f0b6078e924857710ded9d3 Mon Sep 17 00:00:00 2001 From: Hrvoje Cavrak Date: Thu, 11 Jan 2024 17:57:29 +0100 Subject: [PATCH] Bugfixes and improvements: ========================== Added 1000 Hz polling. (Hopefully) fixed Logitech mouse issues Removed special treatment for 12 and 16-bit mice Increased mouse queue size Increased current allowance from 100mA to 500mA Allow mouse to wake up a suspended host Added memory usage print to build Updated README - Added link to troubleshooting wiki - Mouse polling rate chart - Updated known issues - Updates about possible PCB/assembly ordering --- CMakeLists.txt | 10 ++++++++++ README.md | 21 +++++++++++++++++---- img/polling_rate.png | Bin 0 -> 33572 bytes src/main.h | 2 +- src/mouse.c | 26 ++++++-------------------- src/usb_descriptors.c | 4 ++-- src/user_config.h | 4 ++-- 7 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 img/polling_rate.png diff --git a/CMakeLists.txt b/CMakeLists.txt index cdf0cdb..a21a375 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,3 +86,13 @@ target_link_libraries(board_B PUBLIC ${COMMON_LINK_LIBRARIES}) pico_enable_stdio_usb(board_B 0) pico_add_extra_outputs(board_B) + +target_link_options(board_A PRIVATE + -Xlinker + --print-memory-usage +) + +target_link_options(board_B PRIVATE + -Xlinker + --print-memory-usage +) diff --git a/README.md b/README.md index aaa4b7f..47e3b90 100644 --- a/README.md +++ b/README.md @@ -140,8 +140,7 @@ USB-A connector can be Molex MX-67643-0910 or a cheaper/budget one that shares t Additional steps: - - making the PCB ([Gerber provided](pcb/), JLC does it for a few bucks, choose 1.6 mm thickness) - + - making the PCB ([Gerber provided](pcb/), choose 1.6 mm thickness) - 3d printing the case ([stl files provided](case/), ~33g filament) ## Assembly guide @@ -166,6 +165,10 @@ The standard process to do that is using isopropyl alcohol and an old toothbrush *I'm not selling anything, this is just a personal, non-commercial hobby project.* +[update] There is a manufacturing/assembly company in China that might offer PCBs in qty of 1, assembled boards and boards + case, so stay tuned. + +I **don't want to take any commission** on this - the only goal is to provide an alternative for people who don't feel confident enough to assemble the boards themselves. + 4. When the active screen is changed via the mouse, does the keyboard follow (and vice versa)? Yes, the idea was to make it behave like it was one single computer. @@ -178,6 +181,10 @@ Not with the current version, but there is work ongoing to add support. Testing It should work - tried an Anker wireless mouse with a separate receiver and that worked just fine. +7. I have issues with build or compilation + +Check out the [Troubleshooting Wiki](https://github.com/hrvach/deskhop/wiki/Troubleshooting) that might have some answers. + ## Software Alternatives There are several software alternatives you can use if that works in your particular situation. @@ -190,9 +197,11 @@ There are several software alternatives you can use if that works in your partic ## Shortcomings -- Slow mouse movement reported for modern mice with 16-bit x/y values. Can't reproduce with my 2$ mouse, ordered a better one so once it arrives, I'll hopefully be able to recreate and fix. Apologies and thanks for understanding! +- Slow mouse movement with some devices. +- Windows 10 broke HID absolute coordinates behavior in KB5003637, so you can't use more than 1 screen on Windows (mouse will stay on the main screen). +- If you have more than one display, the mouse is faster in the X direction on that machine. Will get fixed with per-output configurable speed settings. - Code needs cleanup, some refactoring etc. -- Occasional bugs and weird behavior. +- Occasional bugs and weird behavior. - Not tested with a wide variety of devices, I don't know how it will work with your hardware. There is a reasonable chance things might not work out-of-the-box. - NOTE: Both computers need to be connected and powered on for this to work (as each board gets powered by the computer it plugs into). @@ -210,6 +219,10 @@ Planned features: - Unified firmware for both Picos - ... and more! +Mouse polling should now work at 1000 Hz (the dips in the graph is my arm hurting from all the movement :-)): + +![Mouse polling rate](img/polling_rate.png) + ## Disclaimer I kindly request that anyone attempting to build this project understands and acknowledges that I am not liable for any injuries, damages, or other consequences. Your safety is important, and I encourage you to approach this project carefully, taking necessary precautions and assuming personal responsibility for your well-being throughout the process. Please don't get electrocuted, burned, stressed or angry. Have fun and enjoy! diff --git a/img/polling_rate.png b/img/polling_rate.png new file mode 100644 index 0000000000000000000000000000000000000000..9ac3c316eb9d8488c61c8c6c7d481107d67c3199 GIT binary patch literal 33572 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 literal 0 HcmV?d00001 diff --git a/src/main.h b/src/main.h index 6208f0c..5478ecb 100644 --- a/src/main.h +++ b/src/main.h @@ -124,7 +124,7 @@ typedef struct { #define RAW_PACKET_LENGTH (START_LENGTH + PACKET_LENGTH) #define KBD_QUEUE_LENGTH 128 -#define MOUSE_QUEUE_LENGTH 256 +#define MOUSE_QUEUE_LENGTH 2048 #define KEYS_IN_USB_REPORT 6 #define KBD_REPORT_LENGTH 8 diff --git a/src/mouse.c b/src/mouse.c index 582873f..b6896c0 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -96,30 +96,12 @@ void extract_values_report_protocol(uint8_t* report, values->move_y = get_report_value(report, &state->mouse_dev.move_y); values->wheel = get_report_value(report, &state->mouse_dev.wheel); values->buttons = get_report_value(report, &state->mouse_dev.buttons); - - /* Mice generally come in 3 categories - 8-bit, 12-bit and 16-bit. */ - switch (state->mouse_dev.move_x.size) { - case 12: - /* If we're already 12 bit, great! */ - break; - case 16: - /* Initially we downscale fancy mice to 12-bits, - adding a 32-bit internal coordinate tracking is TODO */ - values->move_x >>= 4; - values->move_y >>= 4; - break; - default: - /* 8-bit is the default, upscale to 12-bit. */ - values->move_x <<= 4; - values->move_y <<= 4; - } } void extract_values_boot_protocol(uint8_t* report, device_state_t* state, mouse_values_t* values) { hid_mouse_report_t* mouse_report = (hid_mouse_report_t*)report; - /* For 8-bit values, we upscale them to 12-bit, TODO: 16 bit */ - values->move_x = mouse_report->x << 4; - values->move_y = mouse_report->y << 4; + values->move_x = mouse_report->x; + values->move_y = mouse_report->y; values->wheel = mouse_report->wheel; values->buttons = mouse_report->buttons; } @@ -171,6 +153,10 @@ void process_mouse_queue_task(device_state_t* state) { if (!queue_try_peek(&state->mouse_queue, &report)) return; + /* If we are suspended, let's wake the host up */ + if(tud_suspended()) + tud_remote_wakeup(); + /* ... try sending it to the host, if it's successful */ bool succeeded = tud_hid_abs_mouse_report(REPORT_ID_MOUSE, report.buttons, report.x, report.y, report.wheel, report.pan); diff --git a/src/usb_descriptors.c b/src/usb_descriptors.c index 246a0b4..9c3d309 100644 --- a/src/usb_descriptors.c +++ b/src/usb_descriptors.c @@ -107,7 +107,7 @@ uint8_t const desc_configuration[] = { 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, - 100), + 500), // Interface number, string index, protocol, report descriptor len, EP In address, size & // polling interval @@ -117,7 +117,7 @@ uint8_t const desc_configuration[] = { sizeof(desc_hid_report), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, - 5)}; + 1)}; #if TUD_OPT_HIGH_SPEED // Per USB specs: high speed capable device must report device_qualifier and diff --git a/src/user_config.h b/src/user_config.h index 27626c3..681bda1 100644 --- a/src/user_config.h +++ b/src/user_config.h @@ -44,7 +44,7 @@ * * */ -#define MOUSE_SPEED_FACTOR_X 1 -#define MOUSE_SPEED_FACTOR_Y 1 +#define MOUSE_SPEED_FACTOR_X 16 +#define MOUSE_SPEED_FACTOR_Y 16 #define MOUSE_JUMP_THRESHOLD 0