[Keyboard] Update ZSA Moonlander (#23911)

This commit is contained in:
Drashna Jaelre 2024-08-18 17:13:38 -07:00 committed by GitHub
parent 48d3edd66f
commit e9cb9f42a5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 365 additions and 331 deletions

View file

@ -18,60 +18,15 @@
#pragma once
#define WEBUSB_LANDING_PAGE_URL u8"configure.ergodox-ez.com"
/* key matrix size */
#define MATRIX_ROWS 12
#define MATRIX_COLS 7
/* PCB default pin-out */
// #define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 }
// #define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 }
// #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 }
// #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 }
// #define MCP23_LED_R GPB7
// #define MCP23_LED_G GPB6
// #define MCP23_LED_B GPA7
#define EEPROM_I2C_24LC128
// Not needed, is default address:
// #define EXTERNAL_EEPROM_I2C_BASE_ADDRESS 0b10100000
/* COL2ROW or ROW2COL */
#define DIODE_DIRECTION ROW2COL
/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/
/* disable debug print */
//#define NO_DEBUG
/* disable print */
//#define NO_PRINT
/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
#define IS31FL3731_I2C_ADDRESS_1 IS31FL3731_I2C_ADDRESS_GND
#define IS31FL3731_I2C_ADDRESS_2 IS31FL3731_I2C_ADDRESS_VCC
#define MOUSEKEY_INTERVAL 20
#define MOUSEKEY_DELAY 0
#define MOUSEKEY_TIME_TO_MAX 60
#define MOUSEKEY_MAX_SPEED 7
#define MOUSEKEY_WHEEL_DELAY 400
#define MOUSEKEY_WHEEL_INTERVAL MOUSEKEY_INTERVAL
#define MOUSEKEY_WHEEL_MAX_SPEED MOUSEKEY_MAX_SPEED
#define MOUSEKEY_WHEEL_TIME_TO_MAX MOUSEKEY_TIME_TO_MAX
#define MUSIC_MAP
#define FIRMWARE_VERSION_SIZE 17

View file

@ -16,6 +16,7 @@
"bootmagic": true,
"command": true,
"console": true,
"deferred_exec": true,
"extrakey": true,
"mousekey": true,
"nkro": true,
@ -37,6 +38,13 @@
"eeprom": {
"driver": "i2c"
},
"mousekey": {
"delay": 0,
"interval": 20,
"max_speed": 7,
"time_to_max": 60,
"wheel_delay": 400
},
"rgb_matrix": {
"animations": {
"alphas_mods": true,
@ -85,6 +93,82 @@
},
"center_point": [120, 36],
"driver": "is31fl3731",
"layout": [
{"matrix": [0, 0], "x": 0, "y": 4, "flags": 1},
{"matrix": [1, 0], "x": 0, "y": 20, "flags": 1},
{"matrix": [2, 0], "x": 0, "y": 36, "flags": 1},
{"matrix": [3, 0], "x": 0, "y": 52, "flags": 1},
{"matrix": [4, 0], "x": 0, "y": 68, "flags": 1},
{"matrix": [0, 1], "x": 16, "y": 3, "flags": 4},
{"matrix": [1, 1], "x": 16, "y": 19, "flags": 4},
{"matrix": [2, 1], "x": 16, "y": 35, "flags": 4},
{"matrix": [3, 1], "x": 16, "y": 51, "flags": 4},
{"matrix": [4, 1], "x": 16, "y": 67, "flags": 1},
{"matrix": [0, 2], "x": 32, "y": 1, "flags": 4},
{"matrix": [1, 2], "x": 32, "y": 17, "flags": 4},
{"matrix": [2, 2], "x": 32, "y": 33, "flags": 4},
{"matrix": [3, 2], "x": 32, "y": 49, "flags": 4},
{"matrix": [4, 2], "x": 32, "y": 65, "flags": 1},
{"matrix": [0, 3], "x": 48, "y": 0, "flags": 4},
{"matrix": [1, 3], "x": 48, "y": 16, "flags": 4},
{"matrix": [2, 3], "x": 48, "y": 32, "flags": 4},
{"matrix": [3, 3], "x": 48, "y": 48, "flags": 4},
{"matrix": [4, 3], "x": 48, "y": 64, "flags": 1},
{"matrix": [0, 4], "x": 64, "y": 1, "flags": 4},
{"matrix": [1, 4], "x": 64, "y": 17, "flags": 4},
{"matrix": [2, 4], "x": 64, "y": 33, "flags": 4},
{"matrix": [3, 4], "x": 64, "y": 49, "flags": 4},
{"matrix": [4, 4], "x": 64, "y": 65, "flags": 1},
{"matrix": [0, 5], "x": 80, "y": 3, "flags": 4},
{"matrix": [1, 5], "x": 80, "y": 19, "flags": 4},
{"matrix": [2, 5], "x": 80, "y": 35, "flags": 4},
{"matrix": [3, 5], "x": 80, "y": 51, "flags": 4},
{"matrix": [0, 6], "x": 96, "y": 4, "flags": 1},
{"matrix": [1, 6], "x": 96, "y": 20, "flags": 1},
{"matrix": [2, 6], "x": 96, "y": 36, "flags": 1},
{"matrix": [5, 0], "x": 88, "y": 69, "flags": 1},
{"matrix": [5, 1], "x": 100, "y": 80, "flags": 1},
{"matrix": [5, 2], "x": 112, "y": 91, "flags": 1},
{"matrix": [5, 3], "x": 108, "y": 69, "flags": 1},
{"matrix": [6, 6], "x": 240, "y": 4, "flags": 1},
{"matrix": [7, 6], "x": 240, "y": 20, "flags": 1},
{"matrix": [8, 6], "x": 240, "y": 36, "flags": 1},
{"matrix": [9, 6], "x": 240, "y": 52, "flags": 1},
{"matrix": [10, 6], "x": 240, "y": 68, "flags": 1},
{"matrix": [6, 5], "x": 224, "y": 3, "flags": 4},
{"matrix": [7, 5], "x": 224, "y": 19, "flags": 4},
{"matrix": [8, 5], "x": 224, "y": 35, "flags": 4},
{"matrix": [9, 5], "x": 224, "y": 51, "flags": 4},
{"matrix": [10, 5], "x": 224, "y": 67, "flags": 1},
{"matrix": [6, 4], "x": 208, "y": 1, "flags": 4},
{"matrix": [7, 4], "x": 208, "y": 17, "flags": 4},
{"matrix": [8, 4], "x": 208, "y": 33, "flags": 4},
{"matrix": [9, 4], "x": 208, "y": 49, "flags": 4},
{"matrix": [10, 4], "x": 208, "y": 65, "flags": 1},
{"matrix": [6, 3], "x": 192, "y": 0, "flags": 4},
{"matrix": [7, 3], "x": 192, "y": 16, "flags": 4},
{"matrix": [8, 3], "x": 192, "y": 32, "flags": 4},
{"matrix": [9, 3], "x": 192, "y": 48, "flags": 4},
{"matrix": [10, 3], "x": 192, "y": 64, "flags": 1},
{"matrix": [6, 2], "x": 176, "y": 1, "flags": 4},
{"matrix": [7, 2], "x": 176, "y": 17, "flags": 4},
{"matrix": [8, 2], "x": 176, "y": 33, "flags": 4},
{"matrix": [9, 2], "x": 176, "y": 49, "flags": 4},
{"matrix": [10, 2], "x": 176, "y": 65, "flags": 1},
{"matrix": [6, 1], "x": 160, "y": 3, "flags": 4},
{"matrix": [7, 1], "x": 160, "y": 19, "flags": 4},
{"matrix": [8, 1], "x": 160, "y": 35, "flags": 4},
{"matrix": [9, 1], "x": 160, "y": 51, "flags": 4},
{"matrix": [6, 0], "x": 144, "y": 4, "flags": 1},
{"matrix": [7, 0], "x": 144, "y": 20, "flags": 1},
{"matrix": [8, 0], "x": 144, "y": 36, "flags": 1},
{"matrix": [11, 6], "x": 152, "y": 69, "flags": 1},
{"matrix": [11, 5], "x": 140, "y": 80, "flags": 1},
{"matrix": [11, 4], "x": 128, "y": 91, "flags": 1},
{"matrix": [11, 3], "x": 132, "y": 69, "flags": 1}
],
"led_flush_limit": 26,
"led_process_limit": 5,
"max_brightness": 175,
"sleep": true
},

View file

@ -0,0 +1,85 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* STM32F303xB memory setup.
*/
MEMORY
{
flash0 (rx) : org = 0x08000000, len = 128k
flash1 (rx) : org = 0x00000000, len = 0
flash2 (rx) : org = 0x00000000, len = 0
flash3 (rx) : org = 0x00000000, len = 0
flash4 (rx) : org = 0x00000000, len = 0
flash5 (rx) : org = 0x00000000, len = 0
flash6 (rx) : org = 0x00000000, len = 0
flash7 (rx) : org = 0x00000000, len = 0
ram0 (wx) : org = 0x20000000, len = 32k
ram1 (wx) : org = 0x00000000, len = 0
ram2 (wx) : org = 0x00000000, len = 0
ram3 (wx) : org = 0x00000000, len = 0
ram4 (wx) : org = 0x10000000, len = 8k
ram5 (wx) : org = 0x00000000, len = 0
ram6 (wx) : org = 0x00000000, len = 0
ram7 (wx) : org = 0x00000000, len = 0
}
/* For each data/text section two region are defined, a virtual region
and a load region (_LMA suffix).*/
/* Flash region to be used for exception vectors.*/
REGION_ALIAS("VECTORS_FLASH", flash0);
REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
/* Flash region to be used for constructors and destructors.*/
REGION_ALIAS("XTORS_FLASH", flash0);
REGION_ALIAS("XTORS_FLASH_LMA", flash0);
/* Flash region to be used for code text.*/
REGION_ALIAS("TEXT_FLASH", flash0);
REGION_ALIAS("TEXT_FLASH_LMA", flash0);
/* Flash region to be used for read only data.*/
REGION_ALIAS("RODATA_FLASH", flash0);
REGION_ALIAS("RODATA_FLASH_LMA", flash0);
/* Flash region to be used for various.*/
REGION_ALIAS("VARIOUS_FLASH", flash0);
REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
/* Flash region to be used for RAM(n) initialization data.*/
REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
/* RAM region to be used for Main stack. This stack accommodates the processing
of all exceptions and interrupts.*/
REGION_ALIAS("MAIN_STACK_RAM", ram0);
/* RAM region to be used for the process stack. This is the stack used by
the main() function.*/
REGION_ALIAS("PROCESS_STACK_RAM", ram0);
/* RAM region to be used for data segment.*/
REGION_ALIAS("DATA_RAM", ram0);
REGION_ALIAS("DATA_RAM_LMA", flash0);
/* RAM region to be used for BSS segment.*/
REGION_ALIAS("BSS_RAM", ram0);
/* RAM region to be used for the default heap.*/
REGION_ALIAS("HEAP_RAM", ram0);
/* Generic rules inclusion.*/
INCLUDE rules.ld

View file

@ -14,62 +14,39 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "moonlander.h"
#include "i2c_master.h"
#include "mcp23018.h"
#pragma GCC push_options
#pragma GCC optimize("-O3")
/*
#define MATRIX_ROW_PINS { B10, B11, B12, B13, B14, B15 } outputs
#define MATRIX_COL_PINS { A0, A1, A2, A3, A6, A7, B0 } inputs
#define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs
#define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs
*/
/* matrix state(1:on, 0:off) */
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
static matrix_row_t raw_matrix_right[MATRIX_COLS];
extern matrix_row_t matrix[MATRIX_ROWS]; // debounced values
extern matrix_row_t raw_matrix[MATRIX_ROWS]; // raw values
static matrix_row_t raw_matrix_right[MATRIX_ROWS];
#define ROWS_PER_HAND (MATRIX_ROWS / 2)
#ifndef MOONLANDER_I2C_TIMEOUT
# define MOONLANDER_I2C_TIMEOUT 100
#endif
#define MCP_ROWS_PER_HAND (MATRIX_ROWS / 2)
extern bool mcp23018_leds[3];
extern bool is_launching;
bool mcp23018_initd = false;
static uint8_t mcp23018_reset_loop;
static uint16_t mcp23018_reset_loop;
uint8_t mcp23018_errors;
uint8_t mcp23018_tx[3];
uint8_t mcp23018_rx[1];
void mcp23018_init(void) {
i2c_init();
// #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs
// #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs
mcp23018_tx[0] = 0x00; // IODIRA
mcp23018_tx[1] = 0b00000000; // A is output
mcp23018_tx[2] = 0b00111111; // B is inputs
if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error hori\n");
} else {
mcp23018_tx[0] = 0x0C; // GPPUA
mcp23018_tx[1] = 0b10000000; // A is not pulled-up
mcp23018_tx[2] = 0b11111111; // B is pulled-up
if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error hori\n");
} else {
mcp23018_initd = is_launching = true;
}
}
bool io_expander_ready(void) {
uint8_t tx;
return mcp23018_read_pins(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTA, &tx);
}
void matrix_init_custom(void) {
dprintf("matrix init\n");
// debug_matrix = true;
// outputs
gpio_set_pin_output(B10);
gpio_set_pin_output(B11);
@ -87,115 +64,116 @@ void matrix_init_custom(void) {
gpio_set_pin_input_low(A7);
gpio_set_pin_input_low(B0);
mcp23018_init();
mcp23018_init(MCP23018_DEFAULT_ADDRESS);
mcp23018_errors += !mcp23018_set_config(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTA, 0b00000000);
mcp23018_errors += !mcp23018_set_config(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTB, 0b00111111);
if (!mcp23018_errors) {
is_launching = true;
}
}
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
bool changed = false;
// Try to re-init right side
if (!mcp23018_initd) {
if (++mcp23018_reset_loop == 0) {
// if (++mcp23018_reset_loop >= 1300) {
// since mcp23018_reset_loop is 8 bit - we'll try to reset once in 255 matrix scans
// this will be approx bit more frequent than once per second
print("trying to reset mcp23018\n");
mcp23018_init();
if (!mcp23018_initd) {
print("right side not responding\n");
} else {
print("right side attached\n");
#ifdef RGB_MATRIX_ENABLE
rgb_matrix_init();
#endif
// Attempt to reset the mcp23018 if it's not initialized
if (mcp23018_errors) {
if (++mcp23018_reset_loop > 0x1FFF) {
if (io_expander_ready()) {
// If we managed to initialize the mcp23018 - we need to reinitialize the matrix / layer state. During an electric discharge the i2c peripherals might be in a weird state. Giving a delay and resetting the MCU allows to recover from this.
wait_ms(200);
mcu_reset();
}
}
}
matrix_row_t data = 0;
// actual matrix
for (uint8_t row = 0; row <= ROWS_PER_HAND; row++) {
for (uint8_t row = 0; row <= MCP_ROWS_PER_HAND; row++) {
// strobe row
switch (row) {
case 0: gpio_write_pin_high(B10); break;
case 1: gpio_write_pin_high(B11); break;
case 2: gpio_write_pin_high(B12); break;
case 3: gpio_write_pin_high(B13); break;
case 4: gpio_write_pin_high(B14); break;
case 5: gpio_write_pin_high(B15); break;
case 6: break; // Left hand has 6 rows
case 0:
gpio_write_pin_high(B10);
break;
case 1:
gpio_write_pin_high(B11);
break;
case 2:
gpio_write_pin_high(B12);
break;
case 3:
gpio_write_pin_high(B13);
break;
case 4:
gpio_write_pin_high(B14);
break;
case 5:
gpio_write_pin_high(B15);
break;
case 6:
break; // Left hand has 6 rows
}
// right side
if (mcp23018_initd) {
// #define MCP23_ROW_PINS { GPB5, GBP4, GBP3, GBP2, GBP1, GBP0 } outputs
// #define MCP23_COL_PINS { GPA0, GBA1, GBA2, GBA3, GBA4, GBA5, GBA6 } inputs
// Selecting the row on the right side of the keyboard.
if (!mcp23018_errors) {
// select row
mcp23018_tx[0] = 0x12; // GPIOA
mcp23018_tx[1] = (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7); // activate row
mcp23018_tx[2] = ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7); // activate row
mcp23018_errors += !mcp23018_set_output_all(MCP23018_DEFAULT_ADDRESS, (0b01111111 & ~(1 << (row))) | ((uint8_t)!mcp23018_leds[2] << 7), ((uint8_t)!mcp23018_leds[1] << 6) | ((uint8_t)!mcp23018_leds[0] << 7));
}
if (MSG_OK != i2c_transmit(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx, 3, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error hori\n");
mcp23018_initd = false;
// Reading the left side of the keyboard.
if (row < MCP_ROWS_PER_HAND) {
// i2c comm incur enough wait time
if (mcp23018_errors) {
// need wait to settle pin state
matrix_io_delay();
}
// read col data
data = ((readPin(A0) << 0) | (readPin(A1) << 1) | (readPin(A2) << 2) | (readPin(A3) << 3) | (readPin(A6) << 4) | (readPin(A7) << 5) | (readPin(B0) << 6));
// unstrobe row
switch (row) {
case 0:
gpio_write_pin_low(B10);
break;
case 1:
gpio_write_pin_low(B11);
break;
case 2:
gpio_write_pin_low(B12);
break;
case 3:
gpio_write_pin_low(B13);
break;
case 4:
gpio_write_pin_low(B14);
break;
case 5:
gpio_write_pin_low(B15);
break;
case 6:
break;
}
// read col
mcp23018_tx[0] = 0x13; // GPIOB
if (MSG_OK != i2c_read_register(MCP23018_DEFAULT_ADDRESS << 1, mcp23018_tx[0], &mcp23018_rx[0], 1, MOONLANDER_I2C_TIMEOUT)) {
dprintf("error vert\n");
mcp23018_initd = false;
if (current_matrix[row] != data) {
current_matrix[row] = data;
changed = true;
}
}
data = ~(mcp23018_rx[0] & 0b00111111);
// data = 0x01;
// Reading the right side of the keyboard.
if (!mcp23018_errors) {
uint8_t rx;
mcp23018_errors += !mcp23018_read_pins(MCP23018_DEFAULT_ADDRESS, mcp23018_PORTB, &rx);
data = ~(rx & 0b00111111);
} else {
data = 0;
}
if (raw_matrix_right[row] != data) {
raw_matrix_right[row] = data;
changed = true;
}
// left side
if (row < ROWS_PER_HAND) {
// i2c comm incur enough wait time
if (!mcp23018_initd) {
// need wait to settle pin state
matrix_io_delay();
}
// read col data
data = (
(gpio_read_pin(A0) << 0 ) |
(gpio_read_pin(A1) << 1 ) |
(gpio_read_pin(A2) << 2 ) |
(gpio_read_pin(A3) << 3 ) |
(gpio_read_pin(A6) << 4 ) |
(gpio_read_pin(A7) << 5 ) |
(gpio_read_pin(B0) << 6 )
);
// unstrobe row
switch (row) {
case 0: gpio_write_pin_low(B10); break;
case 1: gpio_write_pin_low(B11); break;
case 2: gpio_write_pin_low(B12); break;
case 3: gpio_write_pin_low(B13); break;
case 4: gpio_write_pin_low(B14); break;
case 5: gpio_write_pin_low(B15); break;
case 6: break;
}
if (current_matrix[row] != data) {
current_matrix[row] = data;
changed = true;
}
changed = true;
}
}
for (uint8_t row = 0; row < ROWS_PER_HAND; row++) {
for (uint8_t row = 0; row < MCP_ROWS_PER_HAND; row++) {
current_matrix[11 - row] = 0;
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
current_matrix[11 - row] |= ((raw_matrix_right[6 - col] & (1 << row) ? 1 : 0) << col);
@ -222,12 +200,12 @@ void matrix_power_up(void) {
}
// initialize matrix state: all keys off
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
matrix[i] = 0;
}
}
bool is_transport_connected(void) {
return mcp23018_initd;
}
return (bool)(mcp23018_errors == 0);
}
#pragma GCC pop_options

View file

@ -22,10 +22,6 @@
#undef STM32_I2C_USE_I2C1
#define STM32_I2C_USE_I2C1 TRUE
// for future hardwar
#undef STM32_I2C_USE_I2C2
#define STM32_I2C_USE_I2C2 TRUE
// for audio
#undef STM32_DAC_USE_DAC1_CH1
#define STM32_DAC_USE_DAC1_CH1 TRUE
@ -33,7 +29,3 @@
#define STM32_DAC_USE_DAC1_CH2 TRUE
#undef STM32_GPT_USE_TIM6
#define STM32_GPT_USE_TIM6 TRUE
#undef STM32_GPT_USE_TIM7
#define STM32_GPT_USE_TIM7 TRUE
#undef STM32_GPT_USE_TIM8
#define STM32_GPT_USE_TIM8 TRUE

View file

@ -23,87 +23,96 @@ keyboard_config_t keyboard_config;
bool mcp23018_leds[3] = {0, 0, 0};
bool is_launching = false;
#ifdef DYNAMIC_MACRO_ENABLE
static bool is_dynamic_recording = false;
#if defined(DEFERRED_EXEC_ENABLE)
# if defined(DYNAMIC_MACRO_ENABLE)
deferred_token dynamic_macro_token = INVALID_DEFERRED_TOKEN;
static uint32_t dynamic_macro_led(uint32_t trigger_time, void *cb_arg) {
static bool led_state = true;
if (!is_launching) {
led_state = !led_state;
ML_LED_3(led_state);
}
return 100;
}
bool dynamic_macro_record_start_kb(int8_t direction) {
if (!dynamic_macro_record_start_user(direction)) {
return false;
}
is_dynamic_recording = true;
return true;
if (dynamic_macro_token == INVALID_DEFERRED_TOKEN) {
ML_LED_3(true);
dynamic_macro_token = defer_exec(100, dynamic_macro_led, NULL);
}
return true
}
bool dynamic_macro_record_end_kb(int8_t direction) {
if (!dynamic_macro_record_end_user(direction)) {
return false;
}
is_dynamic_recording = false;
ML_LED_3(false);
return false;
if (cancel_deferred_exec(dynamic_macro_token)) {
dynamic_macro_token = INVALID_DEFERRED_TOKEN;
ML_LED_3(false);
}
return false
}
# endif
static uint32_t startup_exec(uint32_t trigger_time, void *cb_arg) {
static uint8_t startup_loop = 0;
switch (startup_loop++) {
case 0:
ML_LED_1(true);
ML_LED_2(false);
ML_LED_3(false);
ML_LED_4(false);
ML_LED_5(false);
ML_LED_6(false);
break;
case 1:
ML_LED_2(true);
break;
case 2:
ML_LED_3(true);
break;
case 3:
ML_LED_4(true);
break;
case 4:
ML_LED_5(true);
break;
case 5:
ML_LED_6(true);
break;
case 6:
ML_LED_1(false);
break;
case 7:
ML_LED_2(false);
break;
case 8:
ML_LED_3(false);
break;
case 9:
ML_LED_4(false);
break;
case 10:
ML_LED_5(false);
break;
case 11:
ML_LED_6(false);
break;
case 12:
is_launching = false;
layer_state_set_kb(layer_state);
return 0;
}
return 250;
}
#endif
void moonlander_led_task(void) {
if (is_launching) {
ML_LED_1(false);
ML_LED_2(false);
ML_LED_3(false);
ML_LED_4(false);
ML_LED_5(false);
ML_LED_6(false);
ML_LED_1(true);
wait_ms(250);
ML_LED_2(true);
wait_ms(250);
ML_LED_3(true);
wait_ms(250);
ML_LED_4(true);
wait_ms(250);
ML_LED_5(true);
wait_ms(250);
ML_LED_6(true);
wait_ms(250);
ML_LED_1(false);
wait_ms(250);
ML_LED_2(false);
wait_ms(250);
ML_LED_3(false);
wait_ms(250);
ML_LED_4(false);
wait_ms(250);
ML_LED_5(false);
wait_ms(250);
ML_LED_6(false);
wait_ms(250);
is_launching = false;
layer_state_set_kb(layer_state);
}
#ifdef DYNAMIC_MACRO_ENABLE
else if (is_dynamic_recording) {
ML_LED_3(true);
wait_ms(100);
ML_LED_3(false);
wait_ms(155);
}
#endif
#if !defined(MOONLANDER_USER_LEDS)
else {
layer_state_set_kb(layer_state);
}
#endif
}
static THD_WORKING_AREA(waLEDThread, 128);
static THD_FUNCTION(LEDThread, arg) {
(void)arg;
chRegSetThreadName("LEDThread");
while (true) {
moonlander_led_task();
}
}
void keyboard_pre_init_kb(void) {
gpio_set_pin_output(B5);
gpio_set_pin_output(B4);
@ -113,13 +122,6 @@ void keyboard_pre_init_kb(void) {
gpio_write_pin_low(B4);
gpio_write_pin_low(B3);
chThdCreateStatic(waLEDThread, sizeof(waLEDThread), NORMALPRIO - 16, LEDThread, NULL);
/* the array is initialized to 0, no need to re-set it here */
// mcp23018_leds[0] = 0; // blue
// mcp23018_leds[1] = 0; // green
// mcp23018_leds[2] = 0; // red
keyboard_pre_init_user();
}
@ -183,13 +185,7 @@ layer_state_t layer_state_set_kb(layer_state_t state) {
#ifdef RGB_MATRIX_ENABLE
// clang-format off
const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
/* Refer to IS31 manual for these locations
* driver
* | R location
* | | G location
* | | | B location
* | | | | */
{0, C3_2, C1_1, C4_2}, // 1
{0, C3_2, C1_1, C4_2},
{0, C2_2, C1_2, C4_3},
{0, C2_3, C1_3, C3_3},
{0, C2_4, C1_4, C3_4},
@ -199,7 +195,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{0, C2_8, C1_8, C3_8},
{0, C3_1, C2_1, C4_1},
{0, C7_8, C6_8, C8_8}, // 10
{0, C7_8, C6_8, C8_8},
{0, C7_7, C6_7, C9_8},
{0, C8_7, C6_6, C9_7},
{0, C8_6, C7_6, C9_6},
@ -209,7 +205,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{0, C8_2, C7_2, C9_2},
{0, C8_1, C7_1, C9_1},
{0, C3_10, C1_9, C4_10}, // 19
{0, C3_10, C1_9, C4_10},
{0, C2_10, C1_10, C4_11},
{0, C2_11, C1_11, C3_11},
{0, C2_12, C1_12, C3_12},
@ -219,7 +215,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{0, C2_16, C1_16, C3_16},
{0, C3_9, C2_9, C4_9},
{0, C7_16, C6_16, C8_16}, // 28
{0, C7_16, C6_16, C8_16},
{0, C7_15, C6_15, C9_16},
{0, C8_15, C6_14, C9_15},
{0, C8_10, C7_10, C9_10},
@ -229,7 +225,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{0, C8_13, C7_13, C9_13},
{0, C8_14, C7_14, C9_14},
{1, C3_2, C1_1, C4_2}, // 1
{1, C3_2, C1_1, C4_2},
{1, C2_2, C1_2, C4_3},
{1, C2_3, C1_3, C3_3},
{1, C2_4, C1_4, C3_4},
@ -239,7 +235,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{1, C2_8, C1_8, C3_8},
{1, C3_1, C2_1, C4_1},
{1, C7_8, C6_8, C8_8}, // 10
{1, C7_8, C6_8, C8_8},
{1, C7_7, C6_7, C9_8},
{1, C8_7, C6_6, C9_7},
{1, C8_6, C7_6, C9_6},
@ -249,7 +245,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{1, C8_2, C7_2, C9_2},
{1, C8_1, C7_1, C9_1},
{1, C3_10, C1_9, C4_10}, // 19
{1, C3_10, C1_9, C4_10},
{1, C2_10, C1_10, C4_11},
{1, C2_11, C1_11, C3_11},
{1, C2_12, C1_12, C3_12},
@ -259,7 +255,7 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{1, C2_16, C1_16, C3_16},
{1, C3_9, C2_9, C4_9},
{1, C7_16, C6_16, C8_16}, // 28
{1, C7_16, C6_16, C8_16},
{1, C7_15, C6_15, C9_16},
{1, C8_15, C6_14, C9_15},
{1, C8_10, C7_10, C9_10},
@ -268,61 +264,8 @@ const is31fl3731_led_t PROGMEM g_is31fl3731_leds[IS31FL3731_LED_COUNT] = {
{1, C8_12, C7_12, C9_12},
{1, C8_13, C7_13, C9_13},
{1, C8_14, C7_14, C9_14},
};
led_config_t g_led_config = { {
{ 0, 5, 10, 15, 20, 25, 29 },
{ 1, 6, 11, 16, 21, 26, 30 },
{ 2, 7, 12, 17, 22, 27, 31 },
{ 3, 8, 13, 18, 23, 28, NO_LED },
{ 4, 9, 14, 19, 24, NO_LED, NO_LED },
{ 32, 33, 34, 35, NO_LED, NO_LED, NO_LED },
{ 65, 61, 56, 51, 46, 41, 36 },
{ 66, 62, 57, 52, 47, 42, 37 },
{ 67, 63, 58, 53, 48, 43, 38 },
{ NO_LED, 64, 59, 54, 49, 44, 39 },
{ NO_LED, NO_LED, 60, 55, 50, 45, 40 },
{ NO_LED, NO_LED, NO_LED, 71, 70, 69, 68 }
}, {
{ 0, 4}, { 0, 20}, { 0, 36}, { 0, 52}, { 0, 68},
{ 16, 3}, { 16, 19}, { 16, 35}, { 16, 51}, { 16, 67},
{ 32, 1}, { 32, 17}, { 32, 33}, { 32, 49}, { 32, 65},
{ 48, 0}, { 48, 16}, { 48, 32}, { 48, 48}, { 48, 64},
{ 64, 1}, { 64, 17}, { 64, 33}, { 64, 49}, { 64, 65},
{ 80, 3}, { 80, 19}, { 80, 35}, { 80, 51},
{ 96, 4}, { 96, 20}, { 96, 36},
{ 88, 69}, {100, 80}, {112, 91}, {108, 69},
{240, 4}, {240, 20}, {240, 36}, {240, 52}, {240, 68},
{224, 3}, {224, 19}, {224, 35}, {224, 51}, {224, 67},
{208, 1}, {208, 17}, {208, 33}, {208, 49}, {208, 65},
{192, 0}, {192, 16}, {192, 32}, {192, 48}, {192, 64},
{176, 1}, {176, 17}, {176, 33}, {176, 49}, {176, 65},
{160, 3}, {160, 19}, {160, 35}, {160, 51},
{144, 4}, {144, 20}, {144, 36},
{152, 69}, {140, 80}, {128, 91}, {132, 69}
}, {
1, 1, 1, 1, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4,
1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4, 1,
4, 4, 4, 4,
1, 1, 1,
1, 1, 1, 1
} };
// clang-format on
#endif
#ifdef AUDIO_ENABLE
@ -368,11 +311,6 @@ const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
{{6,5}, {5,5}, {4,5}, {3,5}, {2,5}, {1,5},{0,5}},
};
// clang-format on
void keyboard_post_init_kb(void) {
rgb_matrix_enable_noeeprom();
keyboard_post_init_user();
}
#endif
#if defined(AUDIO_ENABLE) && defined(MUSIC_MAP)
@ -451,7 +389,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
return true;
}
void matrix_init_kb(void) {
void keyboard_post_init_kb(void) {
keyboard_config.raw = eeconfig_read_kb();
if (!keyboard_config.led_level && !keyboard_config.led_level_res) {
@ -460,11 +398,11 @@ void matrix_init_kb(void) {
eeconfig_update_kb(keyboard_config.raw);
}
#ifdef RGB_MATRIX_ENABLE
if (keyboard_config.rgb_matrix_enable) {
rgb_matrix_set_flags(LED_FLAG_ALL);
} else {
rgb_matrix_set_flags(LED_FLAG_NONE);
}
rgb_matrix_enable_noeeprom();
#endif
#if defined(DEFERRED_EXEC_ENABLE)
is_launching = true;
defer_exec(500, startup_exec, NULL);
#endif
matrix_init_user();
}

View file

@ -1,5 +1,7 @@
CUSTOM_MATRIX = lite
# project specific files
SRC += matrix.c
VPATH += drivers/gpio
SRC += matrix.c mcp23018.c
I2C_DRIVER_REQUIRED = yes
MCU_LDSCRIPT = STM32F303xB