~ruther/qmk_firmware

37fb14f1b5cbcb0e5ff60abc9152073635234ba4 — Ryan 4 years ago 3925ff5
CLI-ify rgblight_breathing_table_calc.c (#11174)

Co-authored-by: Takeshi ISHII <2170248+mtei@users.noreply.github.com>
Co-authored-by: Zach White <skullydazed@drpepper.org>
M docs/cli_commands.md => docs/cli_commands.md +10 -0
@@ 296,6 296,16 @@ This command allows you to generate QMK documentation locally. It can be uses fo
qmk generate-docs
```

## `qmk generate-rgb-breathe-table`

This command generates a lookup table (LUT) header file for the [RGB Lighting](feature_rgblight.md) feature's breathing animation. Place this file in your keyboard or keymap directory as `rgblight_breathe_table.h` to override the default LUT in `quantum/`.

**Usage**:

```
qmk generate-rgb-breathe-table [-q] [-o OUTPUT] [-m MAX] [-c CENTER]
```

## `qmk kle2json`

This command allows you to convert from raw KLE data to QMK Configurator JSON. It accepts either an absolute file path, or a file name in the current directory. By default it will not overwrite `info.json` if it is already present. Use the `-f` or `--force` flag to overwrite.

M lib/python/qmk/cli/generate/__init__.py => lib/python/qmk/cli/generate/__init__.py +1 -0
@@ 1,2 1,3 @@
from . import api
from . import docs
from . import rgb_breathe_table

A lib/python/qmk/cli/generate/rgb_breathe_table.py => lib/python/qmk/cli/generate/rgb_breathe_table.py +79 -0
@@ 0,0 1,79 @@
"""Generate rgblight_breathe_table.h
"""
import math
from argparse import ArgumentTypeError

from milc import cli

import qmk.path


def breathing_center(value):
    value = float(value)
    if value >= 1 and value <= 2.7:
        return value
    else:
        raise ArgumentTypeError('Breathing center must be between 1 and 2.7')


def breathing_max(value):
    value = int(value)
    if value in range(0, 256):
        return value
    else:
        raise ArgumentTypeError('Breathing max must be between 0 and 255')


@cli.argument('-c', '--center', arg_only=True, type=breathing_center, default=1.85, help='The breathing center value, from 1 to 2.7. Default: 1.85')
@cli.argument('-m', '--max', arg_only=True, type=breathing_max, default=255, help='The breathing maximum value, from 0 to 255. Default: 255')
@cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help='Quiet mode, only output error messages')
@cli.subcommand('Generates an RGB Light breathing table header.')
def generate_rgb_breathe_table(cli):
    """Generate a rgblight_breathe_table.h file containing a breathing LUT for RGB Lighting (Underglow) feature.
    """
    breathe_values = [0] * 256
    for pos in range(0, 256):
        breathe_values[pos] = (int)((math.exp(math.sin((pos/255) * math.pi)) - cli.args.center / math.e) * (cli.args.max / (math.e - 1 / math.e)))  # noqa: yapf insists there be no whitespace around /

    values_template = ''
    for s in range(0, 3):
        step = 1 << s

        values_template += '#if RGBLIGHT_BREATHE_TABLE_SIZE == {}\n'.format(256 >> s)

        for pos in range(0, 256, step):
            values_template += '    ' if pos % 8 == 0 else ''
            values_template += '0x{:02X}'.format(breathe_values[pos])
            values_template += ',' if (pos + step) < 256 else ''
            values_template += '\n' if (pos+step) % 8 == 0 else ' '  # noqa: yapf insists there be no whitespace around +

        values_template += '#endif'
        values_template += '\n\n' if s < 2 else ''

    table_template = '''#pragma once

#define RGBLIGHT_EFFECT_BREATHE_TABLE

// clang-format off

// Breathing center: {0:.2f}
// Breathing max:    {1:d}

const uint8_t PROGMEM rgblight_effect_breathe_table[] = {{
{2}
}};

static const int table_scale = 256 / sizeof(rgblight_effect_breathe_table);
'''.format(cli.args.center, cli.args.max, values_template)

    if cli.args.output:
        cli.args.output.parent.mkdir(parents=True, exist_ok=True)
        if cli.args.output.exists():
            cli.args.output.replace(cli.args.output.name + '.bak')
        cli.args.output.write_text(table_template)

        if not cli.args.quiet:
            cli.log.info('Wrote header to %s.', cli.args.output)
    else:
        print(table_template)

M lib/python/qmk/tests/test_cli_commands.py => lib/python/qmk/tests/test_cli_commands.py +7 -0
@@ 190,3 190,10 @@ def test_clean():
    result = check_subcommand('clean', '-a')
    check_returncode(result)
    assert result.stdout.count('done') == 2


def test_generate_rgb_breathe_table():
    result = check_subcommand("generate-rgb-breathe-table", "-c", "1.2", "-m", "127")
    check_returncode(result)
    assert 'Breathing center: 1.2' in result.stdout
    assert 'Breathing max:    127' in result.stdout

M quantum/rgblight_breathe_table.h => quantum/rgblight_breathe_table.h +106 -457
@@ 1,468 1,117 @@
#ifndef RGBLIGHT_EFFECT_BREATHE_TABLE
#pragma once

#define RGBLIGHT_EFFECT_BREATHE_TABLE

const uint8_t rgblight_effect_breathe_table[] PROGMEM = {
/* #define RGBLIGHT_EFFECT_BREATHE_CENTER   1.85 */
/* #define RGBLIGHT_EFFECT_BREATHE_MAX      255 */
// clang-format off

// Breathing center: 1.85
// Breathing max:    255

const uint8_t PROGMEM rgblight_effect_breathe_table[] = {
#if RGBLIGHT_BREATHE_TABLE_SIZE == 256
    0x22,
    0x23,
    0x25,
    0x26,
    0x28,
    0x29,
    0x2a,
    0x2c,
    0x2d,
    0x2f,
    0x30,
    0x32,
    0x33,
    0x35,
    0x36,
    0x38,
    0x3a,
    0x3b,
    0x3d,
    0x3e,
    0x40,
    0x42,
    0x43,
    0x45,
    0x47,
    0x49,
    0x4a,
    0x4c,
    0x4e,
    0x50,
    0x51,
    0x53,
    0x55,
    0x57,
    0x59,
    0x5a,
    0x5c,
    0x5e,
    0x60,
    0x62,
    0x64,
    0x66,
    0x68,
    0x69,
    0x6b,
    0x6d,
    0x6f,
    0x71,
    0x73,
    0x75,
    0x77,
    0x79,
    0x7b,
    0x7d,
    0x7f,
    0x81,
    0x83,
    0x85,
    0x87,
    0x89,
    0x8a,
    0x8c,
    0x8e,
    0x90,
    0x92,
    0x94,
    0x96,
    0x98,
    0x9a,
    0x9c,
    0x9e,
    0x9f,
    0xa1,
    0xa3,
    0xa5,
    0xa7,
    0xa8,
    0xaa,
    0xac,
    0xae,
    0xaf,
    0xb1,
    0xb3,
    0xb4,
    0xb6,
    0xb8,
    0xb9,
    0xbb,
    0xbc,
    0xbe,
    0xbf,
    0xc1,
    0xc2,
    0xc3,
    0xc5,
    0xc6,
    0xc7,
    0xc9,
    0xca,
    0xcb,
    0xcc,
    0xcd,
    0xce,
    0xd0,
    0xd1,
    0xd2,
    0xd2,
    0xd3,
    0xd4,
    0xd5,
    0xd6,
    0xd7,
    0xd7,
    0xd8,
    0xd9,
    0xd9,
    0xda,
    0xda,
    0xdb,
    0xdb,
    0xdb,
    0xdc,
    0xdc,
    0xdc,
    0xdc,
    0xdc,
    0xdd,
    0xdd,
    0xdd,
    0xdd,
    0xdc,
    0xdc,
    0xdc,
    0xdc,
    0xdc,
    0xdb,
    0xdb,
    0xdb,
    0xda,
    0xda,
    0xd9,
    0xd9,
    0xd8,
    0xd7,
    0xd7,
    0xd6,
    0xd5,
    0xd4,
    0xd3,
    0xd2,
    0xd2,
    0xd1,
    0xd0,
    0xce,
    0xcd,
    0xcc,
    0xcb,
    0xca,
    0xc9,
    0xc7,
    0xc6,
    0xc5,
    0xc3,
    0xc2,
    0xc1,
    0xbf,
    0xbe,
    0xbc,
    0xbb,
    0xb9,
    0xb8,
    0xb6,
    0xb4,
    0xb3,
    0xb1,
    0xaf,
    0xae,
    0xac,
    0xaa,
    0xa8,
    0xa7,
    0xa5,
    0xa3,
    0xa1,
    0x9f,
    0x9e,
    0x9c,
    0x9a,
    0x98,
    0x96,
    0x94,
    0x92,
    0x90,
    0x8e,
    0x8c,
    0x8a,
    0x89,
    0x87,
    0x85,
    0x83,
    0x81,
    0x7f,
    0x7d,
    0x7b,
    0x79,
    0x77,
    0x75,
    0x73,
    0x71,
    0x6f,
    0x6d,
    0x6b,
    0x69,
    0x68,
    0x66,
    0x64,
    0x62,
    0x60,
    0x5e,
    0x5c,
    0x5a,
    0x59,
    0x57,
    0x55,
    0x53,
    0x51,
    0x50,
    0x4e,
    0x4c,
    0x4a,
    0x49,
    0x47,
    0x45,
    0x43,
    0x42,
    0x40,
    0x3e,
    0x3d,
    0x3b,
    0x3a,
    0x38,
    0x36,
    0x35,
    0x33,
    0x32,
    0x30,
    0x2f,
    0x2d,
    0x2c,
    0x2a,
    0x29,
    0x28,
    0x26,
    0x25,
    0x23,
    0x22
#endif /* 256 bytes table */
    0x22, 0x23, 0x25, 0x26, 0x28, 0x29, 0x2A, 0x2C,
    0x2D, 0x2F, 0x30, 0x32, 0x33, 0x35, 0x36, 0x38,
    0x3A, 0x3B, 0x3D, 0x3E, 0x40, 0x42, 0x43, 0x45,
    0x47, 0x49, 0x4A, 0x4C, 0x4E, 0x50, 0x51, 0x53,
    0x55, 0x57, 0x59, 0x5A, 0x5C, 0x5E, 0x60, 0x62,
    0x64, 0x66, 0x68, 0x69, 0x6B, 0x6D, 0x6F, 0x71,
    0x73, 0x75, 0x77, 0x79, 0x7B, 0x7D, 0x7F, 0x81,
    0x83, 0x85, 0x87, 0x89, 0x8A, 0x8C, 0x8E, 0x90,
    0x92, 0x94, 0x96, 0x98, 0x9A, 0x9C, 0x9E, 0x9F,
    0xA1, 0xA3, 0xA5, 0xA7, 0xA8, 0xAA, 0xAC, 0xAE,
    0xAF, 0xB1, 0xB3, 0xB4, 0xB6, 0xB8, 0xB9, 0xBB,
    0xBC, 0xBE, 0xBF, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6,
    0xC7, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xD0,
    0xD1, 0xD2, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
    0xD7, 0xD8, 0xD9, 0xD9, 0xDA, 0xDA, 0xDB, 0xDB,
    0xDB, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDD, 0xDD,
    0xDD, 0xDD, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDB,
    0xDB, 0xDB, 0xDA, 0xDA, 0xD9, 0xD9, 0xD8, 0xD7,
    0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD2, 0xD1,
    0xD0, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7,
    0xC6, 0xC5, 0xC3, 0xC2, 0xC1, 0xBF, 0xBE, 0xBC,
    0xBB, 0xB9, 0xB8, 0xB6, 0xB4, 0xB3, 0xB1, 0xAF,
    0xAE, 0xAC, 0xAA, 0xA8, 0xA7, 0xA5, 0xA3, 0xA1,
    0x9F, 0x9E, 0x9C, 0x9A, 0x98, 0x96, 0x94, 0x92,
    0x90, 0x8E, 0x8C, 0x8A, 0x89, 0x87, 0x85, 0x83,
    0x81, 0x7F, 0x7D, 0x7B, 0x79, 0x77, 0x75, 0x73,
    0x71, 0x6F, 0x6D, 0x6B, 0x69, 0x68, 0x66, 0x64,
    0x62, 0x60, 0x5E, 0x5C, 0x5A, 0x59, 0x57, 0x55,
    0x53, 0x51, 0x50, 0x4E, 0x4C, 0x4A, 0x49, 0x47,
    0x45, 0x43, 0x42, 0x40, 0x3E, 0x3D, 0x3B, 0x3A,
    0x38, 0x36, 0x35, 0x33, 0x32, 0x30, 0x2F, 0x2D,
    0x2C, 0x2A, 0x29, 0x28, 0x26, 0x25, 0x23, 0x22
#endif

#if RGBLIGHT_BREATHE_TABLE_SIZE == 128
    0x22,
    0x25,
    0x28,
    0x2a,
    0x2d,
    0x30,
    0x33,
    0x36,
    0x3a,
    0x3d,
    0x40,
    0x43,
    0x47,
    0x4a,
    0x4e,
    0x51,
    0x55,
    0x59,
    0x5c,
    0x60,
    0x64,
    0x68,
    0x6b,
    0x6f,
    0x73,
    0x77,
    0x7b,
    0x7f,
    0x83,
    0x87,
    0x8a,
    0x8e,
    0x92,
    0x96,
    0x9a,
    0x9e,
    0xa1,
    0xa5,
    0xa8,
    0xac,
    0xaf,
    0xb3,
    0xb6,
    0xb9,
    0xbc,
    0xbf,
    0xc2,
    0xc5,
    0xc7,
    0xca,
    0xcc,
    0xce,
    0xd1,
    0xd2,
    0xd4,
    0xd6,
    0xd7,
    0xd9,
    0xda,
    0xdb,
    0xdb,
    0xdc,
    0xdc,
    0xdd,
    0xdd,
    0xdc,
    0xdc,
    0xdc,
    0xdb,
    0xda,
    0xd9,
    0xd8,
    0xd7,
    0xd5,
    0xd3,
    0xd2,
    0xd0,
    0xcd,
    0xcb,
    0xc9,
    0xc6,
    0xc3,
    0xc1,
    0xbe,
    0xbb,
    0xb8,
    0xb4,
    0xb1,
    0xae,
    0xaa,
    0xa7,
    0xa3,
    0x9f,
    0x9c,
    0x98,
    0x94,
    0x90,
    0x8c,
    0x89,
    0x85,
    0x81,
    0x7d,
    0x79,
    0x75,
    0x71,
    0x6d,
    0x69,
    0x66,
    0x62,
    0x5e,
    0x5a,
    0x57,
    0x53,
    0x50,
    0x4c,
    0x49,
    0x45,
    0x42,
    0x3e,
    0x3b,
    0x38,
    0x35,
    0x32,
    0x2f,
    0x2c,
    0x29,
    0x26,
    0x23
#endif /* 128 bytes table */
    0x22, 0x25, 0x28, 0x2A,
    0x2D, 0x30, 0x33, 0x36,
    0x3A, 0x3D, 0x40, 0x43,
    0x47, 0x4A, 0x4E, 0x51,
    0x55, 0x59, 0x5C, 0x60,
    0x64, 0x68, 0x6B, 0x6F,
    0x73, 0x77, 0x7B, 0x7F,
    0x83, 0x87, 0x8A, 0x8E,
    0x92, 0x96, 0x9A, 0x9E,
    0xA1, 0xA5, 0xA8, 0xAC,
    0xAF, 0xB3, 0xB6, 0xB9,
    0xBC, 0xBF, 0xC2, 0xC5,
    0xC7, 0xCA, 0xCC, 0xCE,
    0xD1, 0xD2, 0xD4, 0xD6,
    0xD7, 0xD9, 0xDA, 0xDB,
    0xDB, 0xDC, 0xDC, 0xDD,
    0xDD, 0xDC, 0xDC, 0xDC,
    0xDB, 0xDA, 0xD9, 0xD8,
    0xD7, 0xD5, 0xD3, 0xD2,
    0xD0, 0xCD, 0xCB, 0xC9,
    0xC6, 0xC3, 0xC1, 0xBE,
    0xBB, 0xB8, 0xB4, 0xB1,
    0xAE, 0xAA, 0xA7, 0xA3,
    0x9F, 0x9C, 0x98, 0x94,
    0x90, 0x8C, 0x89, 0x85,
    0x81, 0x7D, 0x79, 0x75,
    0x71, 0x6D, 0x69, 0x66,
    0x62, 0x5E, 0x5A, 0x57,
    0x53, 0x50, 0x4C, 0x49,
    0x45, 0x42, 0x3E, 0x3B,
    0x38, 0x35, 0x32, 0x2F,
    0x2C, 0x29, 0x26, 0x23
#endif

#if RGBLIGHT_BREATHE_TABLE_SIZE == 64
    0x22,
    0x28,
    0x2d,
    0x33,
    0x3a,
    0x40,
    0x47,
    0x4e,
    0x55,
    0x5c,
    0x64,
    0x6b,
    0x73,
    0x7b,
    0x83,
    0x8a,
    0x92,
    0x9a,
    0xa1,
    0xa8,
    0xaf,
    0xb6,
    0xbc,
    0xc2,
    0xc7,
    0xcc,
    0xd1,
    0xd4,
    0xd7,
    0xda,
    0xdb,
    0xdc,
    0xdd,
    0xdc,
    0xdb,
    0xd9,
    0xd7,
    0xd3,
    0xd0,
    0xcb,
    0xc6,
    0xc1,
    0xbb,
    0xb4,
    0xae,
    0xa7,
    0x9f,
    0x98,
    0x90,
    0x89,
    0x81,
    0x79,
    0x71,
    0x69,
    0x62,
    0x5a,
    0x53,
    0x4c,
    0x45,
    0x3e,
    0x38,
    0x32,
    0x2c,
    0x26
#endif /* 64 bytes table */
    0x22, 0x28,
    0x2D, 0x33,
    0x3A, 0x40,
    0x47, 0x4E,
    0x55, 0x5C,
    0x64, 0x6B,
    0x73, 0x7B,
    0x83, 0x8A,
    0x92, 0x9A,
    0xA1, 0xA8,
    0xAF, 0xB6,
    0xBC, 0xC2,
    0xC7, 0xCC,
    0xD1, 0xD4,
    0xD7, 0xDA,
    0xDB, 0xDC,
    0xDD, 0xDC,
    0xDB, 0xD9,
    0xD7, 0xD3,
    0xD0, 0xCB,
    0xC6, 0xC1,
    0xBB, 0xB4,
    0xAE, 0xA7,
    0x9F, 0x98,
    0x90, 0x89,
    0x81, 0x79,
    0x71, 0x69,
    0x62, 0x5A,
    0x53, 0x4C,
    0x45, 0x3E,
    0x38, 0x32,
    0x2C, 0x26
#endif
};

static const int table_scale = 256 / sizeof(rgblight_effect_breathe_table);

#endif /* RGBLIGHT_EFFECT_BREATHE_TABLE */

D util/rgblight_breathing_table_calc.c => util/rgblight_breathing_table_calc.c +0 -49
@@ 1,49 0,0 @@
//
// calculate rgblight_effect_breathe_table[] values
//
// this is host program for quantum/rgblight.c:void rgblight_effect_breathing();
//
// example:
//  $ edit util/rgblight_breathing_table_calc.c
//  $ cc -o util/rgblight_breathing_table_calc util/rgblight_breathing_table_calc.c
//  $ ./util/rgblight_breathing_table_calc > keyboards/KEYBOARD_NAME/keymaps/KEYMAP_NAME/rgblight_breathe_table.h
//
#include <stdio.h>
#include <math.h>
#include <stdint.h>

/// customize breeathing effect part ///////////////////////////
#define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85  // 1 to 2.7
#define RGBLIGHT_EFFECT_BREATHE_MAX    255   // 0 to 255
////////////////////////////////////////////////////////////////

int main(void) {
    int pos, step;
    int table[256];
    for (pos = 0; pos < 256; pos ++ ) {
        table[pos] = (uint8_t)(
              (exp(sin((pos/255.0)*M_PI))- RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)
              * (RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E))
              );
    }
    printf("#ifndef RGBLIGHT_EFFECT_BREATHE_TABLE\n");
    printf("#define RGBLIGHT_EFFECT_BREATHE_TABLE\n\n");
    printf("const uint8_t rgblight_effect_breathe_table[] PROGMEM = {\n");
    printf("  /* #define RGBLIGHT_EFFECT_BREATHE_CENTER   %.2f */\n", RGBLIGHT_EFFECT_BREATHE_CENTER);
    printf("  /* #define RGBLIGHT_EFFECT_BREATHE_MAX      %d */\n", RGBLIGHT_EFFECT_BREATHE_MAX);

    for (int s = 0, step = (1<<s); s < 3 ; s += 1, step = (1<<s) ) {
        printf("\n #if RGBLIGHT_BREATHE_TABLE_SIZE == %d\n",
               s == 0 ? 256:(s== 1 ? 128: 64));
        for (pos = 0; pos < 256; pos += step ) {
            printf("  0x%x%s", table[pos], (pos+step)>=256?"":"," );
            if ((pos+step) % 8 == 0)
                printf("\n");
        }
        printf(" #endif /* %d bytes table */\n", s == 0 ? 256:(s== 1 ? 128: 64));
    }
    printf("};\n");
    printf("\nstatic const int table_scale = 256/sizeof(rgblight_effect_breathe_table);\n");
    printf("\n#endif /* RGBLIGHT_EFFECT_BREATHE_TABLE */\n");
    return 0;
}