DeskHop v0.68

- Wrote a "proper" user manual
  - Added screensaver shortcuts
  - Modified descriptor from 5+3 buttons to 8 buttons
  - Added OSHW cert to docs
  - Bumped bootsel detection to debug version
  - Tidied up CMakeList
This commit is contained in:
Hrvoje Cavrak 2024-11-25 21:06:20 +01:00
parent 1bbee41e3f
commit 4a3ca5c83a
10 changed files with 154 additions and 49 deletions

View File

@ -1,23 +1,36 @@
cmake_minimum_required(VERSION 3.6)
## Version Configuration
set(VERSION_MAJOR 00)
set(VERSION_MINOR 160)
set(VERSION_MINOR 161)
## Release Type Selection
option(DH_DEBUG "Build a debug version" OFF)
## Hardware Configuration
set(DP_PIN_DEFAULT 14 CACHE STRING "Default USB D+ Pin Number")
set(PIO_USE_TINYUSB 1 CACHE STRING "Make TinyUSB Manage the PIO USB Port")
set(PICO_BOARD "pico")
## Pico SDK Configuration
set(PICO_SDK_FETCH_FROM_GIT off)
set(PICO_BOARD=pico)
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR}/pico-sdk)
set(SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/src)
include(pico_sdk_import.cmake)
set(CMAKE_C_FLAGS "-Ofast -Wall -mcpu=cortex-m0plus -mtune=cortex-m0plus -fstack-usage")
set(PICO_COPY_TO_RAM 1)
## Project Setup
project(deskhop_project C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(PICO_COPY_TO_RAM 1)
## Compiler Flags
set(CMAKE_C_FLAGS "-Ofast -Wall -mcpu=cortex-m0plus -mtune=cortex-m0plus -fstack-usage")
## Initialize Pico SDK
pico_sdk_init()
## PIO USB Library Setup
set(PICO_PIO_USB_DIR ${CMAKE_CURRENT_LIST_DIR}/Pico-PIO-USB)
add_library(Pico-PIO-USB STATIC
@ -36,33 +49,36 @@ target_link_libraries(Pico-PIO-USB PRIVATE
)
target_include_directories(Pico-PIO-USB PRIVATE ${PICO_PIO_USB_DIR})
## Source Files
set(COMMON_SOURCES
${CMAKE_CURRENT_LIST_DIR}/src/usb_descriptors.c
${CMAKE_CURRENT_LIST_DIR}/src/defaults.c
${CMAKE_CURRENT_LIST_DIR}/src/constants.c
${CMAKE_CURRENT_LIST_DIR}/src/protocol.c
${CMAKE_CURRENT_LIST_DIR}/src/hid_parser.c
${CMAKE_CURRENT_LIST_DIR}/src/hid_report.c
${CMAKE_CURRENT_LIST_DIR}/src/utils.c
${CMAKE_CURRENT_LIST_DIR}/src/handlers.c
${CMAKE_CURRENT_LIST_DIR}/src/setup.c
${CMAKE_CURRENT_LIST_DIR}/src/keyboard.c
${CMAKE_CURRENT_LIST_DIR}/src/mouse.c
${CMAKE_CURRENT_LIST_DIR}/src/tasks.c
${CMAKE_CURRENT_LIST_DIR}/src/led.c
${CMAKE_CURRENT_LIST_DIR}/src/uart.c
${CMAKE_CURRENT_LIST_DIR}/src/usb.c
${CMAKE_CURRENT_LIST_DIR}/src/main.c
${CMAKE_CURRENT_LIST_DIR}/src/ramdisk.c
${SRC_DIR}/usb_descriptors.c
${SRC_DIR}/defaults.c
${SRC_DIR}/constants.c
${SRC_DIR}/protocol.c
${SRC_DIR}/hid_parser.c
${SRC_DIR}/hid_report.c
${SRC_DIR}/utils.c
${SRC_DIR}/handlers.c
${SRC_DIR}/setup.c
${SRC_DIR}/keyboard.c
${SRC_DIR}/mouse.c
${SRC_DIR}/tasks.c
${SRC_DIR}/led.c
${SRC_DIR}/uart.c
${SRC_DIR}/usb.c
${SRC_DIR}/main.c
${SRC_DIR}/ramdisk.c
${PICO_TINYUSB_PATH}/src/portable/raspberrypi/pio_usb/dcd_pio_usb.c
${PICO_TINYUSB_PATH}/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
)
## Include Directories
set(COMMON_INCLUDES
${CMAKE_CURRENT_LIST_DIR}/src/include
${SRC_DIR}/include
${PICO_PIO_USB_DIR}/src
)
## Library Dependencies
set(COMMON_LINK_LIBRARIES
pico_stdlib
hardware_flash
@ -76,12 +92,14 @@ set(COMMON_LINK_LIBRARIES
pico_multicore
Pico-PIO-USB
)
set(binary deskhop)
## Disk Image Configuration
# This assembles disk.S, then updates the elf section in post-build
# With the disk FAT image binary in /disk/disk.img
set(DISK_ASM "${CMAKE_CURRENT_LIST_DIR}/disk/disk.S")
set(DISK_BIN "${CMAKE_CURRENT_LIST_DIR}/disk/disk.img")
set_property(SOURCE ${DISK_ASM} APPEND PROPERTY COMPILE_OPTIONS "-x" "assembler-with-cpp")
add_executable(${binary} ${DISK_ASM})
@ -89,21 +107,28 @@ add_executable(${binary} ${DISK_ASM})
target_sources(${binary} PUBLIC ${COMMON_SOURCES})
target_compile_definitions(${binary}
PRIVATE
PIO_USB_USE_TINYUSB=1
PIO_USB_DP_PIN_DEFAULT=14
# Uncomment to enable debug uart:
# DH_DEBUG=1
PIO_USB_USE_TINYUSB=${PIO_USE_TINYUSB}
PIO_USB_DP_PIN_DEFAULT=${DP_PIN_DEFAULT}
__disk_file_path__="${DISK_BIN}"
)
## Support building a debug version
if (DH_DEBUG)
add_definitions(-DDH_DEBUG)
endif()
target_include_directories(${binary} PUBLIC ${COMMON_INCLUDES})
target_link_libraries(${binary} PUBLIC ${COMMON_LINK_LIBRARIES})
## Configure Pico Library
pico_enable_stdio_usb(${binary} 0)
pico_enable_stdio_uart(${binary} 0)
pico_set_linker_script(${binary} ${CMAKE_SOURCE_DIR}/memory_map.ld)
## Build other file formats as well
pico_add_extra_outputs(${binary})
## Post-Build Commands
add_custom_command(
TARGET ${binary} POST_BUILD
COMMAND python3 ${CMAKE_SOURCE_DIR}/tools/crc32.py ${binary}.bin ${binary}.crc ${VERSION_MAJOR}${VERSION_MINOR}
@ -113,9 +138,9 @@ add_custom_command(
COMMENT "Update CRC32 section to match the actual binary"
)
## Linker Options
target_link_options(${binary} PRIVATE
-Xlinker
--print-memory-usage
)
pico_set_linker_script(${binary} ${CMAKE_SOURCE_DIR}/memory_map.ld)

View File

@ -19,6 +19,9 @@ All I wanted was a way to use a keyboard shortcut to quickly switch outputs, pai
- Full Galvanic isolation between your outputs
- Works with Linux, macOS and Windows
![Image](img/oshw.svg){width=240}
[Proudly certified](https://certification.oshwa.org/de000149.html) by the Open Source Hardware Association (oshwa.org)
------
## How it works
@ -50,6 +53,9 @@ It also remembers the LED state for each computer, so you can pick up exactly ho
![Image](img/demo-typing.gif)
## User Manual
To help you set up, configure and program the board available [read the manual provided here](user-manual.pdf).
## How to build
To avoid version mismatch and reported path issues when building, as well as to save you from having to download a large SDK, the project now bundles minimal pico sdk and tinyusb.
@ -208,19 +214,20 @@ The standard process to do that is using isopropyl alcohol and an old toothbrush
## Usage guide
### Keyboard shortcuts - (fw versions 0.64 +)
### Keyboard shortcuts - (fw versions 0.68+)
_Config_
- ~~```Left Shift```~~ ```Left Ctrl + Right Shift + C + O``` - enter config mode
- ```Right Shift + F12 + D``` - remove flash config
- ```Right Shift + F12 + Y``` - save screen switch offset
- ```Right Shift + F12 + S``` - turn on/off screensaver option
_Usage_
- ```Right CTRL + Right ALT``` - Toggle slower mouse mode
- ```Right CTRL + K``` - Lock/Unlock mouse desktop switching
- ```Right CTRL + L``` - Lock both outputs at once (set output OS before, see shortcuts below)
- ~~```Left Shift```~~ ```Left Ctrl + Right Shift + G``` - Toggle gaming mode (lock to screen, act as standard mouse)
- ~~```Left Shift```~~ ```Left CTRL + Right Shift + G``` - Toggle gaming mode (lock to screen, act as standard mouse)
- ```Left CTRL + Right Shift + S``` - Enable screensaver
- ```Left CTRL + Right Shift + X``` - Disable screensaver
- ```Left CTRL + Caps Lock``` - Switch between outputs
Note: some keyboards don't send both shifts at the same time properly, that's why the shortcut was changed - to work for everyone. Apologies for the confusion.
@ -316,6 +323,7 @@ This still doesn't guarantee anything, but I believe it makes a reasonable set o
*I'm not selling anything, this is just a personal, non-commercial hobby project.*
[UPDATE] It seems you can order it in QTY of 1 (for either PCB, assembled PCB or a fully assembled device) from [Elecrow if you follow this link](https://www.elecrow.com/deskhop-fast-desktop-switching.html)
As reported by users, your **board will arrive blank** and you have to write the firmware yourself.
[UPDATE2] - I never asked Elecrow for anything, but a couple of days ago they offered to sponsor the project with a small budget that will be used for future board prototyping. Since my goal is to create a better board with more than 2 outputs etc, I believe prototyping services might be beneficial to the project.

35
img/oshw.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -39,6 +39,12 @@ void _get_border_position(device_t *state, border_size_t *border) {
border->top = state->pointer_y;
}
void _screensaver_set(device_t *state, bool value) {
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT)
state->config.output[BOARD_ROLE].screensaver.mode = value;
else
send_value(value, SCREENSAVER_MSG);
};
/* This key combo records switch y top coordinate for different-size monitors */
void screen_border_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
@ -115,6 +121,15 @@ void mouse_zoom_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
send_value(state->mouse_zoom, MOUSE_ZOOM_MSG);
};
/* When pressed, enables the screensaver on active output */
void enable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
_screensaver_set(state, true);
}
/* When pressed, disables the screensaver on active output */
void disable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
_screensaver_set(state, false);
}
/* Put the device into a special configuration mode */
void config_enable_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
@ -209,6 +224,11 @@ void handle_wipe_config_msg(uart_packet_t *packet, device_t *state) {
load_config(state);
}
/* Update screensaver state after received message */
void handle_screensaver_msg(uart_packet_t *packet, device_t *state) {
state->config.output[BOARD_ROLE].screensaver.mode = packet->data[0];
}
/* Process consumer control message */
void handle_consumer_control_msg(uart_packet_t *packet, device_t *state) {
queue_cc_packet(packet->data, state);

View File

@ -123,6 +123,7 @@ enum packet_type_e {
SYNC_BORDERS_MSG = 8,
FLASH_LED_MSG = 9,
WIPE_CONFIG_MSG = 10,
SCREENSAVER_MSG = 11,
HEARTBEAT_MSG = 12,
GAMING_MODE_MSG = 13,
CONSUMER_CONTROL_MSG = 14,
@ -540,6 +541,8 @@ void screenlock_hotkey_handler(device_t *, hid_keyboard_report_t *);
void output_config_hotkey_handler(device_t *, hid_keyboard_report_t *);
void wipe_config_hotkey_handler(device_t *, hid_keyboard_report_t *);
void config_enable_hotkey_handler(device_t *, hid_keyboard_report_t *);
void enable_screensaver_hotkey_handler(device_t *, hid_keyboard_report_t *);
void disable_screensaver_hotkey_handler(device_t *, hid_keyboard_report_t *);
void handle_keyboard_uart_msg(uart_packet_t *, device_t *);
void handle_mouse_abs_uart_msg(uart_packet_t *, device_t *);
@ -563,6 +566,7 @@ void handle_proxy_msg(uart_packet_t *, device_t *);
void handle_api_msgs(uart_packet_t *, device_t *);
void handle_api_read_all_msg(uart_packet_t *, device_t *);
void handle_toggle_gaming_msg(uart_packet_t *, device_t *);
void handle_screensaver_msg(uart_packet_t *, device_t *);
void switch_output(device_t *, uint8_t);

View File

@ -70,15 +70,11 @@
HID_LOGICAL_MIN ( 0 ) ,\
HID_LOGICAL_MAX ( 1 ) ,\
\
/* Left, Right, Middle, Backward, Forward buttons */ \
HID_REPORT_COUNT( 5 ) ,\
/* Left, Right, Mid, Back, Forward buttons + 3 extra */ \
HID_REPORT_COUNT( 8 ) ,\
HID_REPORT_SIZE ( 1 ) ,\
HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
\
/* 3 bit padding */ \
HID_REPORT_COUNT( 1 ) ,\
HID_REPORT_SIZE ( 3 ) ,\
HID_INPUT ( HID_CONSTANT ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
\
/* X, Y position [MOUSE_MIN, 32767] */ \

View File

@ -58,6 +58,20 @@ hotkey_combo_t hotkeys[] = {
.acknowledge = true,
.action_handler = &toggle_gaming_mode_handler},
/* Enable screensaver for active output */
{.modifier = KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_RIGHTSHIFT,
.keys = {HID_KEY_S},
.key_count = 1,
.acknowledge = true,
.action_handler = &enable_screensaver_hotkey_handler},
/* Disable screensaver for active output */
{.modifier = KEYBOARD_MODIFIER_LEFTCTRL | KEYBOARD_MODIFIER_RIGHTSHIFT,
.keys = {HID_KEY_X},
.key_count = 1,
.acknowledge = true,
.action_handler = &disable_screensaver_hotkey_handler},
/* Erase stored config */
{.modifier = KEYBOARD_MODIFIER_RIGHTSHIFT,
.keys = {HID_KEY_F12, HID_KEY_D},

View File

@ -133,9 +133,11 @@ void heartbeat_output_task(device_t *state) {
blink_led(state);
}
#ifdef DH_DEBUG
/* Holding the button invokes bootsel firmware upgrade */
if (is_bootsel_pressed())
reset_usb_boot(1 << PICO_DEFAULT_LED_PIN, 0);
#endif
uart_packet_t packet = {
.type = HEARTBEAT_MSG,

View File

@ -78,6 +78,7 @@ const uart_handler_t uart_handler[] = {
{.type = FLASH_LED_MSG, .handler = handle_flash_led_msg},
{.type = GAMING_MODE_MSG, .handler = handle_toggle_gaming_msg},
{.type = CONSUMER_CONTROL_MSG, .handler = handle_consumer_control_msg},
{.type = SCREENSAVER_MSG, .handler = handle_screensaver_msg},
/* Config */
{.type = WIPE_CONFIG_MSG, .handler = handle_wipe_config_msg},

BIN
user-manual.pdf Normal file

Binary file not shown.