summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPascal Getreuer <50221757+getreuer@users.noreply.github.com>2025-05-11 16:30:19 -0700
committerGitHub <noreply@github.com>2025-05-12 09:30:19 +1000
commitf4171412a676ae3cbd1cd50e859a7deb1a554e15 (patch)
tree57d1acc2b9f9651b8d82299a3288cbe51b0199cb
parent7f42a5bc03a3f80d65314c69adb0b1176cf13167 (diff)
Enable community modules to define LED matrix and RGB matrix effects. (#25187)
Co-authored-by: Joel Challis <git@zvecr.com>
-rw-r--r--builddefs/build_keyboard.mk13
-rw-r--r--data/constants/module_hooks/1.1.1.hjson3
-rw-r--r--docs/features/community_modules.md8
-rw-r--r--keyboards/handwired/onekey/info.json12
-rw-r--r--keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/config.h16
-rw-r--r--keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.c27
-rw-r--r--keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.json3
-rw-r--r--keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/config.h16
-rw-r--r--keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.c27
-rw-r--r--keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.json3
-rw-r--r--lib/python/qmk/cli/generate/community_modules.py75
-rw-r--r--modules/qmk/flow_led_matrix_effect/led_matrix_module.inc58
-rw-r--r--modules/qmk/flow_led_matrix_effect/qmk_module.json8
-rw-r--r--modules/qmk/flow_rgb_matrix_effect/qmk_module.json8
-rw-r--r--modules/qmk/flow_rgb_matrix_effect/rgb_matrix_module.inc64
-rw-r--r--quantum/led_matrix/led_matrix.c12
-rw-r--r--quantum/led_matrix/led_matrix.h6
-rw-r--r--quantum/rgb_matrix/rgb_matrix.c12
-rw-r--r--quantum/rgb_matrix/rgb_matrix.h6
19 files changed, 339 insertions, 38 deletions
diff --git a/builddefs/build_keyboard.mk b/builddefs/build_keyboard.mk
index 514191b17d..c2c47c00fb 100644
--- a/builddefs/build_keyboard.mk
+++ b/builddefs/build_keyboard.mk
@@ -274,10 +274,19 @@ $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h: $(KEYMAP_JSON) $(D
274 $(eval CMD=$(QMK_BIN) generate-community-modules-introspection-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(KEYMAP_JSON)) 274 $(eval CMD=$(QMK_BIN) generate-community-modules-introspection-h -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(KEYMAP_JSON))
275 @$(BUILD_CMD) 275 @$(BUILD_CMD)
276 276
277SRC += $(INTERMEDIATE_OUTPUT)/src/community_modules.c 277$(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
278 @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
279 $(eval CMD=$(QMK_BIN) generate-led-matrix-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(KEYMAP_JSON))
280 @$(BUILD_CMD)
278 281
279generated-files: $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h 282$(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc: $(KEYMAP_JSON) $(DD_CONFIG_FILES)
283 @$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
284 $(eval CMD=$(QMK_BIN) generate-rgb-matrix-community-modules-inc -kb $(KEYBOARD) --quiet --output $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc $(KEYMAP_JSON))
285 @$(BUILD_CMD)
286
287SRC += $(INTERMEDIATE_OUTPUT)/src/community_modules.c
280 288
289generated-files: $(INTERMEDIATE_OUTPUT)/src/community_modules.h $(INTERMEDIATE_OUTPUT)/src/community_modules.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.c $(INTERMEDIATE_OUTPUT)/src/community_modules_introspection.h $(INTERMEDIATE_OUTPUT)/src/led_matrix_community_modules.inc $(INTERMEDIATE_OUTPUT)/src/rgb_matrix_community_modules.inc
281 290
282include $(BUILDDEFS_PATH)/converters.mk 291include $(BUILDDEFS_PATH)/converters.mk
283 292
diff --git a/data/constants/module_hooks/1.1.1.hjson b/data/constants/module_hooks/1.1.1.hjson
new file mode 100644
index 0000000000..49f5d0d5d0
--- /dev/null
+++ b/data/constants/module_hooks/1.1.1.hjson
@@ -0,0 +1,3 @@
1{
2 // This version exists to signify addition of LED/RGB effect support.
3}
diff --git a/docs/features/community_modules.md b/docs/features/community_modules.md
index 8dede47bd4..eff07c939a 100644
--- a/docs/features/community_modules.md
+++ b/docs/features/community_modules.md
@@ -123,6 +123,14 @@ The source file may provide functions which allow access to information specifie
123Introspection is a relatively advanced topic within QMK, and existing patterns should be followed. If you need help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) or [chat with us on Discord](https://discord.gg/qmk). 123Introspection is a relatively advanced topic within QMK, and existing patterns should be followed. If you need help please [open an issue](https://github.com/qmk/qmk_firmware/issues/new) or [chat with us on Discord](https://discord.gg/qmk).
124::: 124:::
125 125
126### `led_matrix_module.inc`
127
128This file defines LED matrix effects in the same form as used with `led_matrix_kb.inc` and `led_matrix_user.inc` (see [Custom LED Matrix Effects](led_matrix#custom-led-matrix-effects)). Effect mode names are prepended with `LED_MATRIX_COMMUNITY_MODULE_`.
129
130### `rgb_matrix_module.inc`
131
132This file defines RGB matrix effects in the same form as used with `rgb_matrix_kb.inc` and `rgb_matrix_user.inc` (see [Custom RGB Matrix Effects](rgb_matrix#custom-rgb-matrix-effects)). Effect mode names are prepended with `RGB_MATRIX_COMMUNITY_MODULE_`.
133
126### Compatible APIs 134### Compatible APIs
127 135
128Community Modules may provide specializations for the following APIs: 136Community Modules may provide specializations for the following APIs:
diff --git a/keyboards/handwired/onekey/info.json b/keyboards/handwired/onekey/info.json
index 7b6b7ddab8..d5f650f1bd 100644
--- a/keyboards/handwired/onekey/info.json
+++ b/keyboards/handwired/onekey/info.json
@@ -26,5 +26,17 @@
26 {"x": 0, "y": 0, "matrix": [0, 0]} 26 {"x": 0, "y": 0, "matrix": [0, 0]}
27 ] 27 ]
28 } 28 }
29 },
30 "led_matrix": {
31 "driver": "snled27351",
32 "layout": [
33 {"matrix": [0, 0], "x": 0, "y": 0, "flags": 1}
34 ]
35 },
36 "rgb_matrix": {
37 "driver": "snled27351",
38 "layout": [
39 {"matrix": [0, 0], "x": 0, "y": 0, "flags": 1}
40 ]
29 } 41 }
30} 42}
diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/config.h b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/config.h
new file mode 100644
index 0000000000..aed1e4ac6f
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/config.h
@@ -0,0 +1,16 @@
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14#pragma once
15
16#define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.c b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.c
new file mode 100644
index 0000000000..0bd835ff25
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.c
@@ -0,0 +1,27 @@
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// This keymap serves as a test for modules/qmk/flow_led_matrix_effect.
16
17#include QMK_KEYBOARD_H
18
19const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(LM_TOGG)};
20
21const snled27351_led_t PROGMEM g_snled27351_leds[LED_MATRIX_LED_COUNT] = {
22 {0, CB6_CA1},
23};
24
25void keyboard_post_init_user(void) {
26 led_matrix_mode_noeeprom(LED_MATRIX_COMMUNITY_MODULE_FLOW);
27}
diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.json b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.json
new file mode 100644
index 0000000000..0ff6bf5a4d
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/cm_flow_led_matrix_effect/keymap.json
@@ -0,0 +1,3 @@
1{
2 "modules": ["qmk/flow_led_matrix_effect"]
3}
diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/config.h b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/config.h
new file mode 100644
index 0000000000..aed1e4ac6f
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/config.h
@@ -0,0 +1,16 @@
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14#pragma once
15
16#define SNLED27351_I2C_ADDRESS_1 SNLED27351_I2C_ADDRESS_GND
diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.c b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.c
new file mode 100644
index 0000000000..72ef2d3f80
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.c
@@ -0,0 +1,27 @@
1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// This keymap serves as a test for modules/qmk/flow_rgb_matrix_effect.
16
17#include QMK_KEYBOARD_H
18
19const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {LAYOUT_ortho_1x1(RM_TOGG)};
20
21const snled27351_led_t PROGMEM g_snled27351_leds[LED_MATRIX_LED_COUNT] = {
22 {0, CB6_CA1},
23};
24
25void keyboard_post_init_user(void) {
26 rgb_matrix_mode_noeeprom(RGB_MATRIX_COMMUNITY_MODULE_FLOW);
27}
diff --git a/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.json b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.json
new file mode 100644
index 0000000000..56d2342867
--- /dev/null
+++ b/keyboards/handwired/onekey/keymaps/cm_flow_rgb_matrix_effect/keymap.json
@@ -0,0 +1,3 @@
1{
2 "modules": ["qmk/flow_rgb_matrix_effect"]
3}
diff --git a/lib/python/qmk/cli/generate/community_modules.py b/lib/python/qmk/cli/generate/community_modules.py
index 61e24077d3..1f37b760ca 100644
--- a/lib/python/qmk/cli/generate/community_modules.py
+++ b/lib/python/qmk/cli/generate/community_modules.py
@@ -278,33 +278,32 @@ def generate_community_modules_c(cli):
278 dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True) 278 dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
279 279
280 280
281def _generate_include_per_module(cli, include_file_name):
282 """Generates C code to include "<module_path>/include_file_name" for each module."""
283 if cli.args.output and cli.args.output.name == '-':
284 cli.args.output = None
285
286 lines = [GPL2_HEADER_C_LIKE, GENERATED_HEADER_C_LIKE]
287
288 for module in get_modules(cli.args.keyboard, cli.args.filename):
289 full_path = f'{find_module_path(module)}/{include_file_name}'
290 lines.append('')
291 lines.append(f'#if __has_include("{full_path}")')
292 lines.append(f'#include "{full_path}"')
293 lines.append(f'#endif // __has_include("{full_path}")')
294
295 dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
296
297
281@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') 298@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
282@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") 299@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
283@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules.c for.') 300@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate community_modules_introspection.h for.')
284@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file') 301@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
285@cli.subcommand('Creates a community_modules_introspection.h from a keymap.json file.') 302@cli.subcommand('Creates a community_modules_introspection.h from a keymap.json file.')
286def generate_community_modules_introspection_h(cli): 303def generate_community_modules_introspection_h(cli):
287 """Creates a community_modules_introspection.h from a keymap.json file 304 """Creates a community_modules_introspection.h from a keymap.json file
288 """ 305 """
289 if cli.args.output and cli.args.output.name == '-': 306 _generate_include_per_module(cli, 'introspection.h')
290 cli.args.output = None
291
292 lines = [
293 GPL2_HEADER_C_LIKE,
294 GENERATED_HEADER_C_LIKE,
295 '',
296 ]
297
298 modules = get_modules(cli.args.keyboard, cli.args.filename)
299 if len(modules) > 0:
300 for module in modules:
301 module_path = find_module_path(module)
302 lines.append(f'#if __has_include("{module_path}/introspection.h")')
303 lines.append(f'#include "{module_path}/introspection.h"')
304 lines.append(f'#endif // __has_include("{module_path}/introspection.h")')
305 lines.append('')
306
307 dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True)
308 307
309 308
310@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to') 309@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@@ -315,22 +314,26 @@ def generate_community_modules_introspection_h(cli):
315def generate_community_modules_introspection_c(cli): 314def generate_community_modules_introspection_c(cli):
316 """Creates a community_modules_introspection.c from a keymap.json file 315 """Creates a community_modules_introspection.c from a keymap.json file
317 """ 316 """
318 if cli.args.output and cli.args.output.name == '-': 317 _generate_include_per_module(cli, 'introspection.c')
319 cli.args.output = None
320 318
321 lines = [
322 GPL2_HEADER_C_LIKE,
323 GENERATED_HEADER_C_LIKE,
324 '',
325 ]
326 319
327 modules = get_modules(cli.args.keyboard, cli.args.filename) 320@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
328 if len(modules) > 0: 321@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
329 for module in modules: 322@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate led_matrix_community_modules.inc for.')
330 module_path = find_module_path(module) 323@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
331 lines.append(f'#if __has_include("{module_path}/introspection.c")') 324@cli.subcommand('Creates an led_matrix_community_modules.inc from a keymap.json file.')
332 lines.append(f'#include "{module_path}/introspection.c"') 325def generate_led_matrix_community_modules_inc(cli):
333 lines.append(f'#endif // __has_include("{module_path}/introspection.c")') 326 """Creates an led_matrix_community_modules.inc from a keymap.json file
334 lines.append('') 327 """
328 _generate_include_per_module(cli, 'led_matrix_module.inc')
335 329
336 dump_lines(cli.args.output, lines, cli.args.quiet, remove_repeated_newlines=True) 330
331@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
332@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
333@cli.argument('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, help='Keyboard to generate rgb_matrix_community_modules.inc for.')
334@cli.argument('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.json'), help='Configurator JSON file')
335@cli.subcommand('Creates an rgb_matrix_community_modules.inc from a keymap.json file.')
336def generate_rgb_matrix_community_modules_inc(cli):
337 """Creates an rgb_matrix_community_modules.inc from a keymap.json file
338 """
339 _generate_include_per_module(cli, 'rgb_matrix_module.inc')
diff --git a/modules/qmk/flow_led_matrix_effect/led_matrix_module.inc b/modules/qmk/flow_led_matrix_effect/led_matrix_module.inc
new file mode 100644
index 0000000000..734e0f3494
--- /dev/null
+++ b/modules/qmk/flow_led_matrix_effect/led_matrix_module.inc
@@ -0,0 +1,58 @@
1// Copyright 2024-2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15LED_MATRIX_EFFECT(FLOW)
16
17#ifdef LED_MATRIX_CUSTOM_EFFECT_IMPLS
18
19// "Flow" animated effect. Draws moving wave patterns mimicking the appearance
20// of flowing liquid. For interesting variety of patterns, space coordinates are
21// slowly rotated and a function of several sine waves is evaluated.
22static bool FLOW(effect_params_t* params) {
23 LED_MATRIX_USE_LIMITS(led_min, led_max);
24
25 static uint16_t wrap_correction = 0;
26 static uint8_t last_high_byte = 0;
27 const uint8_t time_scale = 1 + led_matrix_eeconfig.speed / 8;
28 const uint8_t high_byte = (uint8_t)(g_led_timer >> 16);
29 if (last_high_byte != high_byte) {
30 last_high_byte = high_byte;
31 wrap_correction += ((uint16_t)time_scale) << 8;
32 }
33 const uint16_t time = scale16by8(g_led_timer, time_scale) + wrap_correction;
34
35 // Compute rotation coefficients with 7 fractional bits.
36 const int8_t rot_c = cos8(time / 4) - 128;
37 const int8_t rot_s = sin8(time / 4) - 128;
38 const uint8_t omega = 32 + sin8(time) / 4;
39
40 for (uint8_t i = led_min; i < led_max; ++i) {
41 LED_MATRIX_TEST_LED_FLAGS();
42 const uint8_t x = g_led_config.point[i].x;
43 const uint8_t y = g_led_config.point[i].y;
44
45 // Rotate (x, y) by the 2x2 rotation matrix described by rot_c, rot_s.
46 const uint8_t x1 = (uint8_t)((((int16_t)rot_c) * ((int16_t)x)) / 128) - (uint8_t)((((int16_t)rot_s) * ((int16_t)y)) / 128);
47 const uint8_t y1 = (uint8_t)((((int16_t)rot_s) * ((int16_t)x)) / 128) + (uint8_t)((((int16_t)rot_c) * ((int16_t)y)) / 128);
48
49 uint8_t value = scale8(sin8(x1 - 2 * time), omega) + y1 + time / 4;
50 value = (value <= 127) ? value : (255 - value);
51
52 led_matrix_set_value(i, scale8(led_matrix_eeconfig.val, value));
53 }
54
55 return led_matrix_check_finished_leds(led_max);
56}
57
58#endif // LED_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/modules/qmk/flow_led_matrix_effect/qmk_module.json b/modules/qmk/flow_led_matrix_effect/qmk_module.json
new file mode 100644
index 0000000000..2d047cd0d0
--- /dev/null
+++ b/modules/qmk/flow_led_matrix_effect/qmk_module.json
@@ -0,0 +1,8 @@
1{
2 "module_name": "Flow LED matrix effect",
3 "maintainer": "QMK Maintainers",
4 "license": "Apache-2.0",
5 "features": {
6 "led_matrix": true
7 }
8}
diff --git a/modules/qmk/flow_rgb_matrix_effect/qmk_module.json b/modules/qmk/flow_rgb_matrix_effect/qmk_module.json
new file mode 100644
index 0000000000..3e42fe1ef4
--- /dev/null
+++ b/modules/qmk/flow_rgb_matrix_effect/qmk_module.json
@@ -0,0 +1,8 @@
1{
2 "module_name": "Flow RGB matrix effect",
3 "maintainer": "QMK Maintainers",
4 "license": "Apache-2.0",
5 "features": {
6 "rgb_matrix": true
7 }
8}
diff --git a/modules/qmk/flow_rgb_matrix_effect/rgb_matrix_module.inc b/modules/qmk/flow_rgb_matrix_effect/rgb_matrix_module.inc
new file mode 100644
index 0000000000..410838f7ec
--- /dev/null
+++ b/modules/qmk/flow_rgb_matrix_effect/rgb_matrix_module.inc
@@ -0,0 +1,64 @@
1// Copyright 2024-2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15RGB_MATRIX_EFFECT(FLOW)
16
17#ifdef RGB_MATRIX_CUSTOM_EFFECT_IMPLS
18
19// "Flow" animated effect. Draws moving wave patterns mimicking the appearance
20// of flowing liquid. For interesting variety of patterns, space coordinates are
21// slowly rotated and a function of several sine waves is evaluated.
22static bool FLOW(effect_params_t* params) {
23 RGB_MATRIX_USE_LIMITS(led_min, led_max);
24
25 static uint16_t wrap_correction = 0;
26 static uint8_t last_high_byte = 0;
27 const uint8_t time_scale = 1 + rgb_matrix_config.speed / 8;
28 const uint8_t high_byte = (uint8_t)(g_rgb_timer >> 16);
29 if (last_high_byte != high_byte) {
30 last_high_byte = high_byte;
31 wrap_correction += ((uint16_t)time_scale) << 8;
32 }
33 const uint16_t time = scale16by8(g_rgb_timer, time_scale) + wrap_correction;
34
35 // Compute rotation coefficients with 7 fractional bits.
36 const int8_t rot_c = cos8(time / 4) - 128;
37 const int8_t rot_s = sin8(time / 4) - 128;
38 const uint8_t omega = 32 + sin8(time) / 4;
39
40 for (uint8_t i = led_min; i < led_max; ++i) {
41 RGB_MATRIX_TEST_LED_FLAGS();
42 const uint8_t x = g_led_config.point[i].x;
43 const uint8_t y = g_led_config.point[i].y;
44
45 // Rotate (x, y) by the 2x2 rotation matrix described by rot_c, rot_s.
46 const uint8_t x1 = (uint8_t)((((int16_t)rot_c) * ((int16_t)x)) / 128) - (uint8_t)((((int16_t)rot_s) * ((int16_t)y)) / 128);
47 const uint8_t y1 = (uint8_t)((((int16_t)rot_s) * ((int16_t)x)) / 128) + (uint8_t)((((int16_t)rot_c) * ((int16_t)y)) / 128);
48
49 uint8_t value = scale8(sin8(x1 - 2 * time), omega) + y1 + time / 4;
50 value = (value <= 127) ? value : (255 - value);
51
52 hsv_t hsv = rgb_matrix_config.hsv;
53 hsv.h -= value / 4;
54 hsv.s = scale8(hsv.s, (value < 74) ? 255 : (549 - 4 * value));
55 hsv.v = scale8(hsv.v, (value < 95) ? (64 + 2 * value) : 255);
56
57 rgb_t rgb = rgb_matrix_hsv_to_rgb(hsv);
58 rgb_matrix_set_color(i, rgb.r, rgb.g, rgb.b);
59 }
60
61 return rgb_matrix_check_finished_leds(led_max);
62}
63
64#endif // RGB_MATRIX_CUSTOM_EFFECT_IMPLS
diff --git a/quantum/led_matrix/led_matrix.c b/quantum/led_matrix/led_matrix.c
index 00bc199ecf..7a0e8a5ebb 100644
--- a/quantum/led_matrix/led_matrix.c
+++ b/quantum/led_matrix/led_matrix.c
@@ -45,6 +45,9 @@ const led_point_t k_led_matrix_center = LED_MATRIX_CENTER;
45#define LED_MATRIX_CUSTOM_EFFECT_IMPLS 45#define LED_MATRIX_CUSTOM_EFFECT_IMPLS
46 46
47#include "led_matrix_effects.inc" 47#include "led_matrix_effects.inc"
48#ifdef COMMUNITY_MODULES_ENABLE
49# include "led_matrix_community_modules.inc"
50#endif
48#ifdef LED_MATRIX_CUSTOM_KB 51#ifdef LED_MATRIX_CUSTOM_KB
49# include "led_matrix_kb.inc" 52# include "led_matrix_kb.inc"
50#endif 53#endif
@@ -282,6 +285,15 @@ static void led_task_render(uint8_t effect) {
282#include "led_matrix_effects.inc" 285#include "led_matrix_effects.inc"
283#undef LED_MATRIX_EFFECT 286#undef LED_MATRIX_EFFECT
284 287
288#ifdef COMMUNITY_MODULES_ENABLE
289# define LED_MATRIX_EFFECT(name, ...) \
290 case LED_MATRIX_COMMUNITY_MODULE_##name: \
291 rendering = name(&led_effect_params); \
292 break;
293# include "led_matrix_community_modules.inc"
294# undef LED_MATRIX_EFFECT
295#endif
296
285#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) 297#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
286# define LED_MATRIX_EFFECT(name, ...) \ 298# define LED_MATRIX_EFFECT(name, ...) \
287 case LED_MATRIX_CUSTOM_##name: \ 299 case LED_MATRIX_CUSTOM_##name: \
diff --git a/quantum/led_matrix/led_matrix.h b/quantum/led_matrix/led_matrix.h
index 0006d487e9..0dfe33ffab 100644
--- a/quantum/led_matrix/led_matrix.h
+++ b/quantum/led_matrix/led_matrix.h
@@ -98,6 +98,12 @@ enum led_matrix_effects {
98#include "led_matrix_effects.inc" 98#include "led_matrix_effects.inc"
99#undef LED_MATRIX_EFFECT 99#undef LED_MATRIX_EFFECT
100 100
101#ifdef COMMUNITY_MODULES_ENABLE
102# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_COMMUNITY_MODULE_##name,
103# include "led_matrix_community_modules.inc"
104# undef LED_MATRIX_EFFECT
105#endif
106
101#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER) 107#if defined(LED_MATRIX_CUSTOM_KB) || defined(LED_MATRIX_CUSTOM_USER)
102# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name, 108# define LED_MATRIX_EFFECT(name, ...) LED_MATRIX_CUSTOM_##name,
103# ifdef LED_MATRIX_CUSTOM_KB 109# ifdef LED_MATRIX_CUSTOM_KB
diff --git a/quantum/rgb_matrix/rgb_matrix.c b/quantum/rgb_matrix/rgb_matrix.c
index 94852e3520..2679c48342 100644
--- a/quantum/rgb_matrix/rgb_matrix.c
+++ b/quantum/rgb_matrix/rgb_matrix.c
@@ -47,6 +47,9 @@ __attribute__((weak)) rgb_t rgb_matrix_hsv_to_rgb(hsv_t hsv) {
47#define RGB_MATRIX_CUSTOM_EFFECT_IMPLS 47#define RGB_MATRIX_CUSTOM_EFFECT_IMPLS
48 48
49#include "rgb_matrix_effects.inc" 49#include "rgb_matrix_effects.inc"
50#ifdef COMMUNITY_MODULES_ENABLE
51# include "rgb_matrix_community_modules.inc"
52#endif
50#ifdef RGB_MATRIX_CUSTOM_KB 53#ifdef RGB_MATRIX_CUSTOM_KB
51# include "rgb_matrix_kb.inc" 54# include "rgb_matrix_kb.inc"
52#endif 55#endif
@@ -310,6 +313,15 @@ static void rgb_task_render(uint8_t effect) {
310#include "rgb_matrix_effects.inc" 313#include "rgb_matrix_effects.inc"
311#undef RGB_MATRIX_EFFECT 314#undef RGB_MATRIX_EFFECT
312 315
316#ifdef COMMUNITY_MODULES_ENABLE
317# define RGB_MATRIX_EFFECT(name, ...) \
318 case RGB_MATRIX_COMMUNITY_MODULE_##name: \
319 rendering = name(&rgb_effect_params); \
320 break;
321# include "rgb_matrix_community_modules.inc"
322# undef RGB_MATRIX_EFFECT
323#endif
324
313#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 325#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
314# define RGB_MATRIX_EFFECT(name, ...) \ 326# define RGB_MATRIX_EFFECT(name, ...) \
315 case RGB_MATRIX_CUSTOM_##name: \ 327 case RGB_MATRIX_CUSTOM_##name: \
diff --git a/quantum/rgb_matrix/rgb_matrix.h b/quantum/rgb_matrix/rgb_matrix.h
index e00e3927c7..c6b302631e 100644
--- a/quantum/rgb_matrix/rgb_matrix.h
+++ b/quantum/rgb_matrix/rgb_matrix.h
@@ -123,6 +123,12 @@ enum rgb_matrix_effects {
123#include "rgb_matrix_effects.inc" 123#include "rgb_matrix_effects.inc"
124#undef RGB_MATRIX_EFFECT 124#undef RGB_MATRIX_EFFECT
125 125
126#ifdef COMMUNITY_MODULES_ENABLE
127# define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_COMMUNITY_MODULE_##name,
128# include "rgb_matrix_community_modules.inc"
129# undef RGB_MATRIX_EFFECT
130#endif
131
126#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER) 132#if defined(RGB_MATRIX_CUSTOM_KB) || defined(RGB_MATRIX_CUSTOM_USER)
127# define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_CUSTOM_##name, 133# define RGB_MATRIX_EFFECT(name, ...) RGB_MATRIX_CUSTOM_##name,
128# ifdef RGB_MATRIX_CUSTOM_KB 134# ifdef RGB_MATRIX_CUSTOM_KB