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 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()
|
||||
|
|
@ -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))
|
||||
|
|
90
makefile
90
makefile
|
@ -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 * .* \
|
||||
|
|
20
src/makefile
20
src/makefile
|
@ -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))
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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