Compare commits

...

221 Commits

Author SHA1 Message Date
Stefan Dorn f9cd0f21d9 lol dumb solution that doesn't break 2017-02-14 16:34:00 +00:00
Stefan Dorn f287876aed fancy combo keys 2017-02-14 15:25:11 +00:00
Stefan Dorn a7c1e67a40 simple control+alt hack 2017-02-14 14:53:06 +00:00
Stefan Dorn 6e7dfe066d keys 2017-01-28 02:04:57 +00:00
Stefan Dorn 2039dedb6a remove debugs 2016-10-31 19:29:04 +00:00
Stefan Dorn 5947829da5 try not using sticky controls 2016-10-31 19:28:52 +00:00
Stefan Dorn f8edc016b2 don't use 32bit teensy 2016-10-30 11:19:17 +00:00
Stefan Dorn b970900306 do resend layer keys 2016-08-28 08:11:55 +01:00
Stefan Dorn 8199d8d21d refactor 2016-08-22 18:31:11 +01:00
Stefan Dorn 487f81b873 debug prep for key repeats 2016-08-22 18:12:42 +01:00
Stefan Dorn a051172412 usable workaround against shifted keys bleeding into next key 2016-08-22 17:26:44 +01:00
Stefan Dorn 24891b6108 cleanup 2016-08-22 16:28:10 +01:00
Stefan Dorn 6e94b69be4 prep for key repeats 2016-08-22 03:04:00 +01:00
Stefan Dorn b77b3ab00d fix matrix mapping 2016-08-22 00:35:57 +01:00
Stefan Dorn 058a7bc914 adopt fancier key syntax, and flip matrixes around 2016-08-21 23:50:03 +01:00
Stefan Dorn 2ed7e87cf1 remove up/down distinction in key layers 2016-08-21 19:32:32 +01:00
Stefan Dorn 1b5090f97a cleanup 2016-08-21 18:39:20 +01:00
Stefan Dorn 6534334973 prep for better layers 2016-08-21 18:25:08 +01:00
Stefan Dorn 2f2cac7dff note 2016-08-21 18:24:55 +01:00
Stefan Dorn 0af5332a59 align 2016-08-21 18:24:51 +01:00
Stefan Dorn 17dd157c1d cleanup 2016-08-09 16:13:24 +01:00
Stefan Dorn d722480b37 don't double-sticky 2016-08-09 16:13:13 +01:00
Stefan Dorn 5a33a1c21b re-break layer switches to unbreak repeats 2016-08-09 02:51:45 +01:00
Stefan Dorn fc3a0906f9 fix stickies 2016-08-09 01:49:27 +01:00
Stefan Dorn 3bfad0fb5c avoid layer inception 2016-08-09 01:11:31 +01:00
Stefan Dorn 20343f60b9 fix funcpunc problem 2016-08-09 00:57:15 +01:00
Stefan Dorn 9fc027ebbe get rid of global state 2016-08-09 00:40:48 +01:00
Stefan Dorn 5e9593a4a5 rewrite layer code 2016-08-08 23:23:04 +01:00
Stefan Dorn 70a8382000 fix debug_print 2016-08-08 20:35:00 +01:00
Stefan Dorn aff9a6b9cf tab key 2016-08-08 19:39:13 +01:00
Stefan Dorn 1de6d9e950 remove debug 2016-07-20 22:32:40 +01:00
Stefan Dorn b929617dae combo layer test 2016-07-20 22:32:15 +01:00
Stefan Dorn 11b79bcc8c combo with layers 2016-07-20 22:22:41 +01:00
Stefan Dorn e20ccf838d fix media keys 2016-07-08 09:39:40 +01:00
Stefan Dorn c2b44c7222 let modifiers unstick layers 2016-06-19 08:48:26 +01:00
Stefan Dorn dbbd699115 cleanup 2016-06-14 20:14:44 +01:00
Stefan Dorn a0289831c1 nkro interface (for later) 2016-06-14 13:52:48 +01:00
Stefan Dorn 90bb49c27d split {mod,layer}_sticky_on 2016-06-14 12:38:17 +01:00
Stefan Dorn e8c5f2a69d typo 2016-06-14 12:23:05 +01:00
Stefan Dorn f9a4c2551d default keyfuncs for keys 2016-06-14 11:57:20 +01:00
Stefan Dorn 2498833488 sticky cleanup 2016-06-14 11:45:57 +01:00
Stefan Dorn 270feb968a sticky modifier keys! 2016-06-14 11:34:43 +01:00
Stefan Dorn e293f31c04 cleanup 2016-06-14 11:34:35 +01:00
Stefan Dorn 6786b70ecc rework sticky layer keys 2016-06-14 10:51:17 +01:00
Stefan Dorn f52da5065a explicit modifiers 2016-06-14 09:39:45 +01:00
Stefan Dorn 9c81274348 refactor (and minor sticky bug) 2016-06-14 07:32:06 +01:00
Stefan Dorn 5dc33a30d0 refactor 2016-06-14 05:53:45 +01:00
Stefan Dorn 118f511e61 refactor 2016-06-14 05:48:02 +01:00
Stefan Dorn f5c1169af3 get rid of trans logic complete 2016-06-14 05:44:11 +01:00
Stefan Dorn bd74409688 cleanup 2016-06-14 05:20:32 +01:00
Stefan Dorn b4ab1b0a7c no leds 2016-06-14 05:04:25 +01:00
Stefan Dorn 39d4cf708a save some memory 2016-06-14 05:02:05 +01:00
Stefan Dorn 60e45f8444 refactor 2016-06-14 04:48:56 +01:00
Stefan Dorn b9678e3239 free memory usage 2016-06-14 01:49:07 +01:00
Stefan Dorn ec2820d15b more explicit types 2016-06-14 01:49:01 +01:00
Stefan Dorn 0f953d4d4a always store constant strings in PROGMEM 2016-06-14 00:38:22 +01:00
Stefan Dorn 5a651b2854 define debug_printf variant as well 2016-06-14 00:29:43 +01:00
Stefan Dorn 8748e15b59 comment 2016-06-13 23:42:34 +01:00
Stefan Dorn b5c9da488a make the whole debug interface conditional 2016-06-13 23:39:48 +01:00
Stefan Dorn 6a2057e1da hid_listen 2016-06-13 23:34:41 +01:00
Stefan Dorn 79cdf4f1f3 conditional debug 2016-06-13 23:31:20 +01:00
Stefan Dorn 01be9a4d7f some basic debug messages 2016-06-13 05:25:30 +01:00
Stefan Dorn fd9de01514 debug works! 2016-06-13 05:25:18 +01:00
Stefan Dorn 415e815f75 part of porting the debug interface from tmk 2016-06-12 08:55:16 +01:00
Stefan Dorn 79b747a5fe no muflax 2016-06-12 06:51:49 +01:00
Stefan Dorn 61a8817f2e get rid of transparent keys as part of the coming sticky cleanup 2016-06-12 06:44:09 +01:00
Stefan Dorn a812590707 cleanup 2016-06-12 06:09:57 +01:00
Stefan Dorn 789169a86f refactor 2016-06-12 05:26:27 +01:00
Stefan Dorn 2f2c3d6994 refactor 2016-06-12 05:20:40 +01:00
Stefan Dorn 445e25b01b refactor so we only use as many layers as we need 2016-06-12 05:04:40 +01:00
Stefan Dorn 91e2e9f41f minor cleanup 2016-06-12 04:39:06 +01:00
Stefan Dorn a57fdf7efd refactor 2016-06-12 04:09:35 +01:00
Stefan Dorn afc7d9f87c cleanup 2016-06-12 03:55:36 +01:00
Stefan Dorn cf032d1395 lto 2016-06-12 03:41:15 +01:00
Stefan Dorn 44d2566936 cleanup 2016-06-12 03:41:12 +01:00
Stefan Dorn 6ec9fcbb98 simplify includes 2016-06-12 03:34:29 +01:00
Stefan Dorn 03a84a272a -Werror 2016-06-12 03:10:33 +01:00
Stefan Dorn f5641c807e some cleanup 2016-06-12 03:08:50 +01:00
Stefan Dorn 238a98d6b6 refactor 2016-06-12 02:54:30 +01:00
Stefan Dorn 1b7a4b23fd simplify makefile 2016-06-12 01:56:10 +01:00
Stefan Dorn 070b4b2caa no more warnings and automatic headers 2016-06-12 01:31:58 +01:00
Stefan Dorn 923e8da156 refactor 2016-06-12 01:00:39 +01:00
Stefan Dorn ba59fee6f9 tree! 2016-06-12 00:58:43 +01:00
Stefan Dorn 2ff9c05a48 simpler makefile 2016-06-12 00:53:15 +01:00
Stefan Dorn 90bd7c9116 almost a tree now! 2016-06-12 00:51:39 +01:00
Stefan Dorn 2b98ca5f8d simplify dependency 2016-06-12 00:33:34 +01:00
Stefan Dorn 02b931fb8d set media keys for testing 2016-06-11 23:10:09 +01:00
Stefan Dorn 0f1d82f1f2 refactor 2016-06-11 23:06:09 +01:00
Stefan Dorn a244e9d58d refactor 2016-06-11 22:58:12 +01:00
Stefan Dorn e25b4b3bff refactor 2016-06-11 22:27:17 +01:00
Stefan Dorn 14d0d1cad6 refactor 2016-06-11 22:16:59 +01:00
Stefan Dorn 8344f05b60 refactor 2016-06-11 22:06:57 +01:00
Stefan Dorn c4399c1963 cleanup 2016-06-11 21:58:20 +01:00
Stefan Dorn b4c9342533 more cleanup 2016-06-11 21:42:22 +01:00
Stefan Dorn 0c141072da clean up header structure 2016-06-11 21:19:48 +01:00
Stefan Dorn 46b1493a07 md5sum 2016-06-11 20:26:01 +01:00
Stefan Dorn dea913d16e less nesting 2016-06-11 20:24:42 +01:00
Stefan Dorn c1cd739af2 less headers 2016-06-11 20:19:04 +01:00
Stefan Dorn e7221e5eab no more variable include 2016-06-11 20:16:11 +01:00
Stefan Dorn 3dda86dd7e remove useless headers 2016-06-11 20:13:46 +01:00
Stefan Dorn c8fd4b83e1 make f key available 2016-05-31 17:14:53 +01:00
Stefan Dorn ea97f185de trust layers_top so we don't disable a layer that was already off 2016-02-13 22:08:05 +00:00
Stefan Dorn b5f88d06f4 fix latch bug 2016-02-06 14:31:54 +00:00
Stefan Dorn 9da1313e70 cleanup 2016-02-06 14:31:45 +00:00
Stefan Dorn 4927d4de7a cleanup 2016-02-06 14:15:31 +00:00
Stefan Dorn 43e1cb309d speedup 2016-02-06 08:03:35 +00:00
Stefan Dorn cc8400f8c9 better layer functions that stack properly-ish 2016-02-04 16:38:33 +00:00
Stefan Dorn 8b78e8b3a4 simplify layer functions by using the keycode again 2016-02-04 15:28:11 +00:00
Stefan Dorn c88a558e8c more safety 2016-02-04 14:58:58 +00:00
Stefan Dorn 5419ab9d7a yes i can loops why 2016-02-04 14:19:14 +00:00
Stefan Dorn 37faadc8aa initialize layers to be safe 2016-02-04 14:19:06 +00:00
Stefan Dorn c08df8dc25 layers are a bit easier now 2016-02-04 14:18:46 +00:00
Stefan Dorn 43228a265a oops 2016-02-04 12:28:07 +00:00
Stefan Dorn d0f71834aa some cleanup 2016-02-04 11:24:51 +00:00
Stefan Dorn fc3259de73 minor refactor 2016-02-04 11:18:09 +00:00
Stefan Dorn fef0497fcf begin layer stacking refactor 2016-02-04 10:19:42 +00:00
Stefan Dorn ac64381896 better names 2016-02-04 10:09:07 +00:00
Stefan Dorn f9f5e4b5aa replace the stack with a flat array 2016-02-04 10:00:05 +00:00
Stefan Dorn c695c37c40 more refactor 2016-02-04 09:38:07 +00:00
Stefan Dorn e19ca08263 remove led code 2016-02-04 09:26:58 +00:00
Stefan Dorn d1c105848b remove old layouts 2016-02-04 09:26:41 +00:00
Stefan Dorn f0da34b909 more refactor 2016-02-04 09:22:40 +00:00
Stefan Dorn 01c9587d31 simplify layers 2016-02-04 08:42:22 +00:00
Stefan Dorn f3654c9fe0 more refactor 2016-02-04 07:47:22 +00:00
Stefan Dorn 447f1fb2cb begin major refactor to replace the layer stack 2016-02-04 06:43:33 +00:00
Stefan Dorn ccd324d972 cleanup 2016-02-04 06:34:57 +00:00
Stefan Dorn 5b65f3eb7c test keys for layout stacking debugs 2016-02-04 04:38:29 +00:00
Stefan Dorn 2159af0050 minor cleanup 2016-02-04 04:38:18 +00:00
Stefan Dorn e71b8fbeb0 simplify names 2016-02-04 04:27:48 +00:00
Stefan Dorn ec5eadf8a5 oops, forgot to commit last time 2016-01-26 15:34:20 +00:00
Stefan Dorn 068da79193 *all* media keys 2016-01-26 15:33:59 +00:00
Stefan Dorn 35bbc544bb ability to use media keys 2016-01-26 15:02:35 +00:00
Stefan Dorn 305ee97312 rename modifiers 2016-01-21 14:31:31 +00:00
Stefan Dorn 61e002128c add number keys on nav 2016-01-21 14:29:00 +00:00
Stefan Dorn 834553af50 fix sticky keys 2016-01-21 14:27:11 +00:00
Stefan Dorn f87e9ea538 Revert "use fancier? syntax"
This reverts commit 1f653839b4.
2016-01-21 14:26:08 +00:00
Stefan Dorn fecaf571c8 Revert "fix sticky keys"
This reverts commit ba20aaebfd.
2016-01-21 14:26:08 +00:00
Stefan Dorn ba20aaebfd fix sticky keys 2016-01-09 23:54:58 +00:00
Stefan Dorn 1f653839b4 use fancier? syntax 2016-01-09 23:45:04 +00:00
Stefan Dorn f7781d869c map f13-f24 for testing 2016-01-04 15:55:10 +00:00
Stefan Dorn 133f6823cf fix f14 and up 2016-01-04 15:55:00 +00:00
Stefan Dorn 2d1023cf42 alternative tab for bg2 2015-12-25 01:04:29 +00:00
Stefan Dorn 4764b3d363 fix broken latch 2015-12-17 21:17:09 +00:00
Stefan Dorn 8949922722 enter = return 2015-12-14 01:47:22 +00:00
Stefan Dorn fa72af8504 use generated layout 2015-12-14 01:23:58 +00:00
Stefan Dorn 3121420267 basic layout generator 2015-12-14 00:28:13 +00:00
Stefan Dorn 1cf945909d sipmlify base makefile 2015-12-09 10:46:03 +00:00
Stefan Dorn 7e97e541eb include teensy 2015-12-09 10:45:57 +00:00
Stefan Dorn 8b392e14fb control-del key 2015-12-09 10:20:56 +00:00
Stefan Dorn 3325dea1cf alternative alt position 2015-12-08 07:55:00 +00:00
Stefan Dorn cf1b23b36d fix empty key 2015-12-08 07:54:51 +00:00
Stefan Dorn 2091d368c8 reverse right side 2015-11-02 15:46:53 +00:00
Stefan Dorn 58ae2cd244 cuter name 2015-11-02 15:25:02 +00:00
Stefan Dorn 431f620d5b work identically on 80-key version 2015-11-02 15:24:46 +00:00
Stefan Dorn d9d7f242b2 try menu key 2015-08-29 09:53:29 +01:00
Stefan Dorn 565ea0a478 cleanup 2015-08-29 09:53:26 +01:00
Stefan Dorn b2c04fbbed space on mod3 2015-08-01 06:56:11 +01:00
Stefan Dorn c5b328ea67 put enter on keys 2015-07-30 09:06:22 +01:00
Stefan Dorn 312b996d1b a bit more natural arrow keys on the right 2015-07-25 22:42:11 +01:00
Stefan Dorn 68c4a67e65 ignore build 2015-07-25 14:14:43 +01:00
Stefan Dorn 3aee762143 duplicate arrow keys on the right 2015-07-23 20:24:52 +01:00
Stefan Dorn 1983339d01 fix altR 2015-07-22 22:06:34 +01:00
Stefan Dorn 5e62e82595 alternatives to the worst pinky keys 2015-07-22 22:04:15 +01:00
Stefan Dorn 884b5ab884 mod3 is ready 2015-07-22 22:01:29 +01:00
Stefan Dorn b4bb0ff792 move everything into hardware 2015-07-22 21:27:58 +01:00
Stefan Dorn fee69ebeaf fill in some unnecessary gaps 2015-07-22 19:37:11 +01:00
Stefan Dorn 9ce238017c setup mod3 on FN1 2015-07-22 18:51:53 +01:00
Stefan Dorn c0fabeae17 move mod4 into hardware 2015-07-21 08:58:59 +01:00
Stefan Dorn fac5d540d2 basic saneo layout 2015-07-20 19:43:50 +01:00
Ben Blazak 8fcfe6cb7e changing gen-ui-info.py per issue #19
some of the script's output won't be accurate anymore; but it's not data
that we actually need (and we haven't needed it for quite some time) so
that shouldn't bother anyone.  the generated keymap, assuming that still
works, should be fine though :)
2014-07-31 19:57:52 -07:00
Ben Blazak d4aa876851 (merging in a small update) 2014-04-12 14:48:11 -07:00
Ben Blazak ed0661e3f7 Merge pull request #41 from nacitar/master
Fixed media key support, cleaning, and added a workman-p layout
2014-04-12 14:47:52 -07:00
Ben Blazak 1f7cbbc345 updated notes 2014-04-12 14:46:01 -07:00
Jacob McIntosh 9fffce4cb8 Forgot to remove this. 2014-03-28 01:02:10 -05:00
Jacob McIntosh 03e1485587 Fixed comment. 2014-03-28 00:40:55 -05:00
Jacob McIntosh 535a67de5d Added comment mentioning only known bug. Minor. 2014-03-28 00:25:06 -05:00
Jacob McIntosh 3455d4a1d4 Removing +x from source files. 2014-03-27 12:12:31 -05:00
Jacob McIntosh 1fe98c0a74 Comment fixes. 2014-03-27 11:59:03 -05:00
Jacob McIntosh 6998047e2a Fixed repeating-mediakey bug, attempt fixing workman-P
Inverted shift code now moved to the layout.
2014-03-27 11:38:42 -05:00
Jacob McIntosh b1c85b73fe Added volume media keys, fixed workman-p layout, added two todo's 2014-03-27 07:15:02 -05:00
Jacob McIntosh 84a6d90a7b Comment tweaks. 2014-03-26 15:01:41 -05:00
Jacob McIntosh 3c1c86f3ae Adding workman-p-kinesis-mod layout. 2014-03-14 15:48:59 -05:00
Jacob McIntosh 7fe2b46280 Added -f to clean command, so it actually cleans. 2014-03-14 15:48:34 -05:00
Jacob McIntosh 971eb539aa Added missing MEDIAKEY_STOP entry (TRANSPORT_STOP was already present). 2014-03-14 15:43:17 -05:00
Ben Blazak 1a38c77ee8 fixed small typo (thanks Rema!) 2013-10-21 10:24:12 -07:00
Ben Blazak a518081a74 readme update 2013-09-04 15:22:28 -07:00
Ben Blazak 9da485a171 Update readme.md 2013-08-03 14:39:12 -07:00
Ben Blazak c75296f455 top level readme: header update 2013-08-03 14:22:26 -07:00
Ben Blazak 60c20b9cb1 updated readme 2013-05-05 18:40:32 -07:00
Ben Blazak f99101c1a0 Merge pull request #23 from judascleric/master
adding media key support
2013-05-05 18:25:20 -07:00
Ben Blazak 65ac90f730 updated readme 2013-04-19 17:04:57 -07:00
Ryan Prince 513b82d585 adding media keys
taken from Hasu codebase (https://github.com/tmk/tmk_keyboard) usb.c/.h
and usb_extra.c/.h, though these files only have the PJRC
copyright/license in the header
2013-04-14 00:29:47 -07:00
Ryan Prince 45c901c308 usb_extra.c now compiles 2013-04-13 16:33:30 -07:00
Ryan Prince ed37259e69 adding usb_extra.c/.h from Hasu's tmk code. Won't compile as is. 2013-04-13 09:52:49 -07:00
Ryan Prince 16992c2ea2 small layout change to move backspace, remove delete, and add tab on layer1 2013-04-13 09:45:43 -07:00
Ben Blazak cbf42d9eb4 (minor) 2013-04-10 23:26:15 -07:00
Ben Blazak 6d48149b5e updated toplevel readme 2013-04-10 23:24:31 -07:00
Ben Blazak 1e9ebe4ece Merge pull request #22 from judascleric/master
sticky key support
2013-04-10 21:57:55 -07:00
Ryan Prince 3008a6d759 removed TODO comment and readded deleted whitespace as per code review comments 2013-04-10 13:23:26 -07:00
Ryan Prince 22e1965902 added a created by line per code review comments and moved the configurator link to come after the description 2013-04-10 13:22:50 -07:00
Ryan Prince 2c39db717a adding layout description and updated layout. removing unused layers 2013-04-10 13:15:32 -07:00
Ryan Prince 26b46ac7d3 Swapping layer 2 sticky and layer 2 toggle keys. Now that sticky works
as desired, it is possible to hold the sticky key down for short number
runs and it is now a more frequently used key that toggle. Also added
notes about mac keycodes that I found in search of play/next/prev
buttons. I suspect that codes need to be inserted into the USB data
stream to indicate that a media key is being pressed.
2013-04-09 11:56:25 -07:00
Ryan Prince 2cd405ad08 checking in my layout file as an example of sticky key usage 2013-04-08 11:55:38 -07:00
Ryan Prince ce4495372c caching the transparent key pressed result to fix sticky key bug
the behavior for transparent keys not affecting sticky key state was
broken because kbfun_transparent() was only getting called for key
press and not for key release because the layer for the key was cached
on keypress. By caching the transparent key press result on key press
we can ensure that the main_arg_trans_key_pressed is set correctly for
any key function called on key release
2013-04-08 11:51:01 -07:00
Ryan Prince 4e56966795 fixing bug/adding function for sticky key behavior - kbfun_press_release_preserve_sticky()
kbfun_press_release_preserve_sticky() is meant to replace
kbfun_press_release as the function used for standard modifiers (shift,
control, alt, and gui) so that the sticky state is preserved and it is
possible to key in chorded commands using a key on another layer
pressing the keys in the chord one key at a time simultaneously without
breaking the sticky state. (e.g. ctrl+F2 as lsticky2, ctrl, x [where x
is defined as F2 on layer 2]

TODO: Noticed a bug where the transparent behavior does not work as
expected for modifiers. lsticky2, ctrl, x does not produce ctrl+F2 when
ctrl is defined as transparent on layer 2 and keycode=ctrl,
press=kprrel, release=kprrel on layer 0.
2013-04-08 10:54:49 -07:00
Ryan Prince eb24aef2d5 cleaning up local changes to prep the sticky keys change for a pull request 2013-04-08 08:49:58 -07:00
Ryan Prince 208aad93d3 Revert "adding local makefile changes"
This reverts commit d88b55a6d9.
2013-04-08 08:48:46 -07:00
Ryan Prince 15a91f7b05 fixing a bug in sticky key one time state behavior, cleaning up a comment, and making braces style consistent with the rest of the code.
sticky layers in the one time state were being popped anytime
kbfun_press_release() was called, which should only happen if the key
was defined for the sticky layer, i.e. kbfun_transparent() was not the
first function mapped to that key in the topmost layer.
2013-04-08 08:46:25 -07:00
Ryan Prince 2d5c6084c0 removing sticky off state, it is never used because off means the layer was popped 2013-04-08 00:56:06 -07:00
Ryan Prince d88b55a6d9 adding local makefile changes 2013-04-08 00:49:59 -07:00
Ryan Prince f2d650b996 adding sticky key functionality
This function gives similar behavior to sticky keys for modifiers
available on most operating systems. It is considered an accessibility
feature because it alleviates the user from having to hold down
modifiers while pressing a key to produce the modified key function. It
is useful for fast touch typing because you can avoid chording motions
which both strain your hands and take your hands out of home-row
position while pressing normal alpha keys.

This function emulates the 3-state behavior which is default on OS X
and optional in Windows where the modifier cycles between
Off->Once->Locked states. This is particularly handy for symbol layers
where you typically only type one symbol before you want to return to
unmodified typing (layer 0), e.g. 'if (condition) { a = "b" + "c"; }'.
If you assign a symbol layer to a thumb key as a layer sticky cycle,
you can type the entire line of code without taking your hands out of
home row position and you do not need to toggle off the layer after
each symbol is pressed, only immediately before keying the symbol.

The exact behavior of the layer sticky cycle function is defined as
follows for each state:
1) One time down (set on key press) - The layer was not active and the
key has been pressed but not yet released. The layer is pushed in the
one time down state.
2) One time up (set on key release) - The layer was active when the
layer sticky key was released. If a key on this layer (not set to
transparent) was pressed before the key was released, the layer will be
popped. If a non-transparent key was not pressed, the layer is popped
and pushed again in the one time up state.
3) Locked (set on key press) - The layer was active and in the one time
up state when the layer sticky key was pressed again. The layer will be
popped if the function is invoked on a subsequent keypress.
2013-04-08 00:49:35 -07:00
Ben Blazak 43ee200b2b added toc in readme.md 2012-12-20 16:34:08 -08:00
Ben Blazak a03263d83b revised the readme 2012-12-20 16:29:31 -08:00
Ben Blazak 6c3a7951b1 changed the generated .zip filename back... lol
i like the original one better. i'll find another way to make the
filenames small for the most current ones on dropbox, so that they're
easy for people to find.
2012-12-20 15:42:10 -08:00
Ben Blazak 721f56588b changed filename of output .zip files 2012-12-20 15:38:21 -08:00
Ben Blazak 08101371e7 Merge branch 'dev' 2012-12-20 00:24:43 -08:00
Ben Blazak d120a0744f Merge branch 'dev' 2012-12-11 18:33:24 -08:00
Ben Blazak 89d8df652e Merge branch 'dev' 2012-12-11 18:28:33 -08:00
Ben Blazak 4810bac2a0 Merge branch 'dev' 2012-12-11 17:59:29 -08:00
Ben Blazak 2aab399a6f Merge branch 'dev' 2012-12-11 17:21:08 -08:00
Ben Blazak 37b425a738 improved toplevel build script output; added colemak
Merge branch 'dev'

