Drashna's split updates (#13350)

Co-authored-by: Ryan <fauxpark@gmail.com>
This commit is contained in:
Drashna Jaelre 2021-07-01 00:42:32 -07:00 committed by GitHub
parent bbe45185e3
commit b7cf9a888a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 1889 additions and 1819 deletions

View File

@ -1,17 +0,0 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// placeholder

View File

@ -1,4 +0,0 @@
USER_NAME := drashna
SRC += ../drashna/keymap.c
include $(KEYBOARD_PATH_1)/keymaps/drashna/rules.mk

View File

@ -1,616 +0,0 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stddef.h>
#include "matrix.h"
#include QMK_KEYBOARD_H
#define ROWS_PER_HAND (MATRIX_ROWS / 2)
#define SYNC_TIMER_OFFSET 2
#ifdef RGBLIGHT_ENABLE
# include "rgblight.h"
#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif
#ifdef ENCODER_ENABLE
# include "encoder.h"
static pin_t encoders_pad[] = ENCODERS_PAD_A;
# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))
#endif
#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
# include "led_matrix.h"
#endif
#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
# include "rgb_matrix.h"
#endif
#ifdef POINTING_DEVICE_ENABLE
static uint16_t device_cpi = 0;
static int8_t split_mouse_x = 0, split_mouse_y = 0;
#endif
#ifdef OLED_DRIVER_ENABLE
# include "oled_driver.h"
#endif
#if defined(USE_I2C)
# include "i2c_master.h"
# include "i2c_slave.h"
typedef struct _I2C_slave_buffer_t {
# ifndef DISABLE_SYNC_TIMER
uint32_t sync_timer;
# endif
# ifdef SPLIT_TRANSPORT_MIRROR
matrix_row_t mmatrix[ROWS_PER_HAND];
# endif
matrix_row_t smatrix[ROWS_PER_HAND];
# ifdef SPLIT_MODS_ENABLE
uint8_t real_mods;
uint8_t weak_mods;
# ifndef NO_ACTION_ONESHOT
uint8_t oneshot_mods;
# endif
# endif
# ifdef BACKLIGHT_ENABLE
uint8_t backlight_level;
# endif
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
rgblight_syncinfo_t rgblight_sync;
# endif
# ifdef ENCODER_ENABLE
uint8_t encoder_state[NUMBER_OF_ENCODERS];
# endif
# ifdef WPM_ENABLE
uint8_t current_wpm;
# endif
int8_t mouse_x;
int8_t mouse_y;
uint16_t device_cpi;
bool oled_on;
layer_state_t t_layer_state;
layer_state_t t_default_layer_state;
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
led_eeconfig_t led_matrix;
bool led_suspend_state;
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
rgb_config_t rgb_matrix;
bool rgb_suspend_state;
# endif
} __attribute__((packed)) I2C_slave_buffer_t;
static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg;
# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)
# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
# define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix)
# define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix)
# define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer)
# define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods)
# define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods)
# define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods)
# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm)
# define I2C_MOUSE_X_START offsetof(I2C_slave_buffer_t, mouse_x)
# define I2C_MOUSE_Y_START offsetof(I2C_slave_buffer_t, mouse_y)
# define I2C_MOUSE_DPI_START offsetof(I2C_slave_buffer_t, device_cpi)
# define I2C_OLED_ON_START offsetof(I2C_slave_buffer_t, oled_on)
# define I2C_LAYER_STATE_START offsetof(I2C_slave_buffer_t, t_layer_state)
# define I2C_DEFAULT_LAYER_STATE_START offsetof(I2C_slave_buffer_t, t_default_layer_state)
# define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix)
# define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state)
# define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix)
# define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state)
# define TIMEOUT 100
# ifndef SLAVE_I2C_ADDRESS
# define SLAVE_I2C_ADDRESS 0x32
# endif
// Get rows from other half over i2c
bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT);
# ifdef SPLIT_TRANSPORT_MIRROR
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT);
# endif
// write backlight info
# ifdef BACKLIGHT_ENABLE
uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0;
if (level != i2c_buffer->backlight_level) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
i2c_buffer->backlight_level = level;
}
}
# endif
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
if (rgblight_get_change_flags()) {
rgblight_syncinfo_t rgblight_sync;
rgblight_get_syncinfo(&rgblight_sync);
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) {
rgblight_clear_change_flags();
}
}
# endif
# ifdef ENCODER_ENABLE
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT);
encoder_update_raw(i2c_buffer->encoder_state);
# endif
# ifdef WPM_ENABLE
uint8_t current_wpm = get_current_wpm();
if (current_wpm != i2c_buffer->current_wpm) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)&current_wpm, sizeof(current_wpm), TIMEOUT) >= 0) {
i2c_buffer->current_wpm = current_wpm;
}
}
# endif
# ifdef POINTING_DEVICE_ENABLE
if (is_keyboard_left()) {
report_mouse_t temp_report = pointing_device_get_report();
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT);
temp_report.x = i2c_buffer->mouse_x;
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT);
temp_report.y = i2c_buffer->mouse_y;
pointing_device_set_report(temp_report);
if (device_cpi != i2c_buffer->device_cpi) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_DPI_START, (void *)&device_cpi, sizeof(device_cpi), TIMEOUT) >= 0) {
i2c_buffer->device_cpi = device_cpi
}
}
}
# endif
# ifdef SPLIT_MODS_ENABLE
uint8_t real_mods = get_mods();
if (real_mods != i2c_buffer->real_mods) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) {
i2c_buffer->real_mods = real_mods;
}
}
uint8_t weak_mods = get_weak_mods();
if (weak_mods != i2c_buffer->weak_mods) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) {
i2c_buffer->weak_mods = weak_mods;
}
}
# ifndef NO_ACTION_ONESHOT
uint8_t oneshot_mods = get_oneshot_mods();
if (oneshot_mods != i2c_buffer->oneshot_mods) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) {
i2c_buffer->oneshot_mods = oneshot_mods;
}
}
# endif
# endif
if (layer_state != i2c_buffer->t_layer_state) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LAYER_STATE_START, (void *)&layer_state, sizeof(layer_state), TIMEOUT) >= 0) {
i2c_buffer->t_layer_state = layer_state;
}
}
if (default_layer_state != i2c_buffer->t_default_layer_state) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_DEFAULT_LAYER_STATE_START, (void *)&default_layer_state, sizeof(default_layer_state), TIMEOUT) >= 0) {
i2c_buffer->t_default_layer_state = default_layer_state;
}
}
# ifdef OLED_DRIVER_ENABLE
bool is_oled_on = is_oled_on();
if (is_oled_on != i2c_buffer->oled_on) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LAYER_STATE_START, (void *)&is_oled_on, sizeof(is_oled_on), TIMEOUT) >= 0) {
i2c_buffer->oled_on = is_oled_on;
}
}
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT);
bool suspend_state = led_matrix_get_suspend_state();
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT);
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT);
bool suspend_state = rgb_matrix_get_suspend_state();
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT);
# 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 master_matrix[], matrix_row_t slave_matrix[]) {
# ifndef DISABLE_SYNC_TIMER
sync_timer_update(i2c_buffer->sync_timer);
# endif
// Copy matrix to I2C buffer
memcpy((void *)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix));
# ifdef SPLIT_TRANSPORT_MIRROR
memcpy((void *)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix));
# endif
// Read Backlight Info
# ifdef BACKLIGHT_ENABLE
backlight_set(i2c_buffer->backlight_level);
# endif
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// Update the RGB with the new data
if (i2c_buffer->rgblight_sync.status.change_flags != 0) {
rgblight_update_sync(&i2c_buffer->rgblight_sync, false);
i2c_buffer->rgblight_sync.status.change_flags = 0;
}
# endif
# ifdef ENCODER_ENABLE
encoder_state_raw(i2c_buffer->encoder_state);
# endif
# ifdef WPM_ENABLE
set_current_wpm(i2c_buffer->current_wpm);
# endif
# ifdef POINTING_DEVICE_ENABLE
if (!is_keyboard_left()) {
static uint16_t cpi;
if (cpi != i2c_buffer->device_cpi) {
cpi = i2c_buffer->device_cpi;
pmw_set_cpi(cpi);
}
i2c_buffer->mouse_x = split_mouse_x;
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT);
i2c_buffer->mouse_y = split_mouse_y;
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT);
}
# endif
# ifdef SPLIT_MODS_ENABLE
set_mods(i2c_buffer->real_mods);
set_weak_mods(i2c_buffer->weak_mods);
# ifndef NO_ACTION_ONESHOT
set_oneshot_mods(i2c_buffer->oneshot_mods);
# endif
# endif
if (layer_state != i2c_buffer->t_layer_state) {
layer_state = i2c_buffer->t_layer_state;
}
if (default_layer_state != i2c_buffer->t_default_layer_state) {
default_layer_state = i2c_buffer->t_default_layer_state;
}
# ifdef OLED_DRIVER_ENABLE
if (i2c_buffer->oled_on) {
oled_on();
} else {
oled_off();
}
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix));
led_matrix_set_suspend_state(i2c_buffer->led_suspend_state);
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix));
rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state);
# endif
}
void transport_master_init(void) { i2c_init(); }
void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
#else // USE_SERIAL
# include "serial.h"
typedef struct _Serial_s2m_buffer_t {
// TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
matrix_row_t smatrix[ROWS_PER_HAND];
# ifdef ENCODER_ENABLE
uint8_t encoder_state[NUMBER_OF_ENCODERS];
# endif
int8_t mouse_x;
int8_t mouse_y;
} __attribute__((packed)) Serial_s2m_buffer_t;
typedef struct _Serial_m2s_buffer_t {
# ifdef SPLIT_MODS_ENABLE
uint8_t real_mods;
uint8_t weak_mods;
# ifndef NO_ACTION_ONESHOT
uint8_t oneshot_mods;
# endif
# endif
# ifndef DISABLE_SYNC_TIMER
uint32_t sync_timer;
# endif
# ifdef SPLIT_TRANSPORT_MIRROR
matrix_row_t mmatrix[ROWS_PER_HAND];
# endif
# ifdef BACKLIGHT_ENABLE
uint8_t backlight_level;
# endif
# ifdef WPM_ENABLE
uint8_t current_wpm;
# endif
uint16_t device_cpi;
bool oled_on;
layer_state_t t_layer_state;
layer_state_t t_default_layer_state;
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
led_eeconfig_t led_matrix;
bool led_suspend_state;
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
rgb_config_t rgb_matrix;
bool rgb_suspend_state;
# endif
} __attribute__((packed)) Serial_m2s_buffer_t;
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// When MCUs on both sides drive their respective RGB LED chains,
// it is necessary to synchronize, so it is necessary to communicate RGB
// information. In that case, define RGBLIGHT_SPLIT with info on the number
// of LEDs on each half.
//
// Otherwise, if the master side MCU drives both sides RGB LED chains,
// there is no need to communicate.
typedef struct _Serial_rgblight_t {
rgblight_syncinfo_t rgblight_sync;
} Serial_rgblight_t;
volatile Serial_rgblight_t serial_rgblight = {};
uint8_t volatile status_rgblight = 0;
# endif
volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
uint8_t volatile status0 = 0;
enum serial_transaction_id {
GET_SLAVE_MATRIX = 0,
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
PUT_RGBLIGHT,
# endif
};
SSTD_t transactions[] = {
[GET_SLAVE_MATRIX] =
{
(uint8_t *)&status0,
sizeof(serial_m2s_buffer),
(uint8_t *)&serial_m2s_buffer,
sizeof(serial_s2m_buffer),
(uint8_t *)&serial_s2m_buffer,
},
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
[PUT_RGBLIGHT] =
{
(uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer
},
# endif
};
void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// rgblight synchronization information communication.
void transport_rgblight_master(void) {
if (rgblight_get_change_flags()) {
rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync);
if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) {
rgblight_clear_change_flags();
}
}
}
void transport_rgblight_slave(void) {
if (status_rgblight == TRANSACTION_ACCEPTED) {
rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false);
status_rgblight = TRANSACTION_END;
}
}
# else
# define transport_rgblight_master()
# define transport_rgblight_slave()
# endif
bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
# ifndef SERIAL_USE_MULTI_TRANSACTION
if (soft_serial_transaction() != TRANSACTION_END) {
return false;
}
# else
transport_rgblight_master();
if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) {
return false;
}
# endif
// TODO: if MATRIX_COLS > 8 change to unpack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
slave_matrix[i] = serial_s2m_buffer.smatrix[i];
# ifdef SPLIT_TRANSPORT_MIRROR
serial_m2s_buffer.mmatrix[i] = master_matrix[i];
# endif
}
# ifdef BACKLIGHT_ENABLE
// Write backlight level for slave to read
serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0;
# endif
# ifdef ENCODER_ENABLE
encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state);
# endif
# ifdef WPM_ENABLE
// Write wpm to slave
serial_m2s_buffer.current_wpm = get_current_wpm();
# endif
# ifdef SPLIT_MODS_ENABLE
serial_m2s_buffer.real_mods = get_mods();
serial_m2s_buffer.weak_mods = get_weak_mods();
# ifndef NO_ACTION_ONESHOT
serial_m2s_buffer.oneshot_mods = get_oneshot_mods();
# endif
# endif
# ifdef POINTING_DEVICE_ENABLE
if (is_keyboard_left()) {
report_mouse_t temp_report = pointing_device_get_report();
temp_report.x = serial_s2m_buffer.mouse_x;
temp_report.y = serial_s2m_buffer.mouse_y;
pointing_device_set_report(temp_report);
serial_m2s_buffer.device_cpi = device_cpi;
}
# endif
serial_m2s_buffer.t_layer_state = layer_state;
serial_m2s_buffer.t_default_layer_state = default_layer_state;
# ifdef OLED_DRIVER_ENABLE
serial_m2s_buffer.oled_on = is_oled_on();
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
serial_m2s_buffer.led_matrix = led_matrix_eeconfig;
serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state();
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
serial_m2s_buffer.rgb_matrix = rgb_matrix_config;
serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state();
# 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 master_matrix[], matrix_row_t slave_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] = slave_matrix[i];
# ifdef SPLIT_TRANSPORT_MIRROR
master_matrix[i] = serial_m2s_buffer.mmatrix[i];
# endif
}
# ifdef BACKLIGHT_ENABLE
backlight_set(serial_m2s_buffer.backlight_level);
# endif
# ifdef ENCODER_ENABLE
encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state);
# endif
# ifdef WPM_ENABLE
set_current_wpm(serial_m2s_buffer.current_wpm);
# endif
# ifdef SPLIT_MODS_ENABLE
set_mods(serial_m2s_buffer.real_mods);
set_weak_mods(serial_m2s_buffer.weak_mods);
# ifndef NO_ACTION_ONESHOT
set_oneshot_mods(serial_m2s_buffer.oneshot_mods);
# endif
# endif
# ifdef POINTING_DEVICE_ENABLE
if (!is_keyboard_left()) {
static uint16_t cpi;
if (cpi != serial_m2s_buffer.device_cpi) {
cpi = serial_m2s_buffer.device_cpi;
pmw_set_cpi(cpi);
}
serial_s2m_buffer.mouse_x = split_mouse_x;
serial_s2m_buffer.mouse_y = split_mouse_y;
}
# endif
if (layer_state != serial_m2s_buffer.t_layer_state) {
layer_state = serial_m2s_buffer.t_layer_state;
}
if (default_layer_state != serial_m2s_buffer.t_default_layer_state) {
default_layer_state = serial_m2s_buffer.t_default_layer_state;
}
# ifdef OLED_DRIVER_ENABLE
if (serial_m2s_buffer.oled_on) {
oled_on();
} else {
oled_off();
}
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
led_matrix_eeconfig = serial_m2s_buffer.led_matrix;
led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state);
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
rgb_matrix_config = serial_m2s_buffer.rgb_matrix;
rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state);
# endif
}
#endif
#ifdef POINTING_DEVICE_ENABLE
void master_mouse_send(int8_t x, int8_t y) {
split_mouse_x = x;
split_mouse_y = y;
}
void trackball_set_cpi(uint16_t cpi) {
if (!is_keyboard_left()) {
pmw_set_cpi(cpi);
} else {
device_cpi = cpi;
}
}
#endif

View File

@ -16,8 +16,6 @@
#include "6x6.h"
#elif KEYBOARD_handwired_dactyl_manuform_dmote_62key
#include "62key.h"
#elif KEYBOARD_handwired_dactyl_manuform_5x6_right_trackball
# include "5x6_right_trackball.h"
#endif
#include "quantum.h"

View File

