Compare commits
221 Commits
partial-re
...
master
Author | SHA1 | Date |
---|---|---|
Stefan Dorn | f9cd0f21d9 | |
Stefan Dorn | f287876aed | |
Stefan Dorn | a7c1e67a40 | |
Stefan Dorn | 6e7dfe066d | |
Stefan Dorn | 2039dedb6a | |
Stefan Dorn | 5947829da5 | |
Stefan Dorn | f8edc016b2 | |
Stefan Dorn | b970900306 | |
Stefan Dorn | 8199d8d21d | |
Stefan Dorn | 487f81b873 | |
Stefan Dorn | a051172412 | |
Stefan Dorn | 24891b6108 | |
Stefan Dorn | 6e94b69be4 | |
Stefan Dorn | b77b3ab00d | |
Stefan Dorn | 058a7bc914 | |
Stefan Dorn | 2ed7e87cf1 | |
Stefan Dorn | 1b5090f97a | |
Stefan Dorn | 6534334973 | |
Stefan Dorn | 2f2cac7dff | |
Stefan Dorn | 0af5332a59 | |
Stefan Dorn | 17dd157c1d | |
Stefan Dorn | d722480b37 | |
Stefan Dorn | 5a33a1c21b | |
Stefan Dorn | fc3a0906f9 | |
Stefan Dorn | 3bfad0fb5c | |
Stefan Dorn | 20343f60b9 | |
Stefan Dorn | 9fc027ebbe | |
Stefan Dorn | 5e9593a4a5 | |
Stefan Dorn | 70a8382000 | |
Stefan Dorn | aff9a6b9cf | |
Stefan Dorn | 1de6d9e950 | |
Stefan Dorn | b929617dae | |
Stefan Dorn | 11b79bcc8c | |
Stefan Dorn | e20ccf838d | |
Stefan Dorn | c2b44c7222 | |
Stefan Dorn | dbbd699115 | |
Stefan Dorn | a0289831c1 | |
Stefan Dorn | 90bb49c27d | |
Stefan Dorn | e8c5f2a69d | |
Stefan Dorn | f9a4c2551d | |
Stefan Dorn | 2498833488 | |
Stefan Dorn | 270feb968a | |
Stefan Dorn | e293f31c04 | |
Stefan Dorn | 6786b70ecc | |
Stefan Dorn | f52da5065a | |
Stefan Dorn | 9c81274348 | |
Stefan Dorn | 5dc33a30d0 | |
Stefan Dorn | 118f511e61 | |
Stefan Dorn | f5c1169af3 | |
Stefan Dorn | bd74409688 | |
Stefan Dorn | b4ab1b0a7c | |
Stefan Dorn | 39d4cf708a | |
Stefan Dorn | 60e45f8444 | |
Stefan Dorn | b9678e3239 | |
Stefan Dorn | ec2820d15b | |
Stefan Dorn | 0f953d4d4a | |
Stefan Dorn | 5a651b2854 | |
Stefan Dorn | 8748e15b59 | |
Stefan Dorn | b5c9da488a | |
Stefan Dorn | 6a2057e1da | |
Stefan Dorn | 79cdf4f1f3 | |
Stefan Dorn | 01be9a4d7f | |
Stefan Dorn | fd9de01514 | |
Stefan Dorn | 415e815f75 | |
Stefan Dorn | 79b747a5fe | |
Stefan Dorn | 61a8817f2e | |
Stefan Dorn | a812590707 | |
Stefan Dorn | 789169a86f | |
Stefan Dorn | 2f2c3d6994 | |
Stefan Dorn | 445e25b01b | |
Stefan Dorn | 91e2e9f41f | |
Stefan Dorn | a57fdf7efd | |
Stefan Dorn | afc7d9f87c | |
Stefan Dorn | cf032d1395 | |
Stefan Dorn | 44d2566936 | |
Stefan Dorn | 6ec9fcbb98 | |
Stefan Dorn | 03a84a272a | |
Stefan Dorn | f5641c807e | |
Stefan Dorn | 238a98d6b6 | |
Stefan Dorn | 1b7a4b23fd | |
Stefan Dorn | 070b4b2caa | |
Stefan Dorn | 923e8da156 | |
Stefan Dorn | ba59fee6f9 | |
Stefan Dorn | 2ff9c05a48 | |
Stefan Dorn | 90bd7c9116 | |
Stefan Dorn | 2b98ca5f8d | |
Stefan Dorn | 02b931fb8d | |
Stefan Dorn | 0f1d82f1f2 | |
Stefan Dorn | a244e9d58d | |
Stefan Dorn | e25b4b3bff | |
Stefan Dorn | 14d0d1cad6 | |
Stefan Dorn | 8344f05b60 | |
Stefan Dorn | c4399c1963 | |
Stefan Dorn | b4c9342533 | |
Stefan Dorn | 0c141072da | |
Stefan Dorn | 46b1493a07 | |
Stefan Dorn | dea913d16e | |
Stefan Dorn | c1cd739af2 | |
Stefan Dorn | e7221e5eab | |
Stefan Dorn | 3dda86dd7e | |
Stefan Dorn | c8fd4b83e1 | |
Stefan Dorn | ea97f185de | |
Stefan Dorn | b5f88d06f4 | |
Stefan Dorn | 9da1313e70 | |
Stefan Dorn | 4927d4de7a | |
Stefan Dorn | 43e1cb309d | |
Stefan Dorn | cc8400f8c9 | |
Stefan Dorn | 8b78e8b3a4 | |
Stefan Dorn | c88a558e8c | |
Stefan Dorn | 5419ab9d7a | |
Stefan Dorn | 37faadc8aa | |
Stefan Dorn | c08df8dc25 | |
Stefan Dorn | 43228a265a | |
Stefan Dorn | d0f71834aa | |
Stefan Dorn | fc3259de73 | |
Stefan Dorn | fef0497fcf | |
Stefan Dorn | ac64381896 | |
Stefan Dorn | f9f5e4b5aa | |
Stefan Dorn | c695c37c40 | |
Stefan Dorn | e19ca08263 | |
Stefan Dorn | d1c105848b | |
Stefan Dorn | f0da34b909 | |
Stefan Dorn | 01c9587d31 | |
Stefan Dorn | f3654c9fe0 | |
Stefan Dorn | 447f1fb2cb | |
Stefan Dorn | ccd324d972 | |
Stefan Dorn | 5b65f3eb7c | |
Stefan Dorn | 2159af0050 | |
Stefan Dorn | e71b8fbeb0 | |
Stefan Dorn | ec5eadf8a5 | |
Stefan Dorn | 068da79193 | |
Stefan Dorn | 35bbc544bb | |
Stefan Dorn | 305ee97312 | |
Stefan Dorn | 61e002128c | |
Stefan Dorn | 834553af50 | |
Stefan Dorn | f87e9ea538 | |
Stefan Dorn | fecaf571c8 | |
Stefan Dorn | ba20aaebfd | |
Stefan Dorn | 1f653839b4 | |
Stefan Dorn | f7781d869c | |
Stefan Dorn | 133f6823cf | |
Stefan Dorn | 2d1023cf42 | |
Stefan Dorn | 4764b3d363 | |
Stefan Dorn | 8949922722 | |
Stefan Dorn | fa72af8504 | |
Stefan Dorn | 3121420267 | |
Stefan Dorn | 1cf945909d | |
Stefan Dorn | 7e97e541eb | |
Stefan Dorn | 8b392e14fb | |
Stefan Dorn | 3325dea1cf | |
Stefan Dorn | cf1b23b36d | |
Stefan Dorn | 2091d368c8 | |
Stefan Dorn | 58ae2cd244 | |
Stefan Dorn | 431f620d5b | |
Stefan Dorn | d9d7f242b2 | |
Stefan Dorn | 565ea0a478 | |
Stefan Dorn | b2c04fbbed | |
Stefan Dorn | c5b328ea67 | |
Stefan Dorn | 312b996d1b | |
Stefan Dorn | 68c4a67e65 | |
Stefan Dorn | 3aee762143 | |
Stefan Dorn | 1983339d01 | |
Stefan Dorn | 5e62e82595 | |
Stefan Dorn | 884b5ab884 | |
Stefan Dorn | b4bb0ff792 | |
Stefan Dorn | fee69ebeaf | |
Stefan Dorn | 9ce238017c | |
Stefan Dorn | c0fabeae17 | |
Stefan Dorn | fac5d540d2 | |
Ben Blazak | 8fcfe6cb7e | |
Ben Blazak | d4aa876851 | |
Ben Blazak | ed0661e3f7 | |
Ben Blazak | 1f7cbbc345 | |
Jacob McIntosh | 9fffce4cb8 | |
Jacob McIntosh | 03e1485587 | |
Jacob McIntosh | 535a67de5d | |
Jacob McIntosh | 3455d4a1d4 | |
Jacob McIntosh | 1fe98c0a74 | |
Jacob McIntosh | 6998047e2a | |
Jacob McIntosh | b1c85b73fe | |
Jacob McIntosh | 84a6d90a7b | |
Jacob McIntosh | 3c1c86f3ae | |
Jacob McIntosh | 7fe2b46280 | |
Jacob McIntosh | 971eb539aa | |
Ben Blazak | 1a38c77ee8 | |
Ben Blazak | a518081a74 | |
Ben Blazak | 9da485a171 | |
Ben Blazak | c75296f455 | |
Ben Blazak | 60c20b9cb1 | |
Ben Blazak | f99101c1a0 | |
Ben Blazak | 65ac90f730 | |
Ryan Prince | 513b82d585 | |
Ryan Prince | 45c901c308 | |
Ryan Prince | ed37259e69 | |
Ryan Prince | 16992c2ea2 | |
Ben Blazak | cbf42d9eb4 | |
Ben Blazak | 6d48149b5e | |
Ben Blazak | 1e9ebe4ece | |
Ryan Prince | 3008a6d759 | |
Ryan Prince | 22e1965902 | |
Ryan Prince | 2c39db717a | |
Ryan Prince | 26b46ac7d3 | |
Ryan Prince | 2cd405ad08 | |
Ryan Prince | ce4495372c | |
Ryan Prince | 4e56966795 | |
Ryan Prince | eb24aef2d5 | |
Ryan Prince | 208aad93d3 | |
Ryan Prince | 15a91f7b05 | |
Ryan Prince | 2d5c6084c0 | |
Ryan Prince | d88b55a6d9 | |
Ryan Prince | f2d650b996 | |
Ben Blazak | 43ee200b2b | |
Ben Blazak | a03263d83b | |
Ben Blazak | 6c3a7951b1 | |
Ben Blazak | 721f56588b | |
Ben Blazak | 08101371e7 | |
Ben Blazak | d120a0744f | |
Ben Blazak | 89d8df652e | |
Ben Blazak | 4810bac2a0 | |
Ben Blazak | 2aab399a6f | |
Ben Blazak | 37b425a738 |
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -1,423 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
# Released under The MIT License (MIT) (see "license.md")
|
||||
# Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
Generate a depiction of the layout (in html + svg)
|
||||
|
||||
Depends on:
|
||||
- the UI info file (in JSON)
|
||||
"""
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
class Namespace():
|
||||
pass
|
||||
|
||||
template = Namespace()
|
||||
doc = Namespace()
|
||||
info = Namespace()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
description = "Generate a picture of the firmware's "
|
||||
+ "keyboard layout" )
|
||||
|
||||
arg_parser.add_argument(
|
||||
'--ui-info-file',
|
||||
required = True )
|
||||
|
||||
args = arg_parser.parse_args(sys.argv[1:])
|
||||
|
||||
# constant file paths
|
||||
args.template_svg_file = './build-scripts/gen_layout/template.svg'
|
||||
args.template_js_file = './build-scripts/gen_layout/template.js'
|
||||
|
||||
# normalize paths
|
||||
args.ui_info_file = os.path.abspath(args.ui_info_file)
|
||||
args.template_svg_file = os.path.abspath(args.template_svg_file)
|
||||
args.template_js_file = os.path.abspath(args.template_js_file)
|
||||
|
||||
# set vars
|
||||
doc.main = '' # to store the html document we're generating
|
||||
template.svg = open(args.template_svg_file).read()
|
||||
template.js = open(args.template_js_file).read()
|
||||
info.all = json.loads(open(args.ui_info_file).read())
|
||||
|
||||
info.matrix_positions = info.all['mappings']['matrix-positions']
|
||||
info.matrix_layout = info.all['mappings']['matrix-layout']
|
||||
|
||||
# prefix
|
||||
doc.prefix = ("""
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<script>
|
||||
"""
|
||||
+ template.js +
|
||||
""" </script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h1>Firmware Layout</h1>
|
||||
|
||||
<ul>
|
||||
<li>git commit date:
|
||||
<code>""" + info.all['miscellaneous']['git-commit-date'] + """</code></li>
|
||||
<li>git commit id:
|
||||
<code>""" + info.all['miscellaneous']['git-commit-id'] + """</code></li>
|
||||
</ul>
|
||||
|
||||
<h2>Notes</h2>
|
||||
|
||||
<ul>
|
||||
<li>Layer keys are labeled e.g. <code>la 2 +- 2</code>
|
||||
<ul>
|
||||
<li><code>la</code> is for "layer"</li>
|
||||
<li><code>2</code> indicates that the second pair of push|pop functions is
|
||||
being used (differently numbered pairs won't interfere with each
|
||||
other)</li>
|
||||
<li><code>+</code> indicates that the layer is being "pushed" onto the
|
||||
stack at some point, either when the key is pressed or when it is
|
||||
released</li>
|
||||
<li><code>-</code> indicates that the layer is being "popped" off of the
|
||||
stack at some point</li>
|
||||
<li>the last <code>2</code> indicates the layer-number that will be
|
||||
activated on "push".</li>
|
||||
</ul>
|
||||
See the project 'readme.md' file on <a
|
||||
href='https://github.com/benblazak/ergodox-firmware'>the github page</a> as a
|
||||
starting point for learning more about how this firmware implements
|
||||
layers.</li>
|
||||
<br>
|
||||
<li>Shifted keys are labeled with an <code>sh</code> at the beginning. This
|
||||
indicates that a 'Shift' is generated with that keypress, the same as if you
|
||||
had held down 'Shift', and pressed that key.</li>
|
||||
<br>
|
||||
<li><code>(null)</code> indicates that no keypress or keyrelease will be
|
||||
generated for that key, on that layer.</li>
|
||||
<br>
|
||||
<li>Blank keys indicate "transparency": if you press that key on that layer,
|
||||
the key will act as if it was on whatever layer is active below the current
|
||||
one.</li>
|
||||
<br>
|
||||
<li>Some keys may be labled with special functions (like
|
||||
<code>[btldr]</code>, which tells the Teensy to wait for the host to send it
|
||||
a new firmware).</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
|
||||
""")[1:-1]
|
||||
|
||||
# suffix
|
||||
doc.suffix = ("""
|
||||
</body>
|
||||
</html>
|
||||
|
||||
""")[1:-1]
|
||||
|
||||
# substitute into template
|
||||
# -------
|
||||
# note: this is not general enough to handle any possible layout well, at
|
||||
# the moment. but it should handle more standard ones well. (hopefully
|
||||
# minor) modifications may be necessary on a case by case basis
|
||||
# -------
|
||||
layer_number = -1
|
||||
for (layout, layer) in zip( info.matrix_layout,
|
||||
range(len(info.matrix_layout))):
|
||||
layer_number += 1
|
||||
svg = template.svg
|
||||
for (name, (code, press, release)) \
|
||||
in zip(info.matrix_positions, layout):
|
||||
replace = ''
|
||||
if press == 'kbfun_transparent':
|
||||
replace = ''
|
||||
elif press == 'kbfun_shift_press_release':
|
||||
replace = 'sh ' + keycode_to_string.get(code, '[n/a]')
|
||||
elif press == 'kbfun_jump_to_bootloader':
|
||||
replace = '[btldr]'
|
||||
elif press == 'NULL' and release == 'NULL':
|
||||
replace = '(null)'
|
||||
elif re.search(r'numpad', press+release):
|
||||
replace = '[num]'
|
||||
elif re.search(r'layer', press+release):
|
||||
replace = 'la ' + re.findall(r'\d+', press+release)[0] + ' '
|
||||
if re.search(r'push', press+release):
|
||||
replace += '+'
|
||||
if re.search(r'pop', press+release):
|
||||
replace += '-'
|
||||
replace += ' ' + str(code)
|
||||
else:
|
||||
replace = keycode_to_string.get(code, '[n/a]')
|
||||
|
||||
svg = re.sub(
|
||||
'>'+name+'<', '>'+replace+'<', svg )
|
||||
svg = re.sub(
|
||||
r"\('(" + name + r".*)'\)",
|
||||
r"('\1', " + str(layer) + r")",
|
||||
svg )
|
||||
|
||||
doc.main += '<h2>Layer ' + str(layer_number) + '</h2>\n' + svg
|
||||
|
||||
# change the font size
|
||||
doc.main = re.sub(r'22.5px', '15px', doc.main)
|
||||
|
||||
print(doc.prefix + doc.main + doc.suffix)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
keycode_to_string = {
|
||||
0x01: "Error", # ErrorRollOver
|
||||
0x02: "POSTFail",
|
||||
0x03: "Error", # ErrorUndefined
|
||||
0x04: "a A",
|
||||
0x05: "b B",
|
||||
0x06: "c C",
|
||||
0x07: "d D",
|
||||
0x08: "e E",
|
||||
0x09: "f F",
|
||||
0x0A: "g G",
|
||||
0x0B: "h H",
|
||||
0x0C: "i I",
|
||||
0x0D: "j J",
|
||||
0x0E: "k K",
|
||||
0x0F: "l L",
|
||||
0x10: "m M",
|
||||
0x11: "n N",
|
||||
0x12: "o O",
|
||||
0x13: "p P",
|
||||
0x14: "q Q",
|
||||
0x15: "r R",
|
||||
0x16: "s S",
|
||||
0x17: "t T",
|
||||
0x18: "u U",
|
||||
0x19: "v V",
|
||||
0x1A: "w W",
|
||||
0x1B: "x X",
|
||||
0x1C: "y Y",
|
||||
0x1D: "z Z",
|
||||
0x1E: "1 !",
|
||||
0x1F: "2 @",
|
||||
0x20: "3 #",
|
||||
0x21: "4 $",
|
||||
0x22: "5 %",
|
||||
0x23: "6 ^",
|
||||
0x24: "7 &",
|
||||
0x25: "8 *",
|
||||
0x26: "9 (",
|
||||
0x27: "0 )",
|
||||
0x28: "Return",
|
||||
0x29: "Esc",
|
||||
0x2A: "Backspace",
|
||||
0x2B: "Tab",
|
||||
0x2C: "Space",
|
||||
0x2D: "- _",
|
||||
0x2E: "= +",
|
||||
0x2F: "[ {",
|
||||
0x30: "] }",
|
||||
0x31: "\ |",
|
||||
0x32: "# ~",
|
||||
0x33: "; :",
|
||||
0x34: "\' \"",
|
||||
0x35: "` ~",
|
||||
0x36: ", <",
|
||||
0x37: ". >",
|
||||
0x38: "/ ?",
|
||||
0x39: "Caps",
|
||||
0x3A: "F1",
|
||||
0x3B: "F2",
|
||||
0x3C: "F3",
|
||||
0x3D: "F4",
|
||||
0x3E: "F5",
|
||||
0x3F: "F6",
|
||||
0x40: "F7",
|
||||
0x41: "F8",
|
||||
0x42: "F9",
|
||||
0x43: "F10",
|
||||
0x44: "F11",
|
||||
0x45: "F12",
|
||||
0x46: "PrintScreen",
|
||||
0x47: "ScrollLock",
|
||||
0x48: "Pause",
|
||||
0x49: "Ins", # Insert
|
||||
0x4A: "Hm", # Home
|
||||
0x4B: "Pg\u2191", # up arrow
|
||||
0x4C: "Delete",
|
||||
0x4D: "End",
|
||||
0x4E: "Pg\u2193", # down arrow
|
||||
0x4F: "\u2192", # right arrow
|
||||
0x50: "\u2190", # left arrow
|
||||
0x51: "\u2193", # down arrow
|
||||
0x52: "\u2191", # up arrow
|
||||
|
||||
0x53: "Num",
|
||||
0x54: "/",
|
||||
0x55: "*",
|
||||
0x56: "-",
|
||||
0x57: "+",
|
||||
0x58: "Enter",
|
||||
0x59: "1 End",
|
||||
0x5A: "2 \u2193", # down arrow
|
||||
0x5B: "3 Pg\u2193", # down arrow
|
||||
0x5C: "4 \u2190", # left arrow
|
||||
0x5D: "5",
|
||||
0x5E: "6 \u2192", # right arrow
|
||||
0x5F: "7 Hm", # Home
|
||||
0x60: "8 \u2191", # up arrow
|
||||
0x61: "9 Pg\u2191", # up arrow
|
||||
0x62: "0 Ins", # Insert
|
||||
0x63: ". Del",
|
||||
|
||||
0x64: "\ |",
|
||||
0x65: "App",
|
||||
0x66: "Power",
|
||||
|
||||
0x67: "=",
|
||||
|
||||
0x68: "F13",
|
||||
0x69: "F14",
|
||||
0x6A: "F15",
|
||||
0x6B: "F16",
|
||||
0x6C: "F17",
|
||||
0x6D: "F18",
|
||||
0x6E: "F19",
|
||||
0x6F: "F20",
|
||||
0x70: "F21",
|
||||
0x71: "F22",
|
||||
0x72: "F23",
|
||||
0x73: "F24",
|
||||
0x74: "Exec",
|
||||
0x75: "Help",
|
||||
0x76: "Menu",
|
||||
0x77: "Select",
|
||||
0x78: "Stop",
|
||||
0x79: "Again",
|
||||
0x7A: "Undo",
|
||||
0x7B: "Cut",
|
||||
0x7C: "Copy",
|
||||
0x7D: "Paste",
|
||||
0x7E: "Find",
|
||||
0x7F: "Mute",
|
||||
0x80: "VolUp",
|
||||
0x81: "VolDown",
|
||||
0x82: "LockingCapsLock",
|
||||
0x83: "LockingNumLock",
|
||||
0x84: "LockingScrollLock",
|
||||
|
||||
0x85: ",",
|
||||
0x86: "=",
|
||||
|
||||
0x87: "Int1",
|
||||
0x88: "Int2",
|
||||
0x89: "Int3",
|
||||
0x8A: "Int4",
|
||||
0x8B: "Int5",
|
||||
0x8C: "Int6",
|
||||
0x8D: "Int7",
|
||||
0x8E: "Int8",
|
||||
0x8F: "Int9",
|
||||
0x90: "LANG1",
|
||||
0x91: "LANG2",
|
||||
0x92: "LANG3",
|
||||
0x93: "LANG4",
|
||||
0x94: "LANG5",
|
||||
0x95: "LANG6",
|
||||
0x96: "LANG7",
|
||||
0x97: "LANG8",
|
||||
0x98: "LANG9",
|
||||
0x99: "AlternateErase",
|
||||
0x9A: "SysReq_Attention",
|
||||
0x9B: "Cancel",
|
||||
0x9C: "Clear",
|
||||
0x9D: "Prior",
|
||||
0x9E: "Return",
|
||||
0x9F: "Separator",
|
||||
0xA0: "Out",
|
||||
0xA1: "Oper",
|
||||
0xA2: "Clear_Again",
|
||||
0xA3: "CrSel_Props",
|
||||
0xA4: "ExSel",
|
||||
|
||||
0xB0: "00",
|
||||
0xB1: "000",
|
||||
|
||||
0xB2: "Thousands_Sep",
|
||||
0xB3: "Decimal_Sep",
|
||||
0xB4: "$",
|
||||
0xB5: "Currency_Subunit",
|
||||
|
||||
0xB6: "(",
|
||||
0xB7: ")",
|
||||
0xB8: "{",
|
||||
0xB9: "}",
|
||||
|
||||
0xBA: "Tab",
|
||||
0xBB: "Backspace",
|
||||
0xBC: "A",
|
||||
0xBD: "B",
|
||||
0xBE: "C",
|
||||
0xBF: "D",
|
||||
0xC0: "E",
|
||||
0xC1: "F",
|
||||
0xC2: "XOR",
|
||||
0xC3: "^",
|
||||
0xC4: "%",
|
||||
0xC5: "<",
|
||||
0xC6: ">",
|
||||
0xC7: "&",
|
||||
0xC8: "&&",
|
||||
0xC9: "|",
|
||||
0xCA: "||",
|
||||
0xCB: ":",
|
||||
0xCC: "#",
|
||||
0xCD: "Space",
|
||||
0xCE: "@",
|
||||
0xCF: "!",
|
||||
0xD0: "Mem_Store",
|
||||
0xD1: "Mem_Recall",
|
||||
0xD2: "Mem_Clear",
|
||||
0xD3: "Mem_+",
|
||||
0xD4: "Mem_-",
|
||||
0xD5: "Mem_*",
|
||||
0xD6: "Mem_/",
|
||||
0xD7: "+-",
|
||||
0xD8: "Clear",
|
||||
0xD9: "ClearEntry",
|
||||
0xDA: "Binary",
|
||||
0xDB: "Octal",
|
||||
0xDC: ".",
|
||||
0xDD: "Hexadecimal",
|
||||
|
||||
0xE0: "L-Ctrl",
|
||||
0xE1: "L-Shift",
|
||||
0xE2: "L-Alt",
|
||||
0xE3: "L-GUI",
|
||||
0xE4: "R-Ctrl",
|
||||
0xE5: "R-Shift",
|
||||
0xE6: "R-Alt",
|
||||
0xE7: "R-GUI",
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,475 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
# -----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
# Released under The MIT License (MIT) (see "license.md")
|
||||
# Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
Generate UI info file (in JSON)
|
||||
|
||||
Depends on:
|
||||
- the project source code
|
||||
- the project '.map' file (generated by the compiler)
|
||||
"""
|
||||
|
||||
_FORMAT_DESCRIPTION = ("""
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Version 0
|
||||
* ----------------------------------------------------------------------------
|
||||
* Hopefully the add-hoc conventions are clear enough... I didn't feel like
|
||||
* investing the time in making it a real JSON Schema when there aren't many
|
||||
* validators, and the most current completed draft at the moment (draft 3) is
|
||||
* expired...
|
||||
* ----------------------------------------------------------------------------
|
||||
* Please note that in general, fields may be added without changing the
|
||||
* version number, and that programs using this format are not required to fill
|
||||
* (or read) any of the given fields.
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
var ui_info = {
|
||||
".meta-data": { // for the JSON file
|
||||
"version": "<number>",
|
||||
"date-generated": "<string>", // format: RFC 3339
|
||||
"description": "<string>",
|
||||
},
|
||||
"keyboard-functions": {
|
||||
"<(function name)>": {
|
||||
"position": "<number>", // as given by the .map file
|
||||
"length": "<number>", // as given by the .map file
|
||||
"comments": {
|
||||
"name": "<string>", // more user friendly name
|
||||
"description": "<string>",
|
||||
"notes": [
|
||||
"<string>",
|
||||
"..."
|
||||
],
|
||||
"..."
|
||||
}
|
||||
},
|
||||
"..."
|
||||
},
|
||||
"layout-matrices": {
|
||||
"<(matrix name)>": {
|
||||
"position": "<number>", // as given by the .map file
|
||||
"length": "<number>" // as given by the .map file
|
||||
},
|
||||
"..."
|
||||
},
|
||||
"mappings": {
|
||||
/*
|
||||
* The mappings prefixed with 'matrix' have their elements in the same
|
||||
* order as the .hex file (whatever order that is). The mappings
|
||||
* prefixed with 'physical' will have their elements in an order
|
||||
* corresponding to thier physical position on the keyboard. You can
|
||||
* convert between the two using the relative positions of the key-ids
|
||||
* in 'physical-positions' and 'matrix-positions'.
|
||||
*
|
||||
* The current order of 'physical' mappings is:
|
||||
* --------------------------------------------
|
||||
* // left hand, spatial positions
|
||||
* 00, 01, 02, 03, 04, 05, 06,
|
||||
* 07, 08, 09, 10, 11, 12, 13,
|
||||
* 14, 15, 16, 17, 18, 19,
|
||||
* 20, 21, 22, 23, 24, 25, 26,
|
||||
* 27, 28, 29, 30, 31,
|
||||
* 32, 33,
|
||||
* 34, 35, 36,
|
||||
* 37, 38, 39,
|
||||
|
||||
* // right hand, spatial positions
|
||||
* 40, 41, 42, 43, 44, 45, 46,
|
||||
* 47, 48, 49, 50, 51, 52, 53,
|
||||
* 54, 55, 56, 57, 58, 59,
|
||||
* 60, 61, 62, 63, 64, 65, 66,
|
||||
* 67, 68, 69, 70, 71,
|
||||
* 72, 73,
|
||||
* 74, 75, 76,
|
||||
* 77, 78, 79,
|
||||
* --------------------------------------------
|
||||
*/
|
||||
|
||||
"physical-positions": [ // list of key-ids
|
||||
"<string>", "..."
|
||||
],
|
||||
"matrix-positions": [ // list of key-ids
|
||||
"<string>", "..."
|
||||
],
|
||||
"matrix-layout": [
|
||||
[ // begin layer
|
||||
[ // begin key
|
||||
"<number>", // keycode
|
||||
"<string>", // press function name (ex: 'kbfun_...')
|
||||
"<string>" // release function name (ex: 'NULL')
|
||||
],
|
||||
"..." // more keys
|
||||
],
|
||||
"..." // more layers
|
||||
]
|
||||
},
|
||||
"miscellaneous": {
|
||||
"git-commit-date": "<string>", // format: RFC 3339
|
||||
"git-commit-id": "<string>",
|
||||
"number-of-layers": "<number>"
|
||||
}
|
||||
}
|
||||
""")[1:-1]
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def gen_static(current_date=None, git_commit_date=None, git_commit_id=None):
|
||||
"""Generate static information"""
|
||||
|
||||
return {
|
||||
'.meta-data': {
|
||||
'version': 0, # the format version number
|
||||
'date-generated': current_date,
|
||||
'description': _FORMAT_DESCRIPTION,
|
||||
},
|
||||
'miscellaneous': {
|
||||
'git-commit-date': git_commit_date, # should be passed by makefile
|
||||
'git-commit-id': git_commit_id, # should be passed by makefile
|
||||
},
|
||||
}
|
||||
|
||||
def gen_derived(data):
|
||||
"""
|
||||
Generate derived information
|
||||
Should be called last
|
||||
"""
|
||||
return {
|
||||
'miscellaneous': {
|
||||
'number-of-layers':
|
||||
int( data['layout-matrices']['_kb_layout']['length']/(6*14) ),
|
||||
# because 6*14 is the number of bytes/layer for '_kb_layout'
|
||||
# (which is a uint8_t matrix)
|
||||
},
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def parse_mapfile(map_file_path):
|
||||
"""Parse the '.map' file"""
|
||||
|
||||
def parse_keyboard_function(f, line):
|
||||
"""Parse keyboard-functions in the '.map' file"""
|
||||
|
||||
search = re.search(r'(0x\S+)\s+(0x\S+)', next(f))
|
||||
position = int( search.group(1), 16 )
|
||||
length = int( search.group(2), 16 )
|
||||
|
||||
search = re.search(r'0x\S+\s+(\S+)', next(f))
|
||||
name = search.group(1)
|
||||
|
||||
return {
|
||||
'keyboard-functions': {
|
||||
name: {
|
||||
'position': position,
|
||||
'length': length,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
def parse_layout_matrices(f, line):
|
||||
"""Parse layout matrix information in the '.map' file"""
|
||||
|
||||
name = re.search(r'.progmem.data.(_kb_layout\S*)', line).group(1)
|
||||
|
||||
search = re.search(r'(0x\S+)\s+(0x\S+)', next(f))
|
||||
position = int( search.group(1), 16 )
|
||||
length = int( search.group(2), 16 )
|
||||
|
||||
return {
|
||||
'layout-matrices': {
|
||||
name: {
|
||||
'position': position,
|
||||
'length': length,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# --- parse_mapfile() ---
|
||||
|
||||
# normalize paths
|
||||
map_file_path = os.path.abspath(map_file_path)
|
||||
# check paths
|
||||
if not os.path.exists(map_file_path):
|
||||
raise ValueError("invalid 'map_file_path' given")
|
||||
|
||||
output = {}
|
||||
|
||||
f = open(map_file_path)
|
||||
|
||||
for line in f:
|
||||
if re.search(r'^\s*\.text\.kbfun_', line):
|
||||
dict_merge(output, parse_keyboard_function(f, line))
|
||||
elif re.search(r'^\s*\.progmem\.data.*layout', line):
|
||||
dict_merge(output, parse_layout_matrices(f, line))
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def find_keyboard_functions(source_code_path):
|
||||
"""Parse all files in the source directory"""
|
||||
|
||||
def read_comments(f, line):
|
||||
"""
|
||||
Read in properly formatted multi-line comments
|
||||
- Comments must start with '/*' and end with '*/', each on their own
|
||||
line
|
||||
"""
|
||||
comments = ''
|
||||
while(line.strip() != r'*/'):
|
||||
comments += line[2:].strip()+'\n'
|
||||
line = next(f)
|
||||
return comments
|
||||
|
||||
def parse_comments(comments):
|
||||
"""
|
||||
Parse an INI style comment string
|
||||
- Fields begin with '[field-name]', and continue until the next field,
|
||||
or the end of the comment
|
||||
- Fields '[name]', '[description]', and '[note]' are treated specially
|
||||
"""
|
||||
|
||||
def add_field(output, field, value):
|
||||
"""Put a field+value pair in 'output', the way we want it, if the
|
||||
pair is valid"""
|
||||
|
||||
value = value.strip()
|
||||
|
||||
if field is not None:
|
||||
if field in ('name', 'description'):
|
||||
if field not in output:
|
||||
output[field] = value
|
||||
else:
|
||||
if field == 'note':
|
||||
field = 'notes'
|
||||
|
||||
if field not in output:
|
||||
output[field] = []
|
||||
|
||||
output[field] += [value]
|
||||
|
||||
# --- parse_comments() ---
|
||||
|
||||
output = {}
|
||||
|
||||
field = None
|
||||
value = None
|
||||
for line in comments.split('\n'):
|
||||
line = line.strip()
|
||||
|
||||
if re.search(r'^\[.*\]$', line):
|
||||
add_field(output, field, value)
|
||||
field = line[1:-1]
|
||||
value = None
|
||||
|
||||
else:
|
||||
if value is None:
|
||||
value = ''
|
||||
if len(value) > 0 and value[-1] == '.':
|
||||
line = ' '+line
|
||||
value += ' '+line
|
||||
|
||||
add_field(output, field, value)
|
||||
|
||||
return output
|
||||
|
||||
def parse_keyboard_function(f, line, comments):
|
||||
"""Parse keyboard-functions in the source code"""
|
||||
|
||||
search = re.search(r'void\s+(kbfun_\S+)\s*\(void\)', line)
|
||||
name = search.group(1)
|
||||
|
||||
return {
|
||||
'keyboard-functions': {
|
||||
name: {
|
||||
'comments': parse_comments(comments),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# --- find_keyboard_functions() ---
|
||||
|
||||
# normalize paths
|
||||
source_code_path = os.path.abspath(source_code_path)
|
||||
# check paths
|
||||
if not os.path.exists(source_code_path):
|
||||
raise ValueError("invalid 'source_code_path' given")
|
||||
|
||||
output = {}
|
||||
|
||||
for tup in os.walk(source_code_path):
|
||||
for file_name in tup[2]:
|
||||
# normalize paths
|
||||
file_name = os.path.abspath( os.path.join( tup[0], file_name ) )
|
||||
|
||||
# ignore non '.c' files
|
||||
if file_name[-2:] != '.c':
|
||||
continue
|
||||
|
||||
f = open(file_name)
|
||||
|
||||
comments = ''
|
||||
for line in f:
|
||||
if line.strip() == r'/*':
|
||||
comments = read_comments(f, line)
|
||||
elif re.search(r'void\s+kbfun_\S+\s*\(void\)', line):
|
||||
dict_merge(
|
||||
output,
|
||||
parse_keyboard_function(f, line, comments) )
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def gen_mappings(matrix_file_path, layout_file_path):
|
||||
# normalize paths
|
||||
matrix_file_path = os.path.abspath(matrix_file_path)
|
||||
layout_file_path = os.path.abspath(layout_file_path)
|
||||
|
||||
def parse_matrix_file(matrix_file_path):
|
||||
match = re.search( # find the whole 'KB_MATRIX_LAYER' macro
|
||||
r'#define\s+KB_MATRIX_LAYER\s*\(([^)]+)\)[^{]*\{\{([^#]+)\}\}',
|
||||
open(matrix_file_path).read() )
|
||||
|
||||
return {
|
||||
"mappings": {
|
||||
"physical-positions": re.findall(r'k..', match.group(1)),
|
||||
"matrix-positions": re.findall(r'k..|na', match.group(2)),
|
||||
},
|
||||
}
|
||||
|
||||
def parse_layout_file(layout_file_path):
|
||||
match = re.findall( # find each whole '_kb_layout*' matrix definition
|
||||
r'(_kb_layout\w*)[^=]*=((?:[^{}]*\{){3}[^=]*(?:[^{}]*\}){3})',
|
||||
subprocess.getoutput("gcc -E '"+layout_file_path+"'") )
|
||||
|
||||
layout = {}
|
||||
# collect all the values
|
||||
for (name, matrix) in match:
|
||||
layout[name] = [
|
||||
re.findall( # find all numbers and function pointers
|
||||
r'[x0-9A-F]+|&\w+|NULL',
|
||||
re.sub( # replace '((void *) 0)' with 'NULL'
|
||||
r'\(\s*\(\s*void\s*\*\s*\)\s*0\s*\)',
|
||||
'NULL',
|
||||
el ) )
|
||||
for el in
|
||||
re.findall( # find each whole layer
|
||||
r'(?:[^{}]*\{){2}((?:[^}]|\}\s*,)+)(?:[^{}]*\}){2}',
|
||||
matrix ) ]
|
||||
|
||||
# make the numbers into actual numbers
|
||||
layout['_kb_layout'] = \
|
||||
[[eval(el) for el in layer] for layer in layout['_kb_layout']]
|
||||
# remove the preceeding '&' from function pointers
|
||||
for matrix in ('_kb_layout_press', '_kb_layout_release'):
|
||||
layout[matrix] = \
|
||||
[ [re.sub(r'&', '', el) for el in layer]
|
||||
for layer in layout[matrix] ]
|
||||
|
||||
return {
|
||||
"mappings": {
|
||||
"matrix-layout":
|
||||
# group them all properly
|
||||
[ [[c, p, r] for (c, p, r) in zip(code, press, release)]
|
||||
for (code, press, release) in
|
||||
zip( layout['_kb_layout'],
|
||||
layout['_kb_layout_press'],
|
||||
layout['_kb_layout_release'] ) ]
|
||||
},
|
||||
}
|
||||
|
||||
return dict_merge(
|
||||
parse_matrix_file(matrix_file_path),
|
||||
parse_layout_file(layout_file_path) )
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def dict_merge(a, b):
|
||||
"""
|
||||
Recursively merge two dictionaries
|
||||
- I was looking around for an easy way to do this, and found something
|
||||
[here]
|
||||
(http://www.xormedia.com/recursively-merge-dictionaries-in-python.html).
|
||||
This is pretty close, but i didn't copy it exactly.
|
||||
"""
|
||||
|
||||
if not isinstance(a, dict) or not isinstance(b, dict):
|
||||
return b
|
||||
|
||||
for (key, value) in b.items():
|
||||
if key in a:
|
||||
a[key] = dict_merge(a[key], value)
|
||||
else:
|
||||
a[key] = value
|
||||
|
||||
return a
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def main():
|
||||
arg_parser = argparse.ArgumentParser(
|
||||
description = 'Generate project data for use with the UI' )
|
||||
|
||||
arg_parser.add_argument(
|
||||
'--current-date',
|
||||
help = ( "should be in the format rfc-3339 "
|
||||
+ "(e.g. 2006-08-07 12:34:56-06:00)" ),
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--git-commit-date',
|
||||
help = ( "should be in the format rfc-3339 "
|
||||
+ "(e.g. 2006-08-07 12:34:56-06:00)" ),
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--git-commit-id',
|
||||
help = "the git commit ID",
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--map-file-path',
|
||||
help = "the path to the '.map' file",
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--source-code-path',
|
||||
help = "the path to the source code directory",
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--matrix-file-path',
|
||||
help = "the path to the matrix file we're using",
|
||||
required = True )
|
||||
arg_parser.add_argument(
|
||||
'--layout-file-path',
|
||||
help = "the path to the layout file we're using",
|
||||
required = True )
|
||||
|
||||
args = arg_parser.parse_args(sys.argv[1:])
|
||||
|
||||
output = {}
|
||||
dict_merge( output, gen_static( args.current_date,
|
||||
args.git_commit_date,
|
||||
args.git_commit_id ) )
|
||||
dict_merge(output, parse_mapfile(args.map_file_path))
|
||||
dict_merge(output, find_keyboard_functions(args.source_code_path))
|
||||
dict_merge(output, gen_mappings( args.matrix_file_path,
|
||||
args.layout_file_path ))
|
||||
dict_merge(output, gen_derived(output))
|
||||
|
||||
print(json.dumps(output, sort_keys=True, indent=4))
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
function keyclick(position, layer) {
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 94 KiB |
|
@ -1,2 +0,0 @@
|
|||
This directory is for projects closely related to the firmware.
|
||||
|
|
@ -0,0 +1,700 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright muflax <mail@muflax.com>, 2015
|
||||
# License: GNU GPLv3 (or later) <http://www.gnu.org/copyleft/gpl.html>
|
||||
|
||||
GC.disable
|
||||
|
||||
# avoid having to require muflax
|
||||
class Object
|
||||
def blank?
|
||||
respond_to?(:empty?) ? !!empty? : !self
|
||||
end
|
||||
end
|
||||
|
||||
class String
|
||||
BLANK_RE = /\A[[:space:]]*\z/
|
||||
def blank?
|
||||
BLANK_RE === self
|
||||
end
|
||||
end
|
||||
|
||||
LayoutDir = "src/keyboard"
|
||||
LayoutFile = "#{LayoutDir}/layout.c"
|
||||
|
||||
puts "generating #{LayoutFile}..."
|
||||
|
||||
class Layer
|
||||
@@layers = {}
|
||||
@@primitives = 0
|
||||
|
||||
def initialize name
|
||||
case name
|
||||
when Symbol
|
||||
raise "layer already defined: #{name}" if @@layers.include? name
|
||||
|
||||
@@primitives += 1
|
||||
@@layers[name] = @@primitives
|
||||
|
||||
when Array
|
||||
name.each do |prim|
|
||||
raise "unknown layers: #{prim}" if not @@layers.include? prim
|
||||
raise "can only combo primitive layers: #{prim}" if not prim.is_a? Symbol
|
||||
end
|
||||
|
||||
combo = name.reduce(0) do |code, prim|
|
||||
code | (@@layers[prim])
|
||||
end
|
||||
|
||||
combo_name = name.sort_by{|p| @@layers[p]}.join("_").to_sym
|
||||
|
||||
@@layers[combo_name] = combo
|
||||
|
||||
else
|
||||
raise "invalid layer definition: #{name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Keydef = Struct.new :code, :func
|
||||
|
||||
class Key
|
||||
attr_reader :keydefs, :name, :row, :col
|
||||
|
||||
Layers = [ :LB, :LP, :LN, :LF, :LD ]
|
||||
|
||||
Functions = {
|
||||
#
|
||||
"basic" => "&kbfun_normal_press_release",
|
||||
"media" => "&kbfun_mediakey_press_release",
|
||||
#
|
||||
"mod" => "&kbfun_modifier_press_release",
|
||||
"sticky_mod" => "&kbfun_modifier_sticky",
|
||||
#
|
||||
"layer" => "&kbfun_layer_press_release",
|
||||
"sticky" => "&kbfun_layer_sticky",
|
||||
#
|
||||
"shift" => "&kbfun_shift_press_release",
|
||||
"ctrl" => "&kbfun_control_press_release",
|
||||
"alt" => "&kbfun_alt_press_release",
|
||||
"win" => "&kbfun_win_press_release",
|
||||
#
|
||||
"shift_once" => "&kbfun_shift_press_release_once",
|
||||
"ctrl_once" => "&kbfun_control_press_release_once",
|
||||
"alt_once" => "&kbfun_alt_press_release_once",
|
||||
"win_once" => "&kbfun_win_press_release_once",
|
||||
#
|
||||
"shift_layer" => "&kbfun_shift_layer_press_release",
|
||||
"ctrl_layer" => "&kbfun_control_layer_press_release",
|
||||
"alt_layer" => "&kbfun_alt_layer_press_release",
|
||||
"win_layer" => "&kbfun_win_layer_press_release",
|
||||
#
|
||||
"capslock" => "&kbfun_capslock_press_release",
|
||||
#
|
||||
"S" => "&kbfun_shift_press_release",
|
||||
"C" => "&kbfun_control_press_release",
|
||||
"A" => "&kbfun_alt_press_release",
|
||||
"M" => "&kbfun_alt_press_release",
|
||||
"W" => "&kbfun_win_press_release",
|
||||
"CL" => "&kbfun_capslock_press_release",
|
||||
"_L" => "&kbfun_layer_sticky",
|
||||
"_M" => "&kbfun_modifier_sticky",
|
||||
"_C" => "&kbfun_control_layer_press_release",
|
||||
"_A" => "&kbfun_alt_layer_press_release",
|
||||
"_W" => "&kbfun_win_layer_press_release",
|
||||
}
|
||||
|
||||
Keys = {
|
||||
# letters
|
||||
"a" => "KEY_a_A",
|
||||
"b" => "KEY_b_B",
|
||||
"c" => "KEY_c_C",
|
||||
"d" => "KEY_d_D",
|
||||
"e" => "KEY_e_E",
|
||||
"f" => "KEY_f_F",
|
||||
"g" => "KEY_g_G",
|
||||
"h" => "KEY_h_H",
|
||||
"i" => "KEY_i_I",
|
||||
"j" => "KEY_j_J",
|
||||
"k" => "KEY_k_K",
|
||||
"l" => "KEY_l_L",
|
||||
"m" => "KEY_m_M",
|
||||
"n" => "KEY_n_N",
|
||||
"o" => "KEY_o_O",
|
||||
"p" => "KEY_p_P",
|
||||
"q" => "KEY_q_Q",
|
||||
"r" => "KEY_r_R",
|
||||
"s" => "KEY_s_S",
|
||||
"t" => "KEY_t_T",
|
||||
"u" => "KEY_u_U",
|
||||
"v" => "KEY_v_V",
|
||||
"w" => "KEY_w_W",
|
||||
"x" => "KEY_x_X",
|
||||
"y" => "KEY_y_Y",
|
||||
"z" => "KEY_z_Z",
|
||||
# numbers
|
||||
"0" => "KEY_0_RightParenthesis",
|
||||
"1" => "KEY_1_Exclamation",
|
||||
"2" => "KEY_2_At",
|
||||
"3" => "KEY_3_Pound",
|
||||
"4" => "KEY_4_Dollar",
|
||||
"5" => "KEY_5_Percent",
|
||||
"6" => "KEY_6_Caret",
|
||||
"7" => "KEY_7_Ampersand",
|
||||
"8" => "KEY_8_Asterisk",
|
||||
"9" => "KEY_9_LeftParenthesis",
|
||||
# punctuation
|
||||
"\\" => "KEY_Backslash_Pipe",
|
||||
"{" => ["KEY_LeftBracket_LeftBrace", "shift_once"],
|
||||
"}" => ["KEY_RightBracket_RightBrace", "shift_once"],
|
||||
"[" => "KEY_LeftBracket_LeftBrace",
|
||||
"]" => "KEY_RightBracket_RightBrace",
|
||||
"," => "KEY_Comma_LessThan",
|
||||
"-" => "KEY_Dash_Underscore",
|
||||
"=" => "KEY_Equal_Plus",
|
||||
"`" => "KEY_GraveAccent_Tilde",
|
||||
"." => "KEY_Period_GreaterThan",
|
||||
"\'" => "KEY_SingleQuote_DoubleQuote",
|
||||
";" => "KEY_Semicolon_Colon",
|
||||
"/" => "KEY_Slash_Question",
|
||||
"~" => ["KEY_GraveAccent_Tilde", "shift_once"],
|
||||
"%" => ["KEY_5_Percent", "shift_once"],
|
||||
"*" => ["KEY_8_Asterisk", "shift_once"],
|
||||
":" => ["KEY_Semicolon_Colon", "shift_once"],
|
||||
"^" => ["KEY_6_Caret", "shift_once"],
|
||||
"<" => ["KEY_Comma_LessThan", "shift_once"],
|
||||
">" => ["KEY_Period_GreaterThan", "shift_once"],
|
||||
"?" => ["KEY_Slash_Question", "shift_once"],
|
||||
"!" => ["KEY_1_Exclamation", "shift_once"],
|
||||
"(" => ["KEY_9_LeftParenthesis", "shift_once"],
|
||||
")" => ["KEY_0_RightParenthesis", "shift_once"],
|
||||
"|" => ["KEY_Backslash_Pipe", "shift_once"],
|
||||
"@" => ["KEY_2_At", "shift_once"],
|
||||
"\"" => ["KEY_SingleQuote_DoubleQuote", "shift_once"],
|
||||
"_" => ["KEY_Dash_Underscore", "shift_once"],
|
||||
"+" => ["KEY_Equal_Plus", "shift_once"],
|
||||
"$" => ["KEY_4_Dollar", "shift_once"],
|
||||
"&" => ["KEY_7_Ampersand", "shift_once"],
|
||||
"#" => ["KEY_3_Pound", "shift_once"],
|
||||
"hash" => ["KEY_3_Pound", "shift_once"],
|
||||
"hsh" => ["KEY_3_Pound", "shift_once"],
|
||||
# enter etc
|
||||
"enter" => "KEY_ReturnEnter",
|
||||
"return" => "KEY_ReturnEnter",
|
||||
"ret" => "KEY_ReturnEnter",
|
||||
"space" => "KEY_Spacebar",
|
||||
"spc" => "KEY_Spacebar",
|
||||
"tab" => "KEY_Tab",
|
||||
"backspace" => "KEY_DeleteBackspace",
|
||||
"bksp" => "KEY_DeleteBackspace",
|
||||
"bs" => "KEY_DeleteBackspace",
|
||||
"delete" => "KEY_DeleteForward",
|
||||
"del" => "KEY_DeleteForward",
|
||||
"home" => "KEY_Home",
|
||||
"hom" => "KEY_Home",
|
||||
"end" => "KEY_End",
|
||||
"page_up" => "KEY_PageUp",
|
||||
"pgup" => "KEY_PageUp",
|
||||
"p-^" => "KEY_PageUp",
|
||||
"page_down" => "KEY_PageDown",
|
||||
"pgdn" => "KEY_PageDown",
|
||||
"p-v" => "KEY_PageDown",
|
||||
"up" => "KEY_UpArrow",
|
||||
"a-^" => "KEY_UpArrow",
|
||||
"down" => "KEY_DownArrow",
|
||||
"a-v" => "KEY_DownArrow",
|
||||
"left" => "KEY_LeftArrow",
|
||||
"a-<" => "KEY_LeftArrow",
|
||||
"right" => "KEY_RightArrow",
|
||||
"a->" => "KEY_RightArrow",
|
||||
"escape" => "KEY_Escape",
|
||||
"esc" => "KEY_Escape",
|
||||
"insert" => "KEY_Insert",
|
||||
"ins" => "KEY_Insert",
|
||||
"menu" => "KEY_Application",
|
||||
"men" => "KEY_Application",
|
||||
# modifiers
|
||||
"alt" => ["MOD_KEY_LeftAlt", "mod" ],
|
||||
"A" => ["MOD_KEY_LeftAlt", "mod" ],
|
||||
"M" => ["MOD_KEY_LeftAlt", "mod" ],
|
||||
"alt_gr" => ["MOD_KEY_RightAlt", "mod" ],
|
||||
"umlaut" => ["MOD_KEY_RightAlt", "mod" ],
|
||||
# "UM" => ["MOD_KEY_RightAlt", "mod" ],
|
||||
"UM" => ["MOD_KEY_RightAlt", "sticky_mod" ],
|
||||
"ctrl" => ["MOD_KEY_LeftControl", "mod" ],
|
||||
"C" => ["MOD_KEY_LeftControl", "mod" ],
|
||||
"control_l" => ["MOD_KEY_LeftControl", "mod" ],
|
||||
"control_r" => ["MOD_KEY_RightControl", "mod" ],
|
||||
"win" => ["MOD_KEY_LeftGUI", "mod" ],
|
||||
"W" => ["MOD_KEY_LeftGUI", "mod" ],
|
||||
"shift_l" => ["MOD_KEY_LeftShift", "mod" ],
|
||||
"S_l" => ["MOD_KEY_LeftShift", "mod" ],
|
||||
"shift_r" => ["MOD_KEY_RightShift", "mod" ],
|
||||
"S_r" => ["MOD_KEY_RightShift", "mod" ],
|
||||
"scroll_lock" => "KEY_ScrollLock",
|
||||
"SCL" => "KEY_ScrollLock",
|
||||
# null
|
||||
"NULL" => "KEY_NULL",
|
||||
"NUL" => "KEY_NULL",
|
||||
"■" => "KEY_NULL",
|
||||
# functions 1..24
|
||||
"f1" => "KEY_F1",
|
||||
"f2" => "KEY_F2",
|
||||
"f3" => "KEY_F3",
|
||||
"f4" => "KEY_F4",
|
||||
"f5" => "KEY_F5",
|
||||
"f6" => "KEY_F6",
|
||||
"f7" => "KEY_F7",
|
||||
"f8" => "KEY_F8",
|
||||
"f9" => "KEY_F9",
|
||||
"f10" => "KEY_F10",
|
||||
"f11" => "KEY_F11",
|
||||
"f12" => "KEY_F12",
|
||||
"f13" => "KEY_F13",
|
||||
"f14" => "KEY_F14",
|
||||
"f15" => "KEY_F15",
|
||||
"f16" => "KEY_F16",
|
||||
"f17" => "KEY_F17",
|
||||
"f18" => "KEY_F18",
|
||||
"f19" => "KEY_F19",
|
||||
"f20" => "KEY_F20",
|
||||
"f21" => "KEY_F21",
|
||||
"f22" => "KEY_F22",
|
||||
"f23" => "KEY_F23",
|
||||
"f24" => "KEY_F24",
|
||||
# keypad stuff
|
||||
"kp_1" => "KEYPAD_1_End",
|
||||
"kp_2" => "KEYPAD_2_DownArrow",
|
||||
"kp_3" => "KEYPAD_3_PageDown",
|
||||
"kp_4" => "KEYPAD_4_LeftArrow",
|
||||
"kp_5" => "KEYPAD_5",
|
||||
"kp_6" => "KEYPAD_6_RightArrow",
|
||||
"kp_7" => "KEYPAD_7_Home",
|
||||
"kp_8" => "KEYPAD_8_UpArrow",
|
||||
"kp_9" => "KEYPAD_9_PageUp",
|
||||
"kp_0" => "KEYPAD_0_Insert",
|
||||
#
|
||||
"kp_." => "KEYPAD_Period_Delete",
|
||||
"kp_/" => "KEYPAD_Slash",
|
||||
"kp_*" => "KEYPAD_Asterisk",
|
||||
"kp_-" => "KEYPAD_Minus",
|
||||
"kp_+" => "KEYPAD_Plus",
|
||||
"kp_en" => "KEYPAD_ENTER",
|
||||
# mediakeys
|
||||
"MD_PP" => ["MEDIAKEY_PLAY_PAUSE", "media"],
|
||||
"MD_PT" => ["MEDIAKEY_PREV_TRACK", "media"],
|
||||
"MD_NT" => ["MEDIAKEY_NEXT_TRACK", "media"],
|
||||
"MD_S" => ["MEDIAKEY_STOP", "media"],
|
||||
"MD_M" => ["MEDIAKEY_AUDIO_MUTE", "media"],
|
||||
"MD_VU" => ["MEDIAKEY_AUDIO_VOL_UP", "media"],
|
||||
"MD_VD" => ["MEDIAKEY_AUDIO_VOL_DOWN", "media"],
|
||||
"record" => ["MEDIAKEY_RECORD", "media"],
|
||||
"rewind" => ["MEDIAKEY_REWIND", "media"],
|
||||
"eject" => ["MEDIAKEY_EJECT", "media"],
|
||||
"cc_config" => ["MEDIAKEY_CC_CONFIG", "media"],
|
||||
"email" => ["MEDIAKEY_EMAIL", "media"],
|
||||
"calculator" => ["MEDIAKEY_CALCULATOR", "media"],
|
||||
"local_browser" => ["MEDIAKEY_LOCAL_BROWSER", "media"],
|
||||
"bs_search" => ["MEDIAKEY_BROWSER_SEARCH", "media"],
|
||||
"bs_home" => ["MEDIAKEY_BROWSER_HOME", "media"],
|
||||
"bs_b" => ["MEDIAKEY_BROWSER_BACK", "media"],
|
||||
"bs_f" => ["MEDIAKEY_BROWSER_FORWARD", "media"],
|
||||
"bs_stop" => ["MEDIAKEY_BROWSER_STOP", "media"],
|
||||
"bs_refresh" => ["MEDIAKEY_BROWSER_REFRESH", "media"],
|
||||
"bs_bookmarks" => ["MEDIAKEY_BROWSER_BOOKMARKS", "media"],
|
||||
# other weird shit
|
||||
"pause" => "KEY_Pause",
|
||||
"sysreq" => "KEY_SysReq_Attention",
|
||||
"sreq" => "KEY_SysReq_Attention",
|
||||
"SR" => "KEY_SysReq_Attention",
|
||||
#
|
||||
"clear" => "KEY_Clear",
|
||||
# "Clear_Again" => "KEY_Clear_Again", # wut
|
||||
"printscreen" => "KEY_PrintScreen",
|
||||
"prtscr" => "KEY_PrintScreen",
|
||||
"PS" => "KEY_PrintScreen",
|
||||
#
|
||||
"execute" => "KEY_Execute",
|
||||
"exe" => "KEY_Execute",
|
||||
"help" => "KEY_Help",
|
||||
# "menu" => "KEY_Menu", # NOT normal menu!
|
||||
"select" => "KEY_Select",
|
||||
"selct" => "KEY_Select",
|
||||
"sel" => "KEY_Select",
|
||||
"stop" => "KEY_Stop",
|
||||
#
|
||||
"again" => "KEY_Again",
|
||||
"redo" => "KEY_Again",
|
||||
"undo" => "KEY_Undo",
|
||||
#
|
||||
"cut" => "KEY_Cut",
|
||||
"copy" => "KEY_Copy",
|
||||
"paste" => "KEY_Paste",
|
||||
#
|
||||
"find" => "KEY_Find",
|
||||
#
|
||||
"mute" => "KEY_Mute",
|
||||
#
|
||||
"volume_up" => "KEY_VolumeUp",
|
||||
"volume_down" => "KEY_VolumeDown",
|
||||
"vol_up" => "KEY_VolumeUp",
|
||||
"vol_down" => "KEY_VolumeDown",
|
||||
"volumeup" => "KEY_VolumeUp",
|
||||
"volumedown" => "KEY_VolumeDown",
|
||||
"voldown" => "KEY_VolumeDown",
|
||||
"volup" => "KEY_VolumeUp",
|
||||
"voldn" => "KEY_VolumeDown",
|
||||
"vlup" => "KEY_VolumeUp",
|
||||
"vldn" => "KEY_VolumeDown",
|
||||
"vup" => "KEY_VolumeUp",
|
||||
"vdn" => "KEY_VolumeDown",
|
||||
}
|
||||
|
||||
Names = {
|
||||
# unique key identifiers, must have a name for each of the 80 physical keys
|
||||
# NOTE: the mapping to the matrix is a bit weird, so be careful
|
||||
|
||||
# name row col
|
||||
"Ln┳o" => [ 5, 0 ],
|
||||
"Ln┳4" => [ 5, 1 ],
|
||||
"Ln┳3" => [ 5, 2 ],
|
||||
"Ln┳2" => [ 5, 3 ],
|
||||
"Ln┳1" => [ 5, 4 ],
|
||||
"Ln┳0" => [ 5, 5 ],
|
||||
"Ln┳d" => [ 5, 6 ],
|
||||
"Lt┳o" => [ 4, 0 ],
|
||||
"Lt┳4" => [ 4, 1 ],
|
||||
"Lt┳3" => [ 4, 2 ],
|
||||
"Lt┳2" => [ 4, 3 ],
|
||||
"Lt┳1" => [ 4, 4 ],
|
||||
"Lt┳0" => [ 4, 5 ],
|
||||
"Lt┳d" => [ 4, 6 ],
|
||||
"Lh┳o" => [ 3, 0 ],
|
||||
"Lh┳4" => [ 3, 1 ],
|
||||
"Lh┳3" => [ 3, 2 ],
|
||||
"Lh┳2" => [ 3, 3 ],
|
||||
"Lh┳1" => [ 3, 4 ],
|
||||
"Lh┳0" => [ 3, 5 ],
|
||||
"Lb┳o" => [ 2, 0 ],
|
||||
"Lb┳4" => [ 2, 1 ],
|
||||
"Lb┳3" => [ 2, 2 ],
|
||||
"Lb┳2" => [ 2, 3 ],
|
||||
"Lb┳1" => [ 2, 4 ],
|
||||
"Lb┳0" => [ 2, 5 ],
|
||||
"Lb┳d" => [ 2, 6 ],
|
||||
"Lu┳o" => [ 1, 0 ],
|
||||
"Lu┳4" => [ 1, 1 ],
|
||||
"Lu┳3" => [ 1, 2 ],
|
||||
"Lu┳2" => [ 1, 3 ],
|
||||
"Lu┳1" => [ 1, 4 ],
|
||||
"Lz┳b" => [ 0, 5 ],
|
||||
"Lz┳c" => [ 0, 6 ],
|
||||
"Ly┳a" => [ 1, 5 ],
|
||||
"Ly┳b" => [ 1, 6 ],
|
||||
"Ly┳c" => [ 0, 4 ],
|
||||
"Lx┳a" => [ 0, 3 ],
|
||||
"Lx┳b" => [ 0, 2 ],
|
||||
"Lx┳c" => [ 0, 1 ],
|
||||
"Rn┳d" => [ 5, 7 ],
|
||||
"Rn┳0" => [ 5, 8 ],
|
||||
"Rn┳1" => [ 5, 9 ],
|
||||
"Rn┳2" => [ 5, 10 ],
|
||||
"Rn┳3" => [ 5, 11 ],
|
||||
"Rn┳4" => [ 5, 12 ],
|
||||
"Rn┳o" => [ 5, 13 ],
|
||||
"Rt┳d" => [ 4, 7 ],
|
||||
"Rt┳0" => [ 4, 8 ],
|
||||
"Rt┳1" => [ 4, 9 ],
|
||||
"Rt┳2" => [ 4, 10 ],
|
||||
"Rt┳3" => [ 4, 11 ],
|
||||
"Rt┳4" => [ 4, 12 ],
|
||||
"Rt┳o" => [ 4, 13 ],
|
||||
"Rh┳0" => [ 3, 8 ],
|
||||
"Rh┳1" => [ 3, 9 ],
|
||||
"Rh┳2" => [ 3, 10 ],
|
||||
"Rh┳3" => [ 3, 11 ],
|
||||
"Rh┳4" => [ 3, 12 ],
|
||||
"Rh┳o" => [ 3, 13 ],
|
||||
"Rb┳d" => [ 2, 7 ],
|
||||
"Rb┳0" => [ 2, 8 ],
|
||||
"Rb┳1" => [ 2, 9 ],
|
||||
"Rb┳2" => [ 2, 10 ],
|
||||
"Rb┳3" => [ 2, 11 ],
|
||||
"Rb┳4" => [ 2, 12 ],
|
||||
"Rb┳o" => [ 2, 13 ],
|
||||
"Ru┳1" => [ 1, 9 ],
|
||||
"Ru┳2" => [ 1, 10 ],
|
||||
"Ru┳3" => [ 1, 11 ],
|
||||
"Ru┳4" => [ 1, 12 ],
|
||||
"Ru┳o" => [ 1, 13 ],
|
||||
"Rz┳c" => [ 0, 7 ],
|
||||
"Rz┳b" => [ 0, 8 ],
|
||||
"Ry┳c" => [ 0, 9 ],
|
||||
"Ry┳b" => [ 1, 7 ],
|
||||
"Ry┳a" => [ 1, 8 ],
|
||||
"Rx┳c" => [ 0, 12 ],
|
||||
"Rx┳b" => [ 0, 11 ],
|
||||
"Rx┳a" => [ 0, 10 ],
|
||||
}
|
||||
|
||||
Layers.each.with_index do |layer, i|
|
||||
Keys["#{layer}"] = ["#{i}", "layer"]
|
||||
end
|
||||
|
||||
def initialize layers, name
|
||||
@keydefs = Array.new(layers.size)
|
||||
@name = name
|
||||
@pos = Key::Names[name]
|
||||
@row, @col = @pos
|
||||
|
||||
if layers.all?(&:empty?)
|
||||
layers[0] = ["NUL"]
|
||||
end
|
||||
|
||||
layers.each.with_index do |(key, type), i|
|
||||
if type.nil? and key.nil?
|
||||
@keydefs[i] = @keydefs[i-1]
|
||||
next
|
||||
end
|
||||
|
||||
# keycode and default keyfunc
|
||||
keycode, default_type = Keys[key]
|
||||
|
||||
# keyfunc
|
||||
type ||= default_type || "basic"
|
||||
keyfunc = Functions[type]
|
||||
|
||||
raise "overwriting shift key: #{key}, #{type}" if default_type == "shift" and type != default_type
|
||||
|
||||
raise "key not found: #{key}" if keycode.nil?
|
||||
raise "func not found: #{type}" if keyfunc.nil?
|
||||
|
||||
case type
|
||||
when "layer", "sticky", "_L"
|
||||
raise "invalid layer: #{key}" unless key.to_i < Key::Layers.size
|
||||
when "mod", "sticky_mod", "_M"
|
||||
raise "invalid modifier: #{key}" unless keycode.start_with? "MOD_KEY"
|
||||
end
|
||||
|
||||
case keycode
|
||||
when /^MOD_KEY/
|
||||
case type
|
||||
when "mod", "sticky_mod", "CL", "_M"; # pass
|
||||
else
|
||||
raise "invalid modifier keyfunc: #{key}, #{type}"
|
||||
end
|
||||
end
|
||||
|
||||
@keydefs[i] = Keydef.new(keycode, keyfunc)
|
||||
end
|
||||
|
||||
raise "transparency error: #{layers}" if @keydefs.any?(&:nil?)
|
||||
end
|
||||
|
||||
Dummy = Key.new(Key::Layers.map{"NULL"}, "dummy")
|
||||
end
|
||||
|
||||
class Layout
|
||||
def initialize name, keys
|
||||
@name = name
|
||||
@keys = keys
|
||||
|
||||
@rows = @keys.map(&:row).max + 1
|
||||
@cols = @keys.map(&:col).max + 1
|
||||
@matrix = @rows.times.map{Array.new(@cols)}
|
||||
|
||||
@keys.each do |key|
|
||||
@matrix[key.row][key.col] = key
|
||||
end
|
||||
end
|
||||
|
||||
def keys_to_matrix type, method
|
||||
matrix = []
|
||||
|
||||
@matrix.each.with_index do |row, row_i|
|
||||
matrix << "{"
|
||||
row.each.with_index do |key, col_i|
|
||||
key ||= Key::Dummy # some matrix positions are empty
|
||||
|
||||
matrix << "\t{ // row #{row_i} x col #{col_i}"
|
||||
Key::Layers.each.with_index do |layer_name, layer|
|
||||
matrix << "\t\t(#{type}) #{key.keydefs[layer].send(method)},".ljust(60) + "// #{key.name} on #{layer_name}"
|
||||
end
|
||||
matrix << "\t},"
|
||||
end
|
||||
matrix << "},"
|
||||
end
|
||||
|
||||
matrix.join("\n")
|
||||
end
|
||||
|
||||
def save! file
|
||||
puts "saving #{@name}..."
|
||||
|
||||
header =<<HEADER
|
||||
// ----------------------------------------------------------------------------
|
||||
// ergoDOX layout : saneo (generated)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
HEADER
|
||||
|
||||
keys = keys_to_matrix "keycode", :code
|
||||
funcs = keys_to_matrix "keyfunc", :func
|
||||
|
||||
File.open(LayoutFile, "w+") do |f|
|
||||
f.puts header
|
||||
f.puts "#define KB_LAYERS #{Key::Layers.size}"
|
||||
f.puts "static const keycode PROGMEM _kb_layout_code[KB_ROWS][KB_COLUMNS][KB_LAYERS] = {", keys, "};"
|
||||
f.puts "static const keyfunc PROGMEM _kb_layout_func[KB_ROWS][KB_COLUMNS][KB_LAYERS] = {", funcs, "};"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
left =<<EOL
|
||||
╳ Ln┳o ___ __ Ln┳4 ___ __ Ln┳3 ___ __ Ln┳2 ___ __ Ln┳1 ___ __ Ln┳0 ___ __ Ln┳d ___ __
|
||||
_LB ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃ 5 ┃ 6
|
||||
_LP ┃ f11 ┃ f1 ┃ f2 ┃ f3 ┃ f4 ┃ f5 ┃ f6
|
||||
_LN ┃ f11 ┃ f1 ┃ f2 ┃ f3 ┃ f4 ┃ f5 ┃ f6
|
||||
_LF ┃ f11 ┃ f1 ┃ f2 ┃ f3 ┃ f4 ┃ f5 ┃ f6
|
||||
_LD ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃ 5 ┃ 6
|
||||
╳ Lt┳o ___ __ Lt┳4 ___ __ Lt┳3 ___ __ Lt┳2 ___ __ Lt┳1 ___ __ Lt┳0 ___ __ Lt┳d ___ __
|
||||
_LB ┃ tab ┃ x ┃ v ┃ l ┃ c ┃ w ┃ pause
|
||||
_LP ┃ ┃ ~ ┃ [ ┃ ' ┃ < ┃ \\ ┃
|
||||
_LN ┃ ┃ esc ┃ bs ┃ ret ┃ del ┃ ins ┃
|
||||
_LF ┃ ┃ f24 ┃ f23 ┃ f22 ┃ f21 ┃ f24 ┃
|
||||
_LD ┃ ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 9 ┃
|
||||
╳ Lh┳o ___ __ Lh┳4 ___ __ Lh┳3 ___ __ Lh┳2 ___ __ Lh┳1 ___ __ Lh┳0 ___ __
|
||||
_LB ┃ UM ┃ u ┃ i ┃ a ┃ e ┃ o
|
||||
_LP ┃ ┃ , ┃ \{ ┃ ? ┃ ! ┃ (
|
||||
_LN ┃ ┃ a-< ┃ a-^ ┃ a-v ┃ a-> ┃ tab
|
||||
_LF ┃ ┃ f14 ┃ f13 ┃ f12 ┃ f11 ┃ f20
|
||||
_LD ┃ ┃ 4 ┃ 3 ┃ 2 ┃ 1 ┃ 0
|
||||
╳ Lb┳o ___ __ Lb┳4 ___ __ Lb┳3 ___ __ Lb┳2 ___ __ Lb┳1 ___ __ Lb┳0 ___ __ Lb┳d ___ __
|
||||
_LB ┃ S_l CL ┃ % ┃ * ┃ : ┃ p ┃ z ┃ ret
|
||||
_LP ┃ ┃ ` ┃ ^ ┃ | ┃ - ┃ @ ┃
|
||||
_LN ┃ ┃ hom ┃ p-^ ┃ p-v ┃ end ┃ NUL ┃
|
||||
_LF ┃ ┃ f18 ┃ f17 ┃ f16 ┃ f15 ┃ f19 ┃
|
||||
_LD ┃ ┃ 8 ┃ 7 ┃ 6 ┃ 5 ┃ 9 ┃
|
||||
╳ Lu┳o ___ __ Lu┳4 ___ __ Lu┳3 ___ __ Lu┳2 ___ __ Lu┳1 ___ __
|
||||
_LB ┃ a-< ┃ a-^ ┃ a-v ┃ a-> ┃ W
|
||||
_LP ┃ ┃ ┃ ┃ ┃
|
||||
_LN ┃ ┃ ┃ ┃ ┃
|
||||
_LF ┃ ┃ ┃ ┃ ┃
|
||||
_LD ┃ ┃ ┃ ┃ ┃
|
||||
╳ Lz┳b ___ __ Lz┳c ___ __
|
||||
_LB ┃ esc ┃ SCL
|
||||
_LP ┃ ┃
|
||||
_LN ┃ ┃
|
||||
_LF ┃ ┃
|
||||
_LD ┃ ┃
|
||||
╳ Ly┳a ___ __ Ly┳b ___ __ Ly┳c ___ __
|
||||
_LB ┃ spc ┃ C ┃ A
|
||||
_LP ┃ ┃ ┃
|
||||
_LN ┃ ┃ ┃
|
||||
_LF ┃ ┃ ┃
|
||||
_LD ┃ ┃ ┃
|
||||
╳ Lx┳a ___ __ Lx┳b ___ __ Lx┳c ___ __
|
||||
_LB ┃ spc ┃ C ┃ A
|
||||
_LP ┃ ┃ ┃
|
||||
_LN ┃ ┃ ┃
|
||||
_LF ┃ ┃ ┃
|
||||
_LD ┃ ┃ ┃
|
||||
EOL
|
||||
|
||||
right =<<EOL
|
||||
╳ Rn┳d ___ __ Rn┳0 ___ __ Rn┳1 ___ __ Rn┳2 ___ __ Rn┳3 ___ __ Rn┳4 ___ __ Rn┳o ___ __
|
||||
_LB ┃ 5 ┃ 6 ┃ 7 ┃ 8 ┃ 9 ┃ 0 ┃ 0
|
||||
_LP ┃ f5 ┃ f6 ┃ f7 ┃ f8 ┃ f9 ┃ f10 ┃ f12
|
||||
_LN ┃ f5 ┃ f6 ┃ f7 ┃ f8 ┃ f9 ┃ f10 ┃ f12
|
||||
_LF ┃ f5 ┃ f6 ┃ f7 ┃ f8 ┃ f9 ┃ f10 ┃ f12
|
||||
_LD ┃ 5 ┃ 6 ┃ 7 ┃ 8 ┃ 9 ┃ 0 ┃ 0
|
||||
╳ Rt┳d ___ __ Rt┳0 ___ __ Rt┳1 ___ __ Rt┳2 ___ __ Rt┳3 ___ __ Rt┳4 ___ __ Rt┳o ___ __
|
||||
_LB ┃ NUL ┃ k ┃ h ┃ g ┃ f ┃ q ┃ q
|
||||
_LP ┃ ┃ = ┃ > ┃ " ┃ ] ┃ ` ┃ `
|
||||
_LN ┃ ┃ 9 ┃ 5 ┃ 6 ┃ 7 ┃ 8 ┃ 8
|
||||
_LF ┃ ┃ f24 ┃ f21 ┃ f22 ┃ f23 ┃ f24 ┃ f24
|
||||
_LD ┃ ┃ 9 ┃ 5 ┃ 6 ┃ 7 ┃ 8 ┃ 8
|
||||
╳ Rh┳0 ___ __ Rh┳1 ___ __ Rh┳2 ___ __ Rh┳3 ___ __ Rh┳4 ___ __ Rh┳o ___ __
|
||||
_LB ┃ s ┃ n ┃ r ┃ t ┃ d ┃ UM
|
||||
_LP ┃ ) ┃ _ ┃ / ┃ \} ┃ . ┃
|
||||
_LN ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃
|
||||
_LF ┃ f10 ┃ f1 ┃ f2 ┃ f3 ┃ f4 ┃
|
||||
_LD ┃ 0 ┃ 1 ┃ 2 ┃ 3 ┃ 4 ┃
|
||||
╳ Rb┳d ___ __ Rb┳0 ___ __ Rb┳1 ___ __ Rb┳2 ___ __ Rb┳3 ___ __ Rb┳4 ___ __ Rb┳o ___ __
|
||||
_LB ┃ ret ┃ b ┃ m ┃ j ┃ y ┃ ; ┃ S_r CL
|
||||
_LP ┃ ┃ + ┃ $ ┃ & ┃ hsh ┃ ^ ┃
|
||||
_LN ┃ ┃ 9 ┃ 5 ┃ 6 ┃ 7 ┃ 8 ┃
|
||||
_LF ┃ ┃ f9 ┃ f5 ┃ f6 ┃ f7 ┃ f8 ┃
|
||||
_LD ┃ ┃ 9 ┃ 5 ┃ 6 ┃ 7 ┃ 8 ┃
|
||||
╳ Ru┳1 ___ __ Ru┳2 ___ __ Ru┳3 ___ __ Ru┳4 ___ __ Ru┳o ___ __
|
||||
_LB ┃ LN ┃ a-< ┃ a-^ ┃ a-v ┃ a->
|
||||
_LP ┃ ┃ ┃ ┃ ┃
|
||||
_LN ┃ ┃ ┃ ┃ ┃
|
||||
_LF ┃ ┃ ┃ ┃ ┃
|
||||
_LD ┃ ┃ ┃ ┃ ┃
|
||||
╳ Rz┳c ___ __ Rz┳b ___ __
|
||||
_LB ┃ LF ┃ LF _C
|
||||
_LP ┃ ┃
|
||||
_LN ┃ ┃
|
||||
_LF ┃ ┃
|
||||
_LD ┃ ┃
|
||||
╳ Ry┳c ___ __ Ry┳b ___ __ Ry┳a ___ __
|
||||
_LB ┃ men ┃ LF ┃ LP _L
|
||||
_LP ┃ ┃ ┃
|
||||
_LN ┃ ┃ ┃
|
||||
_LF ┃ ┃ ┃
|
||||
_LD ┃ ┃ ┃
|
||||
╳ Rx┳c ___ __ Rx┳b ___ __ Rx┳a ___ __
|
||||
_LB ┃ men ┃ LF ┃ LP _L
|
||||
_LP ┃ ┃ ┃
|
||||
_LN ┃ ┃ ┃
|
||||
_LF ┃ ┃ ┃
|
||||
_LD ┃ ┃ ┃
|
||||
EOL
|
||||
|
||||
keys_string = [
|
||||
left,
|
||||
right,
|
||||
]
|
||||
|
||||
groups = keys_string.flat_map do |str|
|
||||
str.gsub(/#.*$/, '').split(/╳/).reject(&:blank?).map(&:lines)
|
||||
end
|
||||
|
||||
keys_parsed = {}
|
||||
|
||||
groups.each.with_index(1) do |group, group_id|
|
||||
layers = Key::Layers.size
|
||||
|
||||
# extract names
|
||||
names = group.first
|
||||
names = names.scan(/(\S+)(?:[ ]*\t[^\t]*){2}/).map{|name, _| name.strip}
|
||||
keyrow = group[1..-1].reject(&:blank?)
|
||||
|
||||
# sanity check
|
||||
if keyrow.size != layers
|
||||
raise "wrong number of key layers in group ##{group_id}: #{keyrow}"
|
||||
end
|
||||
|
||||
# remove first label
|
||||
keyrow = keyrow.map{|l| l.split("┃").drop(1)}
|
||||
|
||||
(0..(keyrow.size-1)).step(layers).each do |row|
|
||||
keyrow[row].size.times do |col|
|
||||
key = layers.times.map do |layer|
|
||||
keyrow[row+layer][col]
|
||||
end
|
||||
key = key.map{|l| l.strip.split(/\s+/, 2)}
|
||||
name = names[col]
|
||||
|
||||
raise "name not unique: #{name}" if keys_parsed.include? name
|
||||
raise "unknown name: #{name}" unless Key::Names.include? name
|
||||
keys_parsed[name] = key
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
keys = keys_parsed.map {|name, layers| Key.new(layers, name)}
|
||||
|
||||
saneo = Layout.new :saneo, keys
|
||||
saneo.save! LayoutFile
|
|
@ -0,0 +1 @@
|
|||
/hid_listen
|
|
@ -0,0 +1,68 @@
|
|||
PROG = hid_listen
|
||||
|
||||
OS = LINUX
|
||||
#OS = DARWIN
|
||||
#OS = WINDOWS
|
||||
|
||||
|
||||
ifeq ($(OS), LINUX)
|
||||
TARGET = $(PROG)
|
||||
CC = gcc
|
||||
STRIP = strip
|
||||
CFLAGS = -O2 -Wall -D$(OS)
|
||||
LIBS =
|
||||
else ifeq ($(OS), DARWIN)
|
||||
TARGET = $(PROG)
|
||||
CC = gcc
|
||||
STRIP = strip
|
||||
SDK = /Developer/SDKs/MacOSX10.5.sdk
|
||||
CFLAGS = -O2 -Wall -isysroot $(SDK) -D$(OS) -arch ppc -arch i386
|
||||
LIBS = -Xlinker -syslibroot -Xlinker $(SDK) -framework IOKit -framework CoreFoundation
|
||||
else ifeq ($(OS), WINDOWS)
|
||||
TARGET = $(PROG).exe
|
||||
CC = i586-mingw32msvc-gcc
|
||||
STRIP = i586-mingw32msvc-strip
|
||||
WINDRES = i586-mingw32msvc-windres
|
||||
CFLAGS = -O2 -Wall -D$(OS)
|
||||
LIBS = -lhid -lsetupapi
|
||||
KEY_SPC = ~/bin/cert/mykey.spc
|
||||
KEY_PVK = ~/bin/cert/mykey.pvk
|
||||
KEY_TS = http://timestamp.comodoca.com/authenticode
|
||||
endif
|
||||
|
||||
|
||||
MAKEFLAGS = --jobs=2
|
||||
OBJS = hid_listen.o rawhid.o
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(PROG): $(OBJS)
|
||||
gcc -o $(PROG) $(OBJS) $(LIBS)
|
||||
$(STRIP) $(PROG)
|
||||
|
||||
$(PROG).app: $(PROG) Info.plist
|
||||
mkdir -p $(PROG).app/Contents/MacOS
|
||||
mkdir -p $(PROG).app/Contents/Resources/English.lproj
|
||||
cp Info.plist $(PROG).app/Contents/
|
||||
echo -n 'APPL????' > $(PROG).app/Contents/PkgInfo
|
||||
cp $(PROG) $(PROG).app/Contents/MacOS/$(PROG)
|
||||
cp icons/$(PROG).icns $(PROG).app/Contents/Resources/$(PROG).icns
|
||||
touch $(PROG).app
|
||||
|
||||
$(PROG).dmg: $(PROG).app
|
||||
hdiutil create -ov -srcfolder $(PROG).app $(PROG).dmg
|
||||
|
||||
$(PROG).exe: $(OBJS)
|
||||
$(CC) $(OBJS) -o $(PROG).exe $(LIBS)
|
||||
$(STRIP) $(PROG).exe
|
||||
-signcode -spc $(KEY_SPC) -v $(KEY_PVK) -t $(KEY_TS) $(PROG).exe
|
||||
|
||||
resource.o: resource.rs icons/$(PROG).ico
|
||||
$(WINDRES) -o resource.o resource.rs
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROG) $(PROG).exe $(PROG).exe.bak $(PROG).dmg
|
||||
rm -rf $(PROG).app
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/* HID Listen, http://www.pjrc.com/teensy/hid_listen.html
|
||||
* Listens (and prints) all communication received from a USB HID device,
|
||||
* which is useful for view debug messages from the Teensy USB Board.
|
||||
* Copyright 2008, PJRC.COM, LLC
|
||||
*
|
||||
* You may redistribute this program and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/
|
||||
*/
|
||||
|
||||
#include "rawhid.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
static void delay_ms(unsigned int msec);
|
||||
|
||||
int main(void) {
|
||||
char buf[64], *in, *out;
|
||||
rawhid_t *hid;
|
||||
int num, count;
|
||||
|
||||
printf("Waiting for device:");
|
||||
fflush(stdout);
|
||||
while (1) {
|
||||
hid = rawhid_open_only1(0, 0, 0xFF31, 0x0074);
|
||||
if (hid == NULL) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
delay_ms(1000);
|
||||
continue;
|
||||
}
|
||||
printf("\nListening:\n");
|
||||
while (1) {
|
||||
num = rawhid_read(hid, buf, sizeof(buf), 200);
|
||||
if (num < 0)
|
||||
break;
|
||||
if (num == 0)
|
||||
continue;
|
||||
in = out = buf;
|
||||
for (count = 0; count < num; count++) {
|
||||
if (*in) {
|
||||
*out++ = *in;
|
||||
}
|
||||
in++;
|
||||
}
|
||||
count = out - buf;
|
||||
// printf("read %d bytes, %d actual\n", num, count);
|
||||
if (count) {
|
||||
struct timeval tv;
|
||||
time_t nowtime;
|
||||
struct tm *nowtm;
|
||||
char tmbuf[64];
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
nowtime = tv.tv_sec;
|
||||
nowtm = localtime(&nowtime);
|
||||
strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
|
||||
printf("%s.%06ld ", tmbuf, tv.tv_usec);
|
||||
|
||||
num = fwrite(buf, 1, count, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
rawhid_close(hid);
|
||||
printf("\nDevice disconnected.\nWaiting for new device:");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (defined(WIN32) || defined(WINDOWS) || defined(__WINDOWS__))
|
||||
#include <windows.h>
|
||||
static void delay_ms(unsigned int msec) { Sleep(msec); }
|
||||
#else
|
||||
#include <unistd.h>
|
||||
static void delay_ms(unsigned int msec) { usleep(msec * 1000); }
|
||||
#endif
|
|
@ -0,0 +1,720 @@
|
|||
/* Raw HID I/O Routines
|
||||
* Copyright 2008, PJRC.COM, LLC
|
||||
* paul@pjrc.com
|
||||
*
|
||||
* You may redistribute this program and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/
|
||||
*/
|
||||
|
||||
|
||||
// This code will someday be turned into "librawhid", an easy-to-use
|
||||
// and truly cross platform library for accessing HID reports. But
|
||||
// there are many complexities not properly handled by this simple
|
||||
// code that would be expected from a high quality library. In
|
||||
// particular, how report IDs are handled is not uniform on the 3
|
||||
// platforms. The mac code uses a single buffer which assumes no
|
||||
// other functions can cause the "run loop" to process HID callbacks.
|
||||
// The linux version doesn't extract usage and usage page from the
|
||||
// report descriptor and just hardcodes a signature for the Teensy
|
||||
// USB debug example. Lacking from all platforms are functions to
|
||||
// manage multiple devices and robust detection of device removal
|
||||
// and attachment. There are probably lots of other issues... this
|
||||
// code has really only been used in 2 projects. If you use it,
|
||||
// please report bugs to paul@pjrc.com
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "rawhid.h"
|
||||
|
||||
#ifdef OPERATING_SYSTEM
|
||||
#undef OPERATING_SYSTEM
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/** **/
|
||||
/** Linux **/
|
||||
/** **/
|
||||
/*************************************************************************/
|
||||
|
||||
#if defined(LINUX) || defined(__LINUX__) || #system(linux)
|
||||
#define OPERATING_SYSTEM linux
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/hidraw.h>
|
||||
|
||||
|
||||
struct rawhid_struct {
|
||||
int fd;
|
||||
int name;
|
||||
int isok;
|
||||
};
|
||||
|
||||
|
||||
rawhid_t * rawhid_open_only1(int vid, int pid, int usage_page, int usage)
|
||||
{
|
||||
struct rawhid_struct *hid;
|
||||
struct stat devstat;
|
||||
struct hidraw_devinfo info;
|
||||
struct hidraw_report_descriptor *desc;
|
||||
char buf[512];
|
||||
// TODO; inputs are ignored and hardcoded into this signature....
|
||||
const unsigned char signature[]={0x06,0x31,0xFF,0x09,0x74};
|
||||
int r, i, fd=-1, len, found=0;
|
||||
|
||||
//printf("Searching for device using hidraw....\n");
|
||||
for (i=0; i<HIDRAW_MAX_DEVICES; i++) {
|
||||
if (fd > 0) close(fd);
|
||||
snprintf(buf, sizeof(buf), "/dev/hidraw%d", i);
|
||||
r = stat(buf, &devstat);
|
||||
if (r < 0) continue;
|
||||
//printf("device: %s\n", buf);
|
||||
fd = open(buf, O_RDWR);
|
||||
if (fd < 0) continue;
|
||||
//printf(" opened\n");
|
||||
r = ioctl(fd, HIDIOCGRAWINFO, &info);
|
||||
if (r < 0) continue;
|
||||
//printf(" vid=%04X, pid=%04X\n", info.vendor & 0xFFFF, info.product & 0xFFFF);
|
||||
r = ioctl(fd, HIDIOCGRDESCSIZE, &len);
|
||||
if (r < 0 || len < 1) continue;
|
||||
//printf(" len=%u\n", len);
|
||||
desc = (struct hidraw_report_descriptor *)buf;
|
||||
if (len > sizeof(buf)-sizeof(int)) len = sizeof(buf)-sizeof(int);
|
||||
desc->size = len;
|
||||
r = ioctl(fd, HIDIOCGRDESC, desc);
|
||||
if (r < 0) continue;
|
||||
if (len >= sizeof(signature) &&
|
||||
memcmp(desc->value, signature, sizeof(signature)) == 0) {
|
||||
//printf(" Match\n");
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (fd > 0) close(fd);
|
||||
return NULL;
|
||||
}
|
||||
hid = (struct rawhid_struct *)malloc(sizeof(struct rawhid_struct));
|
||||
if (!hid) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
hid->fd = fd;
|
||||
return hid;
|
||||
}
|
||||
|
||||
int rawhid_status(rawhid_t *hid)
|
||||
{
|
||||
// TODO: how to check if device is still online?
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rawhid_read(rawhid_t *h, void *buf, int bufsize, int timeout_ms)
|
||||
{
|
||||
struct rawhid_struct *hid;
|
||||
int num;
|
||||
|
||||
hid = (struct rawhid_struct *)h;
|
||||
if (!hid || hid->fd < 0) return -1;
|
||||
|
||||
while (1) {
|
||||
num = read(hid->fd, buf, bufsize);
|
||||
if (num < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN) continue;
|
||||
if (errno == EIO) {
|
||||
return -1;
|
||||
printf("I/O Error\n");
|
||||
}
|
||||
printf("read error, r=%d, errno=%d\n", num, errno);
|
||||
return -1;
|
||||
}
|
||||
//printf("read %d bytes\n", num);
|
||||
return num;
|
||||
}
|
||||
}
|
||||
|
||||
void rawhid_close(rawhid_t *h)
|
||||
{
|
||||
struct rawhid_struct *hid;
|
||||
|
||||
hid = (struct rawhid_struct *)h;
|
||||
if (!hid || hid->fd < 0) return;
|
||||
close(hid->fd);
|
||||
hid->fd = -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
struct rawhid_list_struct {
|
||||
int count;
|
||||
struct rawhid_list_entry {
|
||||
int name;
|
||||
int desc_length;
|
||||
const char *desc;
|
||||
} dev[HIDRAW_MAX_DEVICES];
|
||||
};
|
||||
|
||||
rawhid_list_t * rawhid_list_open(int vid, int pid, int usage_page, int usage)
|
||||
{
|
||||
struct rawhid_list_struct *list;
|
||||
struct stat devstat;
|
||||
struct hidraw_devinfo info;
|
||||
struct hidraw_report_descriptor *desc;
|
||||
char buf[512], *p;
|
||||
const unsigned char signature[]={0x06,0x31,0xFF,0x09,0x74};
|
||||
int r, i, fd=-1, len;
|
||||
|
||||
list = (struct rawhid_list_struct *)malloc(sizeof(struct rawhid_list_struct));
|
||||
if (!list) return NULL;
|
||||
list->count = 0;
|
||||
|
||||
printf("Searching for device using hidraw....\n");
|
||||
for (i=0; i<HIDRAW_MAX_DEVICES; i++) {
|
||||
if (fd > 0) close(fd);
|
||||
snprintf(buf, sizeof(buf), "/dev/hidraw%d", i);
|
||||
r = stat(buf, &devstat);
|
||||
if (r < 0) continue;
|
||||
printf("device: %s\n", buf);
|
||||
fd = open(buf, O_RDWR);
|
||||
if (fd < 0) continue;
|
||||
printf(" opened\n");
|
||||
r = ioctl(fd, HIDIOCGRAWINFO, &info);
|
||||
if (r < 0) continue;
|
||||
printf(" vid=%04X, pid=%04X\n", info.vendor & 0xFFFF, info.product & 0xFFFF);
|
||||
r = ioctl(fd, HIDIOCGRDESCSIZE, &len);
|
||||
if (r < 0 || len < 1) continue;
|
||||
printf(" len=%u\n", len);
|
||||
desc = (struct hidraw_report_descriptor *)buf;
|
||||
if (len > sizeof(buf)-sizeof(int)) len = sizeof(buf)-sizeof(int);
|
||||
desc->size = len;
|
||||
r = ioctl(fd, HIDIOCGRDESC, desc);
|
||||
if (r < 0) continue;
|
||||
if (len < sizeof(signature)) continue;
|
||||
// TODO: actual report parsing would be nice!
|
||||
if (memcmp(desc->value, signature, sizeof(signature)) != 0) continue;
|
||||
p = (char *)malloc(len);
|
||||
if (!p) continue;
|
||||
printf(" Match\n");
|
||||
memcpy(p, desc->value, len);
|
||||
list->dev[list->count].desc = p;
|
||||
list->dev[list->count].desc_length = len;
|
||||
list->dev[list->count].name = i;
|
||||
list->count++;
|
||||
}
|
||||
if (fd > 0) close(fd);
|
||||
return list;
|
||||
}
|
||||
|
||||
int rawhid_list_count(rawhid_list_t *list)
|
||||
{
|
||||
if (!list) return 0;
|
||||
return ((struct rawhid_list_struct *)list)->count;
|
||||
}
|
||||
|
||||
void rawhid_list_close(rawhid_list_t *list)
|
||||
{
|
||||
if (list) free(list);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // linux
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/** **/
|
||||
/** Mac OS X 10.5 **/
|
||||
/** **/
|
||||
/*************************************************************************/
|
||||
|
||||
#if (defined(DARWIN) || defined(__DARWIN__)) && !defined(OPERATING_SYSTEM)
|
||||
#define OPERATING_SYSTEM darwin
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/hid/IOHIDDevice.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// http://developer.apple.com/technotes/tn2007/tn2187.html
|
||||
|
||||
|
||||
struct rawhid_struct {
|
||||
IOHIDDeviceRef ref;
|
||||
int disconnected;
|
||||
uint8_t *buffer;
|
||||
int buffer_used;
|
||||
int buffer_report_id;
|
||||
};
|
||||
|
||||
|
||||
static void unplug_callback(void *hid, IOReturn ret, void *ref)
|
||||
{
|
||||
// This callback can only be called when the "run loop" (managed by macos)
|
||||
// is run. If the GUI is running it when idle, this will get called
|
||||
// automatically. If not, the run loop needs to be run explicitly
|
||||
// before checking the result of this function.
|
||||
//printf("HID/macos: unplugged callback!\n");
|
||||
((struct rawhid_struct *)hid)->disconnected = 1;
|
||||
}
|
||||
|
||||
|
||||
static void input_callback(void *context, IOReturn result, void *sender,
|
||||
IOHIDReportType type, uint32_t reportID, uint8_t *report,
|
||||
CFIndex reportLength)
|
||||
{
|
||||
struct rawhid_struct *hid;
|
||||
|
||||
//printf("input callback\n");
|
||||
if (!context) return;
|
||||
hid = (struct rawhid_struct *)context;
|
||||
hid->buffer_used = reportLength;
|
||||
hid->buffer_report_id = reportID;
|
||||
//printf("id = %d, reportLength = %d\n", reportID, (int)reportLength);
|
||||
//if (hid->ref == sender) printf("ref matches :-)\n");
|
||||
//if (report == hid->buffer) printf("buffer matches :)\n");
|
||||
}
|
||||
|
||||
|
||||
rawhid_t * rawhid_open_only1(int vid, int pid, int usage_page, int usage)
|
||||
{
|
||||
IOHIDManagerRef hid_manager;
|
||||
CFMutableDictionaryRef dict;
|
||||
IOReturn ret;
|
||||
CFSetRef device_set;
|
||||
IOHIDDeviceRef device_list[256];
|
||||
uint8_t *buf;
|
||||
struct rawhid_struct *hid;
|
||||
int num_devices;
|
||||
|
||||
// get access to the HID Manager
|
||||
hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
if (hid_manager == NULL || CFGetTypeID(hid_manager) != IOHIDManagerGetTypeID()) {
|
||||
printf("HID/macos: unable to access HID manager");
|
||||
return NULL;
|
||||
}
|
||||
// configure it to look for our type of device
|
||||
dict = IOServiceMatching(kIOHIDDeviceKey);
|
||||
if (dict == NULL) {
|
||||
printf("HID/macos: unable to create iokit dictionary");
|
||||
return NULL;
|
||||
}
|
||||
if (vid > 0) {
|
||||
CFDictionarySetValue(dict, CFSTR(kIOHIDVendorIDKey),
|
||||
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vid));
|
||||
}
|
||||
if (pid > 0) {
|
||||
CFDictionarySetValue(dict, CFSTR(kIOHIDProductIDKey),
|
||||
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid));
|
||||
}
|
||||
if (usage_page > 0) {
|
||||
CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsagePageKey),
|
||||
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page));
|
||||
}
|
||||
if (usage > 0) {
|
||||
CFDictionarySetValue(dict, CFSTR(kIOHIDPrimaryUsageKey),
|
||||
CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage));
|
||||
}
|
||||
IOHIDManagerSetDeviceMatching(hid_manager, dict);
|
||||
|
||||
// now open the HID manager
|
||||
ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
|
||||
if (ret != kIOReturnSuccess) {
|
||||
printf("HID/macos: Unable to open HID manager (IOHIDManagerOpen failed)");
|
||||
return NULL;
|
||||
}
|
||||
// get a list of devices that match our requirements
|
||||
device_set = IOHIDManagerCopyDevices(hid_manager);
|
||||
if (device_set == NULL) {
|
||||
//printf("HID/macos: no devices found\n");
|
||||
return NULL;
|
||||
}
|
||||
num_devices = (int)CFSetGetCount(device_set);
|
||||
//printf("number of devices found = %d\n", num_devices);
|
||||
if (num_devices < 1) {
|
||||
CFRelease(device_set);
|
||||
printf("HID/macos: no devices found, even though HID manager returned a set\n");
|
||||
return NULL;
|
||||
}
|
||||
if (num_devices > 256) {
|
||||
CFRelease(device_set);
|
||||
printf("HID/macos: too many devices, we get confused if more than 256!\n");
|
||||
return NULL;
|
||||
}
|
||||
CFSetGetValues(device_set, (const void **)&device_list);
|
||||
CFRelease(device_set);
|
||||
// open the first device in the list
|
||||
ret = IOHIDDeviceOpen(device_list[0], kIOHIDOptionsTypeNone);
|
||||
if (ret != kIOReturnSuccess) {
|
||||
printf("HID/macos: error opening device\n");
|
||||
return NULL;
|
||||
}
|
||||
// return this device
|
||||
hid = (struct rawhid_struct *)malloc(sizeof(struct rawhid_struct));
|
||||
buf = (uint8_t *)malloc(0x1000);
|
||||
if (hid == NULL || buf == NULL) {
|
||||
IOHIDDeviceRegisterRemovalCallback(device_list[0], NULL, NULL);
|
||||
IOHIDDeviceClose(device_list[0], kIOHIDOptionsTypeNone);
|
||||
printf("HID/macos: Unable to allocate memory\n");
|
||||
return NULL;
|
||||
}
|
||||
hid->ref = device_list[0];
|
||||
hid->disconnected = 0;
|
||||
hid->buffer = buf;
|
||||
hid->buffer_used = 0;
|
||||
|
||||
// register a callback to receive input
|
||||
IOHIDDeviceRegisterInputReportCallback(hid->ref, hid->buffer, 0x1000,
|
||||
input_callback, hid);
|
||||
|
||||
|
||||
// register a callback to find out when it's unplugged
|
||||
IOHIDDeviceScheduleWithRunLoop(hid->ref, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
IOHIDDeviceRegisterRemovalCallback(hid->ref, unplug_callback, hid);
|
||||
return hid;
|
||||
}
|
||||
|
||||
int rawhid_status(rawhid_t *hid)
|
||||
{
|
||||
if (!hid) return -1;
|
||||
// if a GUI is causing the run loop run, this will likely mess it up. Just
|
||||
// comment it out and if the callback still gets called without this, then
|
||||
// there's no need to run the run loop here!
|
||||
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) ;
|
||||
if (((struct rawhid_struct *)hid)->disconnected) {
|
||||
//printf("HID/macos: status: disconnected\n");
|
||||
return -1;
|
||||
}
|
||||
//printf("HID/macos: status: ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rawhid_close(rawhid_t *hid)
|
||||
{
|
||||
IOHIDDeviceRef ref;
|
||||
|
||||
if (!hid) return;
|
||||
ref = ((struct rawhid_struct *)hid)->ref;
|
||||
IOHIDDeviceRegisterRemovalCallback(ref, NULL, NULL);
|
||||
IOHIDDeviceClose(ref, kIOHIDOptionsTypeNone);
|
||||
free(hid);
|
||||
}
|
||||
|
||||
int rawhid_read(rawhid_t *h, void *buf, int bufsize, int timeout_ms)
|
||||
{
|
||||
struct rawhid_struct *hid;
|
||||
int r, len;
|
||||
|
||||
//printf("begin read\n");
|
||||
hid = (struct rawhid_struct *)h;
|
||||
if (!hid || hid->disconnected) return -1;
|
||||
while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) == kCFRunLoopRunHandledSource) {
|
||||
if (hid->buffer_used) {
|
||||
len = hid->buffer_used;
|
||||
if (len > bufsize) len = bufsize;
|
||||
memcpy(buf, hid->buffer, len);
|
||||
hid->buffer_used = 0;
|
||||
return len;
|
||||
}
|
||||
if (hid->disconnected) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
r = CFRunLoopRunInMode(kCFRunLoopDefaultMode, (double)timeout_ms / 1000.0, true);
|
||||
if (r == kCFRunLoopRunTimedOut) {
|
||||
//printf("read timeout\n");
|
||||
return 0;
|
||||
}
|
||||
if (hid->buffer_used) {
|
||||
len = hid->buffer_used;
|
||||
if (len > bufsize) len = bufsize;
|
||||
memcpy(buf, hid->buffer, len);
|
||||
hid->buffer_used = 0;
|
||||
return len;
|
||||
}
|
||||
if (hid->disconnected) return -1;
|
||||
return 0;
|
||||
//num = bufsize;
|
||||
//ret = IOHIDDeviceGetReport(ref, kIOHIDReportTypeInput, 0, buf, &num);
|
||||
//if (!ret) return -1;
|
||||
//return num;
|
||||
}
|
||||
|
||||
int rawhid_write(rawhid_t *hid, const void *buf, int len, int timeout_ms)
|
||||
{
|
||||
IOReturn ret;
|
||||
|
||||
if (((struct rawhid_struct *)hid)->disconnected) return -1;
|
||||
ret = IOHIDDeviceSetReport(((struct rawhid_struct *)hid)->ref,
|
||||
kIOHIDReportTypeOutput, 0, buf, len);
|
||||
if (ret != kIOReturnSuccess) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // Darwin - Mac OS X
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/** **/
|
||||
/** Windows 2000/XP/Vista **/
|
||||
/** **/
|
||||
/*************************************************************************/
|
||||
|
||||
#if (defined(WIN32) || defined(WINDOWS) || defined(__WINDOWS__)) && !defined(OPERATING_SYSTEM)
|
||||
#define OPERATING_SYSTEM windows
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <ddk/hidsdi.h>
|
||||
#include <ddk/hidclass.h>
|
||||
|
||||
// http://msdn.microsoft.com/en-us/library/ms790932.aspx
|
||||
|
||||
struct rawhid_struct {
|
||||
HANDLE handle;
|
||||
};
|
||||
|
||||
|
||||
rawhid_t * rawhid_open_only1(int vid, int pid, int usage_page, int usage)
|
||||
{
|
||||
GUID guid;
|
||||
HDEVINFO info;
|
||||
DWORD index=0, required_size;
|
||||
SP_DEVICE_INTERFACE_DATA iface;
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA *details;
|
||||
HIDD_ATTRIBUTES attrib;
|
||||
PHIDP_PREPARSED_DATA hid_data;
|
||||
HIDP_CAPS capabilities;
|
||||
struct rawhid_struct *hid;
|
||||
HANDLE h;
|
||||
BOOL ret;
|
||||
|
||||
|
||||
HidD_GetHidGuid(&guid);
|
||||
info = SetupDiGetClassDevs(&guid, NULL, NULL,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (info == INVALID_HANDLE_VALUE) {
|
||||
printf("HID/win32: SetupDiGetClassDevs failed");
|
||||
return NULL;
|
||||
}
|
||||
for (index=0; ;index++) {
|
||||
iface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
ret = SetupDiEnumDeviceInterfaces(info, NULL, &guid, index, &iface);
|
||||
if (!ret) {
|
||||
// end of list
|
||||
SetupDiDestroyDeviceInfoList(info);
|
||||
return NULL;
|
||||
}
|
||||
SetupDiGetInterfaceDeviceDetail(info, &iface, NULL, 0, &required_size, NULL);
|
||||
details = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(required_size);
|
||||
if (details == NULL) continue;
|
||||
memset(details, 0, required_size);
|
||||
details->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
|
||||
ret = SetupDiGetDeviceInterfaceDetail(info, &iface, details,
|
||||
required_size, NULL, NULL);
|
||||
if (!ret) {
|
||||
free(details);
|
||||
continue;
|
||||
}
|
||||
h = CreateFile(details->DevicePath, GENERIC_READ|GENERIC_WRITE,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED, NULL);
|
||||
free(details);
|
||||
if (h == INVALID_HANDLE_VALUE) continue;
|
||||
attrib.Size = sizeof(HIDD_ATTRIBUTES);
|
||||
ret = HidD_GetAttributes(h, &attrib);
|
||||
if (!ret) {
|
||||
CloseHandle(h);
|
||||
continue;
|
||||
}
|
||||
//printf("HID/win32: USB Device:\n");
|
||||
//printf("HID/win32: vid = 0x%04X\n", (int)(attrib.VendorID));
|
||||
//printf("HID/win32: pid = 0x%04X\n", (int)(attrib.ProductID));
|
||||
if (vid > 0 && vid != (int)(attrib.VendorID)) {
|
||||
CloseHandle(h);
|
||||
continue;
|
||||
}
|
||||
if (pid > 0 && pid != (int)(attrib.ProductID)) {
|
||||
CloseHandle(h);
|
||||
continue;
|
||||
}
|
||||
if (!HidD_GetPreparsedData(h, &hid_data)) {
|
||||
printf("HID/win32: HidD_GetPreparsedData failed\n");
|
||||
CloseHandle(h);
|
||||
continue;
|
||||
}
|
||||
if (!HidP_GetCaps(hid_data, &capabilities)) {
|
||||
printf("HID/win32: HidP_GetCaps failed\n");
|
||||
HidD_FreePreparsedData(hid_data);
|
||||
CloseHandle(h);
|
||||
continue;
|
||||
}
|
||||
//printf("HID/win32: usage_page = 0x%04X\n", (int)(capabilities.UsagePage));
|
||||
//printf("HID/win32: usage = 0x%04X\n", (int)(capabilities.Usage));
|
||||
if (usage_page > 0 && usage_page != (int)(capabilities.UsagePage)) {
|
||||
HidD_FreePreparsedData(hid_data);
|
||||
CloseHandle(h);
|
||||
continue;
|
||||
}
|
||||
if (usage > 0 && usage != (int)(capabilities.Usage)) {
|
||||
HidD_FreePreparsedData(hid_data);
|
||||
CloseHandle(h);
|
||||
continue;
|
||||
}
|
||||
HidD_FreePreparsedData(hid_data);
|
||||
hid = (struct rawhid_struct *)malloc(sizeof(struct rawhid_struct));
|
||||
if (!hid) {
|
||||
CloseHandle(h);
|
||||
printf("HID/win32: Unable to get %d bytes", sizeof(struct rawhid_struct));
|
||||
continue;
|
||||
}
|
||||
hid->handle = h;
|
||||
return hid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int rawhid_status(rawhid_t *hid)
|
||||
{
|
||||
PHIDP_PREPARSED_DATA hid_data;
|
||||
|
||||
if (!hid) return -1;
|
||||
if (!HidD_GetPreparsedData(((struct rawhid_struct *)hid)->handle, &hid_data)) {
|
||||
printf("HID/win32: HidD_GetPreparsedData failed, device assumed disconnected\n");
|
||||
return -1;
|
||||
}
|
||||
printf("HID/win32: HidD_GetPreparsedData ok, device still online :-)\n");
|
||||
HidD_FreePreparsedData(hid_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rawhid_close(rawhid_t *hid)
|
||||
{
|
||||
if (!hid) return;
|
||||
CloseHandle(((struct rawhid_struct *)hid)->handle);
|
||||
free(hid);
|
||||
}
|
||||
|
||||
int rawhid_read(rawhid_t *h, void *buf, int bufsize, int timeout_ms)
|
||||
{
|
||||
DWORD num=0, result;
|
||||
BOOL ret;
|
||||
OVERLAPPED ov;
|
||||
struct rawhid_struct *hid;
|
||||
int r;
|
||||
|
||||
hid = (struct rawhid_struct *)h;
|
||||
if (!hid) return -1;
|
||||
|
||||
memset(&ov, 0, sizeof(OVERLAPPED));
|
||||
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (ov.hEvent == NULL) return -1;
|
||||
|
||||
ret = ReadFile(hid->handle, buf, bufsize, &num, &ov);
|
||||
if (ret) {
|
||||
//printf("HID/win32: read success (immediate)\n");
|
||||
r = num;
|
||||
} else {
|
||||
if (GetLastError() == ERROR_IO_PENDING) {
|
||||
result = WaitForSingleObject(ov.hEvent, timeout_ms);
|
||||
if (result == WAIT_OBJECT_0) {
|
||||
if (GetOverlappedResult(hid->handle, &ov, &num, FALSE)) {
|
||||
//printf("HID/win32: read success (delayed)\n");
|
||||
r = num;
|
||||
} else {
|
||||
//printf("HID/win32: read failure (delayed)\n");
|
||||
r = -1;
|
||||
}
|
||||
} else {
|
||||
//printf("HID/win32: read timeout, %lx\n", result);
|
||||
CancelIo(hid->handle);
|
||||
r = 0;
|
||||
}
|
||||
} else {
|
||||
//printf("HID/win32: read error (immediate)\n");
|
||||
r = -1;
|
||||
}
|
||||
}
|
||||
CloseHandle(ov.hEvent);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int rawhid_write(rawhid_t *h, const void *buf, int len, int timeout_ms)
|
||||
{
|
||||
DWORD num=0;
|
||||
BOOL ret;
|
||||
OVERLAPPED ov;
|
||||
struct rawhid_struct *hid;
|
||||
int r;
|
||||
|
||||
hid = (struct rawhid_struct *)h;
|
||||
if (!hid) return -1;
|
||||
|
||||
memset(&ov, 0, sizeof(OVERLAPPED));
|
||||
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (ov.hEvent == NULL) return -1;
|
||||
|
||||
// first byte is report ID, must be zero if report IDs not used
|
||||
ret = WriteFile(hid->handle, buf, len, &num, &ov);
|
||||
if (ret) {
|
||||
if (num == len) {
|
||||
//printf("HID/win32: write success (immediate)\n");
|
||||
r = 0;
|
||||
} else {
|
||||
//printf("HID/win32: partial write (immediate)\n");
|
||||
r = -1;
|
||||
}
|
||||
} else {
|
||||
if (GetLastError() == ERROR_IO_PENDING) {
|
||||
if (GetOverlappedResult(hid->handle, &ov, &num, TRUE)) {
|
||||
if (num == len) {
|
||||
//printf("HID/win32: write success (delayed)\n");
|
||||
r = 0;
|
||||
} else {
|
||||
//printf("HID/win32: partial write (delayed)\n");
|
||||
r = -1;
|
||||
}
|
||||
} else {
|
||||
//printf("HID/win32: write error (delayed)\n");
|
||||
r = -1;
|
||||
}
|
||||
} else {
|
||||
//printf("HID/win32: write error (immediate)\n");
|
||||
r = -1;
|
||||
}
|
||||
}
|
||||
CloseHandle(ov.hEvent);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#endif // windows
|
||||
|
||||
|
||||
|
||||
#ifndef OPERATING_SYSTEM
|
||||
#error Unknown operating system
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef rawhid_included_h__
|
||||
#define rawhid_included_h__
|
||||
|
||||
// Raw HID, Basic API
|
||||
typedef void rawhid_t;
|
||||
rawhid_t * rawhid_open_only1(int vid, int pid, int usage_page, int usage);
|
||||
int rawhid_status(rawhid_t *hid);
|
||||
int rawhid_read(rawhid_t *h, void *buf, int bufsize, int timeout_ms);
|
||||
int rawhid_write(rawhid_t *hid, const void *buf, int len, int timeout_ms);
|
||||
void rawhid_close(rawhid_t *h);
|
||||
|
||||
|
||||
// Raw HID, Multiple Device API
|
||||
typedef void rawhid_list_t;
|
||||
rawhid_list_t * rawhid_list_open(int vid, int pid, int usage_page, int usage);
|
||||
int rawhid_list_count(rawhid_list_t *list);
|
||||
void rawhid_list_close(rawhid_list_t *list);
|
||||
int rawhid_list_indexof(rawhid_list_t *list, rawhid_t *hid);
|
||||
void rawhid_list_remove(rawhid_list_t *list, rawhid_t *hid);
|
||||
rawhid_t * rawhid_open(rawhid_list_t *list, int index);
|
||||
|
||||
|
||||
#endif
|
116
makefile
116
makefile
|
@ -1,118 +1,16 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# makefile for the ergoDOX project
|
||||
#
|
||||
# This should produce a single file (probably in an archive format) for
|
||||
# distribution, containing everything people will need to use the software.
|
||||
#
|
||||
# DEPENDENCIES: This is unabashedly dependant on (the GNU implementation of)
|
||||
# various Unix commands, and therefore probably won't work in a Windows
|
||||
# environment (besides maybe cygwin). Sorry... I don't know a good portable
|
||||
# way to write it.
|
||||
#
|
||||
# TODO:
|
||||
# - include doc files (and maybe render them in html)
|
||||
# - include the UI stuff (once it's done)
|
||||
# -----------------------------------------------------------------------------
|
||||
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
# Released under The MIT License (MIT) (see "license.md")
|
||||
# Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
.PHONY: all clean firmware layout
|
||||
|
||||
include src/makefile-options
|
||||
|
||||
# which layouts to compile (will override the variable in src/makefile-options)
|
||||
# --- default
|
||||
LAYOUT := qwerty-kinesis-mod
|
||||
# --- all
|
||||
LAYOUTS := qwerty-kinesis-mod dvorak-kinesis-mod colemak-symbol-mod
|
||||
|
||||
# system specific stuff
|
||||
UNAME := $(shell uname)
|
||||
ifeq ($(UNAME),Darwin)
|
||||
DATE_PROG := gdate
|
||||
else
|
||||
DATE_PROG := date
|
||||
endif
|
||||
|
||||
CURRENT_DATE := $(shell $(DATE_PROG) --rfc-3339 s)
|
||||
|
||||
# git info
|
||||
GIT_BRANCH := $(shell git branch -l | grep '*' | cut -c 3-)
|
||||
GIT_COMMIT_DATE := $(shell git log -n 1 --pretty --date=iso | grep 'Date' | cut -c 9- )
|
||||
GIT_COMMIT_ID := $(shell git log -n 1 | grep 'commit' | cut -c 8-)
|
||||
|
||||
# name to use for the final distribution file or package
|
||||
TARGET := ergodox-firmware--$(GIT_BRANCH)--$(shell $(DATE_PROG) -d "$(GIT_COMMIT_DATE)" +'%Y%m%dT%H%M%S')--$(shell echo $(GIT_COMMIT_ID) | cut -c 1-7)--$(LAYOUT)
|
||||
|
||||
# directories
|
||||
BUILD := build
|
||||
ROOT := $(BUILD)/$(TARGET)
|
||||
SCRIPTS := build-scripts
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
.PHONY: all clean checkin build-dir firmware dist zip zip-all
|
||||
|
||||
all: dist
|
||||
all: firmware
|
||||
|
||||
clean:
|
||||
git clean -dX # remove ignored files and directories
|
||||
-rm -r '$(BUILD)'
|
||||
cd src; $(MAKE) clean
|
||||
|
||||
checkin:
|
||||
-git commit -a
|
||||
|
||||
build-dir:
|
||||
-rm -r '$(BUILD)/$(TARGET)'*
|
||||
-mkdir -p '$(BUILD)/$(TARGET)'
|
||||
|
||||
firmware:
|
||||
cd src; $(MAKE) LAYOUT=$(LAYOUT) all
|
||||
|
||||
$(ROOT)/firmware.%: firmware
|
||||
cp 'src/firmware.$*' '$@'
|
||||
|
||||
|
||||
$(ROOT)/firmware--ui-info.json: $(SCRIPTS)/gen-ui-info.py checkin
|
||||
( ./'$<' \
|
||||
--current-date '$(shell $(DATE_PROG) --rfc-3339 s)' \
|
||||
--git-commit-date '$(GIT_COMMIT_DATE)' \
|
||||
--git-commit-id '$(GIT_COMMIT_ID)' \
|
||||
--map-file-path '$(BUILD)/$(TARGET)/firmware.map' \
|
||||
--source-code-path 'src' \
|
||||
--matrix-file-path 'src/keyboard/$(KEYBOARD)/matrix.h' \
|
||||
--layout-file-path \
|
||||
'src/keyboard/$(KEYBOARD)/layout/$(LAYOUT).c' \
|
||||
) > '$@'
|
||||
|
||||
$(ROOT)/firmware--layout.html: \
|
||||
$(SCRIPTS)/gen-layout.py \
|
||||
$(ROOT)/firmware--ui-info.json
|
||||
\
|
||||
( ./'$<' \
|
||||
--ui-info-file '$(ROOT)/firmware--ui-info.json' \
|
||||
) > '$@'
|
||||
|
||||
|
||||
dist: \
|
||||
checkin \
|
||||
build-dir \
|
||||
$(ROOT)/firmware.hex \
|
||||
$(ROOT)/firmware.eep \
|
||||
$(ROOT)/firmware.map \
|
||||
$(ROOT)/firmware--ui-info.json \
|
||||
$(ROOT)/firmware--layout.html
|
||||
|
||||
zip: dist
|
||||
( cd '$(BUILD)/$(TARGET)'; \
|
||||
zip '../$(TARGET).zip' \
|
||||
-r * .* \
|
||||
-x '..*' )
|
||||
|
||||
zip-all:
|
||||
for layout in $(LAYOUTS); do \
|
||||
make LAYOUT=$$layout zip; \
|
||||
done
|
||||
firmware: clean layout
|
||||
cd src; $(MAKE) all
|
||||
|
||||
layout:
|
||||
./generate_layout.rb
|
||||
|
|
117
readme.md
117
readme.md
|
@ -1,14 +1,62 @@
|
|||
# [ergodox-firmware][]: Firmware for the [ErgoDox keyboard][]
|
||||
# [Firmware][ergodox-firmware] for the [ErgoDox keyboard][]
|
||||
|
||||
The official website is [ergodox.org] (http://www.ergodox.org).
|
||||
Also see the [geekhack]
|
||||
(http://geekhack.org/showthread.php?22780-Interest-Check-Custom-split-ergo-keyboard)
|
||||
and [deskthority]
|
||||
(http://deskthority.net/workshop-f7/split-ergonomic-keyboard-project-t1753.html)
|
||||
discussion threads.
|
||||
discussion threads.
|
||||
Kits are periodically for sale [on Massdrop] (https://www.massdrop.com/buy/ergodox),
|
||||
who also hosts [build instructions] (https://www.massdrop.com/ext/ergodox/assembly.php)
|
||||
and a [web UI] (https://www.massdrop.com/ext/ergodox)
|
||||
for configuring layouts.
|
||||
|
||||
[ergodox-firmware]: https://github.com/benblazak/ergodox-firmware
|
||||
[ergodox keyboard]: http://ergodox.org/
|
||||
|
||||
### Notes
|
||||
A rewrite is currently underway (see the 'partial-rewrite' branch) and so this
|
||||
branch isn't quite receiving the attention it used to. Things that have
|
||||
changed since this document was last properly updated:
|
||||
* Ryan Prince ([judascleric] (https://github.com/judascleric)) implemented
|
||||
sticky keys, and added a Colemak layout using them.
|
||||
* Revision 2 of the firmware (on the 'partial-rewrite' branch) is working! Not
|
||||
ready for merging or a general release though, and I'm not ready to declare
|
||||
anything final, so you may not want to switch yet; but developers may want to
|
||||
think about checking it out. :)
|
||||
* Ryan Prince ([judascleric] (https://github.com/judascleric)) implemented 3
|
||||
media keys (play/pause, previous track, and next track) in Revision 1, using
|
||||
a bit of code from [hasu's tmk firmware]
|
||||
(https://github.com/tmk/tmk_keyboard). Revision 2 probably won't have this
|
||||
functionality for a while.
|
||||
* Gyuri Horak implemented NKRO and mouse keys in [his branch]
|
||||
(https://github.com/dyuri/ergodox-firmware) of rev-2. Not merged, but I plan
|
||||
to implement the features later, if I can. See [Pull Request #28]
|
||||
(https://github.com/benblazak/ergodox-firmware/pull/28).
|
||||
* Oleg Kostyuk (cub-uanic) [ported the TMK firmware]
|
||||
(https://github.com/cub-uanic/tmk_keyboard)
|
||||
(written by "hasu") to the ErgoDox!
|
||||
* Jacob McIntosh ([nacitar](https://github.com/nacitar)) implemented 4 more
|
||||
media keys (stop, mute, vol_up, and vol_down) in rev-1, fixed a media key
|
||||
bug, and implemented workman-p.
|
||||
|
||||
|
||||
|
||||
### Table of Contents
|
||||
*generated with [DocToc](http://doctoc.herokuapp.com/)*
|
||||
|
||||
- [About This File](#about-this-file)
|
||||
- [About This Project](#about-this-project)
|
||||
- [Downloading Binaries](#downloading-binaries)
|
||||
- [Compiling](#compiling)
|
||||
- [Issues and Feature Requests](#issues-and-feature-requests)
|
||||
- [Features (on the ErgoDox)](#features-on-the-ergodox)
|
||||
- [About This Project (more technical)](#about-this-project-more-technical)
|
||||
- [Dependencies (for building from source)](#dependencies-for-building-from-source)
|
||||
- [HowTo](#howto)
|
||||
- [Load Firmware onto the Teensy](#load-firmware-onto-the-teensy)
|
||||
- [Change the Direction of the Diodes](#change-the-direction-of-the-diodes)
|
||||
- [Compile the Source Code](#compile-the-source-code)
|
||||
- [Create a New Keymap](#create-a-new-keymap)
|
||||
- [Add Code for a Different Type of Keyboard](#add-code-for-a-different-type-of-keyboard)
|
||||
|
||||
|
||||
## About This File
|
||||
|
@ -21,35 +69,47 @@ the fact that Markdown doesn't have any way (that I know of) to rewrite the
|
|||
URLs as would be required.
|
||||
|
||||
|
||||
## Features (on the ErgoDox)
|
||||
* 6KRO
|
||||
## About This Project
|
||||
|
||||
This project is meant to be a usable firmware for the [ErgoDox keyboard][]. I
|
||||
started writing it because, at the time, it was the easiest way for me to get
|
||||
I²C working, and I very much wanted to avoid having the designers put a
|
||||
16-pin connector (or something awful like that) between the two halves :) . It
|
||||
was also my first project in pure C (though I'm planning to rewrite it in C++),
|
||||
and my first attempt at anything remotely this close to hardware. I've done my
|
||||
best to put decent documentation everywhere, in the hope that my perspective as
|
||||
a n00b to this area might be useful for others.
|
||||
|
||||
The 'master' branch is meant to be stable - the one you want if you're going to
|
||||
update your keyboard firmware, and usually the one you want if you're going to
|
||||
fork. This is a small project, so there may be times when other branches have
|
||||
a bunch going on, and 'master' doesn't, and things sort of fall out of sync...
|
||||
but I'll try to avoid that. See the other branches for what's going on there.
|
||||
|
||||
Also, lots of other documentation can be found intermixed with the source
|
||||
(especially in the accompanying '.md' files), and [references.md]
|
||||
(references.md) contains lots of good links, along with descriptions.
|
||||
|
||||
### Downloading Binaries
|
||||
If you're just looking for binaries, they can be downloaded [here]
|
||||
[dropbox-download-page].
|
||||
|
||||
### Compiling
|
||||
If you're just trying to compile, jump to the How To: [Compile the Source Code]
|
||||
(#compile-the-source-code) section.
|
||||
|
||||
### Issues and Feature Requests
|
||||
Open issues, feature requests, and such are tracked [on github]
|
||||
(/benblazak/ergodox-firmware/issues).
|
||||
|
||||
### Features (on the ErgoDox)
|
||||
* 6KRO (conforms to the USB boot specification)
|
||||
* Teensy 2.0, MCP23018 I/O expander
|
||||
* ~167 Hz scan rate (last time I measured it) (most of which is spent
|
||||
communicating via I²C)
|
||||
* firmware level layers
|
||||
|
||||
|
||||
## About This Project
|
||||
|
||||
If you're just looking for binaries, they can be downloaded [here]
|
||||
[dropbox-download-page].
|
||||
|
||||
If you're just trying to compile, jump to the How To: [Compile the Source Code]
|
||||
(#compile-the-source-code) section.
|
||||
|
||||
Open issues, feature requests, and such are tracked [on github]
|
||||
(/benblazak/ergodox-firmware/issues).
|
||||
|
||||
This project is still definitely a work in progress, but it's getting towards
|
||||
something I'll be happy with when the keyboard finally goes into group buy.
|
||||
The 'master' branch should always contain the most recent "stable" release of
|
||||
the code. The 'dev' branch may have new things, but it may also have
|
||||
expiremental or not yet fixed things. Code on the 'master' branch should also
|
||||
tend to be more thoroughly tested. Please see the source (and especially the
|
||||
accompanying '.md' files) for documentation. And [references.md]
|
||||
(references.md) contains lots of good links, along with descriptions.
|
||||
|
||||
|
||||
## About This Project (more technical)
|
||||
|
||||
If you're looking to hack on the source, or just feel like reading it:
|
||||
|
@ -303,6 +363,9 @@ your goal.
|
|||
|
||||
|
||||
[dropbox-download-page]: https://www.dropbox.com/sh/8bbol6fkvydmtmg/QLudrdEyc9
|
||||
[ergodox-firmware]: https://github.com/benblazak/ergodox-firmware
|
||||
[ergodox keyboard]: http://ergodox.org/
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Copyright © 2012 Ben Blazak <benblazak.dev@gmail.com>
|
||||
|
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,167 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* controller specific exports
|
||||
*
|
||||
* Files for different keyboards are used by modifying a variable in the
|
||||
* Makefile
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/controller.h )
|
||||
#include INCLUDE
|
||||
#define USB_DEBUG_HID
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <util/delay.h>
|
||||
#include <util/twi.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 MCP23018__DRIVE_ROWS 0
|
||||
#define TEENSY__DRIVE_COLUMNS 1
|
||||
#define MCP23018__DRIVE_COLUMNS 1
|
||||
|
||||
#define KB_ROWS 6 // must match real life
|
||||
#define KB_COLUMNS 14 // must match real life
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
u8 kb_init(void);
|
||||
u8 kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define MCP23018_TWI_ADDRESS 0b0100000
|
||||
|
||||
u8 mcp23018_init(void);
|
||||
u8 mcp23018_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
u8 teensy_init(void);
|
||||
u8 teensy_update_matrix( bool matrix[KB_ROWS][KB_COLUMNS] );
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define TWI_FREQ 400000
|
||||
|
||||
void twi_init (void);
|
||||
u8 twi_start (void);
|
||||
void twi_stop (void);
|
||||
u8 twi_send (u8 data);
|
||||
u8 twi_read (u8 * data);
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
void usb_init(void); // initialize everything
|
||||
u8 usb_configured(void); // is the USB port configured
|
||||
|
||||
i8 usb_keyboard_send(void);
|
||||
extern u8 keyboard_modifier_keys;
|
||||
extern u8 keyboard_keys[6];
|
||||
|
||||
extern u16 consumer_key;
|
||||
|
||||
// Everything below this point is only intended for usb_serial.c
|
||||
|
||||
#define EP_TYPE_CONTROL 0x00
|
||||
#define EP_TYPE_BULK_IN 0x81
|
||||
#define EP_TYPE_BULK_OUT 0x80
|
||||
#define EP_TYPE_INTERRUPT_IN 0xC1
|
||||
#define EP_TYPE_INTERRUPT_OUT 0xC0
|
||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41
|
||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
|
||||
|
||||
#define EP_SINGLE_BUFFER 0x02
|
||||
#define EP_DOUBLE_BUFFER 0x06
|
||||
|
||||
#define EP_SIZE(s) ((s) == 64 ? 0x30 : \
|
||||
((s) == 32 ? 0x20 : \
|
||||
((s) == 16 ? 0x10 : \
|
||||
0x00)))
|
||||
|
||||
#define MAX_ENDPOINT 4
|
||||
|
||||
#define LSB(n) (n & 255)
|
||||
#define MSB(n) ((n >> 8) & 255)
|
||||
|
||||
#define HW_CONFIG() (UHWCON = 0x01)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x12)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
|
||||
// standard control endpoint request types
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
#define SET_FEATURE 3
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
// HID (human interface device)
|
||||
#define HID_GET_REPORT 1
|
||||
#define HID_GET_IDLE 2
|
||||
#define HID_GET_PROTOCOL 3
|
||||
#define HID_SET_REPORT 9
|
||||
#define HID_SET_IDLE 10
|
||||
#define HID_SET_PROTOCOL 11
|
||||
// CDC (communication class device)
|
||||
#define CDC_SET_LINE_CODING 0x20
|
||||
#define CDC_GET_LINE_CODING 0x21
|
||||
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// debug
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
extern volatile u8 debug_flush_timer;
|
||||
|
||||
void usb_debug_free_memory(void);
|
||||
void usb_debug_print(const char *s);
|
||||
void usb_debug_printf(const char *fmt, ...);
|
||||
i8 usb_debug_putchar(char c);
|
||||
void usb_debug_flush_output(void);
|
||||
|
||||
#ifdef KBD_DEBUG
|
||||
#define debug_print(s) usb_debug_print(PSTR(s))
|
||||
#define debug_printf(s, args...) usb_debug_printf(PSTR(s), args)
|
||||
#else
|
||||
#define debug_print(s)
|
||||
#define debug_printf(...)
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// timer
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
extern volatile uint32_t timer0_ms;
|
||||
|
||||
void timer0_init(void);
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller 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 "./matrix.h"
|
||||
#include "./controller/mcp23018--functions.h"
|
||||
#include "./controller/teensy-2-0--functions.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
* - error: number of the function that failed
|
||||
*/
|
||||
uint8_t kb_init(void) {
|
||||
if (teensy_init()) // must be first
|
||||
return 1;
|
||||
if (mcp23018_init()) // must be second
|
||||
return 2;
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
/* returns
|
||||
* - success: 0
|
||||
* - error: number of the function that failed
|
||||
*/
|
||||
uint8_t kb_update_matrix(bool matrix[KB_ROWS][KB_COLUMNS]) {
|
||||
if (teensy_update_matrix(matrix))
|
||||
return 1;
|
||||
if (mcp23018_update_matrix(matrix))
|
||||
return 2;
|
||||
|
||||
return 0; // success
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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,27 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : controller : MCP23018 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__MCP23018__FUNCTIONS_h
|
||||
#define KEYBOARD__ERGODOX__CONTROLLER__MCP23018__FUNCTIONS_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] );
|
||||
|
||||
#endif
|
||||
|
|
@ -1,206 +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 <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
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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,59 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#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
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#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))
|
||||
|
||||
#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(); \
|
||||
} while(0)
|
||||
|
||||
#define _kb_led_all_set(n) do { \
|
||||
_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); \
|
||||
} while(0)
|
||||
|
||||
#endif
|
||||
|
|
@ -1,234 +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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// 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
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : layout exports
|
||||
*
|
||||
* Different layouts 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#ifndef KEYBOARD__ERGODOX__LAYOUT_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT_h
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// include the appropriate keyboard layout header
|
||||
#include "../../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./layout/MAKEFILE_KEYBOARD_LAYOUT.h )
|
||||
#include INCLUDE
|
||||
|
||||
#endif
|
||||
|
|
@ -1,383 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : COLEMAK (modified from the Kinesis layout)
|
||||
*
|
||||
* Submitted by Jason Trill [jjt] (https://github.com/jjt)
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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] = {
|
||||
// LAYOUT L0: COLEMAK
|
||||
KB_MATRIX_LAYER( 0,
|
||||
// left hand
|
||||
_equal, _1, _2, _3, _4, _5, 2,
|
||||
_tab, _Q, _W, _F, _P, _G, _esc,
|
||||
_ctrlL, _A, _R, _S, _T, _D,
|
||||
_shiftL, _Z, _X, _C, _V, _B, 2,
|
||||
_guiL, _grave, _backslash, _altL, 1,
|
||||
|
||||
_ctrlL, _altL,
|
||||
0, 0, _home,
|
||||
_space, _enter, _end,
|
||||
|
||||
// right hand
|
||||
3, _6, _7, _8, _9, _0, _dash,
|
||||
_esc, _J, _L, _U, _Y, _semicolon, _backslash,
|
||||
_H, _N, _E, _I, _O, _quote,
|
||||
3, _K, _M, _comma, _period, _slash, _shiftR,
|
||||
1, _arrowL, _arrowD, _arrowU, _arrowR,
|
||||
|
||||
_altR, _ctrlR,
|
||||
_pageU, 0, 0,
|
||||
_pageD, _del, _bs ),
|
||||
|
||||
|
||||
// LAYOUT L1: function and symbol keys
|
||||
KB_MATRIX_LAYER( 0,
|
||||
// left hand
|
||||
0, _F1, _F2, _F3, _F4, _F5, _F11,
|
||||
0, _bracketL, _bracketR, _bracketL, _bracketR, _semicolon, 0,
|
||||
0, _backslash, _slash, _9, _0, _semicolon,
|
||||
0, _1, _2, _3, _4, _5, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
_F12, _F6, _F7, _F8, _F9, _F10, _power,
|
||||
0, 0, _equal, _equal, _dash, _dash, 0,
|
||||
_arrowL, _arrowD, _arrowU, _arrowR, 0, 0,
|
||||
0, _6, _7, _8, _9, _0, _mute,
|
||||
0, 0, 0, 0, 0,
|
||||
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
|
||||
// LAYOUT L2: QWERTY alphanum
|
||||
KB_MATRIX_LAYER( 0,
|
||||
// left hand
|
||||
0, _1, _2, _3, _4, _5, 0,
|
||||
0, _Q, _W, _E, _R, _T, 0,
|
||||
0, _A, _S, _D, _F, _G,
|
||||
0, _Z, _X, _C, _V, _B, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0,
|
||||
// right hand
|
||||
0, _6, _7, _8, _9, _0, 0,
|
||||
0, _Y, _U, _I, _O, _P, 0,
|
||||
_H, _J, _K, _L, _semicolon, 0,
|
||||
0, _N, _M, _comma, _period, _slash, 0,
|
||||
0, 0, 0, 0, 0,
|
||||
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, 0 ),
|
||||
|
||||
|
||||
// LAYOUT L3: numpad
|
||||
KB_MATRIX_LAYER( 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, _period, _enter_kp, 0,
|
||||
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, _0_kp ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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] = {
|
||||
|
||||
// PRESS L0: COLEMAK
|
||||
KB_MATRIX_LAYER( NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, lpush2,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
s2kcap, kprrel, kprrel, kprrel, kprrel, kprrel, lpush2,
|
||||
kprrel, kprrel, kprrel, kprrel, lpush1,
|
||||
|
||||
kprrel, kprrel,
|
||||
NULL, 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,
|
||||
slpunum, kprrel, kprrel, kprrel, kprrel, kprrel, s2kcap,
|
||||
lpush1, kprrel, kprrel, kprrel, kprrel,
|
||||
|
||||
kprrel, kprrel,
|
||||
kprrel, NULL, NULL,
|
||||
kprrel, kprrel, kprrel ),
|
||||
|
||||
|
||||
// PRESS L1: function and symbol keys
|
||||
KB_MATRIX_LAYER( NULL,
|
||||
// left hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, sshprre, sshprre, kprrel, kprrel, sshprre, ktrans,
|
||||
ktrans, kprrel, kprrel, sshprre, sshprre, kprrel,
|
||||
ktrans, sshprre, sshprre, sshprre, sshprre, sshprre, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, kprrel, kprrel, sshprre, kprrel, sshprre, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, sshprre, sshprre, sshprre, sshprre, sshprre, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
// PRESS L2: QWERTY
|
||||
KB_MATRIX_LAYER( NULL,
|
||||
// left hand
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, lpop2,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
// PRESS L3: numpad
|
||||
KB_MATRIX_LAYER( 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, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, kprrel ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const void_funptr_t PROGMEM _kb_layout_release[KB_LAYERS][KB_ROWS][KB_COLUMNS] = {
|
||||
|
||||
// RELEASE L0: COLEMAK
|
||||
KB_MATRIX_LAYER( NULL,
|
||||
// left hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, NULL,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
s2kcap, kprrel, kprrel, kprrel, kprrel, kprrel, lpop2,
|
||||
kprrel, kprrel, kprrel, kprrel, lpop1,
|
||||
|
||||
kprrel, kprrel,
|
||||
NULL, 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,
|
||||
slponum, kprrel, kprrel, kprrel, kprrel, kprrel, s2kcap,
|
||||
lpop1, kprrel, kprrel, kprrel, kprrel,
|
||||
|
||||
kprrel, kprrel,
|
||||
kprrel, NULL, NULL,
|
||||
kprrel, kprrel, kprrel ),
|
||||
|
||||
|
||||
// RELEASE L1: function and symbol keys
|
||||
KB_MATRIX_LAYER( NULL,
|
||||
// left hand
|
||||
NULL, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, sshprre, sshprre, kprrel, kprrel, sshprre, ktrans,
|
||||
ktrans, kprrel, kprrel, sshprre, sshprre, kprrel,
|
||||
ktrans, sshprre, sshprre, sshprre, sshprre, sshprre, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, kprrel, kprrel, sshprre, kprrel, sshprre, kprrel,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, sshprre, sshprre, sshprre, sshprre, sshprre, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
// RELEASE L2: QWERTY
|
||||
KB_MATRIX_LAYER( NULL,
|
||||
// left hand
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, NULL,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
// right hand
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, kprrel, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, ktrans, ktrans, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans ),
|
||||
|
||||
|
||||
// RELEASE L3: numpad
|
||||
KB_MATRIX_LAYER( 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,
|
||||
lpop3, ktrans, kprrel, kprrel, kprrel, kprrel, ktrans,
|
||||
ktrans, ktrans, kprrel, kprrel, ktrans,
|
||||
|
||||
ktrans, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, kprrel ),
|
||||
|
||||
|
||||
// RELEASE L3: nothing (just making sure unused
|
||||
// functions don't get compiled out)
|
||||
KB_MATRIX_LAYER( 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,32 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : layout : COLEMAK : exports
|
||||
*
|
||||
* Submitted by Jason Trill [jjt] (https://github.com/jjt)
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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__COLEMAK_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT__COLEMAK_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,86 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
|
@ -1,370 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : Dvorak (modified from the Kinesis layout)
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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,
|
||||
_ctrlL, _altL,
|
||||
0, 0, _home,
|
||||
_bs, _del, _end,
|
||||
// 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,
|
||||
_altR, _ctrlR,
|
||||
_pageU, 0, 0,
|
||||
_pageD, _enter, _space ),
|
||||
|
||||
|
||||
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, _period, _enter_kp, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, _0_kp ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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, kprrel,
|
||||
NULL, 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,
|
||||
kprrel, kprrel,
|
||||
kprrel, NULL, NULL,
|
||||
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, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, kprrel ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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, kprrel,
|
||||
NULL, 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,
|
||||
kprrel, kprrel,
|
||||
kprrel, NULL, NULL,
|
||||
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, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, kprrel ),
|
||||
|
||||
|
||||
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,30 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : layout : Dvorak : 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__DVORAK_h
|
||||
#define KEYBOARD__ERGODOX__LAYOUT__DVORAK_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,370 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX layout : QWERTY (modified from the Kinesis layout)
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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,
|
||||
_ctrlL, _altL,
|
||||
0, 0, _home,
|
||||
_bs, _del, _end,
|
||||
// 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,
|
||||
_altR, _ctrlR,
|
||||
_pageU, 0, 0,
|
||||
_pageD, _enter, _space ),
|
||||
|
||||
|
||||
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, _period, _enter_kp, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0, _0_kp ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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, kprrel,
|
||||
NULL, 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,
|
||||
kprrel, kprrel,
|
||||
kprrel, NULL, NULL,
|
||||
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, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, kprrel ),
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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, kprrel,
|
||||
NULL, 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,
|
||||
kprrel, kprrel,
|
||||
kprrel, NULL, NULL,
|
||||
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, ktrans,
|
||||
ktrans, ktrans, ktrans,
|
||||
ktrans, ktrans, kprrel ),
|
||||
|
||||
|
||||
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,30 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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,104 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ergoDOX : matrix 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__MATRIX_h
|
||||
#define KEYBOARD__ERGODOX__MATRIX_h
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#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
|
||||
* keys both on the keyboard and in the layout
|
||||
* - matrix position: the coordinate in the matrix to which a key is
|
||||
* scanned by the update functions
|
||||
*
|
||||
* - location numbers are in the format `row##column`, where both 'row'
|
||||
* 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
|
||||
* - 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; used, unused
|
||||
* per hand: 6 x 7 = 42; 40, 2
|
||||
* total: 6 x 14 = 84; 80, 4
|
||||
*
|
||||
* left hand : rows 0..5, cols 0..6
|
||||
* right hand : rows 0..5, cols 7..D
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
#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, \
|
||||
k05,k06, \
|
||||
k15,k16,k04, \
|
||||
k03,k02,k01, \
|
||||
\
|
||||
/* 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, \
|
||||
k07,k08, \
|
||||
k09,k17,k18, \
|
||||
k0C,k0B,k0A ) \
|
||||
\
|
||||
/* 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 KB_MATRIX_LAYER_SET_ALL(na, kxx) \
|
||||
LAYER( \
|
||||
na, \
|
||||
\
|
||||
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,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, \
|
||||
kxx,kxx, \
|
||||
kxx,kxx,kxx, \
|
||||
kxx,kxx,kxx ) \
|
||||
|
||||
#endif
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
|
@ -20,18 +20,16 @@
|
|||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
#pragma once
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#ifndef USB_USAGE_PAGE_KEYBOARD_h
|
||||
#define USB_USAGE_PAGE_KEYBOARD_h
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define KB_ROWS 6 // must match real life
|
||||
#define KB_COLUMNS 14 // must match real life
|
||||
|
||||
// Name ID // PC Mac Unix Boot Keyboard Req.
|
||||
// --------------------------- ---- -- --- ---- ---------------------
|
||||
|
||||
// (Reserved) 0x00 // √ √ √ 84/101/104
|
||||
|
||||
#define KEY_NULL 0x00 // √ √ √ 84/101/104
|
||||
#define KEY_ErrorRollOver 0x01 // √ √ √ 84/101/104
|
||||
#define KEY_POSTFail 0x02 // √ √ √ 84/101/104
|
||||
#define KEY_ErrorUndefined 0x03 // √ √ √ 84/101/104
|
||||
|
@ -268,8 +266,117 @@
|
|||
|
||||
// (Reserved) 0xE8..0xFFFF // - - - -
|
||||
|
||||
// Media key codes are not real scan codes, they must be translated to a 16
|
||||
// bit number by the consumer key key function
|
||||
#define MEDIAKEY_AUDIO_MUTE 0
|
||||
#define MEDIAKEY_AUDIO_VOL_UP 1
|
||||
#define MEDIAKEY_AUDIO_VOL_DOWN 2
|
||||
#define MEDIAKEY_NEXT_TRACK 3
|
||||
#define MEDIAKEY_PREV_TRACK 4
|
||||
#define MEDIAKEY_STOP 5
|
||||
#define MEDIAKEY_PLAY_PAUSE 6
|
||||
#define MEDIAKEY_RECORD 7
|
||||
#define MEDIAKEY_REWIND 8
|
||||
#define MEDIAKEY_EJECT 9
|
||||
#define MEDIAKEY_CC_CONFIG 10
|
||||
#define MEDIAKEY_EMAIL 11
|
||||
#define MEDIAKEY_CALCULATOR 12
|
||||
#define MEDIAKEY_LOCAL_BROWSER 13
|
||||
#define MEDIAKEY_BROWSER_SEARCH 14
|
||||
#define MEDIAKEY_BROWSER_HOME 15
|
||||
#define MEDIAKEY_BROWSER_BACK 16
|
||||
#define MEDIAKEY_BROWSER_FORWARD 17
|
||||
#define MEDIAKEY_BROWSER_STOP 18
|
||||
#define MEDIAKEY_BROWSER_REFRESH 19
|
||||
#define MEDIAKEY_BROWSER_BOOKMARKS 20
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif
|
||||
/* Consumer Page(0x0C)
|
||||
* following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
|
||||
*/
|
||||
#define AUDIO_MUTE 0x00E2
|
||||
#define AUDIO_VOL_UP 0x00E9
|
||||
#define AUDIO_VOL_DOWN 0x00EA
|
||||
#define TRANSPORT_NEXT_TRACK 0x00B5
|
||||
#define TRANSPORT_PREV_TRACK 0x00B6
|
||||
#define TRANSPORT_STOP 0x00B7
|
||||
#define TRANSPORT_PLAY_PAUSE 0x00CD
|
||||
/* application launch */
|
||||
#define AL_CC_CONFIG 0x0183
|
||||
#define AL_EMAIL 0x018A
|
||||
#define AL_CALCULATOR 0x0192
|
||||
#define AL_LOCAL_BROWSER 0x0194
|
||||
/* application control */
|
||||
#define AC_SEARCH 0x0221
|
||||
#define AC_HOME 0x0223
|
||||
#define AC_BACK 0x0224
|
||||
#define AC_FORWARD 0x0225
|
||||
#define AC_STOP 0x0226
|
||||
#define AC_REFRESH 0x0227
|
||||
#define AC_BOOKMARKS 0x022A
|
||||
/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */
|
||||
#define AL_LOCK 0x019E
|
||||
#define TRANSPORT_RECORD 0x00B2
|
||||
#define TRANSPORT_REWIND 0x00B4
|
||||
#define TRANSPORT_EJECT 0x00B8
|
||||
#define AC_MINIMIZE 0x0206
|
||||
|
||||
/* Generic Desktop Page(0x01) - system power control */
|
||||
#define SYSTEM_POWER_DOWN 0x0081
|
||||
#define SYSTEM_SLEEP 0x0082
|
||||
#define SYSTEM_WAKE_UP 0x0083
|
||||
|
||||
/*
|
||||
* MediaCodeLookupTable is used to translate from enumeration in keyboard.h to
|
||||
* consumer key scan code in usb_keyboard.h
|
||||
*/
|
||||
static const uint16_t PROGMEM _media_code_lookup_table[] = {
|
||||
AUDIO_MUTE, // MEDIAKEY_AUDIO_MUTE
|
||||
AUDIO_VOL_UP, // MEDIAKEY_AUDIO_VOL_UP
|
||||
AUDIO_VOL_DOWN, // MEDIAKEY_AUDIO_VOL_DOWN
|
||||
TRANSPORT_NEXT_TRACK, // MEDIAKEY_NEXT_TRACK
|
||||
TRANSPORT_PREV_TRACK, // MEDIAKEY_PREV_TRACK
|
||||
TRANSPORT_STOP, // MEDIAKEY_STOP
|
||||
TRANSPORT_PLAY_PAUSE, // MEDIAKEY_PLAY_PAUSE
|
||||
TRANSPORT_RECORD, // MEDIAKEY_RECORD
|
||||
TRANSPORT_REWIND, // MEDIAKEY_REWIND
|
||||
TRANSPORT_EJECT, // MEDIAKEY_EJECT
|
||||
AL_CC_CONFIG, // MEDIAKEY_CC_CONFIG
|
||||
AL_EMAIL, // MEDIAKEY_EMAIL
|
||||
AL_CALCULATOR, // MEDIAKEY_CALCULATOR
|
||||
AL_LOCAL_BROWSER, // MEDIAKEY_LOCAL_BROWSER
|
||||
AC_SEARCH, // MEDIAKEY_BROWSER_SEARCH
|
||||
AC_HOME, // MEDIAKEY_BROWSER_HOME
|
||||
AC_BACK, // MEDIAKEY_BROWSER_BACK
|
||||
AC_FORWARD, // MEDIAKEY_BROWSER_FORWARD
|
||||
AC_STOP, // MEDIAKEY_BROWSER_STOP
|
||||
AC_REFRESH, // MEDIAKEY_BROWSER_REFRESH
|
||||
AC_BOOKMARKS, // MEDIAKEY_BROWSER_BOOKMARKS
|
||||
};
|
||||
|
||||
uint16_t _media_code_lookup(uint8_t key) {
|
||||
return (uint16_t) pgm_read_word(&_media_code_lookup_table[key]);
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
#define MOD_KEY_LeftControl 0
|
||||
#define MOD_KEY_LeftShift 1
|
||||
#define MOD_KEY_LeftAlt 2
|
||||
#define MOD_KEY_LeftGUI 3
|
||||
#define MOD_KEY_RightControl 4
|
||||
#define MOD_KEY_RightShift 5
|
||||
#define MOD_KEY_RightAlt 6
|
||||
#define MOD_KEY_RightGUI 7
|
||||
|
||||
static const uint8_t PROGMEM _modifier_lookup_table[] = {
|
||||
KEY_LeftControl,
|
||||
KEY_LeftShift,
|
||||
KEY_LeftAlt,
|
||||
KEY_LeftGUI,
|
||||
KEY_RightControl,
|
||||
KEY_RightShift,
|
||||
KEY_RightAlt,
|
||||
KEY_RightGUI,
|
||||
};
|
||||
|
||||
#define MODIFIERS sizeof(_modifier_lookup_table)
|
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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")
|
||||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "../lib/variable-include.h"
|
||||
#define INCLUDE EXP_STR( ./MAKEFILE_KEYBOARD/layout.h )
|
||||
#include INCLUDE
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
SDA +13 16+ RESET
|
||||
NC +14-------15+ ADDR
|
||||
|
||||
### MCP32018 Pin Assignments
|
||||
### MCP23018 Pin Assignments
|
||||
|
||||
power_negative Vss(GND) +01---.---28o NC
|
||||
NC o02 27o GPA7
|
|
@ -1,19 +0,0 @@
|
|||
# src/lib/pjrc
|
||||
|
||||
## links to original files
|
||||
|
||||
* [pjrc] (http://pjrc.com/teensy/)
|
||||
* [usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.zip)
|
||||
<!--
|
||||
* [usb_mouse] (http://pjrc.com/teensy/usb_mouse.zip)
|
||||
* [usb_serial] (http://pjrc.com/teensy/usb_serial.zip)
|
||||
* Directions for host setup [here]
|
||||
(http://pjrc.com/teensy/usb_serial.html)
|
||||
-->
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
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>
|
||||
|
|
@ -1,593 +0,0 @@
|
|||
/* USB Keyboard Example for Teensy USB Development Board
|
||||
* http://www.pjrc.com/teensy/usb_keyboard.html
|
||||
* Copyright (c) 2009 PJRC.COM, LLC
|
||||
*
|
||||
* 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 the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Version 1.0: Initial Release
|
||||
// Version 1.1: Add support for Teensy 2.0
|
||||
|
||||
#define USB_SERIAL_PRIVATE_INCLUDE
|
||||
#include "usb_keyboard.h"
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Configurable Options
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// You can change these to give your code its own name.
|
||||
#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 0x1d50 // Openmoko, Inc.
|
||||
#define PRODUCT_ID 0x6028 // ErgoDox ergonomic keyboard
|
||||
|
||||
|
||||
// USB devices are supposed to implment a halt feature, which is
|
||||
// rarely (if ever) used. If you comment this line out, the halt
|
||||
// code will be removed, saving 102 bytes of space (gcc 4.3.0).
|
||||
// This is not strictly USB compliant, but works with all major
|
||||
// operating systems.
|
||||
#define SUPPORT_ENDPOINT_HALT
|
||||
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Endpoint Buffer Configuration
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#define ENDPOINT0_SIZE 32
|
||||
|
||||
#define KEYBOARD_INTERFACE 0
|
||||
#define KEYBOARD_ENDPOINT 3
|
||||
#define KEYBOARD_SIZE 8
|
||||
#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER
|
||||
|
||||
static const uint8_t PROGMEM endpoint_config_table[] = {
|
||||
0,
|
||||
0,
|
||||
1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Descriptor Data
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// Descriptors are the data that your computer reads when it auto-detects
|
||||
// this USB device (called "enumeration" in USB lingo). The most commonly
|
||||
// changed items are editable at the top of this file. Changing things
|
||||
// in here should only be done by those who've read chapter 9 of the USB
|
||||
// spec and relevant portions of any USB class specifications!
|
||||
|
||||
|
||||
static const uint8_t PROGMEM device_descriptor[] = {
|
||||
18, // bLength
|
||||
1, // bDescriptorType
|
||||
0x00, 0x02, // bcdUSB
|
||||
0, // bDeviceClass
|
||||
0, // bDeviceSubClass
|
||||
0, // bDeviceProtocol
|
||||
ENDPOINT0_SIZE, // bMaxPacketSize0
|
||||
LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor
|
||||
LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct
|
||||
0x00, 0x01, // bcdDevice
|
||||
1, // iManufacturer
|
||||
2, // iProduct
|
||||
0, // iSerialNumber
|
||||
1 // bNumConfigurations
|
||||
};
|
||||
|
||||
// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
|
||||
static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop),
|
||||
0x09, 0x06, // Usage (Keyboard),
|
||||
0xA1, 0x01, // Collection (Application),
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x95, 0x08, // Report Count (8),
|
||||
0x05, 0x07, // Usage Page (Key Codes),
|
||||
0x19, 0xE0, // Usage Minimum (224),
|
||||
0x29, 0xE7, // Usage Maximum (231),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x01, // Logical Maximum (1),
|
||||
0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x81, 0x03, // Input (Constant), ;Reserved byte
|
||||
0x95, 0x05, // Report Count (5),
|
||||
0x75, 0x01, // Report Size (1),
|
||||
0x05, 0x08, // Usage Page (LEDs),
|
||||
0x19, 0x01, // Usage Minimum (1),
|
||||
0x29, 0x05, // Usage Maximum (5),
|
||||
0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
|
||||
0x95, 0x01, // Report Count (1),
|
||||
0x75, 0x03, // Report Size (3),
|
||||
0x91, 0x03, // Output (Constant), ;LED report padding
|
||||
0x95, 0x06, // Report Count (6),
|
||||
0x75, 0x08, // Report Size (8),
|
||||
0x15, 0x00, // Logical Minimum (0),
|
||||
0x25, 0x68, // Logical Maximum(104),
|
||||
0x05, 0x07, // Usage Page (Key Codes),
|
||||
0x19, 0x00, // Usage Minimum (0),
|
||||
0x29, 0x68, // Usage Maximum (104),
|
||||
0x81, 0x00, // Input (Data, Array),
|
||||
0xc0 // End Collection
|
||||
};
|
||||
|
||||
#define CONFIG1_DESC_SIZE (9+9+9+7)
|
||||
#define KEYBOARD_HID_DESC_OFFSET (9+9)
|
||||
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;
|
||||
LSB(CONFIG1_DESC_SIZE), // wTotalLength
|
||||
MSB(CONFIG1_DESC_SIZE),
|
||||
1, // bNumInterfaces
|
||||
1, // bConfigurationValue
|
||||
0, // iConfiguration
|
||||
0xC0, // bmAttributes
|
||||
50, // bMaxPower
|
||||
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
|
||||
9, // bLength
|
||||
4, // bDescriptorType
|
||||
KEYBOARD_INTERFACE, // bInterfaceNumber
|
||||
0, // bAlternateSetting
|
||||
1, // bNumEndpoints
|
||||
0x03, // bInterfaceClass (0x03 = HID)
|
||||
0x01, // bInterfaceSubClass (0x01 = Boot)
|
||||
0x01, // bInterfaceProtocol (0x01 = Keyboard)
|
||||
0, // iInterface
|
||||
// HID interface descriptor, HID 1.11 spec, section 6.2.1
|
||||
9, // bLength
|
||||
0x21, // bDescriptorType
|
||||
0x11, 0x01, // bcdHID
|
||||
0, // bCountryCode
|
||||
1, // bNumDescriptors
|
||||
0x22, // bDescriptorType
|
||||
sizeof(keyboard_hid_report_desc), // wDescriptorLength
|
||||
0,
|
||||
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
|
||||
7, // bLength
|
||||
5, // bDescriptorType
|
||||
KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress
|
||||
0x03, // bmAttributes (0x03=intr)
|
||||
KEYBOARD_SIZE, 0, // wMaxPacketSize
|
||||
1 // bInterval
|
||||
};
|
||||
|
||||
// If you're desperate for a little extra code memory, these strings
|
||||
// can be completely removed if iManufacturer, iProduct, iSerialNumber
|
||||
// in the device desciptor are changed to zeros.
|
||||
struct usb_string_descriptor_struct {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
int16_t wString[];
|
||||
};
|
||||
static const struct usb_string_descriptor_struct PROGMEM string0 = {
|
||||
4,
|
||||
3,
|
||||
{0x0409}
|
||||
};
|
||||
static const struct usb_string_descriptor_struct PROGMEM string1 = {
|
||||
sizeof(STR_MANUFACTURER),
|
||||
3,
|
||||
STR_MANUFACTURER
|
||||
};
|
||||
static const struct usb_string_descriptor_struct PROGMEM string2 = {
|
||||
sizeof(STR_PRODUCT),
|
||||
3,
|
||||
STR_PRODUCT
|
||||
};
|
||||
|
||||
// This table defines which descriptor data is sent for each specific
|
||||
// request from the host (in wValue and wIndex).
|
||||
static struct descriptor_list_struct {
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
const uint8_t *addr;
|
||||
uint8_t length;
|
||||
} 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)},
|
||||
{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
|
||||
{0x0300, 0x0000, (const uint8_t *)&string0, 4},
|
||||
{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
|
||||
{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
|
||||
};
|
||||
#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Variables - these are the only non-stack RAM usage
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
// zero when we are not configured, non-zero when enumerated
|
||||
static volatile uint8_t usb_configuration=0;
|
||||
|
||||
// which modifier keys are currently pressed
|
||||
// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui
|
||||
// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
|
||||
uint8_t keyboard_modifier_keys=0;
|
||||
|
||||
// which keys are currently pressed, up to 6 keys may be down at once
|
||||
uint8_t keyboard_keys[6]={0,0,0,0,0,0};
|
||||
|
||||
// protocol setting from the host. We use exactly the same report
|
||||
// either way, so this variable only stores the setting since we
|
||||
// are required to be able to report which setting is in use.
|
||||
static uint8_t keyboard_protocol=1;
|
||||
|
||||
// the idle configuration, how often we send the report to the
|
||||
// host (ms * 4) even when it hasn't changed
|
||||
static uint8_t keyboard_idle_config=125;
|
||||
|
||||
// count until idle timeout
|
||||
static uint8_t keyboard_idle_count=0;
|
||||
|
||||
// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
|
||||
volatile uint8_t keyboard_leds=0;
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Public Functions - these are the API intended for the user
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
// initialize USB
|
||||
void usb_init(void)
|
||||
{
|
||||
HW_CONFIG();
|
||||
USB_FREEZE(); // enable USB
|
||||
PLL_CONFIG(); // config PLL
|
||||
while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock
|
||||
USB_CONFIG(); // start USB clock
|
||||
UDCON = 0; // enable attach resistor
|
||||
usb_configuration = 0;
|
||||
UDIEN = (1<<EORSTE)|(1<<SOFE);
|
||||
sei();
|
||||
}
|
||||
|
||||
// return 0 if the USB is not configured, or the configuration
|
||||
// number selected by the HOST
|
||||
uint8_t usb_configured(void)
|
||||
{
|
||||
return usb_configuration;
|
||||
}
|
||||
|
||||
|
||||
// perform a single keystroke
|
||||
int8_t usb_keyboard_press(uint8_t key, uint8_t modifier)
|
||||
{
|
||||
int8_t r;
|
||||
|
||||
keyboard_modifier_keys = modifier;
|
||||
keyboard_keys[0] = key;
|
||||
r = usb_keyboard_send();
|
||||
if (r) return r;
|
||||
keyboard_modifier_keys = 0;
|
||||
keyboard_keys[0] = 0;
|
||||
return usb_keyboard_send();
|
||||
}
|
||||
|
||||
// send the contents of keyboard_keys and keyboard_modifier_keys
|
||||
int8_t usb_keyboard_send(void)
|
||||
{
|
||||
uint8_t i, intr_state, timeout;
|
||||
|
||||
if (!usb_configuration) return -1;
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
UENUM = KEYBOARD_ENDPOINT;
|
||||
timeout = UDFNUML + 50;
|
||||
while (1) {
|
||||
// are we ready to transmit?
|
||||
if (UEINTX & (1<<RWAL)) break;
|
||||
SREG = intr_state;
|
||||
// has the USB gone offline?
|
||||
if (!usb_configuration) return -1;
|
||||
// have we waited too long?
|
||||
if (UDFNUML == timeout) return -1;
|
||||
// get ready to try checking again
|
||||
intr_state = SREG;
|
||||
cli();
|
||||
UENUM = KEYBOARD_ENDPOINT;
|
||||
}
|
||||
UEDATX = keyboard_modifier_keys;
|
||||
UEDATX = 0;
|
||||
for (i=0; i<6; i++) {
|
||||
UEDATX = keyboard_keys[i];
|
||||
}
|
||||
UEINTX = 0x3A;
|
||||
keyboard_idle_count = 0;
|
||||
SREG = intr_state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Private Functions - not intended for general user consumption....
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
|
||||
// USB Device Interrupt - handle all device-level events
|
||||
// the transmit buffer flushing is triggered by the start of frame
|
||||
//
|
||||
ISR(USB_GEN_vect)
|
||||
{
|
||||
uint8_t intbits, i; // used to declare a variable `t` as well, but it
|
||||
// wasn't used ::Ben Blazak, 2012::
|
||||
static uint8_t div4=0;
|
||||
|
||||
intbits = UDINT;
|
||||
UDINT = 0;
|
||||
if (intbits & (1<<EORSTI)) {
|
||||
UENUM = 0;
|
||||
UECONX = 1;
|
||||
UECFG0X = EP_TYPE_CONTROL;
|
||||
UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
|
||||
UEIENX = (1<<RXSTPE);
|
||||
usb_configuration = 0;
|
||||
}
|
||||
if ((intbits & (1<<SOFI)) && usb_configuration) {
|
||||
if (keyboard_idle_config && (++div4 & 3) == 0) {
|
||||
UENUM = KEYBOARD_ENDPOINT;
|
||||
if (UEINTX & (1<<RWAL)) {
|
||||
keyboard_idle_count++;
|
||||
if (keyboard_idle_count == keyboard_idle_config) {
|
||||
keyboard_idle_count = 0;
|
||||
UEDATX = keyboard_modifier_keys;
|
||||
UEDATX = 0;
|
||||
for (i=0; i<6; i++) {
|
||||
UEDATX = keyboard_keys[i];
|
||||
}
|
||||
UEINTX = 0x3A;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Misc functions to wait for ready and send/receive packets
|
||||
static inline void usb_wait_in_ready(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<TXINI))) ;
|
||||
}
|
||||
static inline void usb_send_in(void)
|
||||
{
|
||||
UEINTX = ~(1<<TXINI);
|
||||
}
|
||||
static inline void usb_wait_receive_out(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<RXOUTI))) ;
|
||||
}
|
||||
static inline void usb_ack_out(void)
|
||||
{
|
||||
UEINTX = ~(1<<RXOUTI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// USB Endpoint Interrupt - endpoint 0 is handled here. The
|
||||
// other endpoints are manipulated by the user-callable
|
||||
// functions, and the start-of-frame interrupt.
|
||||
//
|
||||
ISR(USB_COM_vect)
|
||||
{
|
||||
uint8_t intbits;
|
||||
const uint8_t *list;
|
||||
const uint8_t *cfg;
|
||||
uint8_t i, n, len, en;
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
uint16_t wValue;
|
||||
uint16_t wIndex;
|
||||
uint16_t wLength;
|
||||
uint16_t desc_val;
|
||||
const uint8_t *desc_addr;
|
||||
uint8_t desc_length;
|
||||
|
||||
UENUM = 0;
|
||||
intbits = UEINTX;
|
||||
if (intbits & (1<<RXSTPI)) {
|
||||
bmRequestType = UEDATX;
|
||||
bRequest = UEDATX;
|
||||
wValue = UEDATX;
|
||||
wValue |= (UEDATX << 8);
|
||||
wIndex = UEDATX;
|
||||
wIndex |= (UEDATX << 8);
|
||||
wLength = UEDATX;
|
||||
wLength |= (UEDATX << 8);
|
||||
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
|
||||
if (bRequest == GET_DESCRIPTOR) {
|
||||
list = (const uint8_t *)descriptor_list;
|
||||
for (i=0; ; i++) {
|
||||
if (i >= NUM_DESC_LIST) {
|
||||
UECONX = (1<<STALLRQ)|(1<<EPEN); //stall
|
||||
return;
|
||||
}
|
||||
desc_val = pgm_read_word(list);
|
||||
if (desc_val != wValue) {
|
||||
list += sizeof(struct descriptor_list_struct);
|
||||
continue;
|
||||
}
|
||||
list += 2;
|
||||
desc_val = pgm_read_word(list);
|
||||
if (desc_val != wIndex) {
|
||||
list += sizeof(struct descriptor_list_struct)-2;
|
||||
continue;
|
||||
}
|
||||
list += 2;
|
||||
desc_addr = (const uint8_t *)pgm_read_word(list);
|
||||
list += 2;
|
||||
desc_length = pgm_read_byte(list);
|
||||
break;
|
||||
}
|
||||
len = (wLength < 256) ? wLength : 255;
|
||||
if (len > desc_length) len = desc_length;
|
||||
do {
|
||||
// wait for host ready for IN packet
|
||||
do {
|
||||
i = UEINTX;
|
||||
} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
|
||||
if (i & (1<<RXOUTI)) return; // abort
|
||||
// send IN packet
|
||||
n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
|
||||
for (i = n; i; i--) {
|
||||
UEDATX = pgm_read_byte(desc_addr++);
|
||||
}
|
||||
len -= n;
|
||||
usb_send_in();
|
||||
} while (len || n == ENDPOINT0_SIZE);
|
||||
return;
|
||||
}
|
||||
if (bRequest == SET_ADDRESS) {
|
||||
usb_send_in();
|
||||
usb_wait_in_ready();
|
||||
UDADDR = wValue | (1<<ADDEN);
|
||||
return;
|
||||
}
|
||||
if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
|
||||
usb_configuration = wValue;
|
||||
usb_send_in();
|
||||
cfg = endpoint_config_table;
|
||||
for (i=1; i<5; i++) {
|
||||
UENUM = i;
|
||||
en = pgm_read_byte(cfg++);
|
||||
UECONX = en;
|
||||
if (en) {
|
||||
UECFG0X = pgm_read_byte(cfg++);
|
||||
UECFG1X = pgm_read_byte(cfg++);
|
||||
}
|
||||
}
|
||||
UERST = 0x1E;
|
||||
UERST = 0;
|
||||
return;
|
||||
}
|
||||
if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = usb_configuration;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
|
||||
if (bRequest == GET_STATUS) {
|
||||
usb_wait_in_ready();
|
||||
i = 0;
|
||||
#ifdef SUPPORT_ENDPOINT_HALT
|
||||
if (bmRequestType == 0x82) {
|
||||
UENUM = wIndex;
|
||||
if (UECONX & (1<<STALLRQ)) i = 1;
|
||||
UENUM = 0;
|
||||
}
|
||||
#endif
|
||||
UEDATX = i;
|
||||
UEDATX = 0;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
#ifdef SUPPORT_ENDPOINT_HALT
|
||||
if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
|
||||
&& bmRequestType == 0x02 && wValue == 0) {
|
||||
i = wIndex & 0x7F;
|
||||
if (i >= 1 && i <= MAX_ENDPOINT) {
|
||||
usb_send_in();
|
||||
UENUM = i;
|
||||
if (bRequest == SET_FEATURE) {
|
||||
UECONX = (1<<STALLRQ)|(1<<EPEN);
|
||||
} else {
|
||||
UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
|
||||
UERST = (1 << i);
|
||||
UERST = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (wIndex == KEYBOARD_INTERFACE) {
|
||||
if (bmRequestType == 0xA1) {
|
||||
if (bRequest == HID_GET_REPORT) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = keyboard_modifier_keys;
|
||||
UEDATX = 0;
|
||||
for (i=0; i<6; i++) {
|
||||
UEDATX = keyboard_keys[i];
|
||||
}
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_GET_IDLE) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = keyboard_idle_config;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_GET_PROTOCOL) {
|
||||
usb_wait_in_ready();
|
||||
UEDATX = keyboard_protocol;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (bmRequestType == 0x21) {
|
||||
if (bRequest == HID_SET_REPORT) {
|
||||
usb_wait_receive_out();
|
||||
keyboard_leds = UEDATX;
|
||||
usb_ack_out();
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_SET_IDLE) {
|
||||
keyboard_idle_config = (wValue >> 8);
|
||||
keyboard_idle_count = 0;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
if (bRequest == HID_SET_PROTOCOL) {
|
||||
keyboard_protocol = wValue;
|
||||
usb_send_in();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
UECONX = (1<<STALLRQ) | (1<<EPEN); // stall
|
||||
}
|
||||
|
||||
|
|
@ -1,210 +0,0 @@
|
|||
#ifndef usb_serial_h__
|
||||
#define usb_serial_h__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void usb_init(void); // initialize everything
|
||||
uint8_t usb_configured(void); // is the USB port configured
|
||||
|
||||
int8_t usb_keyboard_press(uint8_t key, uint8_t modifier);
|
||||
int8_t usb_keyboard_send(void);
|
||||
extern uint8_t keyboard_modifier_keys;
|
||||
extern uint8_t keyboard_keys[6];
|
||||
extern volatile uint8_t keyboard_leds;
|
||||
|
||||
// This file does not include the HID debug functions, so these empty
|
||||
// macros replace them with nothing, so users can compile code that
|
||||
// has calls to these functions.
|
||||
#define usb_debug_putchar(c)
|
||||
#define usb_debug_flush_output()
|
||||
|
||||
|
||||
#if 0 // removed in favor of equivalent code elsewhere ::Ben Blazak, 2012::
|
||||
|
||||
#define KEY_CTRL 0x01
|
||||
#define KEY_SHIFT 0x02
|
||||
#define KEY_ALT 0x04
|
||||
#define KEY_GUI 0x08
|
||||
#define KEY_LEFT_CTRL 0x01
|
||||
#define KEY_LEFT_SHIFT 0x02
|
||||
#define KEY_LEFT_ALT 0x04
|
||||
#define KEY_LEFT_GUI 0x08
|
||||
#define KEY_RIGHT_CTRL 0x10
|
||||
#define KEY_RIGHT_SHIFT 0x20
|
||||
#define KEY_RIGHT_ALT 0x40
|
||||
#define KEY_RIGHT_GUI 0x80
|
||||
|
||||
#define KEY_A 4
|
||||
#define KEY_B 5
|
||||
#define KEY_C 6
|
||||
#define KEY_D 7
|
||||
#define KEY_E 8
|
||||
#define KEY_F 9
|
||||
#define KEY_G 10
|
||||
#define KEY_H 11
|
||||
#define KEY_I 12
|
||||
#define KEY_J 13
|
||||
#define KEY_K 14
|
||||
#define KEY_L 15
|
||||
#define KEY_M 16
|
||||
#define KEY_N 17
|
||||
#define KEY_O 18
|
||||
#define KEY_P 19
|
||||
#define KEY_Q 20
|
||||
#define KEY_R 21
|
||||
#define KEY_S 22
|
||||
#define KEY_T 23
|
||||
#define KEY_U 24
|
||||
#define KEY_V 25
|
||||
#define KEY_W 26
|
||||
#define KEY_X 27
|
||||
#define KEY_Y 28
|
||||
#define KEY_Z 29
|
||||
#define KEY_1 30
|
||||
#define KEY_2 31
|
||||
#define KEY_3 32
|
||||
#define KEY_4 33
|
||||
#define KEY_5 34
|
||||
#define KEY_6 35
|
||||
#define KEY_7 36
|
||||
#define KEY_8 37
|
||||
#define KEY_9 38
|
||||
#define KEY_0 39
|
||||
#define KEY_ENTER 40
|
||||
#define KEY_ESC 41
|
||||
#define KEY_BACKSPACE 42
|
||||
#define KEY_TAB 43
|
||||
#define KEY_SPACE 44
|
||||
#define KEY_MINUS 45
|
||||
#define KEY_EQUAL 46
|
||||
#define KEY_LEFT_BRACE 47
|
||||
#define KEY_RIGHT_BRACE 48
|
||||
#define KEY_BACKSLASH 49
|
||||
#define KEY_NUMBER 50
|
||||
#define KEY_SEMICOLON 51
|
||||
#define KEY_QUOTE 52
|
||||
#define KEY_TILDE 53
|
||||
#define KEY_COMMA 54
|
||||
#define KEY_PERIOD 55
|
||||
#define KEY_SLASH 56
|
||||
#define KEY_CAPS_LOCK 57
|
||||
#define KEY_F1 58
|
||||
#define KEY_F2 59
|
||||
#define KEY_F3 60
|
||||
#define KEY_F4 61
|
||||
#define KEY_F5 62
|
||||
#define KEY_F6 63
|
||||
#define KEY_F7 64
|
||||
#define KEY_F8 65
|
||||
#define KEY_F9 66
|
||||
#define KEY_F10 67
|
||||
#define KEY_F11 68
|
||||
#define KEY_F12 69
|
||||
#define KEY_PRINTSCREEN 70
|
||||
#define KEY_SCROLL_LOCK 71
|
||||
#define KEY_PAUSE 72
|
||||
#define KEY_INSERT 73
|
||||
#define KEY_HOME 74
|
||||
#define KEY_PAGE_UP 75
|
||||
#define KEY_DELETE 76
|
||||
#define KEY_END 77
|
||||
#define KEY_PAGE_DOWN 78
|
||||
#define KEY_RIGHT 79
|
||||
#define KEY_LEFT 80
|
||||
#define KEY_DOWN 81
|
||||
#define KEY_UP 82
|
||||
#define KEY_NUM_LOCK 83
|
||||
#define KEYPAD_SLASH 84
|
||||
#define KEYPAD_ASTERIX 85
|
||||
#define KEYPAD_MINUS 86
|
||||
#define KEYPAD_PLUS 87
|
||||
#define KEYPAD_ENTER 88
|
||||
#define KEYPAD_1 89
|
||||
#define KEYPAD_2 90
|
||||
#define KEYPAD_3 91
|
||||
#define KEYPAD_4 92
|
||||
#define KEYPAD_5 93
|
||||
#define KEYPAD_6 94
|
||||
#define KEYPAD_7 95
|
||||
#define KEYPAD_8 96
|
||||
#define KEYPAD_9 97
|
||||
#define KEYPAD_0 98
|
||||
#define KEYPAD_PERIOD 99
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
// Everything below this point is only intended for usb_serial.c
|
||||
#ifdef USB_SERIAL_PRIVATE_INCLUDE
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define EP_TYPE_CONTROL 0x00
|
||||
#define EP_TYPE_BULK_IN 0x81
|
||||
#define EP_TYPE_BULK_OUT 0x80
|
||||
#define EP_TYPE_INTERRUPT_IN 0xC1
|
||||
#define EP_TYPE_INTERRUPT_OUT 0xC0
|
||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41
|
||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
|
||||
|
||||
#define EP_SINGLE_BUFFER 0x02
|
||||
#define EP_DOUBLE_BUFFER 0x06
|
||||
|
||||
#define EP_SIZE(s) ((s) == 64 ? 0x30 : \
|
||||
((s) == 32 ? 0x20 : \
|
||||
((s) == 16 ? 0x10 : \
|
||||
0x00)))
|
||||
|
||||
#define MAX_ENDPOINT 4
|
||||
|
||||
#define LSB(n) (n & 255)
|
||||
#define MSB(n) ((n >> 8) & 255)
|
||||
|
||||
#if defined(__AVR_AT90USB162__)
|
||||
#define HW_CONFIG()
|
||||
#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
|
||||
#define USB_CONFIG() (USBCON = (1<<USBE))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#define HW_CONFIG() (UHWCON = 0x01)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x12)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_AT90USB646__)
|
||||
#define HW_CONFIG() (UHWCON = 0x81)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x1A)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#elif defined(__AVR_AT90USB1286__)
|
||||
#define HW_CONFIG() (UHWCON = 0x81)
|
||||
#define PLL_CONFIG() (PLLCSR = 0x16)
|
||||
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
|
||||
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
|
||||
#endif
|
||||
|
||||
// standard control endpoint request types
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
#define SET_FEATURE 3
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
// HID (human interface device)
|
||||
#define HID_GET_REPORT 1
|
||||
#define HID_GET_IDLE 2
|
||||
#define HID_GET_PROTOCOL 3
|
||||
#define HID_SET_REPORT 9
|
||||
#define HID_SET_IDLE 10
|
||||
#define HID_SET_PROTOCOL 11
|
||||
// CDC (communication class device)
|
||||
#define CDC_SET_LINE_CODING 0x20
|
||||
#define CDC_GET_LINE_CODING 0x21
|
||||
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
#endif
|
||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* miscellaneous data types
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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__DATA_TYPES_h
|
||||
#define LIB__DATA_TYPES_h
|
||||
|
||||
typedef void (*void_funptr_t)(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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;
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
# 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>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* TWI (I2C) : exports
|
||||
*
|
||||
* Code specific to different development boards is 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( ./twi/MAKEFILE_BOARD.h )
|
||||
#include INCLUDE
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Very simple Teensy 2.0 TWI library : code
|
||||
*
|
||||
* - This is mostly straight from the datasheet, section 20.6.6, figure 20-11
|
||||
* (the code example in C), and section 20.8.1, figure 20-12
|
||||
* - Also see the documentation for `<util/twi.h>` at
|
||||
* <http://www.nongnu.org/avr-libc/user-manual/group__util__twi.html#ga8d3aca0acc182f459a51797321728168>
|
||||
*
|
||||
* Some other (more complete) TWI libraries for the Teensy 2.0 (and other Atmel
|
||||
* processors):
|
||||
* - [i2cmaster] (http://homepage.hispeed.ch/peterfleury/i2cmaster.zip)
|
||||
* - written by [peter-fleury] (http://homepage.hispeed.ch/peterfleury/)
|
||||
* - [the arduino twi library]
|
||||
* (https://github.com/arduino/Arduino/tree/master/libraries/Wire/utility)
|
||||
* - look for an older version if you need one that doesn't depend on all the
|
||||
* other Arduino stuff
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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) );
|
||||
// set the bit rate
|
||||
// - TWBR should be 10 or higher (datasheet section 20.5.2)
|
||||
// - TWI_FREQ should be 400000 (400kHz) max (datasheet section 20.1)
|
||||
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
|
||||
}
|
||||
|
||||
uint8_t twi_start(void) {
|
||||
// send start
|
||||
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
|
||||
// wait for transmission to complete
|
||||
while (!(TWCR & (1<<TWINT)));
|
||||
// if it didn't work, return the status code (else return 0)
|
||||
if ( (TW_STATUS != TW_START) &&
|
||||
(TW_STATUS != TW_REP_START) )
|
||||
return TW_STATUS; // error
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
void twi_stop(void) {
|
||||
// send stop
|
||||
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
|
||||
// wait for transmission to complete
|
||||
while (TWCR & (1<<TWSTO));
|
||||
}
|
||||
|
||||
uint8_t twi_send(uint8_t data) {
|
||||
// load data into the data register
|
||||
TWDR = data;
|
||||
// send data
|
||||
TWCR = (1<<TWINT)|(1<<TWEN);
|
||||
// wait for transmission to complete
|
||||
while (!(TWCR & (1<<TWINT)));
|
||||
// if it didn't work, return the status code (else return 0)
|
||||
if ( (TW_STATUS != TW_MT_SLA_ACK) &&
|
||||
(TW_STATUS != TW_MT_DATA_ACK) &&
|
||||
(TW_STATUS != TW_MR_SLA_ACK) )
|
||||
return TW_STATUS; // error
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
uint8_t twi_read(uint8_t * data) {
|
||||
// read 1 byte to TWDR, send ACK
|
||||
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
|
||||
// wait for transmission to complete
|
||||
while (!(TWCR & (1<<TWINT)));
|
||||
// set data variable
|
||||
*data = TWDR;
|
||||
// if it didn't work, return the status code (else return 0)
|
||||
if (TW_STATUS != TW_MR_DATA_ACK)
|
||||
return TW_STATUS; // error
|
||||
return 0; // success
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Very simple Teensy 2.0 TWI library : 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 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);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* TODO: not sure where this stuff should be yet. a lot of it (depending on
|
||||
* what ends up here) will likely be device and application specific.
|
||||
*
|
||||
* - The following document versions were used, unless otherwise noted:
|
||||
* - USB Specification: revision 2.0
|
||||
* - HID Usage Tables: version 1.12
|
||||
* - Device Class Definition for Human Interface Devices (HID): version 1.11
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
// TODO: does stuff from spec sec 9.4.* belong directly in an interrupt vector?
|
||||
|
||||
// - spec sec 9.4.1 (Standard Device Requests / Clear Feature) (pg 252)
|
||||
|
||||
// - spec sec 9.4.2 (Standard Device Requests / Get Configuration) (pg 253)
|
||||
|
||||
// - spec sec 9.4.3 (Standard Device Requests / Get Descriptor) (pg 253)
|
||||
|
||||
// - spec sec 9.4.4 (Standard Device Requests / Get Interface) (pg 254)
|
||||
|
||||
// - spec sec 9.4.5 (Standard Device Requests / Get Status) (pg 254)
|
||||
|
||||
// - spec sec 9.4.6 (Standard Device Requests / Set Address) (pg 256)
|
||||
|
||||
// - spec sec 9.4.7 (Standard Device Requests / Set Configuration) (pg 257)
|
||||
|
||||
// - spec sec 9.4.8 (Standard Device Requests / Set Descriptor) (pg 257)
|
||||
|
||||
// - spec sec 9.4.9 (Standard Device Requests / Set Feature) (pg 258)
|
||||
|
||||
// - spec sec 9.4.10 (Standard Device Requests / Set Interface) (pg 259)
|
||||
|
||||
// - spec sec 9.4.11 (Standard Device Requests / Synch Frame) (pg 260)
|
||||
|
||||
// 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
|
||||
// - i think this is more for reference and implementation than
|
||||
// understanding. i've copied the relevant (i think) tables ones into
|
||||
// headers. the unicode usage page, i'll have to look into more later: i'm
|
||||
// not sure if it can be used with keyboards. if so though, i'll have to
|
||||
// look on the unicode website, or elsewhere, coz this .pdf doesn't list
|
||||
// anything about them out, it just references the unicode spec.
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* USB 2.0 common macros and definitions
|
||||
*
|
||||
* See "notes from usb 2.0 spec sec 9 (usb device framework).h".
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 USB_COMMON_h
|
||||
#define USB_COMMON_h
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// - spec table 9-4 (Standard Request Codes)
|
||||
#define USB_GET_STATUS 0
|
||||
#define USB_CLEAR_FEATURE 1
|
||||
// (reserved for future use): 2
|
||||
#define USB_SET_FEATURE 3
|
||||
// (reserved for future use): 4
|
||||
#define USB_SET_ADDRESS 5
|
||||
#define USB_GET_DESCRIPTOR 6
|
||||
#define USB_SET_DESCRIPTOR 7
|
||||
#define USB_GET_CONFIGURATION 8
|
||||
#define USB_SET_CONFIGURATION 9
|
||||
#define USB_GET_INTERFACE 10
|
||||
#define USB_SET_INTERFACE 11
|
||||
#define USB_SYNCH_FRAME 12
|
||||
|
||||
// - spec table 9-5 (Descriptor Types)
|
||||
#define USB_DEVICE 1
|
||||
#define USB_CONFIGURATION 2
|
||||
#define USB_STRING 3
|
||||
#define USB_INTERFACE 4
|
||||
#define USB_ENDPOINT 5
|
||||
#define USB_DEVICE_QUALIFIER 6
|
||||
#define USB_OTHER_SPEED_CONFIGURATION 7
|
||||
#define USB_INTERFACE_POWER 8
|
||||
|
||||
// - spec table 9-6 (Standard Feature Selectors)
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 1 // recipient: device
|
||||
#define USB_ENDPOINT_HALT 0 // recipient: endpoint
|
||||
#define USB_TEST_MODE 2 // recipient: device
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
# Notes from the HID Device Class Definition, version 1.11
|
||||
|
||||
|
||||
* sec 4.1 (The HID Class)
|
||||
* The `bInterfaceClass` member of an Interface descriptor is always 3 for
|
||||
HID class devices.
|
||||
|
||||
* sec 4.2 (Subclass)
|
||||
* The `bInterfaceSubClass` member declares whether a device supports a boot interface.
|
||||
* 0 => no subclass
|
||||
* 1 => boot interface subclass
|
||||
* 2..255 => reserved
|
||||
|
||||
* sec 4.3 (Protocols)
|
||||
* The `bInterfaceProtocol` member of an Interface descriptor only has meaning if the `bInterfaceSubClass` member declares that the device supports a boot interface, otherwise it is 0.
|
||||
* 0 => none
|
||||
* 1 => keyboard
|
||||
* 2 => mouse
|
||||
* 3..255 => reserved
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
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>
|
||||
|
|
@ -1,858 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* Notes from the USB 2.0 specification
|
||||
*
|
||||
* Written as a header file because I was going to actually use it. Changed my
|
||||
* mind because it's simpler to use uint8_t arrays for things than to use
|
||||
* structs. it's also easier i think to keep the least and most significant
|
||||
* bits of uint16_t values separate initially instead of separating them later.
|
||||
* Kept it as a header because it looks cleaner this way than i could make it
|
||||
* look as an .md file.
|
||||
*
|
||||
* - conventions from the spec
|
||||
* - variable prefixes
|
||||
* - 'b' : bits or bytes; dependent on context
|
||||
* - 'bcd' : binary-coded decimal
|
||||
* - 'bm' : bitmap
|
||||
* - 'd' : descriptor
|
||||
* - 'i' : index
|
||||
* - 'w' : word
|
||||
*
|
||||
* - conventions used in this file
|
||||
* - everything prefixed with or `USB_` (for non-function-like macros) or
|
||||
* `usb_` (for everything else)
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 USB_DATA_STRUCTURES_h
|
||||
#define USB_DATA_STRUCTURES_h
|
||||
|
||||
#pragma pack(push)
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec sec 9.3 (USB Device Requests)
|
||||
* - table 9-2 (Format of Setup Data)
|
||||
*/
|
||||
struct usb_setup_data {
|
||||
uint8_t bmRequestType;
|
||||
/* value: bitmap
|
||||
* - data transfer direction, type, recipient
|
||||
* (see macros below)
|
||||
*/
|
||||
|
||||
uint8_t bRequest;
|
||||
/* value: value
|
||||
* - type of request (depending on bmRequestType)
|
||||
* (see spec table 9-3 (Standard Device Requests))
|
||||
*/
|
||||
|
||||
uint16_t wValue;
|
||||
/* value: value
|
||||
* - varies according to request; used to pass a request specific
|
||||
* parameter to the device
|
||||
*/
|
||||
|
||||
uint16_t wIndex;
|
||||
/* value: index or offset
|
||||
* - varies according to request; often used to specify an endpoint or
|
||||
* an interface
|
||||
* (see spec figure 9-2 and 9-3, copied below)
|
||||
*/
|
||||
|
||||
uint16_t wLength;
|
||||
/* value: count
|
||||
* - number of bytes to transfer if there is a data stage
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
/* - spec sec 9.3 (USB Device Requests)
|
||||
* - table 9-2 (Format of Setup Data)
|
||||
* - bmRequestType
|
||||
*
|
||||
* .-------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |-------------------------------------------------------|
|
||||
* | direction | type | recipient |
|
||||
* '-------------------------------------------------------'
|
||||
*
|
||||
* - direction: 0 => host to device
|
||||
* 1 => device to host
|
||||
*
|
||||
* - type: 0 => standard
|
||||
* 1 => class
|
||||
* 2 = vendor
|
||||
* 3 = reserved
|
||||
*
|
||||
* - recipient: 0 => device
|
||||
* 1 => interface
|
||||
* 2 => endpoint
|
||||
* 3 => other
|
||||
* 4..31 => reserved
|
||||
*/
|
||||
// --- data transfer direction
|
||||
#define usb_bmRequestType_hostToDevice(val) (((val) & (0b1<<7)) == (0<<7))
|
||||
#define usb_bmRequestType_deviceToHost(val) (((val) & (0b1<<7)) == (1<<7))
|
||||
// --- type
|
||||
#define usb_bmRequestType_standard(val) (((val) & (0b11<<5)) == (0<<5))
|
||||
#define usb_bmRequestType_class(val) (((val) & (0b11<<5)) == (1<<5))
|
||||
#define usb_bmRequestType_vendor(val) (((val) & (0b11<<5)) == (2<<5))
|
||||
#define usb_bmRequestType_reserved(val) (((val) & (0b11<<5)) == (3<<5))
|
||||
// --- recipient
|
||||
#define usb_bmRequestType_device(val) (((val) & (0b11111<<0)) == (0<<0))
|
||||
#define usb_bmRequestType_interface(val) (((val) & (0b11111<<0)) == (1<<0))
|
||||
#define usb_bmRequestType_endpoint(val) (((val) & (0b11111<<0)) == (2<<0))
|
||||
#define usb_bmRequestType_other(val) (((val) & (0b11111<<0)) == (3<<0))
|
||||
#define usb_bmRequestType_reserved(val) (((val) & (0b11100<<0)) != (0<<0))
|
||||
|
||||
|
||||
/* - spec sec 9.3.4 (wIndex)
|
||||
* - figure 9-2 (format when specifying an endpoint)
|
||||
*
|
||||
* .-------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |-------------------------------------------------------|
|
||||
* | direction | reserved (reset to 0) | endpoint number |
|
||||
* >-----------------------------------------------------<
|
||||
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
|
||||
* |-------------------------------------------------------|
|
||||
* | reserved (reset to 0) |
|
||||
* '-------------------------------------------------------'
|
||||
*
|
||||
* - direction: 0 => out (to device), 1 => in (to host)
|
||||
*/
|
||||
#define usb_wIndex_endpoint(direction, endpoint_number) \
|
||||
( (uint16_t) (((direction)<<7) | (endpoint_number)) )
|
||||
|
||||
|
||||
/* - spec sec 9.3.4 (wIndex)
|
||||
* - figure 9-3 (format when specifying an interface)
|
||||
*
|
||||
* .-------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |-------------------------------------------------------|
|
||||
* | interface number |
|
||||
* >-----------------------------------------------------<
|
||||
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
|
||||
* |-------------------------------------------------------|
|
||||
* | reserved (reset to 0) |
|
||||
* '-------------------------------------------------------'
|
||||
*/
|
||||
#define usb_wIndex_interface(interface_number) \
|
||||
( (uint16_t) (interface_number) )
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec table 9-4 (Standard Request Codes)
|
||||
*/
|
||||
#define USB_GET_STATUS 0
|
||||
#define USB_CLEAR_FEATURE 1
|
||||
// (reserved for future use): 2
|
||||
#define USB_SET_FEATURE 3
|
||||
// (reserved for future use): 4
|
||||
#define USB_SET_ADDRESS 5
|
||||
#define USB_GET_DESCRIPTOR 6
|
||||
#define USB_SET_DESCRIPTOR 7
|
||||
#define USB_GET_CONFIGURATION 8
|
||||
#define USB_SET_CONFIGURATION 9
|
||||
#define USB_GET_INTERFACE 10
|
||||
#define USB_SET_INTERFACE 11
|
||||
#define USB_SYNCH_FRAME 12
|
||||
|
||||
/* - spec table 9-5 (Descriptor Types)
|
||||
*/
|
||||
#define USB_DEVICE 1
|
||||
#define USB_CONFIGURATION 2
|
||||
#define USB_STRING 3
|
||||
#define USB_INTERFACE 4
|
||||
#define USB_ENDPOINT 5
|
||||
#define USB_DEVICE_QUALIFIER 6
|
||||
#define USB_OTHER_SPEED_CONFIGURATION 7
|
||||
#define USB_INTERFACE_POWER 8
|
||||
|
||||
/* - spec table 9-6 (Standard Feature Selectors)
|
||||
*/
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 1 // recipient: device
|
||||
#define USB_ENDPOINT_HALT 0 // recipient: endpoint
|
||||
#define USB_TEST_MODE 2 // recipient: device
|
||||
|
||||
|
||||
/* - spec sec 9.4.5 (Standard Device Requests / Get Status)
|
||||
* - figure 9-4 (information returned by a GetStatus() request to a device)
|
||||
*
|
||||
* .------------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |------------------------------------------------------------|
|
||||
* | reserved (reset to 0) | remote wakeup | self powered |
|
||||
* >----------------------------------------------------------<
|
||||
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
|
||||
* |------------------------------------------------------------|
|
||||
* | reserved (reset to 0) |
|
||||
* '------------------------------------------------------------'
|
||||
*
|
||||
* - remote wakeup: 0 => ability of device to signal remote wakeup disabled
|
||||
* (default)
|
||||
* 1 => ability ................................. enabled
|
||||
*
|
||||
* - self powered: 0 => device is bus powered
|
||||
* 1 => device is self powered
|
||||
*/
|
||||
#define usb_getStatus_device(remote_wakeup, self_powered) \
|
||||
( (uint16_t) (((remote_wakeup)<<1) | (self_powered)) )
|
||||
|
||||
|
||||
/* - spec sec 9.4.5 (Standard Device Requests / Get Status)
|
||||
* - figure 9-5 (information returned by a GetStatus() request to an
|
||||
* interface)
|
||||
*
|
||||
* .------------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |------------------------------------------------------------|
|
||||
* | reserved (reset to 0) |
|
||||
* >----------------------------------------------------------<
|
||||
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
|
||||
* |------------------------------------------------------------|
|
||||
* | reserved (reset to 0) |
|
||||
* '------------------------------------------------------------'
|
||||
*/
|
||||
#define usb_getStatus_interface() ( (uint16_t) 0 )
|
||||
|
||||
|
||||
/* - spec sec 9.4.5 (Standard Device Requests / Get Status)
|
||||
* - figure 9-6 (information returned by a GetStatus() request to an
|
||||
* endpoint)
|
||||
*
|
||||
* .------------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |------------------------------------------------------------|
|
||||
* | reserved (reset to 0) | halt |
|
||||
* >----------------------------------------------------------<
|
||||
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
|
||||
* |------------------------------------------------------------|
|
||||
* | reserved (reset to 0) |
|
||||
* '------------------------------------------------------------'
|
||||
*
|
||||
* - halt: 0 => endpoint not currently halted
|
||||
* 1 => endpoint currently halted
|
||||
*/
|
||||
#define usb_getStatus_endpoint(halt) ( (uint16_t) (halt) )
|
||||
|
||||
|
||||
/* - spec sec 9.4.9 (Set Feature)
|
||||
* - table 9-7 (Test Mode Selectors)
|
||||
*
|
||||
* - in the case of a SetFeature(TEST_MODE...):
|
||||
* - the most significant byte of wIndex is used to specify the test mode
|
||||
* - the lower byte of wIndex must be zero, because the recipient must be the
|
||||
* device
|
||||
*/
|
||||
// (reserved): (0x0000)
|
||||
#define USB_TEST_MODE_wIndex_Test_J ( (uint16_t) (0x0100) )
|
||||
#define USB_TEST_MODE_wIndex_Test_K ( (uint16_t) (0x0200) )
|
||||
#define USB_TEST_MODE_wIndex_Test_SE0_NAK ( (uint16_t) (0x0300) )
|
||||
#define USB_TEST_MODE_wIndex_Test_Packet ( (uint16_t) (0x0400) )
|
||||
#define USB_TEST_MODE_wIndex_Test_Force_Enable ( (uint16_t) (0x0500) )
|
||||
// (reserved for standard test selectors): (0x0600)..(0x3F00)
|
||||
// (reserved): (0x3F00)..(0xBF00)
|
||||
// (reserved for vendor-specific test modes): (0xC000)..(0xFF00)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec sec 9.6.1 (Standard USB Descriptor Definitions / Device)
|
||||
* - table 9-8 (Standard Device Descriptor)
|
||||
*/
|
||||
struct usb_device_descriptor {
|
||||
uint8_t bLength;
|
||||
/* value: number
|
||||
* - size of this descriptor in bytes
|
||||
*/
|
||||
|
||||
uint8_t bDescriptorType;
|
||||
/* value: constant
|
||||
* - DEVICE Descriptor Type
|
||||
* - a high speed capable device will set this to 2.0 (0x0200). if the
|
||||
* device is full-speed or low-speed only, this version number only
|
||||
* means that it'll send a request error when asked for the
|
||||
* device_qualifier descriptor
|
||||
*/
|
||||
|
||||
uint16_t bcdUSB;
|
||||
/* value: binary coded decimal
|
||||
* - usb spec release number
|
||||
* - format: 0xJJMN, where JJ = major version, M = minor version,
|
||||
* N = sub-minor version; e.g. version 2.1.3 => 0x0213
|
||||
*/
|
||||
|
||||
uint8_t bDeviceClass;
|
||||
/* value: class
|
||||
* - class code (assigned by the USB-IF)
|
||||
* - 0x00 => each interface within a configuration specifies its own
|
||||
* class information and the various interfaces operate independently
|
||||
* - 0x01..0xFE => the device supports different class specifications
|
||||
* on different interfaces and the interfaces may not operate
|
||||
* independently. this value identifies the class definition used
|
||||
* for the aggregate interfaces
|
||||
* - 0xFF => the device class is vendor-specific
|
||||
*/
|
||||
|
||||
uint8_t bDeviceSubClass;
|
||||
/* value: subclass
|
||||
* - subclass code (assigned by the USB-IF)
|
||||
* - qualified by bDeviceClass
|
||||
* - if bDeviceClass is reset to 0, this field must be also
|
||||
* - if bDeviceClass != 0xFF , all values are reserved for assignment
|
||||
* by the USB-IF
|
||||
*/
|
||||
|
||||
uint8_t bDeviceProtocol;
|
||||
/* value: protocol
|
||||
* - protocol code (assigned by the USB-IF)
|
||||
* - qualified by bDeviceClass and bDeviceSubClass
|
||||
* - if a device supports class-specific protocols on a device basis as
|
||||
* opposed to an interface basis, this code identifies the protocols
|
||||
* that the device uses as defined by the specification of the device
|
||||
* class
|
||||
* - 0x00 => the device does not use class-specific protocols on a
|
||||
* device basis. however, it may use class-specific protocols on an
|
||||
* interface basis
|
||||
* - 0xFF => the device uses a vendor-specific protocol on a device
|
||||
* basis
|
||||
*/
|
||||
|
||||
uint8_t bMaxPacketSize0;
|
||||
/* value: number
|
||||
* - max packet size for endpoint 0
|
||||
* - only 8, 16, 32, or 64 are valid
|
||||
* - if operating at high-speed, the value must be 64
|
||||
*/
|
||||
|
||||
uint16_t idVendor;
|
||||
/* value: id
|
||||
* - vendor ID (assigned by the USB-IF)
|
||||
*/
|
||||
|
||||
uint16_t idProduct;
|
||||
/* value: id
|
||||
* - product ID (assigned by the manufacturer)
|
||||
*/
|
||||
|
||||
uint16_t bcdDevice;
|
||||
/* value: binary coded decimal
|
||||
* - device release number
|
||||
*/
|
||||
|
||||
uint8_t iManufacturer;
|
||||
/* value: index
|
||||
* - index of string descriptor describing manufacturer
|
||||
*/
|
||||
|
||||
uint8_t iProduct;
|
||||
/* value: index
|
||||
* - index of string descriptor describing product
|
||||
*/
|
||||
|
||||
uint8_t iSerialNumber;
|
||||
/* value: index
|
||||
* - index of string descriptor describing the device's serial number
|
||||
*/
|
||||
|
||||
uint8_t bNumConfigurations;
|
||||
/* value: number
|
||||
* - number of possible configurations (at the current operating speed)
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec sec 9.6.2 (Standard USB Descriptor Definitions / Device_Qualifier)
|
||||
* - table 9-9 (Device_Qualifier Descriptor)
|
||||
*
|
||||
* - required if the device has different device information for full-speed and
|
||||
* high-speed
|
||||
*
|
||||
* - not valid for a full-speed only device (with a device descriptor version
|
||||
* number equal to 0x0200); if requested, the device must respond with a
|
||||
* request error
|
||||
*/
|
||||
struct usb_device_qualifier_descriptor {
|
||||
uint8_t bLength;
|
||||
/* value: number
|
||||
* - size of descriptor
|
||||
*/
|
||||
|
||||
uint8_t bDescriptorType;
|
||||
/* value: constant
|
||||
* - device qualifier type
|
||||
*/
|
||||
|
||||
uint16_t bcdUSB;
|
||||
/* value: binary coded decimal
|
||||
* - usb spec release number
|
||||
* - format: (see note for usb_device_descriptor.bcdUSB)
|
||||
* - must be at least 2.0 (0x0200) for this descriptor
|
||||
*/
|
||||
|
||||
uint8_t bDeviceClass;
|
||||
/* value: class
|
||||
*/
|
||||
|
||||
uint8_t bDeviceSubClass;
|
||||
/* value: subclass
|
||||
*/
|
||||
|
||||
uint8_t bDeviceProtocol;
|
||||
/* value: protocol
|
||||
*/
|
||||
|
||||
uint8_t bMaxPacketSize0;
|
||||
/* value: number
|
||||
* - max packet size for other speed
|
||||
*/
|
||||
|
||||
uint8_t bNumConfigurations;
|
||||
/* value: number
|
||||
* - number of other-speed configurations
|
||||
*/
|
||||
|
||||
uint8_t bReserved;
|
||||
/* value: 0
|
||||
* - reserved for future use
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec sec 9.6.3 (Standard USB Descriptor Definitions / Configuration)
|
||||
* - table 9-10 (Standard Configuration Descriptor)
|
||||
*
|
||||
* - spec sec 9.6.4 (Standard USB Descriptor Definitions /
|
||||
* Other_Speed_Configuration)
|
||||
* - table 9-11 (Other_Speed_Configuration Descriptor)
|
||||
*
|
||||
* - both descriptors have the same structure. the only specified difference
|
||||
* is the value of the bDescriptorType constant.
|
||||
*/
|
||||
struct usb_configuration_descriptor {
|
||||
uint8_t bLength;
|
||||
/* value: number
|
||||
* - size of this descriptor in bytes
|
||||
|
||||
uint8_t bDescriptorType;
|
||||
* value: constant
|
||||
* - CONFIGURATION Descriptor Type
|
||||
* (for Standard Configuration Descriptor)
|
||||
* - OTHER_SPEED_CONFIGURATION Type
|
||||
* (for Other Speed Configuration Descriptor)
|
||||
*/
|
||||
|
||||
uint16_t wTotalLength;
|
||||
/* value: number
|
||||
* - total length of data returned for this configuration. includes
|
||||
* the combined length of all descriptors (configuration, interface,
|
||||
* endpoint, and class- or vendor-specific) returned for this
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
uint8_t bNumInterfaces;
|
||||
/* value: number
|
||||
* - number of interfaces supported by this configuration
|
||||
*/
|
||||
|
||||
uint8_t bConfigurationValue;
|
||||
/* value: number
|
||||
* - value to use as an argument to the SetConfiguration() request to
|
||||
* select this configuration
|
||||
*/
|
||||
|
||||
uint8_t iConfiguration;
|
||||
/* value: index
|
||||
* - index of string descriptor describing this configuration
|
||||
*/
|
||||
|
||||
uint8_t bmAttributes;
|
||||
/* value: bitmap
|
||||
* - self-powered, remote wakeup
|
||||
* (see macro below)
|
||||
*/
|
||||
|
||||
uint8_t bMaxPower;
|
||||
/* value: mA
|
||||
* - max power consumption of the USB device from the bus
|
||||
* (configuration specific) (when device is fully operational)
|
||||
* - format: expressed in 2 mA units (i.e. value=50 => 100mA)
|
||||
* - note: a device configuration reports whether the configuration is
|
||||
* bus-powered or self-powered. device status reports whether the
|
||||
* device is currently self-powered. if a device is disconnected
|
||||
* from its external power source, it updates device status to
|
||||
* indicate that. it may not increase its power draw from the bus
|
||||
* beyond the amount reported by its configuration. if it can
|
||||
* continue to operate, it does so. if not, it fails operations it
|
||||
* can no longer support, and the host software can determine the
|
||||
* cause of failure by checking the status and noting the loss of the
|
||||
* device's external power.
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
/* - spec sec 9.6.3 (Standard USB Descriptor Definitions / Configuration)
|
||||
* - table 9-10 (Standard Configuration Descriptor)
|
||||
* - bmAttributes
|
||||
*
|
||||
* .--------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |--------------------------------------------------------|
|
||||
* | reserved | self | remote | reserved |
|
||||
* | (set to 1) | powered | wakeup | (reset to 0) |
|
||||
* '--------------------------------------------------------'
|
||||
*
|
||||
* - D7: must be set to 1 for historical reasons
|
||||
*
|
||||
* - self powered: 0 => false
|
||||
* 1 => true
|
||||
* - a device configuration that uses both bus and local power must report a
|
||||
* non-zero value in bMaxPower (to indicate the amount of bus power
|
||||
* required) and set D6 = 1
|
||||
*
|
||||
* - remote wakeup: 0 => not supported by configuration
|
||||
* 1 => supported by configuration
|
||||
*/
|
||||
#define usb_configuration_bmAttributes(self_powered, remote_wakeup) \
|
||||
( (uint8_t) ((1<<7) | ((self_powered)<<6) | ((remote_wakeup)<<5)) )
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec sec 9.6.5 (Standard USB Descriptor Definitions / Interface)
|
||||
* - table 9-12 (Standard Interface Descriptor)
|
||||
*/
|
||||
struct usb_interface_descriptor {
|
||||
uint8_t bLength;
|
||||
/* value: number
|
||||
* - size of this descriptor in bytes
|
||||
*/
|
||||
|
||||
uint8_t bDescriptorType;
|
||||
/* value: constant
|
||||
* - INTERFACE Descriptor Type
|
||||
*/
|
||||
|
||||
uint8_t bInterfaceNumber;
|
||||
/* value: number
|
||||
* - number of this interface
|
||||
* - zero-based value identifying the index in the array of concurrent
|
||||
* interfaces supported by this configuration
|
||||
*/
|
||||
|
||||
uint8_t bAlternateSetting;
|
||||
/* value: number
|
||||
* - value used to select this alternate setting for the interface
|
||||
* identified in the prior field
|
||||
*/
|
||||
|
||||
uint8_t bNumEndpoints;
|
||||
/* value: number
|
||||
* - number of endpoints used by this interface (excluding endpoint
|
||||
* zero)
|
||||
* - if this value is zero, this interface only uses the Default
|
||||
* Control Pipe
|
||||
*/
|
||||
|
||||
uint8_t bInterfaceClass;
|
||||
/* value: class
|
||||
* - class code (assigned by the USB-IF)
|
||||
* - 0x00 => reserved for future standardization
|
||||
* - 0xFF => interface class is vendor specific
|
||||
* - [others] => reserved for assignment by the USB-IF
|
||||
*/
|
||||
|
||||
uint8_t bInterfaceSubClass;
|
||||
/* value: subclass
|
||||
* - subclass code (assigned by the USB-IF)
|
||||
* - qualified by the value of the bInterfaceClass field
|
||||
* - if the bInterfaceClass field is reset to zero, this field must be
|
||||
* also
|
||||
* - if the bInterfaceClass field is not set to 0xFF, all values are
|
||||
* reserved for assignment by the USB-IF
|
||||
*/
|
||||
|
||||
uint8_t bInterfaceProtocol;
|
||||
/* value: protocol
|
||||
* - protocol code (assigned by the USB)
|
||||
* - qualified by the values of the bInterfaceClass and
|
||||
* bInterfaceSubClass fields
|
||||
* - if an interface supports class-specific requests, this code
|
||||
* identifies the protocols that the device uses as defined by the
|
||||
* specification of the device class.
|
||||
* - 0x00 => the device does not use a class-specific protocol on this
|
||||
* interface
|
||||
* - 0xFF => the device uses a vendor-specific protocol for this
|
||||
* interface
|
||||
*/
|
||||
|
||||
uint8_t iInterface;
|
||||
/* value: index
|
||||
* - index of string descriptor describing this interface
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
|
||||
* - table 9-13 (Standard Endpoint Descriptor)
|
||||
*
|
||||
* - a feedback endpoint (explicit or implicit) needs to be associated with one
|
||||
* (or more) isochronous data endpoints to which it provides feedback
|
||||
* service. the association is based on endpoint number matching. a
|
||||
* feedback endpoint always has the opposite direction from the data
|
||||
* endpoint(s) it services. if multiple data endpoints are to be serviced by
|
||||
* the same feedback endpoint, the data endpoints must have ascending ordered
|
||||
* (but not necessarily consecutive) endpoint numbers. the first data
|
||||
* endpoint and the feedback endpoint must have the same endpoint number (and
|
||||
* opposite direction). this ensures that a data endpoint can uniquely
|
||||
* identify its feedback endpoint by searching for the first feedback
|
||||
* endpoint that has an endpoint number equal or less than its own endpoint
|
||||
* number.
|
||||
* - see spec figures 9-7 and 9-8
|
||||
*/
|
||||
struct usb_endpoint_descriptor {
|
||||
uint8_t bLength;
|
||||
/* value: number
|
||||
* - size of this descriptor in bytes
|
||||
*/
|
||||
|
||||
uint8_t bDescriptorType;
|
||||
/* value: constant
|
||||
* - ENDPOINT Descriptor Type
|
||||
*/
|
||||
|
||||
uint8_t bEndpointAddress;
|
||||
/* value: endpoint
|
||||
* - the address and direction of the endpoint described
|
||||
* (see macro below)
|
||||
*/
|
||||
|
||||
uint8_t bmAttributes;
|
||||
/* value: bitmap
|
||||
* - endpoint's attributes when it is configured using the
|
||||
* bConfigurationValue
|
||||
* - includes: transfer type
|
||||
* - if transfer type == isochronous, also includes:
|
||||
* synchronization type, usage type
|
||||
* - (see spec chapter 5 for more information)
|
||||
* - (see macros below)
|
||||
*/
|
||||
|
||||
uint16_t wMaxPacketSize;
|
||||
/* value: number
|
||||
* - max packet size this endpoint is capable of sending or receiving
|
||||
* when this configuration is selected
|
||||
* - for isochronous endpoints, this value is used to reserve the bus
|
||||
* time in the schedule, required for the per-(micro)frame data
|
||||
* payloads. the pipe may, on an ongoing basis, actually use less
|
||||
* bandwidth than reserved. the device reports, if necessary, the
|
||||
* actual bandwidth used via its normal, non-USB defined mechanisms
|
||||
* - (see spec chapter 5 for more information)
|
||||
* - (see macro below)
|
||||
*/
|
||||
|
||||
uint8_t bInterval;
|
||||
/* value: number
|
||||
* - interval for polling endpoint for data transfers
|
||||
* - expressed in frames or microframes, depending on the device
|
||||
* operating speed (i.e. either 1 ms or 125 μs units)
|
||||
* - for (full|high)-speed isochronous endpoints and high-speed
|
||||
* interrupt endpoints, this value must be between 1..16 . this
|
||||
* value is used as the exponent for a 2^(bInterval-1) value (e.g. a
|
||||
* bInterval of 4 => a period of 8 == 2^(4-1))
|
||||
* - for (full|low)-speed interrupt endpoints, this value may be
|
||||
* between 1..255
|
||||
* - for high-speed bulk/control OUT endpoints, this value must specify
|
||||
* the max NAK rate of the endpoint. a value of 0 => the endpoint
|
||||
* never NAKs. other values indicate at most 1 NAK each bInterval
|
||||
* number of microframes. this value must be between 0..255
|
||||
* - for high-speed bulk and control OUT endpoints, this field is only
|
||||
* used for compliance purposes (the host controller is not required
|
||||
* to change its behavior based on the value in this field)
|
||||
* - (see spec chapter 5 description of periods for more detail)
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
|
||||
* - table 9-13 (Standard Endpoint Descriptor)
|
||||
* - bEndpointAddress
|
||||
*
|
||||
* .-------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |-------------------------------------------------------|
|
||||
* | direction | reserved (reset to 0) | endpoint number |
|
||||
* '-------------------------------------------------------'
|
||||
*
|
||||
* - D7: 0 => OUT endpoint
|
||||
* 1 => IN endpoint
|
||||
* - ignored for control endpoints
|
||||
*/
|
||||
#define usb_endpoint_bEndpointAddress(direction, endpoint_number) \
|
||||
( (uint8_t) ((direction)<<7) | (endpoint_number) )
|
||||
|
||||
|
||||
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
|
||||
* - table 9-13 (Standard Endpoint Descriptor)
|
||||
* - bmAttributes
|
||||
*
|
||||
* .------------------------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |------------------------------------------------------------------------|
|
||||
* | reserved | usage type | synchronization type | transfer type |
|
||||
* | (reset to 0) | (if isochronous) | (if isochronous) | |
|
||||
* | |(else reset to 0) | (else reset to 0) | |
|
||||
* '------------------------------------------------------------------------'
|
||||
*
|
||||
* - transfer type: 0b00 => control
|
||||
* 0b01 => isochronous
|
||||
* 0b10 => bulk
|
||||
* 0b11 => interrupt
|
||||
*
|
||||
* - synchronization type: 0b00 => no synchronization
|
||||
* 0b01 => asynchronous
|
||||
* 0b10 => adaptive
|
||||
* 0b11 => synchronous
|
||||
* - if transfer type != isochronous, field is reset to 0
|
||||
*
|
||||
* - usage type: 0b00 => data endpoint
|
||||
* 0b01 => feedback endpoint
|
||||
* 0b10 => implicit feedback data endpoint
|
||||
* 0b11 => reserved
|
||||
* - if transfer type != isochronous, field is reset to 0
|
||||
*
|
||||
* - if usage type == feedback endpoint, then transfer type must be isochronous
|
||||
* and synchronization type must be no synchronization
|
||||
*/
|
||||
#define usb_endpoint_bmAttributes(transfer_type) \
|
||||
( (uint8_t) (transfer_type) )
|
||||
#define usb_endpoint_bmAttributes_isochronous( \
|
||||
synchronization_type, usage_type ) \
|
||||
( (uint8_t) (0b01 | ((synchronization_type)<<2) | ((usage_type)<<4)) )
|
||||
|
||||
|
||||
/* - spec sec 9.6.6 (Standard USB Descriptor Definitions / Endpoint)
|
||||
* - table 9-13 (Standard Endpoint Descriptor)
|
||||
* - wMaxPacketSize
|
||||
*
|
||||
* .-----------------------------------------------------------------.
|
||||
* | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||
* |-----------------------------------------------------------------|
|
||||
* | max packet size |
|
||||
* | (D10..D0) |
|
||||
* | |
|
||||
* >---------------------------------------------------------------<
|
||||
* | D15 | D14 | D13 | D12 | D11 | D10 | D9 | D8 |
|
||||
* |-----------------------------------------------------------------|
|
||||
* | reserved | number of additional | max packet size |
|
||||
* | (reset to 0) | transaction opportunities | (D10..D0) |
|
||||
* | | per microframe | (continued) |
|
||||
* | | (for high-speed isochronous | |
|
||||
* | | and interrupt endpoints) | |
|
||||
* '-----------------------------------------------------------------'
|
||||
*
|
||||
* - D12..D11 (additional transaction opportunities for each microframe
|
||||
* specified by bInterval):
|
||||
* 0b00 => none (1 transaction per microframe)
|
||||
* => max packet size: 1..1024
|
||||
* 0b01 => 1 additional (2 per microframe)
|
||||
* => max packet size: 513..1024
|
||||
* 0b10 => 2 additional (3 per microframe)
|
||||
* => max packet size: 683..1024
|
||||
* 0b11 => reserved
|
||||
* - for high-speed isochronous and interrupt endpoints only. else reset to
|
||||
* 0, and max packet size can be any allowed value (as defined in spec
|
||||
* chapter 5)
|
||||
*/
|
||||
#define usb_endpoint_wMaxPacketSize(adtl_trans_ops, max_packet_size) \
|
||||
( (uint16_t) (((adtl_trans_ops)<<11) | max_packet_size) )
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* - spec sec 9.6.7 (Standard USB Descriptor Definitions / String)
|
||||
* - table 9-15 (String Descriptor Zero, Specifying Languages Supported by
|
||||
* the Device)
|
||||
*
|
||||
* - string descriptors are optional. if a device does not support them, all
|
||||
* references to them within all descriptors must be reset to 0 .
|
||||
*
|
||||
* - string descriptors use unicode encodings (as defined in version 3.0 of the
|
||||
* unicode standard)
|
||||
*
|
||||
* - the strings may support multiple languages. when requesting a string
|
||||
* descriptor, the requester specifies the desired language using a 16 bit
|
||||
* language ID (LANGID) (defined by the USB-IF; see
|
||||
* <http://www.usb.org/developers/docs.html>).
|
||||
*
|
||||
* - string index 0 for all languages returns a string descriptor that contains
|
||||
* an array of two-byte LANGID codes supported by the device. USB devices
|
||||
* that omit all string descriptors must not return an array of LANGID codes.
|
||||
*/
|
||||
struct usb_string_descriptor_zero {
|
||||
uint8_t bLength;
|
||||
/* value: N+2
|
||||
* - the size of this descriptor in bytes (which equals the size of the
|
||||
* array of LANGIDs (in bytes) plus two)
|
||||
*/
|
||||
|
||||
uint8_t bDescriptorType;
|
||||
/* value: constant
|
||||
* - STRING Descriptor Type
|
||||
*/
|
||||
|
||||
uint16_t (* wLANGID_ptr)[];
|
||||
/* value: a pointer to the array of supported LANGID codes
|
||||
* - note: these must be transmitted as part of the descriptor; a
|
||||
* pointer is used here to avoid using variable length struct members
|
||||
* + malloc()
|
||||
*/
|
||||
};
|
||||
|
||||
/* - spec sec 9.6.7 (Standard USB Descriptor Definitions / String)
|
||||
* - table 9-16 (UNICODE String Descriptor)
|
||||
*/
|
||||
struct usb_string_descriptor {
|
||||
uint8_t bLength;
|
||||
/* value: number
|
||||
* - the size of this descriptor in bytes (which equals the size of the
|
||||
* string (in bytes) plus two)
|
||||
*/
|
||||
|
||||
uint8_t bDescriptorType;
|
||||
/* value: constant
|
||||
* - STRING Descriptor Type
|
||||
*/
|
||||
|
||||
uint8_t bString;
|
||||
/* value: number
|
||||
* - UNICODE encoded string
|
||||
*/
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
|
@ -1,311 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* USB Keyboard Key Codes : short names
|
||||
*
|
||||
* These are for convenience (and to help with formatting, keeping stuff from
|
||||
* getting too long). See "keyboard-usage-page.h" for definitions and
|
||||
* everything.
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 USB_USAGE_PAGE_KEYBOARD_SHORT_NAMES_h
|
||||
#define USB_USAGE_PAGE_KEYBOARD_SHORT_NAMES_h
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "./keyboard.h"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// protocol
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// error
|
||||
#define _ErrRollover KEY_ErrorRollOver
|
||||
#define _PostFail KEY_POSTFail
|
||||
#define _ErrUndef KEY_ErrorUndefined
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// main keyboard
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// letters
|
||||
#define _A KEY_a_A
|
||||
#define _B KEY_b_B
|
||||
#define _C KEY_c_C
|
||||
#define _D KEY_d_D
|
||||
#define _E KEY_e_E
|
||||
#define _F KEY_f_F
|
||||
#define _G KEY_g_G
|
||||
#define _H KEY_h_H
|
||||
#define _I KEY_i_I
|
||||
#define _J KEY_j_J
|
||||
#define _K KEY_k_K
|
||||
#define _L KEY_l_L
|
||||
#define _M KEY_m_M
|
||||
#define _N KEY_n_N
|
||||
#define _O KEY_o_O
|
||||
#define _P KEY_p_P
|
||||
#define _Q KEY_q_Q
|
||||
#define _R KEY_r_R
|
||||
#define _S KEY_s_S
|
||||
#define _T KEY_t_T
|
||||
#define _U KEY_u_U
|
||||
#define _V KEY_v_V
|
||||
#define _W KEY_w_W
|
||||
#define _X KEY_x_X
|
||||
#define _Y KEY_y_Y
|
||||
#define _Z KEY_z_Z
|
||||
|
||||
// numbers
|
||||
#define _0 KEY_0_RightParenthesis
|
||||
#define _1 KEY_1_Exclamation
|
||||
#define _2 KEY_2_At
|
||||
#define _3 KEY_3_Pound
|
||||
#define _4 KEY_4_Dollar
|
||||
#define _5 KEY_5_Percent
|
||||
#define _6 KEY_6_Caret
|
||||
#define _7 KEY_7_Ampersand
|
||||
#define _8 KEY_8_Asterisk
|
||||
#define _9 KEY_9_LeftParenthesis
|
||||
|
||||
// function
|
||||
#define _F1 KEY_F1
|
||||
#define _F2 KEY_F2
|
||||
#define _F3 KEY_F3
|
||||
#define _F4 KEY_F4
|
||||
#define _F5 KEY_F5
|
||||
#define _F6 KEY_F6
|
||||
#define _F7 KEY_F7
|
||||
#define _F8 KEY_F8
|
||||
#define _F9 KEY_F9
|
||||
#define _F10 KEY_F10
|
||||
#define _F11 KEY_F11
|
||||
#define _F12 KEY_F12
|
||||
#define _F13 KEY_F13
|
||||
#define _F14 KEY_F14
|
||||
#define _F15 KEY_F15
|
||||
#define _F16 KEY_F16
|
||||
#define _F17 KEY_F17
|
||||
#define _F18 KEY_F18
|
||||
#define _F19 KEY_F19
|
||||
#define _F20 KEY_F20
|
||||
#define _F21 KEY_F21
|
||||
#define _F22 KEY_F22
|
||||
#define _F23 KEY_F23
|
||||
#define _F24 KEY_F24
|
||||
|
||||
// whitespace and symbols
|
||||
#define _enter KEY_ReturnEnter
|
||||
#define _space KEY_Spacebar
|
||||
#define _tab KEY_Tab
|
||||
// ---
|
||||
#define _backslash KEY_Backslash_Pipe
|
||||
#define _bracketL KEY_LeftBracket_LeftBrace
|
||||
#define _bracketR KEY_RightBracket_RightBrace
|
||||
#define _comma KEY_Comma_LessThan
|
||||
#define _dash KEY_Dash_Underscore
|
||||
#define _equal KEY_Equal_Plus
|
||||
#define _grave KEY_GraveAccent_Tilde
|
||||
#define _period KEY_Period_GreaterThan
|
||||
#define _quote KEY_SingleQuote_DoubleQuote
|
||||
#define _semicolon KEY_Semicolon_Colon
|
||||
#define _slash KEY_Slash_Question
|
||||
// ---
|
||||
#define _sep_dec KEY_DecimalSeparator
|
||||
#define _sep_thousands KEY_ThousandsSeparator
|
||||
#define _currencyUnit KEY_CurrencyUnit
|
||||
#define _currencySubunit KEY_CurrencySubunit
|
||||
|
||||
// international and language
|
||||
#define _int1 KEY_International1
|
||||
#define _int2 KEY_International2
|
||||
#define _int3 KEY_International3
|
||||
#define _int4 KEY_International4
|
||||
#define _int5 KEY_International5
|
||||
#define _int6 KEY_International6
|
||||
#define _int7 KEY_International7
|
||||
#define _int8 KEY_International8
|
||||
#define _int9 KEY_International9
|
||||
// ---
|
||||
#define _lang1 KEY_LANG1
|
||||
#define _lang2 KEY_LANG2
|
||||
#define _lang3 KEY_LANG3
|
||||
#define _lang4 KEY_LANG4
|
||||
#define _lang5 KEY_LANG5
|
||||
#define _lang6 KEY_LANG6
|
||||
#define _lang7 KEY_LANG7
|
||||
#define _lang8 KEY_LANG8
|
||||
#define _lang9 KEY_LANG9
|
||||
// ---
|
||||
#define _backslash_nonUS KEY_NonUS_Backslash_Pipe
|
||||
#define _pound_nonUS KEY_NonUS_Pound_Tilde
|
||||
|
||||
// text control
|
||||
#define _bs KEY_DeleteBackspace
|
||||
#define _del KEY_DeleteForward
|
||||
#define _home KEY_Home
|
||||
#define _end KEY_End
|
||||
#define _pageU KEY_PageUp
|
||||
#define _pageD KEY_PageDown
|
||||
#define _arrowU KEY_UpArrow
|
||||
#define _arrowD KEY_DownArrow
|
||||
#define _arrowL KEY_LeftArrow
|
||||
#define _arrowR KEY_RightArrow
|
||||
#define _esc KEY_Escape
|
||||
#define _insert KEY_Insert
|
||||
|
||||
// modifier
|
||||
#define _altL KEY_LeftAlt
|
||||
#define _altR KEY_RightAlt
|
||||
#define _ctrlL KEY_LeftControl
|
||||
#define _ctrlR KEY_RightControl
|
||||
#define _guiL KEY_LeftGUI
|
||||
#define _guiR KEY_RightGUI
|
||||
#define _shiftL KEY_LeftShift
|
||||
#define _shiftR KEY_RightShift
|
||||
|
||||
// lock
|
||||
#define _capsLock KEY_CapsLock
|
||||
#define _scrollLock KEY_ScrollLock
|
||||
// (numlock is under keypad)
|
||||
// --- not generally used
|
||||
#define _capsLock_locking KEY_LockingCapsLock
|
||||
#define _numLock_locking KEY_LockingNumLock
|
||||
#define _scrollLock_locking KEY_LockingScrollLock
|
||||
|
||||
// special function
|
||||
#define _pause KEY_Pause
|
||||
#define _print KEY_PrintScreen
|
||||
// ---
|
||||
#define _application KEY_Application
|
||||
#define _execute KEY_Execute
|
||||
#define _power KEY_Power
|
||||
// ---
|
||||
#define _help KEY_Help
|
||||
#define _menu KEY_Menu
|
||||
// ---
|
||||
#define _cut KEY_Cut
|
||||
#define _copy KEY_Copy
|
||||
#define _paste KEY_Paste
|
||||
#define _find KEY_Find
|
||||
#define _select KEY_Select
|
||||
#define _stop KEY_Stop
|
||||
#define _undo KEY_Undo
|
||||
// ---
|
||||
#define _mute KEY_Mute
|
||||
#define _volumeU KEY_VolumeUp
|
||||
#define _volumeD KEY_VolumeDown
|
||||
// ---
|
||||
#define _altErase KEY_AlternateErase
|
||||
// ---
|
||||
#define _again KEY_Again
|
||||
#define _cancel KEY_Cancel
|
||||
#define _clear_again KEY_Clear_Again
|
||||
#define _clear KEY_Clear
|
||||
#define _oper KEY_Oper
|
||||
#define _out KEY_Out
|
||||
#define _prior KEY_Prior
|
||||
#define _return KEY_Return
|
||||
#define _separator KEY_Separator
|
||||
// ---
|
||||
#define _crSel KEY_CrSel_Props
|
||||
#define _exSel KEY_ExSel
|
||||
#define _sysReq KEY_SysReq_Attention
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// keypad
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// numbers and hex letters
|
||||
#define _1_kp KEYPAD_1_End
|
||||
#define _2_kp KEYPAD_2_DownArrow
|
||||
#define _3_kp KEYPAD_3_PageDown
|
||||
#define _4_kp KEYPAD_4_LeftArrow
|
||||
#define _5_kp KEYPAD_5
|
||||
#define _6_kp KEYPAD_6_RightArrow
|
||||
#define _7_kp KEYPAD_7_Home
|
||||
#define _8_kp KEYPAD_8_UpArrow
|
||||
#define _9_kp KEYPAD_9_PageUp
|
||||
#define _0_kp KEYPAD_0_Insert
|
||||
#define _A_kp KEYPAD_A
|
||||
#define _B_kp KEYPAD_B
|
||||
#define _C_kp KEYPAD_C
|
||||
#define _D_kp KEYPAD_D
|
||||
#define _E_kp KEYPAD_E
|
||||
#define _F_kp KEYPAD_F
|
||||
// ---
|
||||
#define _00_kp KEYPAD_00
|
||||
#define _000_kp KEYPAD_000
|
||||
|
||||
// whitespace and symbols
|
||||
#define _tab_kp KEYPAD_Tab
|
||||
#define _space_kp KEYPAD_Space
|
||||
#define _enter_kp KEYPAD_ENTER
|
||||
// ---
|
||||
#define _dec_del_kp KEYPAD_Period_Delete
|
||||
#define _comma_kp KEYPAD_Comma
|
||||
#define _equal_kp KEYPAD_Equal
|
||||
#define _equalSign_kp KEYPAD_EqualSign
|
||||
#define _parenL_kp KEYPAD_LeftParenthesis
|
||||
#define _parenR_kp KEYPAD_RightParenthesis
|
||||
#define _braceL_kp KEYPAD_LeftBrace
|
||||
#define _braceR_kp KEYPAD_RightBrace
|
||||
|
||||
// operations
|
||||
// --- basic
|
||||
#define _add_kp KEYPAD_Plus
|
||||
#define _sub_kp KEYPAD_Minus
|
||||
#define _mul_kp KEYPAD_Asterisk
|
||||
#define _div_kp KEYPAD_Slash
|
||||
#define _plusMinus_kp KEYPAD_PlusMinus
|
||||
// --- logical
|
||||
#define _lt_kp KEYPAD_LessThan
|
||||
#define _gt_kp KEYPAD_GreaterThan
|
||||
#define _xor_kp KEYPAD_XOR
|
||||
#define _and_kp KEYPAD_Ampersand
|
||||
#define _andand_kp KEYPAD_AmpersandAmpersand
|
||||
#define _pipe_kp KEYPAD_Pipe
|
||||
#define _pipepipe_kp KEYPAD_PipePipe
|
||||
#define _caret_kp KEYPAD_Caret
|
||||
#define _exclamation_kp KEYPAD_Exclamation
|
||||
// --- other
|
||||
#define _at_kp KEYPAD_At
|
||||
#define _colon_kp KEYPAD_Colon
|
||||
#define _percent_kp KEYPAD_Percent
|
||||
#define _pound_kp KEYPAD_Pound
|
||||
|
||||
// radix
|
||||
#define _bin_kp KEYPAD_Binary
|
||||
#define _oct_kp KEYPAD_Octal
|
||||
#define _dec_kp KEYPAD_Decimal
|
||||
#define _hex_kp KEYPAD_Hexadecimal
|
||||
|
||||
// text control
|
||||
#define _bs_kp KEYPAD_Backspace
|
||||
#define _clear_kp KEYPAD_Clear
|
||||
#define _clearEntry_kp KEYPAD_ClearEntry
|
||||
|
||||
// lock
|
||||
#define _numLock_kp KEYPAD_NumLock_Clear
|
||||
|
||||
// memory control
|
||||
#define _memStore_kp KEYPAD_MemoryStore
|
||||
#define _memRecall_kp KEYPAD_MemoryRecall
|
||||
#define _memClear_kp KEYPAD_MemoryClear
|
||||
#define _memAdd_kp KEYPAD_MemoryAdd
|
||||
#define _memSub_kp KEYPAD_MemorySubtract
|
||||
#define _memMul_kp KEYPAD_MemoryMultiply
|
||||
#define _memDiv_kp KEYPAD_MemoryDivide
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* USB LED Codes (usage page 0x08)
|
||||
*
|
||||
* Taken from [the HID Usage Tables pdf][1], Section 11,
|
||||
* which can be found on [the HID Page][2] at <http://www.usb.org>
|
||||
*
|
||||
* - applicable Usage Types (from Section 3.4)
|
||||
* - OOC : On/Off Control
|
||||
* - Sel : Selector
|
||||
* - DV : Dynamic Value
|
||||
* - US : Usage Switch
|
||||
* - UM : Usage Modifier
|
||||
*
|
||||
* [1]: http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
|
||||
* [2]: http://www.usb.org/developers/hidpage
|
||||
* ----------------------------------------------------------------------------
|
||||
* 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 USB_USAGE_PAGE_LED_h
|
||||
#define USB_USAGE_PAGE_LED_h
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Name ID Usage Type Section of HID Tables
|
||||
// --------------------------- ---- ---------- ----------------------
|
||||
|
||||
// (Undefined) 0x00 // - -
|
||||
|
||||
#define LED_NumLock 0x01 // OOC 11.1
|
||||
#define LED_CapsLock 0x02 // OOC 11.1
|
||||
#define LED_ScrollLock 0x03 // OOC 11.1
|
||||
#define LED_Compose 0x04 // OOC 11.1
|
||||
#define LED_Kana 0x05 // OOC 11.1
|
||||
#define LED_Power 0x06 // OOC 11.6
|
||||
#define LED_Shift 0x07 // OOC 11.1
|
||||
#define LED_DoNotDisturb 0x08 // OOC 11.2
|
||||
#define LED_Mute 0x09 // OOC 11.3
|
||||
#define LED_ToneEnable 0x0A // OOC 11.3
|
||||
#define LED_HighCutFilter 0x0B // OOC 11.3
|
||||
#define LED_LowCutFilter 0x0C // OOC 11.3
|
||||
#define LED_EqualizerEnable 0x0D // OOC 11.3
|
||||
#define LED_SoundFieldOn 0x0E // OOC 11.3
|
||||
#define LED_SurroundOn 0x0F // OOC 11.3
|
||||
#define LED_Repeat 0x10 // OOC 11.3
|
||||
#define LED_Stereo 0x11 // OOC 11.3
|
||||
#define LED_SamplingRateDetect 0x12 // OOC 11.3
|
||||
#define LED_Spinning 0x13 // OOC 11.4
|
||||
#define LED_CAV 0x14 // OOC 11.3
|
||||
#define LED_CLV 0x15 // OOC 11.3
|
||||
#define LED_RecordingFormatDetect 0x16 // OOC 11.4
|
||||
#define LED_OffHook 0x17 // OOC 11.2
|
||||
#define LED_Ring 0x18 // OOC 11.2
|
||||
#define LED_MessageWaiting 0x19 // OOC 11.2
|
||||
#define LED_DataMode 0x1A // OOC 11.2
|
||||
#define LED_BatteryOperation 0x1B // OOC 11.6
|
||||
#define LED_BatteryOK 0x1C // OOC 11.6
|
||||
#define LED_BatteryLow 0x1D // OOC 11.6
|
||||
#define LED_Speaker 0x1E // OOC 11.2
|
||||
#define LED_HeadSet 0x1F // OOC 11.2
|
||||
#define LED_Hold 0x20 // OOC 11.2
|
||||
#define LED_Microphone 0x21 // OOC 11.2
|
||||
#define LED_Coverage 0x22 // OOC 11.2
|
||||
#define LED_NightMode 0x23 // OOC 11.2
|
||||
#define LED_SendCalls 0x24 // OOC 11.2
|
||||
#define LED_CallPickup 0x25 // OOC 11.2
|
||||
#define LED_Conference 0x26 // OOC 11.2
|
||||
#define LED_Standby 0x27 // OOC 11.6
|
||||
#define LED_CameraOn 0x28 // OOC 11.3
|
||||
#define LED_CameraOff 0x29 // OOC 11.3
|
||||
#define LED_OnLine 0x2A // OOC 11.6
|
||||
#define LED_OffLine 0x2B // OOC 11.6
|
||||
#define LED_Busy 0x2C // OOC 11.6
|
||||
#define LED_Ready 0x2D // OOC 11.6
|
||||
#define LED_PaperOut 0x2E // OOC 11.5
|
||||
#define LED_PaperJam 0x2F // OOC 11.5
|
||||
#define LED_Remote 0x30 // OOC 11.6
|
||||
#define LED_Forward 0x31 // OOC 11.4
|
||||
#define LED_Reverse 0x32 // OOC 11.4
|
||||
#define LED_Stop 0x33 // OOC 11.4
|
||||
#define LED_Rewind 0x34 // OOC 11.4
|
||||
#define LED_FastForward 0x35 // OOC 11.4
|
||||
#define LED_Play 0x36 // OOC 11.4
|
||||
#define LED_Pause 0x37 // OOC 11.4
|
||||
#define LED_Record 0x38 // OOC 11.4
|
||||
#define LED_Error 0x39 // OOC 11.6
|
||||
#define LED_UsageSelectedIndicator 0x3A // US 11.6
|
||||
#define LED_UsageInUseIndicator 0x3B // US 11.6
|
||||
#define LED_UsageMultiModeIndicator 0x3C // UM 11.6
|
||||
#define LED_IndicatorOn 0x3D // Sel 11.6
|
||||
#define LED_IndicatorFlash 0x3E // Sel 11.6
|
||||
#define LED_IndicatorSlowBlink 0x3F // Sel 11.6
|
||||
#define LED_IndicatorFastBlink 0x40 // Sel 11.6
|
||||
#define LED_IndicatorOff 0x41 // Sel 11.6
|
||||
#define LED_FlashOnTime 0x42 // DV 11.6
|
||||
#define LED_SlowBlinkOnTime 0x43 // DV 11.6
|
||||
#define LED_SlowBlinkOffTime 0x44 // DV 11.6
|
||||
#define LED_FastBlinkOnTime 0x45 // DV 11.6
|
||||
#define LED_FastBlinkOffTime 0x46 // DV 11.6
|
||||
#define LED_UsageIndicatorColor 0x47 // UM 11.6
|
||||
#define LED_IndicatorRed 0x48 // Sel 11.6
|
||||
#define LED_IndicatorGreen 0x49 // Sel 11.6
|
||||
#define LED_IndicatorAmber 0x4A // Sel 11.6
|
||||
#define LED_GenericIndicator 0x4B // OOC 11.6
|
||||
#define LED_SystemSuspend 0x4C // OOC 11.6
|
||||
#define LED_ExternalPowerConnected 0x4D // OOC 11.6
|
||||
|
||||
// (Reserved) 0x4E..0xFFFF // - -
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------
|
||||
#endif
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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
|
||||
|
803
src/main.c
803
src/main.c
|
@ -1,4 +1,3 @@
|
|||
// vim: ts=4 sw=4 sts=4
|
||||
/* ----------------------------------------------------------------------------
|
||||
* main()
|
||||
* ----------------------------------------------------------------------------
|
||||
|
@ -7,266 +6,618 @@
|
|||
* Project located at <https://github.com/benblazak/ergodox-firmware>
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <util/delay.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"
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// types and forward declarations
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
typedef int8_t i8;
|
||||
typedef uint8_t u8;
|
||||
typedef int16_t i16;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
|
||||
typedef u8 keycode;
|
||||
typedef u16 media_keycode;
|
||||
typedef u8 layer;
|
||||
typedef u32 millis; // wraps every 50 days, but that's fine for our logic
|
||||
|
||||
typedef void (*keyfunc)(keycode, bool);
|
||||
|
||||
#include "./main.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// --------------------------------------------------------------------
|
||||
// hardware
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
#define MAX_ACTIVE_LAYERS 20
|
||||
// comment out this define to disable the debug interface completely
|
||||
// however, just not using the functions gets rid of most of the firmware bloat already
|
||||
#define KBD_DEBUG
|
||||
#include "./keyboard/controller.c"
|
||||
#include "./keyboard/keyboard.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
|
||||
// layout data
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* main()
|
||||
*/
|
||||
int main(void) {
|
||||
kb_init(); // does controller initialization too
|
||||
#include "./keyboard/layout.c"
|
||||
// defines:
|
||||
// #define KB_LAYERS #{Layers.size}
|
||||
// static const keycode PROGMEM _kb_layout_code[KB_ROWS][KB_COLUMNS][KB_LAYERS];
|
||||
// static const keyfunc PROGMEM _kb_layout_func[KB_ROWS][KB_COLUMNS][KB_LAYERS];
|
||||
|
||||
kb_led_state_power_on();
|
||||
/* static u8 layers[KB_LAYERS] = {0, 1, 1+2, 3, 4, 2+3+4}; */
|
||||
|
||||
usb_init();
|
||||
while (!usb_configured());
|
||||
kb_led_delay_usb_init(); // give the OS time to load drivers, etc.
|
||||
|
||||
kb_led_state_ready();
|
||||
|
||||
for (;;) {
|
||||
// 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;
|
||||
|
||||
kb_update_matrix(*main_kb_is_pressed);
|
||||
|
||||
// this loop is responsible to
|
||||
// - "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)
|
||||
//
|
||||
// note
|
||||
// - 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/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) {
|
||||
if (is_pressed) {
|
||||
layer = main_layers_peek(0);
|
||||
main_layers_pressed[row][col] = layer;
|
||||
} else {
|
||||
layer = main_layers_pressed[row][col];
|
||||
}
|
||||
|
||||
// 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(MAKEFILE_DEBOUNCE_TIME);
|
||||
|
||||
// update LEDs
|
||||
if (keyboard_leds & (1<<0)) { kb_led_num_on(); }
|
||||
else { kb_led_num_off(); }
|
||||
if (keyboard_leds & (1<<1)) { kb_led_caps_on(); }
|
||||
else { kb_led_caps_off(); }
|
||||
if (keyboard_leds & (1<<2)) { kb_led_scroll_on(); }
|
||||
else { kb_led_scroll_off(); }
|
||||
if (keyboard_leds & (1<<3)) { kb_led_compose_on(); }
|
||||
else { kb_led_compose_off(); }
|
||||
if (keyboard_leds & (1<<4)) { kb_led_kana_on(); }
|
||||
else { kb_led_kana_off(); }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#if KB_LAYERS > 8
|
||||
#error "can only handle 8 layers for now"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// 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
|
||||
|
||||
// globals
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* 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) );
|
||||
// state of key presses
|
||||
static bool _kb_is_pressed[KB_ROWS][KB_COLUMNS];
|
||||
static bool (*kb_is_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_is_pressed;
|
||||
|
||||
if (key_function)
|
||||
(*key_function)();
|
||||
}
|
||||
static bool _kb_was_pressed[KB_ROWS][KB_COLUMNS];
|
||||
static bool (*kb_was_pressed)[KB_ROWS][KB_COLUMNS] = &_kb_was_pressed;
|
||||
|
||||
static layer layers_pressed[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* 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.
|
||||
* ------------------------------------------------------------------------- */
|
||||
// layer state
|
||||
static i8 layers_active[KB_LAYERS];
|
||||
static layer layers_top;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// sticky states
|
||||
static bool layer_sticky_on;
|
||||
static bool layer_sticky[KB_LAYERS];
|
||||
static bool layer_sticky_done;
|
||||
static u8 mod_sticky;
|
||||
static bool mod_sticky_done;
|
||||
|
||||
struct layers {
|
||||
uint8_t layer;
|
||||
uint8_t id;
|
||||
// key repeat config
|
||||
static const millis repeat_delay = 300; // ms before key repeat kicks in
|
||||
static const millis repeat_rate = 13; // send 1 / RATE key press
|
||||
|
||||
// key repeat state
|
||||
static millis time_pressed[KB_ROWS][KB_COLUMNS];
|
||||
static bool repeating[KB_ROWS][KB_COLUMNS];
|
||||
|
||||
// TODO this only exists as a workaround until we handle our own key repeats
|
||||
static const keyfunc _kb_layer_funcs[] = {
|
||||
&kbfun_layer_press_release,
|
||||
&kbfun_layer_sticky,
|
||||
&kbfun_shift_layer_press_release,
|
||||
&kbfun_control_layer_press_release,
|
||||
&kbfun_alt_layer_press_release,
|
||||
&kbfun_win_layer_press_release,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// utilities
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct layers layers[MAX_ACTIVE_LAYERS];
|
||||
uint8_t layers_head = 0;
|
||||
uint8_t layers_ids_in_use[MAX_ACTIVE_LAYERS] = {true};
|
||||
#define array_length(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
/*
|
||||
* 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;
|
||||
#define set_bit(x, i) (x) |= (1u << (i))
|
||||
#define unset_bit(x, i) (x) &= ~(1u << (i))
|
||||
#define toggle_bit(x, i) (x) ^= (1u << (i))
|
||||
#define is_set(x, i) (((x) >> (i)) & 1u)
|
||||
#define is_unset(x, i) !is_set((x), (i))
|
||||
|
||||
return 0; // default, or error
|
||||
#define set_layer(x, layer) set_bit((x), (layer) - 1)
|
||||
#define unset_layer(x, layer) unset_bit((x), (layer) - 1)
|
||||
#define toggle_layer(x, layer) toggle_bit((x), (layer) - 1)
|
||||
|
||||
millis now() { return timer0_ms; }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// main
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int main() {
|
||||
// initialize
|
||||
init_hw();
|
||||
init_layers();
|
||||
init_sticky();
|
||||
init_timer();
|
||||
|
||||
// never return
|
||||
main_key_loop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
void main_key_loop() {
|
||||
for (;;) {
|
||||
// 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;
|
||||
|
||||
return 0; // default, or error
|
||||
kb_update_matrix(*kb_is_pressed);
|
||||
|
||||
// - execute key functions when their key changes 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)
|
||||
for (u8 row=0; row<KB_ROWS; row++) {
|
||||
for (u8 col=0; col<KB_COLUMNS; col++) {
|
||||
bool is_pressed = (*kb_is_pressed)[row][col];
|
||||
bool was_pressed = (*kb_was_pressed)[row][col];
|
||||
|
||||
if (is_pressed) {
|
||||
if (!was_pressed) { main_key_down_new(row, col); }
|
||||
else { main_key_down_repeat(row, col); }
|
||||
} else {
|
||||
if (!was_pressed) { continue; } // no change
|
||||
else { main_key_up(row, col); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send the USB report (even if nothing's changed)
|
||||
usb_keyboard_send();
|
||||
usb_extra_consumer_send();
|
||||
|
||||
// unset sticky keys if necessary
|
||||
if (layer_sticky_on && layer_sticky_done) {
|
||||
for (layer l=1; l < KB_LAYERS; l++) {
|
||||
if (layer_sticky[l]) {
|
||||
layer_disable(l);
|
||||
layer_sticky[l] = false;
|
||||
}
|
||||
}
|
||||
layer_sticky_on = false;
|
||||
layer_sticky_done = false;
|
||||
}
|
||||
|
||||
if (mod_sticky && mod_sticky_done) {
|
||||
keyboard_modifier_keys &= ~mod_sticky;
|
||||
usb_keyboard_send();
|
||||
mod_sticky = 0;
|
||||
mod_sticky_done = false;
|
||||
}
|
||||
|
||||
// debounce in ms; see keyswitch spec for necessary value
|
||||
_delay_ms(5);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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--;
|
||||
}
|
||||
void main_key_up(u8 row, u8 col) {
|
||||
layer layer = layers_pressed[row][col];
|
||||
layers_pressed[row][col] = 0;
|
||||
|
||||
// stop key repeat
|
||||
if (repeating[row][col]) {
|
||||
repeating[row][col] = false;
|
||||
/* debug_printf("stop: %lu\n", now() - time_pressed[row][col]); */
|
||||
}
|
||||
|
||||
exec_key(layer, row, col, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
void main_key_down_new(u8 row, u8 col) {
|
||||
layer layer = layers_top;
|
||||
layers_pressed[row][col] = layer;
|
||||
|
||||
return 0; // default, or error
|
||||
time_pressed[row][col] = now();
|
||||
/* debug_printf("down: %lu\n", time_pressed[row][col]); */
|
||||
|
||||
exec_key(layer, row, col, true);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ------------------------------------------------------------------------- */
|
||||
void main_key_down_repeat(u8 row, u8 col) {
|
||||
millis t = now(); // consistency!
|
||||
millis diff = t - time_pressed[row][col];
|
||||
|
||||
if (!repeating[row][col] && diff >= repeat_delay) { // start repeat
|
||||
repeating[row][col] = true;
|
||||
time_pressed[row][col] = t;
|
||||
|
||||
/* debug_printf("start: %lu\n", diff); */
|
||||
} else if (repeating[row][col] && diff >= repeat_rate) { // continue repeat
|
||||
time_pressed[row][col] = t;
|
||||
|
||||
/* debug_printf("cont: %lu\n", diff); */
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// init functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void init_hw() {
|
||||
kb_init();
|
||||
usb_init();
|
||||
while (!usb_configured());
|
||||
}
|
||||
|
||||
void init_sticky() {
|
||||
for (layer l=1; l < KB_LAYERS; l++) {
|
||||
layer_sticky[l] = false;
|
||||
}
|
||||
layer_sticky_on = false;
|
||||
mod_sticky = 0;
|
||||
layer_sticky_done = false;
|
||||
mod_sticky_done = false;
|
||||
}
|
||||
|
||||
void init_layers() {
|
||||
for (layer l=0; l < KB_LAYERS; l++) {
|
||||
layers_active[l] = 0;
|
||||
}
|
||||
layers_active[0] = 1;
|
||||
layers_top = 0;
|
||||
|
||||
for (u8 row=0; row<KB_ROWS; row++) {
|
||||
for (u8 col=0; col<KB_COLUMNS; col++) {
|
||||
layers_pressed[row][col] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_timer() {
|
||||
for (u8 row=0; row<KB_ROWS; row++) {
|
||||
for (u8 col=0; col<KB_COLUMNS; col++) {
|
||||
time_pressed[row][col] = 0;
|
||||
repeating[row][col] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// layer functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// find highest active layer
|
||||
layer highest_active_layer() {
|
||||
for (layer l = KB_LAYERS - 1; l > 0; l--) {
|
||||
if (layers_active[l] > 0) { return l; }
|
||||
}
|
||||
|
||||
// the base layer is always active
|
||||
return 0;
|
||||
}
|
||||
|
||||
// enable a layer
|
||||
void layer_enable(layer l) {
|
||||
if (l >= KB_LAYERS || l == 0) { return; }
|
||||
|
||||
layers_active[l] += 1;
|
||||
|
||||
if (l > layers_top) {
|
||||
layers_top = l;
|
||||
}
|
||||
}
|
||||
|
||||
// disable a layer
|
||||
void layer_disable(layer l) {
|
||||
// base layer stays always on
|
||||
if (l >= KB_LAYERS || l == 0) { return; }
|
||||
|
||||
if (layers_active[l] > 0) {
|
||||
layers_active[l] -= 1;
|
||||
}
|
||||
|
||||
if (l == layers_top) {
|
||||
layers_top = highest_active_layer();
|
||||
}
|
||||
|
||||
// re-press affected keys
|
||||
for (u8 row=0; row<KB_ROWS; row++) {
|
||||
for (u8 col=0; col<KB_COLUMNS; col++) {
|
||||
if (layers_pressed[row][col] == l) {
|
||||
keyfunc func = (kb_keyfunc(l, row, col));
|
||||
// FIXME don't re-send normal keys until we have key repeats
|
||||
if (is_layer_keyfunc(func)) {
|
||||
// FIXME this kinda shouldn't be here and it privileges layer 0 even more
|
||||
layers_pressed[row][col] = 0;
|
||||
exec_key(l, row, col, false);
|
||||
|
||||
layers_pressed[row][col] = layers_top;
|
||||
exec_key(layers_top, row, col, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_layer_keyfunc(keyfunc f) {
|
||||
for (int i=0; i<array_length(_kb_layer_funcs); i++) {
|
||||
if (f == _kb_layer_funcs[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// layout info
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
keycode kb_keycode (layer l, u8 row, u8 col) { return (keycode) pgm_read_byte(&(_kb_layout_code[row][col][l])); }
|
||||
keyfunc kb_keyfunc (layer l, u8 row, u8 col) { return (keyfunc) pgm_read_word(&(_kb_layout_func[row][col][l])); }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// keyfunc primitives
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// basic keypresses
|
||||
void _kbfun_normal_press_release(keycode key, bool is_pressed) {
|
||||
if (key == 0) { return; } // noop
|
||||
|
||||
if (is_pressed) { _kbfun_normal_swap(0, key); }
|
||||
else { _kbfun_normal_swap(key, 0); }
|
||||
}
|
||||
|
||||
void _kbfun_mediakey_press_release(keycode key, bool is_pressed) {
|
||||
media_keycode media_key = _media_code_lookup(key);
|
||||
if (is_pressed) {
|
||||
consumer_key = media_key;
|
||||
} else {
|
||||
// only one media key can be pressed at a time, so only clear most recent one
|
||||
if (media_key == consumer_key) {
|
||||
consumer_key = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _kbfun_modifier_press_release(keycode key, bool is_pressed) {
|
||||
if (is_pressed) {
|
||||
set_bit(keyboard_modifier_keys, key);
|
||||
} else {
|
||||
unset_bit(keyboard_modifier_keys, key);
|
||||
}
|
||||
}
|
||||
|
||||
void _kbfun_normal_swap(keycode from, keycode to) {
|
||||
for (u8 i=0; i < sizeof(keyboard_keys); i++) {
|
||||
if (keyboard_keys[i] == from) {
|
||||
keyboard_keys[i] = to;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _kbfun_normal_is_pressed(keycode key) {
|
||||
for (u8 i=0; i < sizeof(keyboard_keys); i++) {
|
||||
if (keyboard_keys[i] == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool _kbfun_mediakey_is_pressed(keycode key) {
|
||||
return (consumer_key != 0);
|
||||
}
|
||||
|
||||
bool _kbfun_modifier_is_pressed(keycode key) {
|
||||
return is_set(keyboard_modifier_keys, key);
|
||||
}
|
||||
|
||||
void _kbfun_normal_sticky_done() {
|
||||
layer_sticky_done = true;
|
||||
mod_sticky_done = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// basic keyfuncs
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// execute the keypress or keyrelease function (if it exists) of the key at the current possition
|
||||
void exec_key(layer layer, u8 row, u8 col, bool is_pressed) {
|
||||
keycode key = kb_keycode(layer, row, col);
|
||||
void (*key_function)(keycode, bool) = kb_keyfunc(layer, row, col);
|
||||
|
||||
if (key_function) { (*key_function)(key, is_pressed); }
|
||||
}
|
||||
|
||||
// normal key
|
||||
void kbfun_normal_press_release(keycode key, bool is_pressed) {
|
||||
_kbfun_normal_sticky_done();
|
||||
_kbfun_normal_press_release(key, is_pressed);
|
||||
}
|
||||
|
||||
// media key
|
||||
void kbfun_mediakey_press_release(keycode key, bool is_pressed) {
|
||||
_kbfun_normal_sticky_done();
|
||||
_kbfun_mediakey_press_release(key, is_pressed);
|
||||
}
|
||||
|
||||
// modifier
|
||||
void kbfun_modifier_press_release(keycode key, bool is_pressed) {
|
||||
layer_sticky_done = true;
|
||||
_kbfun_modifier_press_release(key, is_pressed);
|
||||
}
|
||||
|
||||
// layer key
|
||||
void kbfun_layer_press_release(keycode key, bool is_pressed) {
|
||||
layer_sticky_done = true; // don't disable sticky mods!
|
||||
|
||||
layer l = (layer) key;
|
||||
if (is_pressed) {
|
||||
layer_enable(l);
|
||||
} else {
|
||||
layer_disable(l);
|
||||
}
|
||||
}
|
||||
|
||||
// sticky layer key
|
||||
void kbfun_layer_sticky(keycode key, bool is_pressed) {
|
||||
layer l = (layer) key;
|
||||
|
||||
if (is_pressed) {
|
||||
if (! layer_sticky[l]) {
|
||||
layer_enable(l);
|
||||
layer_sticky_done = false;
|
||||
}
|
||||
} else {
|
||||
if (layer_sticky_done) {
|
||||
layer_disable(l);
|
||||
} else {
|
||||
layer_sticky[l] = true;
|
||||
layer_sticky_on = true;
|
||||
layer_sticky_done = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sticky modifier key
|
||||
void kbfun_modifier_sticky(keycode key, bool is_pressed) {
|
||||
// TODO handle: sticky, then same modifier
|
||||
keycode mod = key;
|
||||
|
||||
if (is_pressed) {
|
||||
kbfun_modifier_press_release(key, true);
|
||||
mod_sticky_done = false;
|
||||
} else {
|
||||
if (mod_sticky_done) {
|
||||
kbfun_modifier_press_release(key, false);
|
||||
} else {
|
||||
set_bit(mod_sticky, mod);
|
||||
mod_sticky_done = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// combo keyfuncs
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _kbfun_combo_normal_press_release(keycode combo_key, keycode key, bool is_pressed) {
|
||||
_kbfun_modifier_press_release(combo_key, is_pressed);
|
||||
kbfun_normal_press_release(key, is_pressed);
|
||||
}
|
||||
|
||||
void _kbfun_combo_normal_press_release_once(keycode combo_key, keycode key, bool is_pressed) {
|
||||
// FIXME this should be cleaner when we have actual key repeats
|
||||
|
||||
if (is_pressed) {
|
||||
// avoid messing with independently pressed modifiers
|
||||
bool mod_already_pressed = _kbfun_modifier_is_pressed(combo_key);
|
||||
|
||||
if (!mod_already_pressed) {
|
||||
_kbfun_modifier_press_release(combo_key, true);
|
||||
}
|
||||
|
||||
kbfun_normal_press_release(key, true);
|
||||
|
||||
if (!mod_already_pressed) {
|
||||
// we force a keyboard send to prevent the modifier from bleeding into the next key press
|
||||
usb_keyboard_send();
|
||||
_kbfun_modifier_press_release(combo_key, false);
|
||||
}
|
||||
} else {
|
||||
kbfun_normal_press_release(key, false);
|
||||
}
|
||||
}
|
||||
|
||||
void _kbfun_combo_layer_press_release(keycode combo_key, keycode key, bool is_pressed) {
|
||||
kbfun_layer_press_release(key, is_pressed);
|
||||
_kbfun_modifier_press_release(combo_key, is_pressed);
|
||||
}
|
||||
|
||||
void kbfun_shift_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftShift, key, is_pressed); } // +shift
|
||||
void kbfun_control_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftControl, key, is_pressed); } // +control
|
||||
void kbfun_alt_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftAlt, key, is_pressed); } // +alt
|
||||
void kbfun_win_press_release(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release(MOD_KEY_LeftGUI, key, is_pressed); } // +win
|
||||
//
|
||||
void kbfun_shift_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftShift, key, is_pressed); } // +shift once
|
||||
void kbfun_control_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftControl, key, is_pressed); } // +control once
|
||||
void kbfun_alt_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftAlt, key, is_pressed); } // +alt once
|
||||
void kbfun_win_press_release_once(keycode key, bool is_pressed) { _kbfun_combo_normal_press_release_once(MOD_KEY_LeftGUI, key, is_pressed); } // +win once
|
||||
//
|
||||
void kbfun_shift_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftShift, key, is_pressed); } // +shift + layer
|
||||
void kbfun_control_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftControl, key, is_pressed); } // +control + layer
|
||||
void kbfun_alt_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftAlt, key, is_pressed); } // +alt + layer
|
||||
void kbfun_win_layer_press_release(keycode key, bool is_pressed) { _kbfun_combo_layer_press_release(MOD_KEY_LeftGUI, key, is_pressed); } // +win + layer
|
||||
|
||||
// multi-combos
|
||||
|
||||
// TODO lol
|
||||
|
||||
void _kbfun_combo_normal_press_release2(keycode combo_key1, keycode combo_key2, keycode key, bool is_pressed) {
|
||||
_kbfun_modifier_press_release(combo_key1, is_pressed);
|
||||
_kbfun_modifier_press_release(combo_key2, is_pressed);
|
||||
kbfun_normal_press_release(key, is_pressed);
|
||||
}
|
||||
|
||||
void _kbfun_combo_normal_press_release3(keycode combo_key1, keycode combo_key2, keycode combo_key3, keycode key, bool is_pressed) {
|
||||
_kbfun_modifier_press_release(combo_key1, is_pressed);
|
||||
_kbfun_modifier_press_release(combo_key2, is_pressed);
|
||||
_kbfun_modifier_press_release(combo_key3, is_pressed);
|
||||
kbfun_normal_press_release(key, is_pressed);
|
||||
}
|
||||
|
||||
void _kbfun_combo_normal_press_release4(keycode combo_key1, keycode combo_key2, keycode combo_key3, keycode combo_key4, keycode key, bool is_pressed) {
|
||||
_kbfun_modifier_press_release(combo_key1, is_pressed);
|
||||
_kbfun_modifier_press_release(combo_key2, is_pressed);
|
||||
_kbfun_modifier_press_release(combo_key3, is_pressed);
|
||||
_kbfun_modifier_press_release(combo_key4, is_pressed);
|
||||
kbfun_normal_press_release(key, is_pressed);
|
||||
}
|
||||
|
||||
#define COMBO2(x1, x2) _kbfun_combo_normal_press_release2(x1, x2, key, is_pressed)
|
||||
#define COMBO3(x1, x2, x3) _kbfun_combo_normal_press_release3(x1, x2, x3, key, is_pressed)
|
||||
#define COMBO4(x1, x2, x3, x4) _kbfun_combo_normal_press_release4(x1, x2, x3, x4, key, is_pressed)
|
||||
|
||||
void kbfun_shift_control_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftShift, MOD_KEY_LeftControl); }
|
||||
void kbfun_shift_alt_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftShift, MOD_KEY_LeftAlt); }
|
||||
void kbfun_shift_win_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftShift, MOD_KEY_LeftGUI); }
|
||||
void kbfun_control_alt_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftControl, MOD_KEY_LeftAlt); }
|
||||
void kbfun_control_win_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftControl, MOD_KEY_LeftGUI); }
|
||||
void kbfun_alt_win_press_release(keycode key, bool is_pressed) { COMBO2(MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
||||
|
||||
void kbfun_shift_control_alt_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftControl, MOD_KEY_LeftAlt); }
|
||||
void kbfun_shift_control_win_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftControl, MOD_KEY_LeftGUI); }
|
||||
void kbfun_shift_alt_control_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftAlt, MOD_KEY_LeftControl); }
|
||||
void kbfun_shift_alt_win_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
||||
void kbfun_shift_win_control_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftGUI, MOD_KEY_LeftControl); }
|
||||
void kbfun_shift_win_alt_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftShift, MOD_KEY_LeftGUI, MOD_KEY_LeftAlt); }
|
||||
void kbfun_control_alt_shift_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftAlt, MOD_KEY_LeftShift); }
|
||||
void kbfun_control_alt_win_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
||||
void kbfun_control_win_shift_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftGUI, MOD_KEY_LeftShift); }
|
||||
void kbfun_control_win_alt_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftControl, MOD_KEY_LeftGUI, MOD_KEY_LeftAlt); }
|
||||
void kbfun_alt_win_shift_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftAlt, MOD_KEY_LeftGUI, MOD_KEY_LeftShift); }
|
||||
void kbfun_alt_win_control_press_release(keycode key, bool is_pressed) { COMBO3(MOD_KEY_LeftAlt, MOD_KEY_LeftGUI, MOD_KEY_LeftControl); }
|
||||
|
||||
void kbfun_shift_control_alt_win_press_release(keycode key, bool is_pressed) { COMBO4(MOD_KEY_LeftShift, MOD_KEY_LeftControl, MOD_KEY_LeftAlt, MOD_KEY_LeftGUI); }
|
||||
|
||||
// capslock
|
||||
void kbfun_capslock_press_release(keycode key, bool is_pressed) {
|
||||
static u8 keys_pressed;
|
||||
static bool lshift_pressed;
|
||||
static bool rshift_pressed;
|
||||
|
||||
if (!is_pressed) { keys_pressed--; }
|
||||
|
||||
// take care of the key that was actually pressed
|
||||
_kbfun_modifier_press_release(key, is_pressed);
|
||||
|
||||
// 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_modifier_is_pressed(MOD_KEY_LeftShift);
|
||||
rshift_pressed = _kbfun_modifier_is_pressed(MOD_KEY_RightShift);
|
||||
// disable both
|
||||
_kbfun_modifier_press_release(MOD_KEY_LeftShift, false);
|
||||
_kbfun_modifier_press_release(MOD_KEY_RightShift, false);
|
||||
|
||||
// press capslock, then release it
|
||||
_kbfun_normal_press_release(KEY_CapsLock, true); usb_keyboard_send();
|
||||
_kbfun_normal_press_release(KEY_CapsLock, false); usb_keyboard_send();
|
||||
|
||||
// restore the state of left and right shift
|
||||
if (lshift_pressed) { _kbfun_modifier_press_release(MOD_KEY_LeftShift, true); }
|
||||
if (rshift_pressed) { _kbfun_modifier_press_release(MOD_KEY_RightShift, true); }
|
||||
}
|
||||
|
||||
if (is_pressed) { keys_pressed++; }
|
||||
}
|
||||
|
|
115
src/main.h
115
src/main.h
|
@ -1,45 +1,70 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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 "./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
|
||||
|
||||
/* This file was automatically generated. Do not edit! */
|
||||
void kbfun_capslock_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_control_alt_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_alt_win_control_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_alt_win_shift_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_win_alt_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_win_shift_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_alt_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_alt_shift_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_win_alt_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_win_control_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_alt_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_alt_control_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_control_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_control_alt_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_alt_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_alt_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_alt_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_control_press_release(keycode key,bool is_pressed);
|
||||
void _kbfun_combo_normal_press_release4(keycode combo_key1,keycode combo_key2,keycode combo_key3,keycode combo_key4,keycode key,bool is_pressed);
|
||||
void _kbfun_combo_normal_press_release3(keycode combo_key1,keycode combo_key2,keycode combo_key3,keycode key,bool is_pressed);
|
||||
void _kbfun_combo_normal_press_release2(keycode combo_key1,keycode combo_key2,keycode key,bool is_pressed);
|
||||
void kbfun_win_press_release_once(keycode key,bool is_pressed);
|
||||
void kbfun_alt_press_release_once(keycode key,bool is_pressed);
|
||||
void kbfun_control_press_release_once(keycode key,bool is_pressed);
|
||||
void kbfun_shift_press_release_once(keycode key,bool is_pressed);
|
||||
void kbfun_win_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_alt_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_press_release(keycode key,bool is_pressed);
|
||||
void _kbfun_combo_layer_press_release(keycode combo_key,keycode key,bool is_pressed);
|
||||
void _kbfun_combo_normal_press_release_once(keycode combo_key,keycode key,bool is_pressed);
|
||||
void _kbfun_combo_normal_press_release(keycode combo_key,keycode key,bool is_pressed);
|
||||
void kbfun_modifier_sticky(keycode key,bool is_pressed);
|
||||
void kbfun_modifier_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_mediakey_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_normal_press_release(keycode key,bool is_pressed);
|
||||
void _kbfun_normal_sticky_done();
|
||||
bool _kbfun_modifier_is_pressed(keycode key);
|
||||
bool _kbfun_mediakey_is_pressed(keycode key);
|
||||
bool _kbfun_normal_is_pressed(keycode key);
|
||||
void _kbfun_modifier_press_release(keycode key,bool is_pressed);
|
||||
void _kbfun_mediakey_press_release(keycode key,bool is_pressed);
|
||||
void _kbfun_normal_swap(keycode from,keycode to);
|
||||
void _kbfun_normal_press_release(keycode key,bool is_pressed);
|
||||
keycode kb_keycode(layer l,u8 row,u8 col);
|
||||
bool is_layer_keyfunc(keyfunc f);
|
||||
keyfunc kb_keyfunc(layer l,u8 row,u8 col);
|
||||
void layer_enable(layer l);
|
||||
layer highest_active_layer();
|
||||
void exec_key(layer layer,u8 row,u8 col,bool is_pressed);
|
||||
void layer_disable(layer l);
|
||||
void main_key_up(u8 row,u8 col);
|
||||
void main_key_down_repeat(u8 row,u8 col);
|
||||
void main_key_down_new(u8 row,u8 col);
|
||||
void main_key_loop();
|
||||
void init_timer();
|
||||
void init_sticky();
|
||||
void init_layers();
|
||||
void init_hw();
|
||||
int main();
|
||||
millis now();
|
||||
void kbfun_win_layer_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_alt_layer_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_control_layer_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_shift_layer_press_release(keycode key,bool is_pressed);
|
||||
void kbfun_layer_sticky(keycode key,bool is_pressed);
|
||||
void kbfun_layer_press_release(keycode key,bool is_pressed);
|
||||
|
|
147
src/makefile
147
src/makefile
|
@ -1,118 +1,42 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# makefile for the ergoDOX firmware
|
||||
#
|
||||
# - .h file dependencies are automatically generated
|
||||
#
|
||||
# - This makefile was originally (extensively) modified from the WinAVR
|
||||
# makefile template, mostly by removing stuff. The copy I used was from
|
||||
# [pjrc : usb_keyboard] (http://pjrc.com/teensy/usb_keyboard.zip).
|
||||
# -----------------------------------------------------------------------------
|
||||
# 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>
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
CFLAGS := -mmcu=atmega32u4 # processor type (teensy 2.0); must match real life
|
||||
CFLAGS += -DF_CPU=16000000 # processor frequency; must match initialization in source
|
||||
CFLAGS += -std=gnu99 # use C99 plus GCC extensions
|
||||
CFLAGS += -Os -flto # optimize for size
|
||||
CFLAGS += -Wall -Werror # enable lots of common warnings
|
||||
CFLAGS += -fpack-struct # pack all structure members together without holes
|
||||
CFLAGS += -fshort-enums # allocate compact enums
|
||||
CFLAGS += -ffunction-sections # \ place each function or data into its own
|
||||
CFLAGS += -fdata-sections # / section in the output file
|
||||
CFLAGS += -pipe # faster build
|
||||
LDFLAGS += -Wl,--relax # for some linker optimizations
|
||||
LDFLAGS += -Wl,--gc-sections # discard unused functions and data
|
||||
|
||||
include makefile-options
|
||||
|
||||
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)
|
||||
# keyboard and layout stuff
|
||||
# --- remove whitespace from vars
|
||||
KEYBOARD := $(strip $(KEYBOARD))
|
||||
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
|
||||
# compiled out. else, the makefile will have to become more complicated.
|
||||
SRC += $(wildcard lib/*.c)
|
||||
SRC += $(wildcard lib/*/*.c)
|
||||
SRC += $(wildcard lib/*/*/*.c)
|
||||
SRC += $(wildcard lib-other/*.c)
|
||||
SRC += $(wildcard lib-other/*/*.c)
|
||||
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 += -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
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
CFLAGS += -Wall # enable lots of common warnings
|
||||
CFLAGS += -Wstrict-prototypes # "warn if a function is declared or defined
|
||||
# without specifying the argument types"
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
CFLAGS += -fpack-struct # "pack all structure members together without holes"
|
||||
CFLAGS += -fshort-enums # "allocate to an 'enum' type only as many bytes as it
|
||||
# needs for the declared range of possible values"
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
CFLAGS += -ffunction-sections # \ "place each function or data into its own
|
||||
CFLAGS += -fdata-sections # / section in the output file if the
|
||||
# target supports arbitrary sections." for
|
||||
# linker optimizations, and discarding
|
||||
# unused code.
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
LDFLAGS := -Wl,-Map=$(strip $(TARGET)).map,--cref # generate a link map, with
|
||||
# a cross reference table
|
||||
LDFLAGS += -Wl,--relax # for some linker optimizations
|
||||
LDFLAGS += -Wl,--gc-sections # discard unused functions and data
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
GENDEPFLAGS += -MMD -MP -MF $@.dep # generate dependency files
|
||||
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
|
||||
CC := avr-gcc
|
||||
OBJCOPY := avr-objcopy
|
||||
SIZE := avr-size
|
||||
|
||||
|
||||
# remove whitespace from some of the options
|
||||
FORMAT := $(strip $(FORMAT))
|
||||
SRC := main.c
|
||||
|
||||
CC := avr-gcc
|
||||
OBJCOPY := avr-objcopy
|
||||
SIZE := avr-size
|
||||
CHKSUM := md5sum
|
||||
MAKEHEADERS := makeheaders
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(TARGET).hex $(TARGET).eep
|
||||
all: firmware.hex firmware.eep
|
||||
@echo
|
||||
@echo '---------------------------------------------------------------'
|
||||
@echo '------- done --------------------------------------------------'
|
||||
@echo
|
||||
$(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
$(SIZE) --target=ihex firmware.hex
|
||||
@echo
|
||||
$(SIZE) --target=$(FORMAT) $(TARGET).eep
|
||||
$(SIZE) --target=ihex firmware.eep
|
||||
@echo
|
||||
@echo 'you can load "$(TARGET).hex" and "$(TARGET).eep" onto the'
|
||||
@echo 'Teensy using the Teensy loader'
|
||||
$(CHKSUM) firmware.hex firmware.eep
|
||||
@echo
|
||||
@echo '---------------------------------------------------------------'
|
||||
@echo
|
||||
|
@ -120,42 +44,31 @@ all: $(TARGET).hex $(TARGET).eep
|
|||
clean:
|
||||
@echo
|
||||
@echo --- cleaning ---
|
||||
git clean -dX # remove ignored files and directories
|
||||
git clean -dX -f # remove ignored files and directories
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
.SECONDARY:
|
||||
|
||||
%.hex: %.elf
|
||||
firmware.hex: firmware.elf
|
||||
@echo
|
||||
@echo --- making $@ ---
|
||||
# from the WinAVR makefile template (modified)
|
||||
$(OBJCOPY) -O $(FORMAT) \
|
||||
$(OBJCOPY) -O ihex \
|
||||
-R .eeprom -R .fuse -R .lock -R .signature \
|
||||
$< $@
|
||||
|
||||
%.eep: %.elf
|
||||
firmware.eep: firmware.elf
|
||||
@echo
|
||||
@echo --- making $@ ---
|
||||
# from the WinAVR makefile template (modified)
|
||||
-$(OBJCOPY) -O $(FORMAT) \
|
||||
-$(OBJCOPY) -O ihex \
|
||||
-j .eeprom \
|
||||
--set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 \
|
||||
--no-change-warnings \
|
||||
$< $@ || exit 0
|
||||
|
||||
%.elf: $(OBJ)
|
||||
firmware.elf:
|
||||
@echo
|
||||
@echo --- making $@ ---
|
||||
$(CC) $(strip $(CFLAGS)) $(strip $(LDFLAGS)) $^ --output $@
|
||||
|
||||
%.o: %.c
|
||||
@echo
|
||||
@echo --- making $@ ---
|
||||
$(CC) -c $(strip $(CFLAGS)) $(strip $(GENDEPFLAGS)) $< -o $@
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
-include $(OBJ:%=%.dep)
|
||||
|
||||
$(MAKEHEADERS) $(SRC)
|
||||
$(CC) $(strip $(CFLAGS)) $(strip $(LDFLAGS)) $(SRC) --output $@
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
# -----------------------------------------------------------------------------
|
||||
# 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))
|
||||
|
Binary file not shown.
Loading…
Reference in New Issue