still a candidate for release with keyboard :) -- still -- gona stop
saying that with every merge, lol

- the svg/html output that documents the layout looks a lot better now
- merged in a colemak layout from jjt on github
- made a make target in the toplevel to make it easy for me to generate
  a sepatate .hex file for every layout (for posting to the downloads
  page)
2012-12-11 16:46:54 -08:00
70 changed files with 5273 additions and 8966 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -1,423 +0,0 @@
#! /usr/bin/env python3
# -----------------------------------------------------------------------------
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
# Released under The MIT License (MIT) (see "license.md")
# Project located at <https://github.com/benblazak/ergodox-firmware>
# -----------------------------------------------------------------------------
"""
Generate a depiction of the layout (in html + svg)
Depends on:
- the UI info file (in JSON)
"""
# -----------------------------------------------------------------------------
import argparse
import json
import os
import re
import sys
# -----------------------------------------------------------------------------
class Namespace():
pass
template = Namespace()
doc = Namespace()
info = Namespace()
# -----------------------------------------------------------------------------
def main():
arg_parser = argparse.ArgumentParser(
description = "Generate a picture of the firmware's "
+ "keyboard layout" )
arg_parser.add_argument(
'--ui-info-file',
required = True )
args = arg_parser.parse_args(sys.argv[1:])
# constant file paths
args.template_svg_file = './build-scripts/gen_layout/template.svg'
args.template_js_file = './build-scripts/gen_layout/template.js'
# normalize paths
args.ui_info_file = os.path.abspath(args.ui_info_file)
args.template_svg_file = os.path.abspath(args.template_svg_file)
args.template_js_file = os.path.abspath(args.template_js_file)
# set vars
doc.main = '' # to store the html document we're generating
template.svg = open(args.template_svg_file).read()
template.js = open(args.template_js_file).read()
info.all = json.loads(open(args.ui_info_file).read())
info.matrix_positions = info.all['mappings']['matrix-positions']
info.matrix_layout = info.all['mappings']['matrix-layout']
# prefix
doc.prefix = ("""
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<html>
<head>
<script>
"""
+ template.js +
""" </script>
</head>
<body>
<h1>Firmware Layout</h1>
<ul>
<li>git commit date:
<code>""" + info.all['miscellaneous']['git-commit-date'] + """</code></li>
<li>git commit id:
<code>""" + info.all['miscellaneous']['git-commit-id'] + """</code></li>
</ul>
<h2>Notes</h2>
<ul>
<li>Layer keys are labeled e.g. <code>la 2 +- 2</code>
<ul>
<li><code>la</code> is for "layer"</li>
<li><code>2</code> indicates that the second pair of push|pop functions is
being used (differently numbered pairs won't interfere with each
other)</li>
<li><code>+</code> indicates that the layer is being "pushed" onto the
stack at some point, either when the key is pressed or when it is
released</li>
<li><code>-</code> indicates that the layer is being "popped" off of the
stack at some point</li>
<li>the last <code>2</code> indicates the layer-number that will be
activated on "push".</li>
</ul>
See the project 'readme.md' file on <a
href='https://github.com/benblazak/ergodox-firmware'>the github page</a> as a
starting point for learning more about how this firmware implements
layers.</li>
<br>
<li>Shifted keys are labeled with an <code>sh</code> at the beginning. This
indicates that a 'Shift' is generated with that keypress, the same as if you
had held down 'Shift', and pressed that key.</li>
<br>
<li><code>(null)</code> indicates that no keypress or keyrelease will be
generated for that key, on that layer.</li>
<br>
<li>Blank keys indicate "transparency": if you press that key on that layer,
the key will act as if it was on whatever layer is active below the current
one.</li>
<br>
<li>Some keys may be labled with special functions (like
<code>[btldr]</code>, which tells the Teensy to wait for the host to send it
a new firmware).</li>
</ul>
<br>
""")[1:-1]
# suffix
doc.suffix = ("""
</body>
</html>
""")[1:-1]
# substitute into template
# -------
# note: this is not general enough to handle any possible layout well, at
# the moment. but it should handle more standard ones well. (hopefully
# minor) modifications may be necessary on a case by case basis
# -------
layer_number = -1
for (layout, layer) in zip( info.matrix_layout,
range(len(info.matrix_layout))):
layer_number += 1
svg = template.svg
for (name, (code, press, release)) \
in zip(info.matrix_positions, layout):
replace = ''
if press == 'kbfun_transparent':
replace = ''
elif press == 'kbfun_shift_press_release':
replace = 'sh ' + keycode_to_string.get(code, '[n/a]')
elif press == 'kbfun_jump_to_bootloader':
replace = '[btldr]'
elif press == 'NULL' and release == 'NULL':
replace = '(null)'
elif re.search(r'numpad', press+release):
replace = '[num]'
elif re.search(r'layer', press+release):
replace = 'la ' + re.findall(r'\d+', press+release)[0] + ' '
if re.search(r'push', press+release):
replace += '+'
if re.search(r'pop', press+release):
replace += '-'
replace += ' ' + str(code)
else:
replace = keycode_to_string.get(code, '[n/a]')
svg = re.sub(
'>'+name+'<', '>'+replace+'<', svg )
svg = re.sub(
r"\('(" + name + r".*)'\)",
r"('\1', " + str(layer) + r")",
svg )
doc.main += '<h2>Layer ' + str(layer_number) + '</h2>\n' + svg
# change the font size
doc.main = re.sub(r'22.5px', '15px', doc.main)
print(doc.prefix + doc.main + doc.suffix)
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
keycode_to_string = {
0x01: "Error", # ErrorRollOver
0x02: "POSTFail",
0x03: "Error", # ErrorUndefined
0x04: "a A",
0x05: "b B",
0x06: "c C",
0x07: "d D",
0x08: "e E",
0x09: "f F",
0x0A: "g G",
0x0B: "h H",
0x0C: "i I",
0x0D: "j J",
0x0E: "k K",
0x0F: "l L",
0x10: "m M",
0x11: "n N",
0x12: "o O",
0x13: "p P",
0x14: "q Q",
0x15: "r R",
0x16: "s S",
0x17: "t T",
0x18: "u U",
0x19: "v V",
0x1A: "w W",
0x1B: "x X",
0x1C: "y Y",
0x1D: "z Z",
0x1E: "1 !",
0x1F: "2 @",
0x20: "3 #",
0x21: "4 $",
0x22: "5 %",
0x23: "6 ^",
0x24: "7 &",
0x25: "8 *",
0x26: "9 (",
0x27: "0 )",
0x28: "Return",
0x29: "Esc",
0x2A: "Backspace",
0x2B: "Tab",
0x2C: "Space",
0x2D: "- _",
0x2E: "= +",
0x2F: "[ {",
0x30: "] }",
0x31: "\ |",
0x32: "# ~",
0x33: "; :",
0x34: "\' \"",
0x35: "` ~",
0x36: ", <",
0x37: ". >",
0x38: "/ ?",
0x39: "Caps",
0x3A: "F1",
0x3B: "F2",
0x3C: "F3",
0x3D: "F4",
0x3E: "F5",
0x3F: "F6",
0x40: "F7",
0x41: "F8",
0x42: "F9",
0x43: "F10",
0x44: "F11",
0x45: "F12",
0x46: "PrintScreen",
0x47: "ScrollLock",
0x48: "Pause",
0x49: "Ins", # Insert
0x4A: "Hm", # Home
0x4B: "Pg\u2191", # up arrow
0x4C: "Delete",
0x4D: "End",
0x4E: "Pg\u2193", # down arrow
0x4F: "\u2192", # right arrow
0x50: "\u2190", # left arrow
0x51: "\u2193", # down arrow
0x52: "\u2191", # up arrow
0x53: "Num",
0x54: "/",
0x55: "*",
0x56: "-",
0x57: "+",
0x58: "Enter",
0x59: "1 End",
0x5A: "2 \u2193", # down arrow
0x5B: "3 Pg\u2193", # down arrow
0x5C: "4 \u2190", # left arrow
0x5D: "5",
0x5E: "6 \u2192", # right arrow
0x5F: "7 Hm", # Home
0x60: "8 \u2191", # up arrow
0x61: "9 Pg\u2191", # up arrow
0x62: "0 Ins", # Insert
0x63: ". Del",
0x64: "\ |",
0x65: "App",
0x66: "Power",
0x67: "=",
0x68: "F13",
0x69: "F14",
0x6A: "F15",
0x6B: "F16",
0x6C: "F17",
0x6D: "F18",
0x6E: "F19",
0x6F: "F20",
0x70: "F21",
0x71: "F22",
0x72: "F23",
0x73: "F24",
0x74: "Exec",
0x75: "Help",
0x76: "Menu",
0x77: "Select",
0x78: "Stop",
0x79: "Again",
0x7A: "Undo",
0x7B: "Cut",
0x7C: "Copy",
0x7D: "Paste",
0x7E: "Find",
0x7F: "Mute",
0x80: "VolUp",
0x81: "VolDown",
0x82: "LockingCapsLock",
0x83: "LockingNumLock",
0x84: "LockingScrollLock",
0x85: ",",
0x86: "=",
0x87: "Int1",
0x88: "Int2",
0x89: "Int3",
0x8A: "Int4",
0x8B: "Int5",
0x8C: "Int6",
0x8D: "Int7",
0x8E: "Int8",
0x8F: "Int9",
0x90: "LANG1",
0x91: "LANG2",
0x92: "LANG3",
0x93: "LANG4",
0x94: "LANG5",
0x95: "LANG6",
0x96: "LANG7",
0x97: "LANG8",
0x98: "LANG9",
0x99: "AlternateErase",
0x9A: "SysReq_Attention",
0x9B: "Cancel",
0x9C: "Clear",
0x9D: "Prior",
0x9E: "Return",
0x9F: "Separator",
0xA0: "Out",
0xA1: "Oper",
0xA2: "Clear_Again",
0xA3: "CrSel_Props",
0xA4: "ExSel",
0xB0: "00",
0xB1: "000",
0xB2: "Thousands_Sep",
0xB3: "Decimal_Sep",
0xB4: "$",
0xB5: "Currency_Subunit",
0xB6: "(",
0xB7: ")",
0xB8: "{",
0xB9: "}",
0xBA: "Tab",
0xBB: "Backspace",
0xBC: "A",
0xBD: "B",
0xBE: "C",
0xBF: "D",
0xC0: "E",
0xC1: "F",
0xC2: "XOR",
0xC3: "^",
0xC4: "%",
0xC5: "<",
0xC6: ">",
0xC7: "&",
0xC8: "&&",
0xC9: "|",
0xCA: "||",
0xCB: ":",
0xCC: "#",
0xCD: "Space",
0xCE: "@",
0xCF: "!",
0xD0: "Mem_Store",
0xD1: "Mem_Recall",
0xD2: "Mem_Clear",
0xD3: "Mem_+",
0xD4: "Mem_-",
0xD5: "Mem_*",
0xD6: "Mem_/",
0xD7: "+-",
0xD8: "Clear",
0xD9: "ClearEntry",
0xDA: "Binary",
0xDB: "Octal",
0xDC: ".",
0xDD: "Hexadecimal",
0xE0: "L-Ctrl",
0xE1: "L-Shift",
0xE2: "L-Alt",
0xE3: "L-GUI",
0xE4: "R-Ctrl",
0xE5: "R-Shift",
0xE6: "R-Alt",
0xE7: "R-GUI",
}
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
if __name__ == '__main__':
main()

