Skip to content

Commit

Permalink
[Split] Sync Timer feature (qmk#10997)
Browse files Browse the repository at this point in the history
A timer that is kept in sync between the halves of a split keyboard
  • Loading branch information
XScorpion2 authored Dec 1, 2020
1 parent 9c03a89 commit a8d0ec0
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 15 deletions.
1 change: 1 addition & 0 deletions quantum/quantum.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "eeconfig.h"
#include "bootloader.h"
#include "timer.h"
#include "sync_timer.h"
#include "config_common.h"
#include "led.h"
#include "action_util.h"
Expand Down
6 changes: 3 additions & 3 deletions quantum/rgb_matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ static bool rgb_matrix_none(effect_params_t *params) {

static void rgb_task_timers(void) {
#if defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0
uint32_t deltaTime = timer_elapsed32(rgb_timer_buffer);
uint32_t deltaTime = sync_timer_elapsed32(rgb_timer_buffer);
#endif // defined(RGB_MATRIX_KEYREACTIVE_ENABLED) || RGB_DISABLE_TIMEOUT > 0
rgb_timer_buffer = timer_read32();
rgb_timer_buffer = sync_timer_read32();

// Update double buffer timers
#if RGB_DISABLE_TIMEOUT > 0
Expand Down Expand Up @@ -296,7 +296,7 @@ static void rgb_task_timers(void) {

static void rgb_task_sync(void) {
// next task
if (timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;
if (sync_timer_elapsed32(g_rgb_timer) >= RGB_MATRIX_LED_FLUSH_LIMIT) rgb_task_state = STARTING;
}

static void rgb_task_start(void) {
Expand Down
21 changes: 10 additions & 11 deletions quantum/rgblight.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#endif
#include "wait.h"
#include "progmem.h"
#include "timer.h"
#include "sync_timer.h"
#include "rgblight.h"
#include "color.h"
#include "debug.h"
Expand Down Expand Up @@ -684,18 +684,16 @@ static void rgblight_layers_write(void) {

# ifdef RGBLIGHT_LAYER_BLINK
rgblight_layer_mask_t _blinked_layer_mask = 0;
uint16_t _blink_duration = 0;
static uint16_t _blink_timer;

void rgblight_blink_layer(uint8_t layer, uint16_t duration_ms) {
rgblight_set_layer_state(layer, true);
_blinked_layer_mask |= 1 << layer;
_blink_timer = timer_read();
_blink_duration = duration_ms;
_blink_timer = sync_timer_read() + duration_ms;
}

void rgblight_unblink_layers(void) {
if (_blinked_layer_mask != 0 && timer_elapsed(_blink_timer) > _blink_duration) {
if (_blinked_layer_mask != 0 && timer_expired(sync_timer_read(), _blink_timer)) {
for (uint8_t layer = 0; layer < RGBLIGHT_MAX_LAYERS; layer++) {
if ((_blinked_layer_mask & 1 << layer) != 0) {
rgblight_set_layer_state(layer, false);
Expand Down Expand Up @@ -799,7 +797,7 @@ void rgblight_update_sync(rgblight_syncinfo_t *syncinfo, bool write_to_eeprom) {
animation_status.restart = true;
}
# endif /* RGBLIGHT_SPLIT_NO_ANIMATION_SYNC */
# endif /* RGBLIGHT_USE_TIMER */
# endif /* RGBLIGHT_USE_TIMER */
}
#endif /* RGBLIGHT_SPLIT */

Expand Down Expand Up @@ -832,7 +830,7 @@ void rgblight_timer_enable(void) {
if (!is_static_effect(rgblight_config.mode)) {
rgblight_status.timer_enabled = true;
}
animation_status.last_timer = timer_read();
animation_status.last_timer = sync_timer_read();
RGBLIGHT_SPLIT_SET_CHANGE_TIMER_ENABLE;
dprintf("rgblight timer enabled.\n");
}
Expand Down Expand Up @@ -941,18 +939,19 @@ void rgblight_task(void) {
# endif
if (animation_status.restart) {
animation_status.restart = false;
animation_status.last_timer = timer_read() - interval_time - 1;
animation_status.last_timer = sync_timer_read();
animation_status.pos16 = 0; // restart signal to local each effect
}
if (timer_elapsed(animation_status.last_timer) >= interval_time) {
uint16_t now = sync_timer_read();
if (timer_expired(now, animation_status.last_timer)) {
# if defined(RGBLIGHT_SPLIT) && !defined(RGBLIGHT_SPLIT_NO_ANIMATION_SYNC)
static uint16_t report_last_timer = 0;
static bool tick_flag = false;
uint16_t oldpos16;
if (tick_flag) {
tick_flag = false;
if (timer_elapsed(report_last_timer) >= 30000) {
report_last_timer = timer_read();
if (timer_expired(now, report_last_timer)) {
report_last_timer += 30000;
dprintf("rgblight animation tick report to slave\n");
RGBLIGHT_SPLIT_ANIMATION_TICK;
}
Expand Down
26 changes: 25 additions & 1 deletion quantum/split_common/transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "quantum.h"

#define ROWS_PER_HAND (MATRIX_ROWS / 2)
#define SYNC_TIMER_OFFSET 2

#ifdef RGBLIGHT_ENABLE
# include "rgblight.h"
Expand All @@ -27,6 +28,9 @@ static pin_t encoders_pad[] = ENCODERS_PAD_A;
# include "i2c_slave.h"

typedef struct _I2C_slave_buffer_t {
# ifndef DISABLE_SYNC_TIMER
uint32_t sync_timer;
# endif
matrix_row_t smatrix[ROWS_PER_HAND];
uint8_t backlight_level;
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
Expand All @@ -44,6 +48,7 @@ static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_re

# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)
# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
# define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer)
# define I2C_KEYMAP_START offsetof(I2C_slave_buffer_t, smatrix)
# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm)
Expand Down Expand Up @@ -91,10 +96,18 @@ bool transport_master(matrix_row_t matrix[]) {
}
}
# endif

# ifndef DISABLE_SYNC_TIMER
i2c_buffer->sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_SYNC_TIME_START, (void *)&i2c_buffer->sync_timer, sizeof(i2c_buffer->sync_timer), TIMEOUT);
# endif
return true;
}

void transport_slave(matrix_row_t matrix[]) {
# ifndef DISABLE_SYNC_TIMER
sync_timer_update(i2c_buffer->sync_timer);
# endif
// Copy matrix to I2C buffer
memcpy((void *)i2c_buffer->smatrix, (void *)matrix, sizeof(i2c_buffer->smatrix));

Expand Down Expand Up @@ -133,12 +146,15 @@ typedef struct _Serial_s2m_buffer_t {
matrix_row_t smatrix[ROWS_PER_HAND];

# ifdef ENCODER_ENABLE
uint8_t encoder_state[NUMBER_OF_ENCODERS];
uint8_t encoder_state[NUMBER_OF_ENCODERS];
# endif

} Serial_s2m_buffer_t;

typedef struct _Serial_m2s_buffer_t {
# ifndef DISABLE_SYNC_TIMER
uint32_t sync_timer;
# endif
# ifdef BACKLIGHT_ENABLE
uint8_t backlight_level;
# endif
Expand Down Expand Up @@ -251,11 +267,19 @@ bool transport_master(matrix_row_t matrix[]) {
// Write wpm to slave
serial_m2s_buffer.current_wpm = get_current_wpm();
# endif

# ifndef DISABLE_SYNC_TIMER
serial_m2s_buffer.sync_timer = sync_timer_read32() + SYNC_TIMER_OFFSET;
# endif
return true;
}

void transport_slave(matrix_row_t matrix[]) {
transport_rgblight_slave();
# ifndef DISABLE_SYNC_TIMER
sync_timer_update(serial_m2s_buffer.sync_timer);
# endif

// TODO: if MATRIX_COLS > 8 change to pack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
serial_s2m_buffer.smatrix[i] = matrix[i];
Expand Down
1 change: 1 addition & 0 deletions tmk_core/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ TMK_COMMON_SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/report.c \
$(PLATFORM_COMMON_DIR)/suspend.c \
$(PLATFORM_COMMON_DIR)/timer.c \
$(COMMON_DIR)/sync_timer.c \
$(PLATFORM_COMMON_DIR)/bootloader.c \

ifeq ($(PLATFORM),AVR)
Expand Down
2 changes: 2 additions & 0 deletions tmk_core/common/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "led.h"
#include "keycode.h"
#include "timer.h"
#include "sync_timer.h"
#include "print.h"
#include "debug.h"
#include "command.h"
Expand Down Expand Up @@ -255,6 +256,7 @@ __attribute__((weak)) void housekeeping_task_user(void) {}
*/
void keyboard_init(void) {
timer_init();
sync_timer_init();
matrix_init();
#ifdef VIA_ENABLE
via_init();
Expand Down
58 changes: 58 additions & 0 deletions tmk_core/common/sync_timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
If you happen to meet one of the copyright holders in a bar you are obligated
to buy them one pint of beer.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "sync_timer.h"
#include "keyboard.h"

#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
volatile int32_t sync_timer_ms;

void sync_timer_init(void) { sync_timer_ms = 0; }

void sync_timer_update(uint32_t time) {
if (is_keyboard_master()) return;
sync_timer_ms = time - timer_read32();
}

uint16_t sync_timer_read(void) {
if (is_keyboard_master()) return timer_read();
return sync_timer_read32();
}

uint32_t sync_timer_read32(void) {
if (is_keyboard_master()) return timer_read32();
return sync_timer_ms + timer_read32();
}

uint16_t sync_timer_elapsed(uint16_t last) {
if (is_keyboard_master()) return timer_elapsed(last);
return TIMER_DIFF_16(sync_timer_read(), last);
}

uint32_t sync_timer_elapsed32(uint32_t last) {
if (is_keyboard_master()) return timer_elapsed32(last);
return TIMER_DIFF_32(sync_timer_read32(), last);
}
#endif
54 changes: 54 additions & 0 deletions tmk_core/common/sync_timer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright (C) 2020 Ryan Caltabiano <https://github.com/XScorpion2>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
If you happen to meet one of the copyright holders in a bar you are obligated
to buy them one pint of beer.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#pragma once

#include <stdint.h>
#include "timer.h"

#ifdef __cplusplus
extern "C" {
#endif

#if defined(SPLIT_KEYBOARD) && !defined(DISABLE_SYNC_TIMER)
void sync_timer_init(void);
void sync_timer_update(uint32_t time);
uint16_t sync_timer_read(void);
uint32_t sync_timer_read32(void);
uint16_t sync_timer_elapsed(uint16_t last);
uint32_t sync_timer_elapsed32(uint32_t last);
#else
# define sync_timer_init()
# define sync_timer_clear()
# define sync_timer_update(t)
# define sync_timer_read() timer_read()
# define sync_timer_read32() timer_read32()
# define sync_timer_elapsed(t) timer_elapsed(t)
# define sync_timer_elapsed32(t) timer_elapsed32(t)
#endif

#ifdef __cplusplus
}
#endif

0 comments on commit a8d0ec0

Please sign in to comment.