candidate for release with keyboard :)
Merge branch 'dev' - changed the way layers are handled! - reorganized a bunch - updated some documentation and such - updated USB IDs - now compiling in OS X (though it *should* still work in linux and windows (except the toplevel build script is unix only) - it's a bug if it doens't) - toplevel build script now generates a lot more, including a bunch of information in JSON meant for the UI, and an html file thats a currently-very-bad picture of the layout that was compiledf13
commit
11c77a15f7
|
@ -0,0 +1,351 @@
|
|||
#! /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>
|
||||
|
||||
""")[1:-1]
|
||||
|
||||
# suffix
|
||||
doc.suffix = ("""
|
||||
</body>
|
||||
</html>
|
||||
|
||||
""")[1:-1]
|
||||
|
||||
# substitute into template
|
||||
for (layout, layer) in zip( info.matrix_layout,
|
||||
range(len(info.matrix_layout))):
|
||||
svg = template.svg
|
||||
for (name, (code, press, release)) \
|
||||
in zip(info.matrix_positions, layout):
|
||||
replace = ''
|
||||
if press == 'kbfun_jump_to_bootloader':
|
||||
replace = '[btldr]'
|
||||
elif re.search(r'layer', press):
|
||||
replace = '[layer]'
|
||||
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 += svg
|
||||
|
||||
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()
|
||||
|
|
@ -0,0 +1,474 @@
|
|||
#! /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
|
||||
},
|
||||
"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()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
function keyclick(position, layer) {
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 94 KiB |
|
@ -1,9 +1,13 @@
|
|||
# The MIT License (MIT)
|
||||
Taken from <http://www.opensource.org/licenses/MIT> on 2012-03-10
|
||||
Retrieved from <http://www.opensource.org/licenses/MIT> on 2012-03-10
|
||||
|
||||
This copyright and licence apply to all files in this project, except where
|
||||
otherwise noted. If you feel that this infringes on any existing intellectual
|
||||
property, please email me at the address below.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
88
makefile
88
makefile
|
@ -4,9 +4,10 @@
|
|||
# This should produce a single file (probably in an archive format) for
|
||||
# distribution, containing everything people will need to use the software.
|
||||
#
|
||||
# DEPENDENCIES: This is unabashedly dependant on various Unix commands, and
|
||||
# therefore probably won't work in a Windows environment. I'm sorry... I
|
||||
# don't know a good portable way to write it.
|
||||
# DEPENDENCIES: This is unabashedly dependant on (the GNU implementation of)
|
||||
# various Unix commands, and therefore probably won't work in a Windows
|
||||
# environment (besides maybe cygwin). Sorry... I don't know a good portable
|
||||
# way to write it.
|
||||
#
|
||||
# TODO:
|
||||
# - include doc files (and maybe render them in html)
|
||||
|
@ -18,23 +19,35 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# the base name of the file or package to distribute
|
||||
NAME := ergodox-firmware
|
||||
# the branch of the git repo we're currently on
|
||||
BRANCH := $(shell git branch -l | grep '*' | cut -c 3-)
|
||||
# a version identifier
|
||||
VERSION := $(shell git log -n 1 | grep 'commit' | cut -c 8-14)--$(shell date +'%Y%m%dT%H%M%S')
|
||||
include src/makefile-options
|
||||
|
||||
# system specific stuff
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME),Darwin)
|
||||
DATE_PROG := gdate
|
||||
else
|
||||
DATE_PROG := date
|
||||
endif
|
||||
|
||||
CURRENT_DATE := $(shell $(DATE_PROG) --rfc-3339 s)
|
||||
|
||||
# git info
|
||||
GIT_BRANCH := $(shell git branch -l | grep '*' | cut -c 3-)
|
||||
GIT_COMMIT_DATE := $(shell git log -n 1 --pretty --date=iso | grep 'Date' | cut -c 9- )
|
||||
GIT_COMMIT_ID := $(shell git log -n 1 | grep 'commit' | cut -c 8-)
|
||||
|
||||
# name to use for the final distribution file or package
|
||||
TARGET := $(NAME)--$(BRANCH)--$(VERSION)
|
||||
TARGET := ergodox-firmware--$(GIT_BRANCH)--$(shell $(DATE_PROG) -d "$(GIT_COMMIT_DATE)" +'%Y%m%dT%H%M%S')--$(shell echo $(GIT_COMMIT_ID) | cut -c 1-7)
|
||||
|
||||
# the build dir
|
||||
# directories
|
||||
BUILD := build
|
||||
ROOT := $(BUILD)/$(TARGET)
|
||||
SCRIPTS := build-scripts
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
.PHONY: all clean dist
|
||||
.PHONY: all clean checkin build-dir firmware dist zip
|
||||
|
||||
all: dist
|
||||
|
||||
|
@ -42,18 +55,51 @@ clean:
|
|||
git clean -dX # remove ignored files and directories
|
||||
-rm -r '$(BUILD)'
|
||||
|
||||
dist:
|
||||
# set up the build dir
|
||||
checkin:
|
||||
-git commit -a
|
||||
|
||||
build-dir:
|
||||
-rm -r '$(BUILD)/$(TARGET)'*
|
||||
-mkdir -p '$(BUILD)/$(TARGET)'
|
||||
# make all subprojects
|
||||
|
||||
firmware:
|
||||
cd src; $(MAKE) all
|
||||
# copy stuff to build dir
|
||||
# --- from src
|
||||
( cd src; \
|
||||
cp firmware.hex firmware.eep firmware.map \
|
||||
'../$(BUILD)/$(TARGET)' )
|
||||
# make into a zip archive
|
||||
|
||||
$(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 * .* \
|
||||
|
|
43
readme.md
43
readme.md
|
@ -1,7 +1,13 @@
|
|||
# [ergodox-firmware][]: Firmware for the [ergoDOX keyboard][]
|
||||
# [ergodox-firmware][]: Firmware for the [ErgoDox keyboard][]
|
||||
|
||||
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://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard
|
||||
[ergodox keyboard]: http://ergodox.org/
|
||||
|
||||
|
||||
## About this File
|
||||
|
@ -40,38 +46,17 @@ started this project), but for now:
|
|||
matrix to hardware matrix mapping, and hardware specific documentation.
|
||||
* [src/main.c] (src/main.c) ties it all together.
|
||||
|
||||
Open issues and such are tracked [on github]
|
||||
Open issues, feature requests, and such are tracked [on github]
|
||||
(/benblazak/ergodox-firmware/issues).
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
### (2012-04-11) (first major release on branch 'main')
|
||||
As of now, it looks like we have a working 6-KRO keyboard firmware for a Teensy
|
||||
2.0 with a MCP23018 I/O expander. It's scanning at ~167 Hz, most of which is
|
||||
spent communicating over I²C. This should be fast enough, I think.
|
||||
Slight improvements might be possible (without finding a microprocessor capable
|
||||
of > 400 kHz I²C or using SPI, that is, which I imagine would speed things
|
||||
up a lot - but it'd also be much less convenient). I'll attempt them if I see
|
||||
the need.
|
||||
|
||||
Also, layers are implemented, but untested, as no keymaps are written to use
|
||||
them yet. Implementing on-keyboard hardware remapping seems like it'd be very
|
||||
possible too, but I'd need to try it (and learn how to programmatically store
|
||||
stuff in program space) to see if it'd work; and I'm not sure of a good way to
|
||||
do the interface, since different people will likely have different keycap
|
||||
layouts on the ergoDOX.
|
||||
|
||||
Getting to N-KRO is a goal, but I honestly have no idea whether it'll be
|
||||
accomplished. Ideally, I'd like a variable-KRO, where the keyboard is 6-KRO
|
||||
till you press the 7th key (so if you're worried about compatibility, just
|
||||
don't press more than 6 keys at a time). From what I've read, it might be
|
||||
possible, but I just finished everything else (so I'm slightly tired), and the
|
||||
USB spec is scary.
|
||||
|
||||
Discussions about the project as a whole are going on at the forum page (linked
|
||||
in the title) so if you have any imput (or want to participate in the group
|
||||
buy!), please stop by. :) .
|
||||
### Features as of 2012-04-11 : first major release on branch 'main'
|
||||
* 6KRO
|
||||
* Teensy 2.0, MCP23018 I/O expander
|
||||
* ~167 Hz scan rate (most of which is spent communicating via I²C)
|
||||
* firmware level layers
|
||||
|
||||
|
||||
## Dependencies (for building from source)
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
: column by Kevin Ross for Encoder
|
||||
Includes a short thing about pull-up resistors.
|
||||
|
||||
* [Powering Light Emitting Diodes(LEDs)]
|
||||
* [Powering Light Emitting Diodes (LEDs)]
|
||||
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
|
||||
Can you use one resistor for multiple parallel LEDs? No. Or, you can, but
|
||||
it's not the best idea.
|
||||
|
@ -35,6 +35,11 @@
|
|||
-> [powering LEDs]
|
||||
(http://wolfstone.halloweenhost.com/Lighting/litlpo_PoweringLEDs.html)
|
||||
|
||||
* [Notes on LEDs]
|
||||
(http://www.gizmology.net/LEDs.htm)
|
||||
Talks about different types of LEDs, mentioning typical brightnesses,
|
||||
voltages, and other intersting stuff.
|
||||
|
||||
* [All About Circuits : Reference]
|
||||
(http://www.allaboutcircuits.com/vol_5/index.html)
|
||||
Looks like a great collection of info; didn't get to read much of it.
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* keyboard specific exports
|
||||
*
|
||||
* Different keyboards are included by modifying a variable in the makefile.
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
#define _str(s) #s // stringify
|
||||
#define _expstr(s) _str(s) // expand -> stringify
|
||||
#define _inc _expstr(keyboard/MAKEFILE_KEYBOARD.h) // inc(lude)
|
||||
#include _inc
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: Teensy 2.0 specific exports : private
|
||||
* controller specific exports
|
||||
*
|
||||
* Files for different keyboards are used by modifying a variable in the
|
||||
* Makefile
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,13 +10,7 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef TEENSY_2_0_h_PRIVATE
|
||||
#define TEENSY_2_0_h_PRIVATE
|
||||
|
||||
#include "matrix.h"
|
||||
|
||||
uint8_t teensy_init(void);
|
||||
uint8_t teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
||||
|
||||
#endif
|
||||
#include "../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/controller.h )
|
||||
#include INCLUDE
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX specific exports
|
||||
* includes (for centralization) the public exports from all subfiles
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef ERGODOX_h
|
||||
#define ERGODOX_h
|
||||
|
||||
#include "lib/data-types.h"
|
||||
|
||||
#include "ergodox/layout.h" // number of layers, layout
|
||||
#include "ergodox/led.h" // logical led controls
|
||||
#include "ergodox/matrix.h" // kb dimensions, matrix status
|
||||
#include "ergodox/teensy-2-0.h" // LED controls
|
||||
|
||||
|
||||
// note:
|
||||
// - see your keyswitch specification for the necessary value. for
|
||||
// cherry mx switches, the switch bounce time is speced to be <= 5ms.
|
||||
// it looks like most switches are speced to be between 5 and 8 ms.
|
||||
// - if timing is important, balance this value with the main() loop
|
||||
// run time (~5ms, last i checked, nearly all of it in the i2c
|
||||
// update() function)
|
||||
#define KB_DEBOUNCE_TIME 5 // in ms
|
||||
|
||||
|
||||
uint8_t kb_init(void);
|
||||
uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]);
|
||||
|
||||
#endif
|
||||
|
|
@ -26,31 +26,33 @@
|
|||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="464.65225"
|
||||
inkscape:cy="203.44926"
|
||||
inkscape:cx="455.81585"
|
||||
inkscape:cy="210.83562"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer7"
|
||||
showgrid="true"
|
||||
inkscape:snap-global="false"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:snap-nodes="false"
|
||||
inkscape:bbox-nodes="false"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="false"
|
||||
inkscape:bbox-paths="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="997"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="852"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox-midpoints="false"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:object-nodes="false"
|
||||
fit-margin-top="15"
|
||||
fit-margin-left="15"
|
||||
fit-margin-bottom="15"
|
||||
fit-margin-right="15"
|
||||
inkscape:snap-page="true">
|
||||
inkscape:snap-page="true"
|
||||
inkscape:snap-object-midpoints="false"
|
||||
inkscape:snap-center="true">
|
||||
<inkscape:grid
|
||||
id="grid3799"
|
||||
type="xygrid"
|
||||
|
@ -719,6 +721,146 @@
|
|||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker11070-18"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11072-9"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker11070-95"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11072-70"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="DotM-10-7-8"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4023-3-6-7"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3526"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3528"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker11070-72"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11072-54"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker11070-51"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11072-99"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker11070-99"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path11072-09"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3618"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3620"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="DotM-10-7-82"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4023-3-6-5"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
<marker
|
||||
inkscape:stockid="DotM"
|
||||
orient="auto"
|
||||
refY="0"
|
||||
refX="0"
|
||||
id="marker3665"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path3667"
|
||||
d="m -2.5,-1 c 0,2.76 -2.24,5 -5,5 -2.76,0 -5,-2.24 -5,-5 0,-2.76 2.24,-5 5,-5 2.76,0 5,2.24 5,5 z"
|
||||
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none;marker-end:none"
|
||||
transform="matrix(0.4,0,0,0.4,2.96,0.4)" />
|
||||
</marker>
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
|
@ -1696,7 +1838,7 @@
|
|||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;stroke:#000077;stroke-width:0.95463163;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#DotM);marker-end:none;display:inline"
|
||||
d="m 381.70056,355.17608 0.005,-8.45211 -6.22824,-2.5329 12.3705,-2.8149 -12.29462,-2.60895 12.14284,-2.74624 -11.99105,-2.81491 11.91516,-2.81491 -5.91963,-2.60894 0,-8.37607 0,-208.83524"
|
||||
d="m 381.70056,356.94385 0.005,-10.21988 -6.22824,-2.5329 12.3705,-2.8149 -12.29462,-2.60895 12.14284,-2.74624 -11.99105,-2.81491 11.91516,-2.81491 -5.91963,-2.60894 0,-8.37607 0,-208.83524"
|
||||
id="path6326-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
|
@ -1768,7 +1910,7 @@
|
|||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000077;stroke-width:0.95463163;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#DotM);marker-end:none;display:inline"
|
||||
d="m 403.37542,355.17608 0.005,-8.45211 -6.22824,-2.5329 12.3705,-2.8149 -12.29462,-2.60895 12.14284,-2.74624 -11.99105,-2.81491 11.91516,-2.81491 -5.91963,-2.60894 0,-8.37607 0,-208.83524"
|
||||
d="m 403.37542,356.76707 0.005,-10.0431 -6.22824,-2.5329 12.3705,-2.8149 -12.29462,-2.60895 12.14284,-2.74624 -11.99105,-2.81491 11.91516,-2.81491 -5.91963,-2.60894 0,-8.37607 0,-208.83524"
|
||||
id="path6326-2-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
|
@ -1840,7 +1982,7 @@
|
|||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000077;stroke-width:0.95463163;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#DotM);marker-end:none;display:inline"
|
||||
d="m 423.37542,355.17608 0.005,-8.45211 -6.22824,-2.5329 12.3705,-2.8149 -12.29462,-2.60895 12.14284,-2.74624 -11.99105,-2.81491 11.91516,-2.81491 -5.91963,-2.60894 0,-8.37607 0,-208.83524"
|
||||
d="m 423.37542,356.94385 0.005,-10.21988 -6.22824,-2.5329 12.3705,-2.8149 -12.29462,-2.60895 12.14284,-2.74624 -11.99105,-2.81491 11.91516,-2.81491 -5.91963,-2.60894 0,-8.37607 0,-208.83524"
|
||||
id="path6326-2-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
|
@ -1924,22 +2066,22 @@
|
|||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#007700;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10)"
|
||||
d="M 255,127.36218 C 297.1005,68.254966 399.98689,51.202007 403.41299,89.442314 l 0.023,4.815736"
|
||||
d="M 255,127.36218 C 297.1005,68.254966 382.48689,65.827007 382.16299,88.692314 l -0.102,5.940736"
|
||||
id="path7504"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#007700;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10);display:inline"
|
||||
d="M 234.96647,127.29296 C 305.92363,44.536037 388.15055,41.329164 381.99597,85.946323 l 0.023,8.346065"
|
||||
d="M 234.96647,127.29296 C 297.17363,43.911037 403.52555,52.704164 403.49597,88.696323 l 0.023,5.721065"
|
||||
id="path7504-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#007700;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10-7)"
|
||||
d="m 195,247.36218 c -4.32571,23.55176 70.95424,57.80762 144.21458,54.72312 9.45484,-5.50003 -1.67061,-20.3897 5.26135,-28.19694 38.00964,-42.80905 6.84799,-181.553227 13.02147,-196.245847 6.17348,-14.69262 -2.21854,-13.634877 3.33961,-21.779094 5.55815,-8.144217 62.33333,-4.615397 62.61183,28.039681 l -0.0815,10.708503"
|
||||
d="m 195,247.36218 c -4.32571,23.55176 70.95424,57.80762 144.21458,54.72312 9.45484,-5.50003 -1.20117,-19.99688 5.26135,-28.19694 25.0471,-31.78137 -5.00774,-173.86807 10.07621,-195.922273 5.69158,-6.64719 1.79635,-9.549128 3.28486,-15.352668 0.97604,-14.654625 65.33333,-6.490397 65.61183,26.164681 l -0.0815,5.833503"
|
||||
id="path7758"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccszzcc" />
|
||||
sodipodi:nodetypes="ccscccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000077;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10-7);marker-end:url(#DotM-10-7)"
|
||||
d="m 95.105862,247.67467 c -2.592497,38.06584 1.233202,73.99227 7.071068,109.24799"
|
||||
|
@ -1987,14 +2129,14 @@
|
|||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff7700;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="433.5"
|
||||
y="341.86218"
|
||||
x="429.96448"
|
||||
y="346.10483"
|
||||
id="text9042"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan9044"
|
||||
x="433.5"
|
||||
y="341.86218">R = 220 Ω</tspan></text>
|
||||
x="429.96448"
|
||||
y="346.10483">R = (match to LEDs)</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff7700;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
|
@ -2079,32 +2221,32 @@
|
|||
y="176.07817"
|
||||
id="tspan9630">PWM</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-8.1837146"
|
||||
inkscape:transform-center-x="5.960441"
|
||||
transform="matrix(0.7776191,-0.62873566,0.62873566,0.7776191,0,0)"
|
||||
inkscape:transform-center-y="-8.3061223"
|
||||
inkscape:transform-center-x="5.7886394"
|
||||
transform="matrix(0.79055013,-0.61239733,0.61239733,0.79055013,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff7700;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="135.67398"
|
||||
y="246.92535"
|
||||
x="140.45497"
|
||||
y="243.17465"
|
||||
id="text9938"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="135.67398"
|
||||
y="246.92535"
|
||||
x="140.45497"
|
||||
y="243.17465"
|
||||
id="tspan9636">PWM</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-3.7250803"
|
||||
inkscape:transform-center-x="-6.0517844"
|
||||
transform="matrix(0.89909256,-0.43775858,0.43775858,0.89909256,0,0)"
|
||||
inkscape:transform-center-y="-3.6387754"
|
||||
inkscape:transform-center-x="-6.1040665"
|
||||
transform="matrix(0.90521688,-0.42494988,0.42494988,0.90521688,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff7700;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="227.65367"
|
||||
y="215.32523"
|
||||
x="221.5656"
|
||||
y="212.97839"
|
||||
id="text9941"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="227.65367"
|
||||
y="215.32523"
|
||||
x="221.5656"
|
||||
y="212.97839"
|
||||
id="tspan9632">PWM</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
|
@ -2172,7 +2314,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-103.45203"
|
||||
y="119.83008"
|
||||
id="tspan12234">row 0</tspan></text>
|
||||
id="tspan12234">row 5</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
|
@ -2184,7 +2326,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-103.45203"
|
||||
y="139.83008"
|
||||
id="tspan12238">row 1</tspan></text>
|
||||
id="tspan12238">row 4</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
|
@ -2196,7 +2338,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-103.45203"
|
||||
y="159.83008"
|
||||
id="tspan12240">row 2</tspan></text>
|
||||
id="tspan12240">row 3</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
|
@ -2208,7 +2350,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-103.45203"
|
||||
y="179.83008"
|
||||
id="tspan12242">row 3</tspan></text>
|
||||
id="tspan12242">row 2</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="10.541016"
|
||||
inkscape:transform-center-x="-20.767578"
|
||||
|
@ -2222,7 +2364,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-103.45203"
|
||||
y="199.83008"
|
||||
id="tspan12244">row 4</tspan></text>
|
||||
id="tspan12244">row 1</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
|
@ -2234,19 +2376,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-103.45203"
|
||||
y="219.83008"
|
||||
id="tspan12248">row 5</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="-63.024292"
|
||||
y="279.83008"
|
||||
id="text12501"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-63.024292"
|
||||
y="279.83008"
|
||||
id="tspan12252">col 0</tspan></text>
|
||||
id="tspan12248">row 0</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
|
@ -2258,19 +2388,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-339.98328"
|
||||
y="299.83008"
|
||||
id="tspan12254">col 1</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="-339.88953"
|
||||
y="319.83008"
|
||||
id="text12507"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-339.88953"
|
||||
y="319.83008"
|
||||
id="tspan12256">col 2</tspan></text>
|
||||
id="tspan12254">col D</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-4.6435547"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
|
@ -2283,7 +2401,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-340.12976"
|
||||
y="259.83008"
|
||||
id="tspan12258">col 3</tspan></text>
|
||||
id="tspan12258">col B</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
|
@ -2295,19 +2413,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-340.41687"
|
||||
y="279.83008"
|
||||
id="tspan12260">col 4</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
x="-63.024292"
|
||||
y="299.83008"
|
||||
id="text12516"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-63.024292"
|
||||
y="299.83008"
|
||||
id="tspan12262">col 5</tspan></text>
|
||||
id="tspan12260">col C</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
|
@ -2319,7 +2425,7 @@
|
|||
sodipodi:role="line"
|
||||
x="-300.33484"
|
||||
y="119.83008"
|
||||
id="tspan12264">col 6</tspan></text>
|
||||
id="tspan12264">col 7</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 135,127.11218 0,-20.5"
|
||||
|
@ -2372,170 +2478,158 @@
|
|||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-280.29382"
|
||||
x="-335.29382"
|
||||
y="539.83008"
|
||||
id="text12519-4"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-280.29382"
|
||||
x="-335.29382"
|
||||
y="539.83008"
|
||||
id="tspan12264-1">col 0</tspan></text>
|
||||
id="tspan12264-1">row 5</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-279.98328"
|
||||
x="-334.98328"
|
||||
y="559.83008"
|
||||
id="text13816"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13492"
|
||||
sodipodi:role="line"
|
||||
x="-279.98328"
|
||||
y="559.83008">col 1</tspan></text>
|
||||
x="-334.98328"
|
||||
y="559.83008">row 4</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-279.88953"
|
||||
x="-334.88953"
|
||||
y="579.83008"
|
||||
id="text13819"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13494"
|
||||
sodipodi:role="line"
|
||||
x="-279.88953"
|
||||
y="579.83008">col 2</tspan></text>
|
||||
x="-334.88953"
|
||||
y="579.83008">row 3</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-280.12976"
|
||||
x="-335.12976"
|
||||
y="599.83008"
|
||||
id="text13822"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13496"
|
||||
sodipodi:role="line"
|
||||
x="-280.12976"
|
||||
y="599.83008">col 3</tspan></text>
|
||||
x="-335.12976"
|
||||
y="599.83008">row 2</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-280.41687"
|
||||
x="-335.41687"
|
||||
y="619.83008"
|
||||
id="text13825"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13498"
|
||||
sodipodi:role="line"
|
||||
x="-280.41687"
|
||||
y="619.83008">col 4</tspan></text>
|
||||
x="-335.41687"
|
||||
y="619.83008">row 1</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-280.04187"
|
||||
x="-335.04187"
|
||||
y="639.83008"
|
||||
id="text13828"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13502"
|
||||
sodipodi:role="line"
|
||||
x="-280.04187"
|
||||
y="639.83008">col 5</tspan></text>
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-280.33484"
|
||||
y="659.83008"
|
||||
id="text13831"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13508"
|
||||
sodipodi:role="line"
|
||||
x="-280.33484"
|
||||
y="659.83008">col 6</tspan></text>
|
||||
x="-335.04187"
|
||||
y="639.83008">row 0</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-3"
|
||||
inkscape:transform-center-x="-20.5"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-112.36218"
|
||||
y="560"
|
||||
x="-112.33308"
|
||||
y="558.26935"
|
||||
id="text12230-8"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-112.36218"
|
||||
y="560"
|
||||
id="tspan12234-5">row B</tspan></text>
|
||||
x="-112.33308"
|
||||
y="558.26935"
|
||||
id="tspan12234-5">col 5</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-3"
|
||||
inkscape:transform-center-x="-20.5"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-113.45203"
|
||||
y="579.83008"
|
||||
x="-113.42294"
|
||||
y="578.09943"
|
||||
id="text13836"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13461"
|
||||
sodipodi:role="line"
|
||||
x="-113.45203"
|
||||
y="579.83008">row A</tspan></text>
|
||||
x="-113.42294"
|
||||
y="578.09943">col 4</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-3"
|
||||
inkscape:transform-center-x="-20.5"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-113.45203"
|
||||
y="599.83008"
|
||||
x="-113.42294"
|
||||
y="598.09943"
|
||||
id="text13839"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13463"
|
||||
sodipodi:role="line"
|
||||
x="-113.45203"
|
||||
y="599.83008">row 9</tspan></text>
|
||||
x="-113.42294"
|
||||
y="598.09943">col 3</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-3"
|
||||
inkscape:transform-center-x="-20.5"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-113.45203"
|
||||
y="619.83008"
|
||||
x="-113.42294"
|
||||
y="618.09943"
|
||||
id="text13842"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13465"
|
||||
sodipodi:role="line"
|
||||
x="-113.45203"
|
||||
y="619.83008">row 8</tspan></text>
|
||||
x="-113.42294"
|
||||
y="618.09943">col 2</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-3"
|
||||
inkscape:transform-center-x="-20.5"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-113.45203"
|
||||
y="639.83008"
|
||||
x="-113.42294"
|
||||
y="638.09943"
|
||||
id="text13845"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13467"
|
||||
sodipodi:role="line"
|
||||
x="-113.45203"
|
||||
y="639.83008">row 7</tspan></text>
|
||||
x="-113.42294"
|
||||
y="638.09943">col 1</tspan></text>
|
||||
<text
|
||||
inkscape:transform-center-y="-3"
|
||||
inkscape:transform-center-x="-20.5"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-112.36218"
|
||||
y="660"
|
||||
x="-112.33308"
|
||||
y="658.26935"
|
||||
id="text13848"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
id="tspan13469"
|
||||
sodipodi:role="line"
|
||||
x="-112.36218"
|
||||
y="660">row 6</tspan></text>
|
||||
x="-112.33308"
|
||||
y="658.26935">col 0</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 275,247.36218 0,59.74443"
|
||||
|
@ -2548,24 +2642,6 @@
|
|||
id="path11780-7-1-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 315,247.36218 0,59.74443"
|
||||
id="path11780-7-1-05"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 275,127.36218 0,-59.744424"
|
||||
id="path11780-7-1-05-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 295,127.36218 0,-59.744424"
|
||||
id="path11780-7-1-05-0-0"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 575,137.36218 0,-20.49999"
|
||||
|
@ -2598,46 +2674,40 @@
|
|||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 575,227.36218 0,20.5"
|
||||
d="m 575,227.36218 0,71.05813"
|
||||
id="path11780-1-5-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 555,227.36218 0,20.49999"
|
||||
d="m 555,227.36218 0,71.05812"
|
||||
id="path11780-1-5-9-4"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 535,227.36218 0,20.49999"
|
||||
d="m 535,227.36218 0,71.05812"
|
||||
id="path11780-1-5-4-5"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 635,227.36218 0,20.5"
|
||||
d="m 635,227.36218 0,71.05813"
|
||||
id="path11780-1-5-2-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 615,227.36218 0,20.49999"
|
||||
d="m 615,227.36218 0,71.05812"
|
||||
id="path11780-1-5-9-4-1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 595,227.36218 0,20.49999"
|
||||
d="m 595,227.36218 0,71.05812"
|
||||
id="path11780-1-5-4-5-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 655,227.36218 0,20.5"
|
||||
id="path11780-1-5-2-8-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
inkscape:transform-center-y="-7.0750605"
|
||||
inkscape:transform-center-x="0.66599259"
|
||||
|
@ -2697,7 +2767,93 @@
|
|||
sodipodi:role="line"
|
||||
x="37.24189"
|
||||
y="405.93091"
|
||||
id="tspan3451">- Row and column assignments are to matrix positions, not physical positions</tspan></text>
|
||||
id="tspan3450">- Row and column assignments are to matrix positions, not physical positions</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 534.99275,137.36829 0,-20.5"
|
||||
id="path11780-1-5-8"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
inkscape:transform-center-y="-3"
|
||||
inkscape:transform-center-x="-20.5"
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-112.3392"
|
||||
y="538.26208"
|
||||
id="text12230-8-3"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-112.3392"
|
||||
y="538.26208"
|
||||
id="tspan12234-5-3">col 6</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#770000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10-7);marker-end:url(#DotM-10-7);display:inline"
|
||||
d="m 275.03546,127.24605 c 0.90412,-34.974223 19.03956,-22.61202 7.77819,-102.530485"
|
||||
id="path8368-9"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-300.46454"
|
||||
y="139.9549"
|
||||
id="text12519-7"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-300.46454"
|
||||
y="139.9549"
|
||||
id="tspan12264-7">col 8</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 135.12482,247.5319 0,20.5"
|
||||
id="path11780-7-17"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-300.39969"
|
||||
y="159.94453"
|
||||
id="text12519-9"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-300.39969"
|
||||
y="159.94453"
|
||||
id="tspan12264-5">col 9</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 155.11445,247.46705 0,20.5"
|
||||
id="path11780-7-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<text
|
||||
transform="matrix(0,-1,1,0,0,0)"
|
||||
xml:space="preserve"
|
||||
style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#aaaa00;fill-opacity:1;stroke:none;display:inline;font-family:Sans"
|
||||
x="-300.52939"
|
||||
y="180.06935"
|
||||
id="text12519-7-1"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
x="-300.52939"
|
||||
y="180.06935"
|
||||
id="tspan12264-7-6">col A</tspan></text>
|
||||
<path
|
||||
style="fill:none;stroke:#aaaa00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#marker11070);display:inline"
|
||||
d="m 175.23927,247.59677 0,20.5"
|
||||
id="path11780-7-17-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000077;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#DotM-10-7);marker-end:url(#DotM-10-7);display:inline"
|
||||
d="m 368.80181,357.18442 c -5.63959,-38.02199 1.04897,-157.80012 0.47542,-235.71113 -0.23179,-31.485746 -54.84564,-32.329723 -54.21554,6.07822"
|
||||
id="path7962-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csc" />
|
||||
</g>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
|
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 158 KiB |
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX specific code: tying it all together
|
||||
* ergoDOX : controller specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,12 +7,13 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "lib/data-types.h"
|
||||
|
||||
#include "ergodox/matrix.h"
|
||||
#include "ergodox/mcp23018--private.h"
|
||||
#include "ergodox/teensy-2-0--private.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "./matrix.h"
|
||||
#include "./controller/mcp23018--functions.h"
|
||||
#include "./controller/teensy-2-0--functions.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
|
@ -0,0 +1,27 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller specific exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__CONTROLLER_h
|
||||
#define KEYBOARD__ERGODOX__CONTROLLER_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "./matrix.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "./controller/teensy-2-0--led.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
uint8_t kb_init(void);
|
||||
uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: MCP23018 specific exports : private
|
||||
* ergoDOX : controller : MCP23018 specific exports : functions
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,14 +7,19 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef MCP23018_h_PRIVATE
|
||||
#define MCP23018_h_PRIVATE
|
||||
#ifndef KEYBOARD__ERGODOX__CONTROLLER__MCP23018__FUNCTIONS_h
|
||||
#define KEYBOARD__ERGODOX__CONTROLLER__MCP23018__FUNCTIONS_h
|
||||
|
||||
#include "lib/data-types.h"
|
||||
#include "matrix.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "../matrix.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define MCP23018_TWI_ADDRESS 0b0100000
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
uint8_t mcp23018_init(void);
|
||||
uint8_t mcp23018_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller: MCP23018 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <util/twi.h>
|
||||
#include "../../../lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
|
||||
#include "../options.h"
|
||||
#include "../matrix.h"
|
||||
#include "./mcp23018--functions.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// check options
|
||||
#if (MCP23018__DRIVE_ROWS && MCP23018__DRIVE_COLUMNS) \
|
||||
|| !(MCP23018__DRIVE_ROWS || MCP23018__DRIVE_COLUMNS)
|
||||
#error "See 'Pin drive direction' in 'options.h'"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// register addresses (see "mcp23018.md")
|
||||
#define IODIRA 0x00 // i/o direction register
|
||||
#define IODIRB 0x01
|
||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||
#define GPPUB 0x0D
|
||||
#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
|
||||
#define GPIOB 0x13
|
||||
#define OLATA 0x14 // output latch register
|
||||
#define OLATB 0x15
|
||||
|
||||
// TWI aliases
|
||||
#define TWI_ADDR_WRITE ( (MCP23018_TWI_ADDRESS<<1) | TW_WRITE )
|
||||
#define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*
|
||||
* notes:
|
||||
* - `twi_stop()` must be called *exactly once* for each twi block, the way
|
||||
* things are currently set up. this may change in the future.
|
||||
*/
|
||||
uint8_t mcp23018_init(void) {
|
||||
uint8_t ret;
|
||||
|
||||
// set pin direction
|
||||
// - unused : input : 1
|
||||
// - input : input : 1
|
||||
// - driving : output : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(IODIRA);
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
twi_send(0b11111111); // IODIRA
|
||||
twi_send(0b11000000); // IODIRB
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
twi_send(0b10000000); // IODIRA
|
||||
twi_send(0b11111111); // IODIRB
|
||||
#endif
|
||||
twi_stop();
|
||||
|
||||
// set pull-up
|
||||
// - unused : on : 1
|
||||
// - input : on : 1
|
||||
// - driving : off : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(GPPUA);
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
twi_send(0b11111111); // GPPUA
|
||||
twi_send(0b11000000); // GPPUB
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
twi_send(0b10000000); // GPPUA
|
||||
twi_send(0b11111111); // GPPUB
|
||||
#endif
|
||||
twi_stop();
|
||||
|
||||
// set logical value (doesn't matter on inputs)
|
||||
// - unused : hi-Z : 1
|
||||
// - input : hi-Z : 1
|
||||
// - driving : hi-Z : 1
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(OLATA);
|
||||
twi_send(0b11111111); //OLATA
|
||||
twi_send(0b11111111); //OLATB
|
||||
|
||||
out:
|
||||
twi_stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*/
|
||||
#if KB_ROWS != 6 || KB_COLUMNS != 14
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
uint8_t mcp23018_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
uint8_t ret, data;
|
||||
|
||||
// initialize things, just to make sure
|
||||
// - it's not appreciably faster to skip this, and it takes care of the
|
||||
// case when the i/o expander isn't plugged in during the first
|
||||
// init()
|
||||
ret = mcp23018_init();
|
||||
|
||||
// if there was an error
|
||||
if (ret) {
|
||||
// clear our part of the matrix
|
||||
for (uint8_t row=0; row<=5; row++)
|
||||
for (uint8_t col=0; col<=6; col++)
|
||||
matrix[row][col] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// update our part of the matrix
|
||||
|
||||
#if MCP23018__DRIVE_ROWS
|
||||
for (uint8_t row=0; row<=5; row++) {
|
||||
// set active row low : 0
|
||||
// set other rows hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_send( 0xFF & ~(1<<(5-row)) );
|
||||
twi_stop();
|
||||
|
||||
// read column data
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_READ);
|
||||
twi_read(&data);
|
||||
twi_stop();
|
||||
|
||||
// update matrix
|
||||
for (uint8_t col=0; col<=6; col++) {
|
||||
matrix[row][col] = !( data & (1<<col) );
|
||||
}
|
||||
}
|
||||
|
||||
// set all rows hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_send(0xFF);
|
||||
twi_stop();
|
||||
|
||||
#elif MCP23018__DRIVE_COLUMNS
|
||||
for (uint8_t col=0; col<=6; col++) {
|
||||
// set active column low : 0
|
||||
// set other columns hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_send( 0xFF & ~(1<<col) );
|
||||
twi_stop();
|
||||
|
||||
// read row data
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_READ);
|
||||
twi_read(&data);
|
||||
twi_stop();
|
||||
|
||||
// update matrix
|
||||
for (uint8_t row=0; row<=5; row++) {
|
||||
matrix[row][col] = !( data & (1<<(5-row)) );
|
||||
}
|
||||
}
|
||||
|
||||
// set all columns hi-Z : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_send(0xFF);
|
||||
twi_stop();
|
||||
|
||||
#endif
|
||||
|
||||
// /update our part of the matrix
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
return ret; // success
|
||||
}
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
## Pinout and Pin assignments
|
||||
|
||||
* `+` indicates pin
|
||||
* `o` indicates unused pin
|
||||
* `+` indicates connected pin
|
||||
* `o` indicates unconnected pin
|
||||
* `=` is used to list other things the pin is connected to
|
||||
* `-`s inserted between some of the pin functions for readability
|
||||
* `OC**` pins enclosed in parenthesis had lines over them in the pinout
|
||||
|
||||
### MCP23018
|
||||
Vss(GND) +01---.---28+ NC
|
||||
|
@ -27,25 +27,26 @@
|
|||
|
||||
power_negative Vss(GND) +01---.---28o NC
|
||||
NC o02 27o GPA7
|
||||
column0 GPB0 +03 26o GPA6
|
||||
column1 GPB1 +04 25+ GPA5 rowB
|
||||
column2 GPB2 +05 24+ GPA4 rowA
|
||||
column3 GPB3 +06 23+ GPA3 row9
|
||||
column4 GPB4 +07 22+ GPA2 row8
|
||||
column5 GPB5 +08 21+ GPA1 row7
|
||||
column6 GPB6 +09 20+ GPA0 row6
|
||||
row_5 GPB0 +03 26+ GPA6 column_6
|
||||
row_4 GPB1 +04 25+ GPA5 column_5
|
||||
row_3 GPB2 +05 24+ GPA4 column_4
|
||||
row_2 GPB3 +06 23+ GPA3 column_3
|
||||
row_1 GPB4 +07 22+ GPA2 column_2
|
||||
row_0 GPB5 +08 21+ GPA1 column_1
|
||||
GPB6 o09 20+ GPA0 column_0
|
||||
GPB7 o10 19o INTA
|
||||
power_positive Vdd(Vcc) +11 18o INTB
|
||||
I2C SCL +12 17o NC
|
||||
I2C SDA +13 16+ RESET (see note)
|
||||
NC o14-------15+ ADDR (see note)
|
||||
I2C SDA +13 16+ RESET = Vdd(Vcc) (see note)
|
||||
NC o14-------15+ ADDR = Vss(GND) (see note)
|
||||
|
||||
* notes:
|
||||
* Row and column assignments are to matrix positions, which may or may
|
||||
correspond to the physical position of the key: e.g. the key where `row4`
|
||||
and `column2` cross will be scanned into the matrix at `[4][2]`, wherever
|
||||
it happens to be located on the keyboard. Mapping from one to the other
|
||||
(which only matters for defining layouts) is handled elsewhere.
|
||||
or may not correspond to the physical position of the key: e.g. the key
|
||||
where `row_4` and `column_2` cross will be scanned into the matrix at
|
||||
`[4][2]`, wherever it happens to be located on the keyboard. Mapping
|
||||
from one to the other (which only matters for defining layouts) is
|
||||
handled elsewhere.
|
||||
* ADDR (pin15): Set slave address to `0b0100000` by connecting to Vss(GND).
|
||||
* The user-defined bits are the three least significant
|
||||
* I2C addresses are 7 bits long (the last bit in the byte is used for
|
||||
|
@ -85,10 +86,10 @@
|
|||
* notes:
|
||||
* All addresses given for IOCON.BANK = 0, since that's the default value of
|
||||
the bit, and that's what we'll be using.
|
||||
* We want the column pins set as output high (hi-Z) without pull-ups
|
||||
initially, and the row pins set as input with pull-ups. We'll cycle
|
||||
through driving the column pins low and checking the row pins in the
|
||||
update function.
|
||||
* Initially, we want either columns or rows (see <../options.h>) set as
|
||||
hi-Z without pull-ups, and the other set of pins set as input with
|
||||
pull-ups. During the update function, we'll cycle through setting the
|
||||
first set low and checking each pin in the second set.
|
||||
|
||||
* abbreviations:
|
||||
* IODIR = I/O Direction Register
|
|
@ -0,0 +1,23 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller : Teensy 2.0 specific exports : functions
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__FUNCTIONS_h
|
||||
#define KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__FUNCTIONS_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "../matrix.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
uint8_t teensy_init(void);
|
||||
uint8_t teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: Teensy 2.0 specific exports
|
||||
* ergoDOX : controller : Teensy 2.0 specific exports : LED control
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,48 +7,52 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef TEENSY_2_0_h
|
||||
#define TEENSY_2_0_h
|
||||
#ifndef KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__LED_h
|
||||
#define KEYBOARD__ERGODOX__CONTROLLER__TEENSY_2_0__LED_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h> // for the register macros
|
||||
#include "lib/data-types.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define _kb_led_1_on() (DDRB |= (1<<5))
|
||||
#define _kb_led_1_off() (DDRB &= ~(1<<5))
|
||||
#define _kb_led_1_set(n) (OCR1A = (uint8_t)(n))
|
||||
#define _kb_led_1_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
|
||||
|
||||
#define _kb_led_2_on() (DDRB |= (1<<6))
|
||||
#define _kb_led_2_off() (DDRB &= ~(1<<6))
|
||||
#define _kb_led_2_set(n) (OCR1B = (uint8_t)(n))
|
||||
#define _kb_led_2_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
|
||||
|
||||
// LED control
|
||||
#define _kb_led_1_on() (DDRB |= (1<<6))
|
||||
#define _kb_led_1_off() (DDRB &= ~(1<<6))
|
||||
#define _kb_led_1_set(n) (OCR1B = (uint8_t)(n))
|
||||
#define _kb_led_1_set_percent(n) (OCR1B = (uint8_t)((n) * 0xFF))
|
||||
//
|
||||
#define _kb_led_2_on() (DDRB |= (1<<5))
|
||||
#define _kb_led_2_off() (DDRB &= ~(1<<5))
|
||||
#define _kb_led_2_set(n) (OCR1A = (uint8_t)(n))
|
||||
#define _kb_led_2_set_percent(n) (OCR1A = (uint8_t)((n) * 0xFF))
|
||||
//
|
||||
#define _kb_led_3_on() (DDRB |= (1<<7))
|
||||
#define _kb_led_3_off() (DDRB &= ~(1<<7))
|
||||
#define _kb_led_3_set(n) (OCR1C = (uint8_t)(n))
|
||||
#define _kb_led_3_set_percent(n) (OCR1C = (uint8_t)((n) * 0xFF))
|
||||
// ---
|
||||
|
||||
|
||||
#define _kb_led_all_on() do { \
|
||||
_kb_led_1_on(); \
|
||||
_kb_led_2_on(); \
|
||||
_kb_led_3_on(); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_off() do { \
|
||||
_kb_led_1_off(); \
|
||||
_kb_led_2_off(); \
|
||||
_kb_led_3_off(); \
|
||||
_kb_led_1_off(); \
|
||||
_kb_led_2_off(); \
|
||||
_kb_led_3_off(); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_set(n) do { \
|
||||
_kb_led_1_set(n); \
|
||||
_kb_led_2_set(n); \
|
||||
_kb_led_3_set(n); \
|
||||
_kb_led_1_set(n); \
|
||||
_kb_led_2_set(n); \
|
||||
_kb_led_3_set(n); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_set_percent(n) do { \
|
||||
_kb_led_1_set_percent(n); \
|
||||
_kb_led_2_set_percent(n); \
|
||||
_kb_led_3_set_percent(n); \
|
||||
_kb_led_1_set_percent(n); \
|
||||
_kb_led_2_set_percent(n); \
|
||||
_kb_led_3_set_percent(n); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,234 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller: Teensy 2.0 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// for "lib/twi.h"
|
||||
#define TWI_FREQ 400000
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include "../../../lib/twi.h"
|
||||
#include "../options.h"
|
||||
#include "../matrix.h"
|
||||
#include "./teensy-2-0--functions.h"
|
||||
#include "./teensy-2-0--led.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// check options
|
||||
#if (TEENSY__DRIVE_ROWS && TEENSY__DRIVE_COLUMNS) \
|
||||
|| !(TEENSY__DRIVE_ROWS || TEENSY__DRIVE_COLUMNS)
|
||||
#error "See 'Pin drive direction' in 'options.h'"
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define CPU_16MHz 0x00
|
||||
#define CPU_8MHz 0x01
|
||||
#define CPU_4MHz 0x02
|
||||
#define CPU_2MHz 0x03
|
||||
#define CPU_1MHz 0x04
|
||||
#define CPU_500kHz 0x05
|
||||
#define CPU_250kHz 0x06
|
||||
#define CPU_125kHz 0x07
|
||||
#define CPU_62kHz 0x08
|
||||
|
||||
|
||||
/*
|
||||
* pin macros
|
||||
* - note: you can move the `UNUSED`, `ROW`, and `COLUMN` pins around, but be
|
||||
* sure to keep the set of all the pins listed constant. other pins are not
|
||||
* movable, and either are referenced explicitly or have macros defined for
|
||||
* them elsewhere.
|
||||
* - note: if you change pin assignments, please be sure to update
|
||||
* "teensy-2-0.md", and the '.svg' circuit diagram.
|
||||
*/
|
||||
|
||||
// --- unused
|
||||
#define UNUSED_0 C, 7
|
||||
#define UNUSED_1 D, 7
|
||||
#define UNUSED_2 D, 4 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_3 D, 5 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_4 E, 6 // hard to use with breadboard (internal)
|
||||
|
||||
// --- rows
|
||||
#define ROW_0 F, 7
|
||||
#define ROW_1 F, 6
|
||||
#define ROW_2 F, 5
|
||||
#define ROW_3 F, 4
|
||||
#define ROW_4 F, 1
|
||||
#define ROW_5 F, 0
|
||||
|
||||
// --- columns
|
||||
#define COLUMN_7 B, 0
|
||||
#define COLUMN_8 B, 1
|
||||
#define COLUMN_9 B, 2
|
||||
#define COLUMN_A B, 3
|
||||
#define COLUMN_B D, 2
|
||||
#define COLUMN_C D, 3
|
||||
#define COLUMN_D C, 6
|
||||
|
||||
// --- helpers
|
||||
#define SET |=
|
||||
#define CLEAR &=~
|
||||
|
||||
#define _teensypin_write(register, operation, pin_letter, pin_number) \
|
||||
do { \
|
||||
((register##pin_letter) operation (1<<(pin_number))); \
|
||||
_delay_us(1); /* allow pins time to stabilize */ \
|
||||
} while(0)
|
||||
#define teensypin_write(register, operation, pin) \
|
||||
_teensypin_write(register, operation, pin)
|
||||
|
||||
#define _teensypin_read(pin_letter, pin_number) \
|
||||
((PIN##pin_letter) & (1<<(pin_number)))
|
||||
#define teensypin_read(pin) \
|
||||
_teensypin_read(pin)
|
||||
|
||||
#define teensypin_write_all_unused(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, UNUSED_0); \
|
||||
teensypin_write(register, operation, UNUSED_1); \
|
||||
teensypin_write(register, operation, UNUSED_2); \
|
||||
teensypin_write(register, operation, UNUSED_3); \
|
||||
teensypin_write(register, operation, UNUSED_4); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_row(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, ROW_0); \
|
||||
teensypin_write(register, operation, ROW_1); \
|
||||
teensypin_write(register, operation, ROW_2); \
|
||||
teensypin_write(register, operation, ROW_3); \
|
||||
teensypin_write(register, operation, ROW_4); \
|
||||
teensypin_write(register, operation, ROW_5); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_column(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, COLUMN_7); \
|
||||
teensypin_write(register, operation, COLUMN_8); \
|
||||
teensypin_write(register, operation, COLUMN_9); \
|
||||
teensypin_write(register, operation, COLUMN_A); \
|
||||
teensypin_write(register, operation, COLUMN_B); \
|
||||
teensypin_write(register, operation, COLUMN_C); \
|
||||
teensypin_write(register, operation, COLUMN_D); } \
|
||||
while(0)
|
||||
|
||||
|
||||
/*
|
||||
* update macros
|
||||
*/
|
||||
#define update_rows_for_column(matrix, column) \
|
||||
do { \
|
||||
/* set column low (set as output) */ \
|
||||
teensypin_write(DDR, SET, COLUMN_##column); \
|
||||
/* read rows 0..5 and update matrix */ \
|
||||
matrix[0x0][0x##column] = ! teensypin_read(ROW_0); \
|
||||
matrix[0x1][0x##column] = ! teensypin_read(ROW_1); \
|
||||
matrix[0x2][0x##column] = ! teensypin_read(ROW_2); \
|
||||
matrix[0x3][0x##column] = ! teensypin_read(ROW_3); \
|
||||
matrix[0x4][0x##column] = ! teensypin_read(ROW_4); \
|
||||
matrix[0x5][0x##column] = ! teensypin_read(ROW_5); \
|
||||
/* set column hi-Z (set as input) */ \
|
||||
teensypin_write(DDR, CLEAR, COLUMN_##column); \
|
||||
} while(0)
|
||||
|
||||
#define update_columns_for_row(matrix, row) \
|
||||
do { \
|
||||
/* set row low (set as output) */ \
|
||||
teensypin_write(DDR, SET, ROW_##row); \
|
||||
/* read columns 7..D and update matrix */ \
|
||||
matrix[0x##row][0x7] = ! teensypin_read(COLUMN_7); \
|
||||
matrix[0x##row][0x8] = ! teensypin_read(COLUMN_8); \
|
||||
matrix[0x##row][0x9] = ! teensypin_read(COLUMN_9); \
|
||||
matrix[0x##row][0xA] = ! teensypin_read(COLUMN_A); \
|
||||
matrix[0x##row][0xB] = ! teensypin_read(COLUMN_B); \
|
||||
matrix[0x##row][0xC] = ! teensypin_read(COLUMN_C); \
|
||||
matrix[0x##row][0xD] = ! teensypin_read(COLUMN_D); \
|
||||
/* set row hi-Z (set as input) */ \
|
||||
teensypin_write(DDR, CLEAR, ROW_##row); \
|
||||
} while(0)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
uint8_t teensy_init(void) {
|
||||
// CPU speed : should match F_CPU in makefile
|
||||
#if F_CPU != 16000000
|
||||
#error "Expecting different CPU frequency"
|
||||
#endif
|
||||
CPU_PRESCALE(CPU_16MHz);
|
||||
|
||||
// onboard LED
|
||||
// (tied to GND for hardware convenience)
|
||||
DDRD &= ~(1<<6); // set D(6) as input
|
||||
PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
|
||||
|
||||
// (tied to Vcc for hardware convenience)
|
||||
DDRB &= ~(1<<4); // set B(4) as input
|
||||
PORTB &= ~(1<<4); // set B(4) internal pull-up disabled
|
||||
|
||||
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
|
||||
_kb_led_all_off(); // (just to put the pins in a known state)
|
||||
TCCR1A = 0b10101001; // set and configure fast PWM
|
||||
TCCR1B = 0b00001001; // set and configure fast PWM
|
||||
|
||||
// I2C (TWI)
|
||||
twi_init(); // on pins D(1,0)
|
||||
|
||||
// unused pins
|
||||
teensypin_write_all_unused(DDR, CLEAR); // set as input
|
||||
teensypin_write_all_unused(PORT, SET); // set internal pull-up enabled
|
||||
|
||||
// rows and columns
|
||||
teensypin_write_all_row(DDR, CLEAR); // set as input (hi-Z)
|
||||
teensypin_write_all_column(DDR, CLEAR); // set as input (hi-Z)
|
||||
#if TEENSY__DRIVE_ROWS
|
||||
teensypin_write_all_row(PORT, CLEAR); // pull-up disabled
|
||||
teensypin_write_all_column(PORT, SET); // pull-up enabled
|
||||
#elif TEENSY__DRIVE_COLUMNS
|
||||
teensypin_write_all_row(PORT, SET); // pull-up enabled
|
||||
teensypin_write_all_column(PORT, CLEAR); // pull-up disabled
|
||||
#endif
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
#if KB_ROWS != 6 || KB_COLUMNS != 14
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
|
||||
uint8_t teensy_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
#if TEENSY__DRIVE_ROWS
|
||||
update_columns_for_row(matrix, 0);
|
||||
update_columns_for_row(matrix, 1);
|
||||
update_columns_for_row(matrix, 2);
|
||||
update_columns_for_row(matrix, 3);
|
||||
update_columns_for_row(matrix, 4);
|
||||
update_columns_for_row(matrix, 5);
|
||||
#elif TEENSY__DRIVE_COLUMNS
|
||||
update_rows_for_column(matrix, 7);
|
||||
update_rows_for_column(matrix, 8);
|
||||
update_rows_for_column(matrix, 9);
|
||||
update_rows_for_column(matrix, A);
|
||||
update_rows_for_column(matrix, B);
|
||||
update_rows_for_column(matrix, C);
|
||||
update_rows_for_column(matrix, D);
|
||||
#endif
|
||||
|
||||
return 0; // success
|
||||
}
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
## Pinout and Pin assignments
|
||||
|
||||
* `+` indicates pin
|
||||
* `o` indicates unused pin
|
||||
* `+` indicates connected pin
|
||||
* `o` indicates unconnected pin
|
||||
* `=` is used to list other things the pin is connected to
|
||||
* `-`s inserted between some of the pin functions for readability
|
||||
* `OC**` pins enclosed in parenthesis had lines over them in the pinout
|
||||
|
||||
|
@ -28,27 +29,30 @@
|
|||
### Teensy 2.0 Pin Assignments
|
||||
|
||||
power_negative GND +---.....---+ Vcc power_positive
|
||||
column6 PB0 + + PF0 row0
|
||||
PB1 o + PF1 row1
|
||||
PB2 o + PF4 row2
|
||||
PB3 o o o + PF5 row3
|
||||
(OC1C) LED3 PB7 + PE6 AREF + PF6 row4
|
||||
(SCL) I2C PD0 + + PF7 row5
|
||||
(SDA) I2C PD1 + + PB6 LED1 (OC1B)
|
||||
column3 PD2 + + PB5 LED2 (OC1A)
|
||||
column4 PD3 + + PB4 column0
|
||||
column1 PC6 + + PD7 column5
|
||||
column2 PC7 +-o-o-o-o-o-+ PD6 onboardLED
|
||||
column_7 PB0 + + PF0 row_5
|
||||
column_8 PB1 + + PF1 row_4
|
||||
column_9 PB2 + + PF4 row_3
|
||||
column_A PB3 + o o + PF5 row_2
|
||||
(OC1C) LED_3 PB7 + PE6 AREF + PF6 row_1
|
||||
(SCL) I2C PD0 + + PF7 row_0
|
||||
(SDA) I2C PD1 + + PB6 LED_2 (OC1B)
|
||||
column_B PD2 + + PB5 LED_1 (OC1A)
|
||||
column_C PD3 + + PB4 = Vcc
|
||||
column_D PC6 + o PD7
|
||||
PC7 o-o-o-o-o-o-+ PD6 onboardLED = GND
|
||||
PD5 --/ | | | \-- PD4
|
||||
Vcc ----/ | \---- RST
|
||||
GND-------/
|
||||
|
||||
* notes:
|
||||
* Row and column assignments are to matrix positions, which may or may
|
||||
correspond to the physical position of the key: e.g. the key where `row4`
|
||||
and `column2` cross will be scanned into the matrix at `[4][2]`, wherever
|
||||
it happens to be located on the keyboard. Mapping from one to the other
|
||||
(which only matters for defining layouts) is handled elsewhere.
|
||||
or may not correspond to the physical position of the key: e.g. the key
|
||||
where `row_4` and `column_2` cross will be scanned into the matrix at
|
||||
`[4][2]`, wherever it happens to be located on the keyboard. Mapping
|
||||
from one to the other (which only matters for defining layouts) is
|
||||
handled elsewhere.
|
||||
* LEDs are labeled using numbers (starting with '1') instead of letters
|
||||
(starting with 'A') as on the PCB.
|
||||
* SCL and SDA: Need external pull-up resistors. Sometimes the Teensy
|
||||
internal pull-ups are enough (see datasheet section 20.5.1), but i think
|
||||
for this project we'll want external ones. The general recommendation
|
||||
|
@ -75,14 +79,16 @@
|
|||
* PD6 (the onboard LED) already has a defined level (low), so there's no
|
||||
reason to set internal pull-up enabled on it. If we do, it will source
|
||||
current to the LED, which is fine, but unnecessary.
|
||||
* We want the columns to be hi-Z when that column's not being scanned,
|
||||
drive low when it is, and the rows to be input with pull-up enabled.
|
||||
We'll cycle through driving the columns low and scanning all rows.
|
||||
* Initially, we want either columns or rows (see <../options.h>) set as
|
||||
hi-Z without pull-ups, and the other set of pins set as input with
|
||||
pull-ups. During the update function, we'll cycle through setting the
|
||||
first set low and checking each pin in the second set.
|
||||
* To set a pin hi-Z on this board, set it as input with pull-up
|
||||
disabled.
|
||||
* Switching the row pins between hi-Z and drive low (treating them as
|
||||
if they were open drain) seems just as good as, and a little safer
|
||||
than, driving them high when the row's not active.
|
||||
* Switching the driving pins (the first set of pins) between hi-Z and
|
||||
drive low (treating them as if they were open drain) seems just as
|
||||
good as, and a little safer than, driving them high when they're not
|
||||
active.
|
||||
* We need to delay for at least 1 μs between changing the column pins and
|
||||
reading the row pins. I would assume this is to allow the pins time to
|
||||
stabalize.
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : exports
|
||||
* ergoDOX : layout exports
|
||||
*
|
||||
* Different layouts are included by modifying a variable in the makefile.
|
||||
* ----------------------------------------------------------------------------
|
||||
|
@ -8,121 +8,16 @@
|
|||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifndef LAYOUT_h
|
||||
#define LAYOUT_h
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include "lib/data-types.h"
|
||||
#include "lib/key-functions.h" // for `kbfun_funptr_t`
|
||||
#ifndef KEYBOARD__ERGODOX__LAYOUT_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT_h
|
||||
|
||||
#include "matrix.h" // for number of rows and columns
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// include the appropriate keyboard layout header
|
||||
// for:
|
||||
// - possible non-default number of layers
|
||||
// - possible non-default layout matrix definitions
|
||||
// - possible non-default layout 'get' and 'set' definitions
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
#define _str(s) #s // stringify
|
||||
#define _expstr(s) _str(s) // expand -> stringify
|
||||
#define _inc _expstr(layout/MAKEFILE_KEYBOARD_LAYOUT.h) // inc(lude)
|
||||
#include _inc
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
|
||||
|
||||
// default number of layers
|
||||
#ifndef KB_LAYERS
|
||||
#define KB_LAYERS 10
|
||||
#endif
|
||||
|
||||
|
||||
// default layout 'get' macros and `extern` matrix declarations
|
||||
//
|
||||
// these are for when the matrices are stored solely in Flash. layouts
|
||||
// may redefine them if they wish and use RAM, EEPROM, or any
|
||||
// combination of the three, as long as they maintain the same
|
||||
// interface.
|
||||
//
|
||||
// - if the macro is overridden, the matrix declaration must be too,
|
||||
// and vice versa.
|
||||
//
|
||||
// - 'set' functions are optional, and should be defined in the layout
|
||||
// specific '.h'. they'll require the use of the EEPROM, possibly in
|
||||
// clever conjunction with one of the other two memories (since the
|
||||
// EEPROM is small). custom key functions will also need to be
|
||||
// written.
|
||||
//
|
||||
// - to override these macros with real functions, set the macro equal
|
||||
// to itself (e.g. `#define kb_layout_get kb_layout_get`) and provide
|
||||
// function prototypes in the layout specific '.h'
|
||||
|
||||
#ifndef kb_layout_get
|
||||
extern uint8_t PROGMEM \
|
||||
_kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
|
||||
|
||||
#define kb_layout_get(layer,row,column) \
|
||||
( (uint8_t) \
|
||||
pgm_read_byte(&( \
|
||||
_kb_layout[layer][row][column] )) )
|
||||
#endif
|
||||
|
||||
#ifndef kb_layout_press_get
|
||||
extern kbfun_funptr_t PROGMEM \
|
||||
_kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS];
|
||||
|
||||
#define kb_layout_press_get(layer,row,column) \
|
||||
( (kbfun_funptr_t) \
|
||||
pgm_read_word(&( \
|
||||
_kb_layout_press[layer][row][column] )) )
|
||||
#endif
|
||||
|
||||
#ifndef kb_layout_release_get
|
||||
extern kbfun_funptr_t PROGMEM \
|
||||
_kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
|
||||
|
||||
#define kb_layout_release_get(layer,row,column) \
|
||||
( (kbfun_funptr_t) \
|
||||
pgm_read_word(&( \
|
||||
_kb_layout_release[layer][row][column] )) )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// default logical LED macros (all defined to nothing)
|
||||
#ifndef kb_led_num_on
|
||||
#define kb_led_num_on()
|
||||
#endif
|
||||
#ifndef kb_led_num_off
|
||||
#define kb_led_num_off()
|
||||
#endif
|
||||
#ifndef kb_led_caps_on
|
||||
#define kb_led_caps_on()
|
||||
#endif
|
||||
#ifndef kb_led_caps_off
|
||||
#define kb_led_caps_off()
|
||||
#endif
|
||||
#ifndef kb_led_scroll_on
|
||||
#define kb_led_scroll_on()
|
||||
#endif
|
||||
#ifndef kb_led_scroll_off
|
||||
#define kb_led_scroll_off()
|
||||
#endif
|
||||
#ifndef kb_led_compose_on
|
||||
#define kb_led_compose_on()
|
||||
#endif
|
||||
#ifndef kb_led_compose_off
|
||||
#define kb_led_compose_off()
|
||||
#endif
|
||||
#ifndef kb_led_kana_on
|
||||
#define kb_led_kana_on()
|
||||
#endif
|
||||
#ifndef kb_led_kana_off
|
||||
#define kb_led_kana_off()
|
||||
#endif
|
||||
#include "../../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./layout/MAKEFILE_KEYBOARD_LAYOUT.h )
|
||||
#include INCLUDE
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -3,33 +3,22 @@
|
|||
Different layouts are included by modifying a variable in the makefile.
|
||||
|
||||
To write a new one:
|
||||
* You must implement everything defined in [layout.h] (layout.h). Take a look
|
||||
at existing layouts in the 'layout' subdir.
|
||||
* Currently, see [qwerty.c] (layout/qwerty.c) and [qwerty.h]
|
||||
(layout/qwerty.h). The latter is only important if you want more than
|
||||
one layer. And I still need to write the functions to make that possible
|
||||
(though that shouldn't be hard, I just haven't gotten to it yet). But
|
||||
(at least for the QWERTY and Dvorak layouts I'd really like to include)
|
||||
if you indicate it clealy in the layout, and provide complete
|
||||
initializations for `kb_layout[][][]`, `kb_layout_press[][][]`, and
|
||||
`kb_layout_release[][][]`, I'll make sure it gets working.
|
||||
* The number of layers must be defined in the layout *.h file.
|
||||
* Create new layout files under [layout] (layout) (see [qwerty.h]
|
||||
(layout/qwerty.h) and [qwerty.c] (layout/qwerty.c)).
|
||||
* Use `0` for no-operation (unused) keys, and `NULL` for no-operation (unused)
|
||||
functions.
|
||||
* See [matrix.md] (matrix.md) for how the key matrix maps to hardware.
|
||||
* See [matrix/mapping.h] (matrix/mapping.h) for how the key matrix maps to
|
||||
hardware.
|
||||
* See [keyboard-usage-page--short-names.h]
|
||||
(../../lib/_usb/keyboard-usage-page--short-names.h) for available keycodes.
|
||||
* See [key-functions.c] (../../lib/_key-functions.c) for what functions keys
|
||||
* See [key-functions.c] (../../lib/key-functions.c) for what functions keys
|
||||
can call.
|
||||
* See [_defaults.h] (layout/_defaults.h) for default function layers and
|
||||
aliases.
|
||||
|
||||
|
||||
## notes
|
||||
|
||||
* Each full layer takes 420 bytes of memory, wherever it's stored. (The matrix
|
||||
size is 12x7, keycodes are 1 byte each, and function pointers are 2 bytes
|
||||
each.)
|
||||
* Each full layer takes 420 bytes of memory (the matrix size is 12x7, keycodes
|
||||
are 1 byte each, and function pointers are 2 bytes each).
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : layout : default LED control
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__LAYOUT__DEFAULT__LED_CONTROL_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT__DEFAULT__LED_CONTROL_h
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* state and delay macros
|
||||
*/
|
||||
|
||||
#ifndef kb_led_state_power_on
|
||||
#define kb_led_state_power_on() do { \
|
||||
_kb_led_all_set_percent(MAKEFILE_LED_BRIGHTNESS/10); \
|
||||
_kb_led_all_on(); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
// note: need to delay for a total of ~1 second
|
||||
#ifndef kb_led_delay_usb_init
|
||||
#define kb_led_delay_usb_init() do { \
|
||||
_kb_led_1_set_percent(MAKEFILE_LED_BRIGHTNESS); \
|
||||
_delay_ms(333); \
|
||||
_kb_led_2_set_percent(MAKEFILE_LED_BRIGHTNESS); \
|
||||
_delay_ms(333); \
|
||||
_kb_led_3_set_percent(MAKEFILE_LED_BRIGHTNESS); \
|
||||
_delay_ms(333); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#ifndef kb_led_state_ready
|
||||
#define kb_led_state_ready() do { \
|
||||
_kb_led_all_off(); \
|
||||
_kb_led_all_set_percent(MAKEFILE_LED_BRIGHTNESS); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* logical LED macros
|
||||
* - unused macros should be defined to nothing
|
||||
* - they all are here, because they really need to be specified in
|
||||
* the layout specific file
|
||||
*/
|
||||
|
||||
#ifndef kb_led_num_on
|
||||
#define kb_led_num_on()
|
||||
#endif
|
||||
#ifndef kb_led_num_off
|
||||
#define kb_led_num_off()
|
||||
#endif
|
||||
#ifndef kb_led_caps_on
|
||||
#define kb_led_caps_on()
|
||||
#endif
|
||||
#ifndef kb_led_caps_off
|
||||
#define kb_led_caps_off()
|
||||
#endif
|
||||
#ifndef kb_led_scroll_on
|
||||
#define kb_led_scroll_on()
|
||||
#endif
|
||||
#ifndef kb_led_scroll_off
|
||||
#define kb_led_scroll_off()
|
||||
#endif
|
||||
#ifndef kb_led_compose_on
|
||||
#define kb_led_compose_on()
|
||||
#endif
|
||||
#ifndef kb_led_compose_off
|
||||
#define kb_led_compose_off()
|
||||
#endif
|
||||
#ifndef kb_led_kana_on
|
||||
#define kb_led_kana_on()
|
||||
#endif
|
||||
#ifndef kb_led_kana_off
|
||||
#define kb_led_kana_off()
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : layout : default matrix control
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__LAYOUT__DEFAULT__MATRIX_CONTROL_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT__DEFAULT__MATRIX_CONTROL_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "../../../lib/data-types/misc.h"
|
||||
#include "../../../lib/key-functions/public.h"
|
||||
#include "../matrix.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef KB_LAYERS
|
||||
#define KB_LAYERS 10
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* matrix 'get' macros, and `extern` matrix declarations
|
||||
*
|
||||
* These are written for when the matrices are stored solely in Flash.
|
||||
* Layouts may redefine them if they wish and use Flash, RAM, EEPROM,
|
||||
* or any combination of the three, as long as they maintain the same
|
||||
* interface.
|
||||
*
|
||||
* - If the macro is overridden, the matrix declaration must be too,
|
||||
* and vice versa.
|
||||
*
|
||||
* - 'set' functions are optional, and should be defined in the layout
|
||||
* specific '.h'. They'll require the use of the EEPROM, possibly in
|
||||
* clever conjunction with one of the other two memories (since the
|
||||
* EEPROM is small). Custom key functions will also need to be
|
||||
* written.
|
||||
*
|
||||
* - To override these macros with real functions, set the macro equal
|
||||
* to itself (e.g. `#define kb_layout_get kb_layout_get`) and provide
|
||||
* function prototypes, in the layout specific '.h'
|
||||
*/
|
||||
|
||||
#ifndef kb_layout_get
|
||||
extern const uint8_t PROGMEM \
|
||||
_kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS];
|
||||
|
||||
#define kb_layout_get(layer,row,column) \
|
||||
( (uint8_t) \
|
||||
pgm_read_byte(&( \
|
||||
_kb_layout[layer][row][column] )) )
|
||||
#endif
|
||||
|
||||
#ifndef kb_layout_press_get
|
||||
extern const void_funptr_t PROGMEM \
|
||||
_kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS];
|
||||
|
||||
#define kb_layout_press_get(layer,row,column) \
|
||||
( (void_funptr_t) \
|
||||
pgm_read_word(&( \
|
||||
_kb_layout_press[layer][row][column] )) )
|
||||
#endif
|
||||
|
||||
#ifndef kb_layout_release_get
|
||||
extern const void_funptr_t PROGMEM \
|
||||
_kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS];
|
||||
|
||||
#define kb_layout_release_get(layer,row,column) \
|
||||
( (void_funptr_t) \
|
||||
pgm_read_word(&( \
|
||||
_kb_layout_release[layer][row][column] )) )
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : QWERTY (modified from the Kinesis layout)
|
||||
* TODO: rewrite for new kbfun's
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "../../../lib/data-types/misc.h"
|
||||
#include "../../../lib/usb/usage-page/keyboard--short-names.h"
|
||||
#include "../../../lib/key-functions/public.h"
|
||||
#include "../matrix.h"
|
||||
#include "../layout.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 0: default
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
_equal, _1, _2, _3, _4, _5, _esc,
|
||||
_backslash, _quote, _comma, _period, _P, _Y, 1,
|
||||
_tab, _A, _O, _E, _U, _I,
|
||||
_shiftL, _semicolon, _Q, _J, _K, _X, 1,
|
||||
_guiL, _grave, _backslash, _arrowL, _arrowR,
|
||||
_bs, 0,
|
||||
_del, 0, _ctrlL,
|
||||
_end, _home, _altL,
|
||||
// right hand
|
||||
3, _6, _7, _8, _9, _0, _dash,
|
||||
_bracketL, _F, _G, _C, _R, _L, _bracketR,
|
||||
_D, _H, _T, _N, _S, _slash,
|
||||
1, _B, _M, _W, _V, _Z, _shiftR,
|
||||
_arrowL, _arrowD, _arrowU, _arrowR, _guiR,
|
||||
0, _space,
|
||||
_ctrlR, 0, _enter,
|
||||
_altR, _pageU, _pageD ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 1: function and symbol keys
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, _F1, _F2, _F3, _F4, _F5, _F11,
|
||||
0, _bracketL, _bracketR, _bracketL, _bracketR, 0, 1,
|
||||
0, _semicolon, _slash, _dash, _0_kp,_semicolon,
|
||||
0, _6_kp, _7_kp, _8_kp, _9_kp, _equal, 2,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
_F12, _F6, _F7, _F8, _F9, _F10, _power,
|
||||
0, 0, _dash, _comma, _period,_currencyUnit, _volumeU,
|
||||
_backslash, _1_kp, _9, _0, _equal, _volumeD,
|
||||
2, _8, _2_kp, _3_kp, _4_kp, _5_kp, _mute,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 2: keyboard functions
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 3: numpad
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, _insert, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
3, 0, 3, _equal_kp, _div_kp, _mul_kp, 0,
|
||||
0, 0, _7_kp, _8_kp, _9_kp, _sub_kp, 0,
|
||||
0, _4_kp, _5_kp, _6_kp, _add_kp, 0,
|
||||
0, 0, _1_kp, _2_kp, _3_kp, _enter_kp, 0,
|
||||
0, 0, _dec_kp, _enter_kp, 0,
|
||||
0, _0_kp,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// aliases
|
||||
|
||||
// basic
|
||||
#define kprrel &kbfun_press_release
|
||||
#define ktog &kbfun_toggle
|
||||
#define ktrans &kbfun_transparent
|
||||
// --- layer push/pop functions
|
||||
#define lpush1 &kbfun_layer_push_1
|
||||
#define lpush2 &kbfun_layer_push_2
|
||||
#define lpush3 &kbfun_layer_push_3
|
||||
#define lpush4 &kbfun_layer_push_4
|
||||
#define lpush5 &kbfun_layer_push_5
|
||||
#define lpush6 &kbfun_layer_push_6
|
||||
#define lpush7 &kbfun_layer_push_7
|
||||
#define lpush8 &kbfun_layer_push_8
|
||||
#define lpush9 &kbfun_layer_push_9
|
||||
#define lpush10 &kbfun_layer_push_10
|
||||
#define lpop1 &kbfun_layer_pop_1
|
||||
#define lpop2 &kbfun_layer_pop_2
|
||||
#define lpop3 &kbfun_layer_pop_3
|
||||
#define lpop4 &kbfun_layer_pop_4
|
||||
#define lpop5 &kbfun_layer_pop_5
|
||||
#define lpop6 &kbfun_layer_pop_6
|
||||
#define lpop7 &kbfun_layer_pop_7
|
||||
#define lpop8 &kbfun_layer_pop_8
|
||||
#define lpop9 &kbfun_layer_pop_9
|
||||
#define lpop10 &kbfun_layer_pop_10
|
||||
// ---
|
||||
|
||||
// device
|
||||
#define dbtldr &kbfun_jump_to_bootloader
|
||||
|
||||
// special
|
||||
#define sshprre &kbfun_shift_press_release
|
||||
#define s2kcap &kbfun_2_keys_capslock_press_release
|
||||
#define slpunum &kbfun_layer_push_numpad
|
||||
#define slponum &kbfun_layer_pop_numpad
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const void_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 0: default
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, lpush1,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
s2kcap, kprrel, kprrel, kprrel, kprrel, kprrel, lpush1,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, NULL,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel,
|
||||
// right hand
|
||||
slpunum, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lpush1, kprrel, kprrel, kprrel, kprrel, kprrel, s2kcap,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
NULL, kprrel,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 1: function and symbol keys
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans,sshprre,sshprre, kprrel, kprrel, NULL, lpop1,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre, lpush2,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, NULL, kprrel,sshprre,sshprre, kprrel, kprrel,
|
||||
kprrel, kprrel,sshprre,sshprre,sshprre, kprrel,
|
||||
lpush2,sshprre, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 2: keyboard functions
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
dbtldr, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
// right hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 3: numpad
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, kprrel, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
slponum, ktrans,slponum, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const void_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 0: default
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, NULL,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
s2kcap, kprrel, kprrel, kprrel, kprrel, kprrel, lpop1,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, NULL,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel,
|
||||
// right hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lpop1, kprrel, kprrel, kprrel, kprrel, kprrel, s2kcap,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
NULL, kprrel,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 1: function and symbol keys
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans,sshprre,sshprre, kprrel, kprrel, NULL, NULL,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre, lpop2,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, NULL, kprrel,sshprre,sshprre, kprrel, kprrel,
|
||||
kprrel, kprrel,sshprre,sshprre,sshprre, kprrel,
|
||||
lpop2,sshprre, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 2: keyboard functions
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
// right hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 3: numpad
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, kprrel, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
NULL, ktrans, NULL, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 3: nothing (just making sure unused
|
||||
// functions don't get compiled out)
|
||||
// unused
|
||||
NULL,
|
||||
// other
|
||||
kprrel, lpush8, lpop8, NULL, NULL, NULL, NULL, NULL,
|
||||
ktog, lpush9, lpop9, NULL, NULL, NULL, NULL, NULL,
|
||||
ktrans,lpush10, lpop10, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush1, lpop1, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush2, lpop2, dbtldr, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush3, lpop3, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush4, lpop4, s2kcap, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush5, lpop5,slpunum, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush6, lpop6,slponum, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush7, lpop7, NULL, NULL, NULL, NULL, NULL, NULL )
|
||||
|
||||
};
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : QWERTY : exports
|
||||
* ergoDOX : layout : Dvorak : exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,11 +7,12 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef LAYOUT_QWERTY_h
|
||||
#define LAYOUT_QWERTY_h
|
||||
#ifndef KEYBOARD__ERGODOX__LAYOUT__DVORAK_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT__DVORAK_h
|
||||
|
||||
#include "../led.h"
|
||||
#include "../controller.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define kb_led_num_on() _kb_led_1_on()
|
||||
#define kb_led_num_off() _kb_led_1_off()
|
||||
|
@ -20,5 +21,10 @@
|
|||
#define kb_led_scroll_on() _kb_led_3_on()
|
||||
#define kb_led_scroll_off() _kb_led_3_off()
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "./default--led-control.h"
|
||||
#include "./default--matrix-control.h"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : QWERTY (modified from the Kinesis layout)
|
||||
* TODO: rewrite for new kbfun's
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "../../../lib/data-types/misc.h"
|
||||
#include "../../../lib/usb/usage-page/keyboard--short-names.h"
|
||||
#include "../../../lib/key-functions/public.h"
|
||||
#include "../matrix.h"
|
||||
#include "../layout.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 0: default
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
_equal, _1, _2, _3, _4, _5, _esc,
|
||||
_backslash, _Q, _W, _E, _R, _T, 1,
|
||||
_tab, _A, _S, _D, _F, _G,
|
||||
_shiftL, _Z, _X, _C, _V, _B, 1,
|
||||
_guiL, _grave, _backslash, _arrowL, _arrowR,
|
||||
_bs, 0,
|
||||
_del, 0, _ctrlL,
|
||||
_end, _home, _altL,
|
||||
// right hand
|
||||
3, _6, _7, _8, _9, _0, _dash,
|
||||
_bracketL, _Y, _U, _I, _O, _P, _bracketR,
|
||||
_H, _J, _K, _L, _semicolon, _quote,
|
||||
1, _N, _M, _comma, _period, _slash, _shiftR,
|
||||
_arrowL, _arrowD, _arrowU, _arrowR, _guiR,
|
||||
0, _space,
|
||||
_ctrlR, 0, _enter,
|
||||
_altR, _pageU, _pageD ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 1: function and symbol keys
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, _F1, _F2, _F3, _F4, _F5, _F11,
|
||||
0, _bracketL, _bracketR, _bracketL, _bracketR, 0, 1,
|
||||
0, _semicolon, _slash, _dash, _0_kp,_semicolon,
|
||||
0, _6_kp, _7_kp, _8_kp, _9_kp, _equal, 2,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
_F12, _F6, _F7, _F8, _F9, _F10, _power,
|
||||
0, 0, _dash, _comma, _period,_currencyUnit, _volumeU,
|
||||
_backslash, _1_kp, _9, _0, _equal, _volumeD,
|
||||
2, _8, _2_kp, _3_kp, _4_kp, _5_kp, _mute,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 2: keyboard functions
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // layout: layer 3: numpad
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, _insert, 0, 0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
3, 0, 3, _equal_kp, _div_kp, _mul_kp, 0,
|
||||
0, 0, _7_kp, _8_kp, _9_kp, _sub_kp, 0,
|
||||
0, _4_kp, _5_kp, _6_kp, _add_kp, 0,
|
||||
0, 0, _1_kp, _2_kp, _3_kp, _enter_kp, 0,
|
||||
0, 0, _dec_kp, _enter_kp, 0,
|
||||
0, _0_kp,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// aliases
|
||||
|
||||
// basic
|
||||
#define kprrel &kbfun_press_release
|
||||
#define ktog &kbfun_toggle
|
||||
#define ktrans &kbfun_transparent
|
||||
// --- layer push/pop functions
|
||||
#define lpush1 &kbfun_layer_push_1
|
||||
#define lpush2 &kbfun_layer_push_2
|
||||
#define lpush3 &kbfun_layer_push_3
|
||||
#define lpush4 &kbfun_layer_push_4
|
||||
#define lpush5 &kbfun_layer_push_5
|
||||
#define lpush6 &kbfun_layer_push_6
|
||||
#define lpush7 &kbfun_layer_push_7
|
||||
#define lpush8 &kbfun_layer_push_8
|
||||
#define lpush9 &kbfun_layer_push_9
|
||||
#define lpush10 &kbfun_layer_push_10
|
||||
#define lpop1 &kbfun_layer_pop_1
|
||||
#define lpop2 &kbfun_layer_pop_2
|
||||
#define lpop3 &kbfun_layer_pop_3
|
||||
#define lpop4 &kbfun_layer_pop_4
|
||||
#define lpop5 &kbfun_layer_pop_5
|
||||
#define lpop6 &kbfun_layer_pop_6
|
||||
#define lpop7 &kbfun_layer_pop_7
|
||||
#define lpop8 &kbfun_layer_pop_8
|
||||
#define lpop9 &kbfun_layer_pop_9
|
||||
#define lpop10 &kbfun_layer_pop_10
|
||||
// ---
|
||||
|
||||
// device
|
||||
#define dbtldr &kbfun_jump_to_bootloader
|
||||
|
||||
// special
|
||||
#define sshprre &kbfun_shift_press_release
|
||||
#define s2kcap &kbfun_2_keys_capslock_press_release
|
||||
#define slpunum &kbfun_layer_push_numpad
|
||||
#define slponum &kbfun_layer_pop_numpad
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const void_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 0: default
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, lpush1,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
s2kcap, kprrel, kprrel, kprrel, kprrel, kprrel, lpush1,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, NULL,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel,
|
||||
// right hand
|
||||
slpunum, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lpush1, kprrel, kprrel, kprrel, kprrel, kprrel, s2kcap,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
NULL, kprrel,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 1: function and symbol keys
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans,sshprre,sshprre, kprrel, kprrel, NULL, lpop1,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre, lpush2,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, NULL, kprrel,sshprre,sshprre, kprrel, kprrel,
|
||||
kprrel, kprrel,sshprre,sshprre,sshprre, kprrel,
|
||||
lpush2,sshprre, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 2: keyboard functions
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
dbtldr, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
// right hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // press: layer 3: numpad
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, kprrel, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
slponum, ktrans,slponum, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const void_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 0: default
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, NULL,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
s2kcap, kprrel, kprrel, kprrel, kprrel, kprrel, lpop1,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, NULL,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel,
|
||||
// right hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
lpop1, kprrel, kprrel, kprrel, kprrel, kprrel, s2kcap,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
NULL, kprrel,
|
||||
kprrel, NULL, kprrel,
|
||||
kprrel, kprrel, kprrel ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 1: function and symbol keys
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans,sshprre,sshprre, kprrel, kprrel, NULL, NULL,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel,sshprre, lpop2,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, NULL, kprrel,sshprre,sshprre, kprrel, kprrel,
|
||||
kprrel, kprrel,sshprre,sshprre,sshprre, kprrel,
|
||||
lpop2,sshprre, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 2: keyboard functions
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
// right hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 3: numpad
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
ktrans, kprrel, ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
NULL, ktrans, NULL, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
KB_MATRIX_LAYER( // release: layer 3: nothing (just making sure unused
|
||||
// functions don't get compiled out)
|
||||
// unused
|
||||
NULL,
|
||||
// other
|
||||
kprrel, lpush8, lpop8, NULL, NULL, NULL, NULL, NULL,
|
||||
ktog, lpush9, lpop9, NULL, NULL, NULL, NULL, NULL,
|
||||
ktrans,lpush10, lpop10, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush1, lpop1, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush2, lpop2, dbtldr, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush3, lpop3, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush4, lpop4, s2kcap, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush5, lpop5,slpunum, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush6, lpop6,slponum, NULL, NULL, NULL, NULL, NULL,
|
||||
lpush7, lpop7, NULL, NULL, NULL, NULL, NULL, NULL )
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : layout : QWERTY : exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__LAYOUT__QWERTY_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT__QWERTY_h
|
||||
|
||||
#include "../controller.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define kb_led_num_on() _kb_led_1_on()
|
||||
#define kb_led_num_off() _kb_led_1_off()
|
||||
#define kb_led_caps_on() _kb_led_2_on()
|
||||
#define kb_led_caps_off() _kb_led_2_off()
|
||||
#define kb_led_scroll_on() _kb_led_3_on()
|
||||
#define kb_led_scroll_off() _kb_led_3_off()
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#include "./default--led-control.h"
|
||||
#include "./default--matrix-control.h"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,265 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : QWERTY
|
||||
*
|
||||
* This is an overly basic implementation. It needs to be replaced.
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <avr/pgmspace.h>
|
||||
#include "lib/data-types.h"
|
||||
#include "lib/usb/usage-page/keyboard--short-names.h"
|
||||
#include "lib/key-functions.h"
|
||||
|
||||
#include "../matrix.h"
|
||||
#include "../layout.h"
|
||||
|
||||
|
||||
// aliases
|
||||
#define f_prrel &kbfun_press_release
|
||||
#define f_toggl &kbfun_toggle
|
||||
#define f_l_inc &kbfun_layer_inc
|
||||
#define f_l_dec &kbfun_layer_dec
|
||||
#define f_l_iex &kbfun_layer_inc_exec
|
||||
#define f_l_dex &kbfun_layer_dec_exec
|
||||
#define f_2kcap &kbfun_2_keys_capslock_press_release
|
||||
#define f_np_to &kbfun_layermask_numpad_toggle
|
||||
#define f_np_on &kbfun_layermask_numpad_on
|
||||
#define f_np_of &kbfun_layermask_numpad_off
|
||||
#define f_btldr &kbfun_jump_to_bootloader
|
||||
|
||||
|
||||
|
||||
uint8_t PROGMEM _kb_layout[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 0: default
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
_grave, _1, _2, _3, _4, _5, _equal,
|
||||
_bracketL, _Q, _W, _E, _R, _T, _esc,
|
||||
_tab, _A, _S, _D, _F, _G,
|
||||
_shiftL, _Z, _X, _C, _V, _B, 1,
|
||||
_guiL, _arrowL, _arrowU, _arrowD, _arrowR,
|
||||
_bs,
|
||||
_del, _ctrlL,
|
||||
_end, _home, _altL,
|
||||
// right hand
|
||||
_backslash, _6, _7, _8, _9, _0, _dash,
|
||||
_bracketL, _Y, _U, _I, _O, _P, _bracketR,
|
||||
_H, _J, _K, _L, _semicolon, _quote,
|
||||
1, _N, _M, _comma, _period, _slash, _shiftR,
|
||||
_arrowL, _arrowD, _arrowU, _arrowR, _guiR,
|
||||
_space,
|
||||
_ctrlR, _enter,
|
||||
_altR, _pageU, _pageD ),
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 1: function and symbol keys
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
-1, _F1, _F2, _F3, _F4, _F5, _F11,
|
||||
0, _braceL_kp, _braceR_kp, _bracketL, _bracketR, 0, _esc,
|
||||
0, _semicolon, _slash, _dash, 0, _colon_kp,
|
||||
2, 0, 0, 0, 0, 0, 0,
|
||||
0, _arrowL, _arrowU, _arrowD, _arrowR,
|
||||
_bs,
|
||||
_del, _ctrlL,
|
||||
_end, _home, _altL,
|
||||
// right hand
|
||||
_F12, _F6, _F7, _F8, _F9, _F10, 0,
|
||||
2, 0, _dash, _lt_kp, _gt_kp, _currencyUnit, 0,
|
||||
_backslash, 0, _parenL_kp, _parenR_kp, _equal, 0,
|
||||
0, _mul_kp, 0, 0, 0, 0, 0,
|
||||
_arrowL, _arrowD, _arrowU, _arrowR, 0,
|
||||
_space,
|
||||
_ctrlR, _enter,
|
||||
_altR, _pageU, _pageD ),
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 2: numpad
|
||||
// unused
|
||||
0,
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
//------- ------- ------- ------- ------- ------- -------
|
||||
0, 0, _7_kp, _8_kp, _9_kp, _div_kp, 0,
|
||||
0, 0, _4_kp, _5_kp, _6_kp, _mul_kp, 0,
|
||||
0, _1_kp, _2_kp, _3_kp, _sub_kp, 0,
|
||||
0, 0, _0_kp, _period, 0, _add_kp, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, 0,
|
||||
0, 0, 0 )
|
||||
// ----------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
|
||||
kbfun_funptr_t PROGMEM _kb_layout_press[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 0: default
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_2kcap,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_l_inc,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,
|
||||
// right hand
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_l_inc,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_2kcap,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel ),
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 1: function and symbol keys
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
f_btldr,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_np_on,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,
|
||||
// right hand
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_np_to,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel ),
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 2: numpad
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
// right hand
|
||||
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL )
|
||||
// ----------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
|
||||
kbfun_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 0: default
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_2kcap,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_l_dec,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,
|
||||
// right hand
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_l_dec,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_2kcap,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel ),
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 1: function and symbol keys
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_np_of,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,
|
||||
// right hand
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
NULL,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,f_prrel,f_prrel,f_prrel,f_prrel,
|
||||
f_prrel,
|
||||
f_prrel, f_prrel,
|
||||
f_prrel,f_prrel,f_prrel ),
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 2: numpad
|
||||
// unused
|
||||
NULL,
|
||||
// left hand
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
// right hand
|
||||
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL, NULL,f_prrel,f_prrel,f_prrel,f_prrel, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL ),
|
||||
// ----------------------------------------------------------------------------
|
||||
MATRIX_LAYER( // layer 3: nothing (just making sure unused functions
|
||||
// don't get compiled out)
|
||||
// unused
|
||||
NULL,
|
||||
// other
|
||||
f_prrel, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_toggl, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_l_inc, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_l_dec, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_l_iex, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_l_dex, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_2kcap, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_np_to, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_np_on, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_np_of, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
f_btldr, NULL, NULL, NULL, NULL, NULL )
|
||||
// ----------------------------------------------------------------------------
|
||||
};
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* led stuff that isn't microprocessor or layout specific
|
||||
*
|
||||
* you should also include this file for low-level led macros, as it will
|
||||
* always include the file(s) containing those
|
||||
*
|
||||
* - low level LED macros (that have to be shared, but aren't really public)
|
||||
* should all start with '_kb_led_'
|
||||
* - public LED macros should start with 'kb_led_'
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef LED_h
|
||||
#define LED_h
|
||||
|
||||
#include <util/delay.h>
|
||||
|
||||
#include "teensy-2-0.h" // for low-level led macros
|
||||
|
||||
|
||||
#define kb_led_state_power_on() do { \
|
||||
_kb_led_all_set_percent(0.05); \
|
||||
_kb_led_all_on(); \
|
||||
} while(0)
|
||||
|
||||
// note: need to delay for a total of ~1 second
|
||||
#define kb_led_delay_usb_init() do { \
|
||||
_kb_led_1_set_percent(0.5); \
|
||||
_delay_ms(333); \
|
||||
_kb_led_2_set_percent(0.5); \
|
||||
_delay_ms(333); \
|
||||
_kb_led_3_set_percent(0.5); \
|
||||
_delay_ms(333); \
|
||||
} while(0)
|
||||
|
||||
#define kb_led_state_ready() do { \
|
||||
_kb_led_all_off(); \
|
||||
_kb_led_all_set_percent(0.5); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX: keyboard matrix specific exports
|
||||
* ergoDOX : matrix specific exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,17 +7,15 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef MATRIX_h
|
||||
#define MATRIX_h
|
||||
#ifndef KEYBOARD__ERGODOX__MATRIX_h
|
||||
#define KEYBOARD__ERGODOX__MATRIX_h
|
||||
|
||||
#include "lib/data-types.h"
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define KB_ROWS 12 // must match real life
|
||||
#define KB_COLUMNS 7 // must match real life
|
||||
|
||||
extern bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS];
|
||||
extern bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS];
|
||||
#define KB_ROWS 6 // must match real life
|
||||
#define KB_COLUMNS 14 // must match real life
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/* mapping from spatial position to matrix position
|
||||
* - spatial position: where the key is spatially, relative to other
|
||||
|
@ -29,57 +27,58 @@
|
|||
* and 'column' are single digit hex numbers corresponding to the
|
||||
* matrix position (which also corresponds to the row and column pin
|
||||
* labels used in the teensy and mcp23018 files)
|
||||
* - coordinates not listed are unused
|
||||
*
|
||||
* - coordinates
|
||||
* - optional keys
|
||||
* k15, k16 (left hand thumb group)
|
||||
* k17, k18 (right hand thumb group)
|
||||
* - unused keys
|
||||
* k36, k00 (left hand)
|
||||
* k37, k0D (right hand)
|
||||
*
|
||||
* --- other info -----------------------------------------------------
|
||||
* rows x columns = positions; assigned, unassigned
|
||||
* per hand: 6 x 7 = 42; 38, 4
|
||||
* total: 12 x 7 = 84; 76, 8
|
||||
* rows x columns = positions; used, unused
|
||||
* per hand: 6 x 7 = 42; 40, 2
|
||||
* total: 6 x 14 = 84; 80, 4
|
||||
*
|
||||
* left hand : cols 0..6, rows 6..B
|
||||
* right hand : cols 0..6, rows 0..5
|
||||
* left hand : rows 0..5, cols 0..6
|
||||
* right hand : rows 0..5, cols 7..D
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
#define MATRIX_LAYER( \
|
||||
/* for unused positions */ \
|
||||
na, \
|
||||
\
|
||||
/* left hand, spatial positions */ \
|
||||
kB6,kB5,kB4,kB3,kB2,kB1,kB0, \
|
||||
kA6,kA5,kA4,kA3,kA2,kA1,kA0, \
|
||||
k96,k95,k94,k93,k92,k91, \
|
||||
k86,k85,k84,k83,k82,k81,k80, \
|
||||
k76,k75,k74,k73,k72, \
|
||||
k64, \
|
||||
k63, k60, \
|
||||
k65,k62,k61, \
|
||||
\
|
||||
/* right hand, spatial positions */ \
|
||||
k50,k51,k52,k53,k54,k55,k56, \
|
||||
k40,k41,k42,k43,k44,k45,k46, \
|
||||
k31,k32,k33,k34,k35,k36, \
|
||||
k20,k21,k22,k23,k24,k25,k26, \
|
||||
k12,k13,k14,k15,k16, \
|
||||
k04, \
|
||||
k00, k03, \
|
||||
k01,k02,k05 ) \
|
||||
\
|
||||
/* matrix positions */ \
|
||||
{ { k00,k01,k02,k03,k04,k05, na,}, \
|
||||
{ na, na,k12,k13,k14,k15,k16,}, \
|
||||
{ k20,k21,k22,k23,k24,k25,k26,}, \
|
||||
{ na,k31,k32,k33,k34,k35,k36,}, \
|
||||
{ k40,k41,k42,k43,k44,k45,k46,}, \
|
||||
{ k50,k51,k52,k53,k54,k55,k56,}, \
|
||||
{ k60,k61,k62,k63,k64,k65, na,}, \
|
||||
{ na, na,k72,k73,k74,k75,k76,}, \
|
||||
{ k80,k81,k82,k83,k84,k85,k86,}, \
|
||||
{ na,k91,k92,k93,k94,k95,k96,}, \
|
||||
{ kA0,kA1,kA2,kA3,kA4,kA5,kA6,}, \
|
||||
{ kB0,kB1,kB2,kB3,kB4,kB5,kB6 } }
|
||||
#define KB_MATRIX_LAYER( \
|
||||
/* for unused positions */ \
|
||||
na, \
|
||||
\
|
||||
/* left hand, spatial positions */ \
|
||||
k50,k51,k52,k53,k54,k55,k56, \
|
||||
k40,k41,k42,k43,k44,k45,k46, \
|
||||
k30,k31,k32,k33,k34,k35, \
|
||||
k20,k21,k22,k23,k24,k25,k26, \
|
||||
k10,k11,k12,k13,k14, \
|
||||
k03,k15, \
|
||||
k02,k16,k05, \
|
||||
k01,k04,k06, \
|
||||
\
|
||||
/* right hand, spatial positions */ \
|
||||
k57,k58,k59,k5A,k5B,k5C,k5D, \
|
||||
k47,k48,k49,k4A,k4B,k4C,k4D, \
|
||||
k38,k39,k3A,k3B,k3C,k3D, \
|
||||
k27,k28,k29,k2A,k2B,k2C,k2D, \
|
||||
k19,k1A,k1B,k1C,k1D, \
|
||||
k18,k0A, \
|
||||
k08,k17,k0B, \
|
||||
k07,k09,k0C ) \
|
||||
\
|
||||
/* matrix positions */ \
|
||||
{{ na,k01,k02,k03,k04,k05,k06, k07,k08,k09,k0A,k0B,k0C, na }, \
|
||||
{ k10,k11,k12,k13,k14,k15,k16, k17,k18,k19,k1A,k1B,k1C,k1D }, \
|
||||
{ k20,k21,k22,k23,k24,k25,k26, k27,k28,k29,k2A,k2B,k2C,k2D }, \
|
||||
{ k30,k31,k32,k33,k34,k35, na, na,k38,k39,k3A,k3B,k3C,k3D }, \
|
||||
{ k40,k41,k42,k43,k44,k45,k46, k47,k48,k49,k4A,k4B,k4C,k4D }, \
|
||||
{ k50,k51,k52,k53,k54,k55,k56, k57,k58,k59,k5A,k5B,k5C,k5D }}
|
||||
|
||||
|
||||
#define MATRIX_LAYER_SET_ALL(na, kxx) \
|
||||
#define KB_MATRIX_LAYER_SET_ALL(na, kxx) \
|
||||
LAYER( \
|
||||
na, \
|
||||
\
|
||||
|
@ -88,8 +87,8 @@
|
|||
kxx,kxx,kxx,kxx,kxx,kxx, \
|
||||
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
|
||||
kxx,kxx,kxx,kxx,kxx, \
|
||||
kxx, \
|
||||
kxx, kxx, \
|
||||
kxx,kxx, \
|
||||
kxx,kxx,kxx, \
|
||||
kxx,kxx,kxx, \
|
||||
\
|
||||
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
|
||||
|
@ -97,10 +96,9 @@
|
|||
kxx,kxx,kxx,kxx,kxx,kxx, \
|
||||
kxx,kxx,kxx,kxx,kxx,kxx,kxx, \
|
||||
kxx,kxx,kxx,kxx,kxx, \
|
||||
kxx, \
|
||||
kxx, kxx, \
|
||||
kxx,kxx,kxx )
|
||||
|
||||
kxx,kxx, \
|
||||
kxx,kxx,kxx, \
|
||||
kxx,kxx,kxx ) \
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: MCP23018 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <util/twi.h>
|
||||
#include "lib/data-types.h"
|
||||
#include "lib/twi.h" // `TWI_FREQ` defined in "teensy-2-0.c"
|
||||
|
||||
#include "matrix.h"
|
||||
#include "mcp23018--private.h"
|
||||
|
||||
|
||||
// register addresses (see "mcp23018.md")
|
||||
#define IODIRA 0x00 // i/o direction register
|
||||
#define IODIRB 0x01
|
||||
#define GPPUA 0x0C // GPIO pull-up resistor register
|
||||
#define GPPUB 0x0D
|
||||
#define GPIOA 0x12 // general purpose i/o port register (write modifies OLAT)
|
||||
#define GPIOB 0x13
|
||||
#define OLATA 0x14 // output latch register
|
||||
#define OLATB 0x15
|
||||
|
||||
// TWI aliases
|
||||
#define TWI_ADDR_WRITE ( (MCP23018_TWI_ADDRESS<<1) | TW_WRITE )
|
||||
#define TWI_ADDR_READ ( (MCP23018_TWI_ADDRESS<<1) | TW_READ )
|
||||
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*
|
||||
* notes:
|
||||
* - `twi_stop()` must be called *exactly once* for each twi block, the way
|
||||
* things are currently set up. this may change in the future.
|
||||
*/
|
||||
uint8_t mcp23018_init(void) {
|
||||
uint8_t ret;
|
||||
|
||||
// set pin direction
|
||||
// - unused : input : 1
|
||||
// - row : input : 1
|
||||
// - column : output : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(IODIRA);
|
||||
twi_send(0b11111111); // IODIRA
|
||||
twi_send(0b10000000); // IODIRB
|
||||
twi_stop();
|
||||
|
||||
// set pull-up
|
||||
// - unused : on : 1
|
||||
// - rows : on : 1
|
||||
// - columns : off : 0
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(GPPUA);
|
||||
twi_send(0b11111111); // GPPUA
|
||||
twi_send(0b10000000); // GPPUB
|
||||
twi_stop();
|
||||
|
||||
// set logical value (doesn't matter on inputs)
|
||||
// - unused : high (hi-Z) : 1
|
||||
// - rows : high (hi-Z) : 1
|
||||
// - columns : high (hi-Z) : 1
|
||||
twi_start();
|
||||
ret = twi_send(TWI_ADDR_WRITE);
|
||||
if (ret) goto out; // make sure we got an ACK
|
||||
twi_send(OLATA);
|
||||
twi_send(0b11111111); //OLATA
|
||||
twi_send(0b11111111); //OLATB
|
||||
|
||||
out:
|
||||
twi_stop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* returns:
|
||||
* - success: 0
|
||||
* - failure: twi status code
|
||||
*/
|
||||
#if KB_ROWS != 12 || KB_COLUMNS != 7
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
uint8_t mcp23018_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
uint8_t ret, data;
|
||||
|
||||
// initialize things, just to make sure
|
||||
// - it's not appreciably faster to skip this, and it takes care of the
|
||||
// case when the i/o expander isn't plugged in during the first
|
||||
// init()
|
||||
ret = mcp23018_init();
|
||||
|
||||
// if there was an error
|
||||
if (ret) {
|
||||
// clear our part of the matrix
|
||||
for (uint8_t row=0x6; row<=0xB; row++)
|
||||
for (uint8_t col=0; col<=6; col++)
|
||||
matrix[row][col] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// update our part of the matrix
|
||||
for (uint8_t col=0; col<=6; col++) {
|
||||
// set active column low : 0
|
||||
// set other columns high (hi-Z) : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(OLATB);
|
||||
twi_send( 0xFF & ~(1<<col) );
|
||||
twi_stop();
|
||||
|
||||
// read row data
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOA);
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_READ);
|
||||
twi_read(&data);
|
||||
twi_stop();
|
||||
|
||||
// update matrix
|
||||
for (uint8_t row=0x6; row<=0xB; row++)
|
||||
matrix[row][col] = !( data & (1<<(row-6)) );
|
||||
}
|
||||
|
||||
// set all columns high (hi-Z) : 1
|
||||
twi_start();
|
||||
twi_send(TWI_ADDR_WRITE);
|
||||
twi_send(GPIOB);
|
||||
twi_send(0xFF);
|
||||
twi_stop();
|
||||
|
||||
return ret; // success
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : keyboard specific options
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__OPTIONS_h
|
||||
#define KEYBOARD__ERGODOX__OPTIONS_h
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* DRIVE_ROWS and DRIVE_COLUMNS
|
||||
* - Select which pins will drive (alternate between hi-Z and drive
|
||||
* low) and which will be inputs
|
||||
*
|
||||
* Notes
|
||||
* - You must set exactly one of each 'TEENSY' macro, and of each
|
||||
* 'MCP23018' macro
|
||||
* - If you are using internal diodes (inside the key switches)... then
|
||||
* i don't know what to tell you. You will set one chip to drive
|
||||
* rows, and the other to drive columns, but i don't have a key
|
||||
* switch to check which at the moment, and i couldn't seem to find
|
||||
* it online.
|
||||
* - If the diode cathode is towards the square solder pad, set
|
||||
* #define TEENSY__DRIVE_COLUMNS 1
|
||||
* #define MCP23018__DRIVE_COLUMNS 1
|
||||
* - If the diode cathode is towards the circular solder pad, set
|
||||
* #define TEENSY__DRIVE_ROWS 1
|
||||
* #define MCP23018__DRIVE_ROWS 1
|
||||
*/
|
||||
#define TEENSY__DRIVE_ROWS 0
|
||||
#define TEENSY__DRIVE_COLUMNS 1
|
||||
#define MCP23018__DRIVE_ROWS 0
|
||||
#define MCP23018__DRIVE_COLUMNS 1
|
||||
|
||||
#endif
|
|
@ -1,195 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX controller: Teensy 2.0 specific code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include "lib/data-types.h"
|
||||
#define TWI_FREQ 400000
|
||||
#include "lib/twi.h"
|
||||
|
||||
#include "matrix.h"
|
||||
#include "teensy-2-0.h"
|
||||
#include "teensy-2-0--private.h"
|
||||
|
||||
|
||||
// processor frequency (from <http://www.pjrc.com/teensy/prescaler.html>)
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define CPU_16MHz 0x00
|
||||
#define CPU_8MHz 0x01
|
||||
#define CPU_4MHz 0x02
|
||||
#define CPU_2MHz 0x03
|
||||
#define CPU_1MHz 0x04
|
||||
#define CPU_500kHz 0x05
|
||||
#define CPU_250kHz 0x06
|
||||
#define CPU_125kHz 0x07
|
||||
#define CPU_62kHz 0x08
|
||||
|
||||
|
||||
/* pin macros
|
||||
* - note: you can move the `UNUSED`, `ROW`, and `COLUMN` pins around, but be
|
||||
* sure to keep the set of all the pins listed constant. other pins are not
|
||||
* movable, and either are referenced explicitly or have macros defined for
|
||||
* them elsewhere.
|
||||
* - note: if you change pin assignments, please be sure to update
|
||||
* "teensy-2-0.md", and the '.svg' circuit diagram.
|
||||
*/
|
||||
// --- helpers
|
||||
#define teensypin_write(register, operation, pin) do { \
|
||||
_teensypin_write(register, operation, pin); \
|
||||
_delay_us(1); /* allow pins time to stabalize */ \
|
||||
} while(0)
|
||||
#define _teensypin_write(register, operation, pin_letter, pin_number) \
|
||||
((register##pin_letter) operation (1<<(pin_number)))
|
||||
|
||||
#define teensypin_read(pin) \
|
||||
_teensypin_read(pin)
|
||||
#define _teensypin_read(pin_letter, pin_number) \
|
||||
((PIN##pin_letter) & (1<<(pin_number)))
|
||||
|
||||
#define teensypin_write_all_unused(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, UNUSED_0); \
|
||||
teensypin_write(register, operation, UNUSED_1); \
|
||||
teensypin_write(register, operation, UNUSED_2); \
|
||||
teensypin_write(register, operation, UNUSED_3); \
|
||||
teensypin_write(register, operation, UNUSED_4); \
|
||||
teensypin_write(register, operation, UNUSED_5); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_row(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, ROW_0); \
|
||||
teensypin_write(register, operation, ROW_1); \
|
||||
teensypin_write(register, operation, ROW_2); \
|
||||
teensypin_write(register, operation, ROW_3); \
|
||||
teensypin_write(register, operation, ROW_4); \
|
||||
teensypin_write(register, operation, ROW_5); } \
|
||||
while(0)
|
||||
|
||||
#define teensypin_write_all_column(register, operation) \
|
||||
do { \
|
||||
teensypin_write(register, operation, COLUMN_0); \
|
||||
teensypin_write(register, operation, COLUMN_1); \
|
||||
teensypin_write(register, operation, COLUMN_2); \
|
||||
teensypin_write(register, operation, COLUMN_3); \
|
||||
teensypin_write(register, operation, COLUMN_4); \
|
||||
teensypin_write(register, operation, COLUMN_5); \
|
||||
teensypin_write(register, operation, COLUMN_6); } \
|
||||
while(0)
|
||||
|
||||
#define SET |=
|
||||
#define CLEAR &=~
|
||||
|
||||
// --- unused
|
||||
#define UNUSED_0 B, 1 // SPI pin
|
||||
#define UNUSED_1 B, 2 // SPI pin
|
||||
#define UNUSED_2 B, 3 // SPI pin
|
||||
#define UNUSED_3 D, 4 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_4 D, 5 // hard to use with breadboard (on the end)
|
||||
#define UNUSED_5 E, 6 // hard to use with breadboard (internal)
|
||||
|
||||
// --- rows
|
||||
#define ROW_0 F, 0
|
||||
#define ROW_1 F, 1
|
||||
#define ROW_2 F, 4
|
||||
#define ROW_3 F, 5
|
||||
#define ROW_4 F, 6
|
||||
#define ROW_5 F, 7
|
||||
|
||||
// --- columns
|
||||
#define COLUMN_0 B, 4
|
||||
#define COLUMN_1 C, 6
|
||||
#define COLUMN_2 C, 7
|
||||
#define COLUMN_3 D, 2
|
||||
#define COLUMN_4 D, 3
|
||||
#define COLUMN_5 D, 7
|
||||
#define COLUMN_6 B, 0
|
||||
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
uint8_t teensy_init(void) {
|
||||
CPU_PRESCALE(CPU_16MHz); // speed should match F_CPU in makefile
|
||||
|
||||
// onboard LED
|
||||
DDRD &= ~(1<<6); // set D(6) as input
|
||||
PORTD &= ~(1<<6); // set D(6) internal pull-up disabled
|
||||
|
||||
// keyboard LEDs (see "PWM on ports OC1(A|B|C)" in "teensy-2-0.md")
|
||||
_kb_led_all_off(); // (just to put the pins in a known state)
|
||||
TCCR1A = 0b10101001; // set and configure fast PWM
|
||||
TCCR1B = 0b00001001; // set and configure fast PWM
|
||||
|
||||
// I2C (TWI)
|
||||
twi_init(); // on pins D(1,0)
|
||||
|
||||
// unused pins
|
||||
teensypin_write_all_unused(DDR, CLEAR); // set as input
|
||||
teensypin_write_all_unused(PORT, SET); // set internal pull-up enabled
|
||||
|
||||
// rows
|
||||
teensypin_write_all_row(DDR, CLEAR); // set as input
|
||||
teensypin_write_all_row(PORT, SET); // set internal pull-up enabled
|
||||
|
||||
// columns
|
||||
teensypin_write_all_column(DDR, CLEAR); // set as input (hi-Z)
|
||||
teensypin_write_all_column(PORT, CLEAR); // set internal pull-up
|
||||
// disabled
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
*/
|
||||
#if KB_ROWS != 12 || KB_COLUMNS != 7
|
||||
#error "Expecting different keyboard dimensions"
|
||||
#endif
|
||||
static inline void _update_rows(
|
||||
bool matrix[KB_ROWS][KB_COLUMNS], uint8_t column ) {
|
||||
matrix[0][column] = ! teensypin_read(ROW_0);
|
||||
matrix[1][column] = ! teensypin_read(ROW_1);
|
||||
matrix[2][column] = ! teensypin_read(ROW_2);
|
||||
matrix[3][column] = ! teensypin_read(ROW_3);
|
||||
matrix[4][column] = ! teensypin_read(ROW_4);
|
||||
matrix[5][column] = ! teensypin_read(ROW_5);
|
||||
}
|
||||
uint8_t teensy_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
teensypin_write(DDR, SET, COLUMN_0); // set col low (set as output)
|
||||
_update_rows(matrix, 0); // read row 0..5 & update matrix
|
||||
teensypin_write(DDR, CLEAR, COLUMN_0); // set col hi-Z (set as input)
|
||||
|
||||
teensypin_write(DDR, SET, COLUMN_1);
|
||||
_update_rows(matrix, 1);
|
||||
teensypin_write(DDR, CLEAR, COLUMN_1);
|
||||
|
||||
teensypin_write(DDR, SET, COLUMN_2);
|
||||
_update_rows(matrix, 2);
|
||||
teensypin_write(DDR, CLEAR, COLUMN_2);
|
||||
|
||||
teensypin_write(DDR, SET, COLUMN_3);
|
||||
_update_rows(matrix, 3);
|
||||
teensypin_write(DDR, CLEAR, COLUMN_3);
|
||||
|
||||
teensypin_write(DDR, SET, COLUMN_4);
|
||||
_update_rows(matrix, 4);
|
||||
teensypin_write(DDR, CLEAR, COLUMN_4);
|
||||
|
||||
teensypin_write(DDR, SET, COLUMN_5);
|
||||
_update_rows(matrix, 5);
|
||||
teensypin_write(DDR, CLEAR, COLUMN_5);
|
||||
|
||||
teensypin_write(DDR, SET, COLUMN_6);
|
||||
_update_rows(matrix, 6);
|
||||
teensypin_write(DDR, CLEAR, COLUMN_6);
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX: keyboard matrix specific code
|
||||
* layout specific exports
|
||||
*
|
||||
* Files for different keyboards are used by modifying a variable in the
|
||||
* Makefile
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,14 +10,7 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "lib/data-types.h"
|
||||
|
||||
#include "matrix.h"
|
||||
|
||||
|
||||
static bool _kb_is_pressed[KB_ROWS][KB_COLUMNS];
|
||||
static bool _kb_was_pressed[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_is_pressed;
|
||||
bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_was_pressed;
|
||||
#include "../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/layout.h )
|
||||
#include INCLUDE
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* matrix specific exports
|
||||
*
|
||||
* Files for different keyboards are used by modifying a variable in the
|
||||
* Makefile
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 "../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/matrix.h )
|
||||
#include INCLUDE
|
||||
|
|
@ -34,16 +34,16 @@
|
|||
**************************************************************************/
|
||||
|
||||
// You can change these to give your code its own name.
|
||||
#define STR_MANUFACTURER L"MfgName"
|
||||
#define STR_PRODUCT L"Keyboard"
|
||||
#define STR_MANUFACTURER L"unspecified" // TODO
|
||||
#define STR_PRODUCT L"ErgoDox ergonomic keyboard"
|
||||
|
||||
|
||||
// Mac OS-X and Linux automatically load the correct drivers. On
|
||||
// Windows, even though the driver is supplied by Microsoft, an
|
||||
// INF file is needed to load the driver. These numbers need to
|
||||
// match the INF file.
|
||||
#define VENDOR_ID 0x16C0
|
||||
#define PRODUCT_ID 0x047C
|
||||
#define VENDOR_ID 0x1d50 // Openmoko, Inc.
|
||||
#define PRODUCT_ID 0x6028 // ErgoDox ergonomic keyboard
|
||||
|
||||
|
||||
// USB devices are supposed to implment a halt feature, which is
|
||||
|
@ -89,7 +89,7 @@ static const uint8_t PROGMEM endpoint_config_table[] = {
|
|||
// spec and relevant portions of any USB class specifications!
|
||||
|
||||
|
||||
static uint8_t PROGMEM device_descriptor[] = {
|
||||
static const uint8_t PROGMEM device_descriptor[] = {
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x00, 0x02, // bcdUSB
|
||||
|
@ -107,7 +107,7 @@ static uint8_t PROGMEM device_descriptor[] = {
|
|||
};
|
||||
|
||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
|
||||
static uint8_t PROGMEM keyboard_hid_report_desc[] = {
|
||||
static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x06, // Usage (Keyboard),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
|
@ -144,7 +144,7 @@ static uint8_t PROGMEM keyboard_hid_report_desc[] = {
|
|||
|
||||
#define CONFIG1_DESC_SIZE (9+9+9+7)
|
||||
#define KEYBOARD_HID_DESC_OFFSET (9+9)
|
||||
static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||
static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
|
||||
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
|
||||
9, // bLength;
|
||||
2, // bDescriptorType;
|
||||
|
@ -191,17 +191,17 @@ struct usb_string_descriptor_struct {
|
|||
uint8_t bDescriptorType;
|
||||
int16_t wString[];
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string0 = {
|
||||
static const struct usb_string_descriptor_struct PROGMEM string0 = {
|
||||
4,
|
||||
3,
|
||||
{0x0409}
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string1 = {
|
||||
static const struct usb_string_descriptor_struct PROGMEM string1 = {
|
||||
sizeof(STR_MANUFACTURER),
|
||||
3,
|
||||
STR_MANUFACTURER
|
||||
};
|
||||
static struct usb_string_descriptor_struct PROGMEM string2 = {
|
||||
static const struct usb_string_descriptor_struct PROGMEM string2 = {
|
||||
sizeof(STR_PRODUCT),
|
||||
3,
|
||||
STR_PRODUCT
|
||||
|
@ -214,7 +214,7 @@ static struct descriptor_list_struct {
|
|||
uint16_t wIndex;
|
||||
const uint8_t *addr;
|
||||
uint8_t length;
|
||||
} PROGMEM descriptor_list[] = {
|
||||
} const PROGMEM descriptor_list[] = {
|
||||
{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
|
||||
{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
|
||||
{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* linked list
|
||||
*
|
||||
* Notes:
|
||||
* - When 'position' is used, it referes to the position of the node in the
|
||||
* list, not the node's offset. E.g. the node with position == 1 is the
|
||||
* first node in the list.
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <stdlib.h>
|
||||
#include "lib/data-types.h"
|
||||
|
||||
#include "linked-list.h"
|
||||
|
||||
|
||||
// local macros (undefined later)
|
||||
#define _NEW_POINTER(type, name) type * name = (type *) malloc(sizeof(type))
|
||||
#define _list_t linked_list_t
|
||||
#define _node_t linked_list_node_t
|
||||
#define _data_t LINKED_LIST_DATA_TYPE
|
||||
|
||||
|
||||
/*
|
||||
* new()
|
||||
*
|
||||
* Returns
|
||||
* - success: a pointer to a new linked list
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_new(void) {
|
||||
_NEW_POINTER(_list_t, list);
|
||||
if (!list) return NULL;
|
||||
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
|
||||
list->length = 0;
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* insert()
|
||||
*
|
||||
* Arguments
|
||||
* - index: the index of the position that the new node will occupy. if index
|
||||
* is negative, we set index += length (as in Python). so:
|
||||
* - 0 => the first node in the list
|
||||
* - 1 => the second node in the list
|
||||
* - -1 => the last node in the list
|
||||
* - -2 => the second from the last node in the list
|
||||
* - '0' is undefined (returns 'failure')
|
||||
* - out of bounds positions wrap around, so:
|
||||
* - [length] => 0 => the first node in the list
|
||||
* - -[length+1] => -1 => the last node in the list
|
||||
*
|
||||
* Returns
|
||||
* - success: the pointer to the list that was passed
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_insert(_list_t * list, _data_t data, int index) {
|
||||
_NEW_POINTER(_node_t, node);
|
||||
if (!node) return NULL;
|
||||
|
||||
node->data = data;
|
||||
|
||||
if (list->length == 0) {
|
||||
// insert as only node (no others exist yet)
|
||||
list->head = node;
|
||||
list->tail = node;
|
||||
node->next = NULL;
|
||||
} else {
|
||||
// find positive, in-bounds index
|
||||
index = index % list->length;
|
||||
if (index < 0)
|
||||
index += list->length;
|
||||
|
||||
if (index == 0) {
|
||||
// insert as first node
|
||||
node->next = list->head;
|
||||
list->head = node;
|
||||
} else if (index == list->length-1) {
|
||||
// insert as last node
|
||||
list->tail->next = node;
|
||||
list->tail = node;
|
||||
node->next = NULL;
|
||||
} else {
|
||||
// insert as other node
|
||||
_node_t * previous = list->head;
|
||||
for (int i=1; i<index; i++)
|
||||
previous = previous->next;
|
||||
node->next = previous->next;
|
||||
previous->next = node;
|
||||
}
|
||||
}
|
||||
|
||||
list->length++;
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* peek()
|
||||
*
|
||||
* Arguments
|
||||
* - index: [see 'insert()']
|
||||
*
|
||||
* Returns
|
||||
* - success: the data field of the node at the given index
|
||||
* - failure: (_data_t) 0
|
||||
*/
|
||||
_data_t linked_list_peek(_list_t * list, int index) {
|
||||
// if: no nodes exist
|
||||
if (list->length == 0)
|
||||
return (_data_t) 0;
|
||||
|
||||
// find positive, in-bounds index
|
||||
index = index % list->length;
|
||||
if (index < 0)
|
||||
index += list->length;
|
||||
|
||||
// if: last node
|
||||
if (index == list->length-1)
|
||||
return list->tail->data;
|
||||
|
||||
// else
|
||||
_node_t * node = list->head;
|
||||
for (int i=0; i<index; i++)
|
||||
node = node->next;
|
||||
return node->data;
|
||||
}
|
||||
|
||||
/*
|
||||
* pop()
|
||||
*
|
||||
* Arguments
|
||||
* - index: [see 'insert()']
|
||||
*
|
||||
* Returns
|
||||
* - success: the data field of the node at the given index
|
||||
* - failure: (_data_t) 0
|
||||
*/
|
||||
_data_t linked_list_pop(_list_t * list, int index) {
|
||||
// if: no nodes exist
|
||||
if (list->length == 0)
|
||||
return (_data_t) 0;
|
||||
|
||||
// find positive, in-bounds index
|
||||
index = index % list->length;
|
||||
if (index < 0)
|
||||
index += list->length;
|
||||
|
||||
// vars
|
||||
_data_t data;
|
||||
_node_t * node;
|
||||
|
||||
if (index == 0) {
|
||||
// pop first node
|
||||
data = list->head->data;
|
||||
node = list->head;
|
||||
list->head = node->next;
|
||||
} else {
|
||||
// find the index-1'th node
|
||||
_node_t * previous;
|
||||
previous = list->head;
|
||||
for (int i=1; i<index; i++)
|
||||
previous = previous->next;
|
||||
|
||||
// if: last node
|
||||
if (index == list->length-1)
|
||||
list->tail = previous;
|
||||
|
||||
// pop the node at index
|
||||
data = previous->next->data;
|
||||
node = previous->next;
|
||||
previous->next = node->next;
|
||||
}
|
||||
|
||||
free(node);
|
||||
|
||||
list->length--;
|
||||
return data;
|
||||
}
|
||||
|
||||
/*
|
||||
* find()
|
||||
* TODO
|
||||
*/
|
||||
// TODO
|
||||
|
||||
/*
|
||||
* copy()
|
||||
*
|
||||
* Returns
|
||||
* - success: a new pointer to a (deep) copy of the list that was passed
|
||||
* - failure: NULL
|
||||
*/
|
||||
_list_t * linked_list_copy(_list_t * list) {
|
||||
_NEW_POINTER(_list_t, copy);
|
||||
if (!copy) return NULL;
|
||||
|
||||
bool error;
|
||||
_node_t * node = list->head;
|
||||
for (uint8_t i=0; i<(list->length); i++) {
|
||||
error = ! linked_list_insert(copy, node->data, -1);
|
||||
if (error) {
|
||||
linked_list_free(copy);
|
||||
return NULL;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/*
|
||||
* free()
|
||||
* - Free the memory allocated to all the nodes, then free the memory allocated
|
||||
* to the list.
|
||||
*/
|
||||
void linked_list_free(_list_t * list) {
|
||||
_node_t * node;
|
||||
for (uint8_t i=0; i<(list->length); i++) {
|
||||
node = list->head;
|
||||
list->head = list->head->next;
|
||||
free(node);
|
||||
}
|
||||
free(list);
|
||||
}
|
||||
|
||||
|
||||
// local macros (undefined here)
|
||||
#undef _NEW_POINTER
|
||||
#undef _list_t
|
||||
#undef _node_t
|
||||
#undef _data_t
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* linked list : exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef LINKED_LIST_h
|
||||
#define LINKED_LIST_h
|
||||
|
||||
#include "lib/data-types.h"
|
||||
|
||||
|
||||
// default data type for the list
|
||||
#ifndef LINKED_LIST_DATA_TYPE
|
||||
#define LINKED_LIST_DATA_TYPE uint8_t
|
||||
#endif
|
||||
|
||||
|
||||
// structs
|
||||
struct linked_list_node {
|
||||
LINKED_LIST_DATA_TYPE data;
|
||||
struct linked_list_node * next;
|
||||
};
|
||||
|
||||
struct linked_list {
|
||||
uint8_t length;
|
||||
struct linked_list_node * head;
|
||||
struct linked_list_node * tail;
|
||||
};
|
||||
|
||||
// typedefs
|
||||
typedef struct linked_list linked_list_t;
|
||||
typedef struct linked_list_node linked_list_node_t;
|
||||
|
||||
// functions
|
||||
#define _list_t linked_list_t
|
||||
#define _data_t LINKED_LIST_DATA_TYPE
|
||||
// TODO
|
||||
_list_t * linked_list_new (void);
|
||||
_list_t * linked_list_add_head (_list_t * list, _data_t data);
|
||||
_list_t * linked_list_add_tail (_list_t * list, _data_t data);
|
||||
_data_t linked_list_pop_head (_list_t * list);
|
||||
_data_t linked_list_pop_tail (_list_t * list);
|
||||
_data_t linked_list_read (_list_t * list, uint8_t position);
|
||||
_list_t * linked_list_copy (_list_t * list);
|
||||
void linked_list_free (_list_t * list);
|
||||
// /TODO
|
||||
#undef _list_t
|
||||
#undef _data_t
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Common data types
|
||||
* miscellaneous data types
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
* Released under The MIT License (MIT) (see "license.md")
|
||||
|
@ -7,13 +7,10 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef DATA_TYPES_h
|
||||
#define DATA_TYPES_h
|
||||
#ifndef LIB__DATA_TYPES_h
|
||||
#define LIB__DATA_TYPES_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "data-types/linked-list.h"
|
||||
typedef void (*void_funptr_t)(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions: private
|
||||
*
|
||||
* Things to be used only by keyfunctions. Exported any layouts would like to
|
||||
* use these functions to help define their own.
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEY_FUNCTIONS_h_PRIVATE
|
||||
#define KEY_FUNCTIONS_h_PRIVATE
|
||||
|
||||
void _press_release(bool pressed, uint8_t keycode);
|
||||
void _layer_set_current(
|
||||
uint8_t value,
|
||||
uint8_t * current_layer,
|
||||
uint8_t (*current_layers_)[KB_ROWS][KB_COLUMNS] );
|
||||
void _layer_set_mask(
|
||||
uint8_t layer,
|
||||
bool positions[KB_ROWS][KB_COLUMNS],
|
||||
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] );
|
||||
bool _is_pressed(uint8_t keycode);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,510 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions: code
|
||||
*
|
||||
* These functions may do.. pretty much anything rational that thay like. If
|
||||
* they want keycodes to be sent to the host in an aggrate report, they're
|
||||
* responsible for modifying the appropriate report variables.
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <avr/interrupt.h>
|
||||
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "lib/data-types.h"
|
||||
#include "lib/usb/usage-page/keyboard.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
#include "key-functions.h"
|
||||
#include "key-functions--private.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// public functions (not for keys)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Exec key
|
||||
* - Execute the keypress or keyrelease function (if it exists) of the key at
|
||||
* the current possition. Pass the keycode at the current position, and pass
|
||||
* all other arguments as received
|
||||
*/
|
||||
void _kbfun_exec_key( KBFUN_FUNCTION_ARGS ) {
|
||||
kbfun_funptr_t key_function =
|
||||
( (pressed_)
|
||||
? kb_layout_press_get(layer_, *row_, *col_)
|
||||
: kb_layout_release_get(layer_, *row_, *col_) );
|
||||
|
||||
if (key_function)
|
||||
(*key_function)(
|
||||
pressed_,
|
||||
kb_layout_get(layer_, *row_, *col_),
|
||||
layer_,
|
||||
row_,
|
||||
col_,
|
||||
current_layer_,
|
||||
current_layers_,
|
||||
pressed_layers_ );
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Generate a normal keypress or keyrelease
|
||||
*
|
||||
* Arguments
|
||||
* - keycode: the keycode to use
|
||||
* - pressed: whether to generate a keypress (true) or keyrelease (false)
|
||||
*
|
||||
* Note
|
||||
* - Because of the way USB does things, what this actually does is either add
|
||||
* or remove 'keycode' from the list of currently pressed keys, to be sent at
|
||||
* the end of the current cycle (see main.c)
|
||||
*/
|
||||
void _press_release(bool pressed, uint8_t keycode) {
|
||||
// no-op
|
||||
if (keycode == 0)
|
||||
return;
|
||||
|
||||
// modifier keys
|
||||
switch (keycode) {
|
||||
case KEY_LeftControl: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<0))
|
||||
: (keyboard_modifier_keys &= ~(1<<0));
|
||||
return;
|
||||
case KEY_LeftShift: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<1))
|
||||
: (keyboard_modifier_keys &= ~(1<<1));
|
||||
return;
|
||||
case KEY_LeftAlt: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<2))
|
||||
: (keyboard_modifier_keys &= ~(1<<2));
|
||||
return;
|
||||
case KEY_LeftGUI: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<3))
|
||||
: (keyboard_modifier_keys &= ~(1<<3));
|
||||
return;
|
||||
case KEY_RightControl: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<4))
|
||||
: (keyboard_modifier_keys &= ~(1<<4));
|
||||
return;
|
||||
case KEY_RightShift: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<5))
|
||||
: (keyboard_modifier_keys &= ~(1<<5));
|
||||
return;
|
||||
case KEY_RightAlt: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<6))
|
||||
: (keyboard_modifier_keys &= ~(1<<6));
|
||||
return;
|
||||
case KEY_RightGUI: (pressed)
|
||||
? (keyboard_modifier_keys |= (1<<7))
|
||||
: (keyboard_modifier_keys &= ~(1<<7));
|
||||
return;
|
||||
}
|
||||
|
||||
// all others
|
||||
for (uint8_t i=0; i<6; i++) {
|
||||
if (pressed) {
|
||||
if (keyboard_keys[i] == 0) {
|
||||
keyboard_keys[i] = keycode;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (keyboard_keys[i] == keycode) {
|
||||
keyboard_keys[i] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set current layer
|
||||
* - Sets any keys currently set to the overall current layer to the new layer,
|
||||
* and then sets the overall current layer
|
||||
*
|
||||
* Arguments
|
||||
* - layer: the new layer value
|
||||
* - current_layer: (a pointer to) the overall current layer (see main.c)
|
||||
* - current_layers: (a pointer to a matrix of) the current layer for each key
|
||||
* (see main.c and lib/key-functions.h)
|
||||
*
|
||||
* Note
|
||||
* - Leaving all non-current layer values alone allows changing layers while
|
||||
* maintaining a possibly enabled layer mask (as might be used to implement
|
||||
* firmware enabled numlock)
|
||||
*/
|
||||
void _layer_set_current(
|
||||
uint8_t layer,
|
||||
uint8_t * current_layer,
|
||||
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
|
||||
|
||||
// don't switch to out-of-bounds layers
|
||||
if ( layer < 0 || layer >= KB_LAYERS )
|
||||
return;
|
||||
|
||||
for (uint8_t row=0; row<KB_ROWS; row++)
|
||||
for (uint8_t col=0; col<KB_COLUMNS; col++)
|
||||
// if a key is set to a non-current layer, leave it
|
||||
if ((*current_layers)[row][col] == *current_layer)
|
||||
(*current_layers)[row][col] = layer;
|
||||
|
||||
(*current_layer) = layer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set layer mask
|
||||
* - Sets the specified key positions to the specified layer
|
||||
*/
|
||||
void _layer_set_mask(
|
||||
uint8_t layer,
|
||||
bool positions[KB_ROWS][KB_COLUMNS],
|
||||
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
|
||||
|
||||
// don't switch to out-of-bounds layers
|
||||
if ( layer < 0 || layer >= KB_LAYERS )
|
||||
return;
|
||||
|
||||
for (uint8_t row=0; row<KB_ROWS; row++)
|
||||
for (uint8_t col=0; col<KB_COLUMNS; col++)
|
||||
if (positions[row][col])
|
||||
(*current_layers)[row][col] = layer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the given keycode pressed?
|
||||
*/
|
||||
bool _is_pressed(uint8_t keycode) {
|
||||
// modifier keys
|
||||
switch (keycode) {
|
||||
case KEY_LeftControl: if (keyboard_modifier_keys & (1<<0))
|
||||
return true;
|
||||
case KEY_LeftShift: if (keyboard_modifier_keys & (1<<1))
|
||||
return true;
|
||||
case KEY_LeftAlt: if (keyboard_modifier_keys & (1<<2))
|
||||
return true;
|
||||
case KEY_LeftGUI: if (keyboard_modifier_keys & (1<<3))
|
||||
return true;
|
||||
case KEY_RightControl: if (keyboard_modifier_keys & (1<<4))
|
||||
return true;
|
||||
case KEY_RightShift: if (keyboard_modifier_keys & (1<<5))
|
||||
return true;
|
||||
case KEY_RightAlt: if (keyboard_modifier_keys & (1<<6))
|
||||
return true;
|
||||
case KEY_RightGUI: if (keyboard_modifier_keys & (1<<7))
|
||||
return true;
|
||||
}
|
||||
|
||||
// all others
|
||||
for (uint8_t i=0; i<6; i++)
|
||||
if (keyboard_keys[i] == keycode)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// public functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Press|Release
|
||||
* - Generate a normal keypress or keyrelease
|
||||
*/
|
||||
void kbfun_press_release( KBFUN_FUNCTION_ARGS ) {
|
||||
_press_release(pressed_, keycode_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggle
|
||||
* - Toggle the key pressed or unpressed
|
||||
*/
|
||||
void kbfun_toggle( KBFUN_FUNCTION_ARGS ) {
|
||||
if (_is_pressed(keycode_))
|
||||
_press_release(false, keycode_);
|
||||
else
|
||||
_press_release(true, keycode_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase layer
|
||||
* - Increment the current layer by the value specified in the keymap (for all
|
||||
* non-masked keys)
|
||||
*/
|
||||
void kbfun_layer_inc( KBFUN_FUNCTION_ARGS ) {
|
||||
_layer_set_current(
|
||||
(*current_layer_) + keycode_,
|
||||
current_layer_,
|
||||
current_layers_ );
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrease layer
|
||||
* - Decrement the current layer by the value specified in the keymap (for all
|
||||
* non-masked keys)
|
||||
*/
|
||||
void kbfun_layer_dec( KBFUN_FUNCTION_ARGS ) {
|
||||
_layer_set_current(
|
||||
(*current_layer_) - keycode_,
|
||||
current_layer_,
|
||||
current_layers_ );
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase layer, Execute key
|
||||
* - Increment the current layer by the value specified in the keymap (for all
|
||||
* non-masked keys), and execute (usually press|release) the key in the same
|
||||
* position on that new layer
|
||||
*
|
||||
* Note
|
||||
* - Meant to be paired with `kbfun_layer_dec_exec()`
|
||||
*/
|
||||
void kbfun_layer_inc_exec( KBFUN_FUNCTION_ARGS ) {
|
||||
// switch layers
|
||||
_layer_set_current(
|
||||
(*current_layer_) + keycode_,
|
||||
current_layer_,
|
||||
current_layers_ );
|
||||
|
||||
// exececute second key (in the same position)
|
||||
// - `layer_+keycode_` will be constant (under normal circumstances)
|
||||
// between the press and release
|
||||
_kbfun_exec_key(
|
||||
pressed_, 0, layer_+keycode_,
|
||||
row_, col_, current_layer_,
|
||||
current_layers_, pressed_layers_ );
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrease layer, Execute key
|
||||
* - Decrement the current layer by the value specified in the keymap (for all
|
||||
* non-masked keys), and execute (usually press|release) the key in the same
|
||||
* position on that new layer
|
||||
*
|
||||
* Note
|
||||
* - Meant to be paired with `kbfun_layer_inc_exec()`
|
||||
*/
|
||||
void kbfun_layer_dec_exec( KBFUN_FUNCTION_ARGS ) {
|
||||
// switch layers
|
||||
_layer_set_current(
|
||||
(*current_layer_) - keycode_,
|
||||
current_layer_,
|
||||
current_layers_ );
|
||||
|
||||
// exececute second key (in the same position)
|
||||
// - `layer_+keycode_` will be constant (under normal circumstances)
|
||||
// between the press and release
|
||||
_kbfun_exec_key(
|
||||
pressed_, 0, layer_+keycode_,
|
||||
row_, col_, current_layer_,
|
||||
current_layers_, pressed_layers_ );
|
||||
}
|
||||
|
||||
/*
|
||||
* Two keys => capslock
|
||||
* - When assigned to two keys (e.g. the physical left and right shift keys)
|
||||
* (in both the press and release matrices), pressing and holding down one of
|
||||
* the keys will make the second key toggle capslock
|
||||
*
|
||||
* Note
|
||||
* - If either of the shifts are pressed when the second key is pressed, they
|
||||
* wil be released so that capslock will register properly when pressed.
|
||||
* Capslock will then be pressed and released, and the original state of the
|
||||
* shifts will be restored
|
||||
*/
|
||||
void kbfun_2_keys_capslock_press_release( KBFUN_FUNCTION_ARGS ) {
|
||||
static uint8_t keys_pressed;
|
||||
static bool lshift_pressed;
|
||||
static bool rshift_pressed;
|
||||
|
||||
if (!pressed_) keys_pressed--;
|
||||
|
||||
// take care of the key that was actually pressed
|
||||
_press_release(pressed_, keycode_);
|
||||
|
||||
// take care of capslock (only on the press of the 2nd key)
|
||||
if (keys_pressed == 1 && pressed_) {
|
||||
// save the state of left and right shift
|
||||
lshift_pressed = _is_pressed(KEY_LeftShift);
|
||||
rshift_pressed = _is_pressed(KEY_RightShift);
|
||||
// disable both
|
||||
_press_release(false, KEY_LeftShift);
|
||||
_press_release(false, KEY_RightShift);
|
||||
|
||||
// press capslock, then release it
|
||||
_press_release(true, KEY_CapsLock);
|
||||
usb_keyboard_send();
|
||||
_press_release(false, KEY_CapsLock);
|
||||
usb_keyboard_send();
|
||||
|
||||
// restore the state of left and right shift
|
||||
if (lshift_pressed)
|
||||
_press_release(true, KEY_LeftShift);
|
||||
if (rshift_pressed)
|
||||
_press_release(true, KEY_RightShift);
|
||||
}
|
||||
|
||||
if (pressed_) keys_pressed++;
|
||||
}
|
||||
|
||||
|
||||
// TODO: maybe the numpad functions (and other logical sets of functions?) need
|
||||
// to be in (a) seaparate file(s).
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Numpad functions
|
||||
* - Functions to implement an embedded numpad
|
||||
*
|
||||
* Notes
|
||||
* - The numpad is toggled by shifting (without changing the overall current
|
||||
* layer) the layer of the keys specified in this function to the value
|
||||
* specified in the keymap
|
||||
* - When the numpad is toggled, the numlock is set to on (for active) or off
|
||||
* (for inactive) as well
|
||||
* - All these functions cooperate, but if more than one layer mask of this
|
||||
* type is used (by a different set of functions) at the same time, the
|
||||
* second will override the first, and any keys covered by both will be reset
|
||||
* to the overall current layer when either is released (even if the other is
|
||||
* still pressed)
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
// prefix function (undefined later)
|
||||
// - to keep these names reasonable in this block, and obviously not global
|
||||
// outside it
|
||||
// - 'L' is for 'local'
|
||||
#define L(name) _kbfun_layermask_numpad__##name
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
// vars
|
||||
static bool L(numpad_activated) = false;
|
||||
static bool L(layer_mask)[KB_ROWS][KB_COLUMNS] =
|
||||
MATRIX_LAYER(
|
||||
// unused
|
||||
0,
|
||||
|
||||
// left hand
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
|
||||
// right hand
|
||||
0, 0, 1, 1, 1, 1, 0,
|
||||
0, 0, 1, 1, 1, 1, 0,
|
||||
0, 1, 1, 1, 1, 0,
|
||||
0, 0, 1, 1, 1, 1, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
0,
|
||||
0, 0,
|
||||
0, 0, 0 );
|
||||
|
||||
// functions
|
||||
static inline void L(toggle_numlock)(void) {
|
||||
_press_release(true, KEYPAD_NumLock_Clear);
|
||||
usb_keyboard_send();
|
||||
_press_release(false, KEYPAD_NumLock_Clear);
|
||||
usb_keyboard_send();
|
||||
}
|
||||
|
||||
static void L(toggle_numpad)(
|
||||
uint8_t numpad_layer,
|
||||
uint8_t current_layer,
|
||||
uint8_t (*current_layers)[KB_ROWS][KB_COLUMNS] ) {
|
||||
|
||||
if (L(numpad_activated)) {
|
||||
// deactivate numpad
|
||||
_layer_set_mask(current_layer, L(layer_mask), current_layers);
|
||||
L(numpad_activated) = false;
|
||||
|
||||
// if: numlock on
|
||||
if (keyboard_leds & (1<<0))
|
||||
L(toggle_numlock)();
|
||||
} else {
|
||||
// activate numpad
|
||||
_layer_set_mask(numpad_layer, L(layer_mask), current_layers);
|
||||
L(numpad_activated) = true;
|
||||
|
||||
// if: numlock off
|
||||
if (!(keyboard_leds & (1<<0)))
|
||||
L(toggle_numlock)();
|
||||
}
|
||||
}
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
/*
|
||||
* Numpad toggle
|
||||
* - Toggles the numpad and sets numlock on (for active) or off (for inactive)
|
||||
* with it, if it's not already in that state
|
||||
*/
|
||||
void kbfun_layermask_numpad_toggle( KBFUN_FUNCTION_ARGS ) {
|
||||
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Numpad on
|
||||
* - Set the numpad on (along with numlock, if it's not already)
|
||||
*/
|
||||
void kbfun_layermask_numpad_on( KBFUN_FUNCTION_ARGS ) {
|
||||
if (!L(numpad_activated))
|
||||
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Numpad off
|
||||
* - Set the numpad off (along with numlock, if it's not already)
|
||||
*/
|
||||
void kbfun_layermask_numpad_off( KBFUN_FUNCTION_ARGS ) {
|
||||
if (L(numpad_activated))
|
||||
L(toggle_numpad)(keycode_, *current_layer_, current_layers_);
|
||||
}
|
||||
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
// prefix function (undefined here)
|
||||
#undef L
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// public functions (device specific)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void kbfun_jump_to_bootloader( KBFUN_FUNCTION_ARGS ) {
|
||||
|
||||
// from PJRC (slightly modified)
|
||||
// <http://www.pjrc.com/teensy/jump_to_bootloader.html>
|
||||
#if MAKEFILE_BOARD == teensy-2-0
|
||||
// --- for all Teensy boards
|
||||
cli();
|
||||
|
||||
// disable watchdog, if enabled
|
||||
// disable all peripherals
|
||||
UDCON = 1;
|
||||
USBCON = (1<<FRZCLK); // disable USB
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5);
|
||||
|
||||
// --- Teensy 2.0 specific
|
||||
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
|
||||
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
|
||||
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
|
||||
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
|
||||
asm volatile("jmp 0x7E00");
|
||||
#endif
|
||||
|
||||
// else, function does nothing
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions: exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEY_FUNCTIONS_h
|
||||
#define KEY_FUNCTIONS_h
|
||||
|
||||
#include "lib/data-types.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// include the appropriate 'matrix.h'
|
||||
// -------
|
||||
// we're not simply including 'keyboard.h' here because this header is
|
||||
// meant to be included by 'keyboard/layout/*.c', which is indirectly
|
||||
// included by 'keyboard.h'; and that would lead to a circular include,
|
||||
// which gcc might (depending on the order of include statements it
|
||||
// encounters) deal with by processing this file before 'matrix.h',
|
||||
// which would give us undefined macros here
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
#define _str(s) #s // stringify
|
||||
#define _expstr(s) _str(s) // expand -> stringify
|
||||
#define _inc _expstr(keyboard/MAKEFILE_KEYBOARD/matrix.h) // inc(lude)
|
||||
#include _inc
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
|
||||
#define KBFUN_FUNCTION_ARGS \
|
||||
bool pressed_, \
|
||||
uint8_t keycode_, \
|
||||
uint8_t layer_, \
|
||||
uint8_t * row_, \
|
||||
uint8_t * col_, \
|
||||
uint8_t * current_layer_, \
|
||||
uint8_t (*current_layers_)[KB_ROWS][KB_COLUMNS], \
|
||||
uint8_t (*pressed_layers_)[KB_ROWS][KB_COLUMNS]
|
||||
|
||||
typedef void (*kbfun_funptr_t)( KBFUN_FUNCTION_ARGS );
|
||||
|
||||
void _kbfun_exec_key ( KBFUN_FUNCTION_ARGS );
|
||||
|
||||
void kbfun_press_release (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_toggle (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_layer_inc (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_layer_dec (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_layer_inc_exec (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_layer_dec_exec (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_2_keys_capslock_press_release (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_layermask_numpad_toggle (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_layermask_numpad_on (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_layermask_numpad_off (KBFUN_FUNCTION_ARGS);
|
||||
void kbfun_jump_to_bootloader (KBFUN_FUNCTION_ARGS);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions : private : code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "../../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "../../lib/usb/usage-page/keyboard.h"
|
||||
#include "../../keyboard/layout.h"
|
||||
#include "../../keyboard/matrix.h"
|
||||
#include "../../main.h"
|
||||
#include "./public.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Generate a normal keypress or keyrelease
|
||||
*
|
||||
* Arguments
|
||||
* - press: whether to generate a keypress (true) or keyrelease (false)
|
||||
* - keycode: the keycode to use
|
||||
*
|
||||
* Note
|
||||
* - Because of the way USB does things, what this actually does is either add
|
||||
* or remove 'keycode' from the list of currently pressed keys, to be sent at
|
||||
* the end of the current cycle (see main.c)
|
||||
*/
|
||||
void _kbfun_press_release(bool press, uint8_t keycode) {
|
||||
// no-op
|
||||
if (keycode == 0)
|
||||
return;
|
||||
|
||||
// modifier keys
|
||||
switch (keycode) {
|
||||
case KEY_LeftControl: (press)
|
||||
? (keyboard_modifier_keys |= (1<<0))
|
||||
: (keyboard_modifier_keys &= ~(1<<0));
|
||||
return;
|
||||
case KEY_LeftShift: (press)
|
||||
? (keyboard_modifier_keys |= (1<<1))
|
||||
: (keyboard_modifier_keys &= ~(1<<1));
|
||||
return;
|
||||
case KEY_LeftAlt: (press)
|
||||
? (keyboard_modifier_keys |= (1<<2))
|
||||
: (keyboard_modifier_keys &= ~(1<<2));
|
||||
return;
|
||||
case KEY_LeftGUI: (press)
|
||||
? (keyboard_modifier_keys |= (1<<3))
|
||||
: (keyboard_modifier_keys &= ~(1<<3));
|
||||
return;
|
||||
case KEY_RightControl: (press)
|
||||
? (keyboard_modifier_keys |= (1<<4))
|
||||
: (keyboard_modifier_keys &= ~(1<<4));
|
||||
return;
|
||||
case KEY_RightShift: (press)
|
||||
? (keyboard_modifier_keys |= (1<<5))
|
||||
: (keyboard_modifier_keys &= ~(1<<5));
|
||||
return;
|
||||
case KEY_RightAlt: (press)
|
||||
? (keyboard_modifier_keys |= (1<<6))
|
||||
: (keyboard_modifier_keys &= ~(1<<6));
|
||||
return;
|
||||
case KEY_RightGUI: (press)
|
||||
? (keyboard_modifier_keys |= (1<<7))
|
||||
: (keyboard_modifier_keys &= ~(1<<7));
|
||||
return;
|
||||
}
|
||||
|
||||
// all others
|
||||
for (uint8_t i=0; i<6; i++) {
|
||||
if (press) {
|
||||
if (keyboard_keys[i] == 0) {
|
||||
keyboard_keys[i] = keycode;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (keyboard_keys[i] == keycode) {
|
||||
keyboard_keys[i] = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Is the given keycode pressed?
|
||||
*/
|
||||
bool _kbfun_is_pressed(uint8_t keycode) {
|
||||
// modifier keys
|
||||
switch (keycode) {
|
||||
case KEY_LeftControl: if (keyboard_modifier_keys & (1<<0))
|
||||
return true;
|
||||
case KEY_LeftShift: if (keyboard_modifier_keys & (1<<1))
|
||||
return true;
|
||||
case KEY_LeftAlt: if (keyboard_modifier_keys & (1<<2))
|
||||
return true;
|
||||
case KEY_LeftGUI: if (keyboard_modifier_keys & (1<<3))
|
||||
return true;
|
||||
case KEY_RightControl: if (keyboard_modifier_keys & (1<<4))
|
||||
return true;
|
||||
case KEY_RightShift: if (keyboard_modifier_keys & (1<<5))
|
||||
return true;
|
||||
case KEY_RightAlt: if (keyboard_modifier_keys & (1<<6))
|
||||
return true;
|
||||
case KEY_RightGUI: if (keyboard_modifier_keys & (1<<7))
|
||||
return true;
|
||||
}
|
||||
|
||||
// all others
|
||||
for (uint8_t i=0; i<6; i++)
|
||||
if (keyboard_keys[i] == keycode)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions : private : exports
|
||||
*
|
||||
* Things to be used only by keyfunctions. Exported so layouts can use these
|
||||
* functions to help define their own, if they like.
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef LIB__KEY_FUNCTIONS__INTERNAL_h
|
||||
#define LIB__KEY_FUNCTIONS__INTERNAL_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "../../keyboard/matrix.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void _kbfun_press_release (bool press, uint8_t keycode);
|
||||
bool _kbfun_is_pressed (uint8_t keycode);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions : public exports
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef LIB__KEY_FUNCTIONS__COMMON_h
|
||||
#define LIB__KEY_FUNCTIONS__COMMON_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// basic
|
||||
void kbfun_press_release (void);
|
||||
void kbfun_toggle (void);
|
||||
void kbfun_transparent (void);
|
||||
// --- layer push/pop functions
|
||||
void kbfun_layer_push_1 (void);
|
||||
void kbfun_layer_push_2 (void);
|
||||
void kbfun_layer_push_3 (void);
|
||||
void kbfun_layer_push_4 (void);
|
||||
void kbfun_layer_push_5 (void);
|
||||
void kbfun_layer_push_6 (void);
|
||||
void kbfun_layer_push_7 (void);
|
||||
void kbfun_layer_push_8 (void);
|
||||
void kbfun_layer_push_9 (void);
|
||||
void kbfun_layer_push_10 (void);
|
||||
void kbfun_layer_pop_1 (void);
|
||||
void kbfun_layer_pop_2 (void);
|
||||
void kbfun_layer_pop_3 (void);
|
||||
void kbfun_layer_pop_4 (void);
|
||||
void kbfun_layer_pop_5 (void);
|
||||
void kbfun_layer_pop_6 (void);
|
||||
void kbfun_layer_pop_7 (void);
|
||||
void kbfun_layer_pop_8 (void);
|
||||
void kbfun_layer_pop_9 (void);
|
||||
void kbfun_layer_pop_10 (void);
|
||||
// ---
|
||||
|
||||
// device
|
||||
void kbfun_jump_to_bootloader (void);
|
||||
|
||||
// special
|
||||
void kbfun_shift_press_release (void);
|
||||
void kbfun_2_keys_capslock_press_release (void);
|
||||
void kbfun_layer_push_numpad (void);
|
||||
void kbfun_layer_pop_numpad (void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,344 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions : basic : code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 "../../../main.h"
|
||||
#include "../../../keyboard/layout.h"
|
||||
#include "../public.h"
|
||||
#include "../private.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define MAX_LAYER_PUSH_POP_FUNCTIONS 10
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// convenience macros
|
||||
#define LAYER main_arg_layer
|
||||
#define LAYER_OFFSET main_arg_layer_offset
|
||||
#define ROW main_arg_row
|
||||
#define COL main_arg_col
|
||||
#define IS_PRESSED main_arg_is_pressed
|
||||
#define WAS_PRESSED main_arg_was_pressed
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Press|Release
|
||||
*
|
||||
* [description]
|
||||
* Generate a normal keypress or keyrelease
|
||||
*/
|
||||
void kbfun_press_release(void) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
_kbfun_press_release(IS_PRESSED, keycode);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Toggle
|
||||
*
|
||||
* [description]
|
||||
* Toggle the key pressed or unpressed
|
||||
*/
|
||||
void kbfun_toggle(void) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
|
||||
if (_kbfun_is_pressed(keycode))
|
||||
_kbfun_press_release(false, keycode);
|
||||
else
|
||||
_kbfun_press_release(true, keycode);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Transparent
|
||||
*
|
||||
* [description]
|
||||
* Execute the key that would have been executed if the current layer was not
|
||||
* active
|
||||
*/
|
||||
void kbfun_transparent(void) {
|
||||
LAYER_OFFSET++;
|
||||
LAYER = main_layers_peek(LAYER_OFFSET);
|
||||
main_layers_pressed[ROW][COL] = LAYER;
|
||||
main_exec_key();
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* layer push/pop functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
static layer_ids[MAX_LAYER_PUSH_POP_FUNCTIONS];
|
||||
|
||||
static void layer_push(uint8_t local_id) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
main_layers_pop_id(layer_ids[local_id]);
|
||||
layer_ids[local_id] = main_layers_push(keycode);
|
||||
}
|
||||
|
||||
static void layer_pop(uint8_t local_id) {
|
||||
main_layers_pop_id(layer_ids[local_id]);
|
||||
layer_ids[local_id] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #1
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_1(void) {
|
||||
layer_push(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #1
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_1(void) {
|
||||
layer_pop(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #2
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_2(void) {
|
||||
layer_push(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #2
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_2(void) {
|
||||
layer_pop(2);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #3
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_3(void) {
|
||||
layer_push(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #3
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_3(void) {
|
||||
layer_pop(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #4
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_4(void) {
|
||||
layer_push(4);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #4
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_4(void) {
|
||||
layer_pop(4);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #5
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_5(void) {
|
||||
layer_push(5);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #5
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_5(void) {
|
||||
layer_pop(5);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #6
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_6(void) {
|
||||
layer_push(6);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #6
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_6(void) {
|
||||
layer_pop(6);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #7
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_7(void) {
|
||||
layer_push(7);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #7
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_7(void) {
|
||||
layer_pop(7);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #8
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_8(void) {
|
||||
layer_push(8);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #8
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_8(void) {
|
||||
layer_pop(8);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #9
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_9(void) {
|
||||
layer_push(9);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #9
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_9(void) {
|
||||
layer_pop(9);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer push #10
|
||||
*
|
||||
* [description]
|
||||
* Push a layer element containing the layer value specified in the keymap to
|
||||
* the top of the stack, and record the id of that layer element
|
||||
*/
|
||||
void kbfun_layer_push_10(void) {
|
||||
layer_push(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Layer pop #10
|
||||
*
|
||||
* [description]
|
||||
* Pop the layer element created by the corresponding "layer push" function
|
||||
* out of the layer stack (no matter where it is in the stack, without
|
||||
* touching any other elements)
|
||||
*/
|
||||
void kbfun_layer_pop_10(void) {
|
||||
layer_pop(10);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions : device specific : code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include "../public.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// descriptions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Jump to Bootloader
|
||||
*
|
||||
* [description]
|
||||
* For reflashing the controller
|
||||
*/
|
||||
void kbfun_jump_to_bootloader(void);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#if MAKEFILE_BOARD == teensy-2-0
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// from PJRC (slightly modified)
|
||||
// <http://www.pjrc.com/teensy/jump_to_bootloader.html>
|
||||
void kbfun_jump_to_bootloader(void) {
|
||||
// --- for all Teensy boards ---
|
||||
|
||||
cli();
|
||||
|
||||
// disable watchdog, if enabled
|
||||
// disable all peripherals
|
||||
UDCON = 1;
|
||||
USBCON = (1<<FRZCLK); // disable USB
|
||||
UCSR1B = 0;
|
||||
_delay_ms(5);
|
||||
|
||||
// --- Teensy 2.0 specific ---
|
||||
|
||||
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
|
||||
TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
|
||||
DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
|
||||
PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
|
||||
asm volatile("jmp 0x7E00");
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#else
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void kbfun_jump_to_bootloader(void) {}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* key functions : special : code
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "../../../lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "../../../lib/usb/usage-page/keyboard.h"
|
||||
#include "../../../keyboard/layout.h"
|
||||
#include "../../../main.h"
|
||||
#include "../public.h"
|
||||
#include "../private.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// convenience macros
|
||||
#define LAYER main_arg_layer
|
||||
#define LAYER_OFFSET main_arg_layer_offset
|
||||
#define ROW main_arg_row
|
||||
#define COL main_arg_col
|
||||
#define IS_PRESSED main_arg_is_pressed
|
||||
#define WAS_PRESSED main_arg_was_pressed
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Shift + press|release
|
||||
*
|
||||
* [description]
|
||||
* Generate a 'shift' press or release before the normal keypress or
|
||||
* keyrelease
|
||||
*/
|
||||
void kbfun_shift_press_release(void) {
|
||||
_kbfun_press_release(IS_PRESSED, KEY_LeftShift);
|
||||
kbfun_press_release();
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Two keys => capslock
|
||||
*
|
||||
* [description]
|
||||
* When assigned to two keys (e.g. the physical left and right shift keys)
|
||||
* (in both the press and release matrices), pressing and holding down one of
|
||||
* the keys will make the second key toggle capslock
|
||||
*
|
||||
* [note]
|
||||
* If either of the shifts are pressed when the second key is pressed, they
|
||||
* wil be released so that capslock will register properly when pressed.
|
||||
* Capslock will then be pressed and released, and the original state of the
|
||||
* shifts will be restored
|
||||
*/
|
||||
void kbfun_2_keys_capslock_press_release(void) {
|
||||
static uint8_t keys_pressed;
|
||||
static bool lshift_pressed;
|
||||
static bool rshift_pressed;
|
||||
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
|
||||
if (!IS_PRESSED) keys_pressed--;
|
||||
|
||||
// take care of the key that was actually pressed
|
||||
_kbfun_press_release(IS_PRESSED, keycode);
|
||||
|
||||
// take care of capslock (only on the press of the 2nd key)
|
||||
if (keys_pressed == 1 && IS_PRESSED) {
|
||||
// save the state of left and right shift
|
||||
lshift_pressed = _kbfun_is_pressed(KEY_LeftShift);
|
||||
rshift_pressed = _kbfun_is_pressed(KEY_RightShift);
|
||||
// disable both
|
||||
_kbfun_press_release(false, KEY_LeftShift);
|
||||
_kbfun_press_release(false, KEY_RightShift);
|
||||
|
||||
// press capslock, then release it
|
||||
_kbfun_press_release(true, KEY_CapsLock);
|
||||
usb_keyboard_send();
|
||||
_kbfun_press_release(false, KEY_CapsLock);
|
||||
usb_keyboard_send();
|
||||
|
||||
// restore the state of left and right shift
|
||||
if (lshift_pressed)
|
||||
_kbfun_press_release(true, KEY_LeftShift);
|
||||
if (rshift_pressed)
|
||||
_kbfun_press_release(true, KEY_RightShift);
|
||||
}
|
||||
|
||||
if (IS_PRESSED) keys_pressed++;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* numpad functions
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
static uint8_t numpad_layer_id;
|
||||
|
||||
static inline void numpad_toggle_numlock(void) {
|
||||
_kbfun_press_release(true, KEY_LockingNumLock);
|
||||
usb_keyboard_send();
|
||||
_kbfun_press_release(false, KEY_LockingNumLock);
|
||||
usb_keyboard_send();
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Numpad on
|
||||
*
|
||||
* [description]
|
||||
* Set the numpad to on (put the numpad layer, specified in the keymap, in an
|
||||
* element at the top of the layer stack, and record that element's id) and
|
||||
* toggle numlock (regardless of whether or not numlock is currently on)
|
||||
*
|
||||
* [note]
|
||||
* Meant to be assigned (along with "numpad off") instead of a normal numlock
|
||||
* key
|
||||
*/
|
||||
void kbfun_layer_push_numpad(void) {
|
||||
uint8_t keycode = kb_layout_get(LAYER, ROW, COL);
|
||||
main_layers_pop_id(numpad_layer_id);
|
||||
numpad_layer_id = main_layers_push(keycode);
|
||||
numpad_toggle_numlock();
|
||||
}
|
||||
|
||||
/*
|
||||
* [name]
|
||||
* Numpad off
|
||||
*
|
||||
* [description]
|
||||
* Set the numpad to off (pop the layer element created by "numpad on" out of
|
||||
* the stack) and toggle numlock (regardless of whether or not numlock is
|
||||
* currently on)
|
||||
*
|
||||
* [note]
|
||||
* Meant to be assigned (along with "numpad on") instead of a normal numlock
|
||||
* key
|
||||
*/
|
||||
void kbfun_layer_pop_numpad(void) {
|
||||
main_layers_pop_id(numpad_layer_id);
|
||||
numpad_layer_id = 0;
|
||||
numpad_toggle_numlock();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# src/lib/key-functions
|
||||
|
||||
These functions may do.. pretty much anything rational that they like. If they
|
||||
want keycodes to be sent to the host in an aggregate report, they're responsible
|
||||
for modifying the appropriate report variables.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
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>
|
||||
|
|
@ -10,14 +10,7 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
#define _str(s) #s // stringify
|
||||
#define _expstr(s) _str(s) // expand -> stringify
|
||||
#define _inc _expstr(twi/MAKEFILE_BOARD.h) // inc(lude)
|
||||
#include _inc
|
||||
#undef _str
|
||||
#undef _expstr
|
||||
#undef _inc
|
||||
#include "../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./twi/MAKEFILE_BOARD.h )
|
||||
#include INCLUDE
|
||||
|
||||
|
|
|
@ -21,10 +21,17 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <util/twi.h>
|
||||
#include "lib/twi.h"
|
||||
// ----------------------------------------------------------------------------
|
||||
// conditional compile
|
||||
#if MAKEFILE_BOARD == teensy-2-0
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <util/twi.h>
|
||||
#include "./teensy-2-0.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void twi_init(void) {
|
||||
// set the prescaler value to 0
|
||||
TWSR &= ~( (1<<TWPS1)|(1<<TWPS0) );
|
||||
|
@ -81,3 +88,8 @@ uint8_t twi_read(uint8_t * data) {
|
|||
return 0; // success
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -10,16 +10,19 @@
|
|||
#ifndef TWI_h
|
||||
#define TWI_h
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef TWI_FREQ
|
||||
#define TWI_FREQ 100000 // in Hz
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void twi_init(void);
|
||||
uint8_t twi_start(void);
|
||||
void twi_stop(void);
|
||||
uint8_t twi_send(uint8_t data);
|
||||
uint8_t twi_read(uint8_t * data);
|
||||
void twi_init (void);
|
||||
uint8_t twi_start (void);
|
||||
void twi_stop (void);
|
||||
uint8_t twi_send (uint8_t data);
|
||||
uint8_t twi_read (uint8_t * data);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
// TODO
|
||||
// - read the hid device class definition .pdf
|
||||
// - set USB vendor ID = 0x1d50 // Openmoko, Inc.
|
||||
// USB product ID = 0x6028 // ErgoDox ergonomic keyboard
|
||||
|
||||
// DONE
|
||||
// - read the hid usage tables .pdf
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "lib/data-types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "./keyboard.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Macros to help with conditional includes
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#undef INCLUDE
|
||||
#define STR(s) #s // stringify
|
||||
#define EXP_STR(s) STR(s) // expand -> stringify
|
||||
|
248
src/main.c
248
src/main.c
|
@ -8,14 +8,45 @@
|
|||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <util/delay.h>
|
||||
#include "lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "lib/data-types.h"
|
||||
#include "lib/key-functions.h"
|
||||
#include "./lib-other/pjrc/usb_keyboard/usb_keyboard.h"
|
||||
#include "./lib/key-functions/public.h"
|
||||
#include "./keyboard/controller.h"
|
||||
#include "./keyboard/layout.h"
|
||||
#include "./keyboard/matrix.h"
|
||||
#include "./main.h"
|
||||
|
||||
#include "keyboard.h"
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define MAX_ACTIVE_LAYERS 20
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static bool _main_kb_is_pressed[KB_ROWS][KB_COLUMNS];
|
||||
bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_main_kb_is_pressed;
|
||||
|
||||
static bool _main_kb_was_pressed[KB_ROWS][KB_COLUMNS];
|
||||
bool (*main_kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_main_kb_was_pressed;
|
||||
|
||||
uint8_t main_layers_pressed[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
uint8_t main_loop_row;
|
||||
uint8_t main_loop_col;
|
||||
|
||||
uint8_t main_arg_layer;
|
||||
uint8_t main_arg_layer_offset;
|
||||
uint8_t main_arg_row;
|
||||
uint8_t main_arg_col;
|
||||
bool main_arg_is_pressed;
|
||||
bool main_arg_was_pressed;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* main()
|
||||
*/
|
||||
int main(void) {
|
||||
kb_init(); // does controller initialization too
|
||||
|
||||
|
@ -28,24 +59,15 @@ int main(void) {
|
|||
kb_led_state_ready();
|
||||
|
||||
for (;;) {
|
||||
// the overall current layer
|
||||
static uint8_t current_layer;
|
||||
// the current layer for each key
|
||||
static uint8_t current_layers[KB_ROWS][KB_COLUMNS];
|
||||
// the layer each key was on when it was last pressed
|
||||
static uint8_t pressed_layers[KB_ROWS][KB_COLUMNS];
|
||||
// swap `main_kb_is_pressed` and `main_kb_was_pressed`, then update
|
||||
bool (*temp)[KB_ROWS][KB_COLUMNS] = main_kb_was_pressed;
|
||||
main_kb_was_pressed = main_kb_is_pressed;
|
||||
main_kb_is_pressed = temp;
|
||||
|
||||
// swap `kb_is_pressed` and `kb_was_pressed`, then update
|
||||
bool (*temp)[KB_ROWS][KB_COLUMNS] = kb_was_pressed;
|
||||
kb_was_pressed = kb_is_pressed;
|
||||
kb_is_pressed = temp;
|
||||
|
||||
kb_update_matrix(*kb_is_pressed);
|
||||
kb_update_matrix(*main_kb_is_pressed);
|
||||
|
||||
// this loop is responsible to
|
||||
// - "execute" keys when they change state (call `_kbfun_exec_key()`,
|
||||
// which will call the appropriate function with the appropriate
|
||||
// keycode argument from the kb_layout* matrices)
|
||||
// - "execute" keys when they change state
|
||||
// - keep track of which layers the keys were on when they were pressed
|
||||
// (so they can be released using the function from that layer)
|
||||
//
|
||||
|
@ -53,34 +75,42 @@ int main(void) {
|
|||
// - everything else is the key function's responsibility
|
||||
// - see the keyboard layout file ("keyboard/ergodox/layout/*.c") for
|
||||
// which key is assigned which function (per layer)
|
||||
// - see "lib/key-functions.c" for the function definitions
|
||||
// - anything passed to the key function by reference is fair game for
|
||||
// that function to modify
|
||||
for (uint8_t row=0; row<KB_ROWS; row++) {
|
||||
for (uint8_t col=0; col<KB_COLUMNS; col++) {
|
||||
|
||||
bool is_pressed = (*kb_is_pressed)[row][col];
|
||||
bool was_pressed = (*kb_was_pressed)[row][col];
|
||||
// - see "lib/key-functions/public/*.c" for the function definitions
|
||||
#define row main_loop_row
|
||||
#define col main_loop_col
|
||||
#define layer main_arg_layer
|
||||
#define is_pressed main_arg_is_pressed
|
||||
#define was_pressed main_arg_was_pressed
|
||||
for (row=0; row<KB_ROWS; row++) {
|
||||
for (col=0; col<KB_COLUMNS; col++) {
|
||||
is_pressed = (*main_kb_is_pressed)[row][col];
|
||||
was_pressed = (*main_kb_was_pressed)[row][col];
|
||||
|
||||
if (is_pressed != was_pressed) {
|
||||
uint8_t layer = ( (is_pressed)
|
||||
? current_layers[row][col]
|
||||
: pressed_layers[row][col] );
|
||||
if (is_pressed) {
|
||||
layer = main_layers_peek(0);
|
||||
main_layers_pressed[row][col] = layer;
|
||||
} else {
|
||||
layer = main_layers_pressed[row][col];
|
||||
}
|
||||
|
||||
if (is_pressed)
|
||||
pressed_layers[row][col] = layer;
|
||||
|
||||
_kbfun_exec_key(
|
||||
is_pressed, 0, layer,
|
||||
&row, &col, ¤t_layer,
|
||||
¤t_layers, &pressed_layers );
|
||||
// set remaining vars, and "execute" key
|
||||
main_arg_row = row;
|
||||
main_arg_col = col;
|
||||
main_arg_layer_offset = 0;
|
||||
main_exec_key();
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef row
|
||||
#undef col
|
||||
#undef layer
|
||||
#undef is_pressed
|
||||
#undef was_pressed
|
||||
|
||||
// send the USB report (even if nothing's changed)
|
||||
usb_keyboard_send();
|
||||
_delay_ms(KB_DEBOUNCE_TIME);
|
||||
_delay_ms(MAKEFILE_DEBOUNCE_TIME);
|
||||
|
||||
// update LEDs
|
||||
if (keyboard_leds & (1<<0)) { kb_led_num_on(); }
|
||||
|
@ -98,3 +128,145 @@ int main(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// convenience macros (for the helper functions below)
|
||||
#define layer main_arg_layer
|
||||
#define row main_arg_row
|
||||
#define col main_arg_col
|
||||
#define is_pressed main_arg_is_pressed
|
||||
#define was_pressed main_arg_was_pressed
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Exec key
|
||||
* - Execute the keypress or keyrelease function (if it exists) of the key at
|
||||
* the current possition.
|
||||
*/
|
||||
void main_exec_key(void) {
|
||||
void (*key_function)(void) =
|
||||
( (is_pressed)
|
||||
? kb_layout_press_get(layer, row, col)
|
||||
: kb_layout_release_get(layer, row, col) );
|
||||
|
||||
if (key_function)
|
||||
(*key_function)();
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Layer Functions
|
||||
* ----------------------------------------------------------------------------
|
||||
* We keep track of which layer is foremost by placing it on a stack. Layers
|
||||
* may appear in the stack more than once. The base layer will always be
|
||||
* layer-0.
|
||||
*
|
||||
* Implemented as a fixed size stack.
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct layers {
|
||||
uint8_t layer;
|
||||
uint8_t id;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct layers layers[MAX_ACTIVE_LAYERS];
|
||||
uint8_t layers_head = 0;
|
||||
uint8_t layers_ids_in_use[MAX_ACTIVE_LAYERS] = {true};
|
||||
|
||||
/*
|
||||
* peek()
|
||||
*
|
||||
* Arguments
|
||||
* - 'offset': the offset (down the stack) from the head element
|
||||
*
|
||||
* Returns
|
||||
* - success: the layer-number of the requested element (which may be 0)
|
||||
* - failure: 0 (default) (out of bounds)
|
||||
*/
|
||||
uint8_t main_layers_peek(uint8_t offset) {
|
||||
if (offset <= layers_head)
|
||||
return layers[layers_head - offset].layer;
|
||||
|
||||
return 0; // default, or error
|
||||
}
|
||||
|
||||
/*
|
||||
* push()
|
||||
*
|
||||
* Arguments
|
||||
* - 'layer': the layer-number to push to the top of the stack
|
||||
*
|
||||
* Returns
|
||||
* - success: the id assigned to the newly added element
|
||||
* - failure: 0 (the stack was already full)
|
||||
*/
|
||||
uint8_t main_layers_push(uint8_t layer) {
|
||||
// look for an available id
|
||||
for (uint8_t id=1; id<MAX_ACTIVE_LAYERS; id++)
|
||||
// if one is found
|
||||
if (layers_ids_in_use[id] == false) {
|
||||
layers_ids_in_use[id] = true;
|
||||
layers_head++;
|
||||
layers[layers_head].layer = layer;
|
||||
layers[layers_head].id = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
return 0; // default, or error
|
||||
}
|
||||
|
||||
/*
|
||||
* pop_id()
|
||||
*
|
||||
* Arguments
|
||||
* - 'id': the id of the element to pop from the stack
|
||||
*/
|
||||
void main_layers_pop_id(uint8_t id) {
|
||||
// look for the element with the id we want to pop
|
||||
for (uint8_t element=1; element<=layers_head; element++)
|
||||
// if we find it
|
||||
if (layers[element].id == id) {
|
||||
// move all layers above it down one
|
||||
for (; element<layers_head; element++) {
|
||||
layers[element].layer = layers[element+1].layer;
|
||||
layers[element].id = layers[element+1].id;
|
||||
}
|
||||
// reinitialize the topmost (now unused) slot
|
||||
layers[layers_head].layer = 0;
|
||||
layers[layers_head].id = 0;
|
||||
// record keeping
|
||||
layers_ids_in_use[id] = false;
|
||||
layers_head--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_offset_id()
|
||||
*
|
||||
* Arguments
|
||||
* - 'id': the id of the element you want the offset of
|
||||
*
|
||||
* Returns
|
||||
* - success: the offset (down the stack from the head element) of the element
|
||||
* with the given id
|
||||
* - failure: 0 (default) (id unassigned)
|
||||
*/
|
||||
uint8_t main_layers_get_offset_id(uint8_t id) {
|
||||
// look for the element with the id we want to get the offset of
|
||||
for (uint8_t element=1; element<=layers_head; element++)
|
||||
// if we find it
|
||||
if (layers[element].id == id)
|
||||
return (layers_head - element);
|
||||
|
||||
return 0; // default, or error
|
||||
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* main() : functions and data that may be useful externally
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef MAIN_h
|
||||
#define MAIN_h
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "./lib/key-functions/public.h"
|
||||
#include "./keyboard/matrix.h"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
extern bool (*main_kb_is_pressed)[KB_ROWS][KB_COLUMNS];
|
||||
extern bool (*main_kb_was_pressed)[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
extern uint8_t main_layers_pressed[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
extern uint8_t main_loop_row;
|
||||
extern uint8_t main_loop_col;
|
||||
|
||||
extern uint8_t main_arg_layer;
|
||||
extern uint8_t main_arg_layer_offset;
|
||||
extern uint8_t main_arg_row;
|
||||
extern uint8_t main_arg_col;
|
||||
extern bool main_arg_is_pressed;
|
||||
extern bool main_arg_was_pressed;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void main_exec_key (void);
|
||||
|
||||
uint8_t main_layers_peek (uint8_t offset);
|
||||
uint8_t main_layers_push (uint8_t layer);
|
||||
void main_layers_pop_id (uint8_t id);
|
||||
uint8_t main_layers_get_offset_id (uint8_t id);
|
||||
|
||||
|
||||
#endif
|
||||
|
30
src/makefile
30
src/makefile
|
@ -13,15 +13,12 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
TARGET := firmware # the name we want for our program binary
|
||||
FORMAT := ihex # the program binary's format
|
||||
KEYBOARD := ergodox # keyboard model; see "src/keyboard" for what's available
|
||||
LAYOUT := qwerty # keyboard layout; see "src/keyboard/*/layout" for what's
|
||||
# available
|
||||
include makefile-options
|
||||
|
||||
MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
|
||||
BOARD := teensy-2-0 # see the libraries you're using for what's available
|
||||
F_CPU := 16000000 # processor speed, in Hz
|
||||
FORMAT := ihex # the program binary's format
|
||||
MCU := atmega32u4 # processor type (for teensy 2.0); must match real life
|
||||
BOARD := teensy-2-0 # see the libraries you're using for what's available
|
||||
F_CPU := 16000000 # processor speed, in Hz
|
||||
|
||||
# firmware stuff
|
||||
SRC := $(wildcard *.c)
|
||||
|
@ -32,8 +29,11 @@ LAYOUT := $(strip $(LAYOUT))
|
|||
# --- include stuff
|
||||
SRC += $(wildcard keyboard/$(KEYBOARD)*.c)
|
||||
SRC += $(wildcard keyboard/$(KEYBOARD)/*.c)
|
||||
SRC += $(wildcard keyboard/$(KEYBOARD)/controller/*.c)
|
||||
SRC += $(wildcard keyboard/$(KEYBOARD)/layout/$(LAYOUT)*.c)
|
||||
# library stuff
|
||||
# - should be last in the list of files to compile, in case there are default
|
||||
# macros that have to be overridden in other source files
|
||||
# - add more "*/*/..."s as necessary to compile everything.
|
||||
# - parts of the stuff under "lib" may not be necessary, depending on other
|
||||
# options, but it's all included here. hopefully any unnecessary stuff gets
|
||||
|
@ -48,15 +48,17 @@ SRC += $(wildcard lib-other/*/*/*.c)
|
|||
OBJ = $(SRC:%.c=%.o)
|
||||
|
||||
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
CFLAGS := -mmcu=$(MCU) # processor type (teensy 2.0); must match real
|
||||
# life
|
||||
CFLAGS += -DF_CPU=$(F_CPU) # processor frequency; must match initialization
|
||||
# in source
|
||||
CFLAGS += -I. # search for includes in the current directory
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
CFLAGS += -DMAKEFILE_BOARD='$(strip $(BOARD))'
|
||||
CFLAGS += -DMAKEFILE_KEYBOARD='$(strip $(KEYBOARD))'
|
||||
CFLAGS += -DMAKEFILE_KEYBOARD_LAYOUT='$(strip $(LAYOUT))'
|
||||
CFLAGS += -DMAKEFILE_DEBOUNCE_TIME='$(strip $(DEBOUNCE_TIME))'
|
||||
CFLAGS += -DMAKEFILE_LED_BRIGHTNESS='$(strip $(LED_BRIGHTNESS))'
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
CFLAGS += -std=gnu99 # use C99 plus GCC extensions
|
||||
CFLAGS += -Os # optimize for size
|
||||
|
@ -83,6 +85,7 @@ LDFLAGS += -Wl,--gc-sections # discard unused functions and data
|
|||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
GENDEPFLAGS += -MMD -MP -MF $@.dep # generate dependency files
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
CC := avr-gcc
|
||||
|
@ -90,10 +93,10 @@ OBJCOPY := avr-objcopy
|
|||
SIZE := avr-size
|
||||
|
||||
|
||||
# remove whitespace from some of the variables
|
||||
TARGET := $(strip $(TARGET))
|
||||
# remove whitespace from some of the options
|
||||
FORMAT := $(strip $(FORMAT))
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
@ -108,11 +111,6 @@ all: $(TARGET).hex $(TARGET).eep
|
|||
@echo
|
||||
$(SIZE) --target=$(FORMAT) $(TARGET).eep
|
||||
@echo
|
||||
@echo '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'
|
||||
@echo
|
||||
$(SIZE) -C --mcu=atmega32u4 $(TARGET).elf
|
||||
@echo '. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .'
|
||||
@echo
|
||||
@echo 'you can load "$(TARGET).hex" and "$(TARGET).eep" onto the'
|
||||
@echo 'Teensy using the Teensy loader'
|
||||
@echo
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# certain compilations options
|
||||
# -----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
# Released under The MIT License (MIT) (see "license.md")
|
||||
# Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
TARGET := firmware # the name we want for our program binary
|
||||
KEYBOARD := ergodox # keyboard model; see "src/keyboard" for what's available
|
||||
LAYOUT := qwerty-kinesis-mod # keyboard layout
|
||||
# see "src/keyboard/*/layout" for what's
|
||||
# available
|
||||
|
||||
LED_BRIGHTNESS := 0.5 # a multiplier, with 1 being the max
|
||||
DEBOUNCE_TIME := 5 # in ms; see keyswitch spec for necessary value; 5ms should
|
||||
# be good for cherry mx switches
|
||||
|
||||
|
||||
# remove whitespace
|
||||
TARGET := $(strip $(TARGET))
|
||||
KEYBOARD := $(strip $(KEYBOARD))
|
||||
LAYOUT := $(strip $(LAYOUT))
|
||||
DEBOUNCE_TIME := $(strip $(DEBOUNCE_TIME))
|
||||
|
Loading…
Reference in New Issue