View File

@ -1,475 +0,0 @@
#! /usr/bin/env python3
# -----------------------------------------------------------------------------
# Copyright (c) 2012 Ben Blazak <benblazak.dev@gmail.com>
# Released under The MIT License (MIT) (see "license.md")
# Project located at <https://github.com/benblazak/ergodox-firmware>
# -----------------------------------------------------------------------------
"""
Generate UI info file (in JSON)
Depends on:
- the project source code
- the project '.map' file (generated by the compiler)
"""
_FORMAT_DESCRIPTION = ("""
/* ----------------------------------------------------------------------------
* Version 0
* ----------------------------------------------------------------------------
* Hopefully the add-hoc conventions are clear enough... I didn't feel like
* investing the time in making it a real JSON Schema when there aren't many
* validators, and the most current completed draft at the moment (draft 3) is
* expired...
* ----------------------------------------------------------------------------
* Please note that in general, fields may be added without changing the
* version number, and that programs using this format are not required to fill
* (or read) any of the given fields.
* ------------------------------------------------------------------------- */
var ui_info = {
".meta-data": { // for the JSON file
"version": "<number>",
"date-generated": "<string>", // format: RFC 3339
"description": "<string>",
},
"keyboard-functions": {
"<(function name)>": {
"position": "<number>", // as given by the .map file
"length": "<number>", // as given by the .map file
"comments": {
"name": "<string>", // more user friendly name
"description": "<string>",
"notes": [
"<string>",
"..."
],
"..."
}
},
"..."
},
"layout-matrices": {
"<(matrix name)>": {
"position": "<number>", // as given by the .map file
"length": "<number>" // as given by the .map file
},
"..."
},
"mappings": {
/*
* The mappings prefixed with 'matrix' have their elements in the same
* order as the .hex file (whatever order that is). The mappings
* prefixed with 'physical' will have their elements in an order
* corresponding to thier physical position on the keyboard. You can
* convert between the two using the relative positions of the key-ids
* in 'physical-positions' and 'matrix-positions'.
*
* The current order of 'physical' mappings is:
* --------------------------------------------
* // left hand, spatial positions
* 00, 01, 02, 03, 04, 05, 06,
* 07, 08, 09, 10, 11, 12, 13,
* 14, 15, 16, 17, 18, 19,
* 20, 21, 22, 23, 24, 25, 26,
* 27, 28, 29, 30, 31,
* 32, 33,
* 34, 35, 36,
* 37, 38, 39,
* // right hand, spatial positions
* 40, 41, 42, 43, 44, 45, 46,
* 47, 48, 49, 50, 51, 52, 53,
* 54, 55, 56, 57, 58, 59,
* 60, 61, 62, 63, 64, 65, 66,
* 67, 68, 69, 70, 71,
* 72, 73,
* 74, 75, 76,
* 77, 78, 79,
* --------------------------------------------
*/
"physical-positions": [ // list of key-ids
"<string>", "..."
],
"matrix-positions": [ // list of key-ids
"<string>", "..."
],
"matrix-layout": [
[ // begin layer
[ // begin key
"<number>", // keycode
"<string>", // press function name (ex: 'kbfun_...')
"<string>" // release function name (ex: 'NULL')
],
"..." // more keys
],
"..." // more layers
]
},
"miscellaneous": {
"git-commit-date": "<string>", // format: RFC 3339
"git-commit-id": "<string>",
"number-of-layers": "<number>"
}
}
""")[1:-1]
# -----------------------------------------------------------------------------
import argparse
import json
import os
import re
import subprocess
import sys
# -----------------------------------------------------------------------------
def gen_static(current_date=None, git_commit_date=None, git_commit_id=None):
"""Generate static information"""
return {
'.meta-data': {
'version': 0, # the format version number
'date-generated': current_date,
'description': _FORMAT_DESCRIPTION,
},
'miscellaneous': {
'git-commit-date': git_commit_date, # should be passed by makefile
'git-commit-id': git_commit_id, # should be passed by makefile
},
}
def gen_derived(data):
"""
Generate derived information
Should be called last
"""
return {
'miscellaneous': {
'number-of-layers':
int( data['layout-matrices']['_kb_layout']['length']/(6*14) ),
# because 6*14 is the number of bytes/layer for '_kb_layout'
# (which is a uint8_t matrix)
},
}
# -----------------------------------------------------------------------------
def parse_mapfile(map_file_path):
"""Parse the '.map' file"""
def parse_keyboard_function(f, line):
"""Parse keyboard-functions in the '.map' file"""
search = re.search(r'(0x\S+)\s+(0x\S+)', next(f))
position = int( search.group(1), 16 )
length = int( search.group(2), 16 )
search = re.search(r'0x\S+\s+(\S+)', next(f))
name = search.group(1)
return {
'keyboard-functions': {
name: {
'position': position,
'length': length,
},
},
}
def parse_layout_matrices(f, line):
"""Parse layout matrix information in the '.map' file"""
name = re.search(r'.progmem.data.(_kb_layout\S*)', line).group(1)
search = re.search(r'(0x\S+)\s+(0x\S+)', next(f))
position = int( search.group(1), 16 )
length = int( search.group(2), 16 )
return {
'layout-matrices': {
name: {
'position': position,
'length': length,
},
},
}
# --- parse_mapfile() ---
# normalize paths
map_file_path = os.path.abspath(map_file_path)
# check paths
if not os.path.exists(map_file_path):
raise ValueError("invalid 'map_file_path' given")
output = {}
f = open(map_file_path)
for line in f:
if re.search(r'^\s*\.text\.kbfun_', line):
dict_merge(output, parse_keyboard_function(f, line))
elif re.search(r'^\s*\.progmem\.data.*layout', line):
dict_merge(output, parse_layout_matrices(f, line))
return output
def find_keyboard_functions(source_code_path):
"""Parse all files in the source directory"""
def read_comments(f, line):
"""
Read in properly formatted multi-line comments
- Comments must start with '/*' and end with '*/', each on their own
line
"""
comments = ''
while(line.strip() != r'*/'):
comments += line[2:].strip()+'\n'
line = next(f)
return comments
def parse_comments(comments):
"""
Parse an INI style comment string
- Fields begin with '[field-name]', and continue until the next field,
or the end of the comment
- Fields '[name]', '[description]', and '[note]' are treated specially
"""
def add_field(output, field, value):
"""Put a field+value pair in 'output', the way we want it, if the
pair is valid"""
value = value.strip()
if field is not None:
if field in ('name', 'description'):
if field not in output:
output[field] = value
else:
if field == 'note':
field = 'notes'
if field not in output:
output[field] = []
output[field] += [value]
# --- parse_comments() ---
output = {}
field = None
value = None
for line in comments.split('\n'):
line = line.strip()
if re.search(r'^\[.*\]$', line):
add_field(output, field, value)
field = line[1:-1]
value = None
else:
if value is None:
value = ''
if len(value) > 0 and value[-1] == '.':
line = ' '+line
value += ' '+line
add_field(output, field, value)
return output
def parse_keyboard_function(f, line, comments):
"""Parse keyboard-functions in the source code"""
search = re.search(r'void\s+(kbfun_\S+)\s*\(void\)', line)
name = search.group(1)
return {
'keyboard-functions': {
name: {
'comments': parse_comments(comments),
},
},
}
# --- find_keyboard_functions() ---
# normalize paths
source_code_path = os.path.abspath(source_code_path)
# check paths
if not os.path.exists(source_code_path):
raise ValueError("invalid 'source_code_path' given")
output = {}
for tup in os.walk(source_code_path):
for file_name in tup[2]:
# normalize paths
file_name = os.path.abspath( os.path.join( tup[0], file_name ) )
# ignore non '.c' files
if file_name[-2:] != '.c':
continue
f = open(file_name)
comments = ''
for line in f:
if line.strip() == r'/*':
comments = read_comments(f, line)
elif re.search(r'void\s+kbfun_\S+\s*\(void\)', line):
dict_merge(
output,
parse_keyboard_function(f, line, comments) )
return output
def gen_mappings(matrix_file_path, layout_file_path):
# normalize paths
matrix_file_path = os.path.abspath(matrix_file_path)
layout_file_path = os.path.abspath(layout_file_path)
def parse_matrix_file(matrix_file_path):
match = re.search( # find the whole 'KB_MATRIX_LAYER' macro
r'#define\s+KB_MATRIX_LAYER\s*\(([^)]+)\)[^{]*\{\{([^#]+)\}\}',
open(matrix_file_path).read() )
return {
"mappings": {
"physical-positions": re.findall(r'k..', match.group(1)),
"matrix-positions": re.findall(r'k..|na', match.group(2)),
},
}
def parse_layout_file(layout_file_path):
match = re.findall( # find each whole '_kb_layout*' matrix definition
r'(_kb_layout\w*)[^=]*=((?:[^{}]*\{){3}[^=]*(?:[^{}]*\}){3})',
subprocess.getoutput("gcc -E '"+layout_file_path+"'") )
layout = {}
# collect all the values
for (name, matrix) in match:
layout[name] = [
re.findall( # find all numbers and function pointers
r'[x0-9A-F]+|&\w+|NULL',
re.sub( # replace '((void *) 0)' with 'NULL'
r'\(\s*\(\s*void\s*\*\s*\)\s*0\s*\)',
'NULL',
el ) )
for el in
re.findall( # find each whole layer
r'(?:[^{}]*\{){2}((?:[^}]|\}\s*,)+)(?:[^{}]*\}){2}',
matrix ) ]
# make the numbers into actual numbers
layout['_kb_layout'] = \
[[eval(el) for el in layer] for layer in layout['_kb_layout']]
# remove the preceeding '&' from function pointers
for matrix in ('_kb_layout_press', '_kb_layout_release'):
layout[matrix] = \
[ [re.sub(r'&', '', el) for el in layer]
for layer in layout[matrix] ]
return {
"mappings": {
"matrix-layout":
# group them all properly
[ [[c, p, r] for (c, p, r) in zip(code, press, release)]
for (code, press, release) in
zip( layout['_kb_layout'],
layout['_kb_layout_press'],
layout['_kb_layout_release'] ) ]
},
}
return dict_merge(
parse_matrix_file(matrix_file_path),
parse_layout_file(layout_file_path) )
# -----------------------------------------------------------------------------
def dict_merge(a, b):
"""
Recursively merge two dictionaries
- I was looking around for an easy way to do this, and found something
[here]
(http://www.xormedia.com/recursively-merge-dictionaries-in-python.html).
This is pretty close, but i didn't copy it exactly.
"""
if not isinstance(a, dict) or not isinstance(b, dict):
return b
for (key, value) in b.items():
if key in a:
a[key] = dict_merge(a[key], value)
else:
a[key] = value
return a
# -----------------------------------------------------------------------------
def main():
arg_parser = argparse.ArgumentParser(
description = 'Generate project data for use with the UI' )
arg_parser.add_argument(
'--current-date',
help = ( "should be in the format rfc-3339 "
+ "(e.g. 2006-08-07 12:34:56-06:00)" ),
required = True )
arg_parser.add_argument(
'--git-commit-date',
help = ( "should be in the format rfc-3339 "
+ "(e.g. 2006-08-07 12:34:56-06:00)" ),
required = True )
arg_parser.add_argument(
'--git-commit-id',
help = "the git commit ID",
required = True )
arg_parser.add_argument(
'--map-file-path',
help = "the path to the '.map' file",
required = True )
arg_parser.add_argument(
'--source-code-path',
help = "the path to the source code directory",
required = True )
arg_parser.add_argument(
'--matrix-file-path',
help = "the path to the matrix file we're using",
required = True )
arg_parser.add_argument(
'--layout-file-path',
help = "the path to the layout file we're using",
required = True )
args = arg_parser.parse_args(sys.argv[1:])
output = {}
dict_merge( output, gen_static( args.current_date,
args.git_commit_date,
args.git_commit_id ) )
dict_merge(output, parse_mapfile(args.map_file_path))
dict_merge(output, find_keyboard_functions(args.source_code_path))
dict_merge(output, gen_mappings( args.matrix_file_path,
args.layout_file_path ))
dict_merge(output, gen_derived(output))
print(json.dumps(output, sort_keys=True, indent=4))
# -----------------------------------------------------------------------------
if __name__ == '__main__':
main()

