removed some more of the old files
(i may put some back, eventually, but right now i'm trying to clean stuff out)partial-rewrite
parent
778e400868
commit
5ed574cd85
|
@ -1,423 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------
|
||||
# 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>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
Generate a depiction of the layout (in html + svg)
|
||||
|
||||
Depends on:
|
||||
- the UI info file (in JSON)
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
class Namespace():
|
||||
pass
|
||||
|
||||
template = Namespace()
|
||||
doc = Namespace()
|
||||
info = Namespace()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
description = "Generate a picture of the firmware's "
|
||||
+ "keyboard layout" )
|
||||
|
||||
arg_parser.add_argument(
|
||||
'--ui-info-file',
|
||||
required = True )
|
||||
|
||||
args = arg_parser.parse_args(sys.argv[1:])
|
||||
|
||||
# constant file paths
|
||||
args.template_svg_file = './build-scripts/gen_layout/template.svg'
|
||||
args.template_js_file = './build-scripts/gen_layout/template.js'
|
||||
|
||||
# normalize paths
|
||||
args.ui_info_file = os.path.abspath(args.ui_info_file)
|
||||
args.template_svg_file = os.path.abspath(args.template_svg_file)
|
||||
args.template_js_file = os.path.abspath(args.template_js_file)
|
||||
|
||||
# set vars
|
||||
doc.main = '' # to store the html document we're generating
|
||||
template.svg = open(args.template_svg_file).read()
|
||||
template.js = open(args.template_js_file).read()
|
||||
info.all = json.loads(open(args.ui_info_file).read())
|
||||
|
||||
info.matrix_positions = info.all['mappings']['matrix-positions']
|
||||
info.matrix_layout = info.all['mappings']['matrix-layout']
|
||||
|
||||
# prefix
|
||||
doc.prefix = ("""
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<script>
|
||||
"""
|
||||
+ template.js +
|
||||
""" </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Firmware Layout</h1>
|
||||
|
||||
<ul>
|
||||
<li>git commit date:
|
||||
<code>""" + info.all['miscellaneous']['git-commit-date'] + """</code></li>
|
||||
<li>git commit id:
|
||||
<code>""" + info.all['miscellaneous']['git-commit-id'] + """</code></li>
|
||||
</ul>
|
||||
|
||||
<h2>Notes</h2>
|
||||
|
||||
<ul>
|
||||
<li>Layer keys are labeled e.g. <code>la 2 +- 2</code>
|
||||
<ul>
|
||||
<li><code>la</code> is for "layer"</li>
|
||||
<li><code>2</code> indicates that the second pair of push|pop functions is
|
||||
being used (differently numbered pairs won't interfere with each
|
||||
other)</li>
|
||||
<li><code>+</code> indicates that the layer is being "pushed" onto the
|
||||
stack at some point, either when the key is pressed or when it is
|
||||
released</li>
|
||||
<li><code>-</code> indicates that the layer is being "popped" off of the
|
||||
stack at some point</li>
|
||||
<li>the last <code>2</code> indicates the layer-number that will be
|
||||
activated on "push".</li>
|
||||
</ul>
|
||||
See the project 'readme.md' file on <a
|
||||
href='https://github.com/benblazak/ergodox-firmware'>the github page</a> as a
|
||||
starting point for learning more about how this firmware implements
|
||||
layers.</li>
|
||||
<br>
|
||||
<li>Shifted keys are labeled with an <code>sh</code> at the beginning. This
|
||||
indicates that a 'Shift' is generated with that keypress, the same as if you
|
||||
had held down 'Shift', and pressed that key.</li>
|
||||
<br>
|
||||
<li><code>(null)</code> indicates that no keypress or keyrelease will be
|
||||
generated for that key, on that layer.</li>
|
||||
<br>
|
||||
<li>Blank keys indicate "transparency": if you press that key on that layer,
|
||||
the key will act as if it was on whatever layer is active below the current
|
||||
one.</li>
|
||||
<br>
|
||||
<li>Some keys may be labled with special functions (like
|
||||
<code>[btldr]</code>, which tells the Teensy to wait for the host to send it
|
||||
a new firmware).</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
""")[1:-1]
|
||||
|
||||
# suffix
|
||||
doc.suffix = ("""
|
||||
</body>
|
||||
</html>
|
||||
|
||||
""")[1:-1]
|
||||
|
||||
# substitute into template
|
||||
# -------
|
||||
# note: this is not general enough to handle any possible layout well, at
|
||||
# the moment. but it should handle more standard ones well. (hopefully
|
||||
# minor) modifications may be necessary on a case by case basis
|
||||
# -------
|
||||
layer_number = -1
|
||||
for (layout, layer) in zip( info.matrix_layout,
|
||||
range(len(info.matrix_layout))):
|
||||
layer_number += 1
|
||||
svg = template.svg
|
||||
for (name, (code, press, release)) \
|
||||
in zip(info.matrix_positions, layout):
|
||||
replace = ''
|
||||
if press == 'kbfun_transparent':
|
||||
replace = ''
|
||||
elif press == 'kbfun_shift_press_release':
|
||||
replace = 'sh ' + keycode_to_string.get(code, '[n/a]')
|
||||
elif press == 'kbfun_jump_to_bootloader':
|
||||
replace = '[btldr]'
|
||||
elif press == 'NULL' and release == 'NULL':
|
||||
replace = '(null)'
|
||||
elif re.search(r'numpad', press+release):
|
||||
replace = '[num]'
|
||||
elif re.search(r'layer', press+release):
|
||||
replace = 'la ' + re.findall(r'\d+', press+release)[0] + ' '
|
||||
if re.search(r'push', press+release):
|
||||
replace += '+'
|
||||
if re.search(r'pop', press+release):
|
||||
replace += '-'
|
||||
replace += ' ' + str(code)
|
||||
else:
|
||||
replace = keycode_to_string.get(code, '[n/a]')
|
||||
|
||||
svg = re.sub(
|
||||
'>'+name+'<', '>'+replace+'<', svg )
|
||||
svg = re.sub(
|
||||
r"\('(" + name + r".*)'\)",
|
||||
r"('\1', " + str(layer) + r")",
|
||||
svg )
|
||||
|
||||
doc.main += '<h2>Layer ' + str(layer_number) + '</h2>\n' + svg
|
||||
|
||||
# change the font size
|
||||
doc.main = re.sub(r'22.5px', '15px', doc.main)
|
||||
|
||||
print(doc.prefix + doc.main + doc.suffix)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
keycode_to_string = {
|
||||
0x01: "Error", # ErrorRollOver
|
||||
0x02: "POSTFail",
|
||||
0x03: "Error", # 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: "Caps",
|
||||
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: "Ins", # Insert
|
||||
0x4A: "Hm", # Home
|
||||
0x4B: "Pg\u2191", # up arrow
|
||||
0x4C: "Delete",
|
||||
0x4D: "End",
|
||||
0x4E: "Pg\u2193", # down arrow
|
||||
0x4F: "\u2192", # right arrow
|
||||
0x50: "\u2190", # left arrow
|
||||
0x51: "\u2193", # down arrow
|
||||
0x52: "\u2191", # up arrow
|
||||
|
||||
0x53: "Num",
|
||||
0x54: "/",
|
||||
0x55: "*",
|
||||
0x56: "-",
|
||||
0x57: "+",
|
||||
0x58: "Enter",
|
||||
0x59: "1 End",
|
||||
0x5A: "2 \u2193", # down arrow
|
||||
0x5B: "3 Pg\u2193", # down arrow
|
||||
0x5C: "4 \u2190", # left arrow
|
||||
0x5D: "5",
|
||||
0x5E: "6 \u2192", # right arrow
|
||||
0x5F: "7 Hm", # Home
|
||||
0x60: "8 \u2191", # up arrow
|
||||
0x61: "9 Pg\u2191", # up arrow
|
||||
0x62: "0 Ins", # Insert
|
||||
0x63: ". Del",
|
||||
|
||||
0x64: "\ |",
|
||||
0x65: "App",
|
||||
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: "VolUp",
|
||||
0x81: "VolDown",
|
||||
0x82: "LockingCapsLock",
|
||||
0x83: "LockingNumLock",
|
||||
0x84: "LockingScrollLock",
|
||||
|
||||
0x85: ",",
|
||||
0x86: "=",
|
||||
|
||||
0x87: "Int1",
|
||||
0x88: "Int2",
|
||||
0x89: "Int3",
|
||||
0x8A: "Int4",
|
||||
0x8B: "Int5",
|
||||
0x8C: "Int6",
|
||||
0x8D: "Int7",
|
||||
0x8E: "Int8",
|
||||
0x8F: "Int9",
|
||||
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: "$",
|
||||
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: ".",
|
||||
0xDD: "Hexadecimal",
|
||||
|
||||
0xE0: "L-Ctrl",
|
||||
0xE1: "L-Shift",
|
||||
0xE2: "L-Alt",
|
||||
0xE3: "L-GUI",
|
||||
0xE4: "R-Ctrl",
|
||||
0xE5: "R-Shift",
|
||||
0xE6: "R-Alt",
|
||||
0xE7: "R-GUI",
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,475 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------
|
||||
# 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>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
Generate UI info file (in JSON)
|
||||
|
||||
Depends on:
|
||||
- the project source code
|
||||
- the project '.map' file (generated by the compiler)
|
||||
"""
|
||||
|
||||
_FORMAT_DESCRIPTION = ("""
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Version 0
|
||||
* ----------------------------------------------------------------------------
|
||||
* Hopefully the add-hoc conventions are clear enough... I didn't feel like
|
||||
* investing the time in making it a real JSON Schema when there aren't many
|
||||
* validators, and the most current completed draft at the moment (draft 3) is
|
||||
* expired...
|
||||
* ----------------------------------------------------------------------------
|
||||
* Please note that in general, fields may be added without changing the
|
||||
* version number, and that programs using this format are not required to fill
|
||||
* (or read) any of the given fields.
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
var ui_info = {
|
||||
".meta-data": { // for the JSON file
|
||||
"version": "<number>",
|
||||
"date-generated": "<string>", // format: RFC 3339
|
||||
"description": "<string>",
|
||||
},
|
||||
"keyboard-functions": {
|
||||
"<(function name)>": {
|
||||
"position": "<number>", // as given by the .map file
|
||||
"length": "<number>", // as given by the .map file
|
||||
"comments": {
|
||||
"name": "<string>", // more user friendly name
|
||||
"description": "<string>",
|
||||
"notes": [
|
||||
"<string>",
|
||||
"..."
|
||||
],
|
||||
"..."
|
||||
}
|
||||
},
|
||||
"..."
|
||||
},
|
||||
"layout-matrices": {
|
||||
"<(matrix name)>": {
|
||||
"position": "<number>", // as given by the .map file
|
||||
"length": "<number>" // as given by the .map file
|
||||
},
|
||||
"..."
|
||||
},
|
||||
"mappings": {
|
||||
/*
|
||||
* The mappings prefixed with 'matrix' have their elements in the same
|
||||
* order as the .hex file (whatever order that is). The mappings
|
||||
* prefixed with 'physical' will have their elements in an order
|
||||
* corresponding to thier physical position on the keyboard. You can
|
||||
* convert between the two using the relative positions of the key-ids
|
||||
* in 'physical-positions' and 'matrix-positions'.
|
||||
*
|
||||
* The current order of 'physical' mappings is:
|
||||
* --------------------------------------------
|
||||
* // left hand, spatial positions
|
||||
* 00, 01, 02, 03, 04, 05, 06,
|
||||
* 07, 08, 09, 10, 11, 12, 13,
|
||||
* 14, 15, 16, 17, 18, 19,
|
||||
* 20, 21, 22, 23, 24, 25, 26,
|
||||
* 27, 28, 29, 30, 31,
|
||||
* 32, 33,
|
||||
* 34, 35, 36,
|
||||
* 37, 38, 39,
|
||||
|
||||
* // right hand, spatial positions
|
||||
* 40, 41, 42, 43, 44, 45, 46,
|
||||
* 47, 48, 49, 50, 51, 52, 53,
|
||||
* 54, 55, 56, 57, 58, 59,
|
||||
* 60, 61, 62, 63, 64, 65, 66,
|
||||
* 67, 68, 69, 70, 71,
|
||||
* 72, 73,
|
||||
* 74, 75, 76,
|
||||
* 77, 78, 79,
|
||||
* --------------------------------------------
|
||||
*/
|
||||
|
||||
"physical-positions": [ // list of key-ids
|
||||
"<string>", "..."
|
||||
],
|
||||
"matrix-positions": [ // list of key-ids
|
||||
"<string>", "..."
|
||||
],
|
||||
"matrix-layout": [
|
||||
[ // begin layer
|
||||
[ // begin key
|
||||
"<number>", // keycode
|
||||
"<string>", // press function name (ex: 'kbfun_...')
|
||||
"<string>" // release function name (ex: 'NULL')
|
||||
],
|
||||
"..." // more keys
|
||||
],
|
||||
"..." // more layers
|
||||
]
|
||||
},
|
||||
"miscellaneous": {
|
||||
"git-commit-date": "<string>", // format: RFC 3339
|
||||
"git-commit-id": "<string>",
|
||||
"number-of-layers": "<number>"
|
||||
}
|
||||
}
|
||||
""")[1:-1]
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def gen_static(current_date=None, git_commit_date=None, git_commit_id=None):
|
||||
"""Generate static information"""
|
||||
|
||||
return {
|
||||
'.meta-data': {
|
||||
'version': 0, # the format version number
|
||||
'date-generated': current_date,
|
||||
'description': _FORMAT_DESCRIPTION,
|
||||
},
|
||||
'miscellaneous': {
|
||||
'git-commit-date': git_commit_date, # should be passed by makefile
|
||||
'git-commit-id': git_commit_id, # should be passed by makefile
|
||||
},
|
||||
}
|
||||
|
||||
def gen_derived(data):
|
||||
"""
|
||||
Generate derived information
|
||||
Should be called last
|
||||
"""
|
||||
return {
|
||||
'miscellaneous': {
|
||||
'number-of-layers':
|
||||
int( data['layout-matrices']['_kb_layout']['length']/(6*14) ),
|
||||
# because 6*14 is the number of bytes/layer for '_kb_layout'
|
||||
# (which is a uint8_t matrix)
|
||||
},
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def parse_mapfile(map_file_path):
|
||||
"""Parse the '.map' file"""
|
||||
|
||||
def parse_keyboard_function(f, line):
|
||||
"""Parse keyboard-functions in the '.map' file"""
|
||||
|
||||
search = re.search(r'(0x\S+)\s+(0x\S+)', next(f))
|
||||
position = int( search.group(1), 16 )
|
||||
length = int( search.group(2), 16 )
|
||||
|
||||
search = re.search(r'0x\S+\s+(\S+)', next(f))
|
||||
name = search.group(1)
|
||||
|
||||
return {
|
||||
'keyboard-functions': {
|
||||
name: {
|
||||
'position': position,
|
||||
'length': length,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def parse_layout_matrices(f, line):
|
||||
"""Parse layout matrix information in the '.map' file"""
|
||||
|
||||
name = re.search(r'.progmem.data.(_kb_layout\S*)', line).group(1)
|
||||
|
||||
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': {
|
||||
name: {
|
||||
'position': position,
|
||||
'length': length,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# --- parse_mapfile() ---
|
||||
|
||||
# normalize paths
|
||||
map_file_path = os.path.abspath(map_file_path)
|
||||
# check paths
|
||||
if not os.path.exists(map_file_path):
|
||||
raise ValueError("invalid 'map_file_path' given")
|
||||
|
||||
output = {}
|
||||
|
||||
f = open(map_file_path)
|
||||
|
||||
for line in f:
|
||||
if re.search(r'^\s*\.text\.kbfun_', line):
|
||||
dict_merge(output, parse_keyboard_function(f, line))
|
||||
elif re.search(r'^\s*\.progmem\.data.*layout', line):
|
||||
dict_merge(output, parse_layout_matrices(f, line))
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def find_keyboard_functions(source_code_path):
|
||||
"""Parse all files in the source directory"""
|
||||
|
||||
def read_comments(f, line):
|
||||
"""
|
||||
Read in properly formatted multi-line comments
|
||||
- Comments must start with '/*' and end with '*/', each on their own
|
||||
line
|
||||
"""
|
||||
comments = ''
|
||||
while(line.strip() != r'*/'):
|
||||
comments += line[2:].strip()+'\n'
|
||||
line = next(f)
|
||||
return comments
|
||||
|
||||
def parse_comments(comments):
|
||||
"""
|
||||
Parse an INI style comment string
|
||||
- Fields begin with '[field-name]', and continue until the next field,
|
||||
or the end of the comment
|
||||
- Fields '[name]', '[description]', and '[note]' are treated specially
|
||||
"""
|
||||
|
||||
def add_field(output, field, value):
|
||||
"""Put a field+value pair in 'output', the way we want it, if the
|
||||
pair is valid"""
|
||||
|
||||
value = value.strip()
|
||||
|
||||
if field is not None:
|
||||
if field in ('name', 'description'):
|
||||
if field not in output:
|
||||
output[field] = value
|
||||
else:
|
||||
if field == 'note':
|
||||
field = 'notes'
|
||||
|
||||
if field not in output:
|
||||
output[field] = []
|
||||
|
||||
output[field] += [value]
|
||||
|
||||
# --- parse_comments() ---
|
||||
|
||||
output = {}
|
||||
|
||||
field = None
|
||||
value = None
|
||||
for line in comments.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
if re.search(r'^\[.*\]$', line):
|
||||
add_field(output, field, value)
|
||||
field = line[1:-1]
|
||||
value = None
|
||||
|
||||
else:
|
||||
if value is None:
|
||||
value = ''
|
||||
if len(value) > 0 and value[-1] == '.':
|
||||
line = ' '+line
|
||||
value += ' '+line
|
||||
|
||||
add_field(output, field, value)
|
||||
|
||||
return output
|
||||
|
||||
def parse_keyboard_function(f, line, comments):
|
||||
"""Parse keyboard-functions in the source code"""
|
||||
|
||||
search = re.search(r'void\s+(kbfun_\S+)\s*\(void\)', line)
|
||||
name = search.group(1)
|
||||
|
||||
return {
|
||||
'keyboard-functions': {
|
||||
name: {
|
||||
'comments': parse_comments(comments),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# --- find_keyboard_functions() ---
|
||||
|
||||
# normalize paths
|
||||
source_code_path = os.path.abspath(source_code_path)
|
||||
# check paths
|
||||
if not os.path.exists(source_code_path):
|
||||
raise ValueError("invalid 'source_code_path' given")
|
||||
|
||||
output = {}
|
||||
|
||||
for tup in os.walk(source_code_path):
|
||||
for file_name in tup[2]:
|
||||
# normalize paths
|
||||
file_name = os.path.abspath( os.path.join( tup[0], file_name ) )
|
||||
|
||||
# ignore non '.c' files
|
||||
if file_name[-2:] != '.c':
|
||||
continue
|
||||
|
||||
f = open(file_name)
|
||||
|
||||
comments = ''
|
||||
for line in f:
|
||||
if line.strip() == r'/*':
|
||||
comments = read_comments(f, line)
|
||||
elif re.search(r'void\s+kbfun_\S+\s*\(void\)', line):
|
||||
dict_merge(
|
||||
output,
|
||||
parse_keyboard_function(f, line, comments) )
|
||||
|
||||
return output
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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']]
|
||||
# remove the preceeding '&' from function pointers
|
||||
for matrix in ('_kb_layout_press', '_kb_layout_release'):
|
||||
layout[matrix] = \
|
||||
[ [re.sub(r'&', '', el) for el in layer]
|
||||
for layer in layout[matrix] ]
|
||||
|
||||
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) )
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def dict_merge(a, b):
|
||||
"""
|
||||
Recursively merge two dictionaries
|
||||
- I was looking around for an easy way to do this, and found something
|
||||
[here]
|
||||
(http://www.xormedia.com/recursively-merge-dictionaries-in-python.html).
|
||||
This is pretty close, but i didn't copy it exactly.
|
||||
"""
|
||||
|
||||
if not isinstance(a, dict) or not isinstance(b, dict):
|
||||
return b
|
||||
|
||||
for (key, value) in b.items():
|
||||
if key in a:
|
||||
a[key] = dict_merge(a[key], value)
|
||||
else:
|
||||
a[key] = value
|
||||
|
||||
return a
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
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 "
|
||||
+ "(e.g. 2006-08-07 12:34:56-06:00)" ),
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--git-commit-id',
|
||||
help = "the git commit ID",
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--map-file-path',
|
||||
help = "the path to the '.map' file",
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--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 )
|
||||
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:])
|
||||
|
||||
output = {}
|
||||
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, find_keyboard_functions(args.source_code_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))
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
function keyclick(position, layer) {
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 94 KiB |
|
@ -1,2 +0,0 @@
|
|||
This directory is for projects closely related to the firmware.
|
||||
|
118
makefile
118
makefile
|
@ -1,118 +0,0 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# makefile for the ergoDOX project
|
||||
#
|
||||
# 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 (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)
|
||||
# - include the UI stuff (once it's done)
|
||||
# -----------------------------------------------------------------------------
|
||||
# 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>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
include src/makefile-options
|
||||
|
||||
# which layouts to compile (will override the variable in src/makefile-options)
|
||||
# --- default
|
||||
LAYOUT := qwerty-kinesis-mod
|
||||
# --- all
|
||||
LAYOUTS := qwerty-kinesis-mod dvorak-kinesis-mod colemak-symbol-mod
|
||||
|
||||
# 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-)
|
||||
|
||||
# name to use for the final distribution file or package
|
||||
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)--$(LAYOUT)
|
||||
|
||||
# directories
|
||||
BUILD := build
|
||||
ROOT := $(BUILD)/$(TARGET)
|
||||
SCRIPTS := build-scripts
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
.PHONY: all clean checkin build-dir firmware dist zip zip-all
|
||||
|
||||
all: dist
|
||||
|
||||
clean:
|
||||
git clean -dX # remove ignored files and directories
|
||||
-rm -r '$(BUILD)'
|
||||
|
||||
checkin:
|
||||
-git commit -a
|
||||
|
||||
build-dir:
|
||||
-rm -r '$(BUILD)/$(TARGET)'*
|
||||
-mkdir -p '$(BUILD)/$(TARGET)'
|
||||
|
||||
firmware:
|
||||
cd src; $(MAKE) LAYOUT=$(LAYOUT) all
|
||||
|
||||
$(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' \
|
||||
--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 * .* \
|
||||
-x '..*' )
|
||||
|
||||
zip-all:
|
||||
for layout in $(LAYOUTS); do \
|
||||
make LAYOUT=$$layout zip; \
|
||||
done
|
||||
|
311
readme.md
311
readme.md
|
@ -1,311 +0,0 @@
|
|||
# [ergodox-firmware][]: Firmware for the [ErgoDox keyboard][]
|
||||
|
||||
The official website is [ergodox.org] (http://www.ergodox.org).
|
||||
Also see the [geekhack]
|
||||
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard)
|
||||
and [deskthority]
|
||||
(http://deskthority.net/workshop-f7/split-ergonomic-keyboard-project-t1753.html)
|
||||
discussion threads.
|
||||
|
||||
[ergodox-firmware]: https://github.com/benblazak/ergodox-firmware
|
||||
[ergodox keyboard]: http://ergodox.org/
|
||||
|
||||
|
||||
## About This File
|
||||
|
||||
If you're viewing this on github, please note that directory links will only
|
||||
work if you're viewing this from the directory, and file links will only work
|
||||
if you're viewing this as a file. This is true for all the '.md' files here.
|
||||
The limitation is due to the way github addresses directories and files, and
|
||||
the fact that Markdown doesn't have any way (that I know of) to rewrite the
|
||||
URLs as would be required.
|
||||
|
||||
|
||||
## Features (on the ErgoDox)
|
||||
* 6KRO
|
||||
* Teensy 2.0, MCP23018 I/O expander
|
||||
* ~167 Hz scan rate (last time I measured it) (most of which is spent
|
||||
communicating via I²C)
|
||||
* firmware level layers
|
||||
|
||||
|
||||
## About This Project
|
||||
|
||||
If you're just looking for binaries, they can be downloaded [here]
|
||||
[dropbox-download-page].
|
||||
|
||||
If you're just trying to compile, jump to the How To: [Compile the Source Code]
|
||||
(#compile-the-source-code) section.
|
||||
|
||||
Open issues, feature requests, and such are tracked [on github]
|
||||
(/benblazak/ergodox-firmware/issues).
|
||||
|
||||
This project is still definitely a work in progress, but it's getting towards
|
||||
something I'll be happy with when the keyboard finally goes into group buy.
|
||||
The 'master' branch should always contain the most recent "stable" release of
|
||||
the code. The 'dev' branch may have new things, but it may also have
|
||||
expiremental or not yet fixed things. Code on the 'master' branch should also
|
||||
tend to be more thoroughly tested. Please see the source (and especially the
|
||||
accompanying '.md' files) for documentation. And [references.md]
|
||||
(references.md) contains lots of good links, along with descriptions.
|
||||
|
||||
|
||||
## About This Project (more technical)
|
||||
|
||||
If you're looking to hack on the source, or just feel like reading it:
|
||||
|
||||
* The [makefile] (./makefile) and [build-scripts] (./build-scripts) folder in
|
||||
the toplevel directory are for building a collection of files for easy
|
||||
distribution. They are not guaranteed to work on non-Unix systems, and may
|
||||
be (read: are) more hackish than the stuff in [src] (./src). They help me
|
||||
out though.
|
||||
* [src/lib] (src/lib) is for generally useful stuff relating to the firmware.
|
||||
[src/lib-other] (src/lib-other) is for generally useful stuff that I didn't
|
||||
write myself. The TWI and USB libraries are in there, along with the files
|
||||
containing key press and release functions.
|
||||
* [src/keyboard] (src/keyboard) is for keyboard specific stuff. All the chip
|
||||
initialization code is there, along with the layout files, the software
|
||||
matrix to hardware matrix mapping, and hardware specific documentation.
|
||||
* [src/main.c] (src/main.c) ties it all together, and provides a few higher
|
||||
level functions that are useful in the key press and release functions.
|
||||
|
||||
|
||||
A few concepts that might be different:
|
||||
|
||||
* The layer stack
|
||||
|
||||
When activated, layers are pushed onto the top of a stack. When deactivated,
|
||||
layers are popped out from wherever they are in the stack. Layers may be
|
||||
active in the stack more than once. When a keypress occures, the top layer
|
||||
is used to determine what actions to take.
|
||||
|
||||
* Keypresses are functions
|
||||
|
||||
Each time a key is pressed, the "press" function assigned to that key on the
|
||||
current layer is called. When the key is released, the "release" function
|
||||
(from the same layer the key was on when it was pressed) is called. These
|
||||
functions may do pretty much anything - from sending multiple different
|
||||
keypresses to the host, to changing the firmware state in some way, to
|
||||
activating a new layer. They may also be "transparent", i.e. execute the
|
||||
function assigned to the key on the layer one down from the top layer
|
||||
(allowing for layers that are effectively "masks" over whatever layer was
|
||||
active before them).
|
||||
|
||||
|
||||
## Dependencies (for building from source)
|
||||
|
||||
* See the PJRC [Getting Started] (http://pjrc.com/teensy/first_use.html) page
|
||||
for instructions on how to set up an AVR programming environment (be sure to
|
||||
click through all the subsections (in the navigation bar on the left), as
|
||||
there is essential information in each one). This project uses C (not
|
||||
Arduino), and Make. I'm compiling with GNU tools under OS X, but other
|
||||
environments (especially Linux, appropriately set up, or [WinAVR]
|
||||
(http://winavr.sourceforge.net/) under Windows) should work too.
|
||||
|
||||
* I also assume that you are using [git] (http://git-scm.com/) (for `make
|
||||
clean`).
|
||||
|
||||
|
||||
|
||||
## HowTo
|
||||
|
||||
Most of these instructions (or notes, rather) are meant for people who's
|
||||
googling skills and patience are directly proportional to the amount of C
|
||||
programming they don't already know :) . I've done my best to organize and
|
||||
comment things though, so I hope that just about anyone who manages to find
|
||||
their way all the way here will be able to figure out a good deal from context.
|
||||
|
||||
|
||||
### Load Firmware onto the Teensy
|
||||
(beginner)
|
||||
|
||||
Before beginning, make sure:
|
||||
|
||||
* Your Teensy is plugged into your computer via USB
|
||||
|
||||
* You have the appropriate version of [the Teensy loader application]
|
||||
(http://www.pjrc.com/teensy/loader.html) from PJRC installed.
|
||||
|
||||
* You know what the "reset button" (a.k.a. the "tiny pushbutton") on the Teensy
|
||||
is. See the "HalfKay Bootloader Mode" section of the [Teensy First Use]
|
||||
(http://www.pjrc.com/teensy/first_use.html) page on the PJRC website.
|
||||
|
||||
After getting set up:
|
||||
|
||||
* Run the Teensy loader program.
|
||||
* This will give you a window, as shown on the website.
|
||||
|
||||
* Click the "Auto" button on the upper right hand side of the window.
|
||||
* The button will light up brighter green.
|
||||
* This tells the loader program to load its current file whenever the
|
||||
Teensy is ready for it.
|
||||
|
||||
* Locate your '.eep' and '.hex' files.
|
||||
* If you don't have any, you can grab the latest ones [here]
|
||||
[dropbox-download-page] (in a '.zip' file). Choose the newest file who's
|
||||
name contains the name of the keymap you want (look for "qwerty" if
|
||||
you're not sure).
|
||||
|
||||
* Drag and drop the '.eep' file onto the Teensy loader window.
|
||||
* The information bar at the bottom of the window should now read
|
||||
"firmware.eep" followed by the percentage of the Teensy memory that will
|
||||
be used by this file.
|
||||
|
||||
* Press and release the Teensy reset button (a.k.a. the "tiny pushbutton").
|
||||
* The Teensy loader should inform you that it is loading the file. Wait
|
||||
until it's done: it shouldn't take long.
|
||||
|
||||
* Drag and drop the '.hex' file onto the Teensy loader window.
|
||||
|
||||
* Press and release the Teensy reset button (a.k.a. the "tiny pushbutton").
|
||||
|
||||
* Your firmware is now loaded! Press a few buttons on your keyboard to make
|
||||
sure everything worked out all right, and enjoy :)
|
||||
|
||||
Notes:
|
||||
|
||||
* It may not be necessary to load the '.eep' file (if the file is 0 bytes, and
|
||||
the Teensy doesn't have anything loaded into its EEPROM already, it doesn't
|
||||
make any difference), but it's good to do so anyway, just to be safe. It
|
||||
won't hurt anything either way.
|
||||
|
||||
* Now that your firmware is loaded, there should be a keyboard shortcut you can
|
||||
press instead of the Teensy reset button. See the documentation on your
|
||||
layout for more information.
|
||||
|
||||
|
||||
### Change the Direction of the Diodes
|
||||
(intermediate)
|
||||
|
||||
That is, how to change whether the rows or the columns are being driven. This can be done for each side of the keyboard independently.
|
||||
|
||||
* See [src/keyboard/ergodox/options.h] (src/keyboard/ergodox/options.h)
|
||||
|
||||
* After this, you'll need to recompile. See the [About This Project]
|
||||
(#about-this-project) section above.
|
||||
|
||||
|
||||
### Compile the Source Code
|
||||
(brief notes)
|
||||
|
||||
Note: This relates to compiling in the [src] (src) directory. The toplevel
|
||||
build process (for generating the ui-info file and such) isn't really intended
|
||||
to be portable; but you could probably get it working without *too* much
|
||||
trouble, if you're familiar with programming in a Unix environment. I'd
|
||||
suggest looking through the toplevel Makefile, as a staring point, if that's
|
||||
your goal.
|
||||
|
||||
* Read the [Dependencies] (#dependencies-for-building-from-source) section.
|
||||
|
||||
* Take a quickish glance at the [About This Project (more technical)]
|
||||
(#about-this-project-more-technical) section.
|
||||
|
||||
* Navigate to the [src] (src) directory (*not* the toplevel directory) in a
|
||||
terminal, and type `make`.
|
||||
|
||||
* If everything worked, the '.hex' and '.eep' files will be in the [src] (src)
|
||||
directory (where you currently are).
|
||||
|
||||
|
||||
### Create a New Keymap
|
||||
|
||||
* Files to reference:
|
||||
* Keycode macros: see the file
|
||||
[src/lib/usb/usage-page/keyboard--short-names.h]
|
||||
(src/lib/usb/usage-page/keyboard--short-names.h).
|
||||
* See [keyboard.h] (src/lib/usb/usage-page/keyboard.h) for the actual
|
||||
values, with references to the specification.
|
||||
* Keyboard functions: see all files in the folder
|
||||
[src/lib/key-functions/public] (src/lib/key-functions/public).
|
||||
* Template layout files: see the QWERTY keymap source files in the folder
|
||||
[src/keyboard/ergodox/layout] (src/keyboard/ergodox/layout)
|
||||
* Currently [qwerty-kinesis-mod.c]
|
||||
(src/keyboard/ergodox/layout/qwerty-kinesis-mod.c) and
|
||||
[qwerty-kinesis-mod.h]
|
||||
(src/keyboard/ergodox/layout/qwerty-kinesis-mod.h)).
|
||||
* You'll probably want to make a copy of each to use as a template.
|
||||
|
||||
* You will need to set the `LAYOUT` variable in [src/makefile-options]
|
||||
(src/makefile-options) to the base name of your new layout files before you
|
||||
recompile. ('.h' files may be called what you wish, but '.c' files must all
|
||||
have the same prefix (i.e. "base name") or they won't be compiled).
|
||||
|
||||
* Among other things, the '.h' layout file defines the macros that control the
|
||||
meaning of each of the LEDs on the keyboard (capslock, etc.). They may be
|
||||
changed freely (or removed, to disable that LED).
|
||||
|
||||
* The '.c' layout file defines the values (keycode|value, press function,
|
||||
release function) assigned to each key, for each layer.
|
||||
* If a "press" function is set to NULL for a given layer, nothing will be
|
||||
called when the key is pressed on that layer. Likewise for "release"
|
||||
functions. If both are set to `NULL`, nothing will happen when the key
|
||||
is pressed in either event, so it doesn't matter what the keycode|value
|
||||
is for that layer - but you should probably pick something like `0` and
|
||||
stick to it, just for clarity.
|
||||
* The default number of layers is 10 (defined in
|
||||
[default--matrix-control.h]
|
||||
(src/keyboard/ergodox/layout/default--matrix-control.h) - you can
|
||||
override it in the layout's '.h' file, if you like). You don't have to
|
||||
define all of them in the '.c' layout file, just the ones you want (C
|
||||
sets the uninitialized portions of the matrices to 0).
|
||||
* Make sure that in layer-0 **nothing is transparent** (see [About this
|
||||
Project (more technical)] (#about-this-project-more-technical). Behavior
|
||||
is undefined if this occurs (off the top of my head, it'll probably cause
|
||||
an infinite loop - and you'll have to reset your keyboard (unplug it and
|
||||
plug it in again)).
|
||||
* Be careful how you assign things. Pay **close attention** to the
|
||||
possible combinations of keypresses that could occur. It's perfectly
|
||||
possible, for example, to make a layout that can shift to layer 2 (or
|
||||
some layer that doesn't even exist) and can't shift back, or that fails
|
||||
to tell the host when keys are released. It's fairly unlikely that
|
||||
anything bad will happen if you mess up (though you could theoretically
|
||||
generate a sequence of keypresses that accidentally do very bad things on
|
||||
your machine), but it's important to have the possibility in mind.
|
||||
Please consider yourself warned :) .
|
||||
|
||||
|
||||
### Add Code for a Different Type of Keyboard
|
||||
|
||||
* All the function prototypes and macro definitions required by the rest of the
|
||||
code should be in the following files (using the ergodox code as an example):
|
||||
* [controller.h] (src/keyboard/ergodox/controller.h)
|
||||
* [layout.h] (src/keyboard/ergodox/layout.h) (which in the ergodox code
|
||||
only exists to include
|
||||
[layout/default--led-control.h]
|
||||
(src/keyboard/ergodox/layout/default--led-control.h) and
|
||||
[layout/default--matrix-control.h]
|
||||
(src/keyboard/ergodox/layout/default--matrix-control.h))
|
||||
* [matrix.h] (src/keyboard/ergodox/matrix.h)
|
||||
|
||||
* (In broad terms, you'll need to define functions that initialize and update
|
||||
the matrix, LED control macros, macros defining matrix dimensions, and
|
||||
keycode | key-lookup macros (or functions).)
|
||||
|
||||
* You will need to set the `KEYBOARD` variable in [src/makefile-options]
|
||||
(src/makefile-options) to the name of your new keyboard folder before you
|
||||
recompile. You may also wish to change some of the other options in that
|
||||
file.
|
||||
|
||||
* The '.h' files listed above *must* exist, with those names, in the toplevel
|
||||
of your keyboard's directory (e.g. in `src/keyboard/new-keyboard-name`).
|
||||
They may include other '.h' files if you wish to put various definitions or
|
||||
prototypes in other places. They will be included (with the help of some
|
||||
handy macros) in the corresponding files in [src/keyboard] (src/keyboard),
|
||||
which are in turn the files included by "main" and the keyboard functions.
|
||||
|
||||
* If you change the way things are included, be careful for circular includes.
|
||||
"main", the keyboard functions, and the keyboard code all need various
|
||||
parts of each other.
|
||||
|
||||
* Make sure to keep your eye on the `SRC` variable in [src/makefile]
|
||||
(src/makefile), to make sure all your '.c' files are getting compiled.
|
||||
|
||||
|
||||
|
||||
[dropbox-download-page]: https://www.dropbox.com/sh/8bbol6fkvydmtmg/QLudrdEyc9
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 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>
|
||||
|
470
references.md
470
references.md
|
@ -1,470 +0,0 @@
|
|||
## Electronics Stuff
|
||||
|
||||
* [Resistor Color Codes]
|
||||
(http://www.ladyada.net/wiki/lib/exe/fetch.php?hash=a2c6a9&w=501&h=785&media=http%3A%2F%2Fwww.ladyada.net%2Fimages%2Fmetertutorial%2Frescolorcode.jpg)
|
||||
: image
|
||||
|
||||
* from [the Multimeter Tutorial]
|
||||
(http://www.ladyada.net/learn/multimeter/resistance.html)
|
||||
(on <http://ladyada.net/>)
|
||||
|
||||
* [Schematic Symbols]
|
||||
(http://img.docstoccdn.com/thumb/orig/28066054.png)
|
||||
: image
|
||||
|
||||
* [Vcc, Vdd, Vss, etc.]
|
||||
(http://encyclobeamia.solarbotics.net/articles/vxx.html)
|
||||
A neat little discussion of the symbols and where they came from.
|
||||
|
||||
* [Very Basic Circuits]
|
||||
(http://www.seattlerobotics.org/encoder/mar97/basics.html)
|
||||
: column by Kevin Ross for Encoder
|
||||
Includes a short thing about pull-up resistors.
|
||||
|
||||
* [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.
|
||||
|
||||
* can also be reached via <http://thewolfstone.com/>
|
||||
-> [ENTER] ('http://thewolfstone.com/Welcome/Home.html)
|
||||
-> [Wolfstone's Haunted Halloween Page]
|
||||
(http://thewolfstone.com/_ar/Halloween.html)
|
||||
-> [technology]
|
||||
(http://wolfstone.halloweenhost.com/Navigation/TechBase.html)
|
||||
-> [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.
|
||||
|
||||
* [Effects of Varying I2C Pull-Up Resistors]
|
||||
(http://dsscircuits.com/articles/effects-of-varying-i2c-pull-up-resistors.html) : article by Wayne Truchsess
|
||||
Great discussion on the topic, with oscilloscope graphs. The practical
|
||||
takeaway is that 4.7kΩ is a good value for 100kHz I²C, and 2.2kΩ is good
|
||||
for 400kHz.
|
||||
|
||||
|
||||
## C Stuff
|
||||
|
||||
* [comp.lang.c Frequently Asked Questions]
|
||||
(http://c-faq.com/index.html)
|
||||
Really good information, if they happen to address the question you have.
|
||||
|
||||
* [The C Preprocessor]
|
||||
(http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC1)
|
||||
(on <http://gcc.gnu.org/>)
|
||||
One of my main references.
|
||||
|
||||
* [The GNU C Preprocessor]
|
||||
(http://tigcc.ticalc.org/doc/cpp.html#SEC27)
|
||||
A modified version on a different site. Has a few really useful things that
|
||||
I don't think I saw in the official documentation.
|
||||
|
||||
* [C Library Reference]
|
||||
(http://www.cplusplus.com/reference/)
|
||||
(on <http://cplusplus.com>)
|
||||
|
||||
* [C Operators/Expressions]
|
||||
(http://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/CONCEPT/expressions.html)
|
||||
(on <http://www.lix.polytechnique.fr/>)
|
||||
|
||||
* [Bitwise Operators in C and C++: A Tutorial]
|
||||
(http://www.cprogramming.com/tutorial/bitwise_operators.html)
|
||||
(on <http://cprogramming.com/>)
|
||||
|
||||
* [AVR Tutorials - \[TUT\] \[C\] Bit manipulation (AKA "Programming 101")]
|
||||
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=37871&start=0)
|
||||
|
||||
* [In C++ is "const" after type ID acceptable?]
|
||||
(http://stackoverflow.com/questions/988069/in-c-is-const-after-type-id-acceptable)
|
||||
(on <http://stackoverflow.com/>)
|
||||
|
||||
* [Arrays and pointers in C]
|
||||
(http://www.ibiblio.org/pub/languages/fortran/append-c.html)
|
||||
(on <http://www.ibiblio.org/>)
|
||||
|
||||
* [how to use array of function pointers?]
|
||||
(http://stackoverflow.com/questions/252748/how-to-use-array-of-function-pointers)
|
||||
(on <http://stackoverflow.com/>)
|
||||
|
||||
* [The Function Pointer Tutorials]
|
||||
(http://www.newty.de/fpt/index.html)
|
||||
|
||||
* [C preprocessor and concatenation]
|
||||
(http://stackoverflow.com/questions/1489932/c-preprocessor-and-concatenation)
|
||||
(on <http://stackoverflow.com/>)
|
||||
|
||||
* [The New C: Inline Functions]
|
||||
(http://drdobbs.com/184401540)
|
||||
by Randy Meyers
|
||||
(on <http://drdobbs.com/>)
|
||||
|
||||
* [gcc: why the -lm flag is needed to link the math library?]
|
||||
(http://stackoverflow.com/questions/4606301/gcc-why-the-lm-flag-is-needed-to-link-the-math-library)
|
||||
(on <http://stackoverflow.com/>)
|
||||
|
||||
### For the AVR
|
||||
|
||||
* [AVR Newbie guide]
|
||||
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=70673)
|
||||
by stu_san (on <http://www.avrfreaks.net/>)
|
||||
Didn't read much of it, but it looks like a great collection of info.
|
||||
|
||||
* [AVR Libc Library Reference]
|
||||
(http://www.nongnu.org/avr-libc/user-manual/modules.html)
|
||||
One of my main references.
|
||||
|
||||
* [AVR : Data in Program Space]
|
||||
(http://www.nongnu.org/avr-libc/user-manual/pgmspace.html)
|
||||
How to use '<avr/pgmspace.h>'.
|
||||
|
||||
* [avr-libc/include/avr/iom32u4.h]
|
||||
(http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/include/avr/iom32u4.h?revision=2288&root=avr-libc&view=markup)
|
||||
List of registers and associated bit numbers for the ATmega32U4
|
||||
|
||||
* [A Brief Tutorial on Programming the AVR without Arduino]
|
||||
(https://www.mainframe.cx/~ckuethe/avr-c-tutorial/)
|
||||
by Chris Kuethe
|
||||
Goes over a bunch of stuff pretty generally. Useful to me because it was
|
||||
talking about exactly what I was trying to do (e.g. program the thing
|
||||
directly instead of messing around with gratuitous libraries).
|
||||
|
||||
* [Optimisations of AVR programs using avr-gcc]
|
||||
(http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html)
|
||||
About compiling and stuff.
|
||||
|
||||
* [Using the EEPROM memory in AVR-GCC]
|
||||
(http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=38417)
|
||||
: tutorial by [Dean Camera] (http://fourwalledcubicle.com/AboutMe.php)
|
||||
(on <http://www.avrfreaks.net/>)
|
||||
The EEPROM is non-volatile data memory that can withstand 100,000 writes and
|
||||
is byte accessible from within the program. On the Teensy 2.0 there's only
|
||||
1,024 bytes of it though (compared to 32,256 bytes of flash, and 2,560 bytes
|
||||
of RAM), so you have to use it sparingly. It's useful because flash
|
||||
(program) memory is not really something that's meant to be written to (it
|
||||
can only withstand 10,000 writes, and has to be written in pages using
|
||||
instructions meant for the bootloader), and RAM is volatile.
|
||||
|
||||
* updated version available as a pdf at
|
||||
[Four Walled Cubicle : AVR Articles]
|
||||
(http://www.fourwalledcubicle.com/AVRArticles.php), along with a few
|
||||
other good articles on AVR programming
|
||||
|
||||
|
||||
## Protocol Stuff
|
||||
|
||||
### I²C
|
||||
|
||||
* [Arduino I²C Expansion IO]
|
||||
(http://www.neufeld.newton.ks.us/electronics/?p=241)
|
||||
(from [Keith's Electronics Blog]
|
||||
(http://www.neufeld.newton.ks.us/electronics/))
|
||||
Didn't use this much, but it's nice (if you're using the Arduino 'Wire'
|
||||
library), and it has pictures.
|
||||
|
||||
* [Arduino Playground :: Wire Library, Explored]
|
||||
(http://arduino.cc/playground/Main/WireLibraryDetailedReference)
|
||||
More about the Wire library. If you're not using interrupts, I think you'll
|
||||
be better off looking throught the datasheet and writing your own trivial
|
||||
library in C. It really is trivial, almost all the code is in the datasheet
|
||||
(at least for the ATmega32U4), and it'll make more sense to you that way :) .
|
||||
|
||||
### USB
|
||||
|
||||
* About Keyboard [Scan Codes]
|
||||
(http://geekhack.org/showwiki.php?title=Scan+Codes)
|
||||
(on <http://geekhack.org/>)
|
||||
Interesting discussion. For practical purposes, if you're just dealing with
|
||||
USB, you can skip this and go straight to the keyboard usage page in the HID
|
||||
Usage Tables (see below).
|
||||
|
||||
* [USB - boot mode, NKRO, compatibility, etc...]
|
||||
(http://geekhack.org/showthread.php?13162-USB-boot-mode-NKRO-compatibility-etc/page2)
|
||||
: old thread by [Soarer]
|
||||
(http://geekhack.org/member.php?4274-Soarer)
|
||||
(on <http://geekhack.org/>)
|
||||
Discussion about getting NKRO to work over USB and still be compatible with
|
||||
various BIOSs.
|
||||
|
||||
* [USB 2.0 Specification]
|
||||
(http://www.usb.org/developers/docs/usb_20_101111.zip)
|
||||
: zip (from <http://www.usb.org/developers/docs/>)
|
||||
|
||||
* [HID Device Class Definition]
|
||||
(http://www.usb.org/developers/devclass_docs/HID1_11.pdf)
|
||||
: pdf (from <http://www.usb.org/developers/hidpage>)
|
||||
* HID = Human Interface Device
|
||||
|
||||
* [HID Usage Tables]
|
||||
(http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf)
|
||||
: pdf (from <http://www.usb.org/developers/hidpage>)
|
||||
|
||||
|
||||
## Other People's Code
|
||||
|
||||
### Keyboard Firmware
|
||||
|
||||
* zip: [Phantom Firmware from PrinsValium]
|
||||
(http://geekhack.org/attachment.php?attachmentid=38982&d=1327895092)
|
||||
Pretty basic (unless I'm missing nuances, which is entirely possible).
|
||||
Helped me a lot when I was learning how to initialize stuff on the Teensy.
|
||||
|
||||
* mentioned in the [Building Phantom Hardware and Firmware Mods]
|
||||
(http://geekhack.org/showwiki.php?title=Island:26742)
|
||||
article (on <http://geekhack.org/>)
|
||||
|
||||
* github: [tmk / tmk_keyboard]
|
||||
(https://github.com/tmk/tmk_keyboard)
|
||||
Firmware by [hasu] (http://geekhack.org/member.php?3412-hasu) on geekhack.
|
||||
Supports NKRO and mouse movements.
|
||||
|
||||
* forked by [Pyrolistical / tmk_keyboard]
|
||||
(https://github.com/Pyrolistical/tmk_keyboard/tree/master/fourway)
|
||||
|
||||
* mentioned in the [KeyPoard]
|
||||
(http://geekhack.org/showwiki.php?title=Island:26845)
|
||||
article on <http://geekhack.org/>
|
||||
|
||||
* forked by [riffautae / tmk_keyboard]
|
||||
(https://github.com/riffautae/tmk_keyboard)
|
||||
|
||||
* mentioned on the [Teensy Keyboard Firmware Discussion]
|
||||
(http://geekhack.org/showthread.php?26730-Teensy-Keyboard-Firmware-Discussion/page2)
|
||||
thread on <http://geekhack.org/>
|
||||
|
||||
* github: [humblehacker / keyboard]
|
||||
(https://github.com/humblehacker/keyboard)
|
||||
Looks like it has some cool ideas, but I haven't read through it well enough
|
||||
to know what's going on.
|
||||
|
||||
* mentioned on [the humblehacker keyboard website]
|
||||
(http://humblehacker.com/keyboard/)
|
||||
|
||||
* mentioned on [the humblehacker geekhack page]
|
||||
(http://geekhack.org/showwiki.php?title=Island:6292)
|
||||
|
||||
* mentioned on [the designer's blog]
|
||||
(http://humblehacker.com/blog/)
|
||||
|
||||
### USB Libraries
|
||||
|
||||
* [LUFA (2012) (Lightweight USB Framework for AVRs)]
|
||||
(http://www.fourwalledcubicle.com/LUFA.php)
|
||||
Very well known USB library for AVRs. And it looks like it'd be really good
|
||||
too, but the documentation is hard to get into, and the examples don't seem
|
||||
to have enough explanation for me, since I don't have any background in what
|
||||
USB is doing in the first place.
|
||||
|
||||
* zip: [PJRC: usb_keyboard]
|
||||
(http://pjrc.com/teensy/usb_keyboard.zip)
|
||||
From the [LUFA Library : Alternative USB AVR Stacks]
|
||||
(http://www.fourwalledcubicle.com/files/LUFA/Doc/110528/html/_page__alternative_stacks.html)
|
||||
page: "Not so much a complete stack as a collection of USB enabled demos,
|
||||
this library is specifically designed for the PJRC Teensy line of USB AVRs,
|
||||
and thus may need to be modified for other USB AVR chips. These minimal code
|
||||
samples shows the inner workings of the USB controller, without all the
|
||||
abstraction present in most other USB AVR stacks."
|
||||
|
||||
* mentioned on [the PJRC website]
|
||||
(http://pjrc.com/teensy/usb_keyboard.html)
|
||||
|
||||
* [V-USB]
|
||||
(http://vusb.wikidot.com/driver-api)
|
||||
From the [LUFA Library : Alternative USB AVR Stacks]
|
||||
(http://www.fourwalledcubicle.com/files/LUFA/Doc/110528/html/_page__alternative_stacks.html)
|
||||
page: "Well regarded and complete USB 1.1 software stack for several AVR
|
||||
models, implementing Low Speed HID. Used in many commercial and
|
||||
non-commercial designs, with user-submitted projects available for viewing on
|
||||
the company's website. Uses C language code mixed with assembly for
|
||||
time-critical sections."
|
||||
Also, it has really good documentation.
|
||||
|
||||
### TWI Libraries
|
||||
|
||||
* github: [TWI library in C]
|
||||
(https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility)
|
||||
: (arduino / Arduino / libraries / Wire / utility)
|
||||
Well done (as far as I can tell) and complete (includes code for interrupt
|
||||
handling). Meant to be used through the Arduino 'Wire' library interface,
|
||||
but you can use it alone as well. The version on github pulls in a whole
|
||||
bunch of Arduino dependencies though, if you're just going to use the
|
||||
library look for an older version that doesn't (like the one included in the
|
||||
version of Arduino in the Ubuntu 11.10 repos).
|
||||
|
||||
* zip: [i2cmaster]
|
||||
(http://homepage.hispeed.ch/peterfleury/i2cmaster.zip)
|
||||
(by Peter Fleury, on [his homepage]
|
||||
(http://homepage.hispeed.ch/peterfleury/))
|
||||
Good I2C library. Includes stuff both in assembly and C (though, I didn't
|
||||
look at the assembly code). I still think you're better off writing your
|
||||
own, it's not that hard and you'll understand it better. Also, this library
|
||||
is under the GPL (from what it says on his site; couldn't find a licence in
|
||||
the code).
|
||||
|
||||
* forum: [Interfacing MCP23018 io expander via Arduino]
|
||||
(http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282150189)
|
||||
Contains a quick MCP23017 library in C++. Didn't end up looking at it too
|
||||
hard.
|
||||
|
||||
* github: [maniacbug / Arduino / libraries / MCP23018]
|
||||
(https://github.com/maniacbug/Arduino/tree/master/libraries/MCP23018)
|
||||
Library in C++. Don't think I ended up looking through this one at all.
|
||||
|
||||
### Other
|
||||
|
||||
* [Soarer's Converter (XT/AT/PS2/Terminal to USB Converter with NKRO)]
|
||||
(http://geekhack.org/showwiki.php?title=Island:17458)
|
||||
No code for the part that talks over USB though. Code only available for the
|
||||
tools that allow you to change the keymap and stuff, I think.
|
||||
|
||||
* zip: [PJRC: blinky]
|
||||
(http://pjrc.com/teensy/blinky.zip)
|
||||
Little baby example project for the Teensy. Quite nice.
|
||||
|
||||
* mentioned on [the PJRC website]
|
||||
(http://pjrc.com/teensy/gcc.html)
|
||||
|
||||
|
||||
## Hardware Documentation
|
||||
|
||||
* [Microchip: Analog & Interface Product Selector Guide]
|
||||
(http://ww1.microchip.com/downloads/en/DeviceDoc/21060z.pdf)
|
||||
|
||||
* from [the Microchip website (MCP23017 product listing page)]
|
||||
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en023499)
|
||||
|
||||
* [MCP23017 / MCP23S17 Data Sheet]
|
||||
(http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf)
|
||||
|
||||
* from [the Microchip website]
|
||||
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en023499)
|
||||
|
||||
* [MCP23018 / MCP23S18 Data Sheet]
|
||||
(http://ww1.microchip.com/downloads/en/DeviceDoc/22103a.pdf)
|
||||
|
||||
* from [the Microchip website]
|
||||
(http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en537375)
|
||||
|
||||
* [Teensy 2.0 (ATMEGA32U4) Data Sheet]
|
||||
(http://pjrc.com/teensy/atmega32u4.pdf)
|
||||
|
||||
* from [the PJRC website]
|
||||
(http://pjrc.com/teensy/datasheets.html)
|
||||
|
||||
* [Teensy++ 2.0 (AT90USB1286) Data Sheet]
|
||||
(http://pjrc.com/teensy/at90usb1286.pdf)
|
||||
|
||||
* from [the PJRC website]
|
||||
(http://pjrc.com/teensy/datasheets.html)
|
||||
|
||||
* [Teensy 2.0 Pin Assignments, Using C]
|
||||
(http://pjrc.com/teensy/card2a.pdf)
|
||||
|
||||
* from [the PJRC website]
|
||||
(http://pjrc.com/teensy/datasheets.html)
|
||||
|
||||
* [Teensy 2.0 Pin Assignments, Using Arduino]
|
||||
(http://pjrc.com/teensy/card2b.pdf)
|
||||
|
||||
* from [the PJRC website]
|
||||
(http://pjrc.com/teensy/datasheets.html)
|
||||
|
||||
* [Cherry MX Series Keyswitches : Specifications]
|
||||
(http://www.cherrycorp.com/english/switches/key/mx.htm)
|
||||
|
||||
|
||||
## Miscellaneous
|
||||
|
||||
### Keyboard Testing Tools
|
||||
|
||||
* [Understanding Rollover]
|
||||
(http://gadzikowski.com/nkeyrollover.html)
|
||||
Includes 3 different tests (2 of which are web based) to see which keys are
|
||||
actually registering as pressed.
|
||||
|
||||
* mentioned on the [Default:NKey Rollover]
|
||||
(http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results)
|
||||
page (on <http://geekhack.org/>)
|
||||
|
||||
### Typical Keyboard Information
|
||||
|
||||
* [Keyboard Scan Rates]
|
||||
(http://geekhack.org/showwiki.php?title=Keyboard+scan+rates)
|
||||
list (on <http://geekhack.org/>)
|
||||
Keyboards seem to typically scan at rates from a little below 100Hz to about
|
||||
300Hz, with the most common values a little below 100Hz. The [PJRC
|
||||
usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.html) example
|
||||
documentation has a limit of 1000 packets (so 500 presses -> releases) per
|
||||
second, but says that even that speed might overwhelm host software, which
|
||||
expects keystrokes to come much more slowly. And, a debounce time of 5ms
|
||||
(which is the spec'ed high value for Cherry MX switches) would give us a max
|
||||
scan rate of 200Hz.
|
||||
|
||||
### Other Awesome Keyboard Projects
|
||||
|
||||
* [My DIY keyboard collection ( or how I became a KB-geek...)]
|
||||
(http://deskthority.net/workshop-f7/my-diy-keyboard-collection-or-how-i-became-a-kb-geek-t2534.html)
|
||||
: post by [suka] (http://deskthority.net/suka-u434/)
|
||||
on <http://deskthority.net/>
|
||||
If I ever decide to do a keyboard completely by myself, I'm going back to
|
||||
this link and starting with this. Looks really well done.
|
||||
|
||||
* linked to in [a post]
|
||||
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard&p=582593&viewfull=1#post582593)
|
||||
on the ergoDOX geekhack thread
|
||||
|
||||
### Documentation and Design Tools
|
||||
|
||||
* [Markdown: Syntax]
|
||||
(http://daringfireball.net/projects/markdown/syntax)
|
||||
A necessity if your code is on github :) .
|
||||
|
||||
* [KiCAD Tutorial]
|
||||
(http://teholabs.com/knowledge/kicad.html)
|
||||
(on <http://teholabs.com/>)
|
||||
I like the tool. Didn't need the functionality just for a little circuit
|
||||
diagram though, so I forwent the learning curve and used Inkscape.
|
||||
|
||||
* mentioned on the [circuit/block-diagram drawing]
|
||||
(http://stackoverflow.com/questions/6422603/circuit-block-diagram-drawing)
|
||||
question (on <http://stackoverflow.com/>)
|
||||
|
||||
* [Ti<i>k</i>Z and PGF]
|
||||
(http://www.texample.net/tikz/)
|
||||
: a TeX graphics package
|
||||
This is really cool. And I wish i knew more about LaTeX (and all its
|
||||
variations) so that it would have been time effective for me to use it. If I
|
||||
ever need to do automatic diagram generation, I'm going to give this a more
|
||||
serious try.
|
||||
|
||||
* mentioned on the [circuit/block-diagram drawing]
|
||||
(http://stackoverflow.com/questions/6422603/circuit-block-diagram-drawing)
|
||||
question (on <http://stackoverflow.com/>)
|
||||
|
||||
* [Documentation (for version 2010-09-28)]
|
||||
(http://www.texample.net/media/pgf/builds/pgfmanualCVS2010-09-28.pdf)
|
||||
: pdf
|
||||
|
||||
* [Example: Block diagram line junctions]
|
||||
(http://www.texample.net/tikz/examples/line-junctions/)
|
||||
|
||||
* [Inkscape : Connector tool tutorial]
|
||||
(http://wiki.inkscape.org/wiki/index.php/UsingTheConnectorTool)
|
||||
The open source vector graphics tool. Not the _best_ for diagrams (though,
|
||||
see the link; as that tool improves it will hopefully become much better),
|
||||
but it works and I like it :) .
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 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>
|
||||
|
Loading…
Reference in New Issue