Compare commits

..

No commits in common. "d78bcd46383fb2068511d303a896e0e9c2727469" and "4a3ca5c83ad8e9c16b3bc2b771cc4b2954777af3" have entirely different histories.

8 changed files with 78 additions and 85 deletions

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.6)
## Version Configuration ## Version Configuration
set(VERSION_MAJOR 00) set(VERSION_MAJOR 00)
set(VERSION_MINOR 162) set(VERSION_MINOR 161)
## Release Type Selection ## Release Type Selection
option(DH_DEBUG "Build a debug version" OFF) option(DH_DEBUG "Build a debug version" OFF)

View File

@ -10,7 +10,7 @@ All I wanted was a way to use a keyboard shortcut to quickly switch outputs, pai
## Features ## Features
- Completely **[free and open source](https://certification.oshwa.org/de000149.html)** - Completely **free and open source**
- No noticeable delay when switching - No noticeable delay when switching
- Simply drag the mouse pointer between computers - Simply drag the mouse pointer between computers
- No software installed - No software installed
@ -19,9 +19,9 @@ All I wanted was a way to use a keyboard shortcut to quickly switch outputs, pai
- Full Galvanic isolation between your outputs - Full Galvanic isolation between your outputs
- Works with Linux, macOS and Windows - Works with Linux, macOS and Windows
[User Manual](user-manual.pdf) is now available ![Image](img/oshw.svg){width=240}
[Proudly certified](https://certification.oshwa.org/de000149.html) by the Open Source Hardware Association (oshwa.org)
![Image](img/oshw.svg)
------ ------
## How it works ## How it works
@ -53,6 +53,9 @@ It also remembers the LED state for each computer, so you can pick up exactly ho
![Image](img/demo-typing.gif) ![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 ## 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. 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.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -39,7 +39,7 @@ void _get_border_position(device_t *state, border_size_t *border) {
border->top = state->pointer_y; border->top = state->pointer_y;
} }
void _screensaver_set(device_t *state, uint8_t value) { void _screensaver_set(device_t *state, bool value) {
if (CURRENT_BOARD_IS_ACTIVE_OUTPUT) if (CURRENT_BOARD_IS_ACTIVE_OUTPUT)
state->config.output[BOARD_ROLE].screensaver.mode = value; state->config.output[BOARD_ROLE].screensaver.mode = value;
else else
@ -123,18 +123,12 @@ void mouse_zoom_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
/* When pressed, enables the screensaver on active output */ /* When pressed, enables the screensaver on active output */
void enable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) { void enable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
uint8_t desired_mode = state->config.output[BOARD_ROLE].screensaver.mode; _screensaver_set(state, true);
/* If the user explicitly asks for screensaver to be active, ignore config and turn it on */
if (desired_mode == DISABLED)
desired_mode = PONG;
_screensaver_set(state, desired_mode);
} }
/* When pressed, disables the screensaver on active output */ /* When pressed, disables the screensaver on active output */
void disable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) { void disable_screensaver_hotkey_handler(device_t *state, hid_keyboard_report_t *report) {
_screensaver_set(state, DISABLED); _screensaver_set(state, false);
} }
/* Put the device into a special configuration mode */ /* Put the device into a special configuration mode */

View File

@ -209,7 +209,6 @@ enum screensaver_mode_e {
DISABLED = 0, DISABLED = 0,
PONG = 1, PONG = 1,
JITTER = 2, JITTER = 2,
MAX_SS_VAL = JITTER,
}; };
#define ITF_NUM_HID 0 #define ITF_NUM_HID 0

View File

@ -66,7 +66,7 @@
HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\
HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\
HID_USAGE_MIN ( 1 ) ,\ HID_USAGE_MIN ( 1 ) ,\
HID_USAGE_MAX ( 8 ) ,\ HID_USAGE_MAX ( 5 ) ,\
HID_LOGICAL_MIN ( 0 ) ,\ HID_LOGICAL_MIN ( 0 ) ,\
HID_LOGICAL_MAX ( 1 ) ,\ HID_LOGICAL_MAX ( 1 ) ,\
\ \

View File