@ -0,0 +1,67 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "4x6_right.h"
#ifdef RGB_MATRIX_ENABLE
led_config_t g_led_config = { {
{ 24, 23, 18, 17, 10, 9 },
{ 25, 22, 19, 16, 11, 8 },
{ 26, 21, 20, 15, 12, 7 },
{ NO_LED, NO_LED, NO_LED, 14, 13, 6 },
{ NO_LED, NO_LED, NO_LED, 14, 13, 6 },
{ 51, 50, 45, 44, 37, 36 },
{ 52, 49, 46, 43, 38, 35 },
{ 53, 48, 47, 42, 39, 34 },
{ NO_LED, NO_LED, NO_LED, 41, 40, 33 },
{ NO_LED, NO_LED, NO_LED, 41, 40, 33 }
}, {
{ 85, 16 }, { 50, 13 }, { 16, 20 }, { 16, 38 }, { 50, 48 }, { 85, 52 }, { 95, 63 },
{ 85, 39 }, { 85, 21 }, { 85, 4 }, { 68, 2 }, { 68, 19 }, { 68, 37 }, { 80, 58 },
{ 60, 55 }, { 50, 35 }, { 50, 13 }, { 50, 0 }, { 33, 3 }, { 33, 20 }, { 33, 37 },
{ 16, 42 }, { 16, 24 }, { 16, 7 }, { 0, 7 }, { 0, 24 }, { 0, 41 }, { 139, 16 },
{ 174, 13 }, { 208, 20 }, { 208, 38 }, { 174, 48 }, { 139, 52 }, { 129, 63 }, { 139, 39 },
{ 139, 21 }, { 139, 4 }, { 156, 2 }, { 156, 19 }, { 156, 37 }, { 144, 58 }, { 164, 55 },
{ 174, 35 }, { 174, 13 }, { 174, 0 }, { 191, 3 }, { 191, 20 }, { 191, 37 }, { 208, 42 },
{ 208, 24 }, { 208, 7 }, { 224, 7 }, { 224, 24 }, { 224, 41 }
}, {
2, 2, 2, 2, 2, 2, 1,
4, 4, 4, 4, 4, 4, 1,
1, 4, 4, 4, 4, 4, 4,
4, 4, 4, 1, 1, 1, 2,
2, 2, 2, 2, 2, 1, 4,
4, 4, 4, 4, 4, 1, 1,
4, 4, 4, 4, 4, 4, 4,
4, 4, 1, 1, 1
} };
#endif
#ifdef SWAP_HANDS_ENABLE
const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
/* Left hand, matrix positions */
{{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}},
{{5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}},
{{5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7}, {0, 7}},
{{5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8}},
{{5, 9}, {4, 9}, {3, 9}, {2, 9}, {1, 9}, {0, 9}},
/* Right hand, matrix positions */
{{5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
{{5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
{{5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
{{5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
{{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}
};
#endif

View File

@ -0,0 +1,47 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "tractyl_manuform.h"
#include "quantum.h"
#define ___ KC_NO
// clang-format off
#define LAYOUT_4x6_right(\
L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
L32, L33, R32, R33, \
L34, L35, R31, \
L44, L45, R41, \
L42, L43, R42, R43 \
) \
{ \
{ L00, L01, L02, L03, L04, L05 }, \
{ L10, L11, L12, L13, L14, L15 }, \
{ L20, L21, L22, L23, L24, L25 }, \
{ ___, ___, L32, L33, L34, L35 }, \
{ ___, ___, L42, L43, L44, L45 }, \
\
{ R00, R01, R02, R03, R04, R05 }, \
{ R10, R11, R12, R13, R14, R15 }, \
{ R20, R21, R22, R23, R24, R25 }, \
{ ___, R31, R32, R33, ___, ___ }, \
{ ___, R41, R42, R43, ___, ___ } \
}
// clang-format on

View File

@ -0,0 +1,91 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "config_common.h"
#define PRODUCT_ID 0x3537
#define DEVICE_VER 0x0001
#define PRODUCT Tractyl Manuform(4x6)
/* key matrix size */
// Rows are doubled-up
#define MATRIX_ROWS 10
#define MATRIX_COLS 6
// wiring of each half
#define MATRIX_COL_PINS { C0, C1, C2, C3, C4, C5 }
#define MATRIX_ROW_PINS { A0, A1, A2, A3, A4 }
#define DIODE_DIRECTION COL2ROW
// WS2812 RGB LED strip input and number of LEDs
#define RGB_DI_PIN E7
#define DRIVER_LED_TOTAL 62
#define RGB_MATRIX_SPLIT { 32, 30 }
#define RGB_DISABLE_WHEN_USB_SUSPENDED true
#define RGB_MATRIX_KEYPRESSES
// #define RGB_MATRIX_KEYRELEASES
#define RGB_MATRIX_FRAMEBUFFER_EFFECTS
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 80
#define SPLIT_TRANSPORT_MIRROR
#define SPLIT_HAND_PIN A6
/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST
/* number of backlight levels */
// #define BACKLIGHT_LEVELS 3
// #define DEBUG_LED_PIN D6
#define ROTATIONAL_TRANSFORM_ANGLE -25
/* Bootmagic Lite key configuration */
#define BOOTMAGIC_LITE_ROW 0
#define BOOTMAGIC_LITE_COLUMN 0
#define BOOTMAGIC_LITE_ROW_RIGHT 4
#define BOOTMAGIC_LITE_COLUMN_RIGHT 5
#define AUDIO_PIN C6
#define AUDIO_PIN_ALT B7
#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095
#define DYNAMIC_KEYMAP_LAYER_COUNT 16
#define LAYER_STATE_16BIT
/* serial.c configuration for split keyboard */
#define SOFT_SERIAL_PIN D3
#define EE_HANDS
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
#define SERIAL_USE_MULTI_TRANSACTION
#define SPLIT_TRANSACTION_IDS_KB RPC_ID_STATE_SYNC, RPC_ID_SLAVE_STATE

View File

@ -1,11 +1,11 @@
{
"keyboard_name": "Dactyl Manuform 5x6",
"keyboard_name": "Tractyl Manuform 4x6",
"url": "",
"maintainer": "qmk",
"maintainer": "drashna",
"width": 17,
"height": 8,
"layouts": {
"LAYOUT_5x6_right_trackball": {
"LAYOUT_5x6_right": {
"layout": [
{"label":"L00", "x":0, "y":0},
{"label":"L01", "x":1, "y":0},

View File

@ -0,0 +1,62 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
enum custom_layers {
_QWERTY,
_LOWER,
_RAISE,
};
#define RAISE MO(_RAISE)
#define LOWER MO(_LOWER)
#define RAISE MO(_RAISE)
#define LOWER MO(_LOWER)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_4x6_right(
KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_MINS,
KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,KC_BSLASH,
KC_LBRC,KC_RBRC, KC_PLUS, KC_EQL,
RAISE, KC_SPC, LOWER,
KC_TAB, KC_HOME, KC_ENT,
KC_BSPC,KC_GRV, KC_LGUI,KC_DEL
),
[_LOWER] = LAYOUT_4x6_right(
_______,_______,_______,_______,_______,KC_LBRC, KC_RBRC, KC_P7, KC_P8, KC_P9, RESET, KC_PLUS,
_______,KC_HOME,KC_PGUP,KC_PGDN,KC_END ,KC_LPRN, KC_RPRN, KC_P4, KC_P5, KC_P6, KC_MINS,KC_PIPE,
_______,_______,_______,_______,_______,_______, _______, KC_P1, KC_P2, KC_P3, KC_EQL, KC_UNDS,
_______,KC_PSCR, _______, KC_P0,
_______,_______, _______,
_______,_______, _______,
_______,_______, _______,_______
),
[_RAISE] = LAYOUT_4x6_right(
_______,RESET, _______,_______,_______,KC_LBRC, KC_RBRC,_______,KC_NLCK,KC_INS, KC_SLCK,KC_MUTE,
_______,KC_LEFT,KC_UP ,KC_DOWN,KC_RGHT,KC_LPRN, KC_RPRN,KC_MPRV,KC_MPLY,KC_MNXT,_______,KC_VOLU,
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,KC_VOLD,
_______,_______, KC_EQL ,_______,
_______,_______, _______,
_______,_______, _______,
_______,_______, _______,_______
),
};

View File

@ -17,13 +17,12 @@
#pragma once
// #define USE_I2C
#define SELECT_SOFT_SERIAL_SPEED 0
// #define SELECT_SOFT_SERIAL_SPEED 1
// #define SERIAL_USE_MULTI_TRANSACTION
#define SPLIT_MODS_ENABLE
#define EE_HANDS
#define TRACKBALL_DPI_OPTIONS \
{ 1200, 1800, 2600, 3400 }
#define TRACKBALL_DPI_OPTIONS { 1200, 1800, 2600, 3400 }
#define RGBLIGHT_MAX_BRIGHTNESS 60
@ -35,5 +34,3 @@
#define OLED_DISPLAY_128X64
#define OLED_BRIGHTNESS 50
#define MK_KINETIC_SPEED

View File

@ -0,0 +1,243 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "drashna.h"
// clang-format off
#define LAYOUT_4x6_right_wrapper(...) LAYOUT_4x6_right(__VA_ARGS__)
#define LAYOUT_4x6_right_base( \
K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, \
K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A \
) \
LAYOUT_4x6_right_wrapper( \
SH_TT, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, SH_TT, \
LALT_T(KC_TAB), K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, RALT_T(K1B), \
OS_LSFT, CTL_T(K21), K22, K23, K24, K25, K26, K27, K28, K29, RCTL_T(K2A), OS_RSFT, \
OS_LGUI, OS_LALT, OS_RGUI, OS_RALT, \
KC_PSCR, KC_GRV, MEH_T(KC_BTN3), \
KC_SPC, OS_LGUI, KC_ENT, \
BK_LWER, TT(_MOUSE), TT(_MOUSE), DL_RAIS \
)
#define LAYOUT_4x6_right_base_wrapper(...) LAYOUT_4x6_right_base(__VA_ARGS__)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_4x6_right_base_wrapper(
_________________QWERTY_L1_________________, _________________QWERTY_R1_________________,
_________________QWERTY_L2_________________, _________________QWERTY_R2_________________,
_________________QWERTY_L3_________________, _________________QWERTY_R3_________________
),
[_COLEMAK] = LAYOUT_4x6_right_base_wrapper(
_________________COLEMAK_L1________________, _________________COLEMAK_R1________________,
_________________COLEMAK_L2________________, _________________COLEMAK_R2________________,
_________________COLEMAK_L3________________, _________________COLEMAK_R3________________
),
[_DVORAK] = LAYOUT_4x6_right_base_wrapper(
_________________DVORAK_L1_________________, _________________DVORAK_R1_________________,
_________________DVORAK_L2_________________, _________________DVORAK_R2_________________,
_________________DVORAK_L3_________________, _________________DVORAK_R3_________________
),
[_WORKMAN] = LAYOUT_4x6_right_base_wrapper(
_________________WORKMAN_L1________________, _________________WORKMAN_R1________________,
_________________WORKMAN_L2________________, _________________WORKMAN_R2________________,
_________________WORKMAN_L3________________, _________________WORKMAN_R3________________
),
[_NORMAN] = LAYOUT_4x6_right_base_wrapper(
_________________NORMAN_L1_________________, _________________NORMAN_L1_________________,
_________________NORMAN_L2_________________, _________________NORMAN_R2_________________,
_________________NORMAN_L3_________________, _________________NORMAN_R3_________________
),
[_MALTRON] = LAYOUT_4x6_right_base_wrapper(
_________________MALTRON_L1________________, _________________MALTRON_R1________________,
_________________MALTRON_L2________________, _________________MALTRON_R2________________,
_________________MALTRON_L3________________, _________________MALTRON_R3________________
),
[_EUCALYN] = LAYOUT_4x6_right_base_wrapper(
_________________EUCALYN_L1________________, _________________EUCALYN_R1________________,
_________________EUCALYN_L2________________, _________________EUCALYN_R2________________,
_________________EUCALYN_L3________________, _________________EUCALYN_R3________________
),
[_CARPLAX] = LAYOUT_4x6_right_base_wrapper(
_____________CARPLAX_QFMLWY_L1_____________, _____________CARPLAX_QFMLWY_R1_____________,
_____________CARPLAX_QFMLWY_L2_____________, _____________CARPLAX_QFMLWY_R2_____________,
_____________CARPLAX_QFMLWY_L3_____________, _____________CARPLAX_QFMLWY_R3_____________
),
[_MOUSE] = LAYOUT_4x6_right(
_______, _______, _______, _______, _______, _______, KC_WH_U, _______, _______, _______, DPI_CONFIG, _______,
_______, _______, _______, _______, _______, _______, KC_WH_D, KC_BTN1, KC_BTN3, KC_BTN2, KC_BTN6, _______,
_______, _______, _______, _______, _______, _______, KC_BTN7, KC_BTN4, KC_BTN5, KC_BTN8, _______, _______,
_______, _______, _______, _______,
_______, _______, _______,
_______, _______, _______,
_______, _______, _______, _______
),
[_GAMEPAD] = LAYOUT_4x6_right(
KC_F1, KC_K, KC_Q, KC_W, KC_E, KC_R, _______, _______, _______, _______, _______, _______,
KC_TAB, KC_G, KC_A, KC_S, KC_D, KC_F, _______, _______, _______, _______, _______, _______,
KC_LCTL, KC_LSFT, KC_Z, KC_X, KC_C, KC_H, _______, _______, _______, _______, _______, _______,
KC_I, KC_T, TG_GAME, KC_NO,
KC_V, KC_O, _______,
KC_SPC, KC_P, _______,
KC_H, KC_LGUI, _______, _______
),
[_DIABLO] = LAYOUT_4x6_right(
KC_TAB, KC_S, KC_I, KC_F, KC_M, KC_T, _______, _______, _______, _______, _______, _______,
KC_Q, KC_1, KC_2, KC_3, KC_4, KC_G, _______, _______, _______, _______, _______, _______,
KC_LCTL, KC_D3_1, KC_D3_2, KC_D3_3, KC_D3_4, KC_Z, _______, _______, _______, _______, _______, _______,
KC_F, KC_L, KC_NO, TG_DBLO,
KC_DIABLO_CLEAR, KC_F, _______,
SFT_T(KC_SPC), KC_J, _______,
ALT_T(KC_Q), KC_LGUI, _______, _______
),
[_LOWER] = LAYOUT_4x6_right_wrapper(
KC_F12, _________________LOWER_L1__________________, _________________LOWER_R1__________________, KC_F11,
_______, _________________LOWER_L2__________________, _________________LOWER_R2__________________, KC_PIPE,
_______, _________________LOWER_L3__________________, _________________LOWER_R3__________________, _______,
_______, _______, _______, _______,
_______, _______, _______,
_______, _______, _______,
_______, _______, _______, _______
),
[_RAISE] = LAYOUT_4x6_right_wrapper(
KC_F12, _________________RAISE_L1__________________, _________________RAISE_R1__________________, KC_F11,
_______, _________________RAISE_L2__________________, _________________RAISE_R2__________________, KC_BSLS,
_______, _________________RAISE_L3__________________, _________________RAISE_R3__________________, _______,
_______, _______, _______, _______,
_______, _______, _______,
_______, _______, _______,
_______, _______, _______, _______
),
[_ADJUST] = LAYOUT_4x6_right_wrapper(
KC_MAKE, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, KC_RST,
VRSN, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, EEP_RST,
UC_MOD, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, TG_MODS,
HPT_DWLI, HPT_DWLD, TG_GAME, TG_DBLO,
HPT_TOG, HPT_BUZ, KC_NUKE,
_______, _______, _______,
_______, _______, KC_NUKE, _______
),
};
// clang-format on
#ifdef POINTING_DEVICE_ENABLE
static uint16_t mouse_timer = 0;
static uint16_t mouse_debounce_timer = 0;
static uint8_t mouse_keycode_tracker = 0;
bool tap_toggling = false;
void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y) {
if ((x || y) && timer_elapsed(mouse_timer) > 125) {
mouse_timer = timer_read();
if (!layer_state_is(_MOUSE) && !(layer_state_is(_GAMEPAD) || layer_state_is(_DIABLO)) && timer_elapsed(mouse_debounce_timer) > 125) {
layer_on(_MOUSE);
}
}
# ifdef TAPPING_TERM_PER_KEY
if (timer_elapsed(mouse_debounce_timer) > get_tapping_term(KC_BTN1, NULL)
# else
if (timer_elapsed(mouse_debounce_timer) > TAPPING_TERM
# endif
|| (layer_state_is(_GAMEPAD) || layer_state_is(_DIABLO))) {
mouse_report->x = x;
mouse_report->y = y;
}
# ifdef OLED_DRIVER_ENABLE
if (x || y) oled_timer = timer_read32();
# endif
}
void matrix_scan_keymap(void) {
if (timer_elapsed(mouse_timer) > 650 && layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) {
layer_off(_MOUSE);
}
if (tap_toggling) {
if (!layer_state_is(_MOUSE)) {
layer_on(_MOUSE);
}
}
}
bool process_record_keymap(uint16_t keycode, keyrecord_t* record) {
switch (keycode) {
case TT(_MOUSE): {
if (record->event.pressed) {
mouse_keycode_tracker++;
} else {
# if TAPPING_TOGGLE != 0
if (record->tap.count == TAPPING_TOGGLE) {
tap_toggling ^= 1;
# if TAPPING_TOGGLE == 1
if (!tap_toggling) mouse_keycode_tracker -= record->tap.count + 1;
# else
if (!tap_toggling) mouse_keycode_tracker -= record->tap.count;
# endif
} else {
mouse_keycode_tracker--;
}
# endif
}
mouse_timer = timer_read();
break;
}
case MO(_MOUSE):
case DPI_CONFIG:
case KC_MS_UP ... KC_MS_WH_RIGHT:
record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
mouse_timer = timer_read();
break;
default:
if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) {
layer_off(_MOUSE);
}
mouse_keycode_tracker = 0;
mouse_debounce_timer = timer_read();
break;
}
return true;
}
layer_state_t layer_state_set_keymap(layer_state_t state) {
if (layer_state_cmp(state, _GAMEPAD) || layer_state_cmp(state, _DIABLO)) {
state |= (1UL << _MOUSE);
}
return state;
}
#endif
void matrix_init_keymap(void) {
#ifdef AUDIO_ENABLE
extern audio_config_t audio_config;
if (!is_keyboard_master()) {
audio_stop_all();
audio_config.enable = false;
}
#endif
}
void keyboard_post_init_keymap(void) {
matrix_init_keymap();
}

View File

@ -1,6 +1,7 @@
RGBLIGHT_STARTUP_ANIMATION = yes
COMMAND_ENABLE = no
AUDIO_ENABLE = yes
HAPTIC_ENABLE = no
COMMAND_ENABLE = no
TAP_DANCE_ENABLE = yes
UNICODE_ENABLE = yes
OLED_DRIVER_ENABLE = yes

View File

@ -0,0 +1,33 @@
# MCU name
MCU = at90usb1286
# Bootloader selection
BOOTLOADER = atmel-dfu
# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration
MOUSEKEY_ENABLE = yes # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
BLUETOOTH_ENABLE = no # Enable Bluetooth
AUDIO_ENABLE = no # Audio output
RGB_MATRIX_ENABLE = no
RGB_MATRIX_DRIVER = WS2812
POINTING_DEVICE_ENABLE = yes
MOUSE_SHARED_EP = no
SPLIT_KEYBOARD = yes
SRC += drivers/sensors/pmw3360.c
QUANTUM_LIB_SRC += spi_master.c tm_sync.c

View File

@ -0,0 +1,35 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "5x6_right.h"
#ifdef SWAP_HANDS_ENABLE
const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
/* Left hand, matrix positions */
{{5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}},
{{5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7}, {0, 7}},
{{5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8}},
{{5, 9}, {4, 9}, {3, 9}, {2, 9}, {1, 9}, {0, 9}},
{{5, 10}, {4, 10}, {3, 10}, {2, 10}, {1, 10}, {0, 10}},
{{5, 11}, {4, 11}, {3, 11}, {2, 11}, {1, 11}, {0, 11}},
/* Right hand, matrix positions */
{{5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
{{5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
{{5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
{{5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
{{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}},
{{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}};
#endif

View File

@ -16,16 +16,13 @@
#pragma once
#include "dactyl_manuform.h"
#include "tractyl_manuform.h"
#include "quantum.h"
#include "spi_master.h"
#include "drivers/sensors/pmw3360.h"
#include "pointing_device.h"
#define ___ KC_NO
#define LAYOUT_5x6_right_trackball(\
// clang-format off
#define LAYOUT_5x6_right(\
L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
@ -50,24 +47,4 @@
{ ___, R41, R42, R43, ___, ___ }, \
{ ___, R51, R52, R53, ___, ___ } \
}
void process_wheel(report_mouse_t* mouse_report);
void process_wheel_user(report_mouse_t* mouse_report, int16_t h, int16_t v);
typedef union {
uint32_t raw;
struct {
uint8_t dpi_config;
};
} keyboard_config_t;
extern keyboard_config_t keyboard_config;
enum ploopy_keycodes {
DPI_CONFIG = SAFE_RANGE,
KEYMAP_SAFE_RANGE,
};
void master_mouse_send(int8_t x, int8_t y);
void trackball_set_cpi(uint16_t cpi);
// clang-format on

View File

@ -22,7 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define PRODUCT_ID 0x3536
#define DEVICE_VER 0x0001
#define PRODUCT Tractyl-Manuform (5x6 with right side Trackball)
#define PRODUCT Tractyl Manuform(5x6)
/* key matrix size */
// Rows are doubled-up
@ -42,7 +42,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define RGBLED_SPLIT { 30, 28 }
#define RGBLIGHT_SLEEP
// #define RGBW
#define RGBLIGHT_LIMIT_VAL 100
#define RGBLIGHT_LIMIT_VAL 50
/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST
@ -51,8 +51,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DEBUG_LED_PIN D6
#define USB_POLLING_INTERVAL_MS 1
#define ROTATIONAL_TRANSFORM_ANGLE -25
/* Bootmagic Lite key configuration */
@ -66,7 +64,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 4095
#define DYNAMIC_KEYMAP_LAYER_COUNT 16
#define LAYER_STATE_16BIT
/* serial.c configuration for split keyboard */
#undef SOFT_SERIAL_PIN
#define SOFT_SERIAL_PIN D2
#define EE_HANDS
#define ENCODERS_PAD_A { D5 }
#define ENCODERS_PAD_B { D6 }
#define ENCODER_RESOLUTION 1
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION
#define SERIAL_USE_MULTI_TRANSACTION
#define SPLIT_TRANSACTION_IDS_KB RPC_ID_STATE_SYNC, RPC_ID_SLAVE_STATE

View File

@ -0,0 +1,75 @@
{
"keyboard_name": "Tractyl Manuform 5x6",
"url": "",
"maintainer": "drashna",
"width": 17,
"height": 8,
"layouts": {
"LAYOUT_5x6_right": {
"layout": [
{"label":"L00", "x":0, "y":0},
{"label":"L01", "x":1, "y":0},
{"label":"L02", "x":2, "y":0},
{"label":"L03", "x":3, "y":0},
{"label":"L04", "x":4, "y":0},
{"label":"L05", "x":5, "y":0},
{"label":"R00", "x":11, "y":0},
{"label":"R01", "x":12, "y":0},
{"label":"R02", "x":13, "y":0},
{"label":"R03", "x":14, "y":0},
{"label":"R04", "x":15, "y":0},
{"label":"R05", "x":16, "y":0},
{"label":"L10", "x":0, "y":1},
{"label":"L11", "x":1, "y":1},
{"label":"L12", "x":2, "y":1},
{"label":"L13", "x":3, "y":1},
{"label":"L14", "x":4, "y":1},
{"label":"L15", "x":5, "y":1},
{"label":"R10", "x":11, "y":1},
{"label":"R11", "x":12, "y":1},
{"label":"R12", "x":13, "y":1},
{"label":"R13", "x":14, "y":1},
{"label":"R14", "x":15, "y":1},
{"label":"R15", "x":16, "y":1},
{"label":"L20", "x":0, "y":2},
{"label":"L21", "x":1, "y":2},
{"label":"L22", "x":2, "y":2},
{"label":"L23", "x":3, "y":2},
{"label":"L24", "x":4, "y":2},
{"label":"L25", "x":5, "y":2},
{"label":"R20", "x":11, "y":2},
{"label":"R21", "x":12, "y":2},
{"label":"R22", "x":13, "y":2},
{"label":"R23", "x":14, "y":2},
{"label":"R24", "x":15, "y":2},
{"label":"R25", "x":16, "y":2},
{"label":"L30", "x":0, "y":3},
{"label":"L31", "x":1, "y":3},
{"label":"L32", "x":2, "y":3},
{"label":"L33", "x":3, "y":3},
{"label":"L34", "x":4, "y":3},
{"label":"L35", "x":5, "y":3},
{"label":"R30", "x":11, "y":3},
{"label":"R31", "x":12, "y":3},
{"label":"R32", "x":13, "y":3},
{"label":"R33", "x":14, "y":3},
{"label":"R34", "x":15, "y":3},
{"label":"R35", "x":16, "y":3},
{"label":"L42", "x":2, "y":4},
{"label":"L43", "x":3, "y":4},
{"label":"R42", "x":13, "y":4},
{"label":"R43", "x":14, "y":4},
{"label":"L44", "x":4, "y":5},
{"label":"L45", "x":5, "y":5},
{"label":"R41", "x":12, "y":5},
{"label":"L54", "x":6, "y":6},
{"label":"L55", "x":7, "y":6},
{"label":"R51", "x":10, "y":6},
{"label":"L52", "x":6, "y":7},
{"label":"L53", "x":7, "y":7},
{"label":"R52", "x":9, "y":7},
{"label":"R53", "x":10, "y":7}
]
}
}
}

View File

@ -0,0 +1,63 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H
enum custom_layers {
_QWERTY,
_LOWER,
_RAISE,
};
#define RAISE MO(_RAISE)
#define LOWER MO(_LOWER)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_5x6_right(
KC_ESC , KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 ,KC_BSPC,
KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P ,KC_MINS,
KC_LSFT, KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L ,KC_SCLN,KC_QUOT,
KC_LCTL, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M ,KC_COMM,KC_DOT ,KC_SLSH,KC_BSLASH,
KC_LBRC,KC_RBRC, KC_PLUS, KC_EQL,
RAISE,KC_SPC, LOWER,
KC_TAB,KC_HOME, KC_DEL,
KC_BSPC, KC_GRV, KC_LGUI, KC_ENT
),
[_LOWER] = LAYOUT_5x6_right(
KC_TILD,KC_EXLM, KC_AT ,KC_HASH,KC_DLR ,KC_PERC, KC_CIRC,KC_AMPR,KC_ASTR,KC_LPRN,KC_RPRN,KC_DEL,
_______,_______,_______,_______,_______,KC_LBRC, KC_RBRC, KC_P7 , KC_P8 , KC_P9 ,_______,KC_PLUS,
_______,KC_HOME,KC_PGUP,KC_PGDN,KC_END ,KC_LPRN, KC_RPRN, KC_P4 , KC_P5 , KC_P6 ,KC_MINS,KC_PIPE,
_______,_______,_______,_______,_______,_______, _______, KC_P1 , KC_P2 , KC_P3 ,KC_EQL ,KC_UNDS,
_______,KC_PSCR, _______, KC_P0,
_______,_______, _______,
_______,_______, _______,
_______,_______, _______,_______
),
[_RAISE] = LAYOUT_5x6_right(
KC_F12 , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 ,KC_F10 ,KC_F11 ,
_______,_______,_______,_______,_______,KC_LBRC, KC_RBRC,_______,KC_NLCK,KC_INS ,KC_SLCK,KC_MUTE,
_______,KC_LEFT,KC_UP ,KC_DOWN,KC_RGHT,KC_LPRN, KC_RPRN,KC_MPRV,KC_MPLY,KC_MNXT,_______,KC_VOLU,
_______,_______,_______,_______,_______,_______, _______,_______,_______,_______,_______,KC_VOLD,
_______,_______, KC_EQL ,_______,
_______,_______, _______,
_______,_______, _______,
_______,_______, _______,_______
),
};

View File

@ -16,18 +16,21 @@
#pragma once
#ifndef MOUSEKEY_WHEEL_DELTA
# define MOUSEKEY_WHEEL_DELTA 1
#endif
#ifndef MOUSEKEY_WHEEL_DELAY
# define MOUSEKEY_WHEEL_DELAY 200
#endif
#ifndef MOUSEKEY_WHEEL_INTERVAL
# define MOUSEKEY_WHEEL_INTERVAL 50
#endif
#ifndef MOUSEKEY_WHEEL_MAX_SPEED
# define MOUSEKEY_WHEEL_MAX_SPEED 8
#endif
#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
# define MOUSEKEY_WHEEL_TIME_TO_MAX 80
#endif
// #define USE_I2C
// #define SELECT_SOFT_SERIAL_SPEED 1
// #define SERIAL_USE_MULTI_TRANSACTION
#define SPLIT_MODS_ENABLE
#define EE_HANDS
#define TRACKBALL_DPI_OPTIONS { 1200, 1800, 2600, 3400 }
#define RGBLIGHT_MAX_BRIGHTNESS 60
#undef DEBOUNCE
#define DEBOUNCE 10
#define SOLENOID_PIN F1
#define SOLENOID_DEFAULT_DWELL 8
#define OLED_DISPLAY_128X64
#define OLED_BRIGHTNESS 50

View File

@ -17,75 +17,75 @@
#include "drashna.h"
// clang-format off
#define LAYOUT_5x6_right_trackball_wrapper(...) LAYOUT_5x6_right_trackball(__VA_ARGS__)
#define LAYOUT_5x6_right_trackball_base( \
#define LAYOUT_5x6_right_wrapper(...) LAYOUT_5x6_right(__VA_ARGS__)
#define LAYOUT_5x6_right_base( \
K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, \
K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, \
K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A \
) \
LAYOUT_5x6_right_trackball_wrapper( \
KC_ESC, ________________NUMBER_LEFT________________, ________________NUMBER_RIGHT_______________, KC_MINS, \
LAYOUT_5x6_right_wrapper( \
KC_ESC, ________________NUMBER_LEFT________________, ________________NUMBER_RIGHT_______________, UC_IRNY, \
SH_TT, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, SH_TT, \
LALT_T(KC_TAB), K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, RALT_T(K1B), \
OS_LSFT, CTL_T(K21), K22, K23, K24, K25, K26, K27, K28, K29, RCTL_T(K2A), OS_RSFT, \
OS_LALT, OS_LGUI, TG_GAME, TG_DBLO, \
OS_LGUI, KC_GRV, OS_RGUI, \
OS_LGUI, OS_LALT, OS_RGUI, OS_RALT, \
KC_PSCR, KC_GRV, MEH_T(KC_BTN3), \
KC_SPC, OS_LGUI, KC_ENT, \
BK_LWER, TT(_MOUSE), TT(_MOUSE), DL_RAIS \
)
#define LAYOUT_5x6_right_trackball_base_wrapper(...) LAYOUT_5x6_right_trackball_base(__VA_ARGS__)
#define LAYOUT_5x6_right_base_wrapper(...) LAYOUT_5x6_right_base(__VA_ARGS__)
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT_5x6_right_trackball_base_wrapper(
[_QWERTY] = LAYOUT_5x6_right_base_wrapper(
_________________QWERTY_L1_________________, _________________QWERTY_R1_________________,
_________________QWERTY_L2_________________, _________________QWERTY_R2_________________,
_________________QWERTY_L3_________________, _________________QWERTY_R3_________________
),
[_COLEMAK] = LAYOUT_5x6_right_trackball_base_wrapper(
[_COLEMAK] = LAYOUT_5x6_right_base_wrapper(
_________________COLEMAK_L1________________, _________________COLEMAK_R1________________,
_________________COLEMAK_L2________________, _________________COLEMAK_R2________________,
_________________COLEMAK_L3________________, _________________COLEMAK_R3________________
),
[_DVORAK] = LAYOUT_5x6_right_trackball_base_wrapper(
[_DVORAK] = LAYOUT_5x6_right_base_wrapper(
_________________DVORAK_L1_________________, _________________DVORAK_R1_________________,
_________________DVORAK_L2_________________, _________________DVORAK_R2_________________,
_________________DVORAK_L3_________________, _________________DVORAK_R3_________________
),
[_WORKMAN] = LAYOUT_5x6_right_trackball_base_wrapper(
[_WORKMAN] = LAYOUT_5x6_right_base_wrapper(
_________________WORKMAN_L1________________, _________________WORKMAN_R1________________,
_________________WORKMAN_L2________________, _________________WORKMAN_R2________________,
_________________WORKMAN_L3________________, _________________WORKMAN_R3________________
),
[_NORMAN] = LAYOUT_5x6_right_trackball_base_wrapper(
[_NORMAN] = LAYOUT_5x6_right_base_wrapper(
_________________NORMAN_L1_________________, _________________NORMAN_L1_________________,
_________________NORMAN_L2_________________, _________________NORMAN_R2_________________,
_________________NORMAN_L3_________________, _________________NORMAN_R3_________________
),
[_MALTRON] = LAYOUT_5x6_right_trackball_base_wrapper(
[_MALTRON] = LAYOUT_5x6_right_base_wrapper(
_________________MALTRON_L1________________, _________________MALTRON_R1________________,
_________________MALTRON_L2________________, _________________MALTRON_R2________________,
_________________MALTRON_L3________________, _________________MALTRON_R3________________
),
[_EUCALYN] = LAYOUT_5x6_right_trackball_base_wrapper(
[_EUCALYN] = LAYOUT_5x6_right_base_wrapper(
_________________EUCALYN_L1________________, _________________EUCALYN_R1________________,
_________________EUCALYN_L2________________, _________________EUCALYN_R2________________,
_________________EUCALYN_L3________________, _________________EUCALYN_R3________________
),
[_CARPLAX] = LAYOUT_5x6_right_trackball_base_wrapper(
[_CARPLAX] = LAYOUT_5x6_right_base_wrapper(
_____________CARPLAX_QFMLWY_L1_____________, _____________CARPLAX_QFMLWY_R1_____________,
_____________CARPLAX_QFMLWY_L2_____________, _____________CARPLAX_QFMLWY_R2_____________,
_____________CARPLAX_QFMLWY_L3_____________, _____________CARPLAX_QFMLWY_R3_____________
),
[_MOUSE] = LAYOUT_5x6_right_trackball(
[_MOUSE] = LAYOUT_5x6_right(
_______, _______, _______, _______, _______, _______, DPI_CONFIG, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, KC_WH_U, _______, _______, _______, _______, _______,
_______, _______, _______, _______, _______, _______, KC_WH_D, KC_BTN1, KC_BTN3, KC_BTN2, KC_BTN6, _______,
@ -95,7 +95,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______,
_______, _______, _______, _______
),
[_GAMEPAD] = LAYOUT_5x6_right_trackball(
[_GAMEPAD] = LAYOUT_5x6_right(
KC_ESC, KC_NO, KC_1, KC_2, KC_3, KC_4, DPI_CONFIG, _______, _______, _______, _______, _______,
KC_F1, KC_K, KC_Q, KC_W, KC_E, KC_R, _______, _______, _______, _______, _______, _______,
KC_TAB, KC_G, KC_A, KC_S, KC_D, KC_F, _______, _______, _______, _______, _______, _______,
@ -105,7 +105,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
KC_SPC, KC_P, _______,
KC_H, KC_LGUI, _______, _______
),
[_DIABLO] = LAYOUT_5x6_right_trackball(
[_DIABLO] = LAYOUT_5x6_right(
KC_ESC, KC_V, KC_D, KC_LALT, KC_NO, KC_NO, KC_F9, KC_F10, KC_F11, KC_F12, KC_NO, KC_NO,
KC_TAB, KC_S, KC_I, KC_F, KC_M, KC_T, _______, _______, _______, _______, _______, _______,
KC_Q, KC_1, KC_2, KC_3, KC_4, KC_G, _______, _______, _______, _______, _______, _______,
@ -115,7 +115,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
SFT_T(KC_SPC), KC_J, _______,
ALT_T(KC_Q), KC_LGUI, _______, _______
),
[_LOWER] = LAYOUT_5x6_right_trackball_wrapper(
[_LOWER] = LAYOUT_5x6_right_wrapper(
KC_F12, _________________FUNC_LEFT_________________, _________________FUNC_RIGHT________________, KC_F11,
_______, _________________LOWER_L1__________________, _________________LOWER_R1__________________, _______,
_______, _________________LOWER_L2__________________, _________________LOWER_R2__________________, KC_PIPE,
@ -125,7 +125,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______,
_______, _______, _______, _______
),
[_RAISE] = LAYOUT_5x6_right_trackball_wrapper(
[_RAISE] = LAYOUT_5x6_right_wrapper(
KC_F12, _________________FUNC_LEFT_________________, _________________FUNC_RIGHT________________, KC_F11,
KC_GRV, _________________RAISE_L1__________________, _________________RAISE_R1__________________, _______,
_______, _________________RAISE_L2__________________, _________________RAISE_R2__________________, KC_BSLS,
@ -135,12 +135,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
_______, _______, _______,
_______, _______, _______, _______
),
[_ADJUST] = LAYOUT_5x6_right_trackball_wrapper(
[_ADJUST] = LAYOUT_5x6_right_wrapper(
KC_MAKE, ___________________BLANK___________________, _________________ADJUST_R1_________________, KC_RST,
VRSN, _________________ADJUST_L1_________________, _________________ADJUST_R1_________________, EEP_RST,
_______, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
UC_MOD, _________________ADJUST_L2_________________, _________________ADJUST_R2_________________, TG_MODS,
_______, _________________ADJUST_L3_________________, _________________ADJUST_R3_________________, KC_MPLY,
HPT_DWLI, HPT_DWLD, _______, _______,
HPT_DWLI, HPT_DWLD, TG_GAME, TG_DBLO,
HPT_TOG, HPT_BUZ, KC_NUKE,
_______, _______, _______,
_______, _______, KC_NUKE, _______

View File

@ -0,0 +1,11 @@
RGBLIGHT_ENABLE = yes
RGBLIGHT_STARTUP_ANIMATION = yes
AUDIO_ENABLE = yes
HAPTIC_ENABLE = no
COMMAND_ENABLE = no
TAP_DANCE_ENABLE = yes
UNICODE_ENABLE = yes
OLED_DRIVER_ENABLE = yes
WPM_ENABLE = yes
ENCODER_ENABLE = yes
# DEBOUNCE_TYPE = sym_eager_pk

View File

@ -0,0 +1,21 @@
# Drashna's Dactyl Manuform (5x6) with a right side trackball
![](https://preview.redd.it/zwt91036m3y51.jpg?width=960&crop=smart&auto=webp&s=e030deb7d8285c95a1a30c69a7e7a71f750e87bb)
It's a Dactyl Manuform with an integrated thumb based trackball, using the pmw3360 optical sensor.
It's powered by 2x Teensy++ 2.0's, using Drashna's [Teensy VBUS Hack](https://docs.qmk.fm/#/feature_split_keyboard?id=hardware-considerations-and-mods) for better detection.
* Keyboard Maintainer: [Drashna Jael're](https://github.com/drashna)
* Hardware Supported: [Design files](https://gitlab.com/keyboards1/dm_r_track/-/tree/master/boolean), [Teensy++ 2.0 (2x)](https://www.pjrc.com/store/teensypp.html), [PMW3360 Optical Sensor](https://www.tindie.com/products/jkicklighter/pmw3360-motion-sensor/)
Make example for this keyboard (after setting up your build environment):
make handwired/dactyl_manuform/5x6_right_trackball:default
Flashing example for this keyboard:
make handwired/dactyl_manuform/5x6_right_trackball:default:flash
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).

View File

@ -17,15 +17,15 @@ SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = yes # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow
BLUETOOTH_ENABLE = no # Enable Bluetooth
AUDIO_ENABLE = no # Audio output
SWAP_HANDS_ENABLE = yes
POINTING_DEVICE_ENABLE = yes
MOUSE_SHARED_EP = no
SPLIT_KEYBOARD = yes
SPLIT_TRANSPORT = custom
SRC += drivers/sensors/pmw3360.c
QUANTUM_LIB_SRC += pointer_transport.c serial.c i2c_master.c i2c_slave.c spi_master.c
QUANTUM_LIB_SRC += spi_master.c tm_sync.c

View File

@ -0,0 +1,43 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "config_common.h"
/* USB Device descriptor parameter */
#define VENDOR_ID 0x44DD
#define MANUFACTURER Drashna
/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5
#define USB_POLLING_INTERVAL_MS 1
/* disable debug print */
// #define NO_DEBUG
/* disable print */
// #define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION

View File

@ -0,0 +1,96 @@
/*
Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// mouse config
# ifndef MOUSEKEY_MOVE_DELTA
# ifndef MK_KINETIC_SPEED
# define MOUSEKEY_MOVE_DELTA 5
# else
# define MOUSEKEY_MOVE_DELTA 25
# endif
# endif
# ifndef MOUSEKEY_DELAY
# ifndef MK_KINETIC_SPEED
# define MOUSEKEY_DELAY 300
# else
# define MOUSEKEY_DELAY 8
# endif
# endif
# ifndef MOUSEKEY_INTERVAL
# ifndef MK_KINETIC_SPEED
# define MOUSEKEY_INTERVAL 50
# else
# define MOUSEKEY_INTERVAL 20
# endif
# endif
# ifndef MOUSEKEY_MAX_SPEED
# define MOUSEKEY_MAX_SPEED 7
# endif
# ifndef MOUSEKEY_TIME_TO_MAX
# define MOUSEKEY_TIME_TO_MAX 60
# endif
# ifndef MOUSEKEY_INITIAL_SPEED
# define MOUSEKEY_INITIAL_SPEED 100
# endif
# ifndef MOUSEKEY_BASE_SPEED
# define MOUSEKEY_BASE_SPEED 1000
# endif
# ifndef MOUSEKEY_DECELERATED_SPEED
# define MOUSEKEY_DECELERATED_SPEED 400
# endif
# ifndef MOUSEKEY_ACCELERATED_SPEED
# define MOUSEKEY_ACCELERATED_SPEED 3000
# endif
// mouse scroll config
# ifndef MOUSEKEY_WHEEL_DELAY
# define MOUSEKEY_WHEEL_DELAY 15
# endif
# ifndef MOUSEKEY_WHEEL_DELTA
# define MOUSEKEY_WHEEL_DELTA 1
# endif
# ifndef MOUSEKEY_WHEEL_INTERVAL
# define MOUSEKEY_WHEEL_INTERVAL 50
# endif
# ifndef MOUSEKEY_WHEEL_MAX_SPEED
# define MOUSEKEY_WHEEL_MAX_SPEED 8
# endif
# ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
# define MOUSEKEY_WHEEL_TIME_TO_MAX 80
# endif
# ifndef MOUSEKEY_WHEEL_INITIAL_MOVEMENTS
# define MOUSEKEY_WHEEL_INITIAL_MOVEMENTS 8
# endif
# ifndef MOUSEKEY_WHEEL_BASE_MOVEMENTS
# define MOUSEKEY_WHEEL_BASE_MOVEMENTS 48
# endif
# ifndef MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS
# define MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS 48
# endif
# ifndef MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS
# define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8
# endif
#ifndef DEBOUNCE
# define DEBOUNCE 5
#endif

View File

@ -0,0 +1,159 @@
Dactyl Manuform (4x5, 5x6, 5x7, 6x6)
======
the [Dactyl-Manuform](https://github.com/tshort/dactyl-keyboard) is a split curved keyboard based on the design of [adereth dactyl](https://github.com/adereth/dactyl-keyboard) and thumb cluster design of the [manuform](https://geekhack.org/index.php?topic=46015.0) keyboard, the hardware is similar to the let's split keyboard. all information needed for making one is in the first link.
![Imgur](https://i.imgur.com/7y0Vbyd.jpg)
## First Time Setup
Download or clone the `qmk_firmware` repo and navigate to its top level directory. Once your build environment is setup, you'll be able to generate the default .hex using:
Depending on your Layout chose one of the follwing commands:
```
$ make handwired/dactyl_manuform/YOUR_LAYOUT:YOUR_KEYMAP_NAME
```
example:
```
$ make handwired/dactyl_manuform/4x5:default
```
If everything worked correctly you will see a file:
```
dactyl_manuform_YOUR_LAYOUT_YOUR_KEYMAP_NAME.hex
```
For more information on customizing keymaps, take a look at the primary documentation for [Customizing Your Keymap](/docs/faq_keymap.md) in the main readme.md.
## Keymaps
### [Keymaps 4x5](/keyboards/handwired/dactyl_manuform/4x5/keymaps/)
#### Default
Simple QWERTY layout with 3 Layers.
#### Dvorak
### [Keymaps 5x6](/keyboards/handwired/dactyl_manuform/5x6/keymaps/)
#### Default
Just a copy of the Impstyle keymap. Feel free to adjust it.
#### Impstyle
A simple QWERTY keymap with 3 Layers. Both sides are connected via serial and the Left ist the master.
### [Keymaps 5x7 aka almost Ergodox](/keyboards/handwired/dactyl_manuform/5x7/keymaps/)
#### Default
Keymap of Loligagger from geekhack.
### [Keymaps 6x6](/keyboards/handwired/dactyl_manuform/6x6/keymaps/)
#### Default
Simple QWERTY layout with 3 Layers.
## Required Hardware
Apart from diodes and key switches for the keyboard matrix in each half, you
will need:
* 2 Arduino Pro Micros. You can find these on AliExpress for ≈3.50USD each.
* 2 TRRS sockets and 1 TRRS cable, or 2 TRS sockets and 1 TRS cable
Alternatively, you can use any sort of cable and socket that has at least 3
wires. If you want to use I2C to communicate between halves, you will need a
cable with at least 4 wires and 2x 4.7kΩ pull-up resistors
## Optional Hardware
A speaker can be hooked-up to either side to the `5` (`C6`) pin and `GND`, and turned on via `AUDIO_ENABLE`.
## Wiring
The 3 wires of the TRS/TRRS cable need to connect GND, VCC, and digital pin 3 (i.e.
PD0 on the ATmega32u4) between the two Pro Micros.
Next, wire your key matrix to any of the remaining 17 IO pins of the pro micro
and modify the `matrix.c` accordingly.
The wiring for serial:
![serial wiring](https://i.imgur.com/C3D1GAQ.png)
The wiring for i2c:
![i2c wiring](https://i.imgur.com/Hbzhc6E.png)
The pull-up resistors may be placed on either half. It is also possible
to use 4 resistors and have the pull-ups in both halves, but this is
unnecessary in simple use cases.
You can change your configuration between serial and i2c by modifying your `config.h` file.
## Notes on Software Configuration
the keymaps in here are for the 4x5 layout of the keyboard only.
## Flashing
To flash your firmware take a look at: [Flashing Instructions and Bootloader Information](https://docs.qmk.fm/#/flashing)
## Choosing which board to plug the USB cable into (choosing Master)
Because the two boards are identical, the firmware has logic to differentiate the left and right board.
It uses two strategies to figure things out: looking at the EEPROM (memory on the chip) or looking if the current board has the usb cable.
The EEPROM approach requires additional setup (flashing the eeprom) but allows you to swap the usb cable to either side.
The USB cable approach is easier to setup and if you just want the usb cable on the left board, you do not need to do anything extra.
### Setting the left hand as master
If you always plug the usb cable into the left board, nothing extra is needed as this is the default. Comment out `EE_HANDS` and comment out `I2C_MASTER_RIGHT` or `MASTER_RIGHT` if for some reason it was set.
### Setting the right hand as master
If you always plug the usb cable into the right board, add an extra flag to your `config.h`
```
#define MASTER_RIGHT
```
### Setting EE_hands to use either hands as master
If you define `EE_HANDS` in your `config.h`, you will need to set the
EEPROM for the left and right halves.
The EEPROM is used to store whether the
half is left handed or right handed. This makes it so that the same firmware
file will run on both hands instead of having to flash left and right handed
versions of the firmware to each half. To flash the EEPROM file for the left
half run:
```
make handwired/dactyl_promicro:default:dfu-split-left
make handwired/dactyl_promicro:default:dfu-split-right
```
After you have flashed the EEPROM, you then need to set `EE_HANDS` in your config.h, rebuild the hex files and reflash.
Note that you need to program both halves, but you have the option of using
different keymaps for each half. You could program the left half with a QWERTY
layout and the right half with a Colemak layout using bootmagic's default layout option.
Then if you connect the left half to a computer by USB the keyboard will use QWERTY and Colemak when the
right half is connected.
Notes on Using Pro Micro 3.3V
-----------------------------
Do update the `F_CPU` parameter in `rules.mk` to `8000000` which reflects
the frequency on the 3.3V board.
Also, if the slave board is producing weird characters in certain columns,
update the following line in `matrix.c` to the following:
```
// wait_us(30); // without this wait read unstable value.
wait_us(300); // without this wait read unstable value.
```

View File

@ -0,0 +1,132 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SPLIT_TRANSACTION_IDS_KB
# include "tractyl_manuform.h"
# include "transactions.h"
# include <string.h>
# include "drivers/sensors/pmw3360.h"
kb_runtime_config_t kb_state;
kb_slave_data_t kb_slave;
void slave_state_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) {
if (target2initiator_buffer_size == sizeof(kb_slave)) {
memcpy(target2initiator_buffer, &kb_slave, sizeof(kb_slave));
if (kb_slave.mouse_x > 127) {
kb_slave.mouse_x -= 127;
} else if (kb_slave.mouse_x < -127) {
kb_slave.mouse_x += 127;
} else {
kb_slave.mouse_x = 0;
}
if (kb_slave.mouse_y > 127) {
kb_slave.mouse_y -= 127;
} else if (kb_slave.mouse_y < -127) {
kb_slave.mouse_y += 127;
} else {
kb_slave.mouse_y = 0;
}
}
}
void pointer_state_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) {
if (initiator2target_buffer_size == sizeof(kb_state)) {
memcpy(&kb_state, initiator2target_buffer, sizeof(kb_state));
}
}
void keyboard_post_init_kb(void) {
// Register keyboard state sync split transaction
transaction_register_rpc(RPC_ID_STATE_SYNC, pointer_state_sync);
transaction_register_rpc(RPC_ID_SLAVE_STATE, slave_state_sync);
keyboard_post_init_user();
}
void kb_state_update(void) {
# ifdef POINTING_DEVICE_ENABLE
if (is_keyboard_master() && !is_keyboard_left()) {
static uint16_t cpi = 0;
if (cpi != kb_state.device_cpi) {
cpi = kb_state.device_cpi;
pmw_set_cpi(cpi);
}
}
# endif
}
void kb_post_state_update(void) {
# ifdef POINTING_DEVICE_ENABLE
if (is_keyboard_master() && is_keyboard_left()) {
report_mouse_t temp_report = pointing_device_get_report();
temp_report.x = kb_slave.mouse_x;
temp_report.y = kb_slave.mouse_y;
pointing_device_set_report(temp_report);
}
# endif
}
void kb_state_sync(void) {
if (is_keyboard_master()) {
// Keep track of the last state, so that we can tell if we need to propagate to slave
static kb_runtime_config_t last_kb_state;
static uint32_t last_sync = 0;
static uint32_t mouse_sync = 0;
bool needs_sync = false;
// Check if the state values are different
if (memcmp(&kb_state, &last_kb_state, sizeof(kb_runtime_config_t))) {
needs_sync = true;
memcpy(&last_kb_state, &kb_state, sizeof(kb_runtime_config_t));
}
// Send to slave every 500ms regardless of state change
if (timer_elapsed32(last_sync) > 500) {
needs_sync = true;
}
// Perform the sync if requested
if (needs_sync) {
if (transaction_rpc_send(RPC_ID_STATE_SYNC, sizeof(kb_runtime_config_t), &kb_state)) {
last_sync = timer_read32();
}
}
if (is_keyboard_left()) {
if (timer_elapsed32(mouse_sync) >= 5) {
// always sync slave data, since it may contain device reports.
if (transaction_rpc_recv(RPC_ID_SLAVE_STATE, sizeof(kb_slave_data_t), &kb_slave)) {
if (kb_slave.mouse_x >= -127 && kb_slave.mouse_x <= 127 && kb_slave.mouse_y >= -127 && kb_slave.mouse_y <= 127) {
mouse_sync = timer_read32();
}
}
}
}
}
}
void housekeeping_task_kb(void) {
// Update kb_state so we can send to slave
kb_state_update();
// Data sync from master to slave
kb_state_sync();
kb_post_state_update();
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
/* Copyright 2020 Christopher Courtney <drashna@live.com> (@drashna)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -14,10 +14,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "5x6_right_trackball.h"
#include "tractyl_manuform.h"
#include "transactions.h"
#include <string.h>
#include "drivers/sensors/pmw3360.h"
#ifndef TRACKBALL_DPI_OPTIONS
# define TRACKBALL_DPI_OPTIONS { 1200, 1600, 2400 }
# define TRACKBALL_DPI_OPTIONS \
{ 1200, 1600, 2400 }
# ifndef TRACKBALL_DPI_DEFAULT
# define TRACKBALL_DPI_DEFAULT 1
# endif
@ -26,6 +30,9 @@
# define TRACKBALL_DPI_DEFAULT 0
#endif
extern kb_runtime_config_t kb_state;
extern kb_slave_data_t kb_slave;
keyboard_config_t keyboard_config;
uint16_t dpi_array[] = TRACKBALL_DPI_OPTIONS;
#define DPI_OPTION_SIZE (sizeof(dpi_array) / sizeof(uint16_t))
@ -53,12 +60,8 @@ __attribute__((weak)) void process_mouse(report_mouse_t* mouse_report) {
MotionStart = timer_read();
}
if (debug_mouse) {
dprintf("Delt] d: %d t: %u\n", abs(data.dx) + abs(data.dy), MotionStart);
}
if (debug_mouse) {
dprintf("Pre ] X: %d, Y: %d\n", data.dx, data.dy);
}
if (debug_mouse) { dprintf("Delt] d: %d t: %u\n", abs(data.dx) + abs(data.dy), MotionStart); }
if (debug_mouse) { dprintf("Pre ] X: %d, Y: %d\n", data.dx, data.dy); }
#if defined(PROFILE_LINEAR)
float scale = float(timer_elaspsed(MotionStart)) / 1000.0;
data.dx *= scale;
@ -146,19 +149,11 @@ void pointing_device_init(void) {
trackball_set_cpi(dpi_array[keyboard_config.dpi_config]);
}
static bool has_report_changed(report_mouse_t new, report_mouse_t old) {
return (new.buttons != old.buttons) ||
(new.x && new.x != old.x) ||
(new.y && new.y != old.y) ||
(new.h && new.h != old.h) ||
(new.v && new.v != old.v);
}
static bool has_report_changed(report_mouse_t new, report_mouse_t old) { return (new.buttons != old.buttons) || (new.x&& new.x != old.x) || (new.y&& new.y != old.y) || (new.h&& new.h != old.h) || (new.v&& new.v != old.v); }
void pointing_device_task(void) {
report_mouse_t mouse_report = pointing_device_get_report();
if (!is_keyboard_left()) {
process_mouse(&mouse_report);
}
if (!is_keyboard_left()) { process_mouse(&mouse_report); }
pointing_device_set_report(mouse_report);
pointing_device_send();
@ -178,9 +173,7 @@ void matrix_init_kb(void) {
// is safe to just read DPI setting since matrix init
// comes before pointing device init.
keyboard_config.raw = eeconfig_read_kb();
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) {
eeconfig_init_kb();
}
if (keyboard_config.dpi_config > DPI_OPTION_SIZE) { eeconfig_init_kb(); }
matrix_init_user();
}
@ -193,9 +186,7 @@ void pointing_device_send(void) {
mouseReport.x = 0;
mouseReport.y = 0;
process_mouse_user(&mouseReport, x, y);
if (has_report_changed(mouseReport, old_report)) {
host_mouse_send(&mouseReport);
}
if (has_report_changed(mouseReport, old_report)) { host_mouse_send(&mouseReport); }
} else {
master_mouse_send(mouseReport.x, mouseReport.y);
}
@ -208,21 +199,20 @@ void pointing_device_send(void) {
}
#endif
#ifdef SWAP_HANDS_ENABLE
const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
/* Left hand, matrix positions */
{{5, 6}, {4, 6}, {3, 6}, {2, 6}, {1, 6}, {0, 6}},
{{5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7}, {0, 7}},
{{5, 8}, {4, 8}, {3, 8}, {2, 8}, {1, 8}, {0, 8}},
{{5, 9}, {4, 9}, {3, 9}, {2, 9}, {1, 9}, {0, 9}},
{{5, 10}, {4, 10}, {3, 10}, {2, 10}, {1, 10}, {0, 10}},
{{5, 11}, {4, 11}, {3, 11}, {2, 11}, {1, 11}, {0, 11}},
/* Right hand, matrix positions */
{{5, 0}, {4, 0}, {3, 0}, {2, 0}, {1, 0}, {0, 0}},
{{5, 1}, {4, 1}, {3, 1}, {2, 1}, {1, 1}, {0, 1}},
{{5, 2}, {4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
{{5, 3}, {4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
{{5, 4}, {4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}},
{{5, 5}, {4, 5}, {3, 5}, {2, 5}, {1, 5}, {0, 5}}
};
#ifdef POINTING_DEVICE_ENABLE
void master_mouse_send(int8_t x, int8_t y) {
#ifdef SPLIT_TRANSACTION_IDS_KB
kb_slave.mouse_x += x;
kb_slave.mouse_y += y;
#endif
}
void trackball_set_cpi(uint16_t cpi) {
if (!is_keyboard_left()) {
pmw_set_cpi(cpi);
} else {
#ifdef SPLIT_TRANSACTION_IDS_KB
kb_state.device_cpi = cpi;
#endif
}
}
#endif

View File

@ -0,0 +1,55 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "quantum.h"
#include "pointing_device.h"
#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
# include "5x6_right.h"
#elif defined(KEYBOARD_handwired_tractyl_manuform_4x6_right)
# include "4x6_right.h"
#endif
void process_mouse(report_mouse_t* mouse_report);
void process_mouse_user(report_mouse_t* mouse_report, int16_t x, int16_t y);
typedef union {
uint32_t raw;
struct {
uint8_t dpi_config;
};
} keyboard_config_t;
extern keyboard_config_t keyboard_config;
enum ploopy_keycodes {
DPI_CONFIG = SAFE_RANGE,
KEYMAP_SAFE_RANGE,
};
void master_mouse_send(int8_t x, int8_t y);
void trackball_set_cpi(uint16_t cpi);
typedef struct {
uint16_t device_cpi;
} kb_runtime_config_t;
typedef struct {
int16_t mouse_x;
int16_t mouse_y;
} kb_slave_data_t;

View File

@ -131,7 +131,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format on
#ifdef OLED_DRIVER_ENABLE
oled_rotation_t oled_init_user(oled_rotation_t rotation) { return OLED_ROTATION_180; }
oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return OLED_ROTATION_180; }
#endif
#ifdef ENCODER_ENABLE

View File

@ -3,19 +3,13 @@ ENCODER_ENABLE = yes # ENables the use of one or more encoders
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
RGBLIGHT_STARTUP_ANIMATION = no
BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration
MOUSEKEY_ENABLE = no # Mouse keys
EXTRAKEY_ENABLE = yes # Audio control and System control
CONSOLE_ENABLE = no # Console for debug
COMMAND_ENABLE = no # Commands for debug and configuration
NKRO_ENABLE = no # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality on B7 by default
MIDI_ENABLE = no # MIDI support
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
AUDIO_ENABLE = no # Audio output on port C6
NKRO_ENABLE = yes # USB Nkey Rollover
UNICODE_ENABLE = yes # Unicode
BOOTLOADER = atmel-dfu
# SPLIT_TRANSPORT = mirror
# TAP_DANCE_ENABLE = yes

View File

@ -19,7 +19,7 @@
#ifdef UNICODEMAP_ENABLE
# include "drashna_unicode.h"
#endif // UNICODEMAP_ENABLE
#include "drivers/sensors/pimoroni_trackball.h"
enum more_custom_keycodes {
KC_SWAP_NUM = NEW_SAFE_RANGE,
PM_SCROLL,
@ -317,13 +317,14 @@ void shutdown_keymap(void) {
static bool mouse_button_one, trackball_button_one;
void trackball_check_click(bool pressed, report_mouse_t* mouse) {
if (mouse_button_one | pressed) {
mouse->buttons |= MOUSE_BTN1;
void trackball_register_button(bool pressed, enum mouse_buttons button) {
report_mouse_t currentReport = pointing_device_get_report();
if (pressed) {
currentReport.buttons |= button;
} else {
mouse->buttons &= ~MOUSE_BTN1;
currentReport.buttons &= ~button;
}
trackball_button_one = pressed;
pointing_device_set_report(currentReport);
}
#endif

View File

@ -74,7 +74,6 @@
// #define INIT_EE_HANDS_RIGHT
#endif
#if defined(AUDIO_ENABLE) && !defined(CONVERT_TO_PROTON_C)
# define AUDIO_PIN B6
# define NO_MUSIC_MODE

View File

@ -114,7 +114,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format on
#ifdef OLED_DRIVER_ENABLE
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
oled_rotation_t oled_init_keymap(oled_rotation_t rotation) {
return OLED_ROTATION_270;
}
#endif

View File

@ -24,28 +24,43 @@
#if defined(SPLIT_KEYBOARD)
# define SPLIT_MODS_ENABLE
# define SPLIT_TRANSPORT_MIRROR
# define SPLIT_LAYER_STATE_ENABLE
# define SPLIT_LED_STATE_ENABLE
// # define SPLIT_TRANSPORT_MIRROR
# define SERIAL_USE_MULTI_TRANSACTION
// # define SPLIT_NUM_TRANSACTIONS_KB 2
# define SPLIT_TRANSACTION_IDS_USER RPC_ID_USER_STATE_SYNC
#endif
#ifdef AUDIO_ENABLE
# define AUDIO_CLICKY
# define AUDIO_CLICKY_FREQ_RANDOMNESS 1.5f
# ifdef USER_SONG_LIST
# define STARTUP_SONG SONG(RICK_ROLL)
# define GOODBYE_SONG SONG(SONIC_RING)
# define DEFAULT_LAYER_SONGS \
{ SONG(QWERTY_SOUND), SONG(COLEMAK_SOUND), SONG(DVORAK_SOUND), SONG(OVERWATCH_THEME) }
# define AUDIO_CLICKY_FREQ_RANDOMNESS 1.5f
# define UNICODE_SONG_MAC SONG(RICK_ROLL)
# define UNICODE_SONG_LNX SONG(RICK_ROLL)
# define UNICODE_SONG_WIN SONG(RICK_ROLL)
# define UNICODE_SONG_MAC SONG(MARIO_THEME)
# define UNICODE_SONG_LNX SONG(MARIO_POWERUP)
# define UNICODE_SONG_WIN SONG(MARIO_ONEUP)
# define UNICODE_SONG_BSD SONG(RICK_ROLL)
# define UNICODE_SONG_WINC SONG(RICK_ROLL)
# else
# define STARTUP_SONG SONG(STARTUP_SOUND)
# define GOODBYE_SONG SONG(GOODBYE_SOUND)
# define DEFAULT_LAYER_SONGS \
{ SONG(QWERTY_SOUND), SONG(COLEMAK_SOUND), SONG(DVORAK_SOUND), SONG(WORKMAN_SOUND) }
# define UNICODE_SONG_MAC SONG(QWERTY_SOUND)
# define UNICODE_SONG_LNX SONG(COLEMAK_SOUND)
# define UNICODE_SONG_WIN SONG(DVORAK_SOUND)
# define UNICODE_SONG_BSD SONG(WORKMAN_SOUND)
# define UNICODE_SONG_WINC SONG(PLOVER_GOODBYE_SOUND)
# endif
#endif // !AUDIO_ENABLE
#define UNICODE_SELECTED_MODES UC_WIN, UC_MAC
#ifdef RGBLIGHT_ENABLE
# define RGBLIGHT_SLEEP
# if defined(__AVR__) && !defined(__AVR_AT90USB1286__)
@ -65,9 +80,7 @@
// # define RGB_MATRIX_KEYRELEASES // reacts to keyreleases (not recommened)
# define RGB_MATRIX_FRAMEBUFFER_EFFECTS
// # define RGB_DISABLE_AFTER_TIMEOUT 0 // number of ticks to wait until disabling effects
# define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
// # define RGB_MATRIX_MAXIMUM_BRIGHTNESS 200 // limits maximum brightness of LEDs to 200 out of 255. If not defined maximum brightness is set to 255
// # define EECONFIG_RGB_MATRIX (uint32_t *)16
// # define RGB_DISABLE_WHEN_USB_SUSPENDED // turn off effects when suspended
# if defined(__AVR__) && !defined(__AVR_AT90USB1286__) && !defined(KEYBOARD_launchpad)
# define DISABLE_RGB_MATRIX_ALPHAS_MODS
@ -152,8 +165,8 @@
// actually sends Ctrl-x. That's bad.)
#define IGNORE_MOD_TAP_INTERRUPT
#undef PERMISSIVE_HOLD
//#define TAPPING_FORCE_HOLD
//#define RETRO_TAPPING
//#define TAPPING_FORCE_HOLD_PER_KEY
//#define RETRO_TAPPING_PER_KEY
#ifndef KEYBOARD_kyria_rev1
# define TAPPING_TERM_PER_KEY
#endif
@ -185,6 +198,8 @@
# undef LOCKING_RESYNC_ENABLE
#endif
#define LAYER_STATE_16BIT
#ifdef CONVERT_TO_PROTON_C
// pins that are available but not present on Pro Micro
# define A3 PAL_LINE(GPIOA, 3)
@ -203,3 +218,79 @@
# define C14 PAL_LINE(GPIOC, 14)
# define C15 PAL_LINE(GPIOC, 15)
#endif
#ifdef MOUSEKEY_ENABLE
// mouse movement config
# ifdef MK_3_SPEED
# undef MK_3_SPEED
# endif
# define MK_KINETIC_SPEED
# ifdef MK_KINETIC_SPEED
# ifndef MOUSEKEY_DELAY
# define MOUSEKEY_DELAY 8
# endif
# ifndef MOUSEKEY_INTERVAL
# define MOUSEKEY_INTERVAL 20
# endif
# ifdef MOUSEKEY_MOVE_DELTA
# define MOUSEKEY_MOVE_DELTA 25
# endif
# else
# ifndef MOUSEKEY_DELAY
# define MOUSEKEY_DELAY 300
# endif
# ifndef MOUSEKEY_INTERVAL
# define MOUSEKEY_INTERVAL 50
# endif
# ifndef MOUSEKEY_MOVE_DELTA
# define MOUSEKEY_MOVE_DELTA 5
# endif
# endif
# ifndef MOUSEKEY_MAX_SPEED
# define MOUSEKEY_MAX_SPEED 7
# endif
# ifndef MOUSEKEY_TIME_TO_MAX
# define MOUSEKEY_TIME_TO_MAX 60
# endif
# ifndef MOUSEKEY_INITIAL_SPEED
# define MOUSEKEY_INITIAL_SPEED 100
# endif
# ifndef MOUSEKEY_BASE_SPEED
# define MOUSEKEY_BASE_SPEED 1000
# endif
# ifndef MOUSEKEY_DECELERATED_SPEED
# define MOUSEKEY_DECELERATED_SPEED 400
# endif
# ifndef MOUSEKEY_ACCELERATED_SPEED
# define MOUSEKEY_ACCELERATED_SPEED 3000
# endif
// mouse scroll config
# ifndef MOUSEKEY_WHEEL_DELAY
# define MOUSEKEY_WHEEL_DELAY 15
# endif
# ifndef MOUSEKEY_WHEEL_DELTA
# define MOUSEKEY_WHEEL_DELTA 1
# endif
# ifndef MOUSEKEY_WHEEL_INTERVAL
# define MOUSEKEY_WHEEL_INTERVAL 50
# endif
# ifndef MOUSEKEY_WHEEL_MAX_SPEED
# define MOUSEKEY_WHEEL_MAX_SPEED 8
# endif
# ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
# define MOUSEKEY_WHEEL_TIME_TO_MAX 80
# endif
// mouse scroll kinetic config
# ifndef MOUSEKEY_WHEEL_INITIAL_MOVEMENTS
# define MOUSEKEY_WHEEL_INITIAL_MOVEMENTS 8
# endif
# ifndef MOUSEKEY_WHEEL_BASE_MOVEMENTS
# define MOUSEKEY_WHEEL_BASE_MOVEMENTS 48
# endif
# ifndef MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS
# define MOUSEKEY_WHEEL_ACCELERATED_MOVEMENTS 48
# endif
# ifndef MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS
# define MOUSEKEY_WHEEL_DECELERATED_MOVEMENTS 8
# endif
#endif // MOUSEKEY_ENABLE

View File

@ -85,6 +85,9 @@ void keyboard_post_init_user(void) {
#endif
#if defined(RGB_MATRIX_ENABLE)
keyboard_post_init_rgb_matrix();
#endif
#if defined(SPLIT_KEYBOARD) && defined(SPLIT_TRANSACTION_IDS_USER)
keyboard_post_init_transport_sync();
#endif
keyboard_post_init_keymap();
}
@ -120,7 +123,11 @@ void suspend_power_down_user(void) {
__attribute__((weak)) void suspend_wakeup_init_keymap(void) {}
void suspend_wakeup_init_user(void) { suspend_wakeup_init_keymap(); }
void suspend_wakeup_init_user(void) {
if (layer_state_is(_GAMEPAD)) { layer_off(_GAMEPAD); }
if (layer_state_is(_DIABLO)) { layer_off(_DIABLO); }
suspend_wakeup_init_keymap();
}
__attribute__((weak)) void matrix_scan_keymap(void) {}
@ -160,9 +167,7 @@ __attribute__((weak)) layer_state_t layer_state_set_keymap(layer_state_t state)
// on layer change, no matter where the change was initiated
// Then runs keymap's layer change check
layer_state_t layer_state_set_user(layer_state_t state) {
if (!is_keyboard_master()) {
return state;
}
if (!is_keyboard_master()) { return state; }
state = layer_state_set_keymap(state);
state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST);
@ -187,9 +192,7 @@ __attribute__((weak)) layer_state_t default_layer_state_set_keymap(layer_state_t
// Runs state check and changes underglow color and animation
layer_state_t default_layer_state_set_user(layer_state_t state) {
if (!is_keyboard_master()) {
return state;
}
if (!is_keyboard_master()) { return state; }
state = default_layer_state_set_keymap(state);
#if 0

View File

@ -35,6 +35,9 @@
#if defined(PIMORONI_TRACKBALL_ENABLE)
# include "drivers/sensors/pimoroni_trackball.h"
#endif
#ifdef SPLIT_KEYBOARD
# include "transport_sync.h"
#endif
/* Define layer names */
enum userspace_layers {

View File

@ -5,8 +5,9 @@
#include "progmem.h"
// clang-format off
static const unsigned char font[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 0
0x07, 0x08, 0x7F, 0x08, 0x07, 0x00, // 0x00 0
0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 0x00, // 0x01 1
0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 0x00, // 0x02 2
0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, // 0x03 3 ♥
@ -1304,3 +1305,5 @@ static const unsigned char font[] PROGMEM = {
#endif
};
// clang-format on

View File

@ -1,603 +0,0 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stddef.h>
#include "matrix.h"
#include QMK_KEYBOARD_H
#define ROWS_PER_HAND (MATRIX_ROWS / 2)
#define SYNC_TIMER_OFFSET 2
#ifdef RGBLIGHT_ENABLE
# include "rgblight.h"
#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif
#ifdef ENCODER_ENABLE
# include "encoder.h"
static pin_t encoders_pad[] = ENCODERS_PAD_A;
# define NUMBER_OF_ENCODERS (sizeof(encoders_pad) / sizeof(pin_t))
#endif
#ifdef POINTING_DEVICE_ENABLE
static uint16_t device_cpi = 0;
static int8_t split_mouse_x = 0, split_mouse_y = 0;
#endif
#ifdef OLED_DRIVER_ENABLE
# include "oled_driver.h"
#endif
#if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
# include "led_matrix.h"
#endif
#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
# include "rgb_matrix.h"
#endif
#if defined(USE_I2C)
# include "i2c_master.h"
# include "i2c_slave.h"
typedef struct _I2C_slave_buffer_t {
# ifndef DISABLE_SYNC_TIMER
uint32_t sync_timer;
# endif
# ifdef SPLIT_TRANSPORT_MIRROR
matrix_row_t mmatrix[ROWS_PER_HAND];
# endif
matrix_row_t smatrix[ROWS_PER_HAND];
# ifdef SPLIT_MODS_ENABLE
uint8_t real_mods;
uint8_t weak_mods;
# ifndef NO_ACTION_ONESHOT
uint8_t oneshot_mods;
# endif
# endif
# ifdef BACKLIGHT_ENABLE
uint8_t backlight_level;
# endif
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
rgblight_syncinfo_t rgblight_sync;
# endif
# ifdef ENCODER_ENABLE
uint8_t encoder_state[NUMBER_OF_ENCODERS];
# endif
# ifdef WPM_ENABLE
uint8_t current_wpm;
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
led_eeconfig_t led_matrix;
bool led_suspend_state;
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
rgb_config_t rgb_matrix;
bool rgb_suspend_state;
# endif
int8_t mouse_x;
int8_t mouse_y;
uint16_t device_cpi;
bool oled_on;
layer_state_t t_layer_state;
layer_state_t t_default_layer_state;
} __attribute__((packed)) I2C_slave_buffer_t;
static I2C_slave_buffer_t *const i2c_buffer = (I2C_slave_buffer_t *)i2c_slave_reg;
# define I2C_BACKLIGHT_START offsetof(I2C_slave_buffer_t, backlight_level)
# define I2C_RGB_START offsetof(I2C_slave_buffer_t, rgblight_sync)
# define I2C_KEYMAP_MASTER_START offsetof(I2C_slave_buffer_t, mmatrix)
# define I2C_KEYMAP_SLAVE_START offsetof(I2C_slave_buffer_t, smatrix)
# define I2C_SYNC_TIME_START offsetof(I2C_slave_buffer_t, sync_timer)
# define I2C_REAL_MODS_START offsetof(I2C_slave_buffer_t, real_mods)
# define I2C_WEAK_MODS_START offsetof(I2C_slave_buffer_t, weak_mods)
# define I2C_ONESHOT_MODS_START offsetof(I2C_slave_buffer_t, oneshot_mods)
# define I2C_ENCODER_START offsetof(I2C_slave_buffer_t, encoder_state)
# define I2C_WPM_START offsetof(I2C_slave_buffer_t, current_wpm)
# define I2C_MOUSE_X_START offsetof(I2C_slave_buffer_t, mouse_x)
# define I2C_MOUSE_Y_START offsetof(I2C_slave_buffer_t, mouse_y)
# define I2C_MOUSE_DPI_START offsetof(I2C_slave_buffer_t, device_cpi)
# define I2C_OLED_ON_START offsetof(I2C_slave_buffer_t, oled_on)
# define I2C_LAYER_STATE_START offsetof(I2C_slave_buffer_t, t_layer_state)
# define I2C_DEFAULT_LAYER_STATE_START offsetof(I2C_slave_buffer_t, t_default_layer_state)
# define I2C_LED_MATRIX_START offsetof(I2C_slave_buffer_t, led_matrix)
# define I2C_LED_SUSPEND_START offsetof(I2C_slave_buffer_t, led_suspend_state)
# define I2C_RGB_MATRIX_START offsetof(I2C_slave_buffer_t, rgb_matrix)
# define I2C_RGB_SUSPEND_START offsetof(I2C_slave_buffer_t, rgb_suspend_state)
# define TIMEOUT 100
# ifndef SLAVE_I2C_ADDRESS
# define SLAVE_I2C_ADDRESS 0x32
# endif
// Get rows from other half over i2c
bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_SLAVE_START, (void *)slave_matrix, sizeof(i2c_buffer->smatrix), TIMEOUT);
# ifdef SPLIT_TRANSPORT_MIRROR
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_KEYMAP_MASTER_START, (void *)master_matrix, sizeof(i2c_buffer->mmatrix), TIMEOUT);
# endif
// write backlight info
# ifdef BACKLIGHT_ENABLE
uint8_t level = is_backlight_enabled() ? get_backlight_level() : 0;
if (level != i2c_buffer->backlight_level) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_BACKLIGHT_START, (void *)&level, sizeof(level), TIMEOUT) >= 0) {
i2c_buffer->backlight_level = level;
}
}
# endif
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
if (rgblight_get_change_flags()) {
rgblight_syncinfo_t rgblight_sync;
rgblight_get_syncinfo(&rgblight_sync);
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_START, (void *)&rgblight_sync, sizeof(rgblight_sync), TIMEOUT) >= 0) {
rgblight_clear_change_flags();
}
}
# endif
# ifdef ENCODER_ENABLE
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_ENCODER_START, (void *)i2c_buffer->encoder_state, sizeof(i2c_buffer->encoder_state), TIMEOUT);
encoder_update_raw(i2c_buffer->encoder_state);
# endif
# ifdef WPM_ENABLE
uint8_t current_wpm = get_current_wpm();
if (current_wpm != i2c_buffer->current_wpm) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WPM_START, (void *)&current_wpm, sizeof(current_wpm), TIMEOUT) >= 0) {
i2c_buffer->current_wpm = current_wpm;
}
}
# endif
# ifdef POINTING_DEVICE_ENABLE
if (is_keyboard_left()) {
report_mouse_t temp_report = pointing_device_get_report();
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT);
temp_report.x = i2c_buffer->mouse_x;
i2c_readReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT);
temp_report.y = i2c_buffer->mouse_y;
pointing_device_set_report(temp_report);
if (device_cpi != i2c_buffer->device_cpi) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_DPI_START, (void *)&device_cpi, sizeof(device_cpi), TIMEOUT) >= 0) {
i2c_buffer->device_cpi = device_cpi
}
}
}
# endif
# ifdef SPLIT_MODS_ENABLE
uint8_t real_mods = get_mods();
if (real_mods != i2c_buffer->real_mods) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_REAL_MODS_START, (void *)&real_mods, sizeof(real_mods), TIMEOUT) >= 0) {
i2c_buffer->real_mods = real_mods;
}
}
uint8_t weak_mods = get_weak_mods();
if (weak_mods != i2c_buffer->weak_mods) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_WEAK_MODS_START, (void *)&weak_mods, sizeof(weak_mods), TIMEOUT) >= 0) {
i2c_buffer->weak_mods = weak_mods;
}
}
# ifndef NO_ACTION_ONESHOT
uint8_t oneshot_mods = get_oneshot_mods();
if (oneshot_mods != i2c_buffer->oneshot_mods) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_ONESHOT_MODS_START, (void *)&oneshot_mods, sizeof(oneshot_mods), TIMEOUT) >= 0) {
i2c_buffer->oneshot_mods = oneshot_mods;
}
}
# endif
# endif
if (layer_state != i2c_buffer->t_layer_state) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LAYER_STATE_START, (void *)&layer_state, sizeof(layer_state), TIMEOUT) >= 0) {
i2c_buffer->t_layer_state = layer_state;
}
}
if (default_layer_state != i2c_buffer->t_default_layer_state) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_DEFAULT_LAYER_STATE_START, (void *)&default_layer_state, sizeof(default_layer_state), TIMEOUT) >= 0) {
i2c_buffer->t_default_layer_state = default_layer_state;
}
}
# ifdef OLED_DRIVER_ENABLE
bool is_oled_on = is_oled_on();
if (is_oled_on != i2c_buffer->oled_on) {
if (i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LAYER_STATE_START, (void *)&is_oled_on, sizeof(is_oled_on), TIMEOUT) >= 0) {
i2c_buffer->oled_on = is_oled_on;
}
}
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_MATRIX_START, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix), TIMEOUT);
bool suspend_state = led_matrix_get_suspend_state();
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_LED_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->led_suspend_state), TIMEOUT);
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_MATRIX_START, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix), TIMEOUT);
bool suspend_state = rgb_matrix_get_suspend_state();
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_RGB_SUSPEND_START, (void *)suspend_state, sizeof(i2c_buffer->rgb_suspend_state), TIMEOUT);
# 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 master_matrix[], matrix_row_t slave_matrix[]) {
# ifndef DISABLE_SYNC_TIMER
sync_timer_update(i2c_buffer->sync_timer);
# endif
// Copy matrix to I2C buffer
memcpy((void *)i2c_buffer->smatrix, (void *)slave_matrix, sizeof(i2c_buffer->smatrix));
# ifdef SPLIT_TRANSPORT_MIRROR
memcpy((void *)master_matrix, (void *)i2c_buffer->mmatrix, sizeof(i2c_buffer->mmatrix));
# endif
// Read Backlight Info
# ifdef BACKLIGHT_ENABLE
backlight_set(i2c_buffer->backlight_level);
# endif
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// Update the RGB with the new data
if (i2c_buffer->rgblight_sync.status.change_flags != 0) {
rgblight_update_sync(&i2c_buffer->rgblight_sync, false);
i2c_buffer->rgblight_sync.status.change_flags = 0;
}
# endif
# ifdef ENCODER_ENABLE
encoder_state_raw(i2c_buffer->encoder_state);
# endif
# ifdef WPM_ENABLE
set_current_wpm(i2c_buffer->current_wpm);
# endif
# ifdef POINTING_DEVICE_ENABLE
if (!is_keyboard_left()) {
static uint16_t cpi;
if (cpi != i2c_buffer->device_cpi) {
cpi = i2c_buffer->device_cpi;
pmw_set_cpi(cpi);
}
i2c_buffer->mouse_x = split_mouse_x;
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_X_START, (void *)&i2c_buffer->mouse_x, sizeof(i2c_buffer->mouse_x), TIMEOUT);
i2c_buffer->mouse_y = split_mouse_y;
i2c_writeReg(SLAVE_I2C_ADDRESS, I2C_MOUSE_Y_START, (void *)&i2c_buffer->mouse_y, sizeof(i2c_buffer->mouse_y), TIMEOUT);
}
# endif
# ifdef SPLIT_MODS_ENABLE
set_mods(i2c_buffer->real_mods);
set_weak_mods(i2c_buffer->weak_mods);
# ifndef NO_ACTION_ONESHOT
set_oneshot_mods(i2c_buffer->oneshot_mods);
# endif
# endif
if (layer_state != i2c_buffer->t_layer_state) {
layer_state = i2c_buffer->t_layer_state;
}
if (default_layer_state != i2c_buffer->t_default_layer_state) {
default_layer_state = i2c_buffer->t_default_layer_state;
}
# ifdef OLED_DRIVER_ENABLE
if (i2c_buffer->oled_on) {
oled_on();
} else {
oled_off();
}
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
memcpy((void *)i2c_buffer->led_matrix, (void *)led_matrix_eeconfig, sizeof(i2c_buffer->led_matrix));
led_matrix_set_suspend_state(i2c_buffer->led_suspend_state);
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
memcpy((void *)i2c_buffer->rgb_matrix, (void *)rgb_matrix_config, sizeof(i2c_buffer->rgb_matrix));
rgb_matrix_set_suspend_state(i2c_buffer->rgb_suspend_state);
# endif
}
void transport_master_init(void) { i2c_init(); }
void transport_slave_init(void) { i2c_slave_init(SLAVE_I2C_ADDRESS); }
#else // USE_SERIAL
# include "serial.h"
typedef struct _Serial_s2m_buffer_t {
// TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
matrix_row_t smatrix[ROWS_PER_HAND];
# ifdef ENCODER_ENABLE
uint8_t encoder_state[NUMBER_OF_ENCODERS];
# endif
int8_t mouse_x;
int8_t mouse_y;
} __attribute__((packed)) Serial_s2m_buffer_t;
typedef struct _Serial_m2s_buffer_t {
# ifdef SPLIT_MODS_ENABLE
uint8_t real_mods;
uint8_t weak_mods;
# ifndef NO_ACTION_ONESHOT
uint8_t oneshot_mods;
# endif
# endif
# ifndef DISABLE_SYNC_TIMER
uint32_t sync_timer;
# endif
# ifdef SPLIT_TRANSPORT_MIRROR
matrix_row_t mmatrix[ROWS_PER_HAND];
# endif
# ifdef BACKLIGHT_ENABLE
uint8_t backlight_level;
# endif
# ifdef WPM_ENABLE
uint8_t current_wpm;
# endif
uint16_t device_cpi;
bool oled_on;
layer_state_t t_layer_state;
layer_state_t t_default_layer_state;
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
led_eeconfig_t led_matrix;
bool led_suspend_state;
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
rgb_config_t rgb_matrix;
bool rgb_suspend_state;
# endif
} __attribute__((packed)) Serial_m2s_buffer_t;
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// When MCUs on both sides drive their respective RGB LED chains,
// it is necessary to synchronize, so it is necessary to communicate RGB
// information. In that case, define RGBLIGHT_SPLIT with info on the number
// of LEDs on each half.
//
// Otherwise, if the master side MCU drives both sides RGB LED chains,
// there is no need to communicate.
typedef struct _Serial_rgblight_t {
rgblight_syncinfo_t rgblight_sync;
} Serial_rgblight_t;
volatile Serial_rgblight_t serial_rgblight = {};
uint8_t volatile status_rgblight = 0;
# endif
volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
uint8_t volatile status0 = 0;
enum serial_transaction_id {
GET_SLAVE_MATRIX = 0,
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
PUT_RGBLIGHT,
# endif
};
SSTD_t transactions[] = {
[GET_SLAVE_MATRIX] =
{
(uint8_t *)&status0,
sizeof(serial_m2s_buffer),
(uint8_t *)&serial_m2s_buffer,
sizeof(serial_s2m_buffer),
(uint8_t *)&serial_s2m_buffer,
},
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
[PUT_RGBLIGHT] =
{
(uint8_t *)&status_rgblight, sizeof(serial_rgblight), (uint8_t *)&serial_rgblight, 0, NULL // no slave to master transfer
},
# endif
};
void transport_master_init(void) { soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
void transport_slave_init(void) { soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
# if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// rgblight synchronization information communication.
void transport_rgblight_master(void) {
if (rgblight_get_change_flags()) {
rgblight_get_syncinfo((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync);
if (soft_serial_transaction(PUT_RGBLIGHT) == TRANSACTION_END) {
rgblight_clear_change_flags();
}
}
}
void transport_rgblight_slave(void) {
if (status_rgblight == TRANSACTION_ACCEPTED) {
rgblight_update_sync((rgblight_syncinfo_t *)&serial_rgblight.rgblight_sync, false);
status_rgblight = TRANSACTION_END;
}
}
# else
# define transport_rgblight_master()
# define transport_rgblight_slave()
# endif
bool transport_master(matrix_row_t master_matrix[], matrix_row_t slave_matrix[]) {
# ifndef SERIAL_USE_MULTI_TRANSACTION
if (soft_serial_transaction() != TRANSACTION_END) {
return false;
}
# else
transport_rgblight_master();
if (soft_serial_transaction(GET_SLAVE_MATRIX) != TRANSACTION_END) {
return false;
}
# endif
// TODO: if MATRIX_COLS > 8 change to unpack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
slave_matrix[i] = serial_s2m_buffer.smatrix[i];
# ifdef SPLIT_TRANSPORT_MIRROR
serial_m2s_buffer.mmatrix[i] = master_matrix[i];
# endif
}
# ifdef BACKLIGHT_ENABLE
// Write backlight level for slave to read
serial_m2s_buffer.backlight_level = is_backlight_enabled() ? get_backlight_level() : 0;
# endif
# ifdef ENCODER_ENABLE
encoder_update_raw((uint8_t *)serial_s2m_buffer.encoder_state);
# endif
# ifdef WPM_ENABLE
// Write wpm to slave
serial_m2s_buffer.current_wpm = get_current_wpm();
# endif
# ifdef SPLIT_MODS_ENABLE
serial_m2s_buffer.real_mods = get_mods();
serial_m2s_buffer.weak_mods = get_weak_mods();
# ifndef NO_ACTION_ONESHOT
serial_m2s_buffer.oneshot_mods = get_oneshot_mods();
# endif
# endif
# ifdef POINTING_DEVICE_ENABLE
if (is_keyboard_left()) {
report_mouse_t temp_report = pointing_device_get_report();
temp_report.x = serial_s2m_buffer.mouse_x;
temp_report.y = serial_s2m_buffer.mouse_y;
pointing_device_set_report(temp_report);
serial_m2s_buffer.device_cpi = device_cpi;
}
# endif
serial_m2s_buffer.t_layer_state = layer_state;
serial_m2s_buffer.t_default_layer_state = default_layer_state;
# ifdef OLED_DRIVER_ENABLE
serial_m2s_buffer.oled_on = is_oled_on();
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
serial_m2s_buffer.led_matrix = led_matrix_eeconfig;
serial_m2s_buffer.led_suspend_state = led_matrix_get_suspend_state();
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
serial_m2s_buffer.rgb_matrix = rgb_matrix_config;
serial_m2s_buffer.rgb_suspend_state = rgb_matrix_get_suspend_state();
# 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 master_matrix[], matrix_row_t slave_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] = slave_matrix[i];
# ifdef SPLIT_TRANSPORT_MIRROR
master_matrix[i] = serial_m2s_buffer.mmatrix[i];
# endif
}
# ifdef BACKLIGHT_ENABLE
backlight_set(serial_m2s_buffer.backlight_level);
# endif
# ifdef ENCODER_ENABLE
encoder_state_raw((uint8_t *)serial_s2m_buffer.encoder_state);
# endif
# ifdef WPM_ENABLE
set_current_wpm(serial_m2s_buffer.current_wpm);
# endif
# ifdef SPLIT_MODS_ENABLE
set_mods(serial_m2s_buffer.real_mods);
set_weak_mods(serial_m2s_buffer.weak_mods);
# ifndef NO_ACTION_ONESHOT
set_oneshot_mods(serial_m2s_buffer.oneshot_mods);
# endif
# endif
# ifdef POINTING_DEVICE_ENABLE
if (!is_keyboard_left()) {
static uint16_t cpi;
if (cpi != serial_m2s_buffer.device_cpi) {
cpi = serial_m2s_buffer.device_cpi;
pmw_set_cpi(cpi);
}
serial_s2m_buffer.mouse_x = split_mouse_x;
serial_s2m_buffer.mouse_y = split_mouse_y;
}
# endif
if (layer_state != serial_m2s_buffer.t_layer_state) {
layer_state = serial_m2s_buffer.t_layer_state;
}
if (default_layer_state != serial_m2s_buffer.t_default_layer_state) {
default_layer_state = serial_m2s_buffer.t_default_layer_state;
}
# ifdef OLED_DRIVER_ENABLE
if (serial_m2s_buffer.oled_on) {
oled_on();
} else {
oled_off();
}
# endif
# if defined(LED_MATRIX_ENABLE) && defined(LED_MATRIX_SPLIT)
led_matrix_eeconfig = serial_m2s_buffer.led_matrix;
led_matrix_set_suspend_state(serial_m2s_buffer.led_suspend_state);
# endif
# if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_SPLIT)
rgb_matrix_config = serial_m2s_buffer.rgb_matrix;
rgb_matrix_set_suspend_state(serial_m2s_buffer.rgb_suspend_state);
# endif
}
#endif

View File

@ -25,7 +25,7 @@
#endif
uint32_t oled_timer = 0;
static char keylog_str[KEYLOGGER_LENGTH + 1] = {"\n"};
static char keylog_str[KEYLOGGER_LENGTH + 1] = { 0 };
static uint16_t log_timer = 0;
// clang-format off
@ -57,12 +57,12 @@ void add_keylog(uint16_t keycode) {
keycode = 0;
}
for (uint8_t i = (KEYLOGGER_LENGTH - 1); i > 0; --i) {
keylog_str[i] = keylog_str[i - 1];
for (uint8_t i = 1; i < KEYLOGGER_LENGTH; i++) {
keylog_str[i-1] = keylog_str[i];
}
if (keycode < (sizeof(code_to_name) / sizeof(char))) {
keylog_str[0] = pgm_read_byte(&code_to_name[keycode]);
keylog_str[(KEYLOGGER_LENGTH - 1)] = pgm_read_byte(&code_to_name[keycode]);
}
log_timer = timer_read();
@ -92,30 +92,14 @@ void render_keylogger_status(void) {
void render_default_layer_state(void) {
oled_write_P(PSTR(OLED_RENDER_LAYOUT_NAME), false);
switch (get_highest_layer(default_layer_state)) {
case _QWERTY:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_QWERTY), false);
break;
case _COLEMAK:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_COLEMAK), false);
break;
case _DVORAK:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_DVORAK), false);
break;
case _WORKMAN:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_WORKMAN), false);
break;
case _NORMAN:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_NORMAN), false);
break;
case _MALTRON:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_MALTRON), false);
break;
case _EUCALYN:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_EUCALYN), false);
break;
case _CARPLAX:
oled_write_P(PSTR(OLED_RENDER_LAYOUT_CARPLAX), false);
break;
case _QWERTY: oled_write_P(PSTR(OLED_RENDER_LAYOUT_QWERTY), false); break;
case _COLEMAK: oled_write_P(PSTR(OLED_RENDER_LAYOUT_COLEMAK), false); break;
case _DVORAK: oled_write_P(PSTR(OLED_RENDER_LAYOUT_DVORAK), false); break;
case _WORKMAN: oled_write_P(PSTR(OLED_RENDER_LAYOUT_WORKMAN), false); break;
case _NORMAN: oled_write_P(PSTR(OLED_RENDER_LAYOUT_NORMAN), false); break;
case _MALTRON: oled_write_P(PSTR(OLED_RENDER_LAYOUT_MALTRON), false); break;
case _EUCALYN: oled_write_P(PSTR(OLED_RENDER_LAYOUT_EUCALYN), false); break;
case _CARPLAX: oled_write_P(PSTR(OLED_RENDER_LAYOUT_CARPLAX), false); break;
}
#ifdef OLED_DISPLAY_128X64
oled_advance_page(true);
@ -284,6 +268,10 @@ void render_user_status(void) {
oled_write_P(rgb_layer_status[userspace_config.rgb_layer_change], false);
static const char PROGMEM nukem_good[2][3] = {{0xF8, 0xF9, 0}, {0xF6, 0xF7, 0}};
oled_write_P(nukem_good[0], userspace_config.nuke_switch);
#if defined(UNICODE_ENABLE)
static const char PROGMEM uc_mod_status[5][3] = {{0xEA, 0xEB, 0}, {0xEC, 0xED, 0}};
oled_write_P(uc_mod_status[get_unicode_input_mode() == UC_MAC], false);
#endif
#if defined(OLED_DISPLAY_128X64)
oled_advance_page(true);
#endif
@ -322,7 +310,7 @@ void render_wpm(void) {
#endif
}
#ifdef KEYBOARD_handwired_dactyl_manuform_5x6_right_trackball
#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
extern keyboard_config_t keyboard_config;
extern uint16_t dpi_array[];
@ -360,7 +348,7 @@ void render_status_main(void) {
# else
render_wpm();
# endif
# ifdef KEYBOARD_handwired_dactyl_manuform_5x6_right_trackball
# if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
render_pointing_dpi_status();
# endif
oled_write_P(PSTR("\n"), false);
@ -375,6 +363,15 @@ void render_status_main(void) {
render_keylogger_status();
}
__attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return rotation; }
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
for (uint8_t i = 0; i < (KEYLOGGER_LENGTH - 1); i++) {
add_keylog(0);
}
return oled_init_keymap(rotation);
}
void oled_task_user(void) {
update_log();

View File

@ -21,6 +21,7 @@
void oled_driver_render_logo(void);
bool process_record_user_oled(uint16_t keycode, keyrecord_t *record);
oled_rotation_t oled_init_keymap(oled_rotation_t rotation);
extern uint32_t oled_timer;
#ifdef OLED_DISPLAY_128X64

View File

@ -91,17 +91,13 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
break;
case VRSN: // Prints firmware version
if (record->event.pressed) {
send_string_with_delay_P(PSTR(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE), TAP_CODE_DELAY);
}
if (record->event.pressed) { send_string_with_delay_P(PSTR(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE), TAP_CODE_DELAY); }
break;
case KC_DIABLO_CLEAR: // reset all Diablo timers, disabling them
#ifdef TAP_DANCE_ENABLE
if (record->event.pressed) {
for (uint8_t index = 0; index < 4; index++) {
diablo_timer[index].key_interval = 0;
}
for (uint8_t index = 0; index < 4; index++) { diablo_timer[index].key_interval = 0; }
}
#endif // TAP_DANCE_ENABLE
break;
@ -119,24 +115,16 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
break;
#ifdef UNICODE_ENABLE
case UC_FLIP: // (ノಠ痊ಠ)ノ彡┻━┻
if (record->event.pressed) {
send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻");
}
if (record->event.pressed) { send_unicode_string("(ノಠ痊ಠ)ノ彡┻━┻"); }
break;
case UC_TABL: // ┬─┬ノ( º _ ºノ)
if (record->event.pressed) {
send_unicode_string("┬─┬ノ( º _ ºノ)");
}
if (record->event.pressed) { send_unicode_string("┬─┬ノ( º _ ºノ)"); }
break;
case UC_SHRG: // ¯\_(ツ)_/¯
if (record->event.pressed) {
send_unicode_string("¯\\_(ツ)_/¯");
}
if (record->event.pressed) { send_unicode_string("¯\\_(ツ)_/¯"); }
break;
case UC_DISA: // ಠ_ಠ
if (record->event.pressed) {
send_unicode_string("ಠ_ಠ");
}
if (record->event.pressed) { send_unicode_string("ಠ_ಠ"); }
break;
#endif
case KC_RGB_T: // This allows me to use underglow as layer indication, or as normal
@ -194,9 +182,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
is_eeprom_updated = true;
}
# endif
if (is_eeprom_updated) {
eeconfig_update_user(userspace_config.raw);
}
if (is_eeprom_updated) { eeconfig_update_user(userspace_config.raw); }
}
#endif
}

View File

@ -17,7 +17,7 @@
#pragma once
#include "drashna.h"
#if defined(KEYBOARD_handwired_dactyl_manuform_5x6_right_trackball)
#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
# define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE
#else
# define PLACEHOLDER_SAFE_RANGE SAFE_RANGE

View File

@ -28,9 +28,7 @@ static uint32_t hypno_timer;
void rgb_matrix_layer_helper(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode, uint8_t speed, uint8_t led_type, uint8_t led_min, uint8_t led_max) {
HSV hsv = {hue, sat, val};
if (hsv.v > rgb_matrix_get_val()) {
hsv.v = rgb_matrix_get_val();
}
if (hsv.v > rgb_matrix_get_val()) { hsv.v = rgb_matrix_get_val(); }
switch (mode) {
case 1: // breathing
@ -39,9 +37,7 @@ void rgb_matrix_layer_helper(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode
hsv.v = scale8(abs8(sin8(time) - 128) * 2, hsv.v);
RGB rgb = hsv_to_rgb(hsv);
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
if (HAS_FLAGS(g_led_config.flags[i], led_type)) {
RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b);
}
if (HAS_FLAGS(g_led_config.flags[i], led_type)) { RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b); }
}
break;
}
@ -49,9 +45,7 @@ void rgb_matrix_layer_helper(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode
{
RGB rgb = hsv_to_rgb(hsv);
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
if (HAS_FLAGS(g_led_config.flags[i], led_type)) {
RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b);
}
if (HAS_FLAGS(g_led_config.flags[i], led_type)) { RGB_MATRIX_INDICATOR_SET_COLOR(i, rgb.r, rgb.g, rgb.b); }
}
break;
}
@ -62,27 +56,21 @@ __attribute__((weak)) void rgb_matrix_indicator_keymap(void) {}
void matrix_scan_rgb_matrix(void) {
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
if (userspace_config.rgb_matrix_idle_anim && rgb_matrix_get_mode() == RGB_MATRIX_TYPING_HEATMAP && sync_timer_elapsed32(hypno_timer) > 15000) {
rgb_matrix_mode_noeeprom(RGB_MATRIX_REST_MODE);
}
if (userspace_config.rgb_matrix_idle_anim && rgb_matrix_get_mode() == RGB_MATRIX_TYPING_HEATMAP && sync_timer_elapsed32(hypno_timer) > 15000) { rgb_matrix_mode_noeeprom(RGB_MATRIX_REST_MODE); }
#endif
rgb_matrix_indicator_keymap();
}
void keyboard_post_init_rgb_matrix(void) {
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
if (userspace_config.rgb_matrix_idle_anim) {
rgb_matrix_mode_noeeprom(RGB_MATRIX_REST_MODE);
}
if (userspace_config.rgb_matrix_idle_anim) { rgb_matrix_mode_noeeprom(RGB_MATRIX_REST_MODE); }
#endif
}
bool process_record_user_rgb_matrix(uint16_t keycode, keyrecord_t *record) {
#if defined(RGB_MATRIX_FRAMEBUFFER_EFFECTS)
hypno_timer = sync_timer_read32();
if (userspace_config.rgb_matrix_idle_anim && rgb_matrix_get_mode() == RGB_MATRIX_REST_MODE) {
rgb_matrix_mode_noeeprom(RGB_MATRIX_TYPING_HEATMAP);
}
if (userspace_config.rgb_matrix_idle_anim && rgb_matrix_get_mode() == RGB_MATRIX_REST_MODE) { rgb_matrix_mode_noeeprom(RGB_MATRIX_TYPING_HEATMAP); }
#endif
switch (keycode) {
case RGB_IDL: // This allows me to use underglow as layer indication, or as normal
@ -91,9 +79,7 @@ bool process_record_user_rgb_matrix(uint16_t keycode, keyrecord_t *record) {
userspace_config.rgb_matrix_idle_anim ^= 1;
dprintf("RGB Matrix Idle Animation [EEPROM]: %u\n", userspace_config.rgb_matrix_idle_anim);
eeconfig_update_user(userspace_config.raw);
if (userspace_config.rgb_matrix_idle_anim) {
rgb_matrix_mode_noeeprom(RGB_MATRIX_TYPING_HEATMAP);
}
if (userspace_config.rgb_matrix_idle_anim) { rgb_matrix_mode_noeeprom(RGB_MATRIX_TYPING_HEATMAP); }
}
#endif
break;

View File

@ -38,21 +38,15 @@ void scan_rgblight_fadeout(void) { // Don't effing change this function .... rg
if (light->life) {
light->life -= 1;
if (get_highest_layer(layer_state) == 0) {
sethsv(light->hue + rand() % 0xF, 255, light->life, (LED_TYPE *)&led[light_index]);
}
if (get_highest_layer(layer_state) == 0) { sethsv(light->hue + rand() % 0xF, 255, light->life, (LED_TYPE *)&led[light_index]); }
light->timer = sync_timer_read();
} else {
if (light->enabled && get_highest_layer(layer_state) == 0) {
rgblight_sethsv_default_helper(light_index);
}
if (light->enabled && get_highest_layer(layer_state) == 0) { rgblight_sethsv_default_helper(light_index); }
litup = light->enabled = false;
}
}
}
if (litup && get_highest_layer(layer_state) == 0) {
rgblight_set();
}
if (litup && get_highest_layer(layer_state) == 0) { rgblight_set(); }
}
/* Triggers a LED to fade/twinkle.
@ -98,9 +92,7 @@ void start_rgb_light(void) {
bool process_record_user_rgb_light(uint16_t keycode, keyrecord_t *record) {
uint16_t temp_keycode = keycode;
// Filter out the actual keycode from MT and LT keys.
if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
temp_keycode &= 0xFF;
}
if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { temp_keycode &= 0xFF; }
switch (temp_keycode) {
# ifdef RGBLIGHT_TWINKLE
@ -110,9 +102,7 @@ bool process_record_user_rgb_light(uint16_t keycode, keyrecord_t *record) {
case KC_KP_SLASH ... KC_KP_DOT:
case KC_F13 ... KC_F24:
case KC_AUDIO_MUTE ... KC_MEDIA_REWIND:
if (record->event.pressed) {
start_rgb_light();
}
if (record->event.pressed) { start_rgb_light(); }
break;
# endif // RGBLIGHT_TWINKLE
}
@ -129,9 +119,7 @@ static uint16_t rgblight_startup_loop_timer;
void keyboard_post_init_rgb_light(void) {
# if defined(RGBLIGHT_STARTUP_ANIMATION)
is_enabled = rgblight_is_enabled();
if (userspace_config.rgb_layer_change) {
rgblight_enable_noeeprom();
}
if (userspace_config.rgb_layer_change) { rgblight_enable_noeeprom(); }
if (rgblight_is_enabled()) {
layer_state_set_rgb_light(layer_state);
old_hue = rgblight_get_hue();
@ -156,12 +144,8 @@ void matrix_scan_rgb_light(void) {
rgblight_startup_loop_timer = sync_timer_read();
if (counter == 255) {
is_rgblight_startup = false;
if (!is_enabled) {
rgblight_disable_noeeprom();
}
if (userspace_config.rgb_layer_change) {
layer_state_set_rgb_light(layer_state);
}
if (!is_enabled) { rgblight_disable_noeeprom(); }
if (userspace_config.rgb_layer_change) { layer_state_set_rgb_light(layer_state); }
}
}
}
@ -179,52 +163,22 @@ layer_state_t layer_state_set_rgb_light(layer_state_t state) {
if (userspace_config.rgb_layer_change) {
switch (get_highest_layer(state | default_layer_state)) {
case _MACROS: // mouse
if (!layer_state_cmp(state, _GAMEPAD) && !layer_state_cmp(state, _DIABLO)) {
rgblight_set_hsv_and_mode(HSV_CHARTREUSE, RGBLIGHT_MODE_BREATHING + 3);
}
break;
case _MEDIA:
rgblight_set_hsv_and_mode(HSV_CHARTREUSE, RGBLIGHT_MODE_KNIGHT + 1);
break;
case _GAMEPAD:
rgblight_set_hsv_and_mode(HSV_ORANGE, RGBLIGHT_MODE_SNAKE + 2);
break;
case _DIABLO:
rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_BREATHING + 3);
break;
case _RAISE:
rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_BREATHING + 3);
break;
case _LOWER:
rgblight_set_hsv_and_mode(HSV_GREEN, RGBLIGHT_MODE_BREATHING + 3);
break;
case _ADJUST:
rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_KNIGHT + 2);
break;
case _COLEMAK:
rgblight_set_hsv_and_mode(HSV_MAGENTA, RGBLIGHT_MODE_STATIC_LIGHT);
break;
case _DVORAK:
rgblight_set_hsv_and_mode(HSV_SPRINGGREEN, RGBLIGHT_MODE_STATIC_LIGHT);
break;
case _WORKMAN:
rgblight_set_hsv_and_mode(HSV_GOLDENROD, RGBLIGHT_MODE_STATIC_LIGHT);
break;
case _NORMAN:
rgblight_set_hsv_and_mode(HSV_CORAL, RGBLIGHT_MODE_STATIC_LIGHT);
break;
case _MALTRON:
rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_STATIC_LIGHT);
break;
case _EUCALYN:
rgblight_set_hsv_and_mode(HSV_PINK, RGBLIGHT_MODE_STATIC_LIGHT);
break;
case _CARPLAX:
rgblight_set_hsv_and_mode(HSV_BLUE, RGBLIGHT_MODE_STATIC_LIGHT);
break;
default:
rgblight_set_hsv_and_mode(HSV_CYAN, RGBLIGHT_MODE_STATIC_LIGHT);
if (!layer_state_cmp(state, _GAMEPAD) && !layer_state_cmp(state, _DIABLO)) { rgblight_set_hsv_and_mode(HSV_CHARTREUSE, RGBLIGHT_MODE_BREATHING + 3); }
break;
case _MEDIA: rgblight_set_hsv_and_mode(HSV_CHARTREUSE, RGBLIGHT_MODE_KNIGHT + 1); break;
case _GAMEPAD: rgblight_set_hsv_and_mode(HSV_ORANGE, RGBLIGHT_MODE_SNAKE + 2); break;
case _DIABLO: rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_BREATHING + 3); break;
case _RAISE: rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_BREATHING + 3); break;
case _LOWER: rgblight_set_hsv_and_mode(HSV_GREEN, RGBLIGHT_MODE_BREATHING + 3); break;
case _ADJUST: rgblight_set_hsv_and_mode(HSV_RED, RGBLIGHT_MODE_KNIGHT + 2); break;
case _COLEMAK: rgblight_set_hsv_and_mode(HSV_MAGENTA, RGBLIGHT_MODE_STATIC_LIGHT); break;
case _DVORAK: rgblight_set_hsv_and_mode(HSV_SPRINGGREEN, RGBLIGHT_MODE_STATIC_LIGHT); break;
case _WORKMAN: rgblight_set_hsv_and_mode(HSV_GOLDENROD, RGBLIGHT_MODE_STATIC_LIGHT); break;
case _NORMAN: rgblight_set_hsv_and_mode(HSV_CORAL, RGBLIGHT_MODE_STATIC_LIGHT); break;
case _MALTRON: rgblight_set_hsv_and_mode(HSV_YELLOW, RGBLIGHT_MODE_STATIC_LIGHT); break;
case _EUCALYN: rgblight_set_hsv_and_mode(HSV_PINK, RGBLIGHT_MODE_STATIC_LIGHT); break;
case _CARPLAX: rgblight_set_hsv_and_mode(HSV_BLUE, RGBLIGHT_MODE_STATIC_LIGHT); break;
default: rgblight_set_hsv_and_mode(HSV_CYAN, RGBLIGHT_MODE_STATIC_LIGHT); break;
}
}
# endif // RGBLIGHT_ENABLE

View File

@ -80,28 +80,29 @@ endif
CUSTOM_SPLIT_TRANSPORT ?= yes
ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
ifneq ($(strip $(SPLIT_TRANSPORT)), custom)
ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT)), yes)
SPLIT_TRANSPORT = custom
QUANTUM_LIB_SRC += drashna_transport.c
OPT_DEFS += -DDRASHNA_CUSTOM_TRANSPORT
# Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
ifeq ($(PLATFORM),AVR)
ifneq ($(NO_I2C),yes)
QUANTUM_LIB_SRC += i2c_master.c \
i2c_slave.c
endif
endif
QUANTUM_LIB_SRC += transport_sync.c
# ifneq ($(strip $(SPLIT_TRANSPORT)), custom)
# ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT)), yes)
# SPLIT_TRANSPORT = custom
# QUANTUM_LIB_SRC += drashna_transport.c
# OPT_DEFS += -DDRASHNA_CUSTOM_TRANSPORT
# # Unused functions are pruned away, which is why we can add multiple drivers here without bloat.
# ifeq ($(PLATFORM),AVR)
# ifneq ($(NO_I2C),yes)
# QUANTUM_LIB_SRC += i2c_master.c \
# i2c_slave.c
# endif
# endif
SERIAL_DRIVER ?= bitbang
OPT_DEFS += -DSERIAL_DRIVER_$(strip $(shell echo $(SERIAL_DRIVER) | tr '[:lower:]' '[:upper:]'))
ifeq ($(strip $(SERIAL_DRIVER)), bitbang)
QUANTUM_LIB_SRC += serial.c
else
QUANTUM_LIB_SRC += serial_$(strip $(SERIAL_DRIVER)).c
endif
endif
endif
# SERIAL_DRIVER ?= bitbang
# OPT_DEFS += -DSERIAL_DRIVER_$(strip $(shell echo $(SERIAL_DRIVER) | tr '[:lower:]' '[:upper:]'))
# ifeq ($(strip $(SERIAL_DRIVER)), bitbang)
# QUANTUM_LIB_SRC += serial.c
# else
# QUANTUM_LIB_SRC += serial_$(strip $(SERIAL_DRIVER)).c
# endif
# endif
# endif
endif
# DEBUG_MATRIX_SCAN_RATE_ENABLE = api

View File

@ -64,9 +64,7 @@ void run_diablo_macro_check(void) {
// reset the timer, since enough time has passed
diablo_timer[index].timer = timer_read();
// send keycode ONLY if we're on the diablo layer.
if (IS_LAYER_ON(_DIABLO)) {
tap_code(diablo_timer[index].keycode);
}
if (IS_LAYER_ON(_DIABLO)) { tap_code(diablo_timer[index].keycode); }
}
}
}

View File

@ -54,9 +54,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
break;
case VRSN:
if (record->event.pressed) {
SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
}
if (record->event.pressed) { SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION); }
return false;
break;
}

View File

@ -0,0 +1,80 @@
#ifdef SPLIT_TRANSACTION_IDS_USER
#include "transport_sync.h"
#include "transactions.h"
#include <string.h>
typedef struct {
bool oled_on;
uint16_t keymap_config;
} user_runtime_config_t;
user_runtime_config_t user_state;
void user_sync(uint8_t initiator2target_buffer_size, const void* initiator2target_buffer, uint8_t target2initiator_buffer_size, void* target2initiator_buffer) {
if (initiator2target_buffer_size == sizeof(user_state)) {
memcpy(&user_state, initiator2target_buffer, initiator2target_buffer_size);
}
}
void keyboard_post_init_transport_sync(void) {
// Register keyboard state sync split transaction
transaction_register_rpc(RPC_ID_USER_STATE_SYNC, user_sync);
}
void user_state_update(void) {
if (is_keyboard_master()) {
#ifdef OLED_DRIVER_ENABLE
user_state.oled_on = is_oled_on();
#endif
user_state.keymap_config = keymap_config.raw;
} else {
#ifdef OLED_DRIVER_ENABLE
if (user_state.oled_on) {
oled_on();
} else {
oled_off();
}
#endif
if (keymap_config.raw != user_state.keymap_config) {
keymap_config.raw = user_state.keymap_config;
}
}
}
void user_state_sync(void) {
if (is_keyboard_master()) {
// Keep track of the last state, so that we can tell if we need to propagate to slave
static user_runtime_config_t last_user_state;
static uint32_t last_sync;
bool needs_sync = false;
// Check if the state values are different
if (memcmp(&user_state, &last_user_state, sizeof(user_state))) {
needs_sync = true;
memcpy(&last_user_state, &user_state, sizeof(user_state));
}
// Send to slave every 500ms regardless of state change
if (timer_elapsed32(last_sync) > 250) {
needs_sync = true;
}
// Perform the sync if requested
if (needs_sync) {
if (transaction_rpc_send(RPC_ID_USER_STATE_SYNC, sizeof(user_state), &user_state)) {
last_sync = timer_read32();
}
}
}
}
void housekeeping_task_user(void) {
// Update kb_state so we can send to slave
user_state_update();
// Data sync from master to slave
user_state_sync();
}
#endif

View File

@ -1,3 +1,4 @@
/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
*
* This program is free software: you can redistribute it and/or modify
@ -14,9 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "drashna.h"
#include "../drashna/config.h"
void keyboard_post_init_transport_sync(void);