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
Ben Blazak 2012-12-20 15:24:43 -08:00
parent 778e400868
commit 5ed574cd85
8 changed files with 0 additions and 3911 deletions

View File

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

View File

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

View File

@ -1,3 +0,0 @@
function keyclick(position, layer) {
}

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 94 KiB

View File

@ -1,2 +0,0 @@
This directory is for projects closely related to the firmware.

118
makefile
View File

@ -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
View File

@ -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&sup2;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 &copy; 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>

View File

@ -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&sup2;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&sup2;C
* [Arduino I&sup2;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 &copy; 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>