@ -17,9 +17,6 @@
#include "main.h" #include "main.h"
#define MACOS_SWITCH_MOVE_X 10
#define MACOS_SWITCH_MOVE_COUNT 5
/* Move mouse coordinate 'position' by 'offset', but don't fall off the screen */ /* Move mouse coordinate 'position' by 'offset', but don't fall off the screen */
int32_t move_and_keep_on_screen(int position, int offset) { int32_t move_and_keep_on_screen(int position, int offset) {
/* Lowest we can go is 0 */ /* Lowest we can go is 0 */
@ -125,7 +122,7 @@ int16_t scale_y_coordinate(int screen_from, int screen_to, device_t *state) {
} }
void switch_screen( void switch_screen(
device_t *state, output_t *output, int output_to, int direction) { device_t *state, output_t *output, int new_x, int output_from, int output_to, int direction) {
uint8_t *mouse_park_pos = &state->config.output[state->active_output].mouse_park_pos; uint8_t *mouse_park_pos = &state->config.output[state->active_output].mouse_park_pos;
int16_t mouse_y = (*mouse_park_pos == 0) ? MIN_SCREEN_COORD : /* Top */ int16_t mouse_y = (*mouse_park_pos == 0) ? MIN_SCREEN_COORD : /* Top */
@ -140,21 +137,17 @@ void switch_screen(
state->pointer_y = scale_y_coordinate(output->number, 1 - output->number, state); state->pointer_y = scale_y_coordinate(output->number, 1 - output->number, state);
} }
void switch_desktop_macos(device_t *state, int direction) { void switch_desktop(device_t *state, output_t *output, int new_index, int direction) {
/* Fix for MACOS: Send relative mouse movement here, one or two pixels in the /* Fix for MACOS: Send relative mouse movement here, one or two pixels in the
direction of movement, BEFORE absolute report sets X to 0 */ direction of movement, BEFORE absolute report sets X to 0 */
uint16_t move = (direction == LEFT) ? -MACOS_SWITCH_MOVE_X : MACOS_SWITCH_MOVE_X; mouse_report_t move_relative_one
mouse_report_t move_relative_one = {.x = move, .mode = RELATIVE}; = {.x = (direction == LEFT) ? -5 : 5, .mode = RELATIVE};
/* Once doesn't seem reliable enough, do it a few times */
for (int i = 0; i < MACOS_SWITCH_MOVE_COUNT; i++)
output_mouse_report(&move_relative_one, state);
}
void switch_desktop(device_t *state, output_t *output, int new_index, int direction) {
switch (output->os) { switch (output->os) {
case MACOS: case MACOS:
switch_desktop_macos(state, direction); /* Once doesn't seem reliable enough, do it a few times */
for (int i = 0; i < 5; i++)
output_mouse_report(&move_relative_one, state);
break; break;
case WINDOWS: case WINDOWS:
@ -206,7 +199,7 @@ void check_screen_switch(const mouse_values_t *values, device_t *state) {
if (state->mouse_buttons) if (state->mouse_buttons)
return; return;
switch_screen(state, output, 1 - state->active_output, direction); switch_screen(state, output, new_x, state->active_output, 1 - state->active_output, direction);
} }
/* If here, this output has multiple desktops and we are not on the main one */ /* If here, this output has multiple desktops and we are not on the main one */
else else

View File

@ -59,51 +59,22 @@ void usb_host_task(device_t *state) {
tuh_task(); tuh_task();
} }
mouse_report_t *screensaver_pong(device_t *state) {
static mouse_report_t report = {0};
static int dx = 20, dy = 25;
/* Check if we are bouncing off the walls and reverse direction in that case. */
if (report.x + dx < MIN_SCREEN_COORD || report.x + dx > MAX_SCREEN_COORD)
dx = -dx;
if (report.y + dy < MIN_SCREEN_COORD || report.y + dy > MAX_SCREEN_COORD)
dy = -dy;
report.x += dx;
report.y += dy;
return &report;
}
mouse_report_t *screensaver_jitter(device_t *state) {
const int16_t jitter_distance = 2;
static mouse_report_t report = {
.y = jitter_distance,
.mode = RELATIVE,
};
report.y = -report.y;
return &report;
}
/* Have something fun and entertaining when idle. */ /* Have something fun and entertaining when idle. */
void screensaver_task(device_t *state) { void screensaver_task(device_t *state) {
const uint32_t delays[] = { const int mouse_move_delay = 5000;
0, /* DISABLED, unused index 0 */
5000, /* PONG, move mouse every 5 ms for a high framerate */
10000000, /* JITTER, once every 10 sec is more than enough */
};
static int last_pointer_move = 0;
screensaver_t *screensaver = &state->config.output[BOARD_ROLE].screensaver; screensaver_t *screensaver = &state->config.output[BOARD_ROLE].screensaver;
uint64_t inactivity_period = time_us_64() - state->last_activity[BOARD_ROLE]; uint64_t inactivity_period = time_us_64() - state->last_activity[BOARD_ROLE];
static mouse_report_t report = {0};
static int last_pointer_move = 0;
static int dx = 20, dy = 25, jitter = 1;
/* If we're not enabled, nothing to do here. */ /* If we're not enabled, nothing to do here. */
if (screensaver->mode == DISABLED) if (screensaver->mode == DISABLED)
return; return;
/* System is still not idle for long enough to activate or screensaver mode is not supported */ /* System is still not idle for long enough to activate or we've been running for too long */
if (inactivity_period < screensaver->idle_time_us || screensaver->mode > MAX_SS_VAL) if (inactivity_period < screensaver->idle_time_us)
return; return;
/* We exceeded the maximum permitted screensaver runtime */ /* We exceeded the maximum permitted screensaver runtime */
@ -116,25 +87,32 @@ void screensaver_task(device_t *state) {
return; return;
/* We're active! Now check if it's time to move the cursor yet. */ /* We're active! Now check if it's time to move the cursor yet. */
if (time_us_32() - last_pointer_move < delays[screensaver->mode]) if ((time_us_32()) - last_pointer_move < mouse_move_delay)
return; return;
mouse_report_t *report;
switch (screensaver->mode) { switch (screensaver->mode) {
case PONG: case PONG:
report = screensaver_pong(state); /* Check if we are bouncing off the walls and reverse direction in that case. */
if (report.x + dx < MIN_SCREEN_COORD || report.x + dx > MAX_SCREEN_COORD)
dx = -dx;
if (report.y + dy < MIN_SCREEN_COORD || report.y + dy > MAX_SCREEN_COORD)
dy = -dy;
report.x += dx;
report.y += dy;
break; break;
case JITTER: case JITTER:
report = screensaver_jitter(state); report.x = state->pointer_x + jitter;
report.y = state->pointer_y + jitter;
jitter = -jitter;
break; break;
default:
return;
} }
/* Move mouse pointer */ /* Move mouse pointer */
queue_mouse_report(report, state); queue_mouse_report(&report, state);
/* Update timer of the last pointer move */ /* Update timer of the last pointer move */
last_pointer_move = time_us_32(); last_pointer_move = time_us_32();