diff --git a/keyboards/junco/README.md b/keyboards/junco/README.md new file mode 100644 index 000000000000..785454ed0b8b --- /dev/null +++ b/keyboards/junco/README.md @@ -0,0 +1,162 @@ +# Junco + +![Junco](https://github.com/Daneski13/Junco/raw/main/img/Junco.webp) + +Junco is a 60% Raspberry Pi Pico powered split keyboard boasting a 4x6 layout with an aggressive columnar stagger. It has 5 "thumb" keys on either side, support for 2-4 rotary encoders, and per-key RGB lighting. + +- Keyboard Maintainer: [Dane Skalski](https://github.com/Daneski13) +- Hardware Supported: Junco PCB, Raspberry Pi Pico +- Hardware Availability: [PCB, Case, Parts List](https://github.com/Daneski13/Junco) + +Remember you have to flash both halves of the keyboard for it to work! + +Make example for this keyboard (after setting up your build environment): + + make junco:default + +Flashing example for this keyboard: + +```bash +# For flashing the left half... +make junco:default:uf2-split-left +# or the qmk cli equivalent: +qmk flash -kb junco --keymap default -bl uf2-split-left + +# For flashing the right half... +make junco:default:uf2-split-right +# or the qmk cli equivalent: +qmk flash -kb junco --keymap default -bl uf2-split-right +``` + +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). + +Does one side of your keyboard think it's the other side? Holding down the `1` key on the left side of your keyboard while plugging it in will tell the left side it's the left side. Holding down the `9` key on the right side of your keyboard while plugging it in will tell the right side it's the right side. + +## Bootloader + +Enter the bootloader in 3 ways: + +- **Bootmagic reset** (works after you have flashed once): Hold down the top far corner key while plugging in the keyboard (`~` left half, `-` right half). This will also clear the EEPROM. +- **Physical reset button**: Hold the `BOOT` button on the Pico and press the `RST` button on the Pico, release the the `RST` button before the `BOOT` button. +- **Keycode in layout**: In the default layout, the `Bootloader` keycode is above home row pinky on the right side's adjust layer. + +Once you enter the bootloader, the keyboard will show up as a USB device on your computer, you could drag and drop a firmware file to flash it, but I recommend using the flash commands for the respective side. + +## Junco Sync + +Junco has a special feature called Junco Sync that will automatically save and sync certain data between the halves of the split. This means that no matter which side you plug in, whenever you change your default layer in a keymap with `DF(layer)`, change your RGB settings with `RGB_***` keycodes, or use one of the `MAGIC_***` keycodes, the data will be saved to EEPROM and synced to the other half of the keyboard. If you choose to plug the other half into a computer, your settings will be the same. + +Also, if you ever clear the EEPROM with `EE_CLR` or reboot with `QK_RBT` on one half, the other half will automatically do the same. + +To enable Junco Sync in your firmware, uncomment `#define JUNCO_SYNC_ENABLE` in your `config.h` so it looks like this: + +```c +/* - Junco Sync - + Enables a special feature that will sync + data between the halves of the split keyboard. + So no matter which side you plug in, your + default layer, RGB settings, and any changes made + via the Magic keycodes will be the same. +*/ +#define JUNCO_SYNC_ENABLE + +// ... Rest of config.h ... +``` + +Junco Sync will do its thing by default, but you can disable it at any time without having to re-compile your firmware. `junco_sync_disable()` will disable syncing and `junco_sync_enable()` will re-enable syncing (these settings will sync and persist between sides). Clearing EEPROM will re-enable Junco Sync since it's enabled by default. `is_junco_sync_enabled()` will tell you whether or not Junco Sync is enabled. + +### Junco Sync - Advanced + +- [Settings](#settings) +- [Syncing User Data](#syncing-user-data) +- [Manually Trigger a Sync](#manually-trigger-a-sync) +- [Extras](#extras) + +#### Settings + +There is a couple of settings for Junco Sync that you can define in your `config.h`. They are: + +- The time between syncs. This is to prevent syncs from happening back to back and/or retries happening too quickly, reducing keyboard responsiveness. The default by not defining anything is 1 second, but you can change it by defining `JUNCO_SYNC_THROTTLE` in your `config.h`. +- The number of retries a sync will attempt before giving up. The default is 10, but you can change it by defining `JUNCO_SYNC_RETRIES` in your `config.h`. + +```c + #define JUNCO_SYNC_THROTTLE 1000 // Throttle to 1 second (already default) + #define JUNCO_SYNC_RETRIES 10 // Allow up to 10 retries (already default) +``` + +Both of these settings have very sane defaults so there is not really a benefit to defining them. Syncs shouldn't decrease responsiveness at all during normal keyboard use since. They are only triggered after pressing keys that have an effect on EEPROM, which shouldn't happen during normal typing or gaming. + +If for some reason you're having issues with syncs not working, you can try increasing the number of retries, but you should probably check if your TRRS cable or TRRS jack soldering job is the problem. + +#### Syncing User Data + +You can sync your own "user level" data between the halves, see [QMK's documentation](https://docs.qmk.fm/#/feature_eeprom) on the subject. To enable syncing of user data between the halves, set `user_config_raw_ptr` to your config's `raw` value in the `keyboard_post_init_user` after reading the config from EEPROM. For example: + +```c +void keyboard_post_init_user(void) { + // Read your config from EEPROM + user_config.raw = eeconfig_read_user(); + // Set the pointer to your config's raw value + user_config_raw_ptr = &user_config.raw; + + /* ... do stuff ... */ +} +``` + +To sync your user data between the halves you can do: + +```c +// Update your config +user_config.my_setting = 123; +// Trigger sync +kb_needs_sync = true; +``` + +The sync will save your config to both side's EEPROM so you so don't have to call `eeconfig_update_user(user_config.raw)` yourself. + +For more info, see the next section about manually triggering a sync. + +#### Manually Trigger a Sync + +You can trigger sync updates manually by setting a flag in your `keymap.c`. You would want to do this if you are updating the default layer, magic settings, RGB, or rebooting / clearing EEPROM within `process_record_user`. + +With Junco Sync... + +- Magic settigs (`keymap_config`) will only be synced if a `MAGIC_***` keycode is pressed and not overridden by the user. +- Default layer will only become persistent and sync if a `DF(layer)` keycode is pressed. +- RGB will only be synced if a `RGB_***` keycode is pressed and not overridden by the user. +- Synced reboot and clear eeprom only happens when `QK_RBT` or `EE_CLR` is pressed and not overridden by the user. +- Custom user data between the halves won't be synced automatically, it won't know whenuser data needs to be synced. + +Triggering a sync is as simple as setting the respective flag to true. For example: + +*Don't worry if your IDE complains about any values being undefined, they will be defined if you have `#defne JUNCO_SYNC_ENABLE` in your config.h and your firmware should still compile.* + +```c +/* Trigger a sync */ +// Syncs keymap_config ("Magic" settings), +// keyboard level config, default layer, and +// user level config (if you have set user_config_raw_ptr) +kb_needs_sync = true; + +// Trigger a RGB sync +kb_needs_rgb_sync = true; + +// Trigger a reboot and optionally an EEPROM clear +// .reset needs to be true even when you want to +// just clear EEPROM +kb_needs_reset = { + .reset = true, // True will trigger a reboot + .eeprom = true // True will clear EEPROM before rebooting +}; +``` + +Once you have set a flag, the keyboard will carry out the action on it's own and set the flag back to false when it's complete. No need to worry about clearing the flags yourself. + +If for some reason your sync isn't working, try setting the flag on the key's release instead of press. + +#### Extras + +- You can directly call Junco Sync functions by including the `junco_sync.h` header file in your `keymap.c`. + - Even after calling `junco_sync_disable()`, you can still manually sync data between the halves by calling Junco Sync functions directly within your `housekeeping_task_user`. `junco.c` can give you some ideas on how to do this. +- All of the Junco Sync's functions are weakly defined so you can override them if you really want to. diff --git a/keyboards/junco/config.h b/keyboards/junco/config.h new file mode 100644 index 000000000000..7728e9ec93e3 --- /dev/null +++ b/keyboards/junco/config.h @@ -0,0 +1,5 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#include "config_common.h" diff --git a/keyboards/junco/info.json b/keyboards/junco/info.json new file mode 100644 index 000000000000..3e13d893dd2f --- /dev/null +++ b/keyboards/junco/info.json @@ -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" + }, + "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 } + ] + } + } +} diff --git a/keyboards/junco/junco.c b/keyboards/junco/junco.c new file mode 100644 index 000000000000..91c3ec8695ad --- /dev/null +++ b/keyboards/junco/junco.c @@ -0,0 +1,198 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// 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 +} diff --git a/keyboards/junco/junco.h b/keyboards/junco/junco.h new file mode 100644 index 000000000000..307fac504a8e --- /dev/null +++ b/keyboards/junco/junco.h @@ -0,0 +1,52 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "quantum.h" +#include "rev1.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 diff --git a/keyboards/junco/junco_sync.c b/keyboards/junco/junco_sync.c new file mode 100644 index 000000000000..f38075843a0c --- /dev/null +++ b/keyboards/junco/junco_sync.c @@ -0,0 +1,286 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Only relevant if junco sync is enabled */ +#ifdef JUNCO_SYNC_ENABLE +# include "junco_sync.h" +# include "print.h" +# include "transactions.h" +# include "split_util.h" +# include "junco.h" + +/* Sync common keyboard data */ + +// Pointer to the user's user_config.raw. If the user wants to sync their own user config, +// set this to the address of user_config.raw in the keyboard_post_init after reading the +// user_config from eeprom `user_config_raw_ptr = &user_config.raw`. +uint32_t* user_config_raw_ptr = NULL; + +// Data type for sending data to slave +typedef struct { + uint32_t kb_conf; // Current keyboard config + uint32_t default_lay; // Current default layer, SPLIT_LAYER_STATE_ENABLE is not persistent and may not sync in time + uint32_t user_conf; // If the user has a config... + uint16_t keymap_conf; // Current keymap config +} kb_sync_data_t; +// Saves common data on master and sends it to slave +__attribute__((weak)) bool junco_sync(void) { + // Count how many times retried + static uint8_t retries = 0; + // Allow max retries + if (retries >= JUNCO_SYNC_RETRIES) { + dprintf("Failure to sync: too many retries\n"); + retries = 0; + return true; + } + + // Ensure a split is actually connected + if (!is_transport_connected()) { + dprintf("Failure to sync: No split detected\n"); + retries++; + return false; + } + + uint32_t layer = get_highest_layer(default_layer_state); + + /* + Save data to eeprom on master + All the update functions will read before writing, so we + don't need to ensure something changed before attempting to + write. + */ + // Save the kb data on master + eeconfig_update_kb(kb_config.raw); + + // Save the default layer + set_single_persistent_default_layer(layer); + + // Save user config on master + uint32_t user_configuration = 0; + if (user_config_raw_ptr) user_configuration = *user_config_raw_ptr; + if (user_configuration != 0) eeconfig_update_user(user_configuration); + + // Save the Magic settings on master + eeconfig_update_keymap(keymap_config.raw); + + // Data to be sent + kb_sync_data_t m2s = { + kb_config.raw, // Send the keyboard config + layer, // Send the default layer + user_configuration, // Send user config + keymap_config.raw // Send the keymap config (Magic) + }; + + // Execute RPC + if (transaction_rpc_send(KB_SYNC, sizeof(m2s), &m2s)) { + dprintf("Split synced!\n"); + retries = 0; + return true; + } else { + dprintf("Failure to sync: RPC failed\n"); + retries++; + return false; + } +} +// Slave handler for KB_SYNC +__attribute__((weak)) void kb_sync_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { + const kb_sync_data_t* m2s = (kb_sync_data_t*)in_data; + + /* Save data to eeprom on slave side */ + // Save the keyboard data on slave + eeconfig_update_kb(m2s->kb_conf); + // Save the default layer + set_single_persistent_default_layer(m2s->default_lay); + // Save the keymap config + if (m2s->keymap_conf != keymap_config.raw) eeconfig_update_keymap(m2s->keymap_conf); + // Save the user config + if (m2s->user_conf != 0) eeconfig_update_user(m2s->user_conf); +} + +/* Reboot/Reset both halves, optionally clear eeprom */ +typedef struct { + bool reset; + bool clear_eeproms; +} kb_sync_reset_flags_t; +// Flags for reset and clear. Will be the same on both the slave and master +kb_sync_reset_flags_t kb_sync_reset_flags = {false, false}; + +// Helper function that will clear EEPROM and reboot +void _junco_reset_helper(void) { + // Clear EEPROM if needed + if (kb_sync_reset_flags.clear_eeproms) { + dprintf("Clearing EEPROM...\n"); +# ifdef EE_HANDS + eeconfig_init_persist_handedness(); +# else + ee_config_disable(); +# endif + } + + // Flags back to false + kb_sync_reset_flags.reset = false; + kb_sync_reset_flags.clear_eeproms = false; + + // Soft reset + dprintf("Rebooting...\n"); + soft_reset_keyboard(); +} +// Reboots the keyboard, optionally clearing EEPROMs +__attribute__((weak)) void junco_sync_reset(bool* needs_reset, bool* clear_eeprom, bool* failed) { + // Count how many times retried + static uint8_t retries = 0; + // Allow max retries until just reseting the master + if (retries >= JUNCO_SYNC_RETRIES) { + // Give the user a chance to detect the failure before just resetting the master + if ((failed) && (retries == JUNCO_SYNC_RETRIES)) { + *failed = true; + retries++; + return; + } + + dprintf("Failure to reset both halves: too many retries. Resetting master...\n"); + retries = 0; + // Reset the external booleans + if (needs_reset) *needs_reset = false; + if (clear_eeprom) *clear_eeprom = false; + if (failed) *failed = false; + _junco_reset_helper(); + } + + // Check pointer + if (!needs_reset) { + dprintf("Failure to reset: needs_reset is NULL\n"); + retries = JUNCO_SYNC_RETRIES; + return; + } + + // Ensure reset actually needs to happen (only the master will know this) + if (!*needs_reset && is_keyboard_master()) return; + + /* + The slave will always reach this point, the master will only reach + this point when a reset needs to happen. We can be assured that + the flag struct will match on both halves. If reset is false on + the slave it can return from the function, but the master knows + a reset needs to happen so it sets its flags and tells the slave + to do the same. We do it this way because rebooting directly + within the slave handler will cause the slave to reset before + the master knows what's happening, causing issues. Thus, this + function is always called twice when a reset need to happen, + first time sets the flags on both halves and the second time + actually resets both halves. + */ + + // When the flag is set (will be same on slave & master) + if (kb_sync_reset_flags.reset) { + // Set the external booleans to false, reset is about to happen + if (needs_reset) *needs_reset = false; + if (clear_eeprom) *clear_eeprom = false; + if (failed) *failed = false; + + // Let master finish first + if (!is_keyboard_master()) wait_ms(100); + + retries = 0; + // On both sides, reboot and clear eeproms as needed + _junco_reset_helper(); + } else { + // Only execute the following on master + if (!is_keyboard_master()) return; + + // Ensure split is actually connected + if (!is_transport_connected()) { + dprintf("Failure to reset: no split detected\n"); + retries++; + return; + } + + /* Send reset request to slave */ + kb_sync_reset_flags_t m2s = {true, clear_eeprom ? (*clear_eeprom ? true : false) : false}; + // Execute RPC (sets flags on slave) + if (transaction_rpc_send(KB_SYNC_RESET, sizeof(m2s), &m2s)) { + // Set flags on master + kb_sync_reset_flags = m2s; + } else { + dprintf("Failed to reset, retrying...\n"); + retries++; + } + } +} +// Slave handler for KB_SYNC_RESET +__attribute__((weak)) void kb_sync_reset_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { + const kb_sync_reset_flags_t* m2s = (kb_sync_reset_flags_t*)in_data; + // Set flags on slave + kb_sync_reset_flags = *m2s; +} + +# ifdef RGB_MATRIX_ENABLE +/* Sync RGB settings between halves */ +// Data to receive from slave +typedef struct { + rgb_config_t config; +} kb_sync_rgb_data_t; +__attribute__((weak)) bool junco_sync_rgb(void) { + // Count how many times retried + static uint8_t retries = 0; + // Allow max retries + if (retries >= JUNCO_SYNC_RETRIES) { + dprintf("Failure to sync RGB: too many retries\n"); + retries = 0; + return true; + } + + // Ensure split is actually connected + if (!is_transport_connected()) { + dprintf("Failure to sync RGB: no split detected\n"); + retries++; + return false; + } + + // Receive the slave's config + kb_sync_rgb_data_t s2m = {0}; + // Execute RPC + if (transaction_rpc_recv(KB_SYNC_RGB, sizeof(s2m), &s2m)) { + /* Check if the configs match */ + if (memcmp(&s2m.config, &rgb_matrix_config, sizeof(rgb_matrix_config)) != 0) { + retries++; + dprintf("Failure to sync RGB: config mismatch, retrying...\n"); + return false; + } + + // Success, both match + dprintf("Successfully synced RGB\n"); + retries = 0; + return true; + } else { + dprintf("Failure to sync RGB: RPC failed, retrying...\n"); + retries++; + return false; + } +} +// Slave handler for KB_SYNC_RGB +__attribute__((weak)) void kb_sync_rgb_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { + kb_sync_rgb_data_t* s2m = (kb_sync_rgb_data_t*)out_data; + // Update the slave's matrix config in EEPROM. + // The slave and master configs sync on in the core, + // however only the master side is saved to EEPROM. + // Thus we can call update on the slave and both will be + // be synced. The update implementation already ensures + // a write only happens when a change is actually needed. + eeconfig_update_rgb_matrix(); + // Send back to master + s2m->config = rgb_matrix_config; +} + +# endif + +/* Register RPC calls for syncing */ +void junco_sync_init(void) { + transaction_register_rpc(KB_SYNC, kb_sync_slave_handler); + transaction_register_rpc(KB_SYNC_RESET, kb_sync_reset_slave_handler); +# ifdef RGB_MATRIX_ENABLE + transaction_register_rpc(KB_SYNC_RGB, kb_sync_rgb_slave_handler); +# endif +} + +#endif diff --git a/keyboards/junco/junco_sync.h b/keyboards/junco/junco_sync.h new file mode 100644 index 000000000000..2484e34703e6 --- /dev/null +++ b/keyboards/junco/junco_sync.h @@ -0,0 +1,41 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#ifdef JUNCO_SYNC_ENABLE + +// Must be called once before any other sync functions. +// Already always be called within Junco's keyboard_post_init_kb +void junco_sync_init(void); + +// Pointer to the user's user_config.raw. If the user wants to sync their own user config, +// set this to the address of user_config.raw in the keyboard_post_init after reading the +// user_config from eeprom `user_config_raw_ptr = &user_config.raw`. +extern uint32_t* user_config_raw_ptr; + +// Syncs common settings between the halves (default layer, Magic settings, user config), +// call only on master. True on success, false on failure. Allows syncing of a user's +// custom config (pass in the user_config.raw, pass 0 if not). +bool junco_sync(void); + +// Reset/reboot both halves, optionally clearing EEPROM. +// Must be called from both halves (top housekeeping). +// +// needs_reset: is required, will set to false on success. +// +// clear_eeprom: is optional, will be set to false when cleared, +// if NULL or false won't clear EEPROM. +// +// failed: is optional, will be set to true if reseting both halves failed, +// just the master will be reset on the next call +void junco_sync_reset(bool* needs_reset, bool* clear_eeprom, bool* failed); + +# ifdef RGB_MATRIX_ENABLE +// Sync RGB matrix settings between the halves, call only on master. +// Also, ensure reaction on both keypress and key release events. +// Returns true on success, false on failure. +bool junco_sync_rgb(void); +# endif + +#endif diff --git a/keyboards/junco/keymaps/default/README.md b/keyboards/junco/keymaps/default/README.md new file mode 100644 index 000000000000..694d23e1d757 --- /dev/null +++ b/keyboards/junco/keymaps/default/README.md @@ -0,0 +1,57 @@ +# Default Junco Keymap + +This is the default layout for Junco. For the most part it's a normal QWERTY layout. The exceptions being the thumb keys, rotary encoders, and lack of caps lock (which is replaced by escape). + +One of the biggest features of QMK is it brings layers into the mix which can give you access to even more keys. There are 4 layers: the default/base layer (QWERTY), a symbol layer, an extension layer, and an adjust layer. + +Layers are very similar to Shift on a normal keyboard, where "a" becomes "A" when holding down shift. With a custom layer, you can have "j" become "4" for example and make an entire side of the keyboard become a number pad. + +The [symbol layer](#symbol-layer) is accessed by holding down backspace, the [extension layer](#extension-layer) is accessed by holding down delete, and the [adjust layer](#adjust-layer) is accessed by holding down both delete and backspace. + +## Default Base Layer (QWERTY) + +Grey keys are rotary encoders (the ones on far left and far right are optional). Middle legend is pressing down the encoder, bottom left legend is counter-clockwise turn, and bottom right legend is clockwise turn of the encoder. + +Those arrows for the bottom legends on the encoders are mouse scroll directions. + +Red legends are the layer activated by holding down a key. + +![Junco's QWERTY Layout](https://i.imgur.com/fXGt5Jh.png) + +## Symbol Layer + +This layer is accessed by holding down backspace on the base layer, thus that key is blacked out. + +On the symbol layer, the right side is a number pad, and the left side contains all the typical symbols (geared for programming). + +Holding down delete within the symbol layer will take you to the adjust layer. + +![Junco's Symbol Layer](https://i.imgur.com/6F35Z4W.png) + +## Extension Layer + +This layer's theme is navigation/extras, its accessed by holding down delete on the base layer, thus that key is blacked out. + +On the extension layer, the right side is the function keys in a number-pad-esque layout with screen brightness up/down, and the left side has navigation keys and caps lock. Also, the rotary on the right side encoder becomes media controls. + +Holding down backspace within the extension layer will take you to the adjust layer. + +![Junco's Extension Layer](https://i.imgur.com/FETcqkC.png) + +## Adjust Layer + +This layer's theme is adjusting the keyboard's settings, it's accessed by holding down both delete and backspace on the base layer. + +On the adjust layer, the right side is the keyboard's settings: clear data, reboot, toggle debug mode, enter the bootloader, and change the base layer between QWERTY and [Colemak-DH](#colemak-dh). The left side adjusts the RGB lighting. + +![Junco's Adjust Layer](https://i.imgur.com/fRsdlt3.png) + +## Colemak-DH + +This keymap offers Colemak-DH as an alternative base layer to QWERTY. + +QWERTY is default when flashing your keyboard, but you can change it to Colemak-DH by selecting it's key on the adjust layer. + +If you've never heard of it, Colemak is a keyboard layout that was designed to be a more ergonomic, modern, efficient, and comfortable replacement to QWERTY. Colemak was designed to place the most common letters in english on the home row along with many of the most common bigrams together (two letters typed in a row). Colemak-DH is a variant of Colemak that moves D and H to beneath the index fingers rather than the home row since most people find it easier and faster to reach the keys that way rather than the middle of the home row. + +![Junco's Colemak-DH Layout](https://i.imgur.com/u5iXszJ.png) diff --git a/keyboards/junco/keymaps/default/config.h b/keyboards/junco/keymaps/default/config.h new file mode 100644 index 000000000000..f7a85f7a939b --- /dev/null +++ b/keyboards/junco/keymaps/default/config.h @@ -0,0 +1,48 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +/* - Junco Sync - + Uncomment to enable a special feature that will sync + data between the halves of the split keyboard. + So no matter which side you plug in, your + default layer, RGB settings, and any changes made + via the Magic keycodes will be the same and saved + after powering off or using a different computer. +*/ +// #define JUNCO_SYNC_ENABLE + +/* - Encoder settings - */ +#ifdef ENCODER_ENABLE +# define ENCODER_RESOLUTION 4 +#endif +#ifdef ENCODER_MAP_ENABLE +// Key delay for encoders (necessary for some keycodes) +# define ENCODER_MAP_KEY_DELAY 10 +#endif + +/* + - RGB Stuff - + All effects can be found in the QMK docs: + https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects +*/ +#ifdef RGB_MATRIX_ENABLE + +// Default effect when EEPROM cleared +# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_RAINBOW_MOVING_CHEVRON + +// Turns off RGB effects when there is no longer a USB connection +# define RGB_DISABLE_WHEN_USB_SUSPENDED + +// Key press reactive animations +# define SPLIT_TRANSPORT_MIRROR // Necessary setting for key press animations +# define RGB_MATRIX_KEYPRESSES // Enables key press effects +# define ENABLE_RGB_MATRIX_MULTISPLASH + +// Normal effects +# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL +# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON +# define ENABLE_RGB_MATRIX_PIXEL_RAIN + +#endif diff --git a/keyboards/junco/keymaps/default/keymap.c b/keyboards/junco/keymaps/default/keymap.c new file mode 100644 index 000000000000..5bd0f6f40e8c --- /dev/null +++ b/keyboards/junco/keymaps/default/keymap.c @@ -0,0 +1,162 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H +// Layers enum +enum junco_layers { _QWERTY, _COLEMAK_DH, _SYMB, _EXT, _ADJUST }; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + // clang-format off + /* + Traditional QWERTY + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ Q │ W │ E │ R │ T │ │ Y │ U │ I │ O │ P │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Esc│ A │ S │ D │ F │ G │ │ H │ J │ K │ L │ ; │ ' │ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │Sft│ Z │ X │ C │ V │ B │Mut│ │XXX│ N │ M │ , │ . │ / │Sft│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │Ctr│Win│Alt│Del│Spc│ │Sft│Bsp│Alt│Win│Ctr│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + For macOS - GUI (cmd) and Alt (opt) swapped + */ + [_QWERTY] = LAYOUT_split4x6_r1( + KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_ENTER, + KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SEMICOLON, KC_QUOTE, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_MUTE, KC_NO, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, + KC_LCTL, KC_LGUI, KC_LALT, LT(_EXT, KC_DEL), KC_SPC, KC_RSFT, LT(_SYMB, KC_BSPC), KC_RALT, KC_RGUI, KC_RCTL + ), + + /* + Colemak-DH + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ Q │ W │ F │ P │ B │ │ J │ L │ U │ Y │ ; │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Esc│ A │ R │ S │ T │ G │ │ M │ N │ E │ I │ O │ ' │ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │Sft│ Z │ X │ C │ D │ V │Mut│ │XXX│ K │ H │ , │ . │ / │Sft│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │Ctr│Win│Alt│Del│Spc│ │Sft│Bsp│Alt│Win│Ctr│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + For macOS - GUI (cmd) and Alt (opt) swapped + */ + [_COLEMAK_DH] = LAYOUT_split4x6_r1( + KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS, + KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SEMICOLON, KC_ENTER, + KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_G, KC_M, KC_N, KC_E, KC_I, KC_O, KC_QUOTE, + KC_LSFT, KC_Z, KC_X, KC_C, KC_D, KC_V, KC_MUTE, KC_NO, KC_K, KC_H, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, + KC_LCTL, KC_LGUI, KC_LALT, LT(_EXT, KC_DEL), KC_SPC, KC_RSFT, LT(_SYMB, KC_BSPC), KC_RALT, KC_RGUI, KC_RCTL + ), + + /* + Symbols/Numpad Layer + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │F1 │F2 │F3 │F4 │F5 │F6 │ │F7 │F8 │F9 │F10│F11│F12│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ ! │ @ │ # │ $ │ % │ │ * │ 7 │ 8 │ 9 │ + │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │ \ │ _ │ [ │ { │ ( │ ^ │ │ = │ 4 │ 5 │ 6 │ 0 │NUM│ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │___│ | │ ] │ } │ ) │ & │___│ │___│ / │ 1 │ 2 │ 3 │ - │___│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_SYMB] = LAYOUT_split4x6_r1( + KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, + KC_TAB, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_PAST, KC_P7, KC_P8, KC_P9, KC_PPLS, KC_ENTER, + KC_BSLS, KC_UNDS, KC_LBRC, KC_LCBR, KC_LPRN, KC_CIRC, KC_PEQL, KC_P4, KC_P5, KC_P6, KC_P0, KC_NUM, + _______, KC_PIPE, KC_RBRC, KC_RCBR, KC_RPRN, KC_AMPR, _______, _______, KC_PSLS, KC_P1, KC_P2, KC_P3, KC_PMNS, _______, + _______, _______, _______, MO(_ADJUST), _______, _______, _______, _______, _______, _______ + ), + + /* + Extension/Function Layer + ┌────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┬────┬────┬────┐ + │ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ │ F7 │ F8 │ F9 │ F10│ F11│ F12│ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │ ⇤ │PGUP│End │ ↑ │Home│ │ │BRIU│ F7 │ F8 │ F9 │ F10│____│ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │Cps │PGDN│ ← │ ↓ │ → │ │ │BRID│ F4 │ F5 │ F6 │ F11│____│ + ├────┼────┼────┼────┼────┼────┼────┐ ┌────┼────┼────┼────┼────┼────┼────┤ + │____│ │ │ │ │ │____│ │ ▶⏸ │ │ F1 │ F2 │ F3 │ F12│____│ + └────┴────┴────┴────┴────┴────┴────┘ └────┴────┴────┴────┴────┴────┴────┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_EXT] = LAYOUT_split4x6_r1( + KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, + S(KC_TAB), KC_PGUP, KC_END, KC_UP, KC_HOME, _______, KC_BRIU, KC_F7, KC_F8, KC_F9, KC_F10, _______, + KC_CAPS, KC_PGDN, KC_LEFT, KC_DOWN, KC_RIGHT, _______, KC_BRID, KC_F4, KC_F5, KC_F6, KC_F11, _______, + _______, _______, _______, _______, _______, _______, _______, KC_MPLY, _______, KC_F1, KC_F2, KC_F3, KC_F12, _______, + _______, _______, _______, _______, _______, _______, MO(_ADJUST), _______, _______, _______ + ), + + /* + Adjust Layer, Keyboard Settings + ┌────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┬────┬────┬────┐ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │SpdU│HueU│SatU│ValU│Rnxt│ │ │ │EClr│Rbt │DBUG│BOOT│ │ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │SpdD│HueD│SatD│ValD│Rprv│RTgl│ │ │QWRT│COLE│ │ │ │ + ├────┼────┼────┼────┼────┼────┼────┐ ┌────┼────┼────┼────┼────┼────┼────┤ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ + └────┴────┴────┴────┴────┴────┴────┘ └────┴────┴────┴────┴────┴────┴────┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_ADJUST] = LAYOUT_split4x6_r1( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + RGB_SPI, RGB_HUI, RGB_SAI, RGB_VAI, RGB_MOD, KC_NO, KC_NO, EE_CLR, QK_RBT, DB_TOGG, QK_BOOT, KC_NO, + RGB_SPD, RGB_HUD, RGB_SAD, RGB_VAD, RGB_RMOD, RGB_TOG, KC_NO, DF(_QWERTY), DF(_COLEMAK_DH), KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ) + // clang-format on +}; + +/* + --- Rotary Encoder Mappings --- + + Encoder mappings go from leftmost encoder to rightmost encoder on the physical board. + index 0 is the the optional leftmost encoder on the left half, index 1 is the right encoder + on the left half (by the thumb keys), index 2 is the left encoder on the right half (by the + thumb keys), and index 3 is the optional rightmost encoder on the right half. + + If you are only using the 2 required encoders by the thumb keys, you only need to worry about + index 1 and index 2. + + Note that the keycode for counter-clockwise rotation (CCW) goes first and then the key for + clockwise (CW) within ENCODER_CCW_CW. +*/ +#ifdef ENCODER_MAP_ENABLE +// clang-format off + +// Base layer encoder mappings: index 0: mouse wheel up (CCW)/down (CW) index 1: volume down/up index 2: mouse wheel up/down index 3: mouse wheel left/right +# define BASE_LAYER_ENCODERS { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_WH_L, KC_WH_R) } +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + // Base layers + [_QWERTY] = BASE_LAYER_ENCODERS, + [_COLEMAK_DH] = BASE_LAYER_ENCODERS, + + // Passes through to base layers + [_SYMB] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // On the extension layer, the right side's left encoder by the thumb keys (mouse wheel up/down) is traded for media previous/next + [_EXT] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_MPRV, KC_MNXT), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // Passes through + [_ADJUST] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // clang-format on +}; + +#endif diff --git a/keyboards/junco/keymaps/default/rules.mk b/keyboards/junco/keymaps/default/rules.mk new file mode 100644 index 000000000000..2304032cba58 --- /dev/null +++ b/keyboards/junco/keymaps/default/rules.mk @@ -0,0 +1,16 @@ +# Change from yes to no to disable features + +# Enables Audio control and System control Keycodes +EXTRAKEY_ENABLE = yes +# Enables Mousekeys +MOUSEKEY_ENABLE = yes +# Encoder Support +ENCODER_ENABLE = yes +# Use Enocoder Mapping +ENCODER_MAP_ENABLE = yes + +# Enables RGB Lighting Effects +RGB_MATRIX_ENABLE = yes + +# Allows use of `qmk console` for debugging +CONSOLE_ENABLE = yes diff --git a/keyboards/junco/keymaps/deluxe/README.md b/keyboards/junco/keymaps/deluxe/README.md new file mode 100644 index 000000000000..81d6339f5fb0 --- /dev/null +++ b/keyboards/junco/keymaps/deluxe/README.md @@ -0,0 +1,47 @@ +# Deluxe Junco Keymap + +This is my personal keymap for Junco at time of writing. It has [VIA](https://www.caniusevia.com/) and [Junco Sync](../../README.md#junco-sync) enabled and departs from the [default layout](../default/README.md) with the encoder mappings and some extra keycodes. + +Also, this keymap implements the ability to sync VIA settings between the keyboard halves (key to trigger on the [adjust layer](#adjust-layer)). It did not make sense to add this feature at the keyboard level within Junco Sync as VIA is not fundamental like the default layer, RGB lighting, and Magic settings. VIA should be relegated to user keymaps. + +This keymap also adds indicators when caps lock and num lock are enabled. When enabled, that key will become a static white (green on the white backlight mode) but only when the layer that respective key is on is active. + +I wanted that classic rainbow barf RGB effect for the underglow even if the per-key lighting is something else, so I added 2 custom RGB matrix animations: white per-key lighting with rainbow underglow and pixel rain with rainbow underglow. + +Here are some gifs of the animations: + +![White + Underglow Animation](https://i.imgur.com/2vCiZz0.gif) + +![Pixel Rain + Underglow Animation](https://i.imgur.com/f6t0OfD.gif) + +## Base Layers + +The base layers are the same as the default layout, except the right side's left encoder (by the thumb keys) is now media controls. Since I am using all 4 encoders it doesn't make sense to have 2 mouse scroll up/down, but for someone with just 2 encoders it may make sense to have media controls on a layer. + +QWERTY: + +![QWERTY Layer](https://i.imgur.com/vkS9Tce.png) + +Colemak-DH: + +![Colemak-DH Layer](https://i.imgur.com/5YYgaUA.png) + +## Symbol Layer + +Symbol layer is identical to the default layout. + +![Symbol Layer](https://i.imgur.com/6F35Z4W.png) + +## Extension Layer + +Encoders on the right side become undo/redo and scrolling horizontally by word. + +![Extension Layer](https://i.imgur.com/0VCStS8.png) + +## Adjust Layer + +Pressing "Stick Adj Layer" will "stick" the adjust layer so you can use the rotary encoders for RGB settings rather than holding down both backspace and delete. To go back to the default layer, press that stick key again or press and release either Del or Backspace. When the adjust layer is currently "sticky" the sticky key will become the indicator color mentioned earlier. + +"Toggle Base" will toggle between QWERTY and Colemak-DH, toggle OS will toggle between macOS and Windows key-mappings (swapping WIN/Command with Alt/Option by the thumb keys and properly mapping redo/word scrolling), "VIA Sync" will sync the VIA settings between the keyboard halves (there isn't a way to do this automatically), and "Toggle Junco Sync" will disable/enable Junco Sync. + +![Adjust layer](https://i.imgur.com/fRsdlt3.png) diff --git a/keyboards/junco/keymaps/deluxe/config.h b/keyboards/junco/keymaps/deluxe/config.h new file mode 100644 index 000000000000..fd47313868d4 --- /dev/null +++ b/keyboards/junco/keymaps/deluxe/config.h @@ -0,0 +1,74 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +/* - Junco Sync - + Enables a special feature that will sync + data between the halves of the split keyboard. + So no matter which side you plug in, your + default layer, RGB settings, and any changes made + via the Magic keycodes will be the same and saved + after powering off or using a different computer. +*/ +#define JUNCO_SYNC_ENABLE + +/* Indicator LEDs */ +// LED index for caps lock key on the extension layer +#define CAPS_LOCK_LED_INDEX 25 +// LED index for num lock key on the symbol layer +#define NUM_LOCK_LED_INDEX 62 +// LED index for key that sticks the adjust layer +#define ADJST_LED_INDEX 19 + +// Number of Layers that can be used by VIA. +// Change this if you want more layers +#define DYNAMIC_KEYMAP_LAYER_COUNT 6 + +/* Syncing VIA */ +// Time between each packet being sent (100ms), increase if issues +#define VIA_SYNC_THROTTLE 100 +// User level sync ID +#define SPLIT_TRANSACTION_IDS_USER USER_VIA_SYNC + +/* - Encoder settings - */ +#ifdef ENCODER_ENABLE +# define ENCODER_RESOLUTION 4 +#endif +#ifdef ENCODER_MAP_ENABLE +// Key delay for encoders (necessary for some keycodes) +# define ENCODER_MAP_KEY_DELAY 10 +#endif + +/* + - RGB Stuff - + All effects can be found in the QMK docs: + https://docs.qmk.fm/#/feature_rgb_matrix?id=rgb-matrix-effects +*/ +#ifdef RGB_MATRIX_ENABLE + +// Allows the indicator LEDs to work +# define SPLIT_LED_STATE_ENABLE +# define SPLIT_LAYER_STATE_ENABLE + +// Default effect when EEPROM cleared +# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_RAINBOW_MOVING_CHEVRON + +// Turns off RGB effects when there is no longer a USB connection +# define RGB_DISABLE_WHEN_USB_SUSPENDED + +// Throttling of RGB to increase keyboard responsiveness, set to 1.5x the default limits +# define RGB_MATRIX_LED_PROCESS_LIMIT (RGB_MATRIX_LED_COUNT + 4) / 6 // limits the number of LEDs to process in an animation per task run (increases keyboard responsiveness) +# define RGB_MATRIX_LED_FLUSH_LIMIT 24 // limits in milliseconds how frequently an animation will update the LEDs. 16 (16ms), the default, is equivalent to limiting to 60fps + +// Key press reactive animations +# define SPLIT_TRANSPORT_MIRROR // Necessary setting for key press animations +# define RGB_MATRIX_KEYPRESSES // Enables key press effects +# define ENABLE_RGB_MATRIX_MULTISPLASH + +// Normal effects +# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL +# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON +# define ENABLE_RGB_MATRIX_PIXEL_RAIN + +#endif diff --git a/keyboards/junco/keymaps/deluxe/keymap.c b/keyboards/junco/keymaps/deluxe/keymap.c new file mode 100644 index 000000000000..b22e1ce47932 --- /dev/null +++ b/keyboards/junco/keymaps/deluxe/keymap.c @@ -0,0 +1,383 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H +#include "via_sync.h" + +// Layers enum +enum junco_layers { _QWERTY, _COLEMAK_DH, _SYMB, _EXT, _ADJUST }; + +// Custom keycodes +enum custom_keycodes { + // Keycode for toggling between macOS and Windows key mappings + // Actually just an alias to the GUI and Alt swap Magic keycode + KC_OS = MAGIC_TOGGLE_ALT_GUI, + // Keycode for swapping the base layer between QWERTY and Colemak-DH + KC_TOGGLE_BASE = SAFE_RANGE, + // Keycode for toggling Junco Sync On/Off + KC_JSYNC, + // Keycode for manually syncing VIA data + KC_VIASYNC, + // Keycode for redo action (Ctrl + Y on windows, Ctrl + Shift + Z on macOS) + KC_REDO, + // Keycodes for next/previous word + KC_WNXT, + KC_WPRV, + // Keycode for sticking/unsticking the adjust layer + KC_ADJST +}; + +// Whether VIA needs sync +bool needs_via_sync = false; + +/* LED indicators */ +bool is_caps_lock_enabled(void) { // Caps lock + return (host_keyboard_led_state().caps_lock); +} +bool is_num_lock_enabled(void) { // Num lock + return (host_keyboard_led_state().num_lock); +} +bool is_adjust_layer_sticky(layer_state_t state) { // Adjust layer sticky + // Checks if the state is equal to just the adjust layer being active. + // Doing it this way can leverage SPLIT_LAYER_STATE_ENABLE + return (state == (1UL << _ADJUST)) ? true : false; +} +// Indicator color based on the RGB Matrix mode +RGB indicator_color(void) { + RGB rgb; + // Normally the indicator color is white to stand out in the RGB rainbow. + // When using the custom RGB mode that already is white, the indicator color + // is green to stand out. + if (rgb_matrix_config.mode == RGB_MATRIX_CUSTOM_WHITE_UNDERGLOW_CYCLE) { + // Green + rgb.r = 0; + rgb.g = 255; + rgb.b = 0; + } else { + // White + rgb.r = 255; + rgb.g = 255; + rgb.b = 255; + } + return rgb; +} + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + // clang-format off + /* + Traditional QWERTY + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ Q │ W │ E │ R │ T │ │ Y │ U │ I │ O │ P │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Esc│ A │ S │ D │ F │ G │ │ H │ J │ K │ L │ ; │ ' │ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │Sft│ Z │ X │ C │ V │ B │Mut│ │▶⏸ │ N │ M │ , │ . │ / │Sft│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │Ctr│Win│Alt│Del│Spc│ │Sft│Bsp│Alt│Win│Ctr│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + For macOS - GUI (cmd) and Alt (opt) swapped + */ + [_QWERTY] = LAYOUT_split4x6_r1( + KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_ENTER, + KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SEMICOLON, KC_QUOTE, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_MUTE, KC_MPLY, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, + KC_LCTL, KC_LGUI, KC_LALT, LT(_EXT, KC_DEL), KC_SPC, KC_RSFT, LT(_SYMB, KC_BSPC), KC_RALT, KC_RGUI, KC_RCTL + ), + + /* + Colemak-DH + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ Q │ W │ F │ P │ B │ │ J │ L │ U │ Y │ ; │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Esc│ A │ R │ S │ T │ G │ │ M │ N │ E │ I │ O │ ' │ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │Sft│ Z │ X │ C │ D │ V │Mut│ │▶⏸ │ K │ H │ , │ . │ / │Sft│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │Ctr│Win│Alt│Del│Spc│ │Sft│Bsp│Alt│Win│Ctr│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + For macOS - GUI/Win (cmd) and Alt (opt) swapped + */ + [_COLEMAK_DH] = LAYOUT_split4x6_r1( + KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS, + KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SEMICOLON, KC_ENTER, + KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_G, KC_M, KC_N, KC_E, KC_I, KC_O, KC_QUOTE, + KC_LSFT, KC_Z, KC_X, KC_C, KC_D, KC_V, KC_MUTE, KC_MPLY, KC_K, KC_H, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, + KC_LCTL, KC_LGUI, KC_LALT, LT(_EXT, KC_DEL), KC_SPC, KC_RSFT, LT(_SYMB, KC_BSPC), KC_RALT, KC_RGUI, KC_RCTL + ), + + /* + Symbols/Numpad Layer + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │F1 │F2 │F3 │F4 │F5 │F6 │ │F7 │F8 │F9 │F10│F11│F12│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ ! │ @ │ # │ $ │ % │ │ * │ 7 │ 8 │ 9 │ + │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │ \ │ _ │ [ │ { │ ( │ ^ │ │ = │ 4 │ 5 │ 6 │ 0 │NUM│ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │___│ | │ ] │ } │ ) │ & │___│ │___│ / │ 1 │ 2 │ 3 │ - │___│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_SYMB] = LAYOUT_split4x6_r1( + KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, + KC_TAB, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_PAST, KC_P7, KC_P8, KC_P9, KC_PPLS, KC_ENTER, + KC_BSLS, KC_UNDS, KC_LBRC, KC_LCBR, KC_LPRN, KC_CIRC, KC_PEQL, KC_P4, KC_P5, KC_P6, KC_P0, KC_NUM, + _______, KC_PIPE, KC_RBRC, KC_RCBR, KC_RPRN, KC_AMPR, _______, _______, KC_PSLS, KC_P1, KC_P2, KC_P3, KC_PMNS, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ), + + /* + Extension/Function Layer + ┌────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┬────┬────┬────┐ + │ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ │ F7 │ F8 │ F9 │ F10│ F11│ F12│ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │ ⇤ │PGUP│End │ ↑ │Home│ │ │BRIU│ F7 │ F8 │ F9 │ F10│____│ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │Cps │PGDN│ ← │ ↓ │ → │ │ │BRID│ F4 │ F5 │ F6 │ F11│____│ + ├────┼────┼────┼────┼────┼────┼────┐ ┌────┼────┼────┼────┼────┼────┼────┤ + │____│ │ │ │ │ │____│ │____│ │ F1 │ F2 │ F3 │ F12│____│ + └────┴────┴────┴────┴────┴────┴────┘ └────┴────┴────┴────┴────┴────┴────┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_EXT] = LAYOUT_split4x6_r1( + KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, + S(KC_TAB), KC_PGUP, KC_END, KC_UP, KC_HOME, _______, KC_BRIU, KC_F7, KC_F8, KC_F9, KC_F10, _______, + KC_CAPS, KC_PGDN, KC_LEFT, KC_DOWN, KC_RIGHT, _______, KC_BRID, KC_F4, KC_F5, KC_F6, KC_F11, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_F1, KC_F2, KC_F3, KC_F12, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ), + + /* + Adjust Layer, Keyboard Settings + ┌────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┬────┬────┬────┐ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │SpdU│HueU│SatU│ValU│Rnxt│Stck│ │ │EClr│Rbt │DBUG│BOOT│ │ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │SpdD│HueD│SatD│ValD│Rprv│RTgl│ │ │LOUT│ OS │VSNC│TJSC│ │ + ├────┼────┼────┼────┼────┼────┼────┐ ┌────┼────┼────┼────┼────┼────┼────┤ + │ │ │ │ │ │ │RTgl│ │ │ │ │ │ │ │ │ + └────┴────┴────┴────┴────┴────┴────┘ └────┴────┴────┴────┴────┴────┴────┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_ADJUST] = LAYOUT_split4x6_r1( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + RGB_SPI, RGB_HUI, RGB_SAI, RGB_VAI, RGB_MOD, KC_ADJST, KC_NO, EE_CLR, QK_RBT, DB_TOGG, QK_BOOT, KC_NO, + RGB_SPD, RGB_HUD, RGB_SAD, RGB_VAD, RGB_RMOD, RGB_TOG, KC_NO, KC_TOGGLE_BASE, KC_OS, KC_VIASYNC, KC_JSYNC, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_TOG, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ) + // clang-format on +}; + +/* + --- Rotary Encoder Mappings --- + + Encoder mappings go from leftmost encoder to rightmost encoder on the physical board. + index 0 is the the optional leftmost encoder on the left half, index 1 is the right encoder + on the left half (by the thumb keys), index 2 is the left encoder on the right half (by the + thumb keys), and index 3 is the optional rightmost encoder on the right half. + + If you are only using the 2 required encoders by the thumb keys, you only need to worry about + index 1 and index 2. + + Note that the key to be sent for counter-clockwise rotation (CCW) goes first and then the key for + clockwise (CW) within ENCODER_CCW_CW. +*/ +#ifdef ENCODER_MAP_ENABLE +// clang-format off + +// Base layer encoder mappings: index 0: mouse wheel up (CCW)/down (CW) index 1: volume up/down index 2: media prev/next index 3: mouse wheel left/right +# define BASE_LAYER_ENCODERS { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MPRV, KC_MNXT), ENCODER_CCW_CW(KC_WH_L, KC_WH_R) } +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + // Base layers + [_QWERTY] = BASE_LAYER_ENCODERS, + [_COLEMAK_DH] = BASE_LAYER_ENCODERS, + + // Passes through to base layer + [_SYMB] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // undo/redo previous word/next word + [_EXT] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_UNDO, KC_REDO), ENCODER_CCW_CW(KC_WPRV, KC_WNXT) }, + // RGB Speed down/up RGB previous mode/next mode RGB brightness down/up + [_ADJUST] = { ENCODER_CCW_CW(RGB_SPD, RGB_SPI), ENCODER_CCW_CW(RGB_RMOD, RGB_MOD), ENCODER_CCW_CW(RGB_VAD, RGB_VAI), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // clang-format on +}; + +#endif + +// User level post init +void keyboard_post_init_user(void) { + // Register VIA Sync + via_sync_init(); +} + +// Called whenever a layer is changed +layer_state_t layer_state_set_user(layer_state_t state) { + // Make sure the adjust layer isn't sticky + if (is_adjust_layer_sticky(state)) return state; + + // When both the symbol and extension layer keys are held, the Adjust layer is active. + return update_tri_layer_state(state, _SYMB, _EXT, _ADJUST); +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + // Toggle base layer + case KC_TOGGLE_BASE: + if (record->event.pressed) { + // Toggle swapping base layers between Colemak-DH and QWERTY. + // When base layer is QWERTY, swap to Colemak-DH and vice-versa + if (get_highest_layer(default_layer_state) == _QWERTY) { + default_layer_set(1UL << _COLEMAK_DH); + } else { + default_layer_set(1UL << _QWERTY); + } + // Junco Sync will automatically save and sync the default layer when we use DF(layer) + // in a keymap, but because we are manually setting the default layer we need + // to tell the keyboard a sync is needed. + kb_needs_sync = true; + } + return false; + + // Toggle Junco Sync On/Off + case KC_JSYNC: + if (record->event.pressed) { + is_junco_sync_enabled() ? junco_sync_disable() : junco_sync_enable(); + } + return false; + + // Manually sync VIA data + case KC_VIASYNC: + if (record->event.pressed) { + needs_via_sync = true; + } + return false; + + // Override undo in favor of the more modern undo action + case KC_UNDO: + if (record->event.pressed) { + // Use the correct modifier for macOS or Windows + uint16_t mod = keymap_config.swap_lalt_lgui ? KC_LGUI : KC_LCTL; + // Send Ctrl+Z/Cmd+Z + register_code(mod); + tap_code_delay(KC_Z, 10); + unregister_code(mod); + } + return false; + + // Redo action + case KC_REDO: + if (record->event.pressed) { + // Whether or not macOS mapping is enabled + if (keymap_config.swap_lalt_lgui) { + // macOS - Send Cmd+Shift+Z + register_code(KC_LGUI); + register_code(KC_LSFT); + tap_code_delay(KC_Z, 10); + unregister_code(KC_LSFT); + unregister_code(KC_LGUI); + } else { + // Windows - Send Ctrl+Y + register_code(KC_LCTL); + tap_code_delay(KC_Y, 10); + unregister_code(KC_LCTL); + } + } + return false; + + // Next word + case KC_WNXT: + if (record->event.pressed) { + // Use the correct modifier for macOS or Windows + uint16_t mod = keymap_config.swap_lalt_lgui ? KC_LALT : KC_LCTL; + // Send Ctrl+Right/Option+Right + register_code(mod); + tap_code_delay(KC_RGHT, 10); + unregister_code(mod); + } + return false; + + // Previous word + case KC_WPRV: + if (record->event.pressed) { + // Use the correct modifier for macOS or Windows + uint16_t mod = keymap_config.swap_lalt_lgui ? KC_LALT : KC_LCTL; + // Send Ctrl+Left/Option+Left + register_code(mod); + tap_code_delay(KC_LEFT, 10); + unregister_code(mod); + } + return false; + + // Stick / Unstick the adjust layer + case KC_ADJST: + if (record->event.pressed) { + // If currently not sticky, we want only the adjust layer to be active to make it stick. + // Otherwise we want the default layer, un-stick. + is_adjust_layer_sticky(layer_state) ? layer_state_set(default_layer_state) : layer_move(_ADJUST); + dprintf("Adjust layer is now %s\n", is_adjust_layer_sticky(layer_state) ? "stuck" : "un-stuck"); + } + return false; + default: + return true; + } +} + +/* Indicators (Caps Lock / Num Lock / Adjust Layer Sticky) */ +bool rgb_matrix_indicators_user(void) { + layer_state_t curr_layer_state = layer_state; + layer_state_t layer = get_highest_layer(curr_layer_state); + RGB rgb = indicator_color(); + + /* Only show the indicator on their respective layers */ + // Caps Lock is only on the extension layer + if (is_caps_lock_enabled() && layer == _EXT) { + rgb_matrix_set_color(CAPS_LOCK_LED_INDEX, rgb.r, rgb.g, rgb.b); + } + + // Num Lock is only on the symbol layer + if (is_num_lock_enabled() && layer == _SYMB) { + rgb_matrix_set_color(NUM_LOCK_LED_INDEX, rgb.r, rgb.g, rgb.b); + } + + // If the adjust layer is stuck/sticky, light it up. Don't need to care about + // checking the layer since it can only be active on the adjust layer anyway + if (is_adjust_layer_sticky(curr_layer_state)) rgb_matrix_set_color(ADJST_LED_INDEX, rgb.r, rgb.g, rgb.b); + + return false; +} + +/* + - User level housekeeping - + Actually where the VIA sync get called. Housekeeping is called periodically, + so sync reties will happen automatically and it can be used as a loop + that doesn't block processing key events. +*/ +void housekeeping_task_user(void) { + // See if a VIA sync needs to happen + if (!needs_via_sync) return; + + /* Only for master side */ + if (!is_keyboard_master()) return; + + // Throttle packet sending + static uint32_t last_sync = 0; + if (timer_elapsed32(last_sync) < VIA_SYNC_THROTTLE) return; + last_sync = timer_read32(); + + // Want to stay true when retrying and sending packets + needs_via_sync = !via_sync(); +} diff --git a/keyboards/junco/keymaps/deluxe/rgb_matrix_user.inc b/keyboards/junco/keymaps/deluxe/rgb_matrix_user.inc new file mode 100644 index 000000000000..3efe5067497c --- /dev/null +++ b/keyboards/junco/keymaps/deluxe/rgb_matrix_user.inc @@ -0,0 +1,48 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +RGB_MATRIX_EFFECT(WHITE_UNDERGLOW_CYCLE) +RGB_MATRIX_EFFECT(PIXEL_RAIN_UNDERGLOW_CYCLE) + +#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS + +// This is a modified version of the effect_runner_dx_dy_dist function from rgb_matrix +// that only applies the effect to the underglow LEDs of this keyboard +static bool underglow_effect_runner(effect_params_t* params, dx_dy_dist_f underglow_effect_func, bool backlight_white) { + RGB_MATRIX_USE_LIMITS(led_min, led_max); + + HSV hsv = rgb_matrix_config.hsv; + HSV white = {0, 0, hsv.v}; + RGB rgb = rgb_matrix_hsv_to_rgb(white); + uint8_t time = scale16by8(g_rgb_timer, rgb_matrix_config.speed / 2); + for (uint8_t i = led_min; i < led_max; i++) { + // Underglow LEDs are indicies 0 - 7 and 37 - 44 + if ((i <= 7) || (37 <= i && i <= 44)) { + // Apply the maths and colors to the underglow LEDs + RGB_MATRIX_TEST_LED_FLAGS(); + int16_t dx = g_led_config.point[i].x - k_rgb_matrix_center.x; + int16_t dy = g_led_config.point[i].y - k_rgb_matrix_center.y; + uint8_t dist = sqrt16(dx * dx + dy * dy); + RGB rgb = rgb_matrix_hsv_to_rgb(underglow_effect_func(hsv, dx, dy, dist, time)); + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } else { + // Set the backlight to white if needed + if (!backlight_white) continue; + rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b); + } + } + return rgb_matrix_check_finished_leds(led_max); +} + +// Solid white but the underglow is a rainbow spiral +static bool WHITE_UNDERGLOW_CYCLE(effect_params_t* params) { + return underglow_effect_runner(params, &CYCLE_SPIRAL_math, true); +} + +// Pixel rain effect but the underglow is a rainbow spiral +static bool PIXEL_RAIN_UNDERGLOW_CYCLE(effect_params_t* params) { + PIXEL_RAIN(params); + return underglow_effect_runner(params, &CYCLE_SPIRAL_math, false); +} + +#endif diff --git a/keyboards/junco/keymaps/deluxe/rules.mk b/keyboards/junco/keymaps/deluxe/rules.mk new file mode 100644 index 000000000000..832eb9a17c69 --- /dev/null +++ b/keyboards/junco/keymaps/deluxe/rules.mk @@ -0,0 +1,22 @@ +# Enables Audio control and System control Keycodes +EXTRAKEY_ENABLE = yes +# Enables Mousekeys +MOUSEKEY_ENABLE = yes +# Encoder Support +ENCODER_ENABLE = yes +# Use Enocoder Mapping +ENCODER_MAP_ENABLE = yes + +# Enables RGB Lighting Effects +RGB_MATRIX_ENABLE = yes + +# Allows use of `qmk console` for debugging +CONSOLE_ENABLE = yes + +# Enables VIA +VIA_ENABLE = yes + +# Custom RGB Matrix Effect +RGB_MATRIX_CUSTOM_USER = yes + +SRC += via_sync.c diff --git a/keyboards/junco/keymaps/deluxe/via_sync.c b/keyboards/junco/keymaps/deluxe/via_sync.c new file mode 100644 index 000000000000..a1c37cd85059 --- /dev/null +++ b/keyboards/junco/keymaps/deluxe/via_sync.c @@ -0,0 +1,88 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "via_sync.h" +#include "transactions.h" +#include "print.h" + +typedef struct { + // The address that was read from + uint32_t addr; + // The 20 bytes of data that was read + uint8_t data[20]; + // How many of those 20 bytes should be updated + uint8_t num_bytes; +} via_sync_packet_t; + +// How many packets we'll be sending in total (+ 1 to always round up) +const uint16_t total_packets = VIA_BLOCK_SIZE / 20 + 1; + +bool via_sync(void) { + /* + The RPC buffer is 32 bytes and changing it caused failures in testing + so we'll send 20 byte packets on each call. The housekeeping task will + act as our loop for sending the next packet / retrying a failed one. + */ + + // What packet we're on + static uint16_t packet_number = 0; + + // Count how many times retried + static uint8_t retries = 0; + // Allow max retries + if (retries >= JUNCO_SYNC_RETRIES) { + dprintf("Failure to sync VIA: too many retries\n"); + packet_number = 0; + retries = 0; + return true; + } + + // First call + if (packet_number == 0) { + dprintf("Attempting to sync VIA's %u bytes of data...\n", VIA_BLOCK_SIZE); + dprintf("This will take about %u seconds\n", total_packets * VIA_SYNC_THROTTLE / 1000); + packet_number = 1; + } + + /* Copy the nth 20 bytes to the packet from EEPROM */ + // The address to read from, start of the VIA block offset to where the last packet left off + uint32_t addr = START_ADDR + ((packet_number - 1) * 20); + // How many bytes to read/update, will be 20 unless we're about to read past the end + // of the VIA block. At which point we'll read the remaining bytes in the block, 1 + the + // difference between the end address and the offset address. + uint8_t num_bytes = ((addr + 20) > END_ADDR) ? (END_ADDR - addr + 1) : 20; + + via_sync_packet_t m2s = {addr, {0}, num_bytes}; + eeprom_read_block(m2s.data, (uint32_t*)addr, num_bytes); + + // Execute the RPC + if (transaction_rpc_send(USER_VIA_SYNC, sizeof(m2s), &m2s)) { + // If we've sent the last packet, return true + if (packet_number == total_packets) { + dprintf("VIA Synced!\n"); + packet_number = 0; + retries = 0; + return true; + } + // Otherwise, increment the packet number and return false + packet_number++; + return false; + } else { + dprintf("Failure to sync VIA, RPC failed, retrying...\n"); + retries++; + return false; + } +} +// Slave handler for USER_VIA_SYNC +void via_sync_slave_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data) { + const via_sync_packet_t* m2s = (const via_sync_packet_t*)in_data; + // The address to write to + const uint32_t addr = m2s->addr; + // Update the EEPROM with the data + eeprom_update_block(m2s->data, (uint32_t*)addr, m2s->num_bytes); +} + +void via_sync_init(void) { + // Register the VIA RPC + transaction_register_rpc(USER_VIA_SYNC, via_sync_slave_handler); +} diff --git a/keyboards/junco/keymaps/deluxe/via_sync.h b/keyboards/junco/keymaps/deluxe/via_sync.h new file mode 100644 index 000000000000..e3b00028038a --- /dev/null +++ b/keyboards/junco/keymaps/deluxe/via_sync.h @@ -0,0 +1,37 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once +#include "eeprom.h" + +/* Manually Sync VIA Data */ +// Size of keymaps in EEPROM +#define KEYMAPS_SIZE (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2) +// Size of encoders in EEPROM +#define ENCODER_SIZE (DYNAMIC_KEYMAP_LAYER_COUNT * NUM_ENCODERS * 2 * 2) +// Starting address of VIA's non-core data +#define START_ADDR VIA_EEPROM_LAYOUT_OPTIONS_ADDR +// DYNAMIC_KEYMAP_EEPROM_MAX_ADDR is the maximum address that VIA will use for its data, +// including macros. This end address minus the start address + 1 is how large the VIA +// data block will be. I'm roughly copying how this address is calculated by default by +// taking the starting address, adding the custom config size, adding the keymaps size (including +// encoders), and the rest for macros. VIA says up to 1 Kilobyte is usable for macros (despite +// it delegating the entire rest of EEPROM to them). Personally I don't use them so I'm setting +// it to 1/3 of that Kilobyte just in case I choose to in the future. Lower numbers will +// speed up the syncing process. If you have no need for macros, you can set it to 0. Syncing VIA +// takes about 5 seconds at the default speed of 10 packets per second with my settings. +#define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR (START_ADDR + VIA_EEPROM_CUSTOM_CONFIG_SIZE + KEYMAPS_SIZE + ENCODER_SIZE + 333) +// Ending address of all VIA data (macros included) +#define END_ADDR DYNAMIC_KEYMAP_EEPROM_MAX_ADDR +// How big the VIA data block is +#define VIA_BLOCK_SIZE (END_ADDR - START_ADDR + 1) + +// Call within keyboard_post_init_user to initialize the VIA sync RPC +void via_sync_init(void); + +// Syncs VIA's data from the master to the slave. +// True when finished, false when still needs to +// send packets and/or retry. +// Call within housekeeping_task_user on the master +// only. VIA sync sends the data in packets of 20 bytes. +bool via_sync(void); diff --git a/keyboards/junco/keymaps/via/README.md b/keyboards/junco/keymaps/via/README.md new file mode 100644 index 000000000000..03efb18e953a --- /dev/null +++ b/keyboards/junco/keymaps/via/README.md @@ -0,0 +1,3 @@ +# VIA Junco Keymap + +The VIA keymap is identical to the [default keymap](../default/README.md), but has VIA enabled for use with the [VIA](https://caniusevia.com/) configurator. diff --git a/keyboards/junco/keymaps/via/config.h b/keyboards/junco/keymaps/via/config.h new file mode 100644 index 000000000000..85e22a687dbc --- /dev/null +++ b/keyboards/junco/keymaps/via/config.h @@ -0,0 +1,97 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +/* - Junco Sync - + Uncomment to enable a special feature that will sync + data between the halves of the split keyboard. + So no matter which side you plug in, your + default layer, RGB settings, and any changes made + via the Magic keycodes will be the same and saved + after powering off or using a different computer. +*/ +// #define JUNCO_SYNC_ENABLE + +// Number of Layers that can be used by VIA. +// Change this if you want more layers +#define DYNAMIC_KEYMAP_LAYER_COUNT 6 + +/* - Encoder settings - */ +#ifdef ENCODER_ENABLE +# define ENCODER_RESOLUTION 4 +#endif +#ifdef ENCODER_MAP_ENABLE +// Key delay for encoders (necessary for some keycodes) +# define ENCODER_MAP_KEY_DELAY 10 +#endif + +/* + - RGB - + Defines all effects so VIA can properly select them +*/ +#ifdef RGB_MATRIX_ENABLE + +// Default effect when EEPROM cleared +# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_RAINBOW_MOVING_CHEVRON + +// Turns off RGB effects when there is no longer a USB connection +# define RGB_DISABLE_WHEN_USB_SUSPENDED + +// Allow keypress reactive animations +# define SPLIT_TRANSPORT_MIRROR // Necessary setting for key press animations on a split +# define RGB_MATRIX_KEYPRESSES // Enables key press effects + +// Allow frame buffer effects +# define RGB_MATRIX_FRAMEBUFFER_EFFECTS // Enables frame buffer effects + +// All effect definitions +# define ENABLE_RGB_MATRIX_ALPHAS_MODS // Enables RGB_MATRIX_ALPHAS_MODS +# define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN // Enables RGB_MATRIX_GRADIENT_UP_DOWN +# define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT // Enables RGB_MATRIX_GRADIENT_LEFT_RIGHT +# define ENABLE_RGB_MATRIX_BREATHING // Enables RGB_MATRIX_BREATHING +# define ENABLE_RGB_MATRIX_BAND_SAT // Enables RGB_MATRIX_BAND_SAT +# define ENABLE_RGB_MATRIX_BAND_VAL // Enables RGB_MATRIX_BAND_VAL +# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT // Enables RGB_MATRIX_BAND_PINWHEEL_SAT +# define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL // Enables RGB_MATRIX_BAND_PINWHEEL_VAL +# define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT // Enables RGB_MATRIX_BAND_SPIRAL_SAT +# define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL // Enables RGB_MATRIX_BAND_SPIRAL_VAL +# define ENABLE_RGB_MATRIX_CYCLE_ALL // Enables RGB_MATRIX_CYCLE_ALL +# define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT // Enables RGB_MATRIX_CYCLE_LEFT_RIGHT +# define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN // Enables RGB_MATRIX_CYCLE_UP_DOWN +# define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON // Enables RGB_MATRIX_RAINBOW_MOVING_CHEVRON +# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN // Enables RGB_MATRIX_CYCLE_OUT_IN +# define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL // Enables RGB_MATRIX_CYCLE_OUT_IN_DUAL +# define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL // Enables RGB_MATRIX_CYCLE_PINWHEEL +# define ENABLE_RGB_MATRIX_CYCLE_SPIRAL // Enables RGB_MATRIX_CYCLE_SPIRAL +# define ENABLE_RGB_MATRIX_DUAL_BEACON // Enables RGB_MATRIX_DUAL_BEACON +# define ENABLE_RGB_MATRIX_RAINBOW_BEACON // Enables RGB_MATRIX_RAINBOW_BEACON +# define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS // Enables RGB_MATRIX_RAINBOW_PINWHEELS +# define ENABLE_RGB_MATRIX_RAINDROPS // Enables RGB_MATRIX_RAINDROPS +# define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS // Enables RGB_MATRIX_JELLYBEAN_RAINDROPS +# define ENABLE_RGB_MATRIX_HUE_BREATHING // Enables RGB_MATRIX_HUE_BREATHING +# define ENABLE_RGB_MATRIX_HUE_PENDULUM // Enables RGB_MATRIX_HUE_PENDULUM +# define ENABLE_RGB_MATRIX_HUE_WAVE // Enables RGB_MATRIX_HUE_WAVE +# define ENABLE_RGB_MATRIX_PIXEL_FRACTAL // Enables RGB_MATRIX_PIXEL_FRACTAL +# define ENABLE_RGB_MATRIX_PIXEL_FLOW // Enables RGB_MATRIX_PIXEL_FLOW +# define ENABLE_RGB_MATRIX_PIXEL_RAIN // Enables RGB_MATRIX_PIXEL_RAIN + +// Following need RGB_MATRIX_FRAMEBUFFER_EFFECTS +# define ENABLE_RGB_MATRIX_TYPING_HEATMAP // Enables RGB_MATRIX_TYPING_HEATMAP +# define ENABLE_RGB_MATRIX_DIGITAL_RAIN // Enables RGB_MATRIX_DIGITAL_RAIN + +// Following need RGB_MATRIX_KEYPRESSES +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE // Enables RGB_MATRIX_SOLID_REACTIVE_SIMPLE +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE // Enables RGB_MATRIX_SOLID_REACTIVE +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE // Enables RGB_MATRIX_SOLID_REACTIVE_WIDE +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE // Enables RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS // Enables RGB_MATRIX_SOLID_REACTIVE_CROSS +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS // Enables RGB_MATRIX_SOLID_REACTIVE_MULTICROSS +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS // Enables RGB_MATRIX_SOLID_REACTIVE_NEXUS +# define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS // Enables RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS +# define ENABLE_RGB_MATRIX_SPLASH // Enables RGB_MATRIX_SPLASH +# define ENABLE_RGB_MATRIX_MULTISPLASH // Enables RGB_MATRIX_MULTISPLASH +# define ENABLE_RGB_MATRIX_SOLID_SPLASH // Enables RGB_MATRIX_SOLID_SPLASH +# define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH // Enables RGB_MATRIX_SOLID_MULTISPLASH + +#endif diff --git a/keyboards/junco/keymaps/via/keymap.c b/keyboards/junco/keymaps/via/keymap.c new file mode 100644 index 000000000000..ba65715e081f --- /dev/null +++ b/keyboards/junco/keymaps/via/keymap.c @@ -0,0 +1,162 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include QMK_KEYBOARD_H +// Layers enum +enum junco_layers { _QWERTY, _COLEMAK_DH, _SYMB, _EXT, _ADJUST }; + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + // clang-format off + /* + Traditional QWERTY + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ Q │ W │ E │ R │ T │ │ Y │ U │ I │ O │ P │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Esc│ A │ S │ D │ F │ G │ │ H │ J │ K │ L │ ; │ ' │ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │Sft│ Z │ X │ C │ V │ B │Mut│ │XXX│ N │ M │ , │ . │ / │Sft│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │Ctr│Win│Alt│Del│Spc│ │Sft│Bsp│Alt│Win│Ctr│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + For macOS - GUI (cmd) and Alt (opt) swapped + */ + [_QWERTY] = LAYOUT_split4x6_r1( + KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_ENTER, + KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SEMICOLON, KC_QUOTE, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_MUTE, KC_NO, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, + KC_LCTL, KC_LGUI, KC_LALT, LT(_EXT, KC_DEL), KC_SPC, KC_RSFT, LT(_SYMB, KC_BSPC), KC_RALT, KC_RGUI, KC_RCTL + ), + + /* + Colemak-DH + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ Q │ W │ F │ P │ B │ │ J │ L │ U │ Y │ ; │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Esc│ A │ R │ S │ T │ G │ │ M │ N │ E │ I │ O │ ' │ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │Sft│ Z │ X │ C │ D │ V │Mut│ │XXX│ K │ H │ , │ . │ / │Sft│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │Ctr│Win│Alt│Del│Spc│ │Sft│Bsp│Alt│Win│Ctr│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + For macOS - GUI (cmd) and Alt (opt) swapped + */ + [_COLEMAK_DH] = LAYOUT_split4x6_r1( + KC_GRAVE, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINUS, + KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_B, KC_J, KC_L, KC_U, KC_Y, KC_SEMICOLON, KC_ENTER, + KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_G, KC_M, KC_N, KC_E, KC_I, KC_O, KC_QUOTE, + KC_LSFT, KC_Z, KC_X, KC_C, KC_D, KC_V, KC_MUTE, KC_NO, KC_K, KC_H, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, + KC_LCTL, KC_LGUI, KC_LALT, LT(_EXT, KC_DEL), KC_SPC, KC_RSFT, LT(_SYMB, KC_BSPC), KC_RALT, KC_RGUI, KC_RCTL + ), + + /* + Symbols/Numpad Layer + ┌───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┐ + │F1 │F2 │F3 │F4 │F5 │F6 │ │F7 │F8 │F9 │F10│F11│F12│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │Tab│ ! │ @ │ # │ $ │ % │ │ * │ 7 │ 8 │ 9 │ + │Ent│ + ├───┼───┼───┼───┼───┼───┤ ├───┼───┼───┼───┼───┼───┤ + │ \ │ _ │ [ │ { │ ( │ ^ │ │ = │ 4 │ 5 │ 6 │ 0 │NUM│ + ├───┼───┼───┼───┼───┼───┼───┐ ┌───┼───┼───┼───┼───┼───┼───┤ + │___│ | │ ] │ } │ ) │ & │___│ │___│ / │ 1 │ 2 │ 3 │ - │___│ + └───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_SYMB] = LAYOUT_split4x6_r1( + KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, + KC_TAB, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_PAST, KC_P7, KC_P8, KC_P9, KC_PPLS, KC_ENTER, + KC_BSLS, KC_UNDS, KC_LBRC, KC_LCBR, KC_LPRN, KC_CIRC, KC_PEQL, KC_P4, KC_P5, KC_P6, KC_P0, KC_NUM, + _______, KC_PIPE, KC_RBRC, KC_RCBR, KC_RPRN, KC_AMPR, _______, _______, KC_PSLS, KC_P1, KC_P2, KC_P3, KC_PMNS, _______, + _______, _______, _______, MO(_ADJUST), _______, _______, _______, _______, _______, _______ + ), + + /* + Extension/Function Layer + ┌────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┬────┬────┬────┐ + │ F1 │ F2 │ F3 │ F4 │ F5 │ F6 │ │ F7 │ F8 │ F9 │ F10│ F11│ F12│ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │ ⇤ │PGUP│End │ ↑ │Home│ │ │BRIU│ F7 │ F8 │ F9 │ F10│____│ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │Cps │PGDN│ ← │ ↓ │ → │ │ │BRID│ F4 │ F5 │ F6 │ F11│____│ + ├────┼────┼────┼────┼────┼────┼────┐ ┌────┼────┼────┼────┼────┼────┼────┤ + │____│ │ │ │ │ │____│ │ ▶⏸ │ │ F1 │ F2 │ F3 │ F12│____│ + └────┴────┴────┴────┴────┴────┴────┘ └────┴────┴────┴────┴────┴────┴────┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_EXT] = LAYOUT_split4x6_r1( + KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, + S(KC_TAB), KC_PGUP, KC_END, KC_UP, KC_HOME, _______, KC_BRIU, KC_F7, KC_F8, KC_F9, KC_F10, _______, + KC_CAPS, KC_PGDN, KC_LEFT, KC_DOWN, KC_RIGHT, _______, KC_BRID, KC_F4, KC_F5, KC_F6, KC_F11, _______, + _______, _______, _______, _______, _______, _______, _______, KC_MPLY, _______, KC_F1, KC_F2, KC_F3, KC_F12, _______, + _______, _______, _______, _______, _______, _______, MO(_ADJUST), _______, _______, _______ + ), + + /* + Adjust Layer, Keyboard Settings + ┌────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┬────┬────┬────┐ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │SpdU│HueU│SatU│ValU│Rnxt│ │ │ │EClr│Rbt │DBUG│BOOT│ │ + ├────┼────┼────┼────┼────┼────┤ ├────┼────┼────┼────┼────┼────┤ + │SpdD│HueD│SatD│ValD│Rprv│RTgl│ │ │QWRT│COLE│ │ │ │ + ├────┼────┼────┼────┼────┼────┼────┐ ┌────┼────┼────┼────┼────┼────┼────┤ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ + └────┴────┴────┴────┴────┴────┴────┘ └────┴────┴────┴────┴────┴────┴────┘ + ┌───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┐ + │___│___│___│___│___│ │___│___│___│___│___│ + └───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┘ + */ + [_ADJUST] = LAYOUT_split4x6_r1( + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + RGB_SPI, RGB_HUI, RGB_SAI, RGB_VAI, RGB_MOD, KC_NO, KC_NO, EE_CLR, QK_RBT, DB_TOGG, QK_BOOT, KC_NO, + RGB_SPD, RGB_HUD, RGB_SAD, RGB_VAD, RGB_RMOD, RGB_TOG, KC_NO, DF(_QWERTY), DF(_COLEMAK_DH), KC_NO, KC_NO, KC_NO, + KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ + ) + // clang-format on +}; + +/* + --- Rotary Encoder Mappings --- + + Encoder mappings go from leftmost encoder to rightmost encoder on the physical board. + index 0 is the the optional leftmost encoder on the left half, index 1 is the right encoder + on the left half (by the thumb keys), index 2 is the left encoder on the right half (by the + thumb keys), and index 3 is the optional rightmost encoder on the right half. + + If you are only using the 2 required encoders by the thumb keys, you only need to worry about + index 1 and index 2. + + Note that the key to be sent for counter-clockwise rotation (CCW) goes first and then the key for + clockwise (CW) within ENCODER_CCW_CW. +*/ +#ifdef ENCODER_MAP_ENABLE +// clang-format off + +// Base layer encoder mappings: index 0: mouse wheel up (CCW)/down (CW) index 1: volume down/up index 2: mouse wheel up/down index 3: mouse wheel left/right +# define BASE_LAYER_ENCODERS { ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_VOLD, KC_VOLU), ENCODER_CCW_CW(KC_MS_WH_UP, KC_MS_WH_DOWN), ENCODER_CCW_CW(KC_WH_L, KC_WH_R) } +const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][2] = { + // Base layers + [_QWERTY] = BASE_LAYER_ENCODERS, + [_COLEMAK_DH] = BASE_LAYER_ENCODERS, + + // Passes through to base layers + [_SYMB] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // On the extension layer, the right side's left encoder by the thumb keys (mouse wheel up/down) is traded for media previous/next + [_EXT] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_MPRV, KC_MNXT), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // Passes through + [_ADJUST] = { ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS), ENCODER_CCW_CW(KC_TRNS, KC_TRNS) }, + // clang-format on +}; + +#endif diff --git a/keyboards/junco/keymaps/via/rules.mk b/keyboards/junco/keymaps/via/rules.mk new file mode 100644 index 000000000000..fd9cd98bcb4c --- /dev/null +++ b/keyboards/junco/keymaps/via/rules.mk @@ -0,0 +1,19 @@ +# Change from yes to no to disable features + +# Enables Audio control and System control Keycodes +EXTRAKEY_ENABLE = yes +# Enables Mousekeys +MOUSEKEY_ENABLE = yes +# Encoder Support +ENCODER_ENABLE = yes +# Use Enocoder Mapping +ENCODER_MAP_ENABLE = yes + +# Enables RGB Matrix +RGB_MATRIX_ENABLE = yes + +# Allows use of `qmk console` for debugging +# CONSOLE_ENABLE = yes + +# Enables VIA +VIA_ENABLE = yes diff --git a/keyboards/junco/post_config.h b/keyboards/junco/post_config.h new file mode 100644 index 000000000000..4f19a6243a8b --- /dev/null +++ b/keyboards/junco/post_config.h @@ -0,0 +1,17 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifdef JUNCO_SYNC_ENABLE +// Keyboard-level data sync ids +# define SPLIT_TRANSACTION_IDS_KB KB_SYNC, KB_SYNC_RESET, KB_SYNC_RGB + +// By default will throttle syncs to a maximum of 1 per second +# ifndef JUNCO_SYNC_THROTTLE +# define JUNCO_SYNC_THROTTLE 1000 +# endif +// By default, syncs will be tried 10 times before giving up +# ifndef JUNCO_SYNC_RETRIES +# define JUNCO_SYNC_RETRIES 10 +# endif + +#endif diff --git a/keyboards/junco/rev1/config.h b/keyboards/junco/rev1/config.h new file mode 100644 index 000000000000..80e4f7ace1f0 --- /dev/null +++ b/keyboards/junco/rev1/config.h @@ -0,0 +1,50 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +// Key matrix size (Rows are doubled-up for split) +#define MATRIX_ROWS 10 +#define MATRIX_COLS 6 + +// Electrical Wiring Stuff +#define MATRIX_ROW_PINS \ + { GP8, GP9, GP10, GP11, GP12 } +#define MATRIX_COL_PINS \ + { GP2, GP3, GP4, GP5, GP6, GP7 } +#define DIODE_DIRECTION COL2ROW + +// Split Keyboard Stuff +#define EE_HANDS // Sets the keyboard’s handedness using EEPROM +#define SPLIT_USB_DETECT // USB Detection to decide which side is "master" +#define SERIAL_USART_FULL_DUPLEX // Use full duplex communication (TRRS) +#define SERIAL_USART_TX_PIN GP0 // USART TX pin +#define SERIAL_USART_RX_PIN GP1 // USART RX pin + +/* RGB Stuff */ +#ifdef RGB_MATRIX_ENABLE + +# define RGB_DI_PIN GP15 // Pin for RGB logic +# define RGBLED_NUM 74 // Number of LEDs +# define DRIVER_LED_TOTAL RGBLED_NUM +# define RGB_MATRIX_LED_COUNT RGBLED_NUM +# define RGB_MATRIX_SPLIT \ + { 37, 37 } // 37 LEDs on each side + +#endif + +/* Rotary Encoders Definition */ +// Indexing goes from physical leftmost to rightmost +// 0: left-half left | 1: left-half right | 2: right-half left | 3: right-half right +#ifdef ENCODER_ENABLE + +# define ENCODERS_PAD_A \ + { GP16, GP14 } +# define ENCODERS_PAD_B \ + { GP17, GP13 } +# define ENCODERS_PAD_A_RIGHT \ + { GP14, GP16 } +# define ENCODERS_PAD_B_RIGHT \ + { GP13, GP17 } + +#endif diff --git a/keyboards/junco/rev1/post_config.h b/keyboards/junco/rev1/post_config.h new file mode 100644 index 000000000000..2068ac51b60e --- /dev/null +++ b/keyboards/junco/rev1/post_config.h @@ -0,0 +1,19 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +/* Default Bootmagic lite */ +// Top left for left side +#ifndef BOOTMAGIC_LITE_ROW +# define BOOTMAGIC_LITE_ROW 0 +#endif +#ifndef BOOTMAGIC_LITE_COLUMN +# define BOOTMAGIC_LITE_COLUMN 0 +#endif + +// Top right for right side +#ifndef BOOTMAGIC_LITE_ROW_RIGHT +# define BOOTMAGIC_LITE_ROW_RIGHT 5 +#endif +#ifndef BOOTMAGIC_LITE_COLUMN_RIGHT +# define BOOTMAGIC_LITE_COLUMN_RIGHT 0 +#endif diff --git a/keyboards/junco/rev1/rev1.c b/keyboards/junco/rev1/rev1.c new file mode 100644 index 000000000000..7facd4af8dc6 --- /dev/null +++ b/keyboards/junco/rev1/rev1.c @@ -0,0 +1,177 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "junco.h" + +// New default bootmagic lite, adds ability to manually set the handedness +// and won't clear it. Mostly copied from the Core bootmagic_lite. +__attribute__((weak)) void bootmagic_lite(void) { + // Multiple scans because debouncing can't be turned off. + matrix_scan(); +#if defined(DEBOUNCE) && DEBOUNCE > 0 + wait_ms(DEBOUNCE * 2); +#else + wait_ms(30); +#endif + matrix_scan(); + + uint8_t row = BOOTMAGIC_LITE_ROW; + uint8_t col = BOOTMAGIC_LITE_COLUMN; + +#if defined(BOOTMAGIC_LITE_ROW_RIGHT) && defined(BOOTMAGIC_LITE_COLUMN_RIGHT) + if (!is_keyboard_left()) { + row = BOOTMAGIC_LITE_ROW_RIGHT; + col = BOOTMAGIC_LITE_COLUMN_RIGHT; + } +#endif + + if (is_keyboard_master()) { + // If key next to bootmagic is pressed + if (matrix_get_row(row) & (1 << (col + 1))) { + // Set left side + eeconfig_update_handedness(true); + soft_reset_keyboard(); + } + + // If key 2 over from bootmagic is pressed + if (matrix_get_row(row) & (1 << (col + 2))) { + // Set right side + eeconfig_update_handedness(false); + soft_reset_keyboard(); + } + } + + // Normal bootmagic + if (matrix_get_row(row) & (1 << col)) { + // Clear EEPROM +#ifdef EE_HANDS + eeconfig_init_persist_handedness(); +#else + eeconfig_disable(); +#endif + // Jump to bootloader. + bootloader_jump(); + } +} + +// Hand swap +#ifdef SWAP_HANDS_ENABLE +__attribute__ ((weak)) +const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { + // Left + {{0, 5}, {1, 5}, {2, 5}, {3, 5}, {4, 5}, {5, 5}, {6, 5}}, + {{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}}, + {{0, 7}, {1, 7}, {2, 7}, {3, 7}, {4, 7}, {5, 7}, {6, 7}}, + {{0, 8}, {1, 8}, {2, 8}, {3, 8}, {4, 8}, {5, 8}, {6, 8}}, + {{0, 9}, {1, 9}, {2, 9}, {3, 9}, {4, 9}, {5, 9}, {6, 9}}, + // Right + {{0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {5, 0}, {6, 0}}, + {{0, 1}, {1, 1}, {2, 1}, {3, 1}, {4, 1}, {5, 1}, {6, 1}}, + {{0, 2}, {1, 2}, {2, 2}, {3, 2}, {4, 2}, {5, 2}, {6, 2}}, + {{0, 3}, {1, 3}, {2, 3}, {3, 3}, {4, 3}, {5, 3}, {6, 3}}, + {{0, 4}, {1, 4}, {2, 4}, {3, 4}, {4, 4}, {5, 4}, {6, 4}} +}; +#endif + +/* RGB LED matrix */ +#ifdef RGB_MATRIX_ENABLE +/* + Key Matrix Physical + 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, + L30, L31, L32, L33, L34, L35, L45, R40, R30, R31, R32, R33, R34, R35, + L40, L41, L42, L43, L44, R42, R41, R43, R44, R45 + + Key Electrical + Left: + { L00, L01, L02, L03, L04, L05 }, + { L10, L11, L12, L13, L14, L15 }, + { L20, L21, L22, L23, L24, L25 }, + { L30, L31, L32, L33, L34, L35 }, + { L40, L41, L42, L43, L44, L45 }, + Right: + { R05, R04, R03, R02, R01, R00 }, + { R15, R14, R13, R12, R11, R10 }, + { R25, R24, R23, R22, R21, R20 }, + { R35, R34, R33, R32, R31, R30 }, + { R45, R44, R43, R42, R41, R40 } + + Key matrix physical filled with LED electrical indexes, count starting at 1 + + Col + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 Row + + 14 13 12 11 10 9 46 47 48 49 50 51 0 + 6 7 8 45 44 43 + 15 16 17 18 19 20 57 56 55 54 53 52 1 + + 26 25 24 23 22 21 58 59 60 61 62 63 2 + 5 4 3 40 41 42 + 27 28 29 30 31 32 NO NO 69 68 67 66 65 64 3 + + 37 36 35 34 33 70 71 72 73 74 4 + 2 1 38 39 +*/ + +// clang-format off +led_config_t g_led_config = { + { // Key Electrical Matrix to LED Index (count start at 0, so 8 is the first non-underglow key) + + // Left Half + { 13, 12, 11, 10, 9, 8 }, + { 14, 15, 16, 17, 18, 19 }, + { 25, 24, 23, 22, 21, 20 }, + { 26, 27, 28, 29, 30, 31 }, + { 36, 35, 34, 33, 32, NO_LED }, + + // Right Half + { 50, 49, 48, 47, 46, 45 }, + { 51, 52, 53, 54, 55, 56 }, + { 62, 61, 60, 59, 58, 57 }, + { 63, 64, 65, 66, 67, 68 }, + { 73, 72, 71, 70, 69, NO_LED } + }, + { // LED Index to LED Physical Position (mirrored on right half) + + // Left Underglow (indicies 1 - 8) + { 95, 72 }, { 52, 72 }, { 86, 40 }, { 52, 40 }, { 9, 40 }, { 9, 8 }, { 52, 8 }, { 86, 8 }, + // Left Matrix (indicies 9 - 37) + { 86, 0 }, { 69, 0 }, { 52, 0 }, { 34, 0 }, { 17, 0 }, { 0, 0 }, + { 0, 16 }, { 17, 16 }, { 34, 16 }, { 52, 16 }, { 69, 16 }, { 86, 16 }, + { 86, 32 }, { 69, 32 }, { 52, 32 }, { 34, 32 }, { 17, 32 }, { 0, 32 }, + { 0, 48 }, { 17, 48 }, { 34, 48 }, { 52, 48 }, { 69, 48 }, { 86, 48 }, /* No Led */ + { 103, 64 }, { 86, 64 }, { 69, 64 }, { 52, 64 }, { 34, 64 }, + + // Right Underglow (indicies 38 - 45) + { 129, 72 }, { 172, 72 }, { 138, 40 }, { 172, 40 }, { 215, 40 }, { 215, 8 }, { 172, 8 }, { 138, 8 }, + // Right Matrix (indicies 46 - 74) + { 138, 0 }, { 155, 0 }, { 172, 0 }, { 190, 0 }, { 207, 0 }, { 224, 0 }, + { 224, 16 }, { 207, 16 }, { 190, 16 }, { 172, 16 }, { 155, 16 }, { 138, 16 }, + { 138, 32 }, { 155, 32 }, { 172, 32 }, { 190, 32 }, { 207, 32 }, { 224, 32 }, + /* No Led */ { 224, 48 }, { 207, 48 }, { 190, 48 }, { 172, 48 }, { 155, 48 }, { 138, 48 }, + { 121, 64 }, { 138, 64 }, { 155, 64 }, { 172, 64 }, { 190, 64 } + }, + { // LED Index to Flag (2 - Underglow, 4 - Key Backlight) + + // Left Underglow + 2, 2, 2, 2, 2, 2, 2, 2, + // Left Matrix + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, + + // Right Underglow + 2, 2, 2, 2, 2, 2, 2, 2, + // Right Matrix + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4 + } +}; + +#endif diff --git a/keyboards/junco/rev1/rev1.h b/keyboards/junco/rev1/rev1.h new file mode 100644 index 000000000000..41ecfea13bc4 --- /dev/null +++ b/keyboards/junco/rev1/rev1.h @@ -0,0 +1,4 @@ +// Copyright 2022 Dane Skalski (@Daneski13) +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once diff --git a/keyboards/junco/rev1/rules.mk b/keyboards/junco/rev1/rules.mk new file mode 100644 index 000000000000..feb836dbe1e0 --- /dev/null +++ b/keyboards/junco/rev1/rules.mk @@ -0,0 +1,3 @@ +# RGB Stuff +RGB_MATRIX_DRIVER = WS2812 +WS2812_DRIVER = vendor diff --git a/keyboards/junco/rules.mk b/keyboards/junco/rules.mk new file mode 100644 index 000000000000..61b68ec5e11d --- /dev/null +++ b/keyboards/junco/rules.mk @@ -0,0 +1,20 @@ +# MCU +MCU = RP2040 + +# Board +BOARD = GENERIC_RP_RP2040 + +# Bootloader selection +BOOTLOADER = rp2040 + +# Split Keyboard Stuff +SPLIT_KEYBOARD = yes +SERIAL_DRIVER = vendor + +# Enable Bootmagic Lite +BOOTMAGIC_ENABLE = yes + +# Default Folder +DEFAULT_FOLDER = junco/rev1 + +SRC += junco_sync.c