View File

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

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 94 KiB

View File

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

700
generate_layout.rb Executable file
View File

@ -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
Lno ___ __ Ln4 ___ __ Ln3 ___ __ Ln2 ___ __ Ln1 ___ __ Ln0 ___ __ Lnd ___ __
_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
Lto ___ __ Lt4 ___ __ Lt3 ___ __ Lt2 ___ __ Lt1 ___ __ Lt0 ___ __ Ltd ___ __
_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
Lho ___ __ Lh4 ___ __ Lh3 ___ __ Lh2 ___ __ Lh1 ___ __ Lh0 ___ __
_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
Lbo ___ __ Lb4 ___ __ Lb3 ___ __ Lb2 ___ __ Lb1 ___ __ Lb0 ___ __ Lbd ___ __
_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
Luo ___ __ Lu4 ___ __ Lu3 ___ __ Lu2 ___ __ Lu1 ___ __
_LB a-< a-^ a-v a-> W
_LP
_LN
_LF
_LD
Lzb ___ __ Lzc ___ __
_LB esc SCL
_LP
_LN
_LF
_LD
Lya ___ __ Lyb ___ __ Lyc ___ __
_LB spc C A
_LP
_LN
_LF
_LD
Lxa ___ __ Lxb ___ __ Lxc ___ __
_LB spc C A
_LP
_LN
_LF
_LD
EOL
right =<<EOL
Rnd ___ __ Rn0 ___ __ Rn1 ___ __ Rn2 ___ __ Rn3 ___ __ Rn4 ___ __ Rno ___ __
_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
Rtd ___ __ Rt0 ___ __ Rt1 ___ __ Rt2 ___ __ Rt3 ___ __ Rt4 ___ __ Rto ___ __
_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
Rh0 ___ __ Rh1 ___ __ Rh2 ___ __ Rh3 ___ __ Rh4 ___ __ Rho ___ __
_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
Rbd ___ __ Rb0 ___ __ Rb1 ___ __ Rb2 ___ __ Rb3 ___ __ Rb4 ___ __ Rbo ___ __
_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
Ru1 ___ __ Ru2 ___ __ Ru3 ___ __ Ru4 ___ __ Ruo ___ __
_LB LN a-< a-^ a-v a->
_LP
_LN
_LF
_LD
Rzc ___ __ Rzb ___ __
_LB LF LF _C
_LP
_LN
_LF
_LD
Ryc ___ __ Ryb ___ __ Rya ___ __
_LB men LF LP _L
_LP
_LN
_LF
_LD
Rxc ___ __ Rxb ___ __ Rxa ___ __
_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

