working on layout graphic generator; almost there!
- also, additions to the ui-info.json file generator - and probably some other small but useful thingspartial-rewrite
parent
c330126076
commit
df7bb3a7d2
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
@ -1,7 +1,9 @@
|
||||||
!# /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
@ -12,24 +14,38 @@ def main():
|
||||||
+ "keyboard layout" )
|
+ "keyboard layout" )
|
||||||
|
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
'--map-file',
|
'--ui-info-file',
|
||||||
required = True )
|
|
||||||
|
|
||||||
arg_parser.add_argument(
|
|
||||||
'--hex-file',
|
|
||||||
required = True )
|
|
||||||
|
|
||||||
arg_parser.add_argument(
|
|
||||||
'--eep-file',
|
|
||||||
required = True )
|
required = True )
|
||||||
|
|
||||||
args = arg_parser.parse_args(sys.argv[1:])
|
args = arg_parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
args.template_file = './build-scripts/gen-layout--template.svg'
|
||||||
|
|
||||||
|
# normalize paths
|
||||||
|
args.ui_info_file = os.path.abspath(args.ui_info_file)
|
||||||
|
|
||||||
|
# do stuff
|
||||||
|
doc = '' # to store the html document we're generating
|
||||||
|
template = open(args.template_file).read()
|
||||||
|
info = json.loads(open(args.ui_info_file).read())
|
||||||
|
|
||||||
|
matrix_positions = info['mappings']['matrix-positions']
|
||||||
|
matrix_layout = info['mappings']['matrix-layout']
|
||||||
|
|
||||||
|
# only consider keycodes, for now
|
||||||
|
for layout in matrix_layout:
|
||||||
|
template_copy = template
|
||||||
|
for (name, (code, press, release)) \
|
||||||
|
in zip(matrix_positions, layout):
|
||||||
|
template_copy = re.sub( name,
|
||||||
|
keycode_to_string.get(code, '[n/a]'),
|
||||||
|
template_copy )
|
||||||
|
|
||||||
|
doc += template_copy
|
||||||
|
|
||||||
|
print(doc)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
keycode_to_string = {
|
keycode_to_string = {
|
||||||
|
@ -264,3 +280,9 @@ keycode_to_string = {
|
||||||
0xE7: "RightGUI",
|
0xE7: "RightGUI",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
|
@ -39,6 +39,10 @@ The file will contain:
|
||||||
],
|
],
|
||||||
"matrix-positions": [
|
"matrix-positions": [
|
||||||
<string>, ...
|
<string>, ...
|
||||||
|
],
|
||||||
|
"matrix-layout": [
|
||||||
|
[ [ <number>, <string>, <string> ], ... ],
|
||||||
|
...
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"miscellaneous": {
|
"miscellaneous": {
|
||||||
|
@ -274,22 +278,63 @@ def find_keyboard_functions(source_code_path):
|
||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def find_mappings(matrix_file_path):
|
def gen_mappings(matrix_file_path, layout_file_path):
|
||||||
# normalize paths
|
# normalize paths
|
||||||
matrix_file_path = os.path.abspath(matrix_file_path)
|
matrix_file_path = os.path.abspath(matrix_file_path)
|
||||||
|
layout_file_path = os.path.abspath(layout_file_path)
|
||||||
|
|
||||||
match = re.search(
|
def parse_matrix_file(matrix_file_path):
|
||||||
r'#define\s+KB_MATRIX_LAYER\s*\(([^)]+)\)[^{]*\{\{([^#]+)\}\}',
|
match = re.search( # find the whole 'KB_MATRIX_LAYER' macro
|
||||||
open(matrix_file_path).read(),
|
r'#define\s+KB_MATRIX_LAYER\s*\(([^)]+)\)[^{]*\{\{([^#]+)\}\}',
|
||||||
re.MULTILINE )
|
open(matrix_file_path).read() )
|
||||||
|
|
||||||
|
return {
|
||||||
|
"mappings": {
|
||||||
|
"physical-positions": re.findall(r'k..', match.group(1)),
|
||||||
|
"matrix-positions": re.findall(r'k..|na', match.group(2)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
def parse_layout_file(layout_file_path):
|
||||||
|
match = re.findall( # find each whole '_kb_layout*' matrix definition
|
||||||
|
r'(_kb_layout\w*)[^=]*=((?:[^{}]*\{){3}[^=]*(?:[^{}]*\}){3})',
|
||||||
|
subprocess.getoutput("gcc -E '"+layout_file_path+"'") )
|
||||||
|
|
||||||
|
layout = {}
|
||||||
|
# collect all the values
|
||||||
|
for (name, matrix) in match:
|
||||||
|
layout[name] = [
|
||||||
|
re.findall( # find all numbers and function pointers
|
||||||
|
r'[x0-9A-F]+|&\w+|NULL',
|
||||||
|
re.sub( # replace '((void *) 0)' with 'NULL'
|
||||||
|
r'\(\s*\(\s*void\s*\*\s*\)\s*0\s*\)',
|
||||||
|
'NULL',
|
||||||
|
el ) )
|
||||||
|
for el in
|
||||||
|
re.findall( # find each whole layer
|
||||||
|
r'(?:[^{}]*\{){2}((?:[^}]|\}\s*,)+)(?:[^{}]*\}){2}',
|
||||||
|
matrix ) ]
|
||||||
|
|
||||||
|
# make the numbers into actual numbers
|
||||||
|
layout['_kb_layout'] = \
|
||||||
|
[[eval(el) for el in layer] for layer in layout['_kb_layout']]
|
||||||
|
|
||||||
|
return {
|
||||||
|
"mappings": {
|
||||||
|
"matrix-layout":
|
||||||
|
# group them all properly
|
||||||
|
[ [[c, p, r] for (c, p, r) in zip(code, press, release)]
|
||||||
|
for (code, press, release) in
|
||||||
|
zip( layout['_kb_layout'],
|
||||||
|
layout['_kb_layout_press'],
|
||||||
|
layout['_kb_layout_release'] ) ]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return dict_merge(
|
||||||
|
parse_matrix_file(matrix_file_path),
|
||||||
|
parse_layout_file(layout_file_path) )
|
||||||
|
|
||||||
return {
|
|
||||||
"mappings": {
|
|
||||||
"physical-positions": re.findall(r'k..', match.group(1)),
|
|
||||||
"matrix-positions": re.findall(r'k..|na', match.group(2)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -345,6 +390,10 @@ def main():
|
||||||
'--matrix-file-path',
|
'--matrix-file-path',
|
||||||
help = "the path to the matrix file we're using",
|
help = "the path to the matrix file we're using",
|
||||||
required = True )
|
required = True )
|
||||||
|
arg_parser.add_argument(
|
||||||
|
'--layout-file-path',
|
||||||
|
help = "the path to the layout file we're using",
|
||||||
|
required = True )
|
||||||
|
|
||||||
args = arg_parser.parse_args(sys.argv[1:])
|
args = arg_parser.parse_args(sys.argv[1:])
|
||||||
|
|
||||||
|
@ -354,7 +403,8 @@ def main():
|
||||||
args.git_commit_id ) )
|
args.git_commit_id ) )
|
||||||
dict_merge(output, parse_mapfile(args.map_file_path))
|
dict_merge(output, parse_mapfile(args.map_file_path))
|
||||||
dict_merge(output, find_keyboard_functions(args.source_code_path))
|
dict_merge(output, find_keyboard_functions(args.source_code_path))
|
||||||
dict_merge(output, find_mappings(args.matrix_file_path))
|
dict_merge(output, gen_mappings( args.matrix_file_path,
|
||||||
|
args.layout_file_path ))
|
||||||
dict_merge(output, gen_derived(output))
|
dict_merge(output, gen_derived(output))
|
||||||
|
|
||||||
print(json.dumps(output, sort_keys=True, indent=4))
|
print(json.dumps(output, sort_keys=True, indent=4))
|
||||||
|
|
90
makefile
90
makefile
|
@ -4,9 +4,10 @@
|
||||||
# This should produce a single file (probably in an archive format) for
|
# This should produce a single file (probably in an archive format) for
|
||||||
# distribution, containing everything people will need to use the software.
|
# distribution, containing everything people will need to use the software.
|
||||||
#
|
#
|
||||||
# DEPENDENCIES: This is unabashedly dependant on various Unix commands, and
|
# DEPENDENCIES: This is unabashedly dependant on (the GNU implementation of)
|
||||||
# therefore probably won't work in a Windows environment. I'm sorry... I
|
# various Unix commands, and therefore probably won't work in a Windows
|
||||||
# don't know a good portable way to write it.
|
# environment (besides maybe cygwin). Sorry... I don't know a good portable
|
||||||
|
# way to write it.
|
||||||
#
|
#
|
||||||
# TODO:
|
# TODO:
|
||||||
# - include doc files (and maybe render them in html)
|
# - include doc files (and maybe render them in html)
|
||||||
|
@ -18,32 +19,35 @@
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
# the base name of the file or package to distribute
|
include src/makefile-options
|
||||||
NAME := ergodox-firmware
|
|
||||||
# the name of the keyboard we're building
|
# system specific stuff
|
||||||
# - must match the same variable in src/makefile
|
UNAME := $(shell uname)
|
||||||
KEYBOARD := ergodox
|
ifeq ($(UNAME),Darwin)
|
||||||
|
DATE_PROG := gdate
|
||||||
|
else
|
||||||
|
DATE_PROG := date
|
||||||
|
endif
|
||||||
|
|
||||||
|
CURRENT_DATE := $(shell $(DATE_PROG) --rfc-3339 s)
|
||||||
|
|
||||||
# git info
|
# git info
|
||||||
GIT_BRANCH := $(shell git branch -l | grep '*' | cut -c 3-)
|
GIT_BRANCH := $(shell git branch -l | grep '*' | cut -c 3-)
|
||||||
GIT_COMMIT_DATE := $(shell git log -n 1 --pretty --date=iso | grep 'Date' | cut -c 9- )
|
GIT_COMMIT_DATE := $(shell git log -n 1 --pretty --date=iso | grep 'Date' | cut -c 9- )
|
||||||
GIT_COMMIT_ID := $(shell git log -n 1 | grep 'commit' | cut -c 8-)
|
GIT_COMMIT_ID := $(shell git log -n 1 | grep 'commit' | cut -c 8-)
|
||||||
|
|
||||||
UNAME := $(shell uname)
|
|
||||||
ifeq ($(UNAME),Darwin)
|
|
||||||
DATE := gdate
|
|
||||||
else
|
|
||||||
DATE := date
|
|
||||||
endif
|
|
||||||
# name to use for the final distribution file or package
|
# name to use for the final distribution file or package
|
||||||
TARGET := $(NAME)--$(GIT_BRANCH)--$(shell $(DATE) -d "$(GIT_COMMIT_DATE)" +'%Y%m%dT%H%M%S')--$(shell echo $(GIT_COMMIT_ID) | cut -c 1-7)
|
TARGET := ergodox-firmware--$(GIT_BRANCH)--$(shell $(DATE_PROG) -d "$(GIT_COMMIT_DATE)" +'%Y%m%dT%H%M%S')--$(shell echo $(GIT_COMMIT_ID) | cut -c 1-7)
|
||||||
|
|
||||||
# the build dir
|
# directories
|
||||||
BUILD := build
|
BUILD := build
|
||||||
|
ROOT := $(BUILD)/$(TARGET)
|
||||||
|
SCRIPTS := build-scripts
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
.PHONY: all clean dist
|
.PHONY: all clean checkin build-dir firmware dist zip
|
||||||
|
|
||||||
all: dist
|
all: dist
|
||||||
|
|
||||||
|
@ -51,29 +55,51 @@ clean:
|
||||||
git clean -dX # remove ignored files and directories
|
git clean -dX # remove ignored files and directories
|
||||||
-rm -r '$(BUILD)'
|
-rm -r '$(BUILD)'
|
||||||
|
|
||||||
dist:
|
checkin:
|
||||||
# make sure we're checked in
|
# -git commit -a
|
||||||
-git commit -a
|
|
||||||
# set up the build dir
|
build-dir:
|
||||||
-rm -r '$(BUILD)/$(TARGET)'*
|
-rm -r '$(BUILD)/$(TARGET)'*
|
||||||
-mkdir -p '$(BUILD)/$(TARGET)'
|
-mkdir -p '$(BUILD)/$(TARGET)'
|
||||||
# make all subprojects
|
|
||||||
|
firmware:
|
||||||
cd src; $(MAKE) all
|
cd src; $(MAKE) all
|
||||||
# copy stuff to build dir
|
|
||||||
# --- from src
|
$(ROOT)/firmware.%: firmware
|
||||||
( cd src; \
|
cp 'src/firmware.$*' '$@'
|
||||||
cp firmware.hex firmware.eep firmware.map \
|
|
||||||
'../$(BUILD)/$(TARGET)' )
|
|
||||||
# run secondary build scripts
|
$(ROOT)/firmware--ui-info.json: $(SCRIPTS)/gen-ui-info.py checkin
|
||||||
( ./build-scripts/gen-ui-info.py \
|
( ./'$<' \
|
||||||
--current-date '$(shell $(DATE) --rfc-3339 s)' \
|
--current-date '$(shell $(DATE_PROG) --rfc-3339 s)' \
|
||||||
--git-commit-date '$(GIT_COMMIT_DATE)' \
|
--git-commit-date '$(GIT_COMMIT_DATE)' \
|
||||||
--git-commit-id '$(GIT_COMMIT_ID)' \
|
--git-commit-id '$(GIT_COMMIT_ID)' \
|
||||||
--map-file-path '$(BUILD)/$(TARGET)/firmware.map' \
|
--map-file-path '$(BUILD)/$(TARGET)/firmware.map' \
|
||||||
--source-code-path 'src' \
|
--source-code-path 'src' \
|
||||||
--matrix-file-path 'src/keyboard/$(KEYBOARD)/matrix.h' \
|
--matrix-file-path 'src/keyboard/$(KEYBOARD)/matrix.h' \
|
||||||
) > '$(BUILD)/$(TARGET)/firmware--ui-info.json'
|
--layout-file-path \
|
||||||
# make into a zip archive
|
'src/keyboard/$(KEYBOARD)/layout/$(LAYOUT).c' \
|
||||||
|
) > '$@'
|
||||||
|
|
||||||
|
$(ROOT)/firmware--layout.html: \
|
||||||
|
$(SCRIPTS)/gen-layout.py \
|
||||||
|
$(ROOT)/firmware--ui-info.json
|
||||||
|
\
|
||||||
|
( ./'$<' \
|
||||||
|
--ui-info-file '$(ROOT)/firmware--ui-info.json' \
|
||||||
|
) > '$@'
|
||||||
|
|
||||||
|
|
||||||
|
dist: \
|
||||||
|
checkin \
|
||||||
|
build-dir \
|
||||||
|
$(ROOT)/firmware.hex \
|
||||||
|
$(ROOT)/firmware.eep \
|
||||||
|
$(ROOT)/firmware.map \
|
||||||
|
$(ROOT)/firmware--ui-info.json \
|
||||||
|
$(ROOT)/firmware--layout.html
|
||||||
|
|
||||||
|
zip: dist
|
||||||
( cd '$(BUILD)/$(TARGET)'; \
|
( cd '$(BUILD)/$(TARGET)'; \
|
||||||
zip '../$(TARGET).zip' \
|
zip '../$(TARGET).zip' \
|
||||||
-r * .* \
|
-r * .* \
|
||||||
|
|
20
src/makefile
20
src/makefile
|
@ -13,18 +13,12 @@
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
TARGET := firmware # the name we want for our program binary
|
include makefile-options
|
||||||
FORMAT := ihex # the program binary's format
|
|
||||||
KEYBOARD := ergodox # keyboard model; see "src/keyboard" for what's available
|
|
||||||
LAYOUT := qwerty # keyboard layout; see "src/keyboard/*/layout" for what's
|
|
||||||
# available
|
|
||||||
|
|
||||||
MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
|
FORMAT := ihex # the program binary's format
|
||||||
BOARD := teensy-2-0 # see the libraries you're using for what's available
|
MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
|
||||||
F_CPU := 16000000 # processor speed, in Hz
|
BOARD := teensy-2-0 # see the libraries you're using for what's available
|
||||||
|
F_CPU := 16000000 # processor speed, in Hz
|
||||||
DEBOUNCE_TIME := 5 # in ms; see keyswitch spec for necessary value; 5ms should
|
|
||||||
# be good for cherry mx switches
|
|
||||||
|
|
||||||
# firmware stuff
|
# firmware stuff
|
||||||
SRC := $(wildcard *.c)
|
SRC := $(wildcard *.c)
|
||||||
|
@ -98,10 +92,10 @@ OBJCOPY := avr-objcopy
|
||||||
SIZE := avr-size
|
SIZE := avr-size
|
||||||
|
|
||||||
|
|
||||||
# remove whitespace from some of the variables
|
# remove whitespace from some of the options
|
||||||
TARGET := $(strip $(TARGET))
|
|
||||||
FORMAT := $(strip $(FORMAT))
|
FORMAT := $(strip $(FORMAT))
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# certain compilations options
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||||
|
# Released under The MIT License (MIT) (see "license.md")
|
||||||
|
# Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
TARGET := firmware # the name we want for our program binary
|
||||||
|
KEYBOARD := ergodox # keyboard model; see "src/keyboard" for what's available
|
||||||
|
LAYOUT := qwerty # keyboard layout; see "src/keyboard/*/layout" for what's
|
||||||
|
# available
|
||||||
|
|
||||||
|
DEBOUNCE_TIME := 5 # in ms; see keyswitch spec for necessary value; 5ms should
|
||||||
|
# be good for cherry mx switches
|
||||||
|
|
||||||
|
|
||||||
|
# remove whitespace
|
||||||
|
TARGET := $(strip $(TARGET))
|
||||||
|
KEYBOARD := $(strip $(KEYBOARD))
|
||||||
|
LAYOUT := $(strip $(LAYOUT))
|
||||||
|
DEBOUNCE_TIME := $(strip $(DEBOUNCE_TIME))
|
||||||
|
|
Loading…
Reference in New Issue