summaryrefslogtreecommitdiff
path: root/lib/python/qmk/cli/generate/config_h.py
blob: e160ffea83cbd2507e2c7e8775f299c3a40c3b89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
"""Used by the make system to generate info_config.h from info.json.
"""
from milc import cli

from qmk.constants import LED_INDICATORS
from qmk.decorators import automagic_keyboard, automagic_keymap
from qmk.info import info_json, rgblight_animations, rgblight_properties, rgblight_toggles
from qmk.path import is_keyboard, normpath

usb_prop_map = {
    'vid': 'VENDOR_ID',
    'pid': 'PRODUCT_ID',
    'device_ver': 'DEVICE_VER',
}


def debounce(debounce):
    """Return the config.h lines that set debounce
    """
    return """
#ifndef DEBOUNCE
#   define DEBOUNCE %s
#endif // DEBOUNCE
""" % debounce


def diode_direction(diode_direction):
    """Return the config.h lines that set diode direction
    """
    return """
#ifndef DIODE_DIRECTION
#   define DIODE_DIRECTION %s
#endif // DIODE_DIRECTION
""" % diode_direction


def keyboard_name(keyboard_name):
    """Return the config.h lines that set the keyboard's name.
    """
    return """
#ifndef DESCRIPTION
#    define DESCRIPTION %s
#endif // DESCRIPTION

#ifndef PRODUCT
#    define PRODUCT %s
#endif // PRODUCT
""" % (keyboard_name, keyboard_name)


def manufacturer(manufacturer):
    """Return the config.h lines that set the manufacturer.
    """
    return """
#ifndef MANUFACTURER
#    define MANUFACTURER %s
#endif // MANUFACTURER
""" % (manufacturer)


def direct_pins(direct_pins):
    """Return the config.h lines that set the direct pins.
    """
    rows = []

    for row in direct_pins:
        cols = ','.join([col or 'NO_PIN' for col in row])
        rows.append('{' + cols + '}')

    col_count = len(direct_pins[0])
    row_count = len(direct_pins)

    return """
#ifndef MATRIX_COLS
#    define MATRIX_COLS %s
#endif // MATRIX_COLS

#ifndef MATRIX_ROWS
#    define MATRIX_ROWS %s
#endif // MATRIX_ROWS

#ifndef DIRECT_PINS
#    define DIRECT_PINS {%s}
#endif // DIRECT_PINS
""" % (col_count, row_count, ','.join(rows))


def col_pins(col_pins):
    """Return the config.h lines that set the column pins.
    """
    cols = ','.join(col_pins)
    col_num = len(col_pins)

    return """
#ifndef MATRIX_COLS
#    define MATRIX_COLS %s
#endif // MATRIX_COLS

#ifndef MATRIX_COL_PINS
#    define MATRIX_COL_PINS {%s}
#endif // MATRIX_COL_PINS
""" % (col_num, cols)


def row_pins(row_pins):
    """Return the config.h lines that set the row pins.
    """
    rows = ','.join(row_pins)
    row_num = len(row_pins)

    return """
#ifndef MATRIX_ROWS
#    define MATRIX_ROWS %s
#endif // MATRIX_ROWS

#ifndef MATRIX_ROW_PINS
#    define MATRIX_ROW_PINS {%s}
#endif // MATRIX_ROW_PINS
""" % (row_num, rows)


def indicators(config):
    """Return the config.h lines that setup LED indicators.
    """
    defines = []

    for led, define in LED_INDICATORS.items():
        if led in config:
            defines.append('')
            defines.append('#ifndef %s' % (define,))
            defines.append('#   define %s %s' % (define, config[led]))
            defines.append('#endif // %s' % (define,))

    return '\n'.join(defines)


def layout_aliases(layout_aliases):
    """Return the config.h lines that setup layout aliases.
    """
    defines = []

    for alias, layout in layout_aliases.items():
        defines.append('')
        defines.append('#ifndef %s' % (alias,))
        defines.append('#   define %s %s' % (alias, layout))
        defines.append('#endif // %s' % (alias,))

    return '\n'.join(defines)


