Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Junco Keyboard #19516

Merged
merged 5 commits into from
Apr 5, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions keyboards/junco/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
{
"manufacturer": "Dane Skalski",
"keyboard_name": "Junco",
"url": "https://github.com/Daneski13/Junco",
"maintainer": "Daneski13",
"usb": {
"vid": "0x4413",
"pid": "0x4A13",
"device_version": "1.0.0"
},
daneski13 marked this conversation as resolved.
Show resolved Hide resolved
"layouts": {
"LAYOUT_split4x6_r1": {
"layout": [
{ "label": "`", "matrix": [0, 0], "x": 0, "y": 0.7 },
{ "label": "1", "matrix": [0, 1], "x": 1, "y": 0.7 },
{ "label": "2", "matrix": [0, 2], "x": 2, "y": 0.3 },
{ "label": "3", "matrix": [0, 3], "x": 3, "y": 0 },
{ "label": "4", "matrix": [0, 4], "x": 4, "y": 0.3 },
{ "label": "5", "matrix": [0, 5], "x": 5, "y": 0.45 },
{ "label": "6", "matrix": [5, 5], "x": 9, "y": 0.45 },
{ "label": "7", "matrix": [5, 4], "x": 10, "y": 0.3 },
{ "label": "8", "matrix": [5, 3], "x": 11, "y": 0 },
{ "label": "9", "matrix": [5, 2], "x": 12, "y": 0.3 },
{ "label": "0", "matrix": [5, 1], "x": 13, "y": 0.7 },
{ "label": "-", "matrix": [5, 0], "x": 14, "y": 0.7 },

{ "label": "Tab", "matrix": [1, 0], "x": 0, "y": 1.7 },
{ "label": "Q", "matrix": [1, 1], "x": 1, "y": 1.7 },
{ "label": "W", "matrix": [1, 2], "x": 2, "y": 1.3 },
{ "label": "E", "matrix": [1, 3], "x": 3, "y": 1 },
{ "label": "R", "matrix": [1, 4], "x": 4, "y": 1.3 },
{ "label": "T", "matrix": [1, 5], "x": 5, "y": 1.45 },
{ "label": "Y", "matrix": [6, 5], "x": 9, "y": 1.45 },
{ "label": "U", "matrix": [6, 4], "x": 10, "y": 1.3 },
{ "label": "I", "matrix": [6, 3], "x": 11, "y": 1 },
{ "label": "O", "matrix": [6, 2], "x": 12, "y": 1.3 },
{ "label": "P", "matrix": [6, 1], "x": 13, "y": 1.7 },
{ "label": "Enter", "matrix": [6, 0], "x": 14, "y": 1.7 },

{ "label": "Esc", "matrix": [2, 0], "x": 0, "y": 2.7 },
{ "label": "A", "matrix": [2, 1], "x": 1, "y": 2.7 },
{ "label": "S", "matrix": [2, 2], "x": 2, "y": 2.3 },
{ "label": "D", "matrix": [2, 3], "x": 3, "y": 2 },
{ "label": "F", "matrix": [2, 4], "x": 4, "y": 2.3 },
{ "label": "G", "matrix": [2, 5], "x": 5, "y": 2.45 },
{ "label": "H", "matrix": [7, 5], "x": 9, "y": 2.45 },
{ "label": "J", "matrix": [7, 4], "x": 10, "y": 2.3 },
{ "label": "K", "matrix": [7, 3], "x": 11, "y": 2 },
{ "label": "L", "matrix": [7, 2], "x": 12, "y": 2.3 },
{ "label": ";", "matrix": [7, 1], "x": 13, "y": 2.7 },
{ "label": "'", "matrix": [7, 0], "x": 14, "y": 2.7 },

{ "label": "Shift", "matrix": [3, 0], "x": 0, "y": 3.7 },
{ "label": "Z", "matrix": [3, 1], "x": 1, "y": 3.7 },
{ "label": "X", "matrix": [3, 2], "x": 2, "y": 3.3 },
{ "label": "C", "matrix": [3, 3], "x": 3, "y": 3 },
{ "label": "V", "matrix": [3, 4], "x": 4, "y": 3.3 },
{ "label": "B", "matrix": [3, 5], "x": 5, "y": 3.45 },
{ "label": "Mute", "matrix": [4, 5], "x": 6.2, "y": 3.45 },
{ "label": "XXX", "matrix": [9, 5], "x": 7.8, "y": 3.45 },
{ "label": "N", "matrix": [8, 5], "x": 9, "y": 3.45 },
{ "label": "M", "matrix": [8, 4], "x": 10, "y": 3.3 },
{ "label": ",", "matrix": [8, 3], "x": 11, "y": 3 },
{ "label": ".", "matrix": [8, 2], "x": 12, "y": 3.3 },
{ "label": "/", "matrix": [8, 1], "x": 13, "y": 3.7 },
{ "label": "Shift", "matrix": [8, 0], "x": 14, "y": 3.7 },

{ "label": "Ctrl", "matrix": [4, 0], "x": 2, "y": 4.3 },
{ "label": "Win", "matrix": [4, 1], "x": 3, "y": 4 },
{ "label": "Alt", "matrix": [4, 2], "x": 4, "y": 4.3 },
{ "label": "Del", "matrix": [4, 3], "x": 5.1, "y": 4.5, "h": 1.5 },
{ "label": "Spc", "matrix": [4, 4], "x": 6.1, "y": 4.5, "h": 1.5 },
{ "label": "Shift", "matrix": [9, 3], "x": 7.9, "y": 4.5, "h": 1.5 },
{ "label": "Bspc", "matrix": [9, 4], "x": 8.9, "y": 4.5, "h": 1.5 },
{ "label": "Alt", "matrix": [9, 2], "x": 10, "y": 4.3 },
{ "label": "Win", "matrix": [9, 1], "x": 11, "y": 4 },
{ "label": "Ctrl", "matrix": [9, 0], "x": 12, "y": 4.3 }
]
}
}
}
198 changes: 198 additions & 0 deletions keyboards/junco/junco.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// Copyright 2022 Dane Skalski (@Daneski13)
daneski13 marked this conversation as resolved.
Show resolved Hide resolved
// SPDX-License-Identifier: GPL-2.0-or-later