1
hid_listen/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/hid_listen

68
hid_listen/Makefile Normal file
View File

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

88
hid_listen/hid_listen.c Normal file
View File

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

720
hid_listen/rawhid.c Normal file
View File

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

23
hid_listen/rawhid.h Normal file
View File

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

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

@ -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&sup2;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&sup2;C)
* firmware level layers
## About This Project
If you're just looking for binaries, they can be downloaded [here]
[dropbox-download-page].
If you're just trying to compile, jump to the How To: [Compile the Source Code]
(#compile-the-source-code) section.
Open issues, feature requests, and such are tracked [on github]
(/benblazak/ergodox-firmware/issues).
This project is still definitely a work in progress, but it's getting towards
something I'll be happy with when the keyboard finally goes into group buy.
The 'master' branch should always contain the most recent "stable" release of
the code. The 'dev' branch may have new things, but it may also have
expiremental or not yet fixed things. Code on the 'master' branch should also
tend to be more thoroughly tested. Please see the source (and especially the
accompanying '.md' files) for documentation. And [references.md]
(references.md) contains lots of good links, along with descriptions.
## About This Project (more technical)
If you're looking to hack on the source, or just feel like reading it:
@ -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 &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>

View File

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

1413
src/keyboard/controller.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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
}

View File

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

View File

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

View File

@ -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
}

View File

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

View File

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

View File

@ -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
}

View File

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

View File

@ -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 )
};

View File

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

View File

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

View File

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

View File

@ -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 )
};

View File

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

View File

@ -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 )
};

View File

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

View File

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

View File

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

View File

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

1209
src/keyboard/layout.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -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 &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>
Released under The MIT License (MIT) (see "license.md")
Project located at <https://github.com/benblazak/ergodox-firmware>

View File

@ -1,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
}

View File

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

View File

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

View File

@ -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;
}

View File

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

View File

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

View File

@ -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);
}
/* ----------------------------------------------------------------------------
* ------------------------------------------------------------------------- */

View File

@ -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
// ----------------------------------------------------------------------------

View File

@ -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();
}
/* ----------------------------------------------------------------------------
* ------------------------------------------------------------------------- */

View File

@ -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 &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>
Released under The MIT License (MIT) (see "license.md")
Project located at <https://github.com/benblazak/ergodox-firmware>

View File

@ -1,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

View File

@ -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
// ----------------------------------------------------------------------------

View File

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

View File

@ -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.

View File

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

View File

@ -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 &copy; 2012 Ben Blazak <benblazak.dev@gmail.com>
Released under The MIT License (MIT) (see "license.md")
Project located at <https://github.com/benblazak/ergodox-firmware>

View File

@ -1,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

View File

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

View File

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

View File

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

View File

@ -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++; }
}

View File

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

View File

@ -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 $@

View File

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

BIN
teensy.64bit Executable file

Binary file not shown.