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 json
import os
import re
import sys
# -----------------------------------------------------------------------------
@ -12,24 +14,38 @@ def main():
+ "keyboard layout" )
arg_parser.add_argument(
'--map-file',
required = True )
arg_parser.add_argument(
'--hex-file',
required = True )
arg_parser.add_argument(
'--eep-file',
'--ui-info-file',
required = True )
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 = {
@ -264,3 +280,9 @@ keycode_to_string = {
0xE7: "RightGUI",
}
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
if __name__ == '__main__':
main()

View File

@ -39,6 +39,10 @@ The file will contain:
],
"matrix-positions": [
<string>, ...
],
"matrix-layout": [
[ [ <number>, <string>, <string> ], ... ],
...
]
},
"miscellaneous": {
@ -274,22 +278,63 @@ def find_keyboard_functions(source_code_path):
return output
def find_mappings(matrix_file_path):
def gen_mappings(matrix_file_path, layout_file_path):
# normalize paths
matrix_file_path = os.path.abspath(matrix_file_path)
layout_file_path = os.path.abspath(layout_file_path)
match = re.search(
r'#define\s+KB_MATRIX_LAYER\s*\(([^)]+)\)[^{]*\{\{([^#]+)\}\}',
open(matrix_file_path).read(),
re.MULTILINE )
def parse_matrix_file(matrix_file_path):
match = re.search( # find the whole 'KB_MATRIX_LAYER' macro
r'#define\s+KB_MATRIX_LAYER\s*\(([^)]+)\)[^{]*\{\{([^#]+)\}\}',
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',
help = "the path to the matrix file we're using",
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:])
@ -354,7 +403,8 @@ def main():
args.git_commit_id ) )
dict_merge(output, parse_mapfile(args.map_file_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))
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
# distribution, containing everything people will need to use the software.
#
# DEPENDENCIES: This is unabashedly dependant on various Unix commands, and
# therefore probably won't work in a Windows environment. I'm sorry... I
# don't know a good portable way to write it.
# DEPENDENCIES: This is unabashedly dependant on (the GNU implementation of)
# various Unix commands, and therefore probably won't work in a Windows
# environment (besides maybe cygwin). Sorry... I don't know a good portable
# way to write it.
#
# TODO:
# - include doc files (and maybe render them in html)
@ -18,32 +19,35 @@
# -----------------------------------------------------------------------------
# the base name of the file or package to distribute
NAME := ergodox-firmware
# the name of the keyboard we're building
# - must match the same variable in src/makefile
KEYBOARD := ergodox
include src/makefile-options
# system specific stuff
UNAME := $(shell uname)
ifeq ($(UNAME),Darwin)
DATE_PROG := gdate
else
DATE_PROG := date
endif
CURRENT_DATE := $(shell $(DATE_PROG) --rfc-3339 s)
# git info
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_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
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
ROOT := $(BUILD)/$(TARGET)
SCRIPTS := build-scripts
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
.PHONY: all clean dist
.PHONY: all clean checkin build-dir firmware dist zip
all: dist
@ -51,29 +55,51 @@ clean:
git clean -dX # remove ignored files and directories
-rm -r '$(BUILD)'
dist:
# make sure we're checked in
-git commit -a
# set up the build dir
checkin:
# -git commit -a
build-dir:
-rm -r '$(BUILD)/$(TARGET)'*
-mkdir -p '$(BUILD)/$(TARGET)'
# make all subprojects
firmware:
cd src; $(MAKE) all
# copy stuff to build dir
# --- from src
( cd src; \
cp firmware.hex firmware.eep firmware.map \
'../$(BUILD)/$(TARGET)' )
# run secondary build scripts
( ./build-scripts/gen-ui-info.py \
--current-date '$(shell $(DATE) --rfc-3339 s)' \
$(ROOT)/firmware.%: firmware
cp 'src/firmware.$*' '$@'
$(ROOT)/firmware--ui-info.json: $(SCRIPTS)/gen-ui-info.py checkin
( ./'$<' \
--current-date '$(shell $(DATE_PROG) --rfc-3339 s)' \
--git-commit-date '$(GIT_COMMIT_DATE)' \
--git-commit-id '$(GIT_COMMIT_ID)' \
--map-file-path '$(BUILD)/$(TARGET)/firmware.map' \
--source-code-path 'src' \
--matrix-file-path 'src/keyboard/$(KEYBOARD)/matrix.h' \
) > '$(BUILD)/$(TARGET)/firmware--ui-info.json'
# make into a zip archive
--layout-file-path \
'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)'; \
zip '../$(TARGET).zip' \
-r * .* \

View File

@ -13,18 +13,12 @@
# -----------------------------------------------------------------------------
TARGET := firmware # the name we want for our program binary
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
include makefile-options
MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
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
FORMAT := ihex # the program binary's format
MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
BOARD := teensy-2-0 # see the libraries you're using for what's available
F_CPU := 16000000 # processor speed, in Hz
# firmware stuff
SRC := $(wildcard *.c)
@ -98,10 +92,10 @@ OBJCOPY := avr-objcopy
SIZE := avr-size
# remove whitespace from some of the variables
TARGET := $(strip $(TARGET))
# remove whitespace from some of the options
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))