#include "junco.h"

// Keyboard level data
kb_config_t kb_config;

#ifdef JUNCO_SYNC_ENABLE

/* Whether to sync flags */
// Whether a reset needs to happen (applies to both sides)
kb_needs_reset_t kb_needs_reset = {.reset = false, .eeprom = false};
// Whether the sides need to sync
bool kb_needs_sync = false;
// Whether the sides need to sync the RGB
bool kb_needs_rgb_sync = false;

/*
Enable/Disable Junco Sync status
(will be synced between sides)
*/
void junco_sync_enable(void) {
if (kb_config.junco_sync_enabled) return;
kb_config.junco_sync_enabled = true;
dprintf("Junco Sync: Enabled\n");
kb_needs_sync = true;
}
void junco_sync_disable(void) {
if (!kb_config.junco_sync_enabled) return;
kb_config.junco_sync_enabled = false;
dprintf("Junco Sync: Disabled\n");
kb_needs_sync = true;
}
bool is_junco_sync_enabled(void) {
return kb_config.junco_sync_enabled;
}

#endif

// With EE_HANDS, if the user didn't explicitly set the handedness at compile time,
// the handedness is cleared with a normal eeconfig_init. This function gets around
// that.
#ifdef EE_HANDS
void eeconfig_init_persist_handedness(void) {
// Clear EEPROM but persist handedness
bool handedness = eeconfig_read_handedness();
eeconfig_init();
eeconfig_update_handedness(handedness);
}
#endif

// Keyboard level EEPROM init
void eeconfig_init_kb(void) {
/* Reset kb eeprom */
kb_config.raw = 0;
kb_config.junco_sync_enabled = true; // Enabled by default
eeconfig_update_kb(kb_config.raw);

// Call the user EEPROM init
eeconfig_init_user();
}

// Keyboard level post init
void keyboard_post_init_kb(void) {
// Read the kb config from EEPROM
kb_config.raw = eeconfig_read_kb();

#ifdef JUNCO_SYNC_ENABLE
printf("Junco Sync available, status: %s\n", kb_config.junco_sync_enabled ? "enabled" : "disabled");

// Register the RPC calls for syncing. Init regardless
// of junco_sync_enabled because if re-enabled, we
// want to be able to sync that state to the slave
// and bring it up-to-date with the master.
junco_sync_init();
#endif

// Call the user post init
keyboard_post_init_user();
}

// Keyboard level intercept of key processing
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
// Call the user key processing first
bool user_process = process_record_user(keycode, record);
// If the user processing returns false, return false
if (!user_process) return false;

#ifdef JUNCO_SYNC_ENABLE
// If Junco sync is disabled, skip
if (!kb_config.junco_sync_enabled) return true;

