diff --git a/build-scripts/gen-layout-graphic--template.svg b/build-scripts/gen-layout-graphic--template.svg
new file mode 100644
index 0000000..373da08
--- /dev/null
+++ b/build-scripts/gen-layout-graphic--template.svg
@@ -0,0 +1,2109 @@
+
+
+
+
diff --git a/build-scripts/gen-layout-graphic.py b/build-scripts/gen-layout-graphic.py
new file mode 100644
index 0000000..a93e116
--- /dev/null
+++ b/build-scripts/gen-layout-graphic.py
@@ -0,0 +1,266 @@
+!# /usr/bin/env python3
+
+import argparse
+import json
+import sys
+
+# -----------------------------------------------------------------------------
+
+def main():
+ arg_parser = argparse.ArgumentParser(
+ description = "Generate a picture of the firmware's "
+ + "keyboard layout" )
+
+ arg_parser.add_argument(
+ '--map-file',
+ required = True )
+
+ arg_parser.add_argument(
+ '--hex-file',
+ required = True )
+
+ arg_parser.add_argument(
+ '--eep-file',
+ required = True )
+
+ args = arg_parser.parse_args(sys.argv[1:])
+
+# -----------------------------------------------------------------------------
+
+if __name__ == '__main__':
+ main()
+
+# -----------------------------------------------------------------------------
+
+keycode_to_string = {
+ 0x01: "ErrorRollOver",
+ 0x02: "POSTFail",
+ 0x03: "ErrorUndefined",
+ 0x04: "a A",
+ 0x05: "b B",
+ 0x06: "c C",
+ 0x07: "d D",
+ 0x08: "e E",
+ 0x09: "f F",
+ 0x0A: "g G",
+ 0x0B: "h H",
+ 0x0C: "i I",
+ 0x0D: "j J",
+ 0x0E: "k K",
+ 0x0F: "l L",
+ 0x10: "m M",
+ 0x11: "n N",
+ 0x12: "o O",
+ 0x13: "p P",
+ 0x14: "q Q",
+ 0x15: "r R",
+ 0x16: "s S",
+ 0x17: "t T",
+ 0x18: "u U",
+ 0x19: "v V",
+ 0x1A: "w W",
+ 0x1B: "x X",
+ 0x1C: "y Y",
+ 0x1D: "z Z",
+ 0x1E: "1 !",
+ 0x1F: "2 @",
+ 0x20: "3 #",
+ 0x21: "4 $",
+ 0x22: "5 %",
+ 0x23: "6 ^",
+ 0x24: "7 &",
+ 0x25: "8 *",
+ 0x26: "9 (",
+ 0x27: "0 )",
+ 0x28: "Return",
+ 0x29: "Esc",
+ 0x2A: "Backspace",
+ 0x2B: "Tab",
+ 0x2C: "Space",
+ 0x2D: "- _",
+ 0x2E: "= +",
+ 0x2F: "[ {",
+ 0x30: "] }",
+ 0x31: "\ |",
+ 0x32: "# ~",
+ 0x33: "; :",
+ 0x34: "\' \"",
+ 0x35: "` ~",
+ 0x36: ", <",
+ 0x37: ". >",
+ 0x38: "/ ?",
+ 0x39: "CapsLock",
+ 0x3A: "F1",
+ 0x3B: "F2",
+ 0x3C: "F3",
+ 0x3D: "F4",
+ 0x3E: "F5",
+ 0x3F: "F6",
+ 0x40: "F7",
+ 0x41: "F8",
+ 0x42: "F9",
+ 0x43: "F10",
+ 0x44: "F11",
+ 0x45: "F12",
+ 0x46: "PrintScreen",
+ 0x47: "ScrollLock",
+ 0x48: "Pause",
+ 0x49: "Insert",
+ 0x4A: "Home",
+ 0x4B: "PageUp",
+ 0x4C: "Delete",
+ 0x4D: "End",
+ 0x4E: "PageDown",
+ 0x4F: "\u2192", # right arrow
+ 0x50: "\u2190", # left arrow
+ 0x51: "\u2193", # down arrow
+ 0x52: "\u2191", # up arrow
+
+ 0x53: "NumLock Clear",
+ 0x54: "/",
+ 0x55: "*",
+ 0x56: "-",
+ 0x57: "+",
+ 0x58: "Enter(kp)",
+ 0x59: "1 End",
+ 0x5A: "2 \u2193", # down arrow
+ 0x5B: "3 PageDown",
+ 0x5C: "4 \u2190", # left arrow
+ 0x5D: "5",
+ 0x5E: "6 \u2192", # right arrow
+ 0x5F: "7 Home",
+ 0x60: "8 \u2191", # up arrow
+ 0x61: "9 PageUp",
+ 0x62: "0 Insert",
+ 0x63: ". Del",
+
+ 0x64: "\ |",
+ 0x65: "Application",
+ 0x66: "Power",
+
+ 0x67: "=",
+
+ 0x68: "F13",
+ 0x69: "F14",
+ 0x6A: "F15",
+ 0x6B: "F16",
+ 0x6C: "F17",
+ 0x6D: "F18",
+ 0x6E: "F19",
+ 0x6F: "F20",
+ 0x70: "F21",
+ 0x71: "F22",
+ 0x72: "F23",
+ 0x73: "F24",
+ 0x74: "Exec",
+ 0x75: "Help",
+ 0x76: "Menu",
+ 0x77: "Select",
+ 0x78: "Stop",
+ 0x79: "Again",
+ 0x7A: "Undo",
+ 0x7B: "Cut",
+ 0x7C: "Copy",
+ 0x7D: "Paste",
+ 0x7E: "Find",
+ 0x7F: "Mute",
+ 0x80: "VolumeUp",
+ 0x81: "VolumeDown",
+ 0x82: "LockingCapsLock",
+ 0x83: "LockingNumLock",
+ 0x84: "LockingScrollLock",
+
+ 0x85: ",",
+ 0x86: "=",
+
+ 0x87: "International1",
+ 0x88: "International2",
+ 0x89: "International3",
+ 0x8A: "International4",
+ 0x8B: "International5",
+ 0x8C: "International6",
+ 0x8D: "International7",
+ 0x8E: "International8",
+ 0x8F: "International9",
+ 0x90: "LANG1",
+ 0x91: "LANG2",
+ 0x92: "LANG3",
+ 0x93: "LANG4",
+ 0x94: "LANG5",
+ 0x95: "LANG6",
+ 0x96: "LANG7",
+ 0x97: "LANG8",
+ 0x98: "LANG9",
+ 0x99: "AlternateErase",
+ 0x9A: "SysReq_Attention",
+ 0x9B: "Cancel",
+ 0x9C: "Clear",
+ 0x9D: "Prior",
+ 0x9E: "Return",
+ 0x9F: "Separator",
+ 0xA0: "Out",
+ 0xA1: "Oper",
+ 0xA2: "Clear_Again",
+ 0xA3: "CrSel_Props",
+ 0xA4: "ExSel",
+
+ 0xB0: "00",
+ 0xB1: "000",
+
+ 0xB2: "Thousands_Sep",
+ 0xB3: "Decimal_Sep",
+ 0xB4: "Currency_Unit",
+ 0xB5: "Currency_Subunit",
+
+ 0xB6: "(",
+ 0xB7: ")",
+ 0xB8: "{",
+ 0xB9: "}",
+
+ 0xBA: "Tab",
+ 0xBB: "Backspace",
+ 0xBC: "A",
+ 0xBD: "B",
+ 0xBE: "C",
+ 0xBF: "D",
+ 0xC0: "E",
+ 0xC1: "F",
+ 0xC2: "XOR",
+ 0xC3: "^",
+ 0xC4: "%",
+ 0xC5: "<",
+ 0xC6: ">",
+ 0xC7: "&",
+ 0xC8: "&&",
+ 0xC9: "|",
+ 0xCA: "||",
+ 0xCB: ":",
+ 0xCC: "#",
+ 0xCD: "Space",
+ 0xCE: "@",
+ 0xCF: "!",
+ 0xD0: "Mem_Store",
+ 0xD1: "Mem_Recall",
+ 0xD2: "Mem_Clear",
+ 0xD3: "Mem_+",
+ 0xD4: "Mem_-",
+ 0xD5: "Mem_*",
+ 0xD6: "Mem_/",
+ 0xD7: "+-",
+ 0xD8: "Clear",
+ 0xD9: "ClearEntry",
+ 0xDA: "Binary",
+ 0xDB: "Octal",
+ 0xDC: "Decimal",
+ 0xDD: "Hexadecimal",
+
+ 0xE0: "LeftControl",
+ 0xE1: "LeftShift",
+ 0xE2: "LeftAlt",
+ 0xE3: "LeftGUI",
+ 0xE4: "RightControl",
+ 0xE5: "RightShift",
+ 0xE6: "RightAlt",
+ 0xE7: "RightGUI",
+ }
+
diff --git a/build-scripts/gen-ui-info.py b/build-scripts/gen-ui-info.py
index 2dbd169..a6df601 100755
--- a/build-scripts/gen-ui-info.py
+++ b/build-scripts/gen-ui-info.py
@@ -33,6 +33,14 @@ The file will contain:
},
...
},
+ "mappings": {
+ "physical-positions": [
+ , ...
+ ],
+ "matrix-positions": [
+ , ...
+ ]
+ },
"miscellaneous": {
"git-commit-date": ,
"git-commit-id": ,
@@ -61,17 +69,13 @@ import sys
# -----------------------------------------------------------------------------
-def gen_static(git_commit_date=None, git_commit_id=None):
+def gen_static(current_date=None, git_commit_date=None, git_commit_id=None):
"""Generate static information"""
- date = None
- if os.name == 'posix':
- date = subprocess.getoutput('date --rfc-3339 s')
-
return {
'.meta-data': {
'version': 0, # the format version number
- 'date-generated': date,
+ 'date-generated': current_date,
},
'miscellaneous': {
'git-commit-date': git_commit_date, # should be passed by makefile
@@ -118,42 +122,19 @@ def parse_mapfile(map_file_path):
}
def parse_layout_matrices(f, line):
- """Parse (all 3) layout matrices"""
+ """Parse layout matrix information in the '.map' file"""
- search = re.search(r'0x\S+\s+(0x\S+)', line)
- # (length for (size of, in bytes) a layer of 1 byte objects)
- base_length = int( int( search.group(1), 16 ) / 5 )
+ name = re.search(r'.progmem.data.(_kb_layout\S*)', line).group(1)
- next_lines = ''.join([next(f), next(f), next(f)])
- layout_position = re.search(
- r'(0x\S+)\s+_kb_layout'+'\n', next_lines ) . group(1)
- layout_press_position = re.search(
- r'(0x\S+)\s+_kb_layout_press'+'\n', next_lines ) . group(1)
- layout_release_position = re.search(
- r'(0x\S+)\s+_kb_layout_release'+'\n', next_lines ) . group(1)
- layout_position = int(layout_position, 16)
- layout_press_position = int(layout_press_position, 16)
- layout_release_position = int(layout_release_position, 16)
-
- if not ( layout_position
- and layout_press_position
- and layout_release_position ):
- raise Exception(
- "parse_mapfile: not all layout matrices were found" )
+ search = re.search(r'(0x\S+)\s+(0x\S+)', next(f))
+ position = int( search.group(1), 16 )
+ length = int( search.group(2), 16 )
return {
'layout-matrices': {
- '_kb_layout': {
- 'position': layout_position,
- 'length': base_length,
- },
- '_kb_layout_press': {
- 'position': layout_press_position,
- 'length': base_length * 2,
- },
- '_kb_layout_release': {
- 'position': layout_release_position,
- 'length': base_length * 2,
+ name: {
+ 'position': position,
+ 'length': length,
},
},
}
@@ -179,7 +160,7 @@ def parse_mapfile(map_file_path):
return output
-def parse_source_code(source_code_path):
+def find_keyboard_functions(source_code_path):
"""Parse all files in the source directory"""
def read_comments(f, line):
@@ -260,13 +241,13 @@ def parse_source_code(source_code_path):
},
}
- # --- parse_source_code() ---
+ # --- find_keyboard_functions() ---
# normalize paths
- source_dir_path = os.path.abspath(source_code_path)
+ source_code_path = os.path.abspath(source_code_path)
# check paths
if not os.path.exists(source_code_path):
- raise ValueError("invalid 'source_dir_path' given")
+ raise ValueError("invalid 'source_code_path' given")
output = {}
@@ -292,6 +273,24 @@ def parse_source_code(source_code_path):
return output
+
+def find_mappings(matrix_file_path):
+ # normalize paths
+ matrix_file_path = os.path.abspath(matrix_file_path)
+
+ match = re.search(
+ r'#define\s+KB_MATRIX_LAYER\s*\(([^)]+)\)[^{]*\{\{([^#]+)\}\}',
+ open(matrix_file_path).read(),
+ re.MULTILINE )
+
+ return {
+ "mappings": {
+ "physical-positions": re.findall(r'k..', match.group(1)),
+ "matrix-positions": re.findall(r'k..|na', match.group(2)),
+ },
+ }
+
+
# -----------------------------------------------------------------------------
def dict_merge(a, b):
@@ -320,6 +319,11 @@ def main():
arg_parser = argparse.ArgumentParser(
description = 'Generate project data for use with the UI' )
+ arg_parser.add_argument(
+ '--current-date',
+ help = ( "should be in the format rfc-3339 "
+ + "(e.g. 2006-08-07 12:34:56-06:00)" ),
+ required = True )
arg_parser.add_argument(
'--git-commit-date',
help = ( "should be in the format rfc-3339 "
@@ -337,13 +341,20 @@ def main():
'--source-code-path',
help = "the path to the source code directory",
required = True )
+ arg_parser.add_argument(
+ '--matrix-file-path',
+ help = "the path to the matrix file we're using",
+ required = True )
args = arg_parser.parse_args(sys.argv[1:])
output = {}
- dict_merge(output, gen_static(args.git_commit_date, args.git_commit_id))
+ dict_merge( output, gen_static( args.current_date,
+ args.git_commit_date,
+ args.git_commit_id ) )
dict_merge(output, parse_mapfile(args.map_file_path))
- dict_merge(output, parse_source_code(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_derived(output))
print(json.dumps(output, sort_keys=True, indent=4))
diff --git a/makefile b/makefile
index 9e3149c..9fb19f0 100644
--- a/makefile
+++ b/makefile
@@ -20,13 +20,22 @@
# 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
# 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 := $(NAME)--$(GIT_BRANCH)--$(shell $(DATE) -d "$(GIT_COMMIT_DATE)" +'%Y%m%dT%H%M%S')--$(shell echo $(GIT_COMMIT_ID) | cut -c 1-7)
# the build dir
BUILD := build
@@ -57,10 +66,12 @@ dist:
'../$(BUILD)/$(TARGET)' )
# run secondary build scripts
( ./build-scripts/gen-ui-info.py \
+ --current-date '$(shell $(DATE) --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
( cd '$(BUILD)/$(TARGET)'; \
diff --git a/references.md b/references.md
index c8c3bdb..af504f3 100644
--- a/references.md
+++ b/references.md
@@ -21,7 +21,7 @@
: column by Kevin Ross for Encoder
Includes a short thing about pull-up resistors.
-* [Powering Light Emitting Diodes(LEDs)]
+* [Powering Light Emitting Diodes (LEDs)]
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
Can you use one resistor for multiple parallel LEDs? No. Or, you can, but
it's not the best idea.
@@ -35,6 +35,11 @@
-> [powering LEDs]
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
+* [Notes on LEDs]
+ (http://www.gizmology.net/LEDs.htm)
+ Talks about different types of LEDs, mentioning typical brightnesses,
+ voltages, and other intersting stuff.
+
* [All About Circuits : Reference]
(http://www.allaboutcircuits.com/vol_5/index.html)
Looks like a great collection of info; didn't get to read much of it.
diff --git a/src/keyboard/ergodox/layout/default--matrix-control.h b/src/keyboard/ergodox/layout/default--matrix-control.h
index 9047826..d24c0e7 100644
--- a/src/keyboard/ergodox/layout/default--matrix-control.h
+++ b/src/keyboard/ergodox/layout/default--matrix-control.h
@@ -47,7 +47,7 @@
*/
#ifndef kb_layout_get
- extern uint8_t PROGMEM \
+ extern const uint8_t PROGMEM \
_kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_get(layer,row,column) \
@@ -57,7 +57,7 @@
#endif
#ifndef kb_layout_press_get
- extern void_funptr_t PROGMEM \
+ extern const void_funptr_t PROGMEM \
_kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_press_get(layer,row,column) \
@@ -67,7 +67,7 @@
#endif
#ifndef kb_layout_release_get
- extern void_funptr_t PROGMEM \
+ extern const void_funptr_t PROGMEM \
_kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
#define kb_layout_release_get(layer,row,column) \
diff --git a/src/keyboard/ergodox/layout/qwerty.c b/src/keyboard/ergodox/layout/qwerty.c
index 38d33b5..9159428 100644
--- a/src/keyboard/ergodox/layout/qwerty.c
+++ b/src/keyboard/ergodox/layout/qwerty.c
@@ -41,7 +41,7 @@
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
-uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
+const uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // layout: layer 0: default
// unused
@@ -113,7 +113,7 @@ _ctrlR, 0, _enter,
// ----------------------------------------------------------------------------
-void_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
+const void_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // press: layer 0: default
// unused
@@ -185,7 +185,7 @@ NULL,
// ----------------------------------------------------------------------------
-void_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
+const void_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
// --------------------------------------------------------------------
KB_MATRIX_LAYER( // release: layer 0: default
// unused
diff --git a/src/lib-other/pjrc/usb_keyboard/usb_keyboard.c b/src/lib-other/pjrc/usb_keyboard/usb_keyboard.c
index 6bbd298..bd759dc 100644
--- a/src/lib-other/pjrc/usb_keyboard/usb_keyboard.c
+++ b/src/lib-other/pjrc/usb_keyboard/usb_keyboard.c
@@ -89,7 +89,7 @@ static const uint8_t PROGMEM endpoint_config_table[] = {
// spec and relevant portions of any USB class specifications!
-static uint8_t PROGMEM device_descriptor[] = {
+static const uint8_t PROGMEM device_descriptor[] = {
18, // bLength
1, // bDescriptorType
0x00, 0x02, // bcdUSB
@@ -107,7 +107,7 @@ static uint8_t PROGMEM device_descriptor[] = {
};
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
-static uint8_t PROGMEM keyboard_hid_report_desc[] = {
+static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
0xA1, 0x01, // Collection (Application),
@@ -144,7 +144,7 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = {
#define CONFIG1_DESC_SIZE (9+9+9+7)
#define KEYBOARD_HID_DESC_OFFSET (9+9)
-static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
+static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
9, // bLength;
2, // bDescriptorType;
@@ -191,17 +191,17 @@ struct usb_string_descriptor_struct {
uint8_t bDescriptorType;
int16_t wString[];
};
-static struct usb_string_descriptor_struct PROGMEM string0 = {
+static const struct usb_string_descriptor_struct PROGMEM string0 = {
4,
3,
{0x0409}
};
-static struct usb_string_descriptor_struct PROGMEM string1 = {
+static const struct usb_string_descriptor_struct PROGMEM string1 = {
sizeof(STR_MANUFACTURER),
3,
STR_MANUFACTURER
};
-static struct usb_string_descriptor_struct PROGMEM string2 = {
+static const struct usb_string_descriptor_struct PROGMEM string2 = {
sizeof(STR_PRODUCT),
3,
STR_PRODUCT
@@ -214,7 +214,7 @@ static struct descriptor_list_struct {
uint16_t wIndex;
const uint8_t *addr;
uint8_t length;
-} PROGMEM descriptor_list[] = {
+} const PROGMEM descriptor_list[] = {
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
diff --git a/src/makefile b/src/makefile
index 15d1298..70bd3d3 100644
--- a/src/makefile
+++ b/src/makefile
@@ -116,11 +116,6 @@ all: $(TARGET).hex $(TARGET).eep
@echo
$(SIZE) --target=$(FORMAT) $(TARGET).eep
@echo
- @echo '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'
- @echo
- $(SIZE) -C --mcu=atmega32u4 $(TARGET).elf
- @echo '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'
- @echo
@echo 'you can load "$(TARGET).hex" and "$(TARGET).eep" onto the'
@echo 'Teensy using the Teensy loader'
@echo