diff --git a/keyboards/system76/launch_1/config.h b/keyboards/system76/launch_1/config.h index 886b5e2b7859..b290abb14da9 100644 --- a/keyboards/system76/launch_1/config.h +++ b/keyboards/system76/launch_1/config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 System76 + * Copyright (C) 2021-2022 System76 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,38 +17,34 @@ #pragma once - -/* - * Key matrix pins - * ROWS: AVR pins used for rows, top to bottom - * COLS: AVR pins used for columns, left to right - */ +// Key matrix pins +// ROWS: AVR pins used for rows, top to bottom +// COLS: AVR pins used for columns, left to right #define MATRIX_ROW_PINS { F0, F1, F4, F5, F6, F7 } #define MATRIX_COL_PINS { D7, C7, C6, B6, B5, B4, D6, D4, E6, D5, D3, D2, B7, B0 } -/* - * Diode Direction - * COL2ROW = COL => Anode (+), ROW => Cathode (-) - * ROW2COL = ROW => Anode (+), COL => Cathode (-) - */ +// Matrix diode direction +// COL2ROW: COL => Anode (+), ROW => Cathode (-) +// ROW2COL: ROW => Anode (+), COL => Cathode (-) #define DIODE_DIRECTION COL2ROW +// RGB matrix #ifdef RGB_MATRIX_ENABLE -# define RGB_DI_PIN E2 -# define RGB_MATRIX_LED_COUNT 84 -# define RGB_MATRIX_KEYPRESSES // Reacts to keypresses -// # define RGB_MATRIX_KEYRELEASES // Reacts to keyreleases (instead of keypresses) -// # define RGB_MATRIX_FRAMEBUFFER_EFFECTS // Enables framebuffer effects -# define RGB_DISABLE_WHEN_USB_SUSPENDED // Turns off effects when suspended +# define RGB_DI_PIN E2 // Pin connected to the data pin of the LEDs +# define RGB_MATRIX_LED_COUNT 84 // Number of LEDs connected +# define RGB_MATRIX_KEYPRESSES // Reacts to keypresses +//# define RGB_MATRIX_KEYRELEASES // Reacts to keyreleases (instead of keypresses) +//# define RGB_MATRIX_FRAMEBUFFER_EFFECTS // Enables framebuffer effects +# define RGB_DISABLE_WHEN_USB_SUSPENDED // Turns off effects when suspended // Limit brightness to support USB-A at 0.5 A // TODO: Do this dynamically based on power source -# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 176 // Limits maximum brightness of LEDs to 176 out of 255. If not defined, maximum brightness is set to 255 -# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_RAINBOW_MOVING_CHEVRON // Sets the default mode, if none has been set -# define RGB_MATRIX_DEFAULT_HUE 142 // Sets the default hue value, if none has been set -# define RGB_MATRIX_DEFAULT_SAT 255 // Sets the default saturation value, if none has been set -# define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set -# define RGB_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set -# define RGB_MATRIX_DISABLE_KEYCODES // Disables control of rgb matrix by keycodes (must use code functions to control the feature) +# define RGB_MATRIX_MAXIMUM_BRIGHTNESS 176 // Limits maximum brightness of LEDs to 176 out of 255. If not defined, maximum brightness is set to 255 +# define RGB_MATRIX_DEFAULT_MODE RGB_MATRIX_RAINBOW_MOVING_CHEVRON // Sets the default mode, if none has been set +# define RGB_MATRIX_DEFAULT_HUE 142 // Sets the default hue value, if none has been set +# define RGB_MATRIX_DEFAULT_SAT 255 // Sets the default saturation value, if none has been set +# define RGB_MATRIX_DEFAULT_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS // Sets the default brightness value, if none has been set +# define RGB_MATRIX_DEFAULT_SPD 127 // Sets the default animation speed, if none has been set +# define RGB_MATRIX_DISABLE_KEYCODES // Disables control of rgb matrix by keycodes (must use code functions to control the feature) # define ENABLE_RGB_MATRIX_CYCLE_ALL # define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT @@ -61,33 +57,24 @@ # define ENABLE_RGB_MATRIX_RAINDROPS # define ENABLE_RGB_MATRIX_SPLASH # define ENABLE_RGB_MATRIX_MULTISPLASH -#endif // RGB_MATRIX_ENABLE - -// Mechanical locking support; use KC_LCAP, KC_LNUM, or KC_LSCR instead in keymap -#define LOCKING_SUPPORT_ENABLE - -// Locking resynchronize hack -#define LOCKING_RESYNC_ENABLE +#endif // RGB_MATRIX_ENABLE -// I2C { +// I2C #define F_SCL 100000UL // Run I2C bus at 100 kHz #define I2C_START_RETRY_COUNT 20 #define I2C_TIMEOUT 100 // milliseconds -// } I2C -// EEPROM { -#define EEPROM_SIZE 1024 -// TODO: Refactor with new user EEPROM code (coming soon) +// EEPROM +#define EEPROM_SIZE 1024 // (TOTAL_EEPROM_BYTE_COUNT) #define EEPROM_MAGIC 0x76EC -#define EEPROM_MAGIC_ADDR 64 -// Bump this every time we change what we store -// This will automatically reset the EEPROM with defaults -// and avoid loading invalid data from the EEPROM +#define EEPROM_MAGIC_ADDR (EECONFIG_SIZE) +// Bump `EEPROM_VERSION' every time what is stored changes +// to automatically reset the EEPROM with defaults and +// avoid loading invalid data from the EEPROM #define EEPROM_VERSION 0x02 #define EEPROM_VERSION_ADDR (EEPROM_MAGIC_ADDR + 2) -// } EEPROM -// Dynamic keymap { +// Dynamic keymap #define DYNAMIC_KEYMAP_LAYER_COUNT 4 #define DYNAMIC_KEYMAP_MACRO_COUNT 0 // Dynamic keymap starts after EEPROM version @@ -95,9 +82,7 @@ // Dynamic macro starts after dynamic keymaps, it is disabled #define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2)) #define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE 0 -// } Dynamic keymap -// System76 EC { +// System76 EC #define SYSTEM76_EC_EEPROM_ADDR (DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE) #define SYSTEM76_EC_EEPROM_SIZE (EEPROM_SIZE - SYSTEM76_EC_EEPROM_ADDR) -// } System76 EC diff --git a/keyboards/system76/launch_1/keymaps/default/keymap.c b/keyboards/system76/launch_1/keymaps/default/keymap.c index 1da2fbf4bc77..887a6fd410e5 100644 --- a/keyboards/system76/launch_1/keymaps/default/keymap.c +++ b/keyboards/system76/launch_1/keymaps/default/keymap.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 System76 + * Copyright (C) 2021-2022 System76 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,28 +17,29 @@ #include QMK_KEYBOARD_H +// clang-format off const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Layer 0, default layer - _________________________________________________________________________________________________________________________________ ________ -| | | | | | | | | | | | | | || | -| ESC | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | DELETE || HOME | -|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| -| ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | _ | + | || | -| ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | BACKSPACE || PGUP | -|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| -| | | | | | | | | | | | [ | ] | | || | -| TAB | Q | W | E | R | T | Y | U | I | O | P | { | } | \ || PGDN | -|____________|________|________|________|________|________|________|________|________|________|________|________|________|________||________| - | | | | | | | | | | | : | " | | | | - | CAPS | A | S | D | F | G | H | J | K | L | ; | ' | ENTER | | END | - |____________|________|________|________|________|________|________|________|________|________|________|________|____________|___|________| - | | | | | | | | | < | > | ? | | | - | SHIFT | Z | X | C | V | B | N | M | , | . | / | SHIFT | UP | - |________________|________|________|________|________|________|________|________|________|________|________|____________|________|________ - | | | | | | | | | | | | | | - | CTRL | LALT | FN | LGUI | SPACE | SPACE | RCTRL | RALT | FN | | LEFT | DOWN | RIGHT | - |____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________| + _________________________________________________________________________________________________________________________________ ________ + | | | | | | | | | | | | | | || | + | ESC | F1 | F2 | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | F11 | F12 | DELETE || HOME | + |________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| + | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | _ | + | || | + | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | - | = | BACKSPACE || PGUP | + |________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| + | | | | | | | | | | | | [ | ] | | || | + | TAB | Q | W | E | R | T | Y | U | I | O | P | { | } | \ || PGDN | + |____________|________|________|________|________|________|________|________|________|________|________|________|________|________||________| + | | | | | | | | | | | : | " | | | | + | CAPS | A | S | D | F | G | H | J | K | L | ; | ' | ENTER | | END | + |____________|________|________|________|________|________|________|________|________|________|________|________|____________|___|________| + | | | | | | | | | < | > | ? | | | + | SHIFT | Z | X | C | V | B | N | M | , | . | / | SHIFT | UP | + |________________|________|________|________|________|________|________|________|________|________|________|____________|________|________ + | | | | | | | | | | | | | | + | CTRL | LALT | FN | LGUI | SPACE | SPACE | RCTRL | RALT | FN | | LEFT | DOWN | RIGHT | + |____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________| */ [0] = LAYOUT( @@ -51,32 +52,32 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ), /* Layer 1, function layer - _________________________________________________________________________________________________________________________________ ________ -| | | | | | | | | | | | | | || PLAY/ | -| QK_BOOT | | | | | | | | | | | | | || PAUSE | -|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| -| | | | | | | | | | | LED | LED | LED | || VOLUME | -| | | | | | | | | | | TOGGLE | DOWN | UP | || UP | -|________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| -| | | | | | | | | | | | | | || VOLUME | -|PRINT SCREEN| | | | | | HOME | PGDN | PGUP | END | | | | || DOWN | -|____________|________|________|________|________|________|________|________|________|________|________|________|________|________||________| - | | | | | | | | | | | | | | | | - | | | | | | | LEFT | DOWN | UP | RIGHT | | | | | MUTE | - |____________|________|________|________|________|________|________|________|________|________|________|________|____________|___|________| - | | | | | | | | | | | | | | - | | | | | | | | | | | | | PGUP | - |________________|________|________|________|________|________|________|________|________|________|________|____________|________|________ - | | | | | | | | | | | | | | - | | | | | | | | | | | HOME | PGDN | END | - |____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________| + _________________________________________________________________________________________________________________________________ ________ + | | | | | | | | | | | | | | || PLAY/ | + | QK_BOOT| | | | | | | | | | | | | || PAUSE | + |________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| + | | | | | | | | | | | LED | LED | LED | || VOLUME | + | | | | | | | | | | | TOGGLE | DOWN | UP | || UP | + |________|________|________|________|________|________|________|________|________|________|________|________|________|____________||________| + | | | | | | | | | | | | | | || VOLUME | + |PRINT SCREEN| | | | | | HOME | PGDN | PGUP | END | | | | || DOWN | + |____________|________|________|________|________|________|________|________|________|________|________|________|________|________||________| + | | | | | | | | | | | | | | | | + | | | | | | | LEFT | DOWN | UP | RIGHT | | | | | MUTE | + |____________|________|________|________|________|________|________|________|________|________|________|________|____________|___|________| + | | | | | | | | | | | | | | + | | | | | | | | | | | | | PGUP | + |________________|________|________|________|________|________|________|________|________|________|________|____________|________|________ + | | | | | | | | | | | | | | + | | | | | | | | | | | HOME | PGDN | END | + |____________|________|_______|________|_________________|_________________|________|________|_____________| |________|________|________| * `QK_BOOT' resets the controller and puts the board into firmware flashing mode. * If this key is hit accidentally, just unplug the board and plug it back in. */ [1] = LAYOUT( - QK_BOOT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, + QK_BOOT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MPLY, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, RGB_TOG, RGB_VAD, RGB_VAI, KC_TRNS, KC_VOLU, KC_PSCR, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_PGDN, KC_PGUP, KC_END, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_VOLD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_MUTE, @@ -102,3 +103,4 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS ), }; +// clang-format on diff --git a/keyboards/system76/launch_1/keymaps/default/readme.md b/keyboards/system76/launch_1/keymaps/default/readme.md new file mode 100644 index 000000000000..90b594c8d303 --- /dev/null +++ b/keyboards/system76/launch_1/keymaps/default/readme.md @@ -0,0 +1,5 @@ +# Default keymap for launch_1 + +![launch_1 Base Layout Image](https://i.imgur.com/7RTC4iVh.png "launch_1 Base Layout") + +This is the default layout that comes flashed out of the box. The `Fn` keys are used to access the additional layer. There are 4 layers available which can be modified without flashing using the [System76 Keyboard Configurator](https://system76.com/accessories/launch/download) application. diff --git a/keyboards/system76/launch_1/launch_1.c b/keyboards/system76/launch_1/launch_1.c index fd780f6fee27..27de22bf60e7 100644 --- a/keyboards/system76/launch_1/launch_1.c +++ b/keyboards/system76/launch_1/launch_1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 System76 + * Copyright (C) 2021-2022 System76 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,7 @@ #include "launch_1.h" +#include "system76_ec.h" #include "usb_mux.h" // clang-format off @@ -33,14 +34,14 @@ // 70 LB0 LC0 LD0 LE0 LF0 LG0 LH0 LI0 LJ0 LK0 // 80 LL0 LM0 LN0 LO0 led_config_t g_led_config = { { - // Key matrix to LED index -/* A B C D E F G H I J K L M N O */ -/* 0 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, */ -/* 1 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, */ -/* 2 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, */ -/* 3 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, */ -/* 4 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, */ -/* 5 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 */ + // Key matrix to LED index (see `launch_1.h' for matrix-to-physical layout) +// A B C D E F G H I J K L M N O +// 0 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, +// 1 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, +// 2 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +// 3 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, +// 4 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, +// 5 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 { 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82 }, { 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55 }, { 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 }, @@ -48,7 +49,7 @@ led_config_t g_led_config = { { { 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 54 }, { 13, 14, 15, 16, 17, 25, 18, 19, 20, 21, 22, 23, 24, 53 }, }, { - // LED index to physical position (see leds.sh in `launch' repo) + // LED index to physical position (see `leds.sh' in `launch' repository) /* 00 */ {209, 51}, {190, 51}, {171, 51}, {156, 51}, {140, 51}, {125, 51}, {110, 51}, {95, 51}, {80, 51}, {65, 51}, /* 10 */ {49, 51}, {34, 51}, {11, 51}, {8, 64}, {27, 64}, {42, 64}, {57, 64}, {80, 64}, {110, 64}, {133, 64}, /* 20 */ {148, 64}, {167, 64}, {194, 64}, {209, 64}, {224, 64}, {224, 38}, {197, 38}, {178, 38}, {163, 38}, {148, 38}, @@ -59,8 +60,8 @@ led_config_t g_led_config = { { /* 70 */ {15, 0}, {30, 0}, {46, 0}, {61, 0}, {76, 0}, {91, 0}, {106, 0}, {121, 0}, {137, 0}, {152, 0}, /* 80 */ {167, 0}, {182, 0}, {201, 0}, {224, 0} }, { - // LED index to flags (set all to LED_FLAG_KEYLIGHT) - /* 0 1 2 3 4 5 6 7 8 9 */ + // LED index to flags (set all to `LED_FLAG_KEYLIGHT') +/* 0 1 2 3 4 5 6 7 8 9 */ /* 00 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 10 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 20 */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, @@ -72,14 +73,11 @@ led_config_t g_led_config = { { /* 80 */ 4, 4, 4, 4 } }; #endif // RGB_MATRIX_ENABLE +// clang-format on -bool eeprom_is_valid(void) { - return ( - eeprom_read_word(((void *)EEPROM_MAGIC_ADDR)) == EEPROM_MAGIC && - eeprom_read_byte(((void *)EEPROM_VERSION_ADDR)) == EEPROM_VERSION - ); +bool eeprom_is_valid(void) { + return (eeprom_read_word(((void *)EEPROM_MAGIC_ADDR)) == EEPROM_MAGIC && eeprom_read_byte(((void *)EEPROM_VERSION_ADDR)) == EEPROM_VERSION); } -// clang-format on void eeprom_set_valid(bool valid) { eeprom_update_word(((void *)EEPROM_MAGIC_ADDR), valid ? EEPROM_MAGIC : 0xFFFF); @@ -87,62 +85,32 @@ void eeprom_set_valid(bool valid) { } void bootmagic_lite_reset_eeprom(void) { - // Set the keyboard-specific EEPROM state as invalid - eeprom_set_valid(false); - // Set the TMK/QMK EEPROM state as invalid - eeconfig_disable(); -} - -// The lite version of TMK's bootmagic based on Wilba. -// 100% less potential for accidentally making the keyboard do stupid things. -void bootmagic_lite(void) { - // Perform 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(); - - // If the configured key (commonly Esc) is held down on power up, - // reset the EEPROM valid state and jump to bootloader. - uint8_t row = 0; // BOOTMAGIC_LITE_ROW; - uint8_t col = 0; // BOOTMAGIC_LITE_COLUMN; - - if (matrix_get_row(row) & (1 << col)) { - bootmagic_lite_reset_eeprom(); - - // Jump to bootloader. - bootloader_jump(); - } + eeprom_set_valid(false); // Set the keyboard-specific EEPROM state as invalid + eeconfig_disable(); // Set the TMK/QMK EEPROM state as invalid } -void system76_ec_rgb_eeprom(bool write); -void system76_ec_rgb_layer(layer_state_t layer_state); -void system76_ec_unlock(void); -bool system76_ec_is_unlocked(void); - rgb_config_t layer_rgb[DYNAMIC_KEYMAP_LAYER_COUNT]; void matrix_init_kb(void) { usb_mux_init(); - bootmagic_lite(); if (!eeprom_is_valid()) { - dynamic_keymap_reset(); - dynamic_keymap_macro_reset(); - system76_ec_rgb_eeprom(true); - eeprom_set_valid(true); + // eeprom_set_valid(false); // Set the magic number to `false', in case this gets interrupted + dynamic_keymap_reset(); // Reset the keymaps in EEPROM to what is in flash + dynamic_keymap_macro_reset(); // Reset the macros in EEPROM to nothing + system76_ec_rgb_eeprom(true); // Populate System76 per-layer RGB matrix settings + eeprom_set_valid(true); // Save the magic number last, in case saving was interrupted } else { - system76_ec_rgb_eeprom(false); + system76_ec_rgb_eeprom(false); // Read System76 per-layer RGB matrix settings } system76_ec_rgb_layer(layer_state); + + matrix_init_user(); } void matrix_scan_kb(void) { - usb_mux_event(); + usb_mux_event(); // Poll the USB hub for cable connections and disconnections matrix_scan_user(); } @@ -160,8 +128,11 @@ static const uint8_t levels[] = { }; // clang-format on +#ifdef SYSTEM76_EC +extern bool input_disabled; +static bool lctl_pressed, rctl_pressed = false; +#endif static uint8_t toggle_level = RGB_MATRIX_MAXIMUM_BRIGHTNESS; -extern bool input_disabled; static void set_value_all_layers(uint8_t value) { if (!system76_ec_is_unlocked()) { @@ -173,9 +144,11 @@ static void set_value_all_layers(uint8_t value) { } bool process_record_kb(uint16_t keycode, keyrecord_t *record) { +#ifdef SYSTEM76_EC if (input_disabled) { return false; } +#endif if (!process_record_user(keycode, record)) { return false; @@ -184,13 +157,9 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case QK_BOOT: if (record->event.pressed) { - system76_ec_unlock(); + rgb_matrix_mode_noeeprom(RGB_MATRIX_NONE); } -#ifdef SYSTEM76_EC - return false; -#else - return true; -#endif + break; case RGB_VAD: if (record->event.pressed) { uint8_t level = rgb_matrix_config.hsv.v; @@ -226,21 +195,38 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) { set_value_all_layers(level); } return false; +#ifdef SYSTEM76_EC + case KC_LEFT_CTRL: + lctl_pressed = record->event.pressed; + break; + case KC_RIGHT_CTRL: + rctl_pressed = record->event.pressed; + break; + case KC_ESCAPE: + if (lctl_pressed && rctl_pressed) { + if (record->event.pressed) { + system76_ec_unlock(); + } + return false; + } + break; +#endif } return true; } -layer_state_t layer_state_set_kb(layer_state_t layer_state) { - system76_ec_rgb_layer(layer_state); +// Layer change callbacks +layer_state_t layer_state_set_kb(layer_state_t state) { + system76_ec_rgb_layer(state); - return layer_state_set_user(layer_state); + return layer_state_set_user(state); } #ifdef CONSOLE_ENABLE void keyboard_post_init_user(void) { - debug_enable = true; - debug_matrix = false; + debug_enable = true; + debug_matrix = false; debug_keyboard = false; } -#endif // CONSOLE_ENABLE +#endif // CONSOLE_ENABLE diff --git a/keyboards/system76/launch_1/launch_1.h b/keyboards/system76/launch_1/launch_1.h index 335b8ecbdf1b..eef546efbfa2 100644 --- a/keyboards/system76/launch_1/launch_1.h +++ b/keyboards/system76/launch_1/launch_1.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 System76 + * Copyright (C) 2021-2022 System76 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/keyboards/system76/launch_1/post_rules.mk b/keyboards/system76/launch_1/post_rules.mk index 3751a8b8c31b..83fe34aa10e2 100644 --- a/keyboards/system76/launch_1/post_rules.mk +++ b/keyboards/system76/launch_1/post_rules.mk @@ -1,12 +1,15 @@ # System76 EC -# remove the RESET HID command -VALID_SYSTEM76_EC_TYPES := yes -SYSTEM76_EC_ENABLE ?= no -ifneq ($(strip $(SYSTEM76_EC_ENABLE)),no) - ifeq ($(filter $(SYSTEM76_EC_ENABLE),$(VALID_SYSTEM76_EC_TYPES)),) - $(error SYSTEM76_EC_EN="$(strip $(SYSTEM76_EC_ENABLE))" is not a valid type for the System76 EC option) +# Add System76 EC raw HID command interface +VALID_SYSTEM76_EC_SETTINGS := yes no +SYSTEM76_EC_ENABLE ?= yes +ifneq ($(strip $(SYSTEM76_EC_ENABLE)),yes) + ifeq ($(filter $(SYSTEM76_EC_ENABLE),$(VALID_SYSTEM76_EC_SETTINGS)),) + $(error SYSTEM76_EC_ENABLE="$(strip $(SYSTEM76_EC_ENABLE))" is not a valid setting for the System76 EC option) endif - ifneq ($(strip $(SYSTEM76_EC_ENABLE)),no) - OPT_DEFS += -DSYSTEM76_EC + ifeq ($(strip $(SYSTEM76_EC_ENABLE)),no) + RAW_ENABLE = no endif +else + OPT_DEFS += -DSYSTEM76_EC endif +SRC += system76_ec.c diff --git a/keyboards/system76/launch_1/readme.md b/keyboards/system76/launch_1/readme.md index f012f861600c..f840eb1955d2 100644 --- a/keyboards/system76/launch_1/readme.md +++ b/keyboards/system76/launch_1/readme.md @@ -13,7 +13,8 @@ Additional Launch Keyboard resources: - Keyboard Maintainer: [System76](https://github.com/system76) - Hardware Supported: [System76 Launch GitHub Repository](https://github.com/system76/launch) -- Hardware Availability: [Shop System76](https://system76.com/accessories/launch) +- Hardware Specifications: [System76 Launch Technical Documentation](https://tech-docs.system76.com/models/launch_1/README.html) +- Hardware Availability: [System76 Shop](https://system76.com/accessories/launch) ## Building Firmware @@ -57,6 +58,6 @@ See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_to Enter the bootloader in 3 ways: -- **Bootmagic reset**: Hold down the key at (0,0) in the matrix (Escape) and plug in the keyboard. -- **Keycode in layout**: Press the key mapped to `QK_BOOT` in the second layer (Escape). +- **Bootmagic reset**: Hold down the key at (0,0) in the matrix (Esc) and plug in the keyboard. +- **Keycode in layout**: Press the key mapped to `QK_BOOT` in the second layer (Esc). - **Electrical reset**: Briefly short AVR ISP's GND (6) and RST (5) pads on the back of the PCB. diff --git a/keyboards/system76/launch_1/rgb_matrix_kb.inc b/keyboards/system76/launch_1/rgb_matrix_kb.inc index 02de10ed500e..0a716703ea0f 100644 --- a/keyboards/system76/launch_1/rgb_matrix_kb.inc +++ b/keyboards/system76/launch_1/rgb_matrix_kb.inc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 System76 + * Copyright (C) 2021-2022 System76 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,7 +38,7 @@ static void active_keys_initialize(void) { active_keys_initialized = true; } -static bool active_keys(effect_params_t* params) { +static bool active_keys(effect_params_t *params) { if (!active_keys_initialized) { active_keys_initialize(); } @@ -72,8 +72,8 @@ RGB raw_rgb_data[RGB_MATRIX_LED_COUNT] = {0}; static uint8_t normalize_component(uint8_t component) { uint16_t x = (uint16_t)component; - x *= rgb_matrix_config.hsv.v; // Multiply by current brightness - x /= 255; // Divide by maximum brightness + x *= rgb_matrix_config.hsv.v; // Multiply by current brightness + x /= 255; // Divide by maximum brightness return (uint8_t)x; } @@ -87,7 +87,7 @@ static RGB normalize_index(uint8_t i) { return rgb; } -static bool raw_rgb(effect_params_t* params) { +static bool raw_rgb(effect_params_t *params) { RGB_MATRIX_USE_LIMITS(led_min, led_max); for (uint8_t i = led_min; i < led_max; i++) { RGB_MATRIX_TEST_LED_FLAGS(); @@ -98,14 +98,14 @@ static bool raw_rgb(effect_params_t* params) { } static uint8_t unlocked_keys[8][2] = { - {2, 7}, // U - {4, 6}, // N - {3, 9}, // L - {2, 9}, // O - {4, 3}, // C - {3, 8}, // K - {2, 3}, // E - {3, 3}, // D + {2, 7}, // U + {4, 6}, // N + {3, 9}, // L + {2, 9}, // O + {4, 3}, // C + {3, 8}, // K + {2, 3}, // E + {3, 3}, // D }; static uint8_t unlocked_ticks = 0; @@ -113,7 +113,7 @@ static uint8_t unlocked_i = 0; static uint8_t unlocked_leds_count = 0; static uint8_t unlocked_leds[2] = {0, 0}; -static bool unlocked(effect_params_t* params) { +static bool unlocked(effect_params_t *params) { RGB_MATRIX_USE_LIMITS(led_min, led_max); unlocked_ticks++; @@ -154,4 +154,4 @@ static bool unlocked(effect_params_t* params) { return led_max < RGB_MATRIX_LED_COUNT; } -#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS +#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS diff --git a/keyboards/system76/launch_1/rules.mk b/keyboards/system76/launch_1/rules.mk index e20aa1fd585f..aaa5cddb9c57 100644 --- a/keyboards/system76/launch_1/rules.mk +++ b/keyboards/system76/launch_1/rules.mk @@ -6,7 +6,8 @@ F_USB = 16000000 # Build options # change yes to no to disable -BOOTMAGIC_ENABLE = no # Bootmagic Lite +# +BOOTMAGIC_ENABLE = yes # Bootmagic Lite MOUSEKEY_ENABLE = no # Mouse keys EXTRAKEY_ENABLE = yes # Audio control and system control CONSOLE_ENABLE = no # Console for debug @@ -14,14 +15,12 @@ COMMAND_ENABLE = no # Commands for debug and configuration DYNAMIC_KEYMAP_ENABLE = yes # Reconfigurable keyboard without flashing firmware NKRO_ENABLE = yes # USB N-key rollover RAW_ENABLE = yes # Raw HID commands (used by Keyboard Configurator) -BACKLIGHT_ENABLE = no # RGB backlight (conflicts with RGB matrix) -RGBLIGHT_ENABLE = no # Enable keyboard RGB underglow +BACKLIGHT_ENABLE = no # Keyboard backlight functionality +RGBLIGHT_ENABLE = no # Keyboard RGB underglow +AUDIO_ENABLE = no # Audio output RGB_MATRIX_ENABLE = yes # RGB matrix RGB_MATRIX_DRIVER = WS2812 RGB_MATRIX_CUSTOM_KB = yes # Custom keyboard effects -AUDIO_ENABLE = no # Audio output LTO_ENABLE = yes # Link-time optimization for smaller binary - -# Add System76 EC command interface as well as I2C and USB mux drivers -SRC += system76_ec.c usb_mux.c -QUANTUM_LIB_SRC += i2c_master.c +SRC += usb_mux.c# Add USB mux driver +QUANTUM_LIB_SRC += i2c_master.c# Add I2C driver diff --git a/keyboards/system76/launch_1/usb_mux.c b/keyboards/system76/launch_1/usb_mux.c index 6cb04dcdd716..2bdeeef4b7fa 100644 --- a/keyboards/system76/launch_1/usb_mux.c +++ b/keyboards/system76/launch_1/usb_mux.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2021 System76 - * Copyright (C) 2021 Jimmy Cassis + * Copyright (C) 2021-2022 System76 + * Copyright (C) 2021-2022 Jimmy Cassis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,14 +23,29 @@ #include "i2c_master.h" #include "wait.h" -#define REG_PF1_CTL 0xBF800C04 -#define REG_PIO64_OEN 0xBF800908 -#define REG_PIO64_OUT 0xBF800928 -#define REG_VID 0xBF803000 -#define REG_PRT_SWAP 0xBF8030FA -#define REG_USB3_HUB_VID 0xBFD2E548 -#define REG_RUNTIME_FLAGS2 0xBFD23408 -#define REG_I2S_FEAT_SEL 0xBFD23412 +// USB signal prefixes from schematic +// - UP = USB C upstream (center) +// - AR = USB A right side +// - AL = USB A left side +// - CR = USB C right side +// - CL = USB C left side + +// System76 USB Vendor ID and Product IDs from `https://github.com/system76/usb_ids'. +#define SYSTEM76_VID 0x3384 +#define LAUNCH_1_PID 0x0001 +#define LAUNCH_USB2_HUB_PID 0x0003 +#define LAUNCH_USB3_HUB_PID 0x0004 + +// USB7206 is a 6-Port USB 3.1 Gen 2 controller hub. +// I2C address: 0x5A = 0x2D << 1 +#define USB7206_PF1_CTL 0xBF800C04 +#define USB7206_VID 0xBF803000 +#define USB7206_HUB_PRT_SWAP 0xBF8030FA +#define USB7206_PIO96_OEN 0xBF800908 +#define USB7206_PIO96_OUT 0xBF800928 +#define USB7206_RUNTIME_FLAGS2 0xBFD23408 +#define USB7206_I2S_FEAT_SEL 0xBFD23412 +#define USB7206_USB3_HUB_VID 0xBFD2E548 struct USB7206 { uint8_t addr; @@ -38,9 +53,10 @@ struct USB7206 { struct USB7206 usb_hub = {.addr = 0x2D}; -// Perform USB7206 register access. +// Read or write USB7206 configuration register. +// The configuration register access opcode is `0x9937'. // Returns zero on success or a negative number on error. -i2c_status_t usb7206_register_access(struct USB7206* self) { +i2c_status_t usb7206_register_access(struct USB7206 *self) { uint8_t register_access[3] = { 0x99, 0x37, @@ -52,19 +68,19 @@ i2c_status_t usb7206_register_access(struct USB7206* self) { // Read data from USB7206 register region. // Returns number of bytes read on success or a negative number on error. -i2c_status_t usb7206_read_reg(struct USB7206* self, uint32_t addr, uint8_t* data, int length) { +i2c_status_t usb7206_read_reg(struct USB7206 *self, uint32_t addr, uint8_t *data, int length) { i2c_status_t status; uint8_t register_read[9] = { - 0x00, // Buffer address MSB: always 0 - 0x00, // Buffer address LSB: always 0 - 0x06, // Number of bytes to write to command block buffer area - 0x01, // Direction: 0 = write, 1 = read - (uint8_t)length, // Number of bytes to read from register - (uint8_t)(addr >> 24), // Register address byte 3 - (uint8_t)(addr >> 16), // Register address byte 2 - (uint8_t)(addr >> 8), // Register address byte 1 - (uint8_t)(addr >> 0), // Register address byte 0 + 0x00, // Buffer address MSB: always 0 + 0x00, // Buffer address LSB: always 0 + 0x06, // Number of bytes to write to command block buffer area + 0x01, // Transaction type: 0 = write, 1 = read + (uint8_t)length, // Number of bytes to read from register + (uint8_t)(addr >> 24), // Register address byte 3 + (uint8_t)(addr >> 16), // Register address byte 2 + (uint8_t)(addr >> 8), // Register address byte 1 + (uint8_t)(addr >> 0), // Register address byte 0 }; status = i2c_transmit(self->addr << 1, register_read, sizeof(register_read), I2C_TIMEOUT); @@ -78,8 +94,8 @@ i2c_status_t usb7206_read_reg(struct USB7206* self, uint32_t addr, uint8_t* data } uint8_t read[2] = { - 0x00, // Buffer address MSB: always 0 - 0x06, // Buffer address LSB: 6 to skip header + 0x00, // Buffer address MSB: always 0 + 0x06, // Buffer address LSB: 6 to skip header }; status = i2c_start((self->addr << 1) | I2C_WRITE, I2C_TIMEOUT); @@ -127,7 +143,7 @@ i2c_status_t usb7206_read_reg(struct USB7206* self, uint32_t addr, uint8_t* data // Read 32-bit value from USB7206 register region. // Returns number of bytes read on success or a negative number on error. -i2c_status_t usb7206_read_reg_32(struct USB7206* self, uint32_t addr, uint32_t* data) { +i2c_status_t usb7206_read_reg_32(struct USB7206 *self, uint32_t addr, uint32_t *data) { i2c_status_t status; // First byte is available length @@ -146,19 +162,19 @@ i2c_status_t usb7206_read_reg_32(struct USB7206* self, uint32_t addr, uint32_t* // Write data to USB7206 register region. // Returns number of bytes written on success or a negative number on error. -i2c_status_t usb7206_write_reg(struct USB7206* self, uint32_t addr, uint8_t* data, int length) { +i2c_status_t usb7206_write_reg(struct USB7206 *self, uint32_t addr, uint8_t *data, int length) { i2c_status_t status; uint8_t register_write[9] = { - 0x00, // Buffer address MSB: always 0 - 0x00, // Buffer address LSB: always 0 - ((uint8_t)length) + 6, // Number of bytes to write to command block buffer area - 0x00, // Direction: 0 = write, 1 = read - (uint8_t)length, // Number of bytes to write to register - (uint8_t)(addr >> 24), // Register address byte 3 - (uint8_t)(addr >> 16), // Register address byte 2 - (uint8_t)(addr >> 8), // Register address byte 1 - (uint8_t)(addr >> 0), // Register address byte 0 + 0x00, // Buffer address MSB: always 0 + 0x00, // Buffer address LSB: always 0 + ((uint8_t)length) + 6, // Number of bytes to write to command block buffer area + 0x00, // Transaction type: 0 = write, 1 = read + (uint8_t)length, // Number of bytes to write to register + (uint8_t)(addr >> 24), // Register address byte 3 + (uint8_t)(addr >> 16), // Register address byte 2 + (uint8_t)(addr >> 8), // Register address byte 1 + (uint8_t)(addr >> 0), // Register address byte 0 }; status = i2c_start((self->addr << 1) | I2C_WRITE, I2C_TIMEOUT); @@ -195,11 +211,13 @@ i2c_status_t usb7206_write_reg(struct USB7206* self, uint32_t addr, uint8_t* dat // Write 8-bit value to USB7206 register region. // Returns number of bytes written on success or a negative number on error. -i2c_status_t usb7206_write_reg_8(struct USB7206* self, uint32_t addr, uint8_t data) { return usb7206_write_reg(self, addr, &data, sizeof(data)); } +i2c_status_t usb7206_write_reg_8(struct USB7206 *self, uint32_t addr, uint8_t data) { + return usb7206_write_reg(self, addr, &data, sizeof(data)); +} // Write 32-bit value to USB7206 register region. // Returns number of bytes written on success or a negative number on error. -i2c_status_t usb7206_write_reg_32(struct USB7206* self, uint32_t addr, uint32_t data) { +i2c_status_t usb7206_write_reg_32(struct USB7206 *self, uint32_t addr, uint32_t data) { // Convert to little endian uint8_t bytes[4] = { (uint8_t)(data >> 0), @@ -213,52 +231,66 @@ i2c_status_t usb7206_write_reg_32(struct USB7206* self, uint32_t addr, uint32_t // Initialize USB7206. // Returns zero on success or a negative number on error. -int usb7206_init(struct USB7206* self) { +i2c_status_t usb7206_init(struct USB7206 *self) { i2c_status_t status; - uint32_t data; + uint32_t data; - // DM and DP are swapped on ports 2 and 3 - status = usb7206_write_reg_8(self, REG_PRT_SWAP, 0x0C); + // DM and DP are swapped on ports 2 (AR) and 3 (AL) + // [5:0] PRT_SWAP => Swaps the upstream and downstream USB DP and DM pins for ease of board routing to devices and connectors: + // - '0' = USB D+ functionality is associated with the DP pin, and D– functionality is associated with the DM pin (default). + // - '1' = USB D+ functionality is associated with the DM pin, and D– functionality is associated with the DP pin. + status = usb7206_write_reg_8(self, USB7206_HUB_PRT_SWAP, 0x0C); if (status < 0) { return status; } // Disable audio - status = usb7206_write_reg_8(self, REG_I2S_FEAT_SEL, 0); + // [7:0] I2S_UNIT_SEL => Control features of the I2S interface if an I2S configuration is selected: + // - 0x00 = I2S is disabled. + // - 0x01 = Audio `IN' through microphone is enabled. + // - 0x02 = Audio `OUT' is enabled. + // - 0x03 = Both audio `IN' are enabled (default). + status = usb7206_write_reg_8(self, USB7206_I2S_FEAT_SEL, 0x00); if (status < 0) { return status; } - // Set HFC_DISABLE - data = 0; - status = usb7206_read_reg_32(self, REG_RUNTIME_FLAGS2, &data); + // Disable Hub Feature Controller (HFC) + // [0] HFC_DISABLE: + // - '0': HFC is enabled (default). + // - '1': HFC is disabled. + data = 0; + status = usb7206_read_reg_32(self, USB7206_RUNTIME_FLAGS2, &data); if (status < 0) { return status; } data |= 1; - status = usb7206_write_reg_32(self, REG_RUNTIME_FLAGS2, data); + status = usb7206_write_reg_32(self, USB7206_RUNTIME_FLAGS2, data); if (status < 0) { return status; } // Set Vendor ID and Product ID of USB 2 hub - status = usb7206_write_reg_32(self, REG_VID, 0x00033384); + data = ((uint32_t)LAUNCH_USB2_HUB_PID << 16) | SYSTEM76_VID; + status = usb7206_write_reg_32(self, USB7206_VID, data); if (status < 0) { return status; } // Set Vendor ID and Product ID of USB 3 hub - status = usb7206_write_reg_32(self, REG_USB3_HUB_VID, 0x00043384); + data = ((uint32_t)LAUNCH_USB3_HUB_PID << 16) | SYSTEM76_VID; + status = usb7206_write_reg_32(self, USB7206_USB3_HUB_VID, data); if (status < 0) { return status; } - return 0; + return I2C_STATUS_SUCCESS; } -// Attach USB7206. -// Returns bytes written on success or a negative number on error. -i2c_status_t usb7206_attach(struct USB7206* self) { +// Attach USB7206 (exit `SOC_CONFIG' and enter `HUB_CONFIG' stage). +// The USB attach opcode is `0xAA55'. +// Returns zero on success or a negative number on error. +i2c_status_t usb7206_attach(struct USB7206 *self) { uint8_t data[3] = { 0xAA, 0x56, @@ -269,22 +301,26 @@ i2c_status_t usb7206_attach(struct USB7206* self) { } struct USB7206_GPIO { - struct USB7206* usb7206; - uint32_t pf; + struct USB7206 *usb7206; + uint32_t pf; }; -struct USB7206_GPIO usb_gpio_sink = {.usb7206 = &usb_hub, .pf = 29}; // UP_SEL = PF29 = GPIO93 -struct USB7206_GPIO usb_gpio_source_left = {.usb7206 = &usb_hub, .pf = 10}; // CL_SEL = PF10 = GPIO74 -struct USB7206_GPIO usb_gpio_source_right = {.usb7206 = &usb_hub, .pf = 25}; // CR_SEL = PF25 = GPIO88 +struct USB7206_GPIO usb_gpio_sink = {.usb7206 = &usb_hub, .pf = 29}; // UP_SEL = PF29 = GPIO93 (93 = 64 + 29) +struct USB7206_GPIO usb_gpio_source_left = {.usb7206 = &usb_hub, .pf = 10}; // CL_SEL = PF10 = GPIO74 (74 = 64 + 10) +struct USB7206_GPIO usb_gpio_source_right = {.usb7206 = &usb_hub, .pf = 25}; // CR_SEL = PF25 = GPIO89 (89 = 64 + 25) // Set USB7206 GPIO to specified value. // Returns zero on success or negative number on error. -i2c_status_t usb7206_gpio_set(struct USB7206_GPIO* self, bool value) { +i2c_status_t usb7206_gpio_set(struct USB7206_GPIO *self, bool value) { i2c_status_t status; - uint32_t data; - - data = 0; - status = usb7206_read_reg_32(self->usb7206, REG_PIO64_OUT, &data); + uint32_t data; + + // Set GPIO output value + // PIO[96:64] OUTPUT REGISTER => PIO96_OUT[x]: + // - '0' = Output is `0'. + // - '1' = Output is `1'. + data = 0; + status = usb7206_read_reg_32(self->usb7206, USB7206_PIO96_OUT, &data); if (status < 0) { return status; } @@ -294,22 +330,22 @@ i2c_status_t usb7206_gpio_set(struct USB7206_GPIO* self, bool value) { } else { data &= ~(((uint32_t)1) << self->pf); } - status = usb7206_write_reg_32(self->usb7206, REG_PIO64_OUT, data); + status = usb7206_write_reg_32(self->usb7206, USB7206_PIO96_OUT, data); if (status < 0) { return status; } - return 0; + return I2C_STATUS_SUCCESS; } // Initialize USB7206 GPIO. // Returns zero on success or a negative number on error. -i2c_status_t usb7206_gpio_init(struct USB7206_GPIO* self) { +i2c_status_t usb7206_gpio_init(struct USB7206_GPIO *self) { i2c_status_t status; - uint32_t data; + uint32_t data; // Set programmable function to GPIO - status = usb7206_write_reg_8(self->usb7206, REG_PF1_CTL + (self->pf - 1), 0); + status = usb7206_write_reg_8(self->usb7206, USB7206_PF1_CTL + (self->pf - 1), 0x00); if (status < 0) { return status; } @@ -318,83 +354,130 @@ i2c_status_t usb7206_gpio_init(struct USB7206_GPIO* self) { usb7206_gpio_set(self, false); // Set GPIO to output - data = 0; - status = usb7206_read_reg_32(self->usb7206, REG_PIO64_OEN, &data); + // PIO[96:64] OUTPUT ENABLE REGISTER => PIO96_OEN[x]: + // - '0' = Disabled. + // - '1' = Enabled. + data = 0; + status = usb7206_read_reg_32(self->usb7206, USB7206_PIO96_OEN, &data); if (status < 0) { return status; } data |= (((uint32_t)1) << self->pf); - status = usb7206_write_reg_32(self->usb7206, REG_PIO64_OEN, data); + status = usb7206_write_reg_32(self->usb7206, USB7206_PIO96_OEN, data); if (status < 0) { return status; } - return 0; + return I2C_STATUS_SUCCESS; } +// PTN5110N is a 1-port Type-C Port controller (TCPC) supporting TCPC Rev 1.0 version 1.1. +#define PTN5110_ROLE_CTRL 0x1A +#define PTN5110_ROLE_CTRL_RP_VAL_SHIFT 4 +#define PTN5110_ROLE_CTRL_RP_VAL_DEF 0x0 +#define PTN5110_ROLE_CTRL_CC2_SHIFT 2 +#define PTN5110_ROLE_CTRL_CC1_SHIFT 0 +#define PTN5110_ROLE_CTRL_CC_RP 0x1 +#define PTN5110_CC_STATUS 0x1D +#define PTN5110_CC_STATUS_CC2_SHIFT 2 +#define PTN5110_CC_STATUS_CC2_MASK 0x3 +#define PTN5110_CC_STATUS_CC1_SHIFT 0 +#define PTN5110_CC_STATUS_CC1_MASK 0x3 +#define PTN5110_CC_STATE_SNK_OPEN 0 +#define PTN5110_CC_STATE_SRC_RD 2 +#define PTN5110_COMMAND 0x23 +#define PTN5110_CMD_SRC_VBUS_DEFAULT 0x77 // 0b01110111 +#define PTN5110_CMD_DISABLE_SRC_VBUS 0x66 // 0b01100110 + +enum TCPC_TYPE { + TCPC_TYPE_SINK, + TCPC_TYPE_SOURCE, +}; + struct PTN5110 { - uint8_t addr; - uint8_t cc; - struct USB7206_GPIO* gpio; + enum TCPC_TYPE type; + uint8_t addr; + uint8_t cc; + struct USB7206_GPIO *gpio; }; -struct PTN5110 usb_sink = {.addr = 0x51, .gpio = &usb_gpio_sink}; -struct PTN5110 usb_source_left = {.addr = 0x52, .gpio = &usb_gpio_source_left}; -struct PTN5110 usb_source_right = {.addr = 0x50, .gpio = &usb_gpio_source_right}; +// USB C upstream port controller (PTN5110DHQ) +// - Configured for Upstream Facing Port (UFP)/Sink role at Power On or Reset (POR). +// - The CC1/2 pins present sink (Rd) role. +// - I2C address: 0xA2 (0b1010001x) = 0x51 << 1 +// USB C left port controller (PTN5110THQ) +// - Configured for Downstream Facing Port (DFP)/Source role at Power On or Reset (POR). +// - I2C address: 0xA4 (0b1010010x) = 0x52 << 1 +// USB C right port controller (PTN5110THQ) +// - Configured for Downstream Facing Port (DFP)/Source role at Power On or Reset (POR). +// - I2C address: 0xA0 (0b1010000x) = 0x50 << 1 +struct PTN5110 usb_sink = {.type = TCPC_TYPE_SINK, .addr = 0x51, .gpio = &usb_gpio_sink}; +struct PTN5110 usb_source_left = {.type = TCPC_TYPE_SOURCE, .addr = 0x52, .gpio = &usb_gpio_source_left}; +struct PTN5110 usb_source_right = {.type = TCPC_TYPE_SOURCE, .addr = 0x50, .gpio = &usb_gpio_source_right}; -// Initialize PTN5110. +// Read PTN5110 CC_STATUS. // Returns zero on success or a negative number on error. -i2c_status_t ptn5110_init(struct PTN5110* self) { - // Set last cc to invalid value, to force update - self->cc = 0xFF; - // Initialize GPIO - return usb7206_gpio_init(self->gpio); +i2c_status_t ptn5110_get_cc_status(struct PTN5110 *self, uint8_t *cc) { + return i2c_readReg(self->addr << 1, PTN5110_CC_STATUS, cc, 1, I2C_TIMEOUT); } -// Read PTN5110 CC_STATUS. +// Write PTN5110 ROLE_CONTROL. // Returns zero on success or a negative number on error. -i2c_status_t ptn5110_get_cc_status(struct PTN5110* self, uint8_t* cc) { return i2c_readReg(self->addr << 1, 0x1D, cc, 1, I2C_TIMEOUT); } +int ptn5110_set_role_control(struct PTN5110 *self, uint8_t role_control) { + return i2c_writeReg(self->addr << 1, PTN5110_ROLE_CTRL, &role_control, 1, I2C_TIMEOUT); +} // Set PTN5110 SSMUX orientation. // Returns zero on success or a negative number on error. -i2c_status_t ptn5110_set_ssmux(struct PTN5110* self, bool orientation) { return usb7206_gpio_set(self->gpio, orientation); } +i2c_status_t ptn5110_set_ssmux(struct PTN5110 *self, bool orientation) { + return usb7206_gpio_set(self->gpio, orientation); +} // Write PTN5110 COMMAND. // Returns zero on success or negative number on error. -i2c_status_t ptn5110_command(struct PTN5110* self, uint8_t command) { return i2c_writeReg(self->addr << 1, 0x23, &command, 1, I2C_TIMEOUT); } +i2c_status_t ptn5110_command(struct PTN5110 *self, uint8_t command) { + return i2c_writeReg(self->addr << 1, PTN5110_COMMAND, &command, 1, I2C_TIMEOUT); +} // Set orientation of PTN5110 operating as a sink, call this once. // Returns zero on success or a negative number on error. -i2c_status_t ptn5110_sink_set_orientation(struct PTN5110* self) { +i2c_status_t ptn5110_sink_set_orientation(struct PTN5110 *self) { i2c_status_t status; - uint8_t cc; + uint8_t cc; status = ptn5110_get_cc_status(self, &cc); if (status < 0) { return status; } - if ((cc & 0x03) == 0) { + // PTN5110N in UFP and therefore ROLE_CONTROL.CC1 = Rd + if (((cc >> PTN5110_CC_STATUS_CC1_SHIFT) & PTN5110_CC_STATUS_CC1_MASK) == PTN5110_CC_STATE_SNK_OPEN) { + // CC_STATUS[1:0] CC1 State: + // - 0b00 = SNK_Open (Below maximum vRa) status = ptn5110_set_ssmux(self, false); if (status < 0) { return status; } } else { + // CC_STATUS[1:0] CC1 State: + // - 0b01 = SNK_Default (Above minimum vRd-Connect) + // - 0b10 = SNK_Power1_5 (Above minimum vRd-Connect) Detects Rp-1.5A + // - 0b11 = SNK_Power3_0 (Above minimum vRd-Connect) Detects Rp-3.0A status = ptn5110_set_ssmux(self, true); if (status < 0) { return status; } } - return 0; + return I2C_STATUS_SUCCESS; } // Update PTN5110 operating as a source, call this repeatedly. // Returns zero on success or a negative number on error. -i2c_status_t ptn5110_source_update(struct PTN5110* self) { +i2c_status_t ptn5110_source_update(struct PTN5110 *self) { i2c_status_t status; - uint8_t cc; + uint8_t cc; status = ptn5110_get_cc_status(self, &cc); if (status < 0) { @@ -402,45 +485,90 @@ i2c_status_t ptn5110_source_update(struct PTN5110* self) { } if (cc != self->cc) { - // WARNING: Setting this here will disable retries - self->cc = cc; + self->cc = cc; // WARNING: Setting this here will disable retries - bool connected = false; + bool connected = false; bool orientation = false; - if ((cc & 0x03) == 2) { - connected = true; + + // PTN5110N in DFP and therefore ROLE_CONTROL.CC1 = Rp and ROLE_CONTROL.CC2 = Rp + if (((cc >> PTN5110_CC_STATUS_CC1_SHIFT) & PTN5110_CC_STATUS_CC1_MASK) == PTN5110_CC_STATE_SRC_RD) { + // CC_STATUS[1:0] CC1 State: + // - 0b10 = SRC_Rd (within the vRd range) + connected = true; orientation = true; - } else if (((cc >> 2) & 0x03) == 2) { - connected = true; + } else if (((cc >> PTN5110_CC_STATUS_CC2_SHIFT) & PTN5110_CC_STATUS_CC2_MASK) == PTN5110_CC_STATE_SRC_RD) { + // CC_STATUS[1:0] CC2 State: + // - 0b10 = SRC_Rd (within the vRd range) + connected = true; orientation = false; } if (connected) { - // Set SS mux orientation + // Set SS multiplexer orientation status = ptn5110_set_ssmux(self, orientation); if (status < 0) { return status; } // Enable source Vbus command - status = ptn5110_command(self, 0b01110111); + // - 0b01110111: SourceVbusDefaultVoltage => Enable sourcing vSafe5V over Vbus and enable Vbus present detection. + status = ptn5110_command(self, PTN5110_CMD_SRC_VBUS_DEFAULT); if (status < 0) { return status; } } else { // Disable source Vbus command - status = ptn5110_command(self, 0b01100110); + // - 0b01100110: DisableSourceVbus => Disable sourcing power over Vbus. + status = ptn5110_command(self, PTN5110_CMD_DISABLE_SRC_VBUS); if (status < 0) { return status; } } } - return 0; + return I2C_STATUS_SUCCESS; +} + +// Initialize PTN5110. +// Returns zero on success or a negative number on error. +i2c_status_t ptn5110_init(struct PTN5110 *self) { + i2c_status_t status; + uint8_t reg; + + self->cc = 0xFF; // Set last cc to invalid value, to force update + + // Initialize GPIO + status = usb7206_gpio_init(self->gpio); + if (status < 0) { + return status; + } + + switch (self->type) { + case TCPC_TYPE_SINK: + // UFP Initialization + status = ptn5110_sink_set_orientation(self); + break; + case TCPC_TYPE_SOURCE: + // DFP Initialization + // [6] DRP: 0b0 = No DRP. + // [5:4] Rp Value: 0b00 = Rp default. + // [3:2] CC2: 0b01 = Rp definition from [5:4]. + // [1:0] CC1: 0b01 = Rp definition from [5:4]. + reg = (PTN5110_ROLE_CTRL_RP_VAL_DEF << PTN5110_ROLE_CTRL_RP_VAL_SHIFT) | + (PTN5110_ROLE_CTRL_CC_RP << PTN5110_ROLE_CTRL_CC2_SHIFT) | + (PTN5110_ROLE_CTRL_CC_RP << PTN5110_ROLE_CTRL_CC1_SHIFT); // 0x05 + status = ptn5110_set_role_control(self, reg); + break; + } + + return (status < 0) ? status : I2C_STATUS_SUCCESS; } +// The interrupt pin is not wired due to lack of pins on the AVR. +// The TCPCs will need to be periodically polled. void usb_mux_event(void) { - // Run this on every 1000th matrix scan + // `tVbusOFF' in the USB C spec is 650 ms which sets the maximum + // polling interval so run every 1000th matrix scan static int cycle = 0; if (cycle >= 1000) { cycle = 0; @@ -456,13 +584,15 @@ void usb_mux_init(void) { i2c_init(); // Set up hub + // I2C pullups are present on the board, so the hub will wait in `SOC_CFG' + // (allowing for external configuration) until it receives the "Attach" command + // and becomes active usb7206_init(&usb_hub); - // Set up sink + // Set up sink and the upstream SS multiplexer first ptn5110_init(&usb_sink); - ptn5110_sink_set_orientation(&usb_sink); - // Set up sources + // Set up sources and the downstream SS multiplexers ptn5110_init(&usb_source_left); ptn5110_init(&usb_source_right); diff --git a/keyboards/system76/launch_1/usb_mux.h b/keyboards/system76/launch_1/usb_mux.h index 26f84de864b6..28df955fa6cd 100644 --- a/keyboards/system76/launch_1/usb_mux.h +++ b/keyboards/system76/launch_1/usb_mux.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 System76 + * Copyright (C) 2021-2022 System76 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/keyboards/system76/layouts.sh b/keyboards/system76/layouts.sh index 1c9118562cd4..7616e74562cb 100755 --- a/keyboards/system76/layouts.sh +++ b/keyboards/system76/layouts.sh @@ -2,7 +2,7 @@ # # This script produces layout data for the System76 Keyboard Configurator. # -# Copyright (C) 2021 System76 +# Copyright (C) 2021-2022 System76 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/keyboards/system76/system76_ec.c b/keyboards/system76/system76_ec.c index 63016590723f..f80a1945b807 100644 --- a/keyboards/system76/system76_ec.c +++ b/keyboards/system76/system76_ec.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2021 System76 - * Copyright (C) 2021 Jimmy Cassis + * Copyright (C) 2021-2022 System76 + * Copyright (C) 2021-2022 Jimmy Cassis * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,35 +16,33 @@ * along with this program. If not, see . */ +#include "system76_ec.h" + #include -#include "dynamic_keymap.h" +#include "quantum.h" +#ifdef SYSTEM76_EC #include "raw_hid.h" -#include "rgb_matrix.h" #include "version.h" enum Command { - CMD_PROBE = 1, // Probe for System76 EC protocol - CMD_BOARD = 2, // Read board string - CMD_VERSION = 3, // Read version string - CMD_RESET = 6, // Reset to bootloader - CMD_KEYMAP_GET = 9, // Get keyboard map index - CMD_KEYMAP_SET = 10, // Set keyboard map index - CMD_LED_GET_VALUE = 11, // Get LED value by index - CMD_LED_SET_VALUE = 12, // Set LED value by index - CMD_LED_GET_COLOR = 13, // Get LED color by index - CMD_LED_SET_COLOR = 14, // Set LED color by index - CMD_LED_GET_MODE = 15, // Get LED matrix mode and speed - CMD_LED_SET_MODE = 16, // Set LED matrix mode and speed - CMD_MATRIX_GET = 17, // Get currently pressed keys - CMD_LED_SAVE = 18, // Save LED settings to ROM - CMD_SET_NO_INPUT = 19, // Enable/disable no input mode + CMD_PROBE = 1, // Probe for System76 EC protocol + CMD_BOARD = 2, // Read board string + CMD_VERSION = 3, // Read version string + CMD_RESET = 6, // Reset to bootloader + CMD_KEYMAP_GET = 9, // Get keyboard map index + CMD_KEYMAP_SET = 10, // Set keyboard map index + CMD_LED_GET_VALUE = 11, // Get LED value by index + CMD_LED_SET_VALUE = 12, // Set LED value by index + CMD_LED_GET_COLOR = 13, // Get LED color by index + CMD_LED_SET_COLOR = 14, // Set LED color by index + CMD_LED_GET_MODE = 15, // Get LED matrix mode and speed + CMD_LED_SET_MODE = 16, // Set LED matrix mode and speed + CMD_MATRIX_GET = 17, // Get currently pressed keys + CMD_LED_SAVE = 18, // Save LED settings to ROM + CMD_SET_NO_INPUT = 19, // Enable/disable no input mode }; -bool input_disabled = false; - -#define CMD_LED_INDEX_ALL 0xFF - static bool keymap_get(uint8_t layer, uint8_t output, uint8_t input, uint16_t *value) { if (layer < dynamic_keymap_get_layer_count()) { if (output < MATRIX_ROWS) { @@ -69,25 +67,30 @@ static bool keymap_set(uint8_t layer, uint8_t output, uint8_t input, uint16_t va return false; } -static bool bootloader_reset = false; -static bool bootloader_unlocked = false; +bool input_disabled = false; +static bool bootloader_reset, bootloader_unlocked = false; void system76_ec_unlock(void) { #ifdef RGB_MATRIX_CUSTOM_KB rgb_matrix_mode_noeeprom(RGB_MATRIX_CUSTOM_unlocked); #endif -#ifdef SYSTEM76_EC bootloader_unlocked = true; -#endif } -bool system76_ec_is_unlocked(void) { return bootloader_unlocked; } +bool system76_ec_is_unlocked(void) { + return bootloader_unlocked; +} +#else // !SYSTEM76_EC +bool system76_ec_is_unlocked(void) { + return false; +} +#endif // SYSTEM76_EC #ifdef RGB_MATRIX_CUSTOM_KB enum Mode { MODE_SOLID_COLOR = 0, MODE_PER_KEY, - #ifndef DISABLE_RGB_MATRIX_ANIMATIONS +#ifndef DISABLE_RGB_MATRIX_ANIMATIONS MODE_CYCLE_ALL, MODE_CYCLE_LEFT_RIGHT, MODE_CYCLE_UP_DOWN, @@ -99,7 +102,7 @@ enum Mode { MODE_RAINDROPS, MODE_SPLASH, MODE_MULTISPLASH, - #endif // DISABLE_RGB_MATRIX_ANIMATIONS +#endif // DISABLE_RGB_MATRIX_ANIMATIONS MODE_ACTIVE_KEYS, MODE_DISABLED, MODE_LAST, @@ -109,7 +112,7 @@ enum Mode { static enum rgb_matrix_effects mode_map[] = { RGB_MATRIX_SOLID_COLOR, RGB_MATRIX_CUSTOM_raw_rgb, - #ifndef DISABLE_RGB_MATRIX_ANIMATIONS +#ifndef DISABLE_RGB_MATRIX_ANIMATIONS RGB_MATRIX_CYCLE_ALL, RGB_MATRIX_CYCLE_LEFT_RIGHT, RGB_MATRIX_CYCLE_UP_DOWN, @@ -121,7 +124,7 @@ static enum rgb_matrix_effects mode_map[] = { RGB_MATRIX_RAINDROPS, RGB_MATRIX_SPLASH, RGB_MATRIX_MULTISPLASH, - #endif // DISABLE_RGB_MATRIX_ANIMATIONS +#endif // DISABLE_RGB_MATRIX_ANIMATIONS RGB_MATRIX_CUSTOM_active_keys, RGB_MATRIX_NONE, }; @@ -145,6 +148,7 @@ rgb_config_t layer_rgb[DYNAMIC_KEYMAP_LAYER_COUNT] = { .speed = RGB_MATRIX_DEFAULT_SPD, .flags = LED_FLAG_KEYLIGHT, }, +#if DYNAMIC_KEYMAP_LAYER_COUNT > 1 // Layer 1 { .enable = 1, @@ -157,30 +161,27 @@ rgb_config_t layer_rgb[DYNAMIC_KEYMAP_LAYER_COUNT] = { .speed = RGB_MATRIX_DEFAULT_SPD, .flags = LED_FLAG_KEYLIGHT, }, +#endif +#if DYNAMIC_KEYMAP_LAYER_COUNT > 2 // Layer 2 { .enable = 1, .mode = RGB_MATRIX_CUSTOM_active_keys, - .hsv = { - .h = RGB_MATRIX_DEFAULT_HUE, - .s = RGB_MATRIX_DEFAULT_SAT, - .v = RGB_MATRIX_DEFAULT_VAL, - }, + .hsv = (HSV){RGB_MATRIX_DEFAULT_HUE, RGB_MATRIX_DEFAULT_SAT, RGB_MATRIX_DEFAULT_VAL}, .speed = RGB_MATRIX_DEFAULT_SPD, .flags = LED_FLAG_KEYLIGHT, }, +#endif +#if DYNAMIC_KEYMAP_LAYER_COUNT > 3 // Layer 3 { .enable = 1, .mode = RGB_MATRIX_CUSTOM_active_keys, - .hsv = { - .h = RGB_MATRIX_DEFAULT_HUE, - .s = RGB_MATRIX_DEFAULT_SAT, - .v = RGB_MATRIX_DEFAULT_VAL, - }, + .hsv = (HSV){RGB_MATRIX_DEFAULT_HUE, RGB_MATRIX_DEFAULT_SAT, RGB_MATRIX_DEFAULT_VAL}, .speed = RGB_MATRIX_DEFAULT_SPD, .flags = LED_FLAG_KEYLIGHT, }, +#endif }; // clang-format on @@ -209,19 +210,19 @@ void system76_ec_rgb_eeprom(bool write) { } // Update RGB parameters on layer change. -void system76_ec_rgb_layer(layer_state_t layer_state) { - if (!bootloader_unlocked) { - uint8_t layer = get_highest_layer(layer_state); +void system76_ec_rgb_layer(layer_state_t state) { + if (!system76_ec_is_unlocked()) { + uint8_t layer = get_highest_layer(state); if (layer < DYNAMIC_KEYMAP_LAYER_COUNT) { rgb_matrix_config = layer_rgb[layer]; } } } -#endif // RGB_MATRIX_CUSTOM_KB +#endif // RGB_MATRIX_CUSTOM_KB +#ifdef SYSTEM76_EC void raw_hid_receive(uint8_t *data, uint8_t length) { - // Error response by default, set to success by commands - data[1] = 1; + data[1] = 1; // Set "error" response by default; changed to "success" by commands switch (data[0]) { case CMD_PROBE: @@ -374,7 +375,7 @@ void raw_hid_receive(uint8_t *data, uint8_t length) { data[1] = 0; } break; -#endif // RGB_MATRIX_CUSTOM_KB +#endif // RGB_MATRIX_CUSTOM_KB case CMD_MATRIX_GET: { // TODO: Improve performance? data[2] = matrix_rows(); @@ -414,7 +415,9 @@ void raw_hid_receive(uint8_t *data, uint8_t length) { if (bootloader_reset) { // Give host time to read response wait_ms(100); + // Jump to the bootloader - bootloader_jump(); + reset_keyboard(); } } +#endif // SYSTEM76_EC diff --git a/keyboards/system76/system76_ec.h b/keyboards/system76/system76_ec.h new file mode 100644 index 000000000000..7b8bca485291 --- /dev/null +++ b/keyboards/system76/system76_ec.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2022 Jimmy Cassis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "action_layer.h" + +void system76_ec_rgb_eeprom(bool write); +void system76_ec_rgb_layer(layer_state_t state); +#ifdef SYSTEM76_EC +void system76_ec_unlock(void); +#endif +bool system76_ec_is_unlocked(void);