/*
Intercept EEPROM related keycodes and reboot, setting
flags that will cause syncing
*/
switch (keycode) {
// Intercept eeprom clear/reboot
case QK_CLEAR_EEPROM:
if (record->event.pressed) {
kb_needs_reset.reset = true;
kb_needs_reset.eeprom = true;
}
return false;
case QK_REBOOT:
if (record->event.pressed) {
kb_needs_reset.reset = true;
kb_needs_reset.eeprom = false;
}
return false;

// Intercept all Magic keycodes for extension
case CL_SWAP ... EC_TOGG:
// Set kb_needs_sync on key release because the
// keypress down will be processed normally.
// It will update the master's EEPROM for us
// so we can be absolutely sure the master
// is up to date
if (!record->event.pressed) {
kb_needs_sync = true;
}
break;
// Intercept all RGB keycodes for extension
case RGB_TOG ... RGB_MODE_TWINKLE:
// Process RGB sync on key release because
// we want both events to be processed normally.
// Depending on the user's settings, RGB changes
// may only actually happen on key release.
if (!record->event.pressed) {
kb_needs_rgb_sync = true;
}
break;
// Intercept default layer changes
case QK_DEF_LAYER ... QK_DEF_LAYER_MAX:
// Processes sync on key release because the
// keypress should be processed normally
if (!record->event.pressed) {
kb_needs_sync = true;
}
break;
// Default case
default:
break;
}
#endif

return true;
}

/*
- Keyboard level housekeeping -
Actually where the syncs get called. Housekeeping is called periodically,
so if a sync fails it will be retried in a timely manner, also acts as
a loop that allows junco_sync_reset to work.
*/
void housekeeping_task_kb(void) {
#ifdef JUNCO_SYNC_ENABLE
// If Junco sync is disabled, skip (assuming we don't need to sync it being disabled)
if (!kb_config.junco_sync_enabled && !kb_needs_sync) return;

// Will only actually reset when the kb_needs_reset.reset is true
// Top level because needs to be called on both the slave and master
junco_sync_reset(&kb_needs_reset.reset, &kb_needs_reset.eeprom, NULL);

/* The rest is only for master side */
if (!is_keyboard_master()) return;

// Ensure something actually needs to be synced.
if (!kb_needs_sync && !kb_needs_rgb_sync) return;

// Throttles syncing to the specified speed.
// (Default is sync no faster than once per second)
static uint32_t last_sync = 0;
if (timer_elapsed32(last_sync) < JUNCO_SYNC_THROTTLE) return;

// Update timer
last_sync = timer_read32();

// Check if sync is needed
if (kb_needs_sync) {
// If attempt failed, flag still needs to be true
kb_needs_sync = !junco_sync();
return;
}

if (kb_needs_rgb_sync) {
# ifdef RGB_MATRIX_ENABLE
// If attempt failed, flag still needs to be true
kb_needs_rgb_sync = !junco_sync_rgb();
# else
kb_needs_rgb_sync = false;
# endif
return;
}

#endif
}
51 changes: 51 additions & 0 deletions keyboards/junco/junco.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2022 Dane Skalski (@Daneski13)
daneski13 marked this conversation as resolved.
Show resolved Hide resolved
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "quantum.h"

typedef union {
uint32_t raw;
struct {
bool junco_sync_enabled;
};
} kb_config_t;
// Keyboard level data
extern kb_config_t kb_config;

#ifdef EE_HANDS
// Clear EEPROM but persist handedness
void eeconfig_init_persist_handedness(void);
#endif

#ifdef JUNCO_SYNC_ENABLE
# include "junco_sync.h"

/* Whether to sync flags */
typedef struct {
bool reset;
bool eeprom;
bool previous_failed;
} kb_needs_reset_t;
// Whether a reboot and/or eeprom clear needs to happen (applies to both sides)
extern kb_needs_reset_t kb_needs_reset;
// Whether the sides need to sync
extern bool kb_needs_sync;
// Whether the sides need to sync the RGB
extern bool kb_needs_rgb_sync;

/* Ability to disable/enable Junco Sync and get status*/

// Disables Junco Sync without the need for recompiling the firmware.
// Will sync across both halves.
void junco_sync_disable(void);

// Enables Junco Sync after it has been disabled by junco_sync_disable.
// Will sync across both halves.
void junco_sync_enable(void);

// Whether or not Junco Sync is currently enabled.
bool is_junco_sync_enabled(void);

#endif
Loading