def matrix_pins(matrix_pins):
    """Add the matrix config to the config.h.
    """
    pins = []

    if 'direct' in matrix_pins:
        pins.append(direct_pins(matrix_pins['direct']))

    if 'cols' in matrix_pins:
        pins.append(col_pins(matrix_pins['cols']))

    if 'rows' in matrix_pins:
        pins.append(row_pins(matrix_pins['rows']))

    return '\n'.join(pins)


def rgblight(config):
    """Return the config.h lines that setup rgblight.
    """
    rgblight_config = []

    for json_key, config_key in rgblight_properties.items():
        if json_key in config:
            rgblight_config.append('')
            rgblight_config.append('#ifndef %s' % (config_key,))
            rgblight_config.append('#   define %s %s' % (config_key, config[json_key]))
            rgblight_config.append('#endif // %s' % (config_key,))

    for json_key, config_key in rgblight_toggles.items():
        if config.get(json_key):
            rgblight_config.append('')
            rgblight_config.append('#ifndef %s' % (config_key,))
            rgblight_config.append('#   define %s' % (config_key,))
            rgblight_config.append('#endif // %s' % (config_key,))

    for json_key, config_key in rgblight_animations.items():
        if 'animations' in config and config['animations'].get(json_key):
            rgblight_config.append('')
            rgblight_config.append('#ifndef %s' % (config_key,))
            rgblight_config.append('#   define %s' % (config_key,))
            rgblight_config.append('#endif // %s' % (config_key,))

    return '\n'.join(rgblight_config)


def usb_properties(usb_props):
    """Return the config.h lines that setup USB params.
    """
    usb_lines = []

    for info_name, config_name in usb_prop_map.items():
        if info_name in usb_props:
            usb_lines.append('')
            usb_lines.append('#ifndef ' + config_name)
            usb_lines.append('#    define %s %s' % (config_name, usb_props[info_name]))
            usb_lines.append('#endif // ' + config_name)

    return '\n'.join(usb_lines)


@cli.argument('-o', '--output', arg_only=True, type=normpath, help='File to write to')
@cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages")
@cli.argument('-kb', '--keyboard', help='Keyboard to generate config.h for.')
@cli.subcommand('Used by the make system to generate info_config.h from info.json', hidden=True)
@automagic_keyboard
@automagic_keymap
def generate_config_h(cli):
    """Generates the info_config.h file.
    """
    # Determine our keyboard(s)
    if not cli.config.generate_config_h.keyboard:
        cli.log.error('Missing paramater: --keyboard')
        cli.subcommands['info'].print_help()
        return False

    if not is_keyboard(cli.config.generate_config_h.keyboard):
        cli.log.error('Invalid keyboard: "%s"', cli.config.generate_config_h.keyboard)
        return False

    # Build the info.json file
    kb_info_json = info_json(cli.config.generate_config_h.keyboard)

    # Build the info_config.h file.
    config_h_lines = ['/* This file was generated by `qmk generate-config-h`. Do not edit or copy.' ' */', '', '#pragma once']

    if 'debounce' in kb_info_json:
        config_h_lines.append(debounce(kb_info_json['debounce']))

    if 'diode_direction' in kb_info_json:
        config_h_lines.append(diode_direction(kb_info_json['diode_direction']))

    if 'indicators' in kb_info_json:
        config_h_lines.append(indicators(kb_info_json['indicators']))

    if 'keyboard_name' in kb_info_json:
        config_h_lines.append(keyboard_name(kb_info_json['keyboard_name']))

    if 'layout_aliases' in kb_info_json:
        config_h_lines.append(layout_aliases(kb_info_json['layout_aliases']))

    if 'manufacturer' in kb_info_json:
        config_h_lines.append(manufacturer(kb_info_json['manufacturer']))

    if 'rgblight' in kb_info_json:
        config_h_lines.append(rgblight(kb_info_json['rgblight']))

    if 'matrix_pins' in kb_info_json:
        config_h_lines.append(matrix_pins(kb_info_json['matrix_pins']))

    if 'usb' in kb_info_json:
        config_h_lines.append(usb_properties(kb_info_json['usb']))

    # Show the results
    config_h = '\n'.join(config_h_lines)

    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(config_h)

        if not cli.args.quiet:
            cli.log.info('Wrote info_config.h to %s.', cli.args.output)

    else:
        print(config_h)