working on layout graphic generator; almost there!

- also, additions to the ui-info.json file generator
- and probably some other small but useful things
partial-rewrite
Ben Blazak 2012-10-08 18:01:06 -07:00
parent c330126076
commit df7bb3a7d2
6 changed files with 188 additions and 72 deletions

View File

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

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

View File

@ -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))

View File

@ -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 * .* \

View File

@ -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))
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------

24
src/makefile-options Normal file
View File

@ -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))