Browse Source

Upload

Initial upload
pull/1/head
di0ib 7 years ago
parent
commit
87e7029039
100 changed files with 16881 additions and 0 deletions
  1. 0
    0
      .gitmodules
  2. 37
    0
      .travis.yml
  3. 527
    0
      README.md
  4. 88
    0
      Vagrantfile
  5. 60
    0
      doc/BUILD_GUIDE.md
  6. 339
    0
      doc/COPYING.GPLv2
  7. 674
    0
      doc/COPYING.GPLv3
  8. 352
    0
      doc/CYGWIN_GUIDE.md
  9. 40
    0
      doc/FUSE.txt
  10. 321
    0
      doc/HAND_WIRE.md
  11. 151
    0
      doc/PCB_GUIDE.md
  12. 62
    0
      doc/POWER.txt
  13. 243
    0
      doc/TMK_README.md
  14. 160
    0
      doc/USB_NKRO.txt
  15. 26
    0
      doc/VAGRANT_GUIDE.md
  16. 187
    0
      doc/build_old.md
  17. 261
    0
      doc/keycode.txt
  18. 599
    0
      doc/keymap.md
  19. 62
    0
      doc/other_projects.md
  20. 186
    0
      keyboard/tv44/Makefile
  21. 37
    0
      keyboard/tv44/backlight.c
  22. 89
    0
      keyboard/tv44/config.h
  23. 81
    0
      keyboard/tv44/keymaps/default/keymap.c
  24. 34
    0
      keyboard/tv44/led.c
  25. 981
    0
      keyboard/tv44/tv44-led.hex
  26. 30
    0
      keyboard/tv44/tv44.c
  27. 21
    0
      keyboard/tv44/tv44.h
  28. 53
    0
      quantum/analog.c
  29. 36
    0
      quantum/analog.h
  30. 477
    0
      quantum/audio/audio.c
  31. 91
    0
      quantum/audio/audio.h
  32. 643
    0
      quantum/audio/audio_pwm.c
  33. 382
    0
      quantum/audio/luts.c
  34. 15
    0
      quantum/audio/luts.h
  35. 217
    0
      quantum/audio/musical_notes.h
  36. 117
    0
      quantum/audio/song_list.h
  37. 165
    0
      quantum/audio/voices.c
  38. 31
    0
      quantum/audio/voices.h
  39. 265
    0
      quantum/audio/wave.h
  40. 119
    0
      quantum/config_common.h
  41. 323
    0
      quantum/keymap_common.c
  42. 292
    0
      quantum/keymap_common.h
  43. 311
    0
      quantum/keymap_extras/keymap_bepo.h
  44. 75
    0
      quantum/keymap_extras/keymap_colemak.h
  45. 74
    0
      quantum/keymap_extras/keymap_dvorak.h
  46. 98
    0
      quantum/keymap_extras/keymap_fr_ch.h
  47. 83
    0
      quantum/keymap_extras/keymap_french.h
  48. 77
    0
      quantum/keymap_extras/keymap_french_osx.h
  49. 99
    0
      quantum/keymap_extras/keymap_german.h
  50. 102
    0
      quantum/keymap_extras/keymap_german_ch.h
  51. 100
    0
      quantum/keymap_extras/keymap_german_osx.h
  52. 63
    0
      quantum/keymap_extras/keymap_neo2.h
  53. 59
    0
      quantum/keymap_extras/keymap_nordic.h
  54. 41
    0
      quantum/keymap_extras/keymap_norwegian.c
  55. 32
    0
      quantum/keymap_extras/keymap_plover.h
  56. 62
    0
      quantum/keymap_extras/keymap_spanish.h
  57. 36
    0
      quantum/keymap_extras/keymap_uk.h
  58. 109
    0
      quantum/keymap_midi.c
  59. 222
    0
      quantum/keymap_midi.h
  60. 48
    0
      quantum/led.c
  61. 181
    0
      quantum/light_ws2812.c
  62. 73
    0
      quantum/light_ws2812.h
  63. 227
    0
      quantum/matrix.c
  64. 642
    0
      quantum/quantum.c
  65. 85
    0
      quantum/quantum.h
  66. 58
    0
      quantum/quantum.mk
  67. 505
    0
      quantum/rgblight.c
  68. 87
    0
      quantum/rgblight.h
  69. 158
    0
      quantum/template/Makefile
  70. 24
    0
      quantum/template/README.md
  71. 158
    0
      quantum/template/config.h
  72. 30
    0
      quantum/template/keymaps/default.c
  73. 110
    0
      quantum/template/template.c
  74. 30
    0
      quantum/template/template.h
  75. 6
    0
      quantum/tools/README.md
  76. 9
    0
      quantum/tools/eeprom_reset.hex
  77. 128
    0
      quantum/unicode.h
  78. 13
    0
      tmk_core/.gitignore
  79. 0
    0
      tmk_core/.gitmodules
  80. 146
    0
      tmk_core/README.md
  81. 104
    0
      tmk_core/common.mk
  82. 698
    0
      tmk_core/common/action.c
  83. 90
    0
      tmk_core/common/action.h
  84. 318
    0
      tmk_core/common/action_code.h
  85. 203
    0
      tmk_core/common/action_layer.c
  86. 89
    0
      tmk_core/common/action_layer.h
  87. 85
    0
      tmk_core/common/action_macro.c
  88. 102
    0
      tmk_core/common/action_macro.h
  89. 377
    0
      tmk_core/common/action_tapping.c
  90. 39
    0
      tmk_core/common/action_tapping.h
  91. 378
    0
      tmk_core/common/action_util.c
  92. 93
    0
      tmk_core/common/action_util.h
  93. 185
    0
      tmk_core/common/avr/bootloader.c
  94. 53
    0
      tmk_core/common/avr/eeconfig.c
  95. 146
    0
      tmk_core/common/avr/suspend.c
  96. 27
    0
      tmk_core/common/avr/suspend_avr.h
  97. 117
    0
      tmk_core/common/avr/timer.c
  98. 42
    0
      tmk_core/common/avr/timer_avr.h
  99. 500
    0
      tmk_core/common/avr/xprintf.S
  100. 0
    0
      tmk_core/common/avr/xprintf.h

+ 0
- 0
.gitmodules View File


+ 37
- 0
.travis.yml View File

@@ -0,0 +1,37 @@
os:
- linux

language:
- c

compiler:
- avr-gcc

env:
- KEYBOARD=alps64
- KEYBOARD=arrow_pad
- KEYBOARD=atomic
- KEYBOARD=atreus
- KEYBOARD=bantam44
- KEYBOARD=clueboard1
- KEYBOARD=clueboard2
- KEYBOARD=cluepad
- KEYBOARD=ergodox_ez
- KEYBOARD=gh60
- KEYBOARD=gh60_rev_c
- KEYBOARD=hhkb
- KEYBOARD=jd45
- KEYBOARD=kc60_v2
- KEYBOARD=planck
- KEYBOARD=preonic
- KEYBOARD=retro_refit

script:
- cd keyboard/$KEYBOARD && make

addons:
apt:
packages:
- avr-libc
- gcc-avr
- dfu-programmer

+ 527
- 0
README.md View File

@@ -0,0 +1,527 @@
[![Build Status](https://travis-ci.org/jackhumbert/qmk_firmware.svg?branch=master)](https://travis-ci.org/jackhumbert/qmk_firmware)
# Quantum Mechanical Keyboard Firmware

This is a keyboard firmware based on the [tmk_keyboard firmware](http://github.com/tmk/tmk_keyboard) with some useful features for Atmel AVR controllers, and more specifically, the [OLKB product line](http://olkb.co), the [ErgoDox EZ](http://www.ergodox-ez.com) keyboard, and the [Clueboard product line](http://clueboard.co/).

QMK is developed and maintained by Jack Humbert of OLKB with contributions from the community, and of course, TMK. In fact, this repo used to be a fork of TMK, and we are incredibly grateful for his founding contributions to the firmware. We've had to break the fork due to purely technical reasons -- it simply became too different over time, and we've had to start refactoring some of the basic bits and pieces. We are huge fans of TMK, both the firmware and the person. :)

This documentation is edited and maintained by Erez Zukerman of ErgoDox EZ. If you spot any typos or inaccuracies, please [open an issue](https://github.com/jackhumbert/qmk_firmware/issues/new).

The OLKB product firmwares are maintained by Jack, the Ergodox EZ by Erez, and the Clueboard by [Zach White](https://github.com/skullydazed).

## Documentation roadmap

This is not a tiny project. While this is the main Readme, there are many other files you might want to consult. Here are some points of interest:

* The Readme for your own keyboard: This is found under `keyboards/<your keyboards's name>/`. So for the ErgoDox EZ, it's [here](keyboard/ergodox_ez/); for the Atomic, it's [here](keyboard/atomic/) and so on.
* The [build guide](doc/BUILD_GUIDE.md), also mentioned in the next section. This is how you put your development environment together so you can compile the firmware.
* The list of possible keycodes you can use in your keymap is actually spread out in a few different places:
* [tmk_core/common/keycode.h](tmk_core/common/keycode.h) - the base TMK keycodes. This is the actual source file.
* [doc/keycode.txt](doc/keycode.txt) - an explanation of those same keycodes.
* [quantum/keymap_common.h](quantum/keymap_common.h) - this is where the QMK-specific aliases are all set up. Things like the Hyper and Meh key, the Leader key, and all of the other QMK innovations. These are also explained and documented below, but `keymap_common.h` is where they're actually defined.
* The [TMK documentation](doc/TMK_README.md). QMK is based on TMK, and this explains how it works internally.

## Getting started

* [BUILD_GUIDE.md](doc/BUILD_GUIDE.md) contains instructions to set up a build environment, build the firmware, and deploy it to a keyboard. Once your build environment has been set up, all `make` commands to actually build the firmware must be run from a folder in `keyboard/`.
* If you're looking to customize a keyboard that currently runs QMK or TMK, find your keyboard's directory under `keyboard/` and run the make commands from there.
* If you're looking to apply this firmware to an entirely new hardware project (a new kind of keyboard), you can create your own Quantum-based project by using `util/new_project.sh <project_name>`, which will create `/keyboard/<project_name>` with all the necessary components for a Quantum project.

### Makefile Options

You have access to a bunch of goodies! Check out the Makefile to enable/disable some of the features. Uncomment the `#` to enable them. Setting them to `no` does nothing and will only confuse future you.

BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
MIDI_ENABLE = yes # MIDI controls
UNICODE_ENABLE = no # <-- This is how you disable an option, just set it to "no"
BLUETOOTH_ENABLE = yes # Enable Bluetooth with the Adafruit EZ-Key HID

### Customizing Makefile options on a per-keymap basis

If your keymap directory has a file called `makefile.mk` (note the lowercase filename, and the `.mk` extension), any Makefile options you set in that file will take precedence over other Makefile options (those set for Quantum as a whole or for your particular keyboard).

So let's say your keyboard's makefile has `CONSOLE_ENABLE = yes` (or maybe doesn't even list the `CONSOLE_ENABLE` option, which would cause it to revert to the global Quantum default). You want your particular keymap to not have the debug console, so you make a file called `makefile.mk` and specify `CONSOLE_ENABLE = no`.

### Customizing config.h on a per-keymap basis

If you use the ErgoDox EZ, you can make a `config_user.h` file in your keymap directory and use it to override any `config.h` settings you don't like. Anything you set there will take precedence over the global `config.h` for the ErgoDox EZ. To see an example of this, check out `keymaps/erez_experimental`.

## Quick aliases to common actions

Your keymap can include shortcuts to common operations (called "function actions" in tmk).

### Switching and toggling layers

`MO(layer)` - momentary switch to *layer*. As soon as you let go of the key, the layer is deactivated and you pop back out to the previous layer. When you apply this to a key, that same key must be set as `KC_TRNS` on the destination layer. Otherwise, you won't make it back to the original layer when you release the key (and you'll get a keycode sent). You can only switch to layers *above* your current layer. If you're on layer 0 and you use `MO(1)`, that will switch to layer 1 just fine. But if you include `MO(3)` on layer 5, that won't do anything for you -- because layer 3 is lower than layer 5 on the stack.

`OSL(layer)` - momentary switch to *layer*, as a one-shot operation. So if you have a key that's defined as `OSL(1)`, and you tap that key, then only the very next keystroke would come from layer 1. You would drop back to layer zero immediately after that one keystroke. That's handy if you have a layer full of custom shortcuts -- for example, a dedicated key for closing a window. So you tap your one-shot layer mod, then tap that magic 'close window' key, and keep typing like a boss. Layer 1 would remain active as long as you hold that key down, too (so you can use it like a momentary toggle-layer key with extra powers).

`LT(layer, kc)` - momentary switch to *layer* when held, and *kc* when tapped. Like `MO()`, this only works upwards in the layer stack (`layer` must be higher than the current layer).

`TG(layer)` - toggles a layer on or off. As with `MO()`, you should set this key as `KC_TRNS` in the destination layer so that tapping it again actually toggles back to the original layer. Only works upwards in the layer stack.


### Fun with modifier keys

* `LSFT(kc)` - applies left Shift to *kc* (keycode) - `S(kc)` is an alias
* `RSFT(kc)` - applies right Shift to *kc*
* `LCTL(kc)` - applies left Control to *kc*
* `RCTL(kc)` - applies right Control to *kc*
* `LALT(kc)` - applies left Alt to *kc*
* `RALT(kc)` - applies right Alt to *kc*
* `LGUI(kc)` - applies left GUI (command/win) to *kc*
* `RGUI(kc)` - applies right GUI (command/win) to *kc*
* `HYPR(kc)` - applies Hyper (all modifiers) to *kc*
* `MEH(kc)` - applies Meh (all modifiers except Win/Cmd) to *kc*
* `LCAG(kc)` - applies CtrlAltGui to *kc*

You can also chain these, like this:

LALT(LCTL(KC_DEL)) -- this makes a key that sends Alt, Control, and Delete in a single keypress.

The following shortcuts automatically add `LSFT()` to keycodes to get commonly used symbols. Their long names are also available and documented in `/quantum/keymap_common.h`.

KC_TILD ~
KC_EXLM !
KC_AT @
KC_HASH #
KC_DLR $
KC_PERC %
KC_CIRC ^
KC_AMPR &
KC_ASTR *
KC_LPRN (
KC_RPRN )
KC_UNDS _
KC_PLUS +
KC_DQUO "
KC_LCBR {
KC_RCBR }
KC_LABK <
KC_RABK >
KC_PIPE |
KC_COLN :

`OSM(mod)` - this is a "one shot" modifier. So let's say you have your left Shift key defined as `OSM(MOD_LSFT)`. Tap it, let go, and Shift is "on" -- but only for the next character you'll type. So to write "The", you don't need to hold down Shift -- you tap it, tap t, and move on with life. And if you hold down the left Shift key, it just works as a left Shift key, as you would expect (so you could type THE). There's also a magical, secret way to "lock" a modifier by tapping it multiple times. If you want to learn more about that, open an issue. :)

`MT(mod, kc)` - is *mod* (modifier key - MOD_LCTL, MOD_LSFT) when held, and *kc* when tapped. In other words, you can have a key that sends Esc (or the letter O or whatever) when you tap it, but works as a Control key or a Shift key when you hold it down.

These are the values you can use for the `mod` in `MT()` and `OSM()` (right-hand modifiers are not available for `MT()`):

* MOD_LCTL
* MOD_LSFT
* MOD_LALT
* MOD_LGUI
* MOD_HYPR
* MOD_MEH


These can also be combined like `MOD_LCTL | MOD_LSFT` e.g. `MT(MOD_LCTL | MOD_LSFT, KC_ESC)` which would activate Control and Shift when held, and send Escape when tapped.

We've added shortcuts to make common modifier/tap (mod-tap) mappings more compact:

* `CTL_T(kc)` - is LCTL when held and *kc* when tapped
* `SFT_T(kc)` - is LSFT when held and *kc* when tapped
* `ALT_T(kc)` - is LALT when held and *kc* when tapped
* `GUI_T(kc)` - is LGUI when held and *kc* when tapped
* `ALL_T(kc)` - is Hyper (all mods) when held and *kc* when tapped. To read more about what you can do with a Hyper key, see [this blog post by Brett Terpstra](http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/)
* `LCAG_T(kc)` - is CtrlAltGui when held and *kc* when tapped
* `MEH_T(kc)` - is like Hyper, but not as cool -- does not include the Cmd/Win key, so just sends Alt+Ctrl+Shift.

### Space Cadet Shift: The future, built in

Steve Losh [described](http://stevelosh.com/blog/2012/10/a-modern-space-cadet/) the Space Cadet Shift quite well. Essentially, you hit the left Shift on its own, and you get an opening parenthesis; hit the right Shift on its own, and you get the closing one. When hit with other keys, the Shift key keeps working as it always does. Yes, it's as cool as it sounds.

To use it, use `KC_LSPO` (Left Shift, Parens Open) for your left Shift on your keymap, and `KC_RSPC` (Right Shift, Parens Close) for your right Shift.

The only other thing you're going to want to do is create a `makefile.mk` in your keymap directory and set the following:

```
COMMAND_ENABLE = no # Commands for debug and configuration
```

This is just to keep the keyboard from going into command mode when you hold both Shift keys at the same time.

### The Leader key: A new kind of modifier

If you've ever used Vim, you know what a Leader key is. If not, you're about to discover a wonderful concept. :) Instead of hitting Alt+Shift+W for example (holding down three keys at the same time), what if you could hit a _sequence_ of keys instead? So you'd hit our special modifier (the Leader key), followed by W and then C (just a rapid succession of keys), and something would happen.

That's what `KC_LEAD` does. Here's an example:

1. Pick a key on your keyboard you want to use as the Leader key. Assign it the keycode `KC_LEAD`. This key would be dedicated just for this -- it's a single action key, can't be used for anything else.
2. Include the line `#define LEADER_TIMEOUT 300` somewhere in your keymap.c file, probably near the top. The 300 there is 300ms -- that's how long you have for the sequence of keys following the leader. You can tweak this value for comfort, of course.
3. Within your `matrix_scan_user` function, do something like this:

```
void matrix_scan_user(void) {
LEADER_DICTIONARY() {
leading = false;
leader_end();

SEQ_ONE_KEY(KC_F) {
register_code(KC_S);
unregister_code(KC_S);
}
SEQ_TWO_KEYS(KC_A, KC_S) {
register_code(KC_H);
unregister_code(KC_H);
}
SEQ_THREE_KEYS(KC_A, KC_S, KC_D) {
register_code(KC_LGUI);
register_code(KC_S);
unregister_code(KC_S);
unregister_code(KC_LGUI);
}
}
}
```

As you can see, you have three function. you can use - `SEQ_ONE_KEY` for single-key sequences (Leader followed by just one key), and `SEQ_TWO_KEYS` and `SEQ_THREE_.EYS` for longer sequences. Each of these accepts one or more keycodes as arguments. This is an important point: You can use keycodes from **any layer on your keyboard**. That layer would need to be active for the leader macro to fire, obviously.

### Temporarily setting the default layer

`DF(layer)` - sets default layer to *layer*. The default layer is the one at the "bottom" of the layer stack - the ultimate fallback layer. This currently does not persist over power loss. When you plug the keyboard back in, layer 0 will always be the default. It is theoretically possible to work around that, but that's not what `DF` does.

### Prevent stuck modifiers

Consider the following scenario:

1. Layer 0 has a key defined as Shift.
2. The same key is defined on layer 1 as the letter A.
3. User presses Shift.
4. User switches to layer 1 for whatever reason.
5. User releases Shift, or rather the letter A.
6. User switches back to layer 0.

Shift was actually never released and is still considered pressed.

If such situation bothers you add this to your `config.h`:

#define PREVENT_STUCK_MODIFIERS

This option uses 5 bytes of memory per every 8 keys on the keyboard
rounded up (5 bits per key). For example on Planck (48 keys) it uses
(48/8)\*5 = 30 bytes.

### Remember: These are just aliases

These functions work the same way that their `ACTION_*` functions do - they're just quick aliases. To dig into all of the tmk ACTION_* functions, please see the [TMK documentation](https://github.com/jackhumbert/qmk_firmware/blob/master/doc/keymap.md#2-action).

Instead of using `FNx` when defining `ACTION_*` functions, you can use `F(x)` - the benefit here is being able to use more than 32 function actions (up to 4096), if you happen to need them.

## Macro shortcuts: Send a whole string when pressing just one key

Instead of using the `ACTION_MACRO` function, you can simply use `M(n)` to access macro *n* - *n* will get passed into the `action_get_macro` as the `id`, and you can use a switch statement to trigger it. This gets called on the keydown and keyup, so you'll need to use an if statement testing `record->event.pressed` (see keymap_default.c).

```c
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) // this is the function signature -- just copy/paste it into your keymap file as it is.
{
switch(id) {
case 0: // this would trigger when you hit a key mapped as M(0)
if (record->event.pressed) {
return MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END ); // this sends the string 'hello' when the macro executes
}
break;
}
return MACRO_NONE;
};
```
A macro can include the following commands:

* I() change interval of stroke in milliseconds.
* D() press key.
* U() release key.
* T() type key(press and release).
* W() wait (milliseconds).
* END end mark.

So above you can see the stroke interval changed to 255ms between each keystroke, then a bunch of keys being typed, waits a while, then the macro ends.

Note: Using macros to have your keyboard send passwords for you is possible, but a bad idea.

### Advanced macro functions

To get more control over the keys/actions your keyboard takes, the following functions are available to you in the `action_get_macro` function block:

* `record->event.pressed`

This is a boolean value that can be tested to see if the switch is being pressed or released. An example of this is

```c
if (record->event.pressed) {
// on keydown
} else {
// on keyup
}
```

* `register_code(<kc>);`

This sends the `<kc>` keydown event to the computer. Some examples would be `KC_ESC`, `KC_C`, `KC_4`, and even modifiers such as `KC_LSFT` and `KC_LGUI`.

* `unregister_code(<kc>);`

Parallel to `register_code` function, this sends the `<kc>` keyup event to the computer. If you don't use this, the key will be held down until it's sent.

* `layer_on(<n>);`

This will turn on the layer `<n>` - the higher layer number will always take priority. Make sure you have `KC_TRNS` for the key you're pressing on the layer you're switching to, or you'll get stick there unless you have another plan.

* `layer_off(<n>);`

This will turn off the layer `<n>`.

* `clear_keyboard();`

This will clear all mods and keys currently pressed.

* `clear_mods();`

This will clear all mods currently pressed.

* `clear_keyboard_but_mods();`

This will clear all keys besides the mods currently pressed.

* `update_tri_layer(layer_1, layer_2, layer_3);`

If the user attempts to activate layer 1 AND layer 2 at the same time (for example, by hitting their respective layer keys), layer 3 will be activated. Layers 1 and 2 will _also_ be activated, for the purposes of fallbacks (so a given key will fall back from 3 to 2, to 1 -- and only then to 0).

#### Naming your macros

If you have a bunch of macros you want to refer to from your keymap, while keeping the keymap easily readable, you can just name them like so:

```
#define AUD_OFF M(6)
#define AUD_ON M(7)
#define MUS_OFF M(8)
#define MUS_ON M(9)
#define VC_IN M(10)
#define VC_DE M(11)
#define PLOVER M(12)
#define EXT_PLV M(13)
```

As was done on the [Planck default keymap](/keyboard/planck/keymaps/default/keymap.c#L33-L40)

#### Timer functionality

It's possible to start timers and read values for time-specific events - here's an example:

```c
static uint16_t key_timer;
key_timer = timer_read();
if (timer_elapsed(key_timer) < 100) {
// do something if less than 100ms have passed
} else {
// do something if 100ms or more have passed
}
```

It's best to declare the `static uint16_t key_timer;` outside of the macro block (top of file, etc).

#### Example: Single-key copy/paste (hold to copy, tap to paste)

With QMK, it's easy to make one key do two things, as long as one of those things is being a modifier. :) So if you want a key to act as Ctrl when held and send the letter R when tapped, that's easy: `CTL_T(KC_R)`. But what do you do when you want that key to send Ctrl-V (paste) when tapped, and Ctrl-C (copy) when held?

Here's what you do:


```
static uint16_t key_timer;

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
switch(id) {
case 0: {
if (record->event.pressed) {
key_timer = timer_read(); // if the key is being pressed, we start the timer.
}
else { // this means the key was just released, so we can figure out how long it was pressed for (tap or "held down").
if (timer_elapsed(key_timer) > 150) { // 150 being 150ms, the threshhold we pick for counting something as a tap.
return MACRO( D(LCTL), T(C), U(LCTL), END );
}
else {
return MACRO( D(LCTL), T(V), U(LCTL), END );
}
}
break;
}
}
return MACRO_NONE;
};
```

And then, to assign this macro to a key on your keyboard layout, you just use `M(0)` on the key you want to press for copy/paste.

## Additional keycode aliases for software-implemented layouts (Colemak, Dvorak, etc)

Everything is assuming you're in Qwerty (in software) by default, but there is built-in support for using a Colemak or Dvorak layout by including this at the top of your keymap:

#include <keymap_colemak.h>

If you use Dvorak, use `keymap_dvorak.h` instead of `keymap_colemak.h` for this line. After including this line, you will get access to:

* `CM_*` for all of the Colemak-equivalent characters
* `DV_*` for all of the Dvorak-equivalent characters

These implementations assume you're using Colemak or Dvorak on your OS, not on your keyboard - this is referred to as a software-implemented layout. If your computer is in Qwerty and your keymap is in Colemak or Dvorak, this is referred to as a firmware-implemented layout, and you won't need these features.

To give an example, if you're using software-implemented Colemak, and want to get an `F`, you would use `CM_F` - `KC_F` under these same circumstances would result in `T`.

## Additional language support

In `quantum/keymap_extras/`, you'll see various language files - these work the same way as the alternative layout ones do. Most are defined by their two letter country/language code followed by an underscore and a 4-letter abbreviation of its name. `FR_UGRV` which will result in a `ù` when using a software-implemented AZERTY layout. It's currently difficult to send such characters in just the firmware (but it's being worked on - see Unicode support).

## Unicode support

You can currently send 4 hex digits with your OS-specific modifier key (RALT for OSX with the "Unicode Hex Input" layout) - this is currently limited to supporting one OS at a time, and requires a recompile for switching. 8 digit hex codes are being worked on. The keycode function is `UC(n)`, where *n* is a 4 digit hexidecimal. Enable from the Makefile.

## Other firmware shortcut keycodes

* `RESET` - puts the MCU in DFU mode for flashing new firmware (with `make dfu`)
* `DEBUG` - the firmware into debug mode - you'll need hid_listen to see things
* `BL_ON` - turns the backlight on
* `BL_OFF` - turns the backlight off
* `BL_<n>` - sets the backlight to level *n*
* `BL_INC` - increments the backlight level by one
* `BL_DEC` - decrements the backlight level by one
* `BL_TOGG` - toggles the backlight
* `BL_STEP` - steps through the backlight levels

Enable the backlight from the Makefile.

## Driving a speaker - audio support

Your keyboard can make sounds! If you've got a Planck, Preonic, or basically any keyboard that allows access to the C6 port, you can hook up a simple speaker and have it beep. You can use those beeps to indicate layer transitions, modifiers, special keys, or just to play some funky 8bit tunes.

The audio code lives in [quantum/audio/audio.h](/quantum/audio/audio.h) and in the other files in the audio directory. It's enabled by default on the Planck [stock keymap](/keyboard/planck/keymaps/default/keymap.c). Here are the important bits:

```
#include "audio.h"
```

Then, lower down the file:

```
float tone_startup[][2] = {
ED_NOTE(_E7 ),
E__NOTE(_CS7),
E__NOTE(_E6 ),
E__NOTE(_A6 ),
M__NOTE(_CS7, 20)
};
```

This is how you write a song. Each of these lines is a note, so we have a little ditty composed of five notes here.

Then, we have this chunk:

```
float tone_qwerty[][2] = SONG(QWERTY_SOUND);
float tone_dvorak[][2] = SONG(DVORAK_SOUND);
float tone_colemak[][2] = SONG(COLEMAK_SOUND);
float tone_plover[][2] = SONG(PLOVER_SOUND);
float tone_plover_gb[][2] = SONG(PLOVER_GOODBYE_SOUND);

float music_scale[][2] = SONG(MUSIC_SCALE_SOUND);
float goodbye[][2] = SONG(GOODBYE_SOUND);
```

Wherein we bind predefined songs (from [audio/song_list.h](/audio/song_list.h)) into named variables. This is one optimization that helps save on memory: These songs only take up memory when you reference them in your keymap, because they're essentially all preprocessor directives.

So now you have something called `tone_plover` for example. How do you make it play the Plover tune, then? If you look further down the keymap, you'll see this:

```
PLAY_NOTE_ARRAY(tone_plover, false, 0); // Signature is: Song name, repeat, rest style
```

This is inside one of the macros. So when that macro executes, your keyboard plays that particular chime.

"Rest style" in the method signature above (the last parameter) specifies if there's a rest (a moment of silence) between the notes.

## MIDI functionalty

This is still a WIP, but check out `quantum/keymap_midi.c` to see what's happening. Enable from the Makefile.

## Bluetooth functionality

This requires [some hardware changes](https://www.reddit.com/r/MechanicalKeyboards/comments/3psx0q/the_planck_keyboard_with_bluetooth_guide_and/?ref=search_posts), but can be enabled via the Makefile. The firmware will still output characters via USB, so be aware of this when charging via a computer. It would make sense to have a switch on the Bluefruit to turn it off at will.

## International Characters on Windows

[AutoHotkey](https://autohotkey.com) allows Windows users to create custom hotkeys among others.

The method does not require Unicode support in the keyboard itself but depends instead of AutoHotkey running in the background.

First you need to select a modifier combination that is not in use by any of your programs.
CtrlAltWin is not used very widely and should therefore be perfect for this.
There is a macro defined for a mod-tab combo `LCAG_T`.
Add this mod-tab combo to a key on your keyboard, e.g.: `LCAG_T(KC_TAB)`.
This makes the key behave like a tab key if pressed and released immediately but changes it to the modifier if used with another key.

In the default script of AutoHotkey you can define custom hotkeys.

<^<!<#a::Send, ä
<^<!<#<+a::Send, Ä

The hotkeys above are for the combination CtrlAltGui and CtrlAltGuiShift plus the letter a.
AutoHotkey inserts the Text right of `Send, ` when this combination is pressed.

## RGB Under Glow Mod

![Planck with RGB Underglow](https://raw.githubusercontent.com/yangliu/qmk_firmware/planck-rgb/keyboard/planck/keymaps/yang/planck-with-rgb-underglow.jpg)

Here is a quick demo on Youtube (with NPKC KC60) (https://www.youtube.com/watch?v=VKrpPAHlisY).

For this mod, you need an unused pin wiring to DI of WS2812 strip. After wiring the VCC, GND, and DI, you can enable the underglow in your Makefile.

RGBLIGHT_ENABLE = yes

Please note that the underglow is not compatible with audio output. So you cannot enable both of them at the same time.

Please add the following options into your config.h, and set them up according your hardware configuration. These settings are for the F4 by default:

#define ws2812_PORTREG PORTF
#define ws2812_DDRREG DDRF
#define ws2812_pin PF4
#define RGBLED_NUM 14 // Number of LEDs
#define RGBLIGHT_HUE_STEP 10
#define RGBLIGHT_SAT_STEP 17
#define RGBLIGHT_VAL_STEP 17

You'll need to edit `PORTF`, `DDRF`, and `PF4` on the first three lines to the port/pin you have your LED(s) wired to, eg for B3 change things to:

#define ws2812_PORTREG PORTB
#define ws2812_DDRREG DDRB
#define ws2812_pin PB3

The firmware supports 5 different light effects, and the color (hue, saturation, brightness) can be customized in most effects. To control the underglow, you need to modify your keymap file to assign those functions to some keys/key combinations. For details, please check this keymap. `keyboard/planck/keymaps/yang/keymap.c`

### WS2812 Wiring

![WS2812 Wiring](https://raw.githubusercontent.com/yangliu/qmk_firmware/planck-rgb/keyboard/planck/keymaps/yang/WS2812-wiring.jpg)

Please note the USB port can only supply a limited amount of power to the keyboard (500mA by standard, however, modern computer and most usb hubs can provide 700+mA.). According to the data of NeoPixel from Adafruit, 30 WS2812 LEDs require a 5V 1A power supply, LEDs used in this mod should not more than 20.

## Safety Considerations

You probably don't want to "brick" your keyboard, making it impossible
to rewrite firmware onto it. Here are some of the parameters to show
what things are (and likely aren't) too risky.

- If a keyboard map does not include RESET, then, to get into DFU
mode, you will need to press the reset button on the PCB, which
requires unscrewing some bits.
- Messing with tmk_core / common files might make the keyboard
inoperable
- Too large a .hex file is trouble; `make dfu` will erase the block,
test the size (oops, wrong order!), which errors out, failing to
flash the keyboard
- DFU tools do /not/ allow you to write into the bootloader (unless
you throw in extra fruitsalad of options), so there is little risk
there.
- EEPROM has around a 100000 write cycle. You shouldn't rewrite the
firmware repeatedly and continually; that'll burn the EEPROM
eventually.


+ 88
- 0
Vagrantfile View File

@@ -0,0 +1,88 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure(2) do |config|
# You can only have one config.vm.box uncommented at a time

# Comment this and uncomment another if you don't want to use the minimal Arch box
config.vm.box = "dragon788/arch-ala-elasticdog"

# VMware/Virtualbox 64 bit
# config.vm.box = "phusion/ubuntu-14.04-amd64"
#
# VMware/Virtualbox 64 bit
#config.vm.box = "puphpet/centos65-x64"
#
# The opensuse boxes don't have dfu-util in their default repositories
#
# The virtualbox version has tools issues
# VMware/Virtualbox 64 bit
#config.vm.box = "bento/opensuse-13.2-x86_64"
#
# Virtualbox only
#config.vm.box = "bento/opensuse-13.2-i386"
# config.vm.box = ""
# config.vm.box = ""

# This section allows you to customize the Virtualbox VM
# settings, ie showing the GUI or upping the memory
# or cores if desired
config.vm.provider "virtualbox" do |vb|
# Hide the VirtualBox GUI when booting the machine
vb.gui = false
# Uncomment the below lines if you want to program
# your Teensy via the VM rather than your host OS
#vb.customize ['modifyvm', :id, '--usb', 'on']
#vb.customize ['usbfilter', 'add', '0',
# '--target', :id,
# '--name', 'teensy',
# '--vendorid', '0x16c0',
# '--productid','0x0478'
# ]
# Customize the amount of memory on the VM:
vb.memory = "512"
end

# This section allows you to customize the VMware VM
# settings, ie showing the GUI or upping the memory
# or cores if desired
config.vm.provider "vmware_workstation" do |vmw|
# Hide the VMware GUI when booting the machine
vmw.gui = false
# Customize the amount of memory on the VM:
vmw.memory = "512"
end

config.vm.provider "vmware_fusion" do |vmf|
# Hide the vmfare GUI when booting the machine
vmf.gui = false
# Customize the amount of memory on the VM:
vmf.memory = "512"
end
# This script ensures the required packages for AVR programming are installed
# It also ensures the system always gets the latest updates when powered on
# If this causes issues you can run a 'vagrant destroy' and then
# add a # before ,args: and run 'vagrant up' to get a working
# non-updated box and then attempt to troubleshoot or open a Github issue
config.vm.provision "shell", run: "always", path: "./util/avr_setup.sh", args: "-update"

config.vm.post_up_message = """
Log into the VM using 'vagrant ssh' on OSX or from Git Bash (Win)
or 'vagrant ssh-config' and Putty or Bitvise SSH or another SSH tool

Change directory (cd) to the keyboard you wish to program
(Optionally) modify your layout,
then run 'make clean'
and then 'make' to compile the .eep and .hex files.

Or you can copy and paste the example line below.
cd /vagrant; cd keyboard; cd ergodox_ez; make clean; make

"""
end

+ 60
- 0
doc/BUILD_GUIDE.md View File

@@ -0,0 +1,60 @@
# Build Guide

## Build Environment Setup

### Windows (Vista and later)
1. If you have ever installed WinAVR, uninstall it.
2. Install [MHV AVR Tools](https://infernoembedded.com/sites/default/files/project/MHV_AVR_Tools_20131101.exe). Disable smatch, but **be sure to leave the option to add the tools to the PATH checked**.
3. Install [MinGW](https://sourceforge.net/projects/mingw/files/Installer/mingw-get-setup.exe/download). During installation, uncheck the option to install a graphical user interface. **DO NOT change the default installation folder.** The scripts depend on the default location.
4. Clone this repository. [This link will download it as a zip file, which you'll need to extract.](https://github.com/jackhumbert/qmk_firmware/archive/master.zip) Open the extracted folder in Windows Explorer.
5. Double-click on the 1-setup-path-win batch script to run it. You'll need to accept a User Account Control prompt. Press the spacebar to dismiss the success message in the command prompt that pops up.
6. Right-click on the 2-setup-environment-win batch script, select "Run as administrator", and accept the User Account Control prompt. This part may take a couple of minutes, and you'll need to approve a driver installation, but once it finishes, your environment is complete!
7. Future build commands should be run from the standard Windows command prompt, which you can find by searching for "command prompt" from the start menu or start screen. Ignore the "MHV AVR Shell".

### Mac
If you're using [homebrew,](http://brew.sh/) you can use the following commands:

brew tap osx-cross/avr
brew install avr-libc
brew install dfu-programmer

This is the recommended method. If you don't have homebrew, [install it!](http://brew.sh/) It's very much worth it for anyone who works in the command line.

You can also try these instructions:

1. Install Xcode from the App Store.
2. Install the Command Line Tools from `Xcode->Preferences->Downloads`.
3. Install [DFU-Programmer][dfu-prog].

### Linux
Install AVR GCC, AVR libc, and dfu-progammer with your favorite package manager.

Debian/Ubuntu example:

sudo apt-get update
sudo apt-get install gcc-avr avr-libc dfu-programmer

### Vagrant
If you have any problems building the firmware, you can try using a tool called Vagrant. It will set up a virtual computer with a known configuration that's ready-to-go for firmware building. OLKB does NOT host the files for this virtual computer. Details on how to set up Vagrant are in the [VAGRANT_GUIDE file](VAGRANT_GUIDE.md).

## Verify Your Installation
1. If you haven't already, obtain this repository ([https://github.com/jackhumbert/qmk_firmware](https://github.com/jackhumbert/qmk_firmware)). You can either download it as a zip file and extract it, or clone it using the command line tool git or the Github Desktop application.
2. Open up a terminal or command prompt and navigate to the qmk_firmware folder using the `cd` command. The command prompt will typically open to your home directory. If, for example, you cloned the repository to your Documents folder, then you would type `cd Documents/qmk_firmware`. If you extracted the file from a zip, then it may be named `qmk_firmware-master` instead.
3. To confirm that you're in the correct location, you can display the contents of your current folder using the `dir` command on Windows, or the `ls` command on Linux or Mac. You should see several files, including `README.md` and a `quantum` folder. From here, you need to navigate to the appropriate folder under `keyboard/`. For example, if you're building for a Planck, run `cd keyboard/planck`.
4. Once you're in the correct keyboard-specific folder, run the `make` command. This should output a lot of information about the build process.

## Customizing, Building, and Deploying Your Firmware

Note: Some keyboard folders have non-standard organizations, and may not even support specifying alternate keymaps. Until these get reorganized, you will need to edit their default keymaps directly.

1. Running the `make` command from your keyboard's folder will generate a .hex file based on the default keymap. All keymaps for a particular keyboard live in the `keymaps` folder in that keyboard's folder. To create your own keymap, duplicate the folder `keymaps/default`, and rename it with your name, for example `jack`. Or, if you don't care about the ability to share your keymap with the community via GitHub, you can just modify the default keymap itself. Details on how to program keymap files can be found in other guides.
2. To build a keymap other than the default, type `KEYMAP=<name>` after `make`. So if I've named my keymap `jack`, the full command would be `make KEYMAP=jack`.
3. How you deploy the firmware will depend on whether you are using a PCB or a Teensy. In both cases, you'll need to put the keyboard in bootloader mode, either by pressing a button on the PCB/Teensy or pressing the key with the `RESET` keycode. Then, if you're using a PCB, just run `make KEYMAP=<name> dfu` to both build and deploy the firmware. If you're using a Teensy, you'll probably need to take the <keyboardname>.hex file that make produces in the keyboard's folder, and deploy it using the [Teensy Loader.](https://www.pjrc.com/teensy/loader.html)

## Helpful Tips
1. On Linux or OS X, you can run `sleep 5; make KEYMAP=<name> dfu` to delay building/deploying the firmware until for 5 seconds, giving you a chance to put the firmware into bootloader mode. You can change the 5 to any number of seconds.

## Troubleshooting
1. Try running `make clean` if the make command fails.

WIP

+ 339
- 0
doc/COPYING.GPLv2 View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.

We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and
modification follow.

GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.

c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.

<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

+ 674
- 0
doc/COPYING.GPLv3 View File

@@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The GNU General Public License is a free, copyleft license for
software and other kinds of works.

The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.

When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.

Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

The precise terms and conditions for copying, distribution and
modification follow.

TERMS AND CONDITIONS

0. Definitions.

"This License" refers to version 3 of the GNU General Public License.

"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.

To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

A "covered work" means either the unmodified Program or a work based
on the Program.

To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

1. Source Code.

The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.

A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

The Corresponding Source for a work in source code form is that
same work.

2. Basic Permissions.

All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.

3. Protecting Users' Legal Rights From Anti-Circumvention Law.

No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

4. Conveying Verbatim Copies.

You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

5. Conveying Modified Source Versions.

You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.

b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".

c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.

d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.

A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

6. Conveying Non-Source Forms.

You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.

b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.

c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.

d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.

e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.

A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

7. Additional Terms.

"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or

b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or

c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or

d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or

e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or

f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.

All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

8. Termination.

You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

9. Acceptance Not Required for Having Copies.

You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

10. Automatic Licensing of Downstream Recipients.

Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.

An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

11. Patents.

A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".

A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

12. No Surrender of Others' Freedom.

If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

13. Use with the GNU Affero General Public License.

Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

14. Revised Versions of this License.

The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

15. Disclaimer of Warranty.

THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

16. Limitation of Liability.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

17. Interpretation of Sections 15 and 16.

If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>

This program is free software: you can redistribute it 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/>.

Also add information on how to contact you by electronic and paper mail.

If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

+ 352
- 0
doc/CYGWIN_GUIDE.md View File

@@ -0,0 +1,352 @@
#Planck Advanced (but not too advanced) `cygwin` Users Guide
If you are a user of the [cygwin environment](https://cygwin.com) in Windows and want the freedom to use the latest tools available, then this is the guide for you. If compiling your own copy of the latest and greatest Gnu C Compiler makes you super happy, then this is the guide for you. If the command line make you smile, then this is the guide for you.

This guide was written step by step as I went through the process on a `Windows 10` `x86_64` and a `Windows 7` `amd k10` based system. This should be generally applicable to to any `Windows` environment with `cygwin`.

#####Do not skip steps. Do not move past a step until the previous step finishes successfully.

Based on [avr-libc installation guide](http://www.nongnu.org/avr-libc/user-manual/install_tools.html)

##Get the Required Packages
Download the `cygwin` setup ([x86_64](https://cygwin.com/setup-x86_64.exe)) and install the default system plus the following if they are not already selected:
- devel/git
- devel/gcc-core
- devel/gcc-g++
- devel/flex
- devel/bison
- devel/make
- devel/texinfo
- devel/gettext-devel
- devel/automake
- devel/autoconfig
- devel/libtool
- text/gettext
- libs/libgcc1
- interpreters/m4
- web/wget
- archive/unzip

The following sources will be required:
- [gmp](https://gmplib.org/) (6.1.0)
- [mpfr](http://www.mpfr.org/) (3.1.4)
- [mpc](http://www.multiprecision.org/) (1.0.3)
- [binutils](https://www.sourceware.org/binutils/) (2.26)
- [gcc](https://gcc.gnu.org/) (5.3.0)
- [avr-libc](http://www.nongnu.org/avr-libc/) (2.0.0)

The `dfu-programmer` will be required to flash the new firmware
- [dfu-programmer](https://dfu-programmer.github.io/) (0.7.2)

The set of commands below will create a directory (`~/local/avr`) for the sources you compile to be installed on the machine and a directory (`~/src`) for these source files to be stored. The commands then download the sources of the needed packages and unpack them. Note: the expand commands are different depending on if the packages are offered as a `bz2` or `gz` archive
```
$ mkdir ~/local
$ mkdir ~/local/avr
$ mkdir ~/src
$ cd ~/src
$ wget https://gmplib.org/download/gmp/gmp-6.1.0.tar.bz2
$ wget http://www.mpfr.org/mpfr-3.1.4/mpfr-3.1.4.tar.bz2
$ wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gz
$ wget http://ftp.gnu.org/gnu/binutils/binutils-2.26.tar.gz
$ wget http://mirror0.babylon.network/gcc/releases/gcc-5.3.0/gcc-5.3.0.tar.gz
$ wget http://download.savannah.gnu.org/releases/avr-libc/avr-libc-2.0.0.tar.bz2
$ tar -xjf gmp-6.1.0.tar.bz2
$ tar -xjf mpfr-3.1.4.tar.bz2
$ tar -zxf mpc-1.0.3.tar.gz
$ tar -zxf binutils-2.26.tar.gz
$ tar -zxf gcc-5.3.0.tar.gz
$ tar -xjf avr-libc-2.0.0.tar.bz2
```

##Setup the Build Environment
These commands will set up the install directory and the `PATH` variable, which will allow you to access your installed packages. Note: if you close the `cygwin` terminal window, you will need to rerun these commands, they are not permanent.
```
$ PREFIX=$HOME/local/avr
$ export PREFIX
$ PATH=/usr/local/bin:/usr/local/lib:/usr/local/include:/bin:/lib:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS
$ PATH=$PATH:$PREFIX/bin:$PREFIX/lib
$ export PATH
```

##The `gcc` Required Math Library Packages
The following packages are required to be complied and installed in order to compile `gcc`. They are not sufficiently available through the `cygwin` package system, so we have to make them ourselves. They must be complied in this order because each one depends on the previous. Verfiy that for each package, `make check` returns all passing and no fails.

###Build and Install `gmp`
```
$ cd ~/src/gmp-6.1.0
$ ./configure --enable-static --disable-shared
$ make
$ make check
$ make install
```

###Build and Install `mpfr`
```
$ cd ~/src/mpfr-3.1.4
$ ./configure --with-gmp-build=../gmp-6.1.0 --enable-static --disable-shared
$ make
$ make check
$ make install
```

###Build and Install `mpc`
```
$ cd ~/src/mpc-1.0.3
$ ./configure --with-gmp=/usr/local --with-mpfr=/usr/local --enable-static --disable-shared
$ make
$ make check
$ make install
```

##OPTIONAL Part
You can build and install a brand new `gcc` or you can use the one supplied by `cygwin`. This will take about 4-5 hours to compile (It is a "native build", so it does the entire build **3 times**. This takes a long while).

###Build and Install `gcc` for Your Machine
```
$ cd ~/src/gcc-5.3.0
$ mkdir obj-local
$ cd obj-local
$ ../configure --enable-languages=c,c++ --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --enable-static --disable-shared
$ make
$ make install
```
##End OPTIONAL Part

###Build and Install `binutils` for Your Machine
```
$ cd ~/src/binutils-2.26
$ mkdir obj-local
$ cd obj-local
$ ../configure
$ make
$ make install
```

##Buliding `binutils`, `gcc`, and `avr-libc` for the AVR system
Now we can make the critical stuff for compiling our firmware: `binutils`, `gcc`, and `avr-libc` for the AVR architecture. These allow us to build and manipulate the firmware for the keyboard.

###Build `binutils` for AVR
If you plan to build and install `avr-gdb` also, use the `gdb` install at the end of this guide as it also builds the `binutils`
```
$ cd ~/src/binutils-2.26
$ mkdir obj-avr
$ cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --disable-nls
$ make
$ make install
```

###Build `gcc` for AVR
```
$ cd ~/src/gcc-5.3.0
$ mkdir obj-avr
$ cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --enable-languages=c,c++ --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --enable-static --disable-shared --disable-nls --disable-libssp --with-dwarf2
$ make
$ make install
```

###Build `avr-libc` for AVR
For building the `avr-libc`, we have to specify the host build system. In my case it is `x86_64-unknown-cygwin`. You can look for build system type in the `gcc` configure notes for the proper `--build` specification to pass when you configure `avr-libc`.
```
$ cd ~/src/avr-libc-2.0.0
$ ./configure --prefix=$PREFIX --build=x86_64-unknown-cygwin --host=avr
$ make
$ make install
```

##Building 'dfu-programmer' for flashing the firmware via USB and installing the drivers
We can either build our own, or use the precomplied binaries. The precompiled binaries don't play well with `cygwin` so it is better to build them ourselves. The procedure for the precompiled binaries is included at the end of this guide.

### Build and Install the `libusb`
The `dfu-programmer` requires `libusb` so that it can interact with the USB system. These repos must be bootstrapped in order to create an appropriate `./configure` and `Makefile` for your system.
```
$ cd ~/src
$ git clone https://github.com/libusb/libusb.git
$ cd libusb
$ ./bootstrap.sh
$ ./configure
$ make
$ make install
```

### Build and Install the `dfu-programmer`
```
$ cd ~/src
$ git clone https://github.com/dfu-programmer/dfu-programmer.git
$ cd dfu-programmer
$ ./bootstrap.sh
$ ./configure
$ make
$ make install
```

Verify the installation with:
```
$ which dfu-programmer
/usr/local/bin/dfu-programmer

$ dfu-programmer
dfu-programmer 0.7.2
https://github.com/dfu-programmer/dfu-programmer
Type 'dfu-programmer --help' for a list of commands
'dfu-programmer --targets' to list supported target devices
```
If you are not getting the above result, you will not be able to flash the firmware!

###Install the USB drivers
The drivers are included in the windows binary version of [`dfu-programmer` 0.7.2](http://iweb.dl.sourceforge.net/project/dfu-programmer/dfu-programmer/0.7.2/dfu-programmer-win-0.7.2.zip).
```
$ cd ~/src
$ wget http://iweb.dl.sourceforge.net/project/dfu-programmer/dfu-programmer/0.7.2/dfu-programmer-win-0.7.2.zip
$ unzip dfu-programmer-win-0.7.2.zip -d dfu-programmer-win-0.7.2
```

or

The official drivers are found in [Atmel's `FLIP` installer](http://www.atmel.com/images/Flip%20Installer%20-%203.4.7.112.exe). Download and then install `FLIP`. Upon installation, the drivers will be found in `C:\Program Files (x86)\Atmel\Flip 3.4.7\usb`.

Then, from an **administrator-privileged** `Windows` terminal, run the following command (adjust the path for username, etc. as necessary) and accept the prompt that pops up:
```
C:\> pnputil -i -a C:\cygwin64\home\Kevin\src\dfu-programmer-win-0.7.2\dfu-prog-usb-1.2.2\atmel_usb_dfu.inf
or
C:\> pnputil -i -a "C:\Program Files (x86)\Atmel\Flip 3.4.7\usb\atmel_usb_dfu.inf"
```

This should be the result:
```
Microsoft PnP Utility

Processing inf : atmel_usb_dfu.inf
Successfully installed the driver on a device on the system.
Driver package added successfully.
Published name : oem104.inf


Total attempted: 1
Number successfully imported: 1
```

Alternatively, the `Windows` driver can be installed when prompted by `Windows` when the keyboard is attached. Do not let `Windows` search for a driver; specify the path to search for a driver and point it to the `atmel_usb_dfu.inf` file.

##Building and Flashing the Planck firmware!
If you did everything else right. This part should be a snap! Grab the latest sources from `github`, make the Plank firmware, then flash it.

###Build Planck and Load the Firmware
```
$ cd ~/src
$ git clone https://github.com/jackhumbert/qmk_firmware.git
$ cd qmk_firmware/keyboard/planck
$ make
```

Make sure there are no errors. You should end up with this or something similar:
```
Creating load file for Flash: planck.hex
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature planck.elf planck.hex

Creating load file for EEPROM: planck.eep
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O ihex planck.elf planck.eep || exit 0

Creating Extended Listing: planck.lss
avr-objdump -h -S -z planck.elf > planck.lss

Creating Symbol Table: planck.sym
avr-nm -n planck.elf > planck.sym

Size after:
text data bss dec hex filename
18602 82 155 18839 4997 planck.elf

-------- end --------
```

If you do not get the above, you **did not** build the firmware, and you will have nothing to flash. If you have the fresh clone from `github`, it was probably something gone wrong in this install process, go check and see what didn't work and threw errors or what steps you might have missed.

But if everything went OK, you are ready to flash! Press the reset button on the bottom of the Planck, wait two seconds, then:
```
$ make dfu
```
.
.
.
profit!!!





##extra bits...

###Installing Precompiled `dfu-programmer` Binaries (not recommended for `cygwin`)
To install the `dfu-programmer` from the binaries, we must get if from [the `dfu-programmer` website](https://dfu-programmer.github.io/) ([0.7.2](http://iweb.dl.sourceforge.net/project/dfu-programmer/dfu-programmer/0.7.2/dfu-programmer-win-0.7.2.zip)).

Copy this file into your `cygwin` home\src directory. (For me, it is `C:\cygwin64\home\Kevin\src`), extract the files, move `dfu-programmer.exe` to `~/local/avr/bin`. Most obnoxiously, the `libusb0_x86.dll` and `libusb0.sys` need to be moved from `./dfu-prog-usb-1.2.2/x86/` to a directory in the `Windows` `PATH` and the `cygwin` `PATH`. This is because the `dfu-programmer` binary is `mingw` based, not `cygwin` based, so the `dlls` do not cooperate. I achieved acceptable pathing by moving the files to `C:\cygwin64\home\Kevin\local\avr\bin` Then, in a `WINDOWS` command prompt running (Adjusting your path for username, etc. as needed):
```
C:\> set PATH=%PATH%;C:\cygwin64\home\Kevin\local\avr\bin
```

Then, rename `libusb0_x86.dll` to `libusb0.dll`.
You can tell that you were successful by trying to execute 'dfu-programmer' from the 'cygwin' prompt:
```
$ which dfu-programmer
/home/Kevin/local/avr/bin/dfu-programmer

$ dfu-programmer
dfu-programmer 0.7.2
https://github.com/dfu-programmer/dfu-programmer
Type 'dfu-programmer --help' for a list of commands
'dfu-programmer --targets' to list supported target devices
```

If you are not getting the above result, you will not be able to flash the firmware!
- Try making sure your `PATH` variables are set correctly for both `Windows` and `cygwin`.
- Make sure the `dll` is named correctly.
- Do not extract it with `cygwin`'s `unzip` as it does not set the executable permission. If you did it anyway, do `chmod +x dfu-programmer.exe`.
- Still have problems? Try building it instead.


##Debugging Tools

These tools are for debugging your firmware, etc. before flashing. Theoretically, it can save your memory from wearing out. However, these tool do not work 100% for the Planck firmware.

### `gdb` for AVR
`gdb` has a simulator for AVR but it does not support all instructions (like WDT), so it immediately crashes when running the Planck firmware (because `lufa.c` disables the WDT in the first few lines of execution). But it can still be useful in debugging example code and test cases, if you know how to use it.

```
$ cd ~/src
$ git clone git://sourceware.org/git/binutils-gdb.git
$ cd binutils-gdb
$ mkdir obj-avr
$ cd obj-avr
$ ../configure --prefix=$PREFIX --target=avr --build=x86_64-unknown-cygwin --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --disable-nls --enable-static
$ make
$ make install
```

### `simulavr`
`simulavr` is an AVR simulator. It runs the complied AVR elfs. `simulavr` does not support the `atmega32u4` device... it does `atmega32` but that is not good enough for the firmware (no PORTE and other things), so you cannot run the Planck firmware. I use it to simulate ideas I have for features in separate test projects.

This one is a major pain in the butt because it has a lot of dependencies and it is buggy. I will do my best to explain it but... it was hard to figure out. A few things need to be changed in the 'Makefile' to make it work in `cygwin`.


```
$ cd ~/src
$ git clone https://github.com/Traumflug/simulavr.git
$ cd simulavr
$ ./bootstrap
$ ./configure --prefix=$PREFIX --enable-static --disable-tcl --disable-doxygen-doc
```
Edit `src/Makefile.am` now so that `-no-undefined` is included (I did this by removing the SYS_MINGW conditional surrounding `libsim_la_LDFLAGS += -no-undefined` and `libsimulavr_la_LDFLAGS += -no-undefined \ libsimulavr_la_LIBADD += $(TCL_LIB)`. Also, `$(EXEEXT)` is added after `kbdgentables` in two places.

```
$ make
$ make install
```


TODO:
- git repos for all sources
- command line magic for cygwin setup
- better options for `dfu-drivers`

+ 40
- 0
doc/FUSE.txt View File

@@ -0,0 +1,40 @@
ATMega168P Fuse/Lock Bits
=========================
This configuration is from usbasploader's Makefile.

HFUSE 0xD6
LFUSE 0xDF
EFUSE 0x00
LOCK 0x3F(intact)

#---------------------------------------------------------------------
# ATMega168P
#---------------------------------------------------------------------
# Fuse extended byte:
# 0x00 = 0 0 0 0 0 0 0 0 <-- BOOTRST (boot reset vector at 0x1800)
# \+/
# +------- BOOTSZ (00 = 2k bytes)
# Fuse high byte:
# 0xd6 = 1 1 0 1 0 1 1 0
# ^ ^ ^ ^ ^ \-+-/
# | | | | | +------ BODLEVEL 0..2 (110 = 1.8 V)
# | | | | + --------- EESAVE (preserve EEPROM over chip erase)
# | | | +-------------- WDTON (if 0: watchdog always on)
# | | +---------------- SPIEN (allow serial programming)
# | +------------------ DWEN (debug wire enable)
# +-------------------- RSTDISBL (reset pin is enabled)
# Fuse low byte:
# 0xdf = 1 1 0 1 1 1 1 1
# ^ ^ \ / \--+--/
# | | | +------- CKSEL 3..0 (external >8M crystal)
# | | +--------------- SUT 1..0 (crystal osc, BOD enabled)
# | +------------------ CKOUT (if 0: Clock output enabled)
# +-------------------- CKDIV8 (if 0: divide by 8)


# Lock Bits
# 0x3f = - - 1 1 1 1 1 1
# \ / \-/ \-/
# | | +----- LB 2..1 (No memory lock features enabled)
# | +--------- BLB0 2..1 (No restrictions for SPM or LPM accessing the Application section)
# +--------------- BLB1 2..1 (No restrictions for SPM or LPM accessing the Boot Loader section)

+ 321
- 0
doc/HAND_WIRE.md View File

@@ -0,0 +1,321 @@
# Quantum Hand-wiring Guide

Parts list:
* *x* keyswitches (MX, Matias, Gateron, etc)
* *x* diodes
* Keyboard plate (metal, plastic, cardboard, etc)
* Wire (strained for wiring to the Teensy, anything for the rows/columns)
* Soldering iron set at 600ºF or 315ºC (if temperature-controlled)
* Resin-cored solder (leaded or lead-free)
* Adequate ventilation/a fan
* Tweezers (optional)
* Wire cutters/snippers

## How the matrix works (why we need diodes)

The microcontroller (in this case, the Teensy 2.0) will be setup up via the firmware to send a logical 1 to the columns, one at a time, and read from the rows, all at once - this process is called matrix scanning. The matrix is a bunch of open switches that, by default, don't allow any current to pass through - the firmware will read this as no keys being pressed. As soon as you press one key down, the logical 1 that was coming from the column the keyswitch is attached to gets passed through the switch and to the corresponding row - check out the following 2x2 example:

Column 0 being scanned Column 1 being scanned
x x
col0 col1 col0 col1
| | | |
row0 ---(key0)---(key1) row0 ---(key0)---(key1)
| | | |
row1 ---(key2)---(key3) row1 ---(key2)---(key3)

The `x` represents that the column/row associated has a value of 1, or is HIGH. Here, we see that no keys are being pressed, so no rows get an `x`. For one keyswitch, keep in mind that one side of the contacts is connected to its row, and the other, its column.

When we press `key0`, `col0` gets connected to `row0`, so the values that the firmware receives for that row is `0b01` (the `0b` here means that this is a bit value, meaning all of the following digits are bits - 0 or 1 - and represent the keys in that column). We'll use this notation to show when a keyswitch has been pressed, to show that the column and row are being connected:

Column 0 being scanned Column 1 being scanned
x x
col0 col1 col0 col1
| | | |
x row0 ---(-+-0)---(key1) row0 ---(-+-0)---(key1)
| | | |
row1 ---(key2)---(key3) row1 ---(key2)---(key3)

We can now see that `row0` has an `x`, so has the value of 1. As a whole, the data the firmware receives when `key0` is pressed is

col0: 0b01
col1: 0b00
│└row0
└row1

A problem arises when you start pressing more than one key at a time. Looking at our matrix again, it should become pretty obvious:

Column 0 being scanned Column 1 being scanned
x x
col0 col1 col0 col1
| | | |
x row0 ---(-+-0)---(-+-1) x row0 ---(-+-0)---(-+-1)
| | | |
x row1 ---(key2)---(-+-3) x row1 ---(key2)---(-+-3)

Remember that this ^ is still connected to row1

The data we get from that is:

col0: 0b11
col1: 0b11
│└row0
└row1

Which isn't accurate, since we only have 3 keys pressed down, not all 4. This behavior is called ghosting, and only happens in odd scenarios like this, but can be much more common on a bigger keyboard. The way we can get around this is by placing a diode after the keyswitch, but before it connects to its row. A diode only allows current to pass through one way, which will protect our other columns/rows from being activated in the previous example. We'll represent a dioded matrix like this;

Column 0 being scanned Column 1 being scanned
x x
col0 col1 col0 col1
│ │ | │
(key0) (key1) (key0) (key1)
! │ ! │ ! | ! │
row0 ─────┴────────┘ │ row0 ─────┴────────┘ │
│ │ | │
(key2) (key3) (key2) (key3)
! ! ! !
row1 ─────┴────────┘ row1 ─────┴────────┘

In practical applications, the black line of the diode will be placed facing the row, and away from the keyswitch - the `!` in this case is the diode, where the gap represents the black line. A good way to remember this is to think of this symbol: `>|`

Now when we press the three keys, invoking what would be a ghosting scenario:

Column 0 being scanned Column 1 being scanned
x x
col0 col1 col0 col1
│ │ │ │
(┌─┤0) (┌─┤1) (┌─┤0) (┌─┤1)
! │ ! │ ! │ ! │
x row0 ─────┴────────┘ │ x row0 ─────┴────────┘ │
│ │ │ │
(key2) (┌─┘3) (key2) (┌─┘3)
! ! ! !
row1 ─────┴────────┘ x row1 ─────┴────────┘

Things act as they should! Which will get us the following data:

col0: 0b01
col1: 0b11
│└row0
└row1

The firmware can then use this correct data to detect what it should do, and eventually, what signals it needs to send to the OS.

## The actual hand-wiring

### Getting things in place

When starting this, you should have all of your stabilisers and keyswitches already installed (and optionally keycaps). If you're using a Cherry-type stabiliser (plate-mounted only, obviously), you'll need to install that before your keyswitches. If you're using Costar ones, you can installed them afterwards.

To make things easier on yourself, make sure all of the keyswitches are oriented the same way (if they can be - not all layouts support this). Despite this, it's important to remember that the contacts on the keyswitches are completely symmetrical. We'll be using the keyswitch's left side contact for wiring the rows, and the right side one for wiring the columns.

Get your soldering iron heated-up and collect the rest of the materials from the part list at the beginning of the guide. Place your keyboard so that the bottoms of the keyswitches are accessible - it may be a good idea to place it on a cloth to protect your keyswitches/keycaps.

Before continuing, plan out where you're going to place your Teensy. If you're working with a board that has a large (6.25u) spacebar, it may be a good idea to place it in-between switches against the plate. Otherwise, you may want to trim some of the leads on the keyswitches where you plan on putting it - this will make it a little harder to solder the wire/diodes, but give you more room to place the Teensy.

### Preparing the diodes

It's a little easier to solder the diodes in place if you bend them at a 90º angle immediately after the black line - this will help to make sure you put them on the right way (direction matters), and in the correct position. The diodes will look like this when bent (with longer leads):

┌─────┬─┐
───┤ │ ├─┐
└─────┴─┘ │

We'll be using the long lead at the bent end to connect it to the elbow (bent part) of the next diode, creating the row.

### Soldering the diodes

Starting at the top-left switch, place the diode (with tweezers if you have them) on the switch so that the diode itself is vertically aligned, and the black line is facing toward you. The straight end of the diode should be touching the left contact on the switch, and the bent end should be facing to the right and resting on the switch there, like this:

│o
┌┴┐ o
│ │ O
├─┤
└┬┘
└─────────────

Letting the diode rest, grab your solder, and touch both it and the soldering iron to the left contact at the same time - the rosin in the solder should make it easy for the solder to flow over both the diode and the keyswitch contact. The diode may move a little, and if it does, carefully position it back it place by grabbing the bent end of the diode - the other end will become hot very quickly. If you find that it's moving too much, using needle-nose pliers of some sort may help to keep the diode still when soldering.

The smoke that the rosin releases is harmful, so be careful not to breath it or get it in your eyes/face.

After soldering things in place, it may be helpful to blow on the joint to push the smoke away from your face, and cool the solder quicker. You should see the solder develop a matte (not shiney) surface as it solidifies. Keep in mind that it will still be very hot afterwards, and will take a couple minutes to be cool to touch. Blow on it will accelerate this process.

When the first diode is complete, the next one will need to be soldered to both the keyswitch, and the previous diode at the new elbow. That will look something like this:

│o │o
┌┴┐ o ┌┴┐ o
│ │ O │ │ O
├─┤ ├─┤
└┬┘ └┬┘
└────────────────┴─────────────

After completing a row, use the wire cutters to trim the excess wire from the tops of the diodes, and from the right side on the final switch. This process will need to completed for each row you have.

When all of the diodes are completely soldered, it's a good idea to quickly inspect each one to ensure that your solder joints are solid and sturdy - repairing things after this is possible, but more difficult.

### Soldering the columns

You'll have some options in the next process - it's a good idea to insulate the column wires (since the diodes aren't), but if you're careful enough, you can use exposed wires for the columns - it's not recommended, though. If you're using single-cored wire, stripping the plastic off of the whole wire and feeding it back on is probably the best option, but can be difficult depending on the size and materials. You'll want to leave parts of the wire exposed where you're going to be solder it onto the keyswitch.

If you're using stranded wire, it's probably easiest to just use a lot of small wires to connect each keyswitch along the column. It's possible to use one and melt through the insulation, but this isn't recommended, will produce even more harmful fumes, and can ruin your soldering iron.

Before beginning to solder, it helps to have your wire pre-bent (if using single-cored), or at least have an idea of how you're going to route the column (especially if you're making a staggered board). Where you go in particular doesn't matter too much, as we'll be basing our keymap definitions on how it was wired - just make sure every key in a particular row is in a unique column, and that they're in order from left to right.

If you're not using any insulation, you can try to keep the column wires elevated, and solder them near the tips of the keyswitch contacts - if the wires are sturdy enough, they won't short out to the row wiring an diodes.

### Wiring things to the Teensy

Now that the matrix itself is complete, it's time to connect what you've done to the Teensy. You'll be needing the number of pins equal to your number of columns + your number of rows. There are some pins on the Teensy that are special, like D6 (the LED on the chip), or some of the UART, SPI, I2C, or PWM channels, but only avoid those if you're planning something in addition to a keyboard. If you're unsure about wanting to add something later, you should have enough pins in total to avoid a couple.

The pins you'll absolutely have to avoid are: GND, VCC, AREF, and RST - all the others are usable and accessible in the firmware.

Place the Teensy where you plan to put it - you'll have to cut wires to length in the next step, and you'll want to make sure they reach.

Starting with the first column on the right side, measure out how much wire you'll need to connect it to the first pin on the Teensy - it helps to pick a side that you'll be able to work down, to keep the wires from overlapping too much. It may help to leave a little bit of slack so things aren't too tight. Cut the piece of wire, and solder it to the Teensy, and then the column - you can solder it anywhere along the column, but it may be easiest at the keyswitch. Just be sure the wire doesn't separate from the keyswitch when soldering.

As you move from column to column, it'll be helpful to write the locations of the pins down. We'll use this data to setup the matrix in the future.

When you're done with the columns, start with the rows in the same process, from top to bottom, and write them all down. Again, you can solder anywhere along the row, as long as it's after the diode - soldering before the diode (on the keyswitch side) will cause that row not to work.

As you move along, be sure that the Teensy is staying in place - recutting and soldering the wires is a pain!

### Getting some basic firmware set-up

From here, you should have a working keyboard with the correct firmware. Before we attach the Teensy permanently to the keyboard, let's quickly get some firmware loaded onto the Teensy so we can test each keyswitch.

To start out, download [the firmware](https://github.com/jackhumbert/qmk_firmware/) - we'll be using my (Jack's) fork of TMK called QMK/Quantum. We'll be doing a lot from the Terminal/command prompt, so get that open, along with a decent text editor like [Sublime Text](http://www.sublimetext.com/).

The first thing we're going to do is create a new project using the script in the root directory of the firmware. In your terminal, run this command with `<project_name>` replaced by the name of your project - it'll need to be different from any other project in the `keyboard/` folder:

util/new_project.sh <project_name>

You'll want to navigate to the `keyboard/<project_name>/` folder by typing, like the print-out from the script specifies:

cd keyboard/<project_name>

#### config.h

The first thing you're going to want to modify is the `config.h` file. Find `MATRIX_ROWS` and `MATRIX_COLS` and them to match the dimensions of your keyboard's matrix.

Farther down are `MATRIX_ROW_PINS` and `MATRIX_COL_PINS`. Change their definitions to match how you wired up your matrix (looking from the top of the keyboard, the rows run top-to-bottom and the columns run left-to-right). Likewise, change the definition of `UNUSED_PINS` to match the pins you did not use (this will save power).

#### \<project_name\>.h

The next file you'll want to look at is `<project_name>.h`. You're going to want to rewrite the `KEYMAP` definition - the format and syntax here is extremely important, so pay attention to how things are setup. The first half of the definition are considered the arguments - this is the format that you'll be following in your keymap later on, so you'll want to have as many k*xy* variables here as you do keys. The second half is the part that the firmware actually looks at, and will contain gaps depending on how you wired your matrix.

We'll dive into how this will work with the following example. Say we have a keyboard like this:

┌───┬───┬───┐
│ │ │ │
├───┴─┬─┴───┤
│ │ │
└─────┴─────┘

This can be described by saying the top row is 3 1u keys, and the bottom row is 2 1.5u keys. The difference between the two rows is important, because the bottom row has an unused column spot (3 v 2). Let's say that this is how we wired the columns:

┌───┬───┬───┐
│ ┋ │ ┋ │ ┋ │
├─┋─┴─┬─┴─┋─┤
│ ┋ │ ┋ │
└─────┴─────┘

The middle column is unused on the bottom row in this example. Our `KEYMAP` definition would look like this:

#define KEYMAP( \
k00, k01, k02, \
k10, k11, \
) \
{ \
{ k00, k01, k02 }, \
{ k10, KC_NO, k11 }, \
}

Notice how the top half is spaced to resemble our physical layout - this helps us understand which keys are associated with which columns. The bottom half uses the keycode `KC_NO` where there is no keyswitch wired in. It's easiest to keep the bottom half aligned in a grid to help us make sense of how the firmware actually sees the wiring.

Let's say that instead, we wired our keyboard like this (a fair thing to do):

┌───┬───┬───┐
│ ┋ │ ┋│ ┋ │
├─┋─┴─┬┋┴───┤
│ ┋ │┋ │
└─────┴─────┘

This would require our `KEYMAP` definition to look like this:

#define KEYMAP( \
k00, k01, k02, \
k10, k11, \
) \
{ \
{ k00, k01, k02 }, \
{ k10, k11, KC_NO }, \
}

Notice how the `k11` and `KC_NO` switched places to represent the wiring, and the unused final column on the bottom row. Sometimes it'll make more sense to put a keyswitch on a particular column, but in the end, it won't matter, as long as all of them are accounted for. You can use this process to write out the `KEYMAP` for your entire keyboard - be sure to remember that your keyboard is actually backwards when looking at the underside of it.

#### keymaps/default.c

This is the actual keymap for your keyboard, and the main place you'll make changes as you perfect your layout. `default.c` is the file that gets pull by default when typing `make`, but you can make other files as well, and specify them by typing `make KEYMAP=<variant>`, which will pull `keymaps/<variant>.c`.

The basis of a keymap is its layers - by default, layer 0 is active. You can activate other layers, the highest of which will be referenced first. Let's start with our base layer.

Using our previous example, let's say we want to create the following layout:

┌───┬───┬───┐
│ A │ 1 │ H │
├───┴─┬─┴───┤
│ TAB │ SPC │
└─────┴─────┘

This can be accomplished by using the following `keymaps` definition:

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = KEYMAP( /* Base */
KC_A, KC_1, KC_H, \
KC_TAB, KC_SPC \
),
};

Note that the layout of the keycodes is similar to the physical layout of our keyboard - this make it much easier to see what's going on. A lot of the keycodes should be fairly obvious, but for a full list of them, check out [tmk_code/doc/keycode.txt](https://github.com/jackhumbert/qmk_firmware/blob/master/tmk_core/doc/keycode.txt) - there are also a lot of aliases to condense your keymap file.

It's also important to use the `KEYMAP` function we defined earlier - this is what allows the firmware to associate our intended readable keymap with the actual wiring.

#### Compiling your firmware

After you've written out your entire keymap, you're ready to get the firmware compiled and onto your Teensy. Before compiling, you'll need to get your [development environment set-up](https://github.com/jackhumbert/qmk_firmware/blob/master/keyboard/planck/PCB_GUIDE.md#setting-up-the-environment) - you can skip the dfu-programmer instructions, but you'll need to download and install the [Teensy Loader](https://www.pjrc.com/teensy/loader.html) to get the firmware on your Teensy.

Once everything is installed, running `make` in the terminal should get you some output, and eventually a `<project_name>.hex` file in that folder. If you're having trouble with this step, see the end of the guide for the trouble-shooting section.

Once you have your `<project_name>.hex` file, open up the Teensy loader application, and click the file icon. From here, navigate to your `QMK/keyboard/<project_name>/` folder, and select the `<project_name>.hex` file. Plug in your keyboard and press the button on the Teensy - you should see the LED on the device turn off once you do. The Teensy Loader app will change a little, and the buttons should be clickable - click the download button (down arrow), and then the reset button (right arrow), and your keyboard should be ready to go!

#### Testing your firmware

Carefully flip your keyboard over, open up a new text document, and try typing - you should get the characters that you put into your keymap. Test each key, and note the ones that aren't working. Here's a quick trouble-shooting guide for non-working keys:

0. Flip the keyboard back over and short the keyswitch's contacts with a piece wire - this will eliminate the possibility of the keyswitch being bad and needing to be replaced.
1. Check the solder points on the keyswitch - these need to be plump and whole. If you touch it with a moderate amount of force and it comes apart, it's not strong enough.
2. Check the solder joints on the diode - if the diode is loose, part of your row may register, while the other may not.
3. Check the solder joints on the columns - if your column wiring is loose, part or all of the column may not work.
4. Check the solder joints on both sides of the wires going to/from the Teensy - the wires need to be fully soldered and connect to both sides.
5. Check the <project_name>.h file for errors and incorrectly placed `KC_NO`s - if you're unsure where they should be, instead duplicate a k*xy* variable.
6. Check to make sure you actually compiled the firmware and flashed the Teensy correctly. Unless you got error messages in the terminal, or a pop-up during flashing, you probably did everything correctly.

If you've done all of these things, keep in mind that sometimes you might have had multiple things affecting the keyswitch, so it doesn't hurt to test the keyswitch by shorting it out at the end.

#### Securing the Teensy, finishing your hardware, getting fancier firmware

Now that you have a working board, it's time to get things in their permanent positions. I've often used liberal amounts of hot glue to secure and insulate things, so if that's your style, start spreading that stuff like butter. Otherwise, double-sided tape is always an elegant solution, and electrical tape is a distant second. Due to the nature of these builds, a lot of this part is up to you and how you planned (or didn't plan) things out.

There are a lot of possibilities inside the firmware - check out the [README](https://github.com/jackhumbert/qmk_firmware/blob/master/README.md) for a full feature list, and dive into the different project (Planck, Ergodox EZ, etc) to see how people use all of them. You can always stop by [the OLKB subreddit for help!](http://reddit.com/r/olkb)

## Trouble-shooting compiling

### Windows

#### fork: Resource temporarily unavailable

http://www.avrfreaks.net/forum/windows-81-compilation-error

### Mac

### Linux

+ 151
- 0
doc/PCB_GUIDE.md View File

@@ -0,0 +1,151 @@
# Planck Firmware Guide

## Setting up the environment

### Windows
1. Install [MHV AVR Tools](https://infernoembedded.com/sites/default/files/project/MHV_AVR_Tools_20131101.exe). Disable smatch, but **be sure to leave the option to add the tools to the PATH checked**.
2. Install [MinGW](https://sourceforge.net/projects/mingw/files/Installer/mingw-get-setup.exe/download). During installation, uncheck the option to install a graphical user interface. **DO NOT change the default installation folder.** The scripts depend on the default location.
3. Clone this repository. [This link will download it as a zip file, which you'll need to extract.](https://github.com/jackhumbert/qmk_firmware/archive/master.zip) Open the extracted folder in Windows Explorer.
4. Right-click on the 1-setup-path-win batch script, select "Run as administrator", and accept the User Account Control prompt. Press the spacebar to dismiss the success message in the command prompt that pops up.
5. Right-click on the 2-setup-environment-win batch script, select "Run as administrator", and accept the User Account Control prompt. This part may take a couple of minutes, and you'll need to approve a driver installation, but once it finishes, your environment is complete!


### Mac

If you're using homebrew, you can use the following commands:

brew tap osx-cross/avr
brew install avr-libc
brew install dfu-programmer

Otherwise, these instructions will work:

1. Install Xcode from the App Store.
2. Install the Command Line Tools from `Xcode->Preferences->Downloads`.
3. Install [DFU-Programmer][dfu-prog].

### Linux
1. Install AVR GCC with your favorite package manager.
2. Install [DFU-Programmer][dfu-prog].

Note that, since it will be directly accessing USB hardware, the
`dfu-programmer` program needs to be run as root.

## Verify Your Installation
1. Clone the following repository: https://github.com/jackhumbert/qmk_firmware
2. Open a Terminal and `cd` into `qmk_firmware/keyboard/planck`
3. Run `make`. This should output a lot of information about the build process.

## Using the built-in functions

Here is a list of some of the functions available from the command line:

* `make clean`: clean the environment - may be required in-between builds
* `make`: compile the code
* `make KEYMAP=<keymap>`: compile with the extended keymap file `extended_keymaps/extended_keymap_<keymap>.c`
* `make dfu`: build and flash the layout to the PCB
* `make dfu-force`: build and force-flash the layout to the PCB (may be require for first flash)

Generally, the instructions to flash the PCB are as follows:

1. Make changes to the appropriate keymap file
2. Save the file
3. `make clean`
4. Press the reset button on the PCB/press the key with the `RESET` keycode
5. `make <arguments> dfu` - use the necessary `KEYMAP=<keymap>` and/or `COMMON=true` arguments here.

## Troubleshooting
If you see something like this

0 [main] sh 13384 sync_with_child: child 9716(0x178) died before initialization with status code 0xC0000142
440 [main] sh 13384 sync_with_child: *** child state waiting for longjmp
/usr/bin/sh: fork: Resource temporarily unavailable

after running 'make' on Windows than you are encountering a very popular issue with WinAVR on Windows 8.1 and 10.
You can easily fix this problem by replacing msys-1.0.dll in WinAVR/utils/bin with [this one](http://www.madwizard.org/download/electronics/msys-1.0-vista64.zip).
Restart your system and everything should work fine!


If you see this

dfu-programmer atmega32u4 erase
process_begin: CreateProcess(NULL, dfu-programmer atmega32u4 erase, ...) failed.
make (e=2): The system cannot find the file specified.
make: *** [dfu] Error 2

when trying to 'make dfu' on Windows you need to copy the dfu-programmer.exe to qmk_firmware/keyboard/planck.


## Quantum MK Firmware

### Keymap

Unlike the other keymaps, prefixing the keycodes with `KC_` is required. A full list of the keycodes is available [here](https://github.com/jackhumbert/qmk_firmware/blob/master/tmk_core/doc/keycode.txt). For the keycodes available only in the extended keymap, see this [header file](https://github.com/jackhumbert/qmk_firmware/blob/master/quantum/keymap_common.h).

You can use modifiers with keycodes like this:

LCTL(KC_C)
Which will generate Ctrl+c. These are daisy-chainable, meaning you can do things like:

LCTL(LALT(KC_C))
That will generate Ctrl+Alt+c. The entire list of these functions is here:

* `LCTL()`: Left control
* `LSFT()` / `S()`: Left shift
* `LALT()`: Left alt/opt
* `LGUI()`: Left win/cmd
* `RCTL()`: Right control
* `RSFT()`: Right shift
* `RALT()`: Right alt/opt
* `RGUI()`: Right win/cmd

`S(KC_1)`-like entries are useful in writing keymaps for the Planck.

### Other keycodes

A number of other keycodes have been added that you may find useful:

* `CM_<key>`: the Colemak equivalent of a key (in place of `KC_<key>`), when using Colemak in software (`CM_O` generates `KC_SCLN`)
* `RESET`: jump to bootloader for flashing (same as press the reset button)
* `BL_STEP`: step through the backlight brightnesses
* `BL_<0-15>`: set backlight brightness to 0-15
* `BL_DEC`: lower the backlight brightness
* `BL_INC`: raise the backlight brightness
* `BL_TOGG`: toggle the backlight on/off

### Function layers

The extended keymap extends the number of function layers from 32 to the near-infinite value of 256. Rather than using `FN<num>` notation (still available, but limited to `FN0`-`FN31`), you can use the `FUNC(<num>)` notation. `F(<num>)` is a shortcut for this.

The function actions are unchanged, and you can see the full list of them [here](https://github.com/jackhumbert/tmk_keyboard/blob/master/common/action_code.h). They are explained in detail [here](https://github.com/jackhumbert/tmk_keyboard/blob/master/doc/keymap.md#2-action).

### Macros

Macros have been setup in the `keymaps/keymap_default.c` file so that you can use `M(<num>)` to access a macro in the `action_get_macro` section on your keymap. The switch/case structure you see here is required, and is setup for `M(0)` - you'll need to copy and paste the code to look like this (e.g. to support `M(3)`):

switch(id) {
case 0:
return MACRODOWN(TYPE(KC_A), END);
break;
case 1:
return MACRODOWN(TYPE(KC_B), END);
break;
case 2:
return MACRODOWN(TYPE(KC_C), END);
break;
case 3:
return MACRODOWN(TYPE(KC_D), END);
break;
}
return MACRO_NONE;

`MACRODOWN()` is a shortcut for `(record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)` which tells the macro to execute when the key is pressed. Without this, the macro will be executed on both the down and up stroke.

[cygwin]: https://www.cygwin.com/
[mingw]: http://www.mingw.org/
[mhv]: https://infernoembedded.com/products/avr-tools
[winavr]: http://winavr.sourceforge.net/
[crosspack]: http://www.obdev.at/products/crosspack/index.html
[dfu-prog]: http://dfu-programmer.sourceforge.net/

+ 62
- 0
doc/POWER.txt View File

@@ -0,0 +1,62 @@
Time to Sleep
=============
USB suspend no activity on USB line for 3ms
No Interaction no user interaction
matrix has no change
matrix has no switch on


AVR Power Management
====================

V-USB suspend
USB suspend
http://vusb.wikidot.com/examples

MCUSR MCU Status Register
WDRF Watchdog Reset Flag
BORF
EXTRF
PORF Power-on Reset Flag

SMCR Sleep Mode Control Register
SE Sleep Enable
SM2:0
#define set_sleep_mode(mode) \
#define SLEEP_MODE_IDLE (0)
#define SLEEP_MODE_ADC _BV(SM0)
#define SLEEP_MODE_PWR_DOWN _BV(SM1)
#define SLEEP_MODE_PWR_SAVE (_BV(SM0) | _BV(SM1))
#define SLEEP_MODE_STANDBY (_BV(SM1) | _BV(SM2))
#define SLEEP_MODE_EXT_STANDBY (_BV(SM0) | _BV(SM1) | _BV(SM2))


ACSR Analog Comparator Control and Status Register
To disable Analog Comparator
ACSR = 0x80;
or
ACSR &= ~_BV(ACIE);
ACSR |= _BV(ACD);

ACD: Analog Comparator Disable
When this bit is written logic one, the power to the Analog Comparator is
switched off. This bit can be set at any time to turn off the Analog
Comparator. This will reduce power consumption in Active and Idle mode.
When changing the ACD bit, the Analog Comparator Interrupt must be disabled
by clearing the ACIE bit in ACSR. Otherwise an interrupt can occur when
the bit is changed.

DIDR1 Digital Input Disable Register 1
AIN1D
AIN0D
When this bit is written logic one, the digital input buffer on the AIN1/0 pin is disabled. The corresponding PIN Register bit will always read as zero when this bit is set. When an analog signal is applied to the AIN1/0 pin and the digital input from this pin is not needed, this bit should be written logic one to reduce power consumption in the digital input buffer.


PRR Power Reduction Register
PRTWI
PRTIM2
PRTIM0
PRTIM1
PRSPI
PRUSART0
PRADC

+ 243
- 0
doc/TMK_README.md View File

@@ -0,0 +1,243 @@
# TMK Documenation

Features
--------
These features can be used in your keyboard.

* Multi-layer Keymap - Multiple keyboard layouts with layer switching
* Mouse key - Mouse control with keyboard
* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up
* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
* USB NKRO - 120 keys(+ 8 modifiers) simultaneously
* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device
* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols
* User Function - Customizable function of key with writing code
* Macro - Very primitive at this time
* Keyboard Tricks - Oneshot modifier and modifier with tapping feature
* Debug Console - Messages for debug and interaction with firmware
* Virtual DIP Switch - Configurations stored EEPROM(Boot Magic)
* Locking CapsLock - Mechanical switch support for CapsLock
* Breathing Sleep LED - Sleep indicator with charm during USB suspend
* Backlight - Control backlight levels



Projects
--------
You can find some keyboard specific projects under `converter` and `keyboard` directory.

## Main projects

### OLKB products
* [planck](keyboard/planck/) - [Planck] Ortholinear 40% keyboard
* [preonic](keyboard/preonic/) - [Preonic] Ortholinear 50% keyboard
* [atomic](keyboard/atomic/) - [Atomic] Ortholinear 60% keyboard

### Ergodox EZ
* [ergodox_ez](keyboard/ergodox_ez) - [Ergodox_EZ] Assembled split keyboard

## Other projects

### converter
* [ps2_usb](converter/ps2_usb/) - [PS/2 keyboard to USB][GH_ps2]
* [adb_usb](converter/adb_usb/) - [ADB keyboard to USB][GH_adb]
* [m0110_usb](converter/m0110_usb) - [Macintosh 128K/512K/Plus keyboard to USB][GH_m0110]
* [terminal_usb](converter/terminal_usb/) - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
* [news_usb](converter/news_usb/) - [Sony NEWS keyboard to USB][GH_news]
* [x68k_usb](converter/x68k_usb/) - [Sharp X68000 keyboard to USB][GH_x68k]
* [sun_usb](converter/sun_usb/) - [Sun] to USB(type4, 5 and 3?)
* [pc98_usb](converter/pc98_usb/) - [PC98] to USB
* [usb_usb](converter/usb_usb/) - USB to USB(experimental)
* [ascii_usb](converter/ascii_usb/) - ASCII(Serial console terminal) to USB
* [ibm4704_usb](converter/ibm4704_usb) - [IBM 4704 keyboard Converter][GH_ibm4704]

### keyboard
* [hhkb](keyboard/hhkb/) - [Happy Hacking Keyboard pro][GH_hhkb] hasu's main board
* [gh60](keyboard/gh60/) - [GH60] DIY 60% keyboard [prototype][GH60_proto] hasu's second board
* [hbkb](keyboard/hbkb/) - [Happy Buckling spring keyboard][GH_hbkb](IBM Model M 60% mod)
* [hid_liber](keyboard/hid_liber/) - [HID liberation][HID_liber] controller (by alaricljs)
* [phantom](keyboard/phantom/) - [Phantom] keyboard (by Tranquilite)
* [IIgs_Standard](keyboard/IIgs/) - Apple [IIGS] keyboard mod(by JeffreySung)
* [macway](keyboard/macway/) - [Compact keyboard mod][GH_macway] [retired]
* [KMAC](keyboard/kmac/) - Korean custom keyboard
* [Lightsaber](keyboard/lightsaber/) - Korean custom keyboard
* [Infinity](keyboard/infinity/) - Massdrop [Infinity keyboard][Infinity]
* [NerD](keyboard/nerd/) - Korean custom keyboard
* [KittenPaw](keyboard/kitten_paw) - Custom Majestouch controller
* [Lightpad](keyboard/lightpad) - Korean custom keypad
* [ghost_squid](keyboard/ghost_squid/) - [The Ghost Squid][ghost_squid] controller for [Cooler Master QuickFire XT][cmxt]

### Extenal projects using tmk_keyboard
* [ErgoDox_cub-uanic][cub-uanic] - Split Ergonomic Keyboard [ErgoDox][ergodox_org]
* [mcdox][mcdox_tmk] - [mcdox][mcdox]


[GH_macway]: http://geekhack.org/showwiki.php?title=Island:11930
[GH_hhkb]: http://geekhack.org/showwiki.php?title=Island:12047
[GH_ps2]: http://geekhack.org/showwiki.php?title=Island:14618
[GH_adb]: http://geekhack.org/showwiki.php?title=Island:14290
[GH_hhkb_bt]: http://geekhack.org/showwiki.php?title=Island:20851
[GH_m0110]: http://geekhack.org/showwiki.php?title=Island:24965
[GH_news]: http://geekhack.org/showwiki.php?title=Island:25759
[GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272
[GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060
[GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483
[GH_ibm4704]: http://geekhack.org/index.php?topic=54706.0
[HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions
[Phantom]: http://geekhack.org/index.php?topic=26742
[GH60]: http://geekhack.org/index.php?topic=34959
[GH60_proto]: http://geekhack.org/index.php?topic=37570.0
[PC98]: http://en.wikipedia.org/wiki/NEC_PC-9801
[Sun]: http://en.wikipedia.org/wiki/Sun-3
[IIGS]: http://en.wikipedia.org/wiki/Apple_IIGS
[Infinity]: https://www.massdrop.com/buy/infinity-keyboard-kit
[ghost_squid]: http://deskthority.net/wiki/Costar_replacement_controllers#The_Ghost_Squid
[cmxt]: http://gaming.coolermaster.com/en/products/keyboards/quickfirext/
[ergodox_org]: http://ergodox.org/
[cub-uanic]: https://github.com/cub-uanic/tmk_keyboard/tree/master/keyboard/ergodox
[mcdox]: https://github.com/DavidMcEwan/mcdox
[mcdox_tmk]: https://github.com/DavidMcEwan/tmk_keyboard/tree/master/keyboard/mcdox
[Planck]: http://olkb.co/planck
[Preonic]: http://olkb.co/preonic
[Atomic]: http://olkb.co/atomic
[Ergodox_EZ]: https://www.indiegogo.com/projects/ergodox-ez-an-incredible-mechanical-keyboard


License
-------
**GPLv2** or later. Some protocol files are under **Modified BSD License**.

Third party libraries like LUFA, PJRC and V-USB have their own license respectively.



Build Firmware and Program Controller
-------------------------------------
See [doc/build.md](tmk_core/doc/build.md), or the README in the particular keyboard/* folder.



Change your keymap
------------------
See [doc/keymap.md](tmk_core/doc/keymap.md).



Magic Commands
--------------
To see help press `Magic` + `H`.

`Magic` key combination is `LShift` + `RShift` in many project, but `Power` key on ADB converter.
`Magic` keybind can be vary on each project, check `config.h` in project directory.

Following commands can be also executed with `Magic` + key. In console mode `Magic` keybind is not needed.

----- Command Help -----
c: enter console mode
d: toggle debug enable
x: toggle matrix debug
k: toggle keyboard debug
m: toggle mouse debug
v: print device version & info
t: print timer count
s: print status
e: print eeprom config
n: toggle NKRO
0/F10: switch to Layer0
1/F1: switch to Layer1
2/F2: switch to Layer2
3/F3: switch to Layer3
4/F4: switch to Layer4
PScr: power down/remote wake-up
Caps: Lock Keyboard(Child Proof)
Paus: jump to bootloader



Boot Magic Configuration - Virtual DIP Switch
---------------------------------------------
Boot Magic are executed during boot up time. Press Magic key below then plug in keyboard cable.
Note that you must use keys of **Layer 0** as Magic keys. These settings are stored in EEPROM so that retain your configure over power cycles.

To avoid configuring accidentally additive salt key `KC_SPACE` also needs to be pressed along with the following configuration keys. The salt key is configurable in `config.h`. See [tmk_core/common/bootmagic.h](tmk_core/common/bootmagic.h).

#### General
- Skip reading EEPROM to start with default configuration(`ESC`)
- Clear configuration stored in EEPROM to reset configuration(`Backspace`)

#### Bootloader
- Kick up Bootloader(`B`)

#### Debug
- Debug enable(`D`)
- Debug matrix enable(`D`+`X`)
- Debug keyboard enable(`D`+`K`)
- Debug mouse enable(`D`+`M`)

#### Keymap
- Swap Control and CapsLock(`Left Control`)
- Change CapsLock to Control(`Caps Lock`)
- Swap LeftAlt and Gui(`Left Alt`)
- Swap RightAlt and Gui(`Right Alt`)
- Disable Gui(`Left Gui`)
- Swap Grave and Escape(`Grave`)
- Swap BackSlash and BackSpace(`Back Slash`)
- Enable NKRO on boot(`N`)

#### Default Layer
- Set Default Layer to 0(`0`)
- Set Default Layer to 1(`1`)
- Set Default Layer to 2(`2`)
- Set Default Layer to 3(`3`)
- Set Default Layer to 4(`4`)
- Set Default Layer to 5(`5`)
- Set Default Layer to 6(`6`)
- Set Default Layer to 7(`7`)



Mechanical Locking support
--------------------------
This feature makes it possible for you to use mechanical locking switch for `CapsLock`, `NumLock`
or `ScrollLock`. To enable this feature define these macros in `config.h` and use `KC_LCAP`, `KC_LN
UM` or `KC_LSCR` in keymap for locking key instead of normal `KC_CAPS`, `KC_NLCK` or `KC_SLCK`. Res
ync option tries to keep switch state consistent with keyboard LED state.
#define LOCKING_SUPPORT_ENABLE
#define LOCKING_RESYNC_ENABLE



Start Your Own Project
-----------------------
**TBD**



Debugging
--------
Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack.

You can use xprintf() to display debug info on `hid_listen`, see `tmk_core/common/xprintf.h`.



Files and Directories
-------------------
### Top
* tmk_core/ - core library
* keyboard/ - keyboard projects
* converter/ - protocol converter projects
* doc/ - documents



Coding Style
-------------
- Doesn't use Tab to indent, use 4-spaces instead.



Other Keyboard Firmware Projects
------------------
You can learn a lot about keyboard firmware from these. See [doc/other_projects.md](tmk_core/doc/other_projects.md).

+ 160
- 0
doc/USB_NKRO.txt View File

@@ -0,0 +1,160 @@
USB NKRO MEMO
=============
2010/12/09


References
----------
USB - boot mode, NKRO, compatibility, etc...
http://geekhack.org/showthread.php?t=13162
NKey Rollover - Overview, Testing Methodology, and Results
http://geekhack.org/showwiki.php?title=NKey+Rollover+-+Overview+Testing+Methodology+and+Results
dfj's NKRO(2010/06)
http://geekhack.org/showpost.php?p=191195&postcount=251
http://geekhack.org/showthread.php?p=204389#post204389


Terminology
---------
NKRO
ghost
matrix
mechanical with diodes
membrane


OS Support Status
-----------------
USB NKRO is possible *without* a custom driver.
At least following OS's supports.
Windows7 64bit
WindowsXP
Windows2000 SP4
Ubuntu10.4(Linux 2.6)
MacOSX(To be tested)


Custom Driver for USB NKRO
--------------------------
NOT NEEDED
at least when using following report formats on Windows, Linux or MacOSX.


USB NKRO methods
----------------
1. Virtual keyboards
Keyboard can increase its KRO by using virtual keyboards with Standard or Extended report.
If the keyboard has 2 virtual keyboard with Standard report(6KRO), it gets 12KRO.
Using this method means the keyboard is a composite device.

2. Extended report
It needs large report size for this method to achieve NKRO.
If a keyboard has 101keys, it needs 103byte report. It seems to be inefficient.

3. Bitmap report
If the keyboard has less than 128keys, 16byte report will be enough for NKRO.
The 16byte report seems to be reasonable cost to get NKRO.


Report Format
-------------
Other report formats than followings are possible, though these format are typical one.

1. Standard 8bytes
modifiers(bitmap) 1byte
reserved 1byte(not used)
keys(array) 1byte*6
Standard report can send 6keys plus 8modifiers simultaneously.
Standard report is used by most keyboards in the marketplace.
Standard report is identical to boot protocol report.
Standard report is hard to suffer from compatibility problems.

2. Extended standard 16,32,64bytes
modifiers(bitmap) 1byte
reserved 1byte(not used)
keys(array) 1byte*(14,32,62)
Extended report can send N-keys by using N+2bytes.
Extended report is expected to be compatible with boot protocol.

3. Bitmap 16,32,64bytes
keys(bitmap) (16,32)bytes
Bitmap report can send at most 128keys by 16bytes and 256keys by 32bytes.
Bitmap report can achieve USB NKRO efficiently in terms of report size.
Bitmap report needs a deliberation for boot protocol implementation.
Bitmap report descriptor sample:
0x05, 0x01, // Usage Page (Generic Desktop),
0x09, 0x06, // Usage (Keyboard),
0xA1, 0x01, // Collection (Application),
// bitmap of modifiers
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
// LED output report
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),
0x95, 0x01, // Report Count (1),
0x75, 0x03, // Report Size (3),
0x91, 0x03, // Output (Constant),
// bitmap of keys
0x95, (REPORT_BYTES-1)*8, // Report Count (),
0x75, 0x01, // Report Size (1),
0x15, 0x00, // Logical Minimum (0),
0x25, 0x01, // Logical Maximum(1),
0x05, 0x07, // Usage Page (Key Codes),
0x19, 0x00, // Usage Minimum (0),
0x29, (REPORT_BYTES-1)*8-1, // Usage Maximum (),
0x81, 0x02, // Input (Data, Variable, Absolute),
0xc0 // End Collection
where REPORT_BYTES is a report size in bytes.


Considerations
--------------
Compatibility
boot protocol
minor/old system
Some BIOS doesn't send SET_PROTOCOL request, a keyboard can't switch to boot protocol mode.
This may cause a problem on a keyboard which uses other report than Standard.
Reactivity
USB polling time
OS/Driver processing time


Windows Problem
---------------
1. Windows accepts only 6keys in case of Standard report.
It should be able to send 6keys plus 8modifiers.
2. Windows accepts only 10keys in case of 16bytes Extended report.
It should be able to send 14keys plus 8modifiers.
3. Windows accepts only 18keys in case of 32bytes Extended report.
It should be able to send 30keys plus 8modifiers.
If keys are pressed in excess of the number, wrong keys are registered on Windows.

This problem will be reportedly fixed soon.(2010/12/05)
http://forums.anandtech.com/showpost.php?p=30873364&postcount=17


Tools for testing NKRO
----------------------
Browser App:
http://www.microsoft.com/appliedsciences/content/projects/KeyboardGhostingDemo.aspx
http://random.xem.us/rollover.html

Windows:
AquaKeyTest.exe http://geekhack.org/showthread.php?t=6643

Linux:
xkeycaps
xev
showkeys

EOF

+ 26
- 0
doc/VAGRANT_GUIDE.md View File

@@ -0,0 +1,26 @@
# Quick Start Directions

This project includes a Vagrantfile that will allow you to build a new firmware for your keyboard very easily without major changes to your primary operating system. This also ensures that when you clone the project and perform a build, you have the exact same environment as anyone else using the Vagrantfile to build. This makes it much easier for people to help you troubleshoot any issues you encounter.

## Requirements

Using the `/Vagrantfile` in this repository requires you have [Vagrant](http://www.vagrantup.com/) as well as [VirtualBox](https://www.virtualbox.org/) (or [VMware Workstation](https://www.vmware.com/products/workstation) and [Vagrant VMware plugin](http://www.vagrantup.com/vmware) but the (paid) VMware plugin requires a licensed copy of VMware Workstation/Fusion).

*COMPATIBILITY NOTICE* Certain versions of Virtualbox 5 appear to have an incompatibility with the Virtualbox extensions installed in the boxes in this Vagrantfile. If you encounter any issues with the /vagrant mount not succeeding, please upgrade your version of Virtualbox to at least 5.0.12.

Other than having Vagrant and Virtualbox installed and possibly a restart of your computer afterwards, you can simple run a 'vagrant up' anywhere inside the folder where you checked out this project and it will start a Linux virtual machine that contains all the tools required to build this project. There is a post Vagrant startup hint that will get you off on the right foot, otherwise you can also reference the build documentation below.

Build Firmware and Program Controller
-------------------------------------
See [/doc/BUIDE_GUIDE.md](/doc/BUILD_GUIDE.md), or the README in the particular keyboard/* folder.

Change your keymap
------------------
See [/doc/keymap.md](/doc/keymap.md).

## Flashing the firmware

The "easy" way to flash the firmware is using a tool from your host OS like the Teensy programming app. [ErgoDox EZ](/keyboard/ergodox_ez/readme.md) gives a great example.

If you want to program via the command line you can uncomment the ['modifyvm'] lines in the Vagrantfile to enable the USB passthrough into Linux and then program using the command line tools like dfu-util/dfu-programmer or you can install the Teensy CLI version.

+ 187
- 0
doc/build_old.md View File

@@ -0,0 +1,187 @@
Build Firmware and Program Controller
=====================================

## This guide may be out-dated - use doc/BUILD_GUIDE.md instead

Download and Install
--------------------
### 1. Install Tools

1. **Toolchain** On Windows install [MHV AVR Tools][mhv] for AVR GCC compiler and [Cygwin][cygwin](or [MinGW][mingw]) for shell terminal. On Mac you can use [CrossPack][crosspack]. On Linux you can install AVR GCC (and avr-libc) with your favorite package manager or run the avr_setup.sh script in the root of this repository.

2. **Programmer** On Windows install [Atmel FLIP][flip]. On Mac and Linux install [dfu-programmer][dfu-prog].

3. **Driver** On Windows you start DFU bootloader on the chip first time you will see 'Found New Hardware Wizard' to install driver. If you install device driver properly you can find chip name like 'ATmega32U4' under 'LibUSB-Win32 Devices' tree on 'Device Manager'. If not you shall need to update its driver on 'Device Manager'. You will find the driver in `FLIP` install directory like: C:\Program Files (x86)\Atmel\Flip 3.4.5\usb\. In case of `dfu-programmer` use its driver.

If you use PJRC Teensy you don't need step 2 and 3 above, just get [Teensy loader][teensy-loader].


### 2. Download source
You can find firmware source at github:

- <https://github.com/tmk/tmk_keyboard>

If you are familiar with `Git` tools you are recommended to use it but you can also download zip archive from:

- <https://github.com/tmk/tmk_keyboard/archive/master.zip>


Build firmware
--------------
### 1. Open terminal
Open terminal window to get access to commands. Use Cygwin(or MingGW) `shell terminal` in Windows or `Terminal.app` on Mac OSX. In Windows press `Windows` key and `R` then enter `cmd` in 'Run command' dialog showing up.

### 2. Change directory
Move to project directory in the firmware source.

cd tmk_keyboard/{'keyboard' or 'converter'}/<project>

### 3. Make
Build firmware using GNU `make` command. You'll see `<project>_<variant>.hex` file in that directory unless something unexpected occurs in build process.


make -f Makefile.<variant> clean
make -f Makefile.<variant>




Program Controller
------------------
Now you have **hex** file to program on current directory. This **hex** is only needed to program your controller, other files are used for development and you may leave and forget them.

### 1. Start bootloader
How to program controller depends on controller chip and its board design. To program AVR USB chips you'll need to start it up in bootloader mode. Most of boards with the chip have a push button to let bootloader come up. Consult with your controller board manual.

### 2. Program with DFU bootloader
Stock AVR USB chip including ATmega32U4 has DFU bootloader by factory default. `FLIP` is a DFU programmer on Windows offered by Atmel. Open source command line tool `dfu-programmer` also supports AVR chips, it runs on Linux, Mac OSX and even Windows.

To program AVR chip with DFU bootloader use `FLIP` or `dfu-programmer`.
If you have a proper program command in `Makefile` just type this.

`FLIP` has two version of tool, GUI app and command line program. If you want GUI see tutorial below.
To use command line tool run this command. Note that you need to set PATH variable properly.

$ make -f Makefile.<variant> flip

Or to program with `dfu-programmer` run:

$ make -f Makefile.<variant> dfu

#### FLIP GUI tutorial
1. On menu bar click Device -> Select, then. `ATmega32u4`.
2. On menu bar click Settings -> Communication -> USB, then click 'Open' button on 'USB Port Connection' dialog.
At this point you'll see grey-outed widgets on the app get colored and ready.

3. On menu bar click File -> Load HEX File, then select your firmware hex file on File Selector dialog.
4. On 'Operations Flow' panel click 'Run' button to load the firmware binary to the chip. Note that you should keep 'Erase', 'Blank Check', 'Program' and 'Verify' check boxes selected.
5. Re-plug USB cord or click 'Start Application' button to restart your controller.
Done.

See also these instructions if you need.

- <http://code.google.com/p/micropendous/wiki/LoadingFirmwareWithFLIP>
- <http://www.atmel.com/Images/doc7769.pdf>


### 3. Program with Teensy Loader
If you have PJRC Teensy see instruction of `Teensy Loader`.

- <http://www.pjrc.com/teensy/loader.html>

Or use this command if you have command line version of Teensy Loader installed.

$ make -f Makefile.<variant> teensy


### 4. Program with Other programmer
You may want to use other programmer like `avrdude` with AVRISPmkII, Arduino or USBasp. In that case you can still use make target `program` for build with configuring `PROGRAM_CMD` in Makefile.

$ make -f Makefile.<variant> program


[cygwin]: https://www.cygwin.com/
[mingw]: http://www.mingw.org/
[mhv]: https://infernoembedded.com/products/avr-tools
[winavr]: http://winavr.sourceforge.net/
[crosspack]: http://www.obdev.at/products/crosspack/index.html
[flip]: http://www.atmel.com/tools/FLIP.aspx
[dfu-prog]: http://dfu-programmer.sourceforge.net/
[teensy-loader]:http://www.pjrc.com/teensy/loader.html



Makefile Options
----------------
### 1. MCU and Frequency.

MCU = atmega32u4 # Teensy 2.0
#MCU = at90usb1286 # Teensy++ 2.0
F_CPU = 16000000

Set your MCU and its clock in Hz.

# Boot Section Size in *bytes*
# Teensy halfKay 512
# Atmel DFU loader 4096
# LUFA bootloader 4096
OPT_DEFS += -DBOOTLOADER_SIZE=4096

If you are using PJRC Teensy use `512` for `BOOTLOADER_SIZE`, otherwise use `4096` unless you are sure.

### 2. Features
Optional. Note that ***comment out*** with `#` to disable them.

BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = yes # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA
#BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality

### 3. Programmer
Optional. Set proper command for your controller, bootloader and programmer. This command can be used with `make program`. Not needed if you use `FLIP`, `dfu-programmer` or `Teensy Loader`.

# avrdude with AVRISPmkII
PROGRAM_CMD = avrdude -p $(MCU) -c avrispmkII -P USB -U flash:w:$(TARGET).hex

# avrdude with USBaspLoader
PROGRAM_CMD = avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex

# avrdude with arduino
PROGRAM_CMD = avrdude -p $(MCU) -c arduino -P COM1 -b 57600 -U flash:w:$(TARGET).hex



Config.h Options
----------------
### 1. Magic command key combination

#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)))

### 2. Mechanical Locking Support for CapsLock

/* Mechanical locking CapsLock support. Use KC_LCAP instead of KC_CAPS in keymap */
#define CAPSLOCK_LOCKING_ENABLE
/* Locking CapsLock re-synchronize hack */
#define CAPSLOCK_LOCKING_RESYNC_ENABLE

### 3. Disable Debug and Print

/* disable debug print */
#define NO_DEBUG

/* disable print */
#define NO_PRINT

### 4. Disable Action Features

#define NO_ACTION_LAYER
#define NO_ACTION_TAPPING
#define NO_ACTION_ONESHOT
#define NO_ACTION_MACRO
#define NO_ACTION_FUNCTION

***TBD***

+ 261
- 0
doc/keycode.txt View File

@@ -0,0 +1,261 @@
Keycode Symbol Table
====================
Keycodes are defined in `common/keycode.h`.
Range of 00-A4 and E0-E7 are identical with HID Usage:
<http://www.usb.org/developers/devclass_docs/Hut1_11.pdf>
Virtual keycodes are defined out of above range to support special actions.


Keycode Symbol Short name Description
--------------------------------------------------------------------------------
KC_NO 00 Reserved (no event indicated)
KC_ROLL_OVER 01 Keyboard ErrorRollOver
KC_POST_FAIL 02 Keyboard POSTFail
KC_UNDEFINED 03 Keyboard ErrorUndefined
KC_A 04 Keyboard a and A
KC_B 05 Keyboard b and B
KC_C 06 Keyboard c and C
KC_D 07 Keyboard d and D
KC_E 08 Keyboard e and E
KC_F 09 Keyboard f and F
KC_G 0A Keyboard g and G
KC_H 0B Keyboard h and H
KC_I 0C Keyboard i and I
KC_J 0D Keyboard j and J
KC_K 0E Keyboard k and K
KC_L 0F Keyboard l and L
KC_M 10 Keyboard m and M
KC_N 11 Keyboard n and N
KC_O 12 Keyboard o and O
KC_P 13 Keyboard p and P
KC_Q 14 Keyboard q and Q
KC_R 15 Keyboard r and R
KC_S 16 Keyboard s and S
KC_T 17 Keyboard t and T
KC_U 18 Keyboard u and U
KC_V 19 Keyboard v and V
KC_W 1A Keyboard w and W
KC_X 1B Keyboard x and X
KC_Y 1C Keyboard y and Y
KC_Z 1D Keyboard z and Z
KC_1 1E Keyboard 1 and !
KC_2 1F Keyboard 2 and @
KC_3 20 Keyboard 3 and #
KC_4 21 Keyboard 4 and $
KC_5 22 Keyboard 5 and %
KC_6 23 Keyboard 6 and ^
KC_7 24 Keyboard 7 and &
KC_8 25 Keyboard 8 and *
KC_9 26 Keyboard 9 and (
KC_0 27 Keyboard 0 and )
KC_ENTER KC_ENT 28 Keyboard Return (ENTER)
KC_ESCAPE KC_ESC 29 Keyboard ESCAPE
KC_BSPACE KC_BSPC 2A Keyboard DELETE (Backspace)
KC_TAB 2B Keyboard Tab
KC_SPACE KC_SPC 2C Keyboard Spacebar
KC_MINUS KC_MINS 2D Keyboard - and (underscore)
KC_EQUAL KC_EQL 2E Keyboard = and +
KC_LBRACKET KC_LBRC 2F Keyboard [ and {
KC_RBRACKET KC_RBRC 30 Keyboard ] and }
KC_BSLASH KC_BSLS 31 Keyboard \ and |
KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~
KC_SCOLON KC_SCLN 33 Keyboard ; and :
KC_QUOTE KC_QUOT 34 Keyboard ‘ and “
KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde
KC_COMMA KC_COMM 36 Keyboard, and <
KC_DOT 37 Keyboard . and >
KC_SLASH KC_SLSH 38 Keyboard / and ?
KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock
KC_F1 3A Keyboard F1
KC_F2 3B Keyboard F2
KC_F3 3C Keyboard F3
KC_F4 3D Keyboard F4
KC_F5 3E Keyboard F5
KC_F6 3F Keyboard F6
KC_F7 40 Keyboard F7
KC_F8 41 Keyboard F8
KC_F9 42 Keyboard F9
KC_F10 43 Keyboard F10
KC_F11 44 Keyboard F11
KC_F12 45 Keyboard F12
KC_PSCREEN KC_PSCR 46 Keyboard PrintScreen1
KC_SCKLOCK KC_SLCK 47 Keyboard Scroll Lock11
KC_PAUSE KC_PAUS 48 Keyboard Pause1
KC_INSERT KC_INS 49 Keyboard Insert1
KC_HOME 4A Keyboard Home1
KC_PGUP 4B Keyboard PageUp1
KC_DELETE KC_DELETE 4C Keyboard Delete Forward
KC_END 4D Keyboard End1
KC_PGDOWN KC_PGDN 4E Keyboard PageDown1
KC_RIGHT KC_RGHT 4F Keyboard RightArrow1
KC_LEFT 50 Keyboard LeftArrow1
KC_DOWN 51 Keyboard DownArrow1
KC_UP 52 Keyboard UpArrow1
KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11
KC_KP_SLASH KC_PSLS 54 Keypad /1
KC_KP_ASTERISK KC_PAST 55 Keypad *
KC_KP_MINUS KC_PMNS 56 Keypad -
KC_KP_PLUS KC_PPLS 57 Keypad +
KC_KP_ENTER KC_PENT 58 Keypad ENTER5
KC_KP_1 KC_P1 59 Keypad 1 and End
KC_KP_2 KC_P2 5A Keypad 2 and Down Arrow
KC_KP_3 KC_P3 5B Keypad 3 and PageDn
KC_KP_4 KC_P4 5C Keypad 4 and Left Arrow
KC_KP_5 KC_P5 5D Keypad 5
KC_KP_6 KC_P6 5E Keypad 6 and Right Arrow
KC_KP_7 KC_P7 5F Keypad 7 and Home
KC_KP_8 KC_P8 60 Keypad 8 and Up Arrow
KC_KP_9 KC_P9 61 Keypad 9 and PageUp
KC_KP_0 KC_P0 62 Keypad 0 and Insert
KC_KP_DOT KC_PDOT 63 Keypad . and Delete
KC_NONUS_BSLASH KC_NUBS 64 Keyboard Non-US \ and |
KC_APPLICATION KC_APP 65 Keyboard Application10
KC_POWER 66 Keyboard Power9
KC_KP_EQUAL KC_PEQL 67 Keypad =
KC_F13 68 Keyboard F13
KC_F14 69 Keyboard F14
KC_F15 6A Keyboard F15
KC_F16 6B Keyboard F16
KC_F17 6C Keyboard F17
KC_F18 6D Keyboard F18
KC_F19 6E Keyboard F19
KC_F20 6F Keyboard F20
KC_F21 70 Keyboard F21
KC_F22 71 Keyboard F22
KC_F23 72 Keyboard F23
KC_F24 73 Keyboard F24
KC_EXECUTE 74 Keyboard Execute
KC_HELP 75 Keyboard Help
KC_MENU 76 Keyboard Menu
KC_SELECT 77 Keyboard Select
KC_STOP 78 Keyboard Stop
KC_AGAIN 79 Keyboard Again
KC_UNDO 7A Keyboard Undo
KC_CUT 7B Keyboard Cut
KC_COPY 7C Keyboard Copy
KC_PASTE 7D Keyboard Paste
KC_FIND 7E Keyboard Find
KC__MUTE 7F Keyboard Mute
KC__VOLUP 80 Keyboard Volume Up
KC__VOLDOWN 81 Keyboard Volume Down
KC_LOCKING_CAPS 82 Keyboard Locking Caps Lock12
KC_LOCKING_NUM 83 Keyboard Locking Num Lock12
KC_LOCKING_SCROLL 84 Keyboard Locking Scroll Lock12
KC_KP_COMMA KC_PCMM 85 Keypad Comma27
KC_KP_EQUAL_AS400 86 Keypad Equal Sign29
KC_INT1 KC_RO 87 Keyboard International115,28
KC_INT2 KC_KANA 88 Keyboard International216
KC_INT3 KC_JYEN 89 Keyboard International317
KC_INT4 KC_HENK 8A Keyboard International418
KC_INT5 KC_MHEN 8B Keyboard International519
KC_INT6 8C Keyboard International620
KC_INT7 8D Keyboard International721
KC_INT8 8E Keyboard International822
KC_INT9 8F Keyboard International922
KC_LANG1 90 Keyboard LANG125
KC_LANG2 91 Keyboard LANG226
KC_LANG3 92 Keyboard LANG330
KC_LANG4 93 Keyboard LANG431
KC_LANG5 94 Keyboard LANG532
KC_LANG6 95 Keyboard LANG68
KC_LANG7 96 Keyboard LANG78
KC_LANG8 97 Keyboard LANG88
KC_LANG9 98 Keyboard LANG98
KC_ALT_ERASE 99 Keyboard Alternate Erase7
KC_SYSREQ 9A Keyboard SysReq/Attention1
KC_CANCEL 9B Keyboard Cancel
KC_CLEAR 9C Keyboard Clear
KC_PRIOR 9D Keyboard Prior
KC_RETURN 9E Keyboard Return
KC_SEPARATOR 9F Keyboard Separator
KC_OUT A0 Keyboard Out
KC_OPER A1 Keyboard Oper
KC_CLEAR_AGAIN A2 Keyboard Clear/Again
KC_CRSEL A3 Keyboard CrSel/Props
KC_EXSEL A4 Keyboard ExSel
/* Modifiers */
KC_LCTRL KC_LCTL E0 Keyboard LeftControl
KC_LSHIFT KC_LSFT E1 Keyboard LeftShift
KC_LALT E2 Keyboard LeftAlt
KC_LGUI E3 Keyboard Left GUI(Windows/Apple/Meta key)
KC_RCTRL KC_RCTL E4 Keyboard RightControl
KC_RSHIFT KC_RSFT E5 Keyboard RightShift
KC_RALT E6 Keyboard RightAlt
KC_RGUI E7 Keyboard Right GUI(Windows/Apple/Meta key)

/*
* Virtual keycodes
*/
/* System Control */
KC_SYSTEM_POWER KC_PWR System Power Down
KC_SYSTEM_SLEEP KC_SLEP System Sleep
KC_SYSTEM_WAKE KC_WAKE System Wake
/* Consumer Page */
KC_AUDIO_MUTE KC_MUTE
KC_AUDIO_VOL_UP KC_VOLU
KC_AUDIO_VOL_DOWN KC_VOLD
KC_MEDIA_NEXT_TRACK KC_MNXT
KC_MEDIA_PREV_TRACK KC_MPRV
KC_MEDIA_STOP KC_MSTP
KC_MEDIA_PLAY_PAUSE KC_MPLY
KC_MEDIA_SELECT KC_MSEL
KC_MAIL KC_MAIL
KC_CALCULATOR KC_CALC
KC_MY_COMPUTER KC_MYCM
KC_WWW_SEARCH KC_WSCH
KC_WWW_HOME KC_WHOM
KC_WWW_BACK KC_WBAK
KC_WWW_FORWARD KC_WFWD
KC_WWW_STOP KC_WSTP
KC_WWW_REFRESH KC_WREF
KC_WWW_FAVORITES KC_WFAV
/* Mousekey */
KC_MS_UP KC_MS_U Mouse Cursor Up
KC_MS_DOWN KC_MS_D Mouse Cursor Down
KC_MS_LEFT KC_MS_L Mouse Cursor Left
KC_MS_RIGHT KC_MS_R Mouse Cursor Right
KC_MS_BTN1 KC_BTN1 Mouse Button 1
KC_MS_BTN2 KC_BTN2 Mouse Button 2
KC_MS_BTN3 KC_BTN3 Mouse Button 3
KC_MS_BTN4 KC_BTN4 Mouse Button 4
KC_MS_BTN5 KC_BTN5 Mouse Button 5
KC_MS_WH_UP KC_WH_U Mouse Wheel Up
KC_MS_WH_DOWN KC_WH_D Mouse Wheel Down
KC_MS_WH_LEFT KC_WH_L Mouse Wheel Left
KC_MS_WH_RIGHT KC_WH_R Mouse Wheel Right
KC_MS_ACCEL0 KC_ACL0 Mouse Acceleration 0
KC_MS_ACCEL1 KC_ACL1 Mouse Acceleration 1
KC_MS_ACCEL2 KC_ACL2 Mouse Acceleration 2
/* Fn key */
KC_FN0
KC_FN1
KC_FN2
KC_FN3
KC_FN4
KC_FN5
KC_FN6
KC_FN7
KC_FN8
KC_FN9
KC_FN10
KC_FN11
KC_FN12
KC_FN13
KC_FN14
KC_FN15
KC_FN16
KC_FN17
KC_FN18
KC_FN19
KC_FN20
KC_FN21
KC_FN22
KC_FN23
KC_FN24
KC_FN25
KC_FN26
KC_FN27
KC_FN28
KC_FN29
KC_FN30
KC_FN31

+ 599
- 0
doc/keymap.md View File

@@ -0,0 +1,599 @@
Keymap framework - how to define your keymap
============================================
***NOTE: This is not final version, may be inconsistent with source code and changed occasionally for a while.***

## 0. Keymap and layers
**Keymap** is comprised of multiple layers of key layout, you can define **32 layers** at most.
**Layer** is an array of **keycodes** to define **actions** for each physical keys.
respective layers can be validated simultaneously. Layers are indexed with 0 to 31 and higher layer has precedence.

Keymap: 32 Layers Layer: Keycode matrix
----------------- ---------------------
stack of layers array_of_keycode[row][column]
____________ precedence _______________________
/ / | high / ESC / F1 / F2 / F3 ....
31 /___________// | /-----/-----/-----/-----
30 /___________// | / TAB / Q / W / E ....
29 /___________/ | /-----/-----/-----/-----
: _:_:_:_:_:__ | : /LCtrl/ A / S / D ....
: / : : : : : / | : / : : : :
2 /___________// | 2 `--------------------------
1 /___________// | 1 `--------------------------
0 /___________/ V low 0 `--------------------------



### 0.1 Keymap status
Keymap has its state in two parameters:
**`default_layer`** indicates a base keymap layer(0-31) which is always valid and to be referred, **`keymap_stat`** is 16bit variable which has current on/off status of layers on its each bit.

Keymap layer '0' is usually `default_layer` and which is the only valid layer and other layers is initially off after boot up firmware, though, you can configured them in `config.h`.
To change `default_layer` will be useful when you switch key layout completely, say you want Colmak instead of Qwerty.

Initial state of Keymap Change base layout
----------------------- ------------------

31 31
30 30
29 29
: :
: : ____________
2 ____________ 2 / /
1 / / ,->1 /___________/
,->0 /___________/ | 0
| |
`--- default_layer = 0 `--- default_layer = 1
layer_state = 0x00000001 layer_state = 0x00000002

On the other hand, you shall change `layer_state` to overlay base layer with some layers for feature such as navigation keys, function key(F1-F12), media keys or special actions.

Overlay feature layer
--------------------- bit|status
____________ ---+------
31 / / 31 | 0
30 /___________// -----> 30 | 1
29 /___________/ -----> 29 | 1
: : | :
: ____________ : | :
2 / / 2 | 0
,->1 /___________/ -----> 1 | 1
| 0 0 | 0
| +
`--- default_layer = 1 |
layer_state = 0x60000002 <-'



### 0.2 Layer Precedence and Transparency
Note that ***higher layer has higher priority on stack of layers***, namely firmware falls down from top layer to bottom to look up keycode. Once it spots keycode other than **`KC_TRNS`**(transparent) on a layer it stops searching and lower layers aren't referred.

You can place `KC_TRNS` on overlay layer changes just part of layout to fall back on lower or base layer.
Key with `KC_TRANS` doesn't has its own keycode and refers to lower valid layers for keycode, instead.
See example below.


### 0.3 Keymap Example
Keymap is **`keymaps[]`** C array in fact and you can define layers in it with **`KEYMAP()`** C macro and keycodes. To use complex actions you need to define `Fn` keycode in **`fn_actions[]`** array.

This is a keymap example for [HHKB](http://en.wikipedia.org/wiki/Happy_Hacking_Keyboard) keyboard.
This example has three layers, 'Qwerty' as base layer, 'Cursor' and 'Mousekey'.
In this example,

`Fn0` is a **momentary layer switching** key, you can use keys on Cursor layer while holding the key.

`Fn1` is a momentary layer switching key with tapping feature, you can get semicolon **';'** with taping the key and switch layers while holding the key. The word **'tap'** or **'tapping'** mean to press and release a key quickly.

`Fn2` is a **toggle layer switch** key, you can stay switched layer after releasing the key unlike momentary switching.

You can find other keymap definitions in file `keymap.c` located on project directories.

static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* 0: Qwerty
* ,-----------------------------------------------------------.
* |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \| `|
* |-----------------------------------------------------------|
* |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|Backs|
* |-----------------------------------------------------------|
* |Contro| A| S| D| F| G| H| J| K| L|Fn1| '|Enter |
* |-----------------------------------------------------------|
* |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
* `-----------------------------------------------------------'
* |Gui|Alt |Space |Alt |Fn2|
* `-------------------------------------------'
*/
KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
LCTL,A, S, D, F, G, H, J, K, L, FN1, QUOT,ENT, \
LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH,RSFT,FN0, \
LGUI,LALT, SPC, RALT,FN2),
/* 1: Cursor(HHKB mode)
* ,-----------------------------------------------------------.
* |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
* |-----------------------------------------------------------|
* |Contro|VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
* |-----------------------------------------------------------|
* |Shift | | | | | | +| -|End|PgD|Dow|Shift | |
* `-----------------------------------------------------------'
* |Gui |Alt |Space |Alt |Gui|
* `--------------------------------------------'
*/
KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,UP, TRNS,BSPC, \
LCTL,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
LGUI,LALT, SPC, RALT,RGUI),
/* 2: Mousekey
* ,-----------------------------------------------------------.
* |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
* |-----------------------------------------------------------|
* |Tab | | | | | |MwL|MwD|MwU|MwR| | | |Backs|
* |-----------------------------------------------------------|
* |Contro| | | | | |McL|McD|McU|McR| | |Return |
* |-----------------------------------------------------------|
* |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
* `-----------------------------------------------------------'
* |Gui |Alt |Mb1 |Alt | |
* `--------------------------------------------'
* Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
*/
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
TAB, TRNS,TRNS,TRNS,TRNS,TRNS,WH_L,WH_D,WH_U,WH_R,TRNS,TRNS,TRNS,BSPC, \
LCTL,TRNS,ACL0,ACL1,ACL2,TRNS,MS_L,MS_D,MS_U,MS_R,TRNS,QUOT,ENT, \
LSFT,TRNS,TRNS,TRNS,TRNS,BTN3,BTN2,BTN1,BTN4,BTN5,SLSH,RSFT,TRNS, \
LGUI,LALT, BTN1, RALT,TRNS),
};

static const uint16_t PROGMEM fn_actions[] = {
ACTION_LAYER_MOMENTARY(1), // FN0
ACTION_LAYER_TAP_KEY(2, KC_SCLN), // FN1
ACTION_LAYER_TOGGLE(2), // FN2
};




## 1. Keycode
See [`common/keycode.h`](../common/keycode.h) or keycode table below for the detail. Keycode is internal **8bit code** to indicate action performed on key in keymap. Keycode has `KC_` prefixed symbol respectively. Most of keycodes like `KC_A` have simple action registers key to host on press and unregister on release, while some of other keycodes has some special actions like `Fn` keys, Media control keys, System control keys and Mousekeys.

***In `KEYMAP()` macro you should omit prefix part `KC_` of keycode to keep keymap compact.*** For example, just use `A` instead you place `KC_A` in `KEYMAP()`. Some keycodes has 4-letter **short name** in addition to descriptive name, you'll prefer short one in `KEYMAP()`.

### 1.0 Other key
- `KC_NO` for no action
- `KC_TRNS` for layer transparency (See above)

### 1.1 Normal key
- `KC_A` to `KC_Z`, `KC_1` to `KC_0` for alpha numeric key
- `KC_MINS`, `KC_EQL`, `KC_GRV`, `KC_RBRC`, `KC_LBRC`, `KC_COMM`, `KC_DOT`, `KC_BSLS`, `KC_SLSH`, `KC_SCLN`, `KC_QUOT`
- `KC_ESC`, `KC_TAB`, `KC_SPC`, `KC_BSPC`, `KC_ENT`, `KC_DEL`, `KC_INS`
- `KC_UP`, `KC_DOWN`, `KC_RGHT`, `KC_LEFT`, `KC_PGUP`, `KC_PGDN`, `KC_HOME`, `KC_END`
- `KC_CAPS`, `KC_NLCK`, `KC_SLCK`, `KC_PSCR`, `KC_PAUS`, `KC_APP`, `KC_F1` to `KC_F24`
- `KC_P1` to `KC_P0`, `KC_PDOT`, `KC_PCMM`, `KC_PSLS`, `KC_PAST`, `KC_PMNS`, `KC_PPLS`, `KC_PEQL`, `KC_PENT` for keypad.

### 1.2 Modifier
There are 8 modifiers which has discrimination between left and right.

- `KC_LCTL` and `KC_RCTL` for Control
- `KC_LSFT` and `KC_RSFT` for Shift
- `KC_LALT` and `KC_RALT` for Alt
- `KC_LGUI` and `KC_RGUI` for Windows key or Command key in Mac

### 1.3 Mousekey
- `KC_MS_U`, `KC_MS_D`, `KC_MS_L`, `KC_MS_R` for mouse cursor
- `KC_WH_U`, `KC_WH_D`, `KC_WH_L`, `KC_WH_R` for mouse wheel
- `KC_BTN1`, `KC_BTN2`, `KC_BTN3`, `KC_BTN4`, `KC_BTN5` for mouse buttons

### 1.4 System & Media key
- `KC_PWR`, `KC_SLEP`, `KC_WAKE` for Power, Sleep, Wake
- `KC_MUTE`, `KC_VOLU`, `KC_VOLD` for audio volume control
- `KC_MNXT`, `KC_MPRV`, `KC_MSTP`, `KC_MPLY`, `KC_MSEL` for media control
- `KC_MAIL`, `KC_CALC`, `KC_MYCM` for application launch
- `KC_WSCH`, `KC_WHOM`, `KC_WBAK`, `KC_WFWD`, `KC_WSTP`, `KC_WREF`, `KC_WFAV` for web browser operation

### 1.5 Fn key
`KC_FNnn` are keycodes for `Fn` key which not given any actions at the beginning unlike most of keycodes has its own inborn action. To use these keycodes in `KEYMAP()` you need to assign action you want at first. Action of `Fn` key is defined in `fn_actions[]` and its index of the array is identical with number part of `KC_FNnn`. Thus `KC_FN0` keycode indicates the action defined in first element of the array. ***32 `Fn` keys can be defined at most.***

### 1.6 Keycode Table
See keycode table in [`doc/keycode.txt`](./keycode.txt) for description of keycodes.

In regard to implementation side most of keycodes are identical with [HID usage][HID_usage](pdf) sent to host for real and some virtual keycodes are defined to support special actions.
[HID_usage]: http://www.usb.org/developers/hidpage/Hut1_12v2.pdf



## 2. Action
See [`common/action_code.h`](../common/action_code.h). Action is a **16bit code** and defines function to perform on events of a key like press, release, holding and tapping.

Most of keys just register 8bit scancode to host, but to support other complex features needs 16bit extended action codes internally. However, using 16bit action codes in keymap results in double size in memory compared to using just keycodes. To avoid this waste 8bit keycodes are used in `KEYMAP()` instead of action codes.

***You can just use keycodes of `Normal key`, `Modifier`, `Mousekey` and `System & Media key` in keymap*** to indicate corresponding actions instead of using action codes. While ***to use other special actions you should use keycode of `Fn` key defined in `fn_actions[]`.***


### 2.1 Key Action
This is a simple action that registers scancodes(HID usage in fact) to host on press event of key and unregister on release.

#### Parameters
+ **mods**: { ` MOD_LCTL`, ` MOD_LSFT`, ` MOD_LALT`, ` MOD_LGUI`,
` MOD_RCTL`, ` MOD_RSFT`, ` MOD_RALT`, ` MOD_RGUI` }
+ **key**: keycode


#### 2.1.1 Normal key and Modifier
***This action usually won't be used expressly in keymap*** because you can just use keycodes in `KEYMAP()` instead.

You can define these actions on *'A'* key and *'left shift'* modifier with:

ACTION_KEY(KC_A)
ACTION_KEY(KC_LSFT)

#### 2.1.2 Modified key
This action is comprised of strokes of modifiers and a key. `Macro` action is needed if you want more complex key strokes.

Say you want to assign a key to `Shift + 1` to get character *'!'* or `Alt + Tab` to switch application windows.

ACTION_MODS_KEY(MOD_LSFT, KC_1)
ACTION_MODS_KEY(MOD_LALT, KC_TAB)

Or `Alt,Shift + Tab` can be defined. `ACTION_MODS_KEY(mods, key)` requires **4-bit modifier state** and a **keycode** as arguments. See `keycode.h` for `MOD_BIT()` macro.

ACTION_MODS_KEY(MOD_LALT | MOD_LSFT, KC_TAB)

#### 2.1.3 Multiple Modifiers
Registers multiple modifiers with pressing a key. To specify multiple modifiers use `|`.

ACTION_MODS(MOD_ALT | MOD_LSFT)

#### 2.1.3 Modifier with Tap key([Dual role][dual_role])
Works as a modifier key while holding, but registers a key on tap(press and release quickly).


ACTION_MODS_TAP_KEY(MOD_RCTL, KC_ENT)



### 2.2 Layer Action
These actions operate layers of keymap.

#### Parameters
You can specify a **target layer** of action and **when the action is executed**. Some actions take a **bit value** for bitwise operation.


+ **layer**: `0`-`31`
+ **on**: { `ON_PRESS` | `ON_RELEASE` | `ON_BOTH` }
+ **bits**: 4-bit value and 1-bit mask bit


#### 2.2.1 Default Layer
Default Layer is a layer which always is valid and referred to when actions is not defined on other overlay layers.

This sets Default Layer to given parameter `layer` and activate it.

ACTION_DEFAULT_LAYER_SET(layer)


#### 2.2.2 Momentary
Turns on `layer` momentarily while holding, in other words it activates when key is pressed and deactivate when released.

ACTION_LAYER_MOMENTARY(layer)


#### 2.2.3 Toggle Switch
Turns on `layer` with first type(press and release) and turns off with next.

ACTION_LAYER_TOGGLE(layer)


#### 2.2.4 Momentary Switch with tap key
Turns on `layer` momentary while holding, but registers key on tap(press and release quickly).

ACTION_LAYER_TAP_KEY(layer, key)


#### 2.2.5 Momentary Switch with tap toggle
Turns on `layer` momentary while holding and toggles it with serial taps.

ACTION_LAYER_TAP_TOGGLE(layer)


#### 2.2.6 Invert state of layer
Inverts current state of `layer`. If the layer is on it becomes off with this action.

ACTION_LAYER_INVERT(layer, on)


#### 2.2.7 Turn On layer
Turns on layer state.

ACTION_LAYER_ON(layer, on)

Turns on layer state on press and turns off on release.

ACTION_LAYER_ON_OFF(layer)


#### 2.2.8 Turn Off layer
Turns off layer state.

ACTION_LAYER_OFF(layer, on)

Turns off layer state on press and activates on release.

ACTION_LAYER_OFF_ON(layer)


#### 2.2.9 Set layer
Turn on layer only.
`layer_state = (1<<layer) [layer: 0-31]`

ACTION_LAYER_SET(layer, on)

Turns on layer only and clear all layer on release..

ACTION_LAYER_SET_CLEAR(layer)


#### 2.2.10 Bitwise operation

**part** indicates which part of 32bit layer state(0-7). **bits** is 5-bit value. **on** indicates when the action is executed.

ACTION_LAYER_BIT_AND(part, bits, on)
ACTION_LAYER_BIT_OR(part, bits, on)
ACTION_LAYER_BIT_XOR(part, bits, on)
ACTION_LAYER_BIT_SET(part, bits, on)

These actions works with parameters as following code.

uint8_t shift = part*4;
uint32_t mask = (bits&0x10) ? ~(0xf<<shift) : 0;
uint32_t layer_state = layer_state <bitop> ((bits<<shift)|mask);


Default Layer also has bitwise operations, they are executed when key is released.

ACTION_DEFAULT_LAYER_BIT_AND(part, bits)
ACTION_DEFAULT_LAYER_BIT_OR(part, bits)
ACTION_DEFAULT_LAYER_BIT_XOR(part, bits)
ACTION_DEFAULT_LAYER_BIT_SET(part, bits)



### 2.3 Macro action
***TBD***

`Macro` action indicates complex key strokes.
MACRO( D(LSHIFT), D(D), END )
MACRO( U(D), U(LSHIFT), END )
MACRO( I(255), T(H), T(E), T(L), T(L), W(255), T(O), END )

#### 2.3.1 Macro Commands
- **I()** change interval of stroke.
- **D()** press key
- **U()** release key
- **T()** type key(press and release)
- **W()** wait
- **END** end mark

#### 2.3.2 Examples

***TODO: sample implementation***
See `keyboard/hhkb/keymap.c` for sample.



### 2.4 Function action
***TBD***

There are two type of action, normal `Function` and tappable `Function`.
These actions call user defined function with `id`, `opt`, and key event information as arguments.

#### 2.4.1 Function
To define normal `Function` action in keymap use this.

ACTION_FUNCTION(id, opt)

#### 2.4.2 Function with tap
To define tappable `Function` action in keymap use this.

ACTION_FUNCTION_TAP(id, opt)

#### 2.4.3 Implement user function
`Function` actions can be defined freely with C by user in callback function:

void keymap_call_function(keyrecord_t *event, uint8_t id, uint8_t opt)

This C function is called every time key is operated, argument `id` selects action to be performed and `opt` can be used for option. Function `id` can be 0-255 and `opt` can be 0-15.

`keyrecord_t` is comprised of key event and tap count. `keyevent_t` indicates which and when key is pressed or released. From `tap_count` you can know tap state, 0 means no tap. These information will be used in user function to decide how action of key is performed.

typedef struct {
keyevent_t event;
uint8_t tap_count;
} keyrecord_t;

typedef struct {
key_t key;
bool pressed;
uint16_t time;
} keyevent_t;

typedef struct {
uint8_t col;
uint8_t row;
} key_t;

***TODO: sample implementation***
See `keyboard/hhkb/keymap.c` for sample.



### 2.5 Backlight Action
These actions control the backlight.

#### 2.5.1 Change backlight level
Increase backlight level.

ACTION_BACKLIGHT_INCREASE()

Decrease backlight level.

ACTION_BACKLIGHT_DECREASE()

Step through backlight levels.

ACTION_BACKLIGHT_STEP()

Turn a specific backlight level on or off.

ACTION_BACKLIGHT_LEVEL(1)

#### 2.5.2 Turn on / off backlight
Turn the backlight on and off without changing level.

ACTION_BACKLIGHT_TOGGLE()



## 3. Layer switching Example
There are some ways to switch layer with 'Layer' actions.

### 3.1 Momentary switching
Momentary switching changes layer only while holding Fn key.

This action makes 'Layer 1' active(valid) on key press event and inactive on release event. Namely you can overlay a layer on lower layers or default layer temporarily with this action.

ACTION_LAYER_MOMENTARY(1)


Note that after switching on press the actions on destination layer(Layer 1) are performed.
***Thus you shall need to place an action to go back on destination layer***, or you will be stuck in destination layer without way to get back. Usually you need to place same action or 'KC_TRNS` on destination layer to get back.


### 3.2 Toggle switching
Toggle switching performed after releasing a key. With this action you can keep staying on the destination layer until you type the key again to return.

This performs toggle switching action of 'Layer 2'.

ACTION_LAYER_TOGGLE(2)



### 3.3 Momentary switching with Tap key
These actions switch a layer only while holding a key but register the key on tap. **Tap** means to press and release a key quickly.

ACTION_LAYER_TAP_KEY(2, KC_SCLN)

With this you can place a layer switching action on normal key like ';' without losing its original key register function. This action allows you to have layer switching action without necessity of a dedicated key. It means you can have it even on home row of keyboard.



### 3.4 Momentary switching with Tap Toggle
This switches layer only while holding a key but toggle layer with several taps. **Tap** means to press and release key quickly.

ACTION_LAYER_TAP_TOGGLE(1)

Number of taps can be configured with `TAPPING_TOGGLE` in `config.h`, `5` by default.



### 3.5 Momentary switching with Modifiers
This registers modifier key(s) simultaneously with layer switching.

ACTION_LAYER_MODS(2, MOD_LSFT | MOD_LALT)



## 4. Tapping
Tapping is to press and release a key quickly. Tapping speed is determined with setting of `TAPPING_TERM`, which can be defined in `config.h`, 200ms by default.

### 4.1 Tap Key
This is a feature to assign normal key action and modifier including layer switching to just same one physical key. This is a kind of [Dual role key][dual_role]. It works as modifier when holding the key but registers normal key when tapping.

Modifier with tap key:

ACTION_MODS_TAP_KEY(MOD_RSFT, KC_GRV)

Layer switching with tap key:

ACTION_LAYER_TAP_KEY(2, KC_SCLN)

[dual_role]: http://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys


### 4.2 Tap Toggle
This is a feature to assign both toggle layer and momentary switch layer action to just same one physical key. It works as momentary layer switch when holding a key but toggle switch with several taps.

ACTION_LAYER_TAP_TOGGLE(1)


### 4.3 Oneshot Modifier
This runs onetime effects which modify only on just one following key. It works as normal modifier key when holding down while oneshot modifier when tapping. The behavior of oneshot modifiers is similar to the [sticky keys](https://en.wikipedia.org/wiki/StickyKeys) functionality found in most operating systems.

ACTION_MODS_ONESHOT(MOD_LSFT)

Oneshot layer key:

ACTION_LAYER_ONESHOT(MY_LAYER)

Say you want to type 'The', you have to push and hold Shift key before type 't' then release it before type 'h' and 'e', otherwise you'll get 'THe' or 'the' unintentionally. With Oneshot Modifier you can tap Shift then type 't', 'h' and 'e' normally, you don't need to holding Shift key properly here. This mean you can release Shift before 't' is pressed down.

Oneshot effect is cancel unless following key is pressed down within `ONESHOT_TIMEOUT` of `config.h`. No timeout when it is `0` or not defined.

Most implementations of sticky keys allow you to lock a modifier by double tapping the modifier. The layer then remains locked untill the modifier is tapped again. To enable this behaviour for oneshot modifiers set `ONESHOT_TAP_TOGGLE` to the number taps required. The feature is disabled if `ONESHOT_TAP_TOGGLE<2` or not defined.


### 4.4 Tap Toggle Mods
Similar to layer tap toggle, this works as a momentary modifier when holding, but toggles on with several taps. A single tap will 'unstick' the modifier again.

ACTION_MODS_TAP_TOGGLE(MOD_LSFT)




## 5. Legacy Keymap
This was used in prior version and still works due to legacy support code in `common/keymap.c`. Legacy keymap doesn't support many of features that new keymap offers. ***It is not recommended to use Legacy Keymap for new project.***

To enable Legacy Keymap support define this macro in `config.h`.

#define USE_LEGACY_KEYMAP

Legacy Keymap uses two arrays `fn_layer[]` and `fn_keycode[]` to define Fn key. The index of arrays corresponds with postfix number of `Fn` key. Array `fn_layer[]` indicates destination layer to switch and `fn_keycode[]` has keycodes to send when tapping `Fn` key.

In following setting example, `Fn0`, `Fn1` and `Fn2` switch layer to 1, 2 and 2 respectively. `Fn2` registers `Space` key when tapping while `Fn0` and `Fn1` doesn't send any key.

static const uint8_t PROGMEM fn_layer[] = {
1, // Fn0
2, // Fn1
2, // Fn2
};

static const uint8_t PROGMEM fn_keycode[] = {
KC_NO, // Fn0
KC_NO, // Fn1
KC_SPC, // Fn2
};


## 6. Terminology
***TBD***
### keymap
is comprised of multiple layers.
### layer
is matrix of keycodes.
### key
is physical button on keyboard or logical switch on software.
### keycode
is codes used on firmware.
### action
is a function assigned on a key.
### layer transparency
Using transparent keycode one layer can refer key definition on other lower layer.
### layer precedence
Top layer has higher precedence than lower layers.
### tapping
is to press and release a key quickly.
### Fn key
is key which executes a special action like layer switching, mouse key, macro or etc.
### dual role key
<http://en.wikipedia.org/wiki/Modifier_key#Dual-role_keys>

+ 62
- 0
doc/other_projects.md View File

@@ -0,0 +1,62 @@
Other Keyboard Firmware Projects
================================
## PJRC USB Keyboard/Mouse Example[USB][PJRC][Teensy][AVR]
- <http://www.pjrc.com/teensy/usb_keyboard.html>
- <http://www.pjrc.com/teensy/usb_mouse.html>

## kbupgrade[USB][V-USB][AVR]
- <http://github.com/rhomann/kbupgrade>
- <http://geekhack.org/showwiki.php?title=Island:8406>

## c64key[USB][V-USB][AVR]
- <http://symlink.dk/projects/c64key/>

## rump[USB][V-USB][AVR]
- <http://mg8.org/rump/>
- <http://github.com/clee/rump>

## dulcimer[USB][V-USB][AVR]
- <http://www.schatenseite.de/dulcimer.html>

## humblehacker-keyboard[USB][LUFA][AVR][Ergo]
- <http://github.com/humblehacker>
- <http://www.humblehacker.com/keyboard/>
- <http://geekhack.org/showwiki.php?title=Island:6292>

## ps2avr[PS/2][AVR]
- <http://sourceforge.net/projects/ps2avr/>

## ErgoDox[Ergo][Split][USB][AVR]
- <http://geekhack.org/index.php?topic=22780.0>
- <https://github.com/benblazak/ergodox-firmware>
- <https://github.com/cub-uanic/tmk_keyboard>

## Suka's keyboard collection[Ergo][Split][3DPrinting][USB][AVR]
- <http://deskthority.net/workshop-f7/my-diy-keyboard-collection-or-how-i-became-a-kb-geek-t2534.html>
- <https://github.com/frobiac/adnw>

## bpiphany's AVR-Keyboard[PJRC][AVR][USB]
- <https://github.com/BathroomEpiphanies/AVR-Keyboard>
- <http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions>
- <http://deskthority.net/wiki/Phantom>

## USB-USB keyboard remapper[converter][USB-USB][AVR][Arduino]
- <http://forum.colemak.com/viewtopic.php?pid=10837>
- <https://github.com/darkytoothpaste/keymapper>

## USB-USB converter threads[converter][USB-USB]
- <http://deskthority.net/workshop-f7/is-remapping-a-usb-keyboard-using-teensy-possible-t2841-30.html>
- <http://geekhack.org/index.php?topic=19458.0>

## kbdbabel.org[converter][vintage][protocol][8051]
Great resource of vintage keyboard protocol information and code

- <http://www.kbdbabel.org/>

## Haata's kiibohd Controller[converter][vintage][protocol][AVR][PJRC][Cortex]
A lots of vintage keyboard protocol supports

- <http://gitorious.org/kiibohd-controller>

## Kinesis ergonomic keyboard firmware replacement[V-USB][LUFA][Ergo]
- <https://github.com/chrisandreae/kinesis-firmware>

+ 186
- 0
keyboard/tv44/Makefile View File

@@ -0,0 +1,186 @@
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device.
# Please customize your programmer settings(PROGRAM_CMD)
#
# make teensy = Download the hex file to the device, using teensy_loader_cli.
# (must have teensy_loader_cli installed).
#
# make dfu = Download the hex file to the device, using dfu-programmer (must
# have dfu-programmer installed).
#
# make flip = Download the hex file to the device, using Atmel FLIP (must
# have Atmel FLIP installed).
#
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
# (must have dfu-programmer installed).
#
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
# (must have Atmel FLIP installed).
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------

# Target file name (without extension).
TARGET = tv44

# Directory common source filess exist
TOP_DIR = ../..
TMK_DIR = ../../tmk_core

# Directory keyboard dependent files exist
TARGET_DIR = .

# # project specific files
SRC = tv44.c backlight.c

ifdef keymap
KEYMAP = $(keymap)
endif

ifdef KEYMAP
ifneq ("$(wildcard keymaps/$(KEYMAP).c)","")
KEYMAP_FILE = keymaps/$(KEYMAP).c
else
ifneq ("$(wildcard keymaps/$(KEYMAP)/keymap.c)","")
KEYMAP_FILE = keymaps/$(KEYMAP)/keymap.c
ifneq ("$(wildcard keymaps/$(KEYMAP)/makefile.mk)","")
include keymaps/$(KEYMAP)/makefile.mk
endif
else
$(error Keymap file does not exist)
endif
endif

else

ifneq ("$(wildcard keymaps/default.c)","")
KEYMAP_FILE = keymaps/default.c
else
KEYMAP_FILE = keymaps/default/keymap.c
endif

ifneq ("$(wildcard keymaps/default/makefile.mk)","")
include keymaps/default/makefile.mk
endif

endif

SRC := $(KEYMAP_FILE) $(SRC)

CONFIG_H = config.h

# MCU name
#MCU = at90usb1287
MCU = atmega32u4

# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency in Hz. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
#
# This will be an integer division of F_USB below, as it is sourced by
# F_USB after it has run through any CPU prescalers. Note that this value
# does not *change* the processor frequency - it should merely be updated to
# reflect the processor speed set externally so that the code can use accurate
# software delays.
F_CPU = 16000000

#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8

# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)

# Interrupt driven control endpoint task(+60)
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT


# Boot Section Size in *bytes*
# Teensy halfKay 512
# Teensy++ halfKay 1024
# Atmel DFU loader 4096
# LUFA bootloader 4096
# USBaspLoader 2048
OPT_DEFS += -DBOOTLOADER_SIZE=4096

# Build Options
# change to "no" to disable the options, or define them in the makefile.mk in
# the appropriate keymap folder that will get included automatically
#
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = no # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = no # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality
MIDI_ENABLE = no # MIDI controls
AUDIO_ENABLE = no # Audio output on port C6
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time.

# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend

ifdef KEYMAP

ifeq ("$(wildcard keymaps/$(KEYMAP).c)","")
ifneq ("$(wildcard keymaps/$(KEYMAP)/makefile.mk)","")
include keymaps/$(KEYMAP)/makefile.mk
endif
endif

else

ifneq ("$(wildcard keymaps/default/makefile.mk)","")
include keymaps/default/makefile.mk
endif

endif

ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
SRC := backlight.c $(SRC)
endif

# Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax

# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
VPATH += $(TMK_DIR)

include $(TOP_DIR)/quantum/quantum.mk

+ 37
- 0
keyboard/tv44/backlight.c View File

@@ -0,0 +1,37 @@

#include <avr/io.h>
#include "backlight.h"

uint8_t led_counter = 0;
uint8_t led_level = 0;

void bl_set()
{
led_counter++;
if (led_counter > 7) {
led_counter = 0;
}

if (led_counter < led_level) {
// output high
DDRB |= (1<<2);
PORTB |= (1<<2);
} else {
// Hi-Z
DDRB &= ~(1<<2);
PORTB &= ~(1<<2);
}
}

void backlight_init_ports()
{
DDRB &= ~(1<<2);
PORTB &= ~(1<<2);
backlight_init();
}

void backlight_set(uint8_t level)
{
led_level = level;
}

+ 89
- 0
keyboard/tv44/config.h View File

@@ -0,0 +1,89 @@
/*
Copyright 2012 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/

#ifndef CONFIG_H
#define CONFIG_H

#include "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6060
#define DEVICE_VER 0x0441
#define MANUFACTURER ME
#define PRODUCT tv44
#define DESCRIPTION Short Bus

/* key matrix size */
#define MATRIX_ROWS 4
#define MATRIX_COLS 12

/* Planck PCB default pin-out */
#define MATRIX_COL_PINS { D2, D3, D5, D6, B4, B6, F6, F5, F4, F1, F0, B3 }
#define MATRIX_ROW_PINS { D7, B5, F7, D4 }
#define UNUSED_PINS

/* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW

/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST

/* number of backlight levels */
#define BACKLIGHT_LEVELS 8

/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5

/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE

/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
)

/* ws2812 RGB LED */
#define ws2812_PORTREG PORTE
#define ws2812_DDRREG DDRE
#define ws2812_pin PE6
#define RGBLED_NUM 7 // Number of LEDs
#define RGBLIGHT_HUE_STEP 10
#define RGBLIGHT_SAT_STEP 17
#define RGBLIGHT_VAL_STEP 17

/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/

/* disable debug print */
//#define NO_DEBUG

/* disable print */
//#define NO_PRINT

/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION

#endif

+ 81
- 0
keyboard/tv44/keymaps/default/keymap.c View File

@@ -0,0 +1,81 @@
// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
// this is the style you want to emulate.

#include "tv44.h"
#include "action_layer.h"
#include "eeconfig.h"

extern keymap_config_t keymap_config;

// Each layer gets a name for readability, which is then used in the keymap matrix below.
// The underscores don't mean anything - you can have a layer called STUFF or any other name.
// Layer names don't all need to be of the same length, obviously, and you can also skip them
// entirely and just use numbers.
#define _QWERTY 0
#define _LOWER 3
#define _RAISE 4
#define _TB 7

// Macro name shortcuts
#define QWERTY M(_QWERTY)
#define LOWER M(_LOWER)
#define RAISE M(_RAISE)



// Fillers to make layering more clear
#define _______ KC_TRNS
#define XXXXXXX KC_NO

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {

/* Qwerty
* ,-----------------------------------------------------------------------------------.
* | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp |
* |------+------+------+------+------+-------------+------+------+------+------+------|
* | Esc | A | S | D | F | G | H | J | K | L | ; | " |
* |------+------+------+------+------+------|------+------+------+------+------+------|
* | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
* |------+------+------+------+------+------+------+------+------+------+------+------|
* | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right |
* `-----------------------------------------------------------------------------------'
*/

[_QWERTY] = { /* Qwerty */
{KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC},
{FUNC(0), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT},
{KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, FUNC(9)},
{KC_LCTL, KC_LGUI, KC_LALT, FUNC(1), XXXXXXX, XXXXXXX, XXXXXXX, FUNC(2), KC_RALT, KC_APP, XXXXXXX, KC_RCTL}
},

[_RAISE] = {
{S(KC_GRV), S(KC_1), S(KC_2), S(KC_3), S(KC_4), S(KC_5), S(KC_6), S(KC_7), S(KC_8), S(KC_9), S(KC_0), KC_BSPC},
{KC_TRNS, KC_TRNS, KC_TRNS, KC_PAUSE, KC_TRNS, KC_TRNS, KC_TRNS, S(KC_MINS), S(KC_EQL), S(KC_LBRC), S(KC_RBRC), S(KC_BSLS)},
{KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_ENT},
{KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, XXXXXXX, XXXXXXX, XXXXXXX, KC_TRNS, KC_MNXT, KC_MUTE, XXXXXXX, KC_MPLY}
},

[_LOWER] = {
{KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DELETE},
{KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS},
{KC_TRNS, KC_F11, KC_F12, KC_F13, KC_F14, KC_F15, KC_F16, KC_F17, KC_F18, KC_PGUP, KC_F20, KC_ENT},
{KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, XXXXXXX, XXXXXXX, XXXXXXX, KC_TRNS, KC_HOME, KC_PGDN, XXXXXXX, KC_END}
},

[_TB] = { /* Tab */
{KC_ESC, KC_CALC, KC_WHOM, KC_MAIL, KC_MYCM, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_TRNS},
{KC_TRNS, BL_STEP, KC_TRNS, KC_TRNS, RESET, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS},
{KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_ENT},
{KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, XXXXXXX, XXXXXXX, XXXXXXX, KC_TRNS, KC_LEFT, KC_DOWN, XXXXXXX, KC_RGHT}
}
};

const uint16_t PROGMEM fn_actions[] = {
[0] = ACTION_LAYER_TAP_KEY(_TB, KC_TAB),
[1] = ACTION_LAYER_TAP_KEY(_RAISE, KC_SPC),
[2] = ACTION_LAYER_TAP_KEY(_LOWER, KC_SPC),
};

void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) {

}

+ 34
- 0
keyboard/tv44/led.c View File

@@ -0,0 +1,34 @@
/*
Copyright 2012 Jun Wako <[email protected]>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 <avr/io.h>
#include "stdint.h"
#include "led.h"
uint8_t led_counter = 0;

void led_set(uint8_t usb_led)
{


// if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
// if (led_counter > 4) {
// // output high
// DDRC |= (1<<6);
// PORTC |= (1<<6);
// } else {
// // Hi-Z
// DDRC &= ~(1<<6);
// PORTC &= ~(1<<6);
// }
}

+ 981
- 0
keyboard/tv44/tv44-led.hex View File

@@ -0,0 +1,981 @@
:100000000C949E020C94E2020C94E2020C94E20224
:100010000C94E2020C94E2020C94E2020C94E202D0
:100020000C94E2020C94E2020C94060C0C94D80C92
:100030000C944A1A0C94E2020C94E2020C94E20230
:100040000C94E2020C94E2020C94E2020C94E202A0
:100050000C94E2020C94B11A0C94E2020C94E202A9
:100060000C94E2020C94E2020C94E2020C94E20280
:100070000C94E2020C94E2020C94E2020C94E20270
:100080000C94E2020C94E2020C94E2020C94E20260
:100090000C94E2020C94E2020C94E2020C94E20250
:1000A0000C94E2020C94E2020C94E2023D0D5F0D0E
:1000B0004A0E5F0D4A0EA10DC40D4A0E190E2C0EEC
:1000C00011111111401140118011E612E612E612D1
:1000D000A211E61249124912B312BB12E612E11242
:1000E00056125612561256125612561256125612D0
:1000F00056125612561256125612561256125612C0
:10010000661276127D1284128E122BA72CA42CA3B9
:10011000290014001A000800150017001C00180020
:100120000C00120013002A00002004001600070033
:1001300009000A000B000D000E000F003300340010
:10014000E1001D001B000600190005001100100051
:100150003600370038000920E000E300E20001200B
:100160000000000000000220E60065000000E4003E
:10017000000000000000000000000000000000007F
:10018000000000000000000000000000000000006F
:10019000000000000000000000000000000000005F
:1001A000000000000000000000000000000000004F
:1001B000000000000000000000000000000000003F
:1001C000000000000000000000000000000000002F
:1001D000000000000000000000000000000000001F
:1001E000000000000000000000000000000000000F
:1001F00000000000000000000000000000000000FF
:1002000000000000000000000000000000000000EE
:1002100000000000000000000000000000000000DE
:1002200000000000000000000000000000000000CE
:1002300035001E001F0020002100220023002400A2
:100240002500260027004C000100010001000100EC
:100250000100010001002D002E002F0030003100B0
:10026000010044004500680069006A006B006C00F2
:100270006D004B006F00280001000100010001002B
:1002800000000000000001004A004E0000004D0088
:1002900035021E021F022002210222022302240232
:1002A0002502260227022A00010001000100480061
:1002B0000100010001002D022E022F023002310246
:1002C00001003A003B003C003D003E003F00400082
:1002D000410042004300280001000100010001002C
:1002E0000000000000000100AB00A8000000AE000C
:1002F00000000000000000000000000000000000FE
:1003000000000000000000000000000000000000ED
:1003100000000000000000000000000000000000DD
:1003200000000000000000000000000000000000CD
:1003300000000000000000000000000000000000BD
:1003400000000000000000000000000000000000AD
:10035000000000000000000000000000000000009D
:10036000000000000000000000000000000000008D
:10037000000000000000000000000000000000007D
:10038000000000000000000000000000000000006D
:10039000000000000000000000000000000000005D
:1003A000000000000000000000000000000000004D
:1003B0002900B200B500B100B30001000100010046
:1003C000010001004600010001008350010001000E
:1003D00000500100010001000100010001000100C6
:1003E0000100010001000100010001000100010005
:1003F000010052000100280001000100010001007D
:1004000000000000000001005000510000004F00FB
:100410000A037400760034003400000006034D0027
:10042000450000000403090409025400030100A070
:10043000FA09040000010301010009211101000172
:10044000223F000705810308000A09040100010397
:100450000000000921110100012236000705820376
:1004600008000A090402000103000000092111012B
:100470000001223900070583031000011201100159
:1004800000000008EDFE606041040102000105016A
:100490000906A101050719E029E7150025019508BE
:1004A000750181020508190129059505750191025B
:1004B000950175039101050719002977150025019C
:1004C000957875018102C005010980A10185021698
:1004D000010026B7001A01002AB7007510950181A6
:1004E00000C0050C0901A1018503160100269C022C
:1004F0001A01002A9C02751095018100C0050109AE
:1005000006A101050719E029E715002501950875E1
:1005100001810295017508810105081901290595D8
:1005200005750191029501750391010507190029CF
:10053000FF150025FF950675088100C011241FBE18
:10054000CFEFDAE0DEBFCDBF04B603FE24C080915A
:10055000D8019091D901A091DA01B091DB018730E7
:10056000904BA740B04BB9F41092D8011092D9012A
:100570001092DA011092DB0114BE84B7877F84BF2A
:1005800088E10FB6F89480936000109260000FBE6F
:10059000E0E0F8E3099511E0A0E0B1E0EAE0FDE376
:1005A00002C005900D92AE32B107D9F711E0AEE26C
:1005B000B1E001C01D92A83DB107E1F70E944E09CC
:1005C0000C94831E0C94000080912F018F5F883063
:1005D00018F480932F0102C010922F0190912F01E7
:1005E00080912E01981718F4229A2A9A0895229839
:1005F0002A98089522982A980C94AF1D80932E0172
:10060000089508950895089508950E94FA020C949B
:1006100002030E9403030C94E4020C94040381E09F
:1006200008950C940F0308950F931F93CF93DF93B6
:10063000EC0108811981C8010E947B18B8010E9451
:10064000AF038C01BE010E941103882309F47AC014
:100650008A818823C9F180913B0181111EC0043138
:1006600080E5180789F50E94130381E080933B0120
:100670000E947C1A90933A018093390110923201C2
:10068000109234011092330110923601109235010C
:10069000109238011092370155C080913901909124
:1006A0003A010E94881A883C910570F480913201C9
:1006B000E82FF0E0EE0FFF1FED5CFE4F118300838B
:1006C0008F5F809332013EC0043880E5180721F027
:1006D00005381045A1F02AC08A81882321F01092A4
:1006E000300182E012C080913001811106C086E2A3
:1006F0000E94AF0F86E20E94771082E014C08A81C8
:10070000882331F01092310180E20E94C6101AC095
:1007100080913101811106C087E20E94AF0F87E20C
:100720000E94771080E20E94CD100CC081E080937F
:10073000300180933101CE01DF91CF911F910F9154
:100740000C940D0380E0DF91CF911F910F910895DC
:100750000C9405030C94090380E090E008959CE05C
:10076000799FF001112490E3899FE00DF11D112480
:10077000E60FF11DEE0FFF1FE05FFE4F8591949194
:100780000895880F991F86579040FC018591949198
:100790000895880F991F865F9E4FFC018591949163
:1007A00008950F931F93CF93DF93EC01811521E3FD
:1007B0009207A0F5811530E3930708F0D7C0883E73
:1007C0009105D8F4803E910508F06FC0883A9105F4
:1007D00078F4853A910508F06AC08130910509F4F2
:1007E000F4C108F4EFC18430910508F05EC0EAC19D
:1007F0008B3B910508F466C0E5C1C11580E2D807BE
:1008000008F0AFC0C11591E0D90708F04EC0C03F55
:10081000D10508F4D7C18E01106518C2803820E5D3
:10082000920700F5803730E5930708F0A3C0C115A3
:1008300080E5D80709F4ACC050F4CE019054803163
:100840009F4008F0BFC18E011F70106AFFC1C13008
:1008500030E5D30709F4AAC0C43180E5D80708F40D
:10086000ABC0B0C1C33890E5D90709F48EC050F4CD
:10087000C13830E5D30709F482C008F083C000E036
:1008800011EDE4C1C03191E5D90708F49BC1C11550
:1008900027E5D20708F432C1CE0190578115904167
:1008A00008F090C18E011F708BC18E01CFC1853AB7
:1008B000910509F48DC1863A910509F48CC103E8CC
:1008C00010E4C4C1883A910509F488C1893A9105B8
:1008D00009F487C18A3A910509F486C18B3A9105DA
:1008E00009F485C18C3A910509F484C18D3A9105CA
:1008F00009F483C1803B910509F482C18E3A9105C8
:1009000009F481C18F3A910509F480C1813B9105B9
:1009100009F47FC1823B910509F47EC1833B9105B7
:1009200009F47DC1843B910509F47CC1853B9105A7
:1009300009F47BC1863B910509F47AC1873B910597
:1009400009F479C1883B910509F478C1893B910587
:1009500009F477C18A3B910509F076C10AE216E4F1
:1009600075C1CE019F700E94C90371C18C0111270E
:10097000106C6CC18C010F701127146D67C100E001
:1009800010ED64C100E012ED61C100E013ED5EC145
:100990000E9450138FEF94E32CE081509040204050
:1009A000E1F700C000000E94D61A50C18091C20138
:1009B00081608093C2014AC10E94881C811102C0DB
:1009C0000E94691C0E94A51C90E09093D70180931F
:1009D000D601C23030E5D30721F48091D601816081
:1009E00086C0C43080E5D80721F48091D6018260AA
:1009F0007EC0C63090E5D90721F48091D60184608D
:100A000076C0C83020E5D20719F48091D60127C0FE
:100A1000CA3030E5D30721F48091D601806167C0E8
:100A2000CC3080E5D80721F48091D60180625FC088
:100A3000CE3090E5D90721F48091D601806457C06B
:100A4000C03120E5D20721F48091D60180684FC0E3
:100A5000C23130E5D30729F48091D60184608860E3
:100A600046C0C33080E5D80721F48091D6018E7F3F
:100A70003EC0C53090E5D90721F48091D6018D7F25
:100A800036C0C73020E5D20721F48091D6018B7F94
:100A90002EC0C93030E5D30719F48091D60126C0A5
:100AA000CB3080E5D80721F48091D6018F7E1FC01E
:100AB000CD3090E5D90721F48091D6018F7D17C004
:100AC000CF3020E5D20721F48091D6018F7B0FC073
:100AD000C13130E5D30721F48091D6018F7707C06B
:100AE000C331D04531F48091D6018B7F877F8093CD
:100AF000D6018091D6010E94A91CA8C08D2F9927EC
:100B00008F70992781309105E9F48E0103701127C8
:100B10009C0102C0220F331F0A95E2F789011C686D
:100B2000CE01E4E0880F991FEA95E1F788279370DA
:100B3000082B192BF3E0CC0FDD1FFA95E1F7C076F7
:100B4000DD272CC08230910529F41C2F0027016F6E
:100B5000106A7CC08330910561F4CE0183709927BF
:100B600001E010E002C0000F111F8A95E2F71C6837
:100B70000EC084309105A9F4CE018370992701E05D
:100B800010E002C0000F111F8A95E2F71A6863E0B7
:100B9000CC0FDD1F6A95E1F7C07ED7700C2B1D2BA3
:100BA00055C08530910529F41C2F0027046F106A69
:100BB0004DC0069709F04AC0CF71DD271C2F0027D2
:100BC000106244C000E010E041C001E010E03EC00F
:100BD00001E810E43BC002E810E438C002EE14E47F
:100BE00035C009EE14E432C00AEE14E42FC005EB60
:100BF00014E42CC006EB14E429C007EB14E426C06F
:100C00000CEC14E423C00DEC14E420C003E815E45C
:100C10001DC00AE815E41AC002E915E417C004E98A
:100C200015E414C001E216E411C003E216E40EC09C
:100C300004E216E40BC005E216E408C006E216E47E
:100C400005C007E216E402C000E014E4C801DF9129
:100C5000CF911F910F9108959CE0799FF00111248D
:100C600090E3899FE00DF11D1124E60FF11DEE0FB9
:100C7000FF1FE05FFE4F85919491803E9105E0F467
:100C8000803C910558F58133910509F46FC048F413
:100C90008932910509F463C08A32910509F46DC067
:100CA00072C089339105E9F082389105D1F085331E
:100CB000910509F44DC067C0833E910581F138F478
:100CC000803E9105B9F0823E9105D9F05CC0863E28
:100CD000910561F1873E9105A1F155C00E94C103C4
:100CE00008952091D60120FD02C021FF4CC080EE66
:100CF00090E049C08091D60180FFF9CF89E390E070
:100D000042C08091D60182FF0EC08091D60184FF3F
:100D100003C080E090E037C083EE90E034C0809163
:100D2000D60182FFF2CF82EE90E02DC08091D601F5
:100D300083FF0BC08091D60184FDEBCF87EE90E05E
:100D400022C08091D60183FFF5CF86EE90E01BC0D4
:100D50008091D60185FF07C089E290E014C08091A0
:100D6000D60185FFF9CF85E390E00DC08091D601D3
:100D700086FF07C08AE290E006C08091D60186FF18
:100D8000F9CF81E390E00E94D103089508950C9477
:100D9000C606E82FF0E0E55EFE4F8081E82FEF7099
:100DA000F0E0282F22952F7081E090E0022E01C004
:100DB000880F0A94EAF780A308950F931F93CF93A7
:100DC000DF9385B7806885BF85B7806885BFC3E03E
:100DD000D0E001E010E0FE01E55EFE4F8081E82FEB
:100DE000EF70F0E021A182958F70A80102C0440F3E
:100DF000551F8A95E2F7242B21A38C2F0E94C90648
:100E0000219748F78BE090E041E050E0FC01E15F82
:100E1000FE4F2081E22FEF70F0E062A122952F704B
:100E2000DA0102C0AA0FBB1F2A95E2F76A2B62A360
:100E3000019760F7DF91CF911F910F910C94A80358
:100E4000EF92FF920F931F93CF93DF93C4E4D1E00F
:100E500083E0E82E01E010E095E0F92E8E2D0E944F
:100E6000C9062BE030E040E050E0F901E15FFE4FC1
:100E70008081E82FEF70F0E060A170E082958F70C4
:100E800002C0759567958A95E2F760FD09C0B801C3
:100E9000022E02C0660F771F0A94E2F7462B572BEB
:100EA0002150310910F73A912A912417350721F082
:100EB00059834883F09200018E2D0E94C906EA945E
:100EC0009FEFE912CBCF8091000187FD2CC08150AC
:100ED000809300018F3F09F5809142019091430179
:100EE00090934B0180934A01809140019091410180
:100EF000909349018093480180913E0190913F0178
:100F0000909347018093460180913C0190913D016F
:100F1000909345018093440106C08FE99FE00197BB
:100F2000F1F700C000000E94AA0381E0DF91CF9199
:100F30001F910F91FF90EF900895E82FF0E0EE0FD2
:100F4000FF1FEC5BFE4F80819181089508951F93F0
:100F5000CF93DF93CCE4D1E010E09A918A910E9484
:100F6000F419180F81E0C434D807B9F7812FDF9145
:100F7000CF911F91089580915C0108950895CF93BA
:100F8000DF9300D01F92CDB7DEB72091CD01243082
:100F900021F523E029839B838A8382E08093E90003
:100FA0008FEF9091E800815095FD06C095ED9A95E0
:100FB000F1F700008111F5CF8091E80085FF0DC0A9
:100FC00040E050E063E070E0CE0101960E94F90934
:100FD0008091E8008E778093E8000F900F900F903B
:100FE000DF91CF910895CF93DF9300D01F92CDB7BB
:100FF000DEB72091CD01243019F522E029839B83AF
:101000008A832093E9008FEF9091E800815095FD4D
:1010100006C095ED9A95F1F700008111F5CF80910A
:10102000E80085FF0DC040E050E063E070E0CE01D5
:1010300001960E94F9098091E8008E778093E8007C
:101040000F900F900F90DF91CF910895CF93DF9382
:10105000EC018091CD01843009F047C080910B01F3
:101060008823E1F080910C018823C1F083E0809314
:10107000E9008FEF9091E800815095FD06C095E161
:101080009A95F1F700008111F5CF8091E80085FF76
:101090002CC040E050E060E170E017C081E0809338
:1010A000E9008FEF9091E800815095FD06C095ED25
:1010B0009A95F1F700008111F5CF8091E80085FF46
:1010C00014C040E050E068E070E0CE010E94F909F1
:1010D0008091E8008E778093E80080E1FE01ACE427
:1010E000B1E001900D928A95E1F7DF91CF910895DB
:1010F0008091CC01811109C00E948B0B0E94E80BEA
:101100008091E20084608093E20008951092CC0107
:101110000895089508950C943F1A42E061EC81E02F
:101120000E94050B42E061EC82E00E94050B42E167
:1011300061EC83E00C94050B8091CF01833009F4BE
:1011400055C030F4813071F0823009F48EC00895BA
:101150008A3009F47AC08B3009F460C0893009F014
:101160009CC020C08091CE01813A09F096C0809148
:10117000E800877F8093E8008091D2019091D301AD
:10118000892B21F060E080E090E003C060E18CE416
:1011900091E070E00E94420A8091E8008B77809392
:1011A000E80008958091CE01813209F076C08091E7
:1011B000D2019091D301009719F0029709F06DC008
:1011C0008091E800877F8093E8008091E80082FDAD
:1011D00005C08091CD018111F8CF5FC08091F100F1
:1011E00080935C018091E8008B7753C08091CE01A1
:1011F000813A09F052C08091D2019091D301892B9C
:1012000009F04BC08091E800877F8093E8008091CF
:10121000E80080FFFCCF80910B0136C08091CE01A9
:101220008132D9F58091D2019091D301892BA9F512
:101230008091E800877F8093E8000E943A0B8091BC
:10124000D00180930B010C9450138091CE01813218
:1012500021F58091E800877F8093E8000E943A0B97
:101260008091D10180935D0108958091CE01813AF2
:10127000A1F48091E800877F8093E8008091E800E6
:1012800080FFFCCF80915D018093F1008091E800A8
:101290008E778093E8000C943A0B089584B7877F8B
:1012A00084BF88E10FB6F8948093600010926000CC
:1012B0000FBE90E080E80FB6F894809361009093A1
:1012C00061000FBE0E94C90E0E948B0B0E94E80BAA
:1012D0008091E20084608093E20078940E94630E23
:1012E0000E94CB0E81E091E00E94800E8091CD01A2
:1012F000853069F40E94001A8091CB018823B1F3F4
:101300000E942E1A882391F30E94E309EFCF0E94D6
:10131000D30EECCF292F332723303105A9F06CF4FD
:101320002130310509F442C02230310509F043C0B3
:1013300084E590E028E234E042C021323105C9F072
:101340002232310519F137C099278130910541F0DA
:101350008230910541F0892B71F5E4E2F4E005C09B
:10136000ECE1F4E002C0E0E1F4E0849190E09F0160
:1013700026C0633000F5E62FF0E0EE0FFF1FE85DBA
:10138000FE4F2081318189E090E019C0633098F4EC
:10139000E62FF0E0DF01AA0FBB1FAE5DBE4F2D911F
:1013A0003C91E15EFE4F808190E009C082E190E0D7
:1013B0002CE734E004C080E090E020E030E0FA0167
:1013C00031832083089580E189BD82E189BD09B41C
:1013D00000FEFDCF8091D8008F7D8093D800809152
:1013E000E00082608093E0008091E00081FDFCCF0E
:1013F0000895CF92DF92EF92FF920F931F93CF93B6
:10140000DF937C018B01EA010E945B0B811131C0EB
:10141000209731F088819981081B190BE80EF91E7D
:10142000C12CD12C0115110519F18091E80085FD21
:1014300014C08091E8008E778093E800209741F0F7
:10144000888199818C0D9D1D9983888385E011C0C9
:101450000E945B0B882331F30CC0F70181917F015F
:101460008093F10001501109FFEFCF1ADF0ADACFA4
:1014700080E0DF91CF911F910F91FF90EF90DF906F
:10148000CF9008952091D4013091D50126173707C8
:1014900048F06115710539F42091E8002E7720930A
:1014A000E80001C0B901FC0120E061157105B9F146
:1014B0008091CD01882309F440C0853009F43FC0F4
:1014C0008091E80083FD3DC08091E80082FF06C066
:1014D0008091E80082FF26C080E008958091E800B6
:1014E00080FFE3CF2091F3008091F20090E0922BF7
:1014F0006115710551F08830910538F421912093E0
:10150000F100615071090196F3CF21E0089709F0CD
:1015100020E08091E8008E778093E800C6CF21110B
:10152000C7CFD6CF8091CD01882339F0853039F0EF
:101530008091E80083FFCCCF04C082E0089583E06F
:10154000089581E008952091D4013091D5012617A6
:10155000370748F06115710539F42091E8002E77BE
:101560002093E80001C0B901FC0120E0611571057C
:10157000C1F18091CD01882309F441C0853009F47F
:1015800040C08091E80083FD3EC08091E80082FF6A
:1015900006C08091E80082FF27C080E00895809116
:1015A000E80080FFE3CF2091F3008091F20090E00B
:1015B000922B6115710559F08830910540F4249102
:1015C0002093F1003196615071090196F2CF21E02C
:1015D000089709F020E08091E8008E778093E8007A
:1015E000C5CF2111C6CFD5CF8091CD01882339F049
:1015F000853039F08091E80083FFCBCF04C082E0D2
:10160000089583E0089581E00895982F973058F564
:101610009093E900981739F07091EC002091ED005B
:101620005091F00003C0242F762F50E021FF19C005
:101630003091EB003E7F3093EB003091ED003D7F29
:101640003093ED003091EB0031603093EB007093FC
:10165000EC002093ED005093F0002091EE0027FF66
:1016600007C09F5FD3CF8F708093E90081E008951A
:1016700080E008958091CE0187FD05C08091E8004B
:1016800080FF0EC012C08091E80082FD05C08091ED
:10169000CD018111F8CF08958091E8008B7708C0C3
:1016A0008091CD018111EACF08958091E8008E7775
:1016B0008093E80008958091E4009091E50045E66C
:1016C0002091EC0020FF21C02091E80020FD21C0E6
:1016D0002091CD01222389F0253089F02091EB0063
:1016E00025FD0FC02091E4003091E500281739074F
:1016F00039F3415041F0C901E3CF82E0089583E01E
:10170000089581E0089584E008952091E80022FF83
:10171000DFCF80E008950E94F90B0E94010CE0EEFB
:10172000F0E0808181608083E8EDF0E080818F7758
:10173000808319BCA7EDB0E08C918E7F8C93808163
:101740008F7E80831092CC0108950F931F93CF93C7
:10175000DF930E94F90B0E94010CC8EDD0E0888154
:101760008F77888388818068888388818F7D88834C
:1017700019BC1092CD011092C9011092CB011092A8
:10178000CA0100EE10E0F80180818B7F80838881A0
:101790008160888342E060E080E00E94050BE1EE1A
:1017A000F0E080818E7F8083E2EEF0E080818160D6
:1017B0008083808188608083F80180818E7F808330
:1017C000888180618883DF91CF911F910F91089567
:1017D000E8EDF0E080818F7E8083E7EDF0E08081AE
:1017E0008160808384E082BF81E08093CC010C948F
:1017F000A50BE8EDF0E080818E7F80831092E200FF
:1018000008951092DA001092E10008951F920F924D
:101810000FB60F9211242F933F934F935F936F93C3
:101820007F938F939F93AF93BF93EF93FF93809199
:10183000E10082FF0BC08091E20082FF07C080912F
:10184000E1008B7F8093E1000E94620E8091DA00BC
:1018500080FF1FC08091D80080FF1BC08091DA00FC
:101860008E7F8093DA008091D90080FF0DC080E1E7
:1018700089BD82E189BD09B400FEFDCF81E080937E
:10188000CD010E94780805C019BC1092CD010E94BC
:1018900086088091E10080FF19C08091E20080FFFE
:1018A00015C08091E2008E7F8093E2008091E2007B
:1018B00080618093E2008091D80080628093D8009C
:1018C00019BC85E08093CD010E948A088091E100D7
:1018D00084FF30C08091E20084FF2CC080E189BD8C
:1018E00082E189BD09B400FEFDCF8091D8008F7DD3
:1018F0008093D8008091E1008F7E8093E1008091F9
:10190000E2008F7E8093E2008091E200816080930C
:10191000E2008091C901882311F084E007C0809122
:10192000E30087FF02C083E001C081E08093CD0126
:101930000E948B088091E10083FF29C08091E20022
:1019400083FF25C08091E100877F8093E10082E0E2
:101950008093CD011092C9018091E1008E7F809328
:10196000E1008091E2008E7F8093E2008091E200AE
:1019700080618093E20042E060E080E00E94050B1D
:101980008091F00088608093F0000E948908FF91A8
:10199000EF91BF91AF919F918F917F916F915F91E7
:1019A0004F913F912F910F900FBE0F901F90189560
:1019B0001F920F920FB60F9211242F933F934F93C4
:1019C0005F936F937F938F939F93AF93BF93CF93C7
:1019D000EF93FF93C091E900CF708091EC001092DB
:1019E000E9008091F000877F8093F00078940E9456
:1019F000140D1092E9008091F00088608093F0004F
:101A0000C093E900FF91EF91CF91BF91AF919F916A
:101A10008F917F916F915F914F913F912F910F9097
:101A20000FBE0F901F9018951F93CF93DF93CDB7E4
:101A3000DEB7AA970FB6F894DEBF0FBECDBFEEECAF
:101A4000F1E08091F100819321E0E63DF207C9F7D2
:101A50000E949C088091E80083FF1CC12091CE0168
:101A60003091CF01832F90E08A30910508F012C1A8
:101A7000FC01EA5AFF4F0C94471E203881F02238AF
:101A800009F008C18091D2018F708093E9008091A4
:101A9000EB0085FB882780F91092E90006C0809151
:101AA000CA019091CB01911182609091E800977FDB
:101AB0009093E8008093F1001092F100C5C0822F4E
:101AC0008D7F09F0E7C0222319F0223061F0E2C0D7
:101AD0008091D001813009F0DDC0333009F080E021
:101AE0008093CB0128C08091D001811124C0209126
:101AF000D2012F7009F4CEC02093E9008091EB0051
:101B000080FF19C08091EB00333011F4806211C066
:101B100080618093EB0081E090E0022E01C0880F8D
:101B20000A94EAF78093EA001092EA008091EB00B1
:101B300088608093EB001092E9008091E800877F35
:101B400086C02111A7C01091D0011F778091E300BA
:101B50008078812B8093E3008091E800877F8093D9
:101B6000E8000E943A0B8091E80080FFFCCF809152
:101B7000E30080688093E300112311F083E001C04B
:101B800082E08093CD0186C02058223008F082C0C8
:101B90008091D0019091D1018C3D23E0920779F59D
:101BA00083E08A838AE289834FB7F894DE01139633
:101BB00020E03EE051E2E32FF0E050935700E49143
:101BC00020FF03C0E295EF703F5FEF708E2F90E033
:101BD000EA3010F0C79601C0C0968D939D932F5F99
:101BE000243149F74FBF8091E800877F8093E80058
:101BF0006AE270E0CE0101960E94420A14C0AE0172
:101C00004F5F5F4F6091D2010E948A09009709F4EB
:101C100041C02091E800277F2093E800BC01898122
:101C20009A810E94A30A8091E8008B778093E80054
:101C300031C0203879F58091E800877F8093E800F3
:101C40008091C9018093F1008091E8008E778093A4
:101C5000E8000E943A0B1EC021111CC09091D001D7
:101C60009230C0F48091E800877F8093E8009093E1
:101C7000C9010E943A0B8091C901811104C0809171
:101C8000E30087FF02C084E001C081E08093CD01C2
:101C90000E948D088091E80083FF0AC08091E800CF
:101CA000877F8093E8008091EB0080628093EB0057
:101CB000AA960FB6F894DEBF0FBECDBFDF91CF91CD
:101CC0001F9108950895CF938091CD018823B1F09D
:101CD0008091E9008F709091EC0090FF02C090E835
:101CE00001C090E0C92FC82B1092E9008091E80054
:101CF00083FD0E94140DCF70C093E900CF91089529
:101D000090936301809362010895E0916201F091E4
:101D10006301309721F00190F081E02D099480E07B
:101D20000895E0916201F0916301309721F0028003
:101D3000F381E02D099408952091600130916101B3
:101D40008217930771F09093610180936001E09195
:101D50006201F0916301309721F00680F781E02D58
:101D60000994089520915E0130915F0182179307D5
:101D700071F090935F0180935E01E0916201F091B8
:101D80006301309721F00084F185E02D09940895D6
:101D900008950C94C80E0E94731A0E94DD060E94DA
:101DA0003E1B0C94AF1D5F926F927F928F929F9219
:101DB000AF92BF92CF92DF92EF92FF920F931F9359
:101DC000CF93DF9300D000D01F92CDB7DEB70E9433
:101DD00020079DE6C92E91E0D92E03E010E0AA2449
:101DE000A394B12C502E802F0E949D073C01F60138
:101DF000F290E2906F01E826F926E114F104A1F4D3
:101E00000150110978F78FEF89838A831B820E9422
:101E10007C1A8160782F9D838C8349815A816B81E4
:101E20008D810E94810F38C08091C20181FD0E9486
:101E3000A6072BE030E04501022E02C0880C991C59
:101E40000A94E2F7C4018E219F21892B09F129838D
:101E50005A826820792081E0672809F480E08B832A
:101E60000E947C1A8160782F9D838C8349815A81DE
:101E70006B818D810E94810FF801EE0FFF1FEB59DE
:101E8000FE4F80819181882599259183808304C0AC
:101E90002150310980F6B4CF109164010E94850E63
:101EA0001817D1F00E94850E809364010F900F9057
:101EB0000F900F900F90DF91CF911F910F91FF9096
:101EC000EF90DF90CF90BF90AF909F908F907F90DA
:101ED0006F905F900C94C7060F900F900F900F902B
:101EE0000F90DF91CF911F910F91FF90EF90DF90B6
:101EF000CF90BF90AF909F908F907F906F905F90AA
:101F00000895CF93DF93CDB7DEB72B970FB6F89434
:101F1000DEBF0FBECDBF4F83588769877A878B8717
:101F2000DE01119686E0FD0111928A95E9F785E0C0
:101F3000FE01379601900D928A95E1F749815A8109
:101F40006B817C818D819E810E9420162B960FB61D
:101F5000F894DEBF0FBECDBFDF91CF910895CF9330
:101F6000C82F882309F4C1C0823859F40E94850E15
:101F700081FDBBC089E30E94FB180E94C51989E35B
:101F80000CC0833879F40E94850E80FDAEC083E5D5
:101F90000E94FB180E94C51983E50E943B19CF914E
:101FA0000C94C519843859F40E94850E82FD9DC099
:101FB00087E40E94FB180E94C51987E4EECF8CEFDE
:101FC0008C0F813A48F48C2F0E94701D81118DC0B6
:101FD0008C2F0E94FB18E3CF80E28C0F883048F4EE
:101FE000C77081E001C0880FCA95EAF70E947C198A
:101FF000D6CF8BE58C0F833078F4C53A29F0C63AFA
:1020000031F482E890E005C081E890E002C083E806
:1020100090E0CF910C949C0E88E58C0F833108F0F2
:1020200064C0C83A39F1C93A41F1CA3A49F1CB3AE8
:1020300051F1CC3A59F1CD3A61F1C03B69F1CE3A58
:1020400071F1CF3A79F1C13B81F1C23B89F1C33BD8
:1020500091F1C43B99F1C53BA1F1C63BA9F1C73B46
:10206000B1F1C83BB9F1C93BC1F1CA3BC9F58AE23C
:1020700092E038C082EE90E035C089EE90E032C048
:102080008AEE90E02FC085EB90E02CC086EB90E0CC
:1020900029C087EB90E026C08CEC90E023C08DEC4B
:1020A00090E020C083E891E01DC08AE891E01AC06A
:1020B00082E991E017C084E991E014C081E292E0E6
:1020C00011C083E292E00EC084E292E00BC085E290
:1020D00092E008C086E292E005C087E292E002C08A
:1020E00080E090E0CF910C94B20ECF9108958823B8
:1020F00009F44BC0823859F40E94850E81FF45C017
:1021000089E30E94FB180E94C51989E30CC083383B
:1021100071F40E94850E80FF38C083E50E94FB1891
:102120000E94C51983E50E943B190C94C519843897
:1021300059F40E94850E82FF28C087E40E94FB1894
:102140000E94C51987E4EFCF9CEF980F913A58F39E
:1021500090E2980F983050F4877091E001C0990F89
:102160008A95EAF7892F0E948219DFCF9BE5980FA5
:10217000933020F480E090E00C949C0E885A8331D8
:1021800020F480E090E00C94B20E0895882321F0B2
:102190000E947C190C94C5190895882321F00E948F
:1021A00082190C94C51908958F929F92AF92BF9295
:1021B000CF92DF92EF92FF920F931F93CF93DF9313
:1021C0001F92CDB7DEB74C01A62E472FFC01E5804C
:1021D000E2948FE0E822F280FF2021F079830E94D0
:1021E0009919498149830E94F4184981882381F013
:1021F000FF2071F080E28A0D883050F082E00E946A
:10220000DD180E94F418BB24B394B826498101C09C
:10221000B12CE42FE295EF70F0E0E05AFF4F0C9400
:10222000471E842F807F142F1F70882311F0129572
:10223000107FFF2089F0112309F48BC180E28A0D01
:10224000883020F4812F0E947C1903C0812F0E94C6
:102250008C190E94C5197DC18A2D0E947710112307
:1022600009F4B4C180E28A0D883020F4812F0E94E5
:10227000821903C0812F0E9492190E94C519A6C11C
:10228000242F207F842F8F70203211F08295807F41
:10229000AA2021F0F1E0AF16B1F021C0FF2041F0FB
:1022A000EE2039F191E0E91224C00E94AC198EC1F0
:1022B000EE2021F0E1E0EE1609F488C189830E9446
:1022C000AF19898100C1FF2029F0F5E0FE1508F45F
:1022D0007DC10FC094E09E1508F478C1F4C0FF20C2
:1022E00059F0EE2031F0F401958190FF32C19F70DA
:1022F00095830E94C6106AC1EE2009F4E4C02FC184
:10230000242F26952695237030E02115310521F0E4
:102310002130310561F05AC1FF2021F08A2D942F20
:10232000937002C080E090E00E949C0E4FC1FF209D
:1023300021F08A2D942F937002C080E090E00E94DB
:10234000B20E44C1842F837009F04EC0F1103EC11B
:102350002A2D229526952770220F220F8A2D8F7005
:10236000C82ED12CE12CF12C022E04C0CC0CDD1C8B
:10237000EE1CFF1C0A94D2F7A4FE10C06FE070E0C0
:1023800080E090E004C0660F771F881F991F2A9590
:10239000D2F7609570958095909503C060E070E0ED
:1023A000CB01242F26952695237030E0223031056D
:1023B00069F02330310589F06C297D298E299F2908
:1023C0002130310571F00E94721700C16C297D29FE
:1023D0008E299F290E948C17F9C00E947217C7018D
:1023E000B6010E945817F2C0FF2019F0842F8170A7
:1023F00001C08695882309F4E9C02A2D22952695E7
:102400002770220F220F8A2D8F70C82ED12CE12C1D
:10241000F12C022E04C0CC0CDD1CEE1CFF1C0A9417
:10242000D2F7A4FE10C06FE070E080E090E004C03E
:10243000660F771F881F991F2A95D2F760957095B0
:102440008095909503C060E070E0CB01242F269525
:102450002695237030E02230310569F023303105B4
:1024600089F06C297D298E299F292130310571F051
:102470000E944618ABC06C297D298E299F290E9495
:102480006018A4C00E944618C701B6010E942C180B
:102490009DC00A2D10E0F801E05EF109E531F1057B
:1024A00008F053C0E059FF4F0C94471E1A2D1F70BF
:1024B000842F8F71FF2021F00E94C517812F19CF23
:1024C0000E94E617812F0E94CD1080C0FF2049F0A6
:1024D000F4E0FE1508F47AC0842F8F710E940B1867
:1024E00075C085E08E1508F471C0F6CFFF2039F075
:1024F000842F8F710E94C51769C0FF20C9F3842FF4
:102500008F710E94E61762C0FF2029F0842F8F711F
:102510000E94B0175BC00E94A61758C0FF2051F060
:10252000142F1F71812F0E94C51763E0812F0E9415
:10253000D4184CC081E00E94DD1891E09E1508F08F
:1025400045C082E00E94DD1841C0FF2031F0EE203E
:1025500079F28A2D0E94AF0F39C0EE2081F28A2DC8
:102560000E94771033C04F706A2DC4010E94AC03E3
:102570000E94CD162BC0F11029C0942F9F70492FB7
:1025800050E042305105B9F04CF44115510581F04D
:1025900041305105D9F40E94D71D18C04330510570
:1025A00069F04430510591F48A2D0E942B1E0EC013
:1025B0000E94C01D0BC00E94F31D08C00E94061E91
:1025C00005C04F706A2DC4010E940103BB20F1F0C9
:1025D0000E94D01880FD1AC0F40112820E94CA180D
:1025E0000E94C517C4010E9414130E94CA180F90BC
:1025F000DF91CF911F910F91FF90EF90DF90CF90DF
:10260000BF90AF909F908F900C94E6170F90DF9142
:10261000CF911F910F91FF90EF90DF90CF90BF90DF
:10262000AF909F908F9008950F931F93CF93DF9358
:10263000EC01288139818B819C81892B31F03F3FCE
:1026400011F080E003C02F3FE1F781E0811113C05A
:10265000CE010E941403882371F0688179818A81F8
:102660000E94C6188C010E947A180E944D17B8016A
:10267000CE010E94D410DF91CF911F910F91089548
:102680000E9499190E94A9190E946E190E94C519E9
:1026900080E090E00E949C0E80E090E00C94B20EEE
:1026A0000E9489190C9440130E94BB18292F22956F
:1026B0002F7030E02C3031054CF42A3031056CF4A9
:1026C0002250310922303105B0F407C02C303105D9
:1026D00071F02F30310559F00EC0803F31F018F401
:1026E000803E48F402C0843F31F481E0089593FBBA
:1026F000882780F9089580E00895CF93DF9300D074
:1027000000D01F92CDB7DEB70F900F900F900F90B3
:102710000F90DF91CF910895CF93DF9300D000D039
:1027200000D0CDB7DEB726960FB6F894DEBF0FBE49
:10273000CDBFDF91CF9108951F93CF93DF93C091C9
:102740006D0116E080916E01C81799F0D0E01C9FD2
:10275000F0011D9FF00D1124E159FE4F4081518180
:1027600062817381848195810E948C132196C77048
:10277000E9CFDF91CF911F91089540919F01509132
:10278000A0016091A1017091A2018091A30190919B
:10279000A4010C948C13CF938091A40182958F7027
:1027A00009F05FC08091A101882309F45AC02091EB
:1027B0006D01A0916E0160919F017091A0018091C7
:1027C000A2019091A30131E06F3F09F030E0B32FF7
:1027D000C6E02A1709F445C0009721F07F3F21F495
:1027E0004B2F03C041E001C040E030E040FD35C068
:1027F000C29FF001C39FF00D1124E159FE4F4181AA
:1028000074132BC04081641328C04281411125C03C
:10281000438154814817590710F441505109481B0E
:10282000590B483C5105C8F48091A4018F70806118
:102830008093A40186E0829FF001839FF00D112414
:10284000EC58FE4F80818F70806180838FE991E02A
:102850000E941413CF910C949C132F5F3F4F27704D
:10286000B8CFCF910895CF92DF92EF92FF920F935E
:102870001F93CF93DF93CDB7DEB762970FB6F8946F
:10288000DEBF0FBECDBF8C0185E0F801DE011D96D5
:1028900001900D928A95E1F7D8014C9111965C91C7
:1028A000119712966C9112971396ED90FC901497D5
:1028B00070919F01E091A0012091A2013091A301AC
:1028C0002115310531F0EF3F31F481E07F3F19F4FC
:1028D00003C081E001C080E0B82FB170CB2E80FD35
:1028E0006CC1D090A101DD2009F4F5C0F091A401E4
:1028F000E216F30638F0C701821B930B883C910562
:1029000048F09BC0209530952E0D3F1D283C310589
:1029100008F093C08F2F807F09F052C0E51314C0D8
:10292000741312C0D62E61110FC0FF70F061F093C6
:10293000A4010E94BD138FE991E00E9414138091BD
:10294000A401F80185836CC1EF2831F05F3F31F4B9
:1029500081E04F3F19F403C081E001C080E080FDB9
:1029600003C081E0862701C080E0F82FF170FF2EC0
:1029700080FF1CC080916D0120916E0136E08217AE
:1029800009F428C190E0389FF001399FF00D11241F
:10299000E159FE4F7181571306C07081471303C080
:1029A0007281671303C001968770E9CFD62E662324
:1029B00009F436C18091A40181608093A40153C0C1
:1029C000E51308C0741306C0611104C0D801159640
:1029D000FC93AEC04D875E878D859E856A8B0E9475
:1029E00054136A89882329F1D62E662311F1209188
:1029F000A401822F82958F7090E002970CF460C042
:102A000080919F019091A00198878F831986FB8602
:102A1000EA862C87CE01079651C0E51731F14D8724
:102A20005E878D859E856A8B0E9454136A89811109
:102A30002EC0C8010E941413A4C08F2F807F69F795
:102A40007E2DF98AE88A89890E947D138FE991E0B9
:102A50000E941413EFE9F1E086E0DF011D928A95F0
:102A6000E9F70E94BD13D12CDBC07413D8CF6111DC
:102A7000D6CFD8011596FC93C8010E941413EFE934
:102A8000F1E086E0DF011D928A95E9F7C9C0D62EF4
:102A9000662379F22091A401822F82958F7090E0B5
:102AA000029774F080919F019091A0019A8389838D
:102AB0001B82FD82EC822E83CE0101960E941413AC
:102AC00086E0F801AFE9B1E001900D928A95E1F757
:102AD0000E94CB136FC0E216F30628F0C701821BD9
:102AE000930B9C0104C0209530952E0D3F1D283C72
:102AF000310508F052C0D62E662309F49ACFE513AB
:102B00002CC074132AC08091A40180FD1DC0982F91
:102B100092959F70C9F0D80115968C9315979F30A8
:102B200039F09F5F9295907F8F70892B15968C93CB
:102B3000C8010E94141386E0F801AFE9B1E00190EA
:102B40000D928A95E1F736C086E0F801AFE9B1E071
:102B500001900D928A95E1F763C04D875E878D8560
:102B60009E850E945413882379F086E0F801AFE92E
:102B7000B1E001900D928A95E1F70E94CB130E947B
:102B8000BD13DD24D3944CC08091A4018160809357
:102B9000A401C8010E94141343C07E2DF98AE88A5B
:102BA00089890E947D13EFE9F1E086E0DF011D9243
:102BB0008A95E9F70E94BD1333C0662309F439CF23
:102BC0004D875E878D859E850E945413882309F466
:102BD00030CFCBCF4D875E878D859E850E94BB18F9
:102BE000292F22952F7030E0223031052CF49F7070
:102BF00041F0811106C00CC0243031052CF49F70C7
:102C000049F4805E883020F0C8010E941413CF2C54
:102C1000DC2C06C0D80115969C91907F91F7F8CFD7
:102C20008D2D62960FB6F894DEBF0FBECDBFDF913B
:102C3000CF911F910F91FF90EF90DF90CF9008956B
:102C40001F93CF93DF93CDB7DEB72C970FB6F894D1
:102C5000DEBF0FBECDBF4F83588769877A878B87CA
:102C60009C87CE0107960E9433148823C1F02F81E0
:102C700038858A859B85892B31F03F3F11F080E0B4
:102C800003C02F3FE1F781E0811147C04F81588594
:102C900069857A858B859C850E948C133EC086E071
:102CA000FE013796DE01119601900D928A95E1F7AB
:102CB000FF81E8854A855B854115510531F0EF3F7D
:102CC00031F481E0FF3F19F403C081E001C080E0EE
:102CD00080FD23C020916E0130E0C901019687700C
:102CE000992760916D0170E086179707F1F1F983DC
:102CF000EA835D834C8396E0929FD001939FB00D51
:102D00001124A159BE4FFE01319601900D929A9562
:102D1000E1F780936E010E949C1316E080916D0193
:102D200090916E01891779F1189FC0011124815982
:102D30009E4F0E943314882331F1E0916D011E9F54
:102D4000F0011124E159FE4F40815181628173816C
:102D5000848195810E948C1380916D0190E0019691
:102D60008770992780936D01D9CF0E9450131092DC
:102D70006E0110926D01EFE9F1E086E0DF011D9236
:102D80008A95E9F7CACF2C960FB6F894DEBF0FBE2E
:102D9000CDBFDF91CF911F910895EF92FF920F93D6
:102DA0001F93CF93DF93FC01009709F46FC0F12CC0
:102DB000EE24E394EF0121968491843740F484302B
:102DC00008F055C0813081F0823021F15FC0853735
:102DD00009F447C0C0F19CE7980F903708F056C03F
:102DE0008F770E94771045C08F010E5F1F4FFE0145
:102DF000849190E2980F983050F48770FE2D01C0B6
:102E0000FF0F8A95EAF78F2F0E949C1915C00E9428
:102E1000AF0F14C08F010E5F1F4FFE01849190E22F
:102E2000980F983068F48770FE2D01C0FF0F8A95C7
:102E3000EAF78F2F0E94A2190E94C519E80119C054
:102E40000E947710FBCFCF010296FE01C491CC23E4
:102E500061F0EFE9FFE03197F1F700C00000C150E9
:102E6000F6CFCF010296FE01F490EC0102C00E9461
:102E7000AF0F8F2D882341F0EFE9FFE03197F1F795
:102E800000C000008150F6CFFE0194CFDF91CF91BA
:102E90001F910F91FF90EF90089508956093A901FD
:102EA0007093AA018093AB019093AC010C944013F2
:102EB0000F931F930091A9011091AA012091AB01DA
:102EC0003091AC01062B172B282B392B0093A9012D
:102ED0001093AA012093AB013093AC011F910F9185
:102EE0000C9440130F931F930091A9011091AA0114
:102EF0002091AB013091AC010623172328233923FD
:102F00000093A9011093AA012093AB013093AC0167
:102F10001F910F910C9440130F931F930091A901DF
:102F20001091AA012091AB013091AC01062717271F
:102F3000282739270093A9011093AA012093AB01F8
:102F40003093AC011F910F910C9440131092A50186
:102F50001092A6011092A7011092A8010C944013A0
:102F600041E050E060E070E004C0440F551F661F70
:102F7000771F8A95D2F74093A5015093A6016093DD
:102F8000A7017093A8010C94401341E050E060E069
:102F900070E004C0440F551F661F771F8A95D2F753
:102FA0008091A5019091A601A091A701B091A801DF
:102FB000842B952BA62BB72B8093A5019093A6016C
:102FC000A093A701B093A8010C94401341E050E0F6
:102FD00060E070E004C0440F551F661F771F8A959C
:102FE000D2F740955095609570958091A50190918C
:102FF000A601A091A701B091A80184239523A6233F
:10300000B7238093A5019093A601A093A701B09345
:10301000A8010C94401341E050E060E070E004C06F
:10302000440F551F661F771F8A95D2F78091A5011F
:103030009091A601A091A701B091A801842795279E
:10304000A627B7278093A5019093A601A093A70177
:10305000B093A8010C9440130F931F930091A50106
:103060001091A6012091A7013091A801062B172BE2
:10307000282B392B0093A5011093A6012093A701BB
:103080003093A8011F910F910C9440130F931F933D
:103090000091A5011091A6012091A7013091A801EE
:1030A00006231723282339230093A5011093A60193
:1030B0002093A7013093A8011F910F910C94401306
:1030C0000F931F930091A5011091A6012091A701D4
:1030D0003091A80106271727282739270093A50133
:1030E0001093A6012093A7013093A8011F910F917F
:1030F0000C9440130895CF92DF92EF92FF920F93BA
:103100001F93CF93DF93EC01C090A901D090AA0147
:10311000E090AB01F090AC018091A5019091A601E7
:10312000A091A701B091A801C82AD92AEA2AFB2AAE
:103130000FE110E0B701A601002E04C07695679557
:10314000579547950A94D2F740FD05C001501109E3
:1031500088F780E007C0BE01802F0E942C060197EF
:10316000A9F3802FDF91CF911F910F91FF90EF90E6
:10317000DF90CF900895CF93DF93EC010E947B18EE
:10318000BE010E942C06DF91CF910895CB010E94D1
:10319000BB1808958091AD01859585958595089515
:1031A0008091AD018770089598E0899F9001112466
:1031B000622B6093AD010C94C5174091AD018095D1
:1031C00084238093AD01982F977069F450E0282FE5
:1031D000332727FD30954217530729F085958595AC
:1031E00085950C94E61708959091AD01977081E054
:1031F00009F480E0089590910B019923D9F0909102
:103200000C019923B9F0982F9695969596959F3035
:1032100088F5E0910D01F0910E01E90FF11D877025
:1032200021E030E001C0220F8A95EAF78181822BEC
:103230008183089540910D0150910E0120E030E00E
:103240009FEFFA01E20FF31F6281681799F09F3F29
:1032500019F4611101C0922F2F5F3F4F2E303105BD
:1032600081F79F3F39F0FA01E90FF11D97FDFA95BB
:1032700082830895089590910B019923E1F0909134
:103280000C019923C1F0982F9695969596959F30AD
:1032900020F5E0910D01F0910E01E90FF11D87700D
:1032A00021E030E001C0220F8A95EAF72095818164
:1032B00028232183089540910D0150910E0120E0B3
:1032C00030E0FA01E20FF31F9281981301C01282DD
:1032D0002F5F3F4F2E303105A1F7089581E090E038
:1032E000E0910D01F0910E01E80FF91F1082019697
:1032F00080319105A9F708959091C101982B909381
:10330000C101089580959091C10198239093C101C6
:1033100008951092C10108959091C001982B909347
:10332000C001089580959091C00198239093C001A9
:1033300008951092C00108959091BF01982B909329
:10334000BF01089580959091BF0198239093BF018C
:1033500008951092BF0108958093AE0108951092D0
:10336000AE01089540910D0150910E0120E030E032
:1033700080E0FA01E20FF31F918191118F5F2F5FBF
:103380003F4F2F303105A9F70895E0910D01F091DD
:103390000E018091C1018083E0910D01F0910E0139
:1033A00080819091C001892B8083E0910D01F09183
:1033B0000E0180819091BF01892B80839091AE0195
:1033C000992361F0E0910D01F0910E018081892B2C
:1033D00080830E94B21981111092AE0180910D017B
:1033E00090910E010C94910E40E0009739F09C01F1
:1033F00021503109822393234F5FF7CF842F089503
:103400008091CD01843039F11092C30120E488E12C
:1034100090E00FB6F894A895809360000FBE2093BB
:10342000600080E00E94FE0280E00E94C70683B731
:10343000817F846083BF83B7816083BF78948895E0
:1034400083B78E7F83BF88E10FB6F89480936000C6
:10345000109260000FBE08950895089580E00E94C4
:10346000FE020E942C1A0E9420070E942D1A0E9420
:10347000A70791E0811101C090E0892F08950E9473
:10348000501380E00E94FE020E94AF1D0E94850E34
:103490000C94C7061F920F920FB60F9211248F93B0
:1034A0009F93AF93BF938091C301811113C080910B
:1034B000C4019091C501A091C601B091C701419688
:1034C000A11DB11D8093C4019093C501A093C601B5
:1034D000B093C701BF91AF919F918F910F900FBE95
:1034E0000F901F90189582E084BD93E095BD9AEFF0
:1034F00097BD80936E0008952FB7F8948091C40112
:103500009091C501A091C601B091C7012FBF089548
:10351000CF92DF92EF92FF920F931F932FB7F89401
:103520004091C4015091C5016091C6017091C701DD
:103530002FBF6A017B01EE24FF248C0120E030E0E4
:10354000C016D106E206F30610F441505109481B9B
:10355000590BCA011F910F91FF90EF90DF90CF9010
:1035600008951F920F920FB60F9211248F939F937D
:10357000AF93BF938091C4019091C501A091C60102
:10358000B091C7010196A11DB11D8093C401909314
:10359000C501A093C601B093C701BF91AF919F91A0
:1035A0008F910F900FBE0F901F9018950E948B0B5C
:1035B000F8942FEF87EA91E6215080409040E1F7A0
:1035C00000C0000087E090EBDC018093D80190936D
:1035D000D901A093DA01B093DB012CE088E190E0FF
:1035E0000FB6F894A895809360000FBE20936000FA
:1035F000FFCFCF92DF92EF92FF920F931F93CF9363
:10360000DF93C82E83E0D82E01E010E08D2D0E94BC
:103610009D077C01CBE0D0E098010C2E02C0220F68
:10362000331F0A94E2F72E213F21232B49F06C2F00
:103630007D2D80E00E94AF03C81202C081E007C068
:10364000219750F7DA948FEFD812E0CF80E0DF9126
:10365000CF911F910F91FF90EF90DF90CF90089541
:10366000CF93C82F8CE20E94F91A882321F08C2F67
:10367000CF910C94F91A80E0CF910895CF930E94D6
:10368000881C811102C00E94691CC5E6C15049F026
:103690000E9420078FE39CE90197F1F700C000002A
:1036A000F5CF89E20E94301B811111C18AE20E948C
:1036B000301B81110E94691C85E00E94301B811122
:1036C0000E94D61A0E94931C8093C20187E00E9438
:1036D000301B882399F18BE10E94301B882351F025
:1036E0009091C20191FB882780F921E0822780FB1D
:1036F00091F922C08EE00E94301B882351F09091F6
:10370000C20192FB882780F921E0822780FB92F991
:1037100013C080E10E94301B9091C201882341F0C8
:1037200093FB882780F921E0822780FB93F904C06E
:10373000892F809580FB90F99093C2018091C201FE
:103740000E94971C0E94A51C8093D60180EE0E94C7
:10375000301B882341F08091D601982F909590FBE3
:1037600080F98093D60189E30E94301B882359F0A9
:103770009091D60191FB882780F921E0822780FB78
:1037800091F99093D60182EE0E94301B882359F064
:103790009091D60192FB882780F921E0822780FB57
:1037A00092F99093D60186EE0E94301B882359F03F
:1037B0009091D60193FB882780F921E0822780FB36
:1037C00093F99093D60183EE0E94301B882359F021
:1037D0009091D60194FB882780F921E0822780FB15
:1037E00094F99093D60185E30E94301B882359F009
:1037F0009091D60195FB882780F921E0822780FBF4
:1038000095F99093D60181E30E94301B882359F0EB
:103810009091D60196FB882780F921E0822780FBD2
:1038200096F99093D60181E10E94301B882359F0CC
:103830009091D60197FB882780F921E0822780FBB1
:1038400097F99093D6018091D6010E94A91C80918E
:10385000D60187FB882780F980930C0187E20E94BC
:10386000301BC82F8EE10E94301B8111C2608FE196
:103870000E94301B8111C46080E20E94301B8111C4
:10388000C86081E20E94301B8111C06182E20E9407
:10389000301B8111C06283E20E94301B8111C06421
:1038A00084E20E94301B882311F0C06802C0CC2340
:1038B00029F08C2F0E94A01C6C2F03C00E949C1C1E
:1038C000682F70E080E090E0CF910C944E17CF917C
:1038D00008956DEE7EEF80E090E00E946D1E60E046
:1038E00082E090E00E945B1E60E083E090E00E9436
:1038F0005B1E60E084E090E00E945B1E60E085E07B
:1039000090E00E945B1E60E086E090E00C945B1EFD
:1039100080E090E00E94551E21E08D3E9E4F09F010
:1039200020E0822F089582E090E00C944D1E682FD5
:1039300082E090E00C945B1E83E090E00C944D1EBE
:10394000682F83E090E00C945B1E84E090E00C9480
:103950004D1E682F84E090E00C945B1E86E090E0A2
:103960000C944D1E682F86E090E00C945B1E8B310A
:1039700009F46AC008F58E3009F470C070F487301D
:1039800009F452C018F48630B9F134C0883009F413
:10399000A1C08B3009F49EC02DC0813109F479C0DB
:1039A00020F4803109F464C025C0863109F492C046
:1039B000893109F48FC01EC0853309F483C060F4D7
:1039C000873209F47FC020F48E3108F06DC012C038
:1039D000893209F477C00EC0833438F48A3308F092
:1039E00061C0883309F476C005C0833409F46AC025
:1039F000883461F080E008958091C201817F8E7FDC
:103A00008093C20181E08093C80108950E94501301
:103A10002FEF83ED90E3215080409040E1F700C00C
:103A200000000E94D61A56C09091C201892F80953D
:103A3000817080FB90F919F09660986027C0997F9B
:103A4000977F9093C20146C09091C20191FB882755
:103A500080F921E0822780FB91F913C09091C20187
:103A600092FB882780F921E0822780FB92F909C028
:103A70009091C20193FB882780F921E0822780FB87
:103A800093F99093C201882329F191609093C20128
:103A900008950E94501380910C0191E08927809332
:103AA0000C0118C027EC01C023EE280F61E070E084
:103AB00080E090E004C0660F771F881F991F2A9549
:103AC000D2F704C061E070E080E090E00E944E1701
:103AD0000E94501381E0089580E0089580E00895E9
:103AE000CF93C82F8091C801882319F0813049F005
:103AF0002EC0E0910D01F0910E018081823249F5D6
:103B000007C0E0910D01F0910E018081823249F4ED
:103B10008C2F0E946C1D811117C08C2F0E94B71C26
:103B200014C08C2F0E946E1D81110EC0C43149F04B
:103B300018F4CB3049F00FC0C93219F0C83321F066
:103B40000AC01092C80107C081E0817006C01092BF
:103B5000C80180E002C080E0F8CFCF9108950E94B4
:103B6000881C811102C00E94691C0E94AE1C8093B7
:103B7000D70180FF02C0869501C080E00C94FE0250
:103B80008091D701982F9695292F30E02830310564
:103B90004CF49F5F990F8170892B81608093D701CE
:103BA0000E94B21C8091D70186950C94FE028091F0
:103BB000D701982F969591F09158990F8170892B84
:103BC0008093D7018E7F91E009F490E08091D70136
:103BD00090FB80F98093D7010E94B21C8091D7019D
:103BE00086950C94FE028091D701982F909590FBBA
:103BF00080F98093D7010E94B21C8091D70180FF89
:103C000002C0869501C080E00C94FE023091D7017D
:103C1000232F26952F5F2F77822F90E03170099701
:103C20002CF4220F232B2093D70102C03093D7010D
:103C30008091D7018E7F91E009F490E08091D701C7
:103C400090FB80F98093D7010E94B21C8091D7012C
:103C500086950C94FE022091D701922F9695982775
:103C6000990F822F8170892B8093D7018E7F91E0ED
:103C700009F490E08091D70190FB80F98093D701FF
:103C80000E94B21C8091D70186950C94FE02EE0F23
:103C9000FF1F0590F491E02D0994F999FECF92BD94
:103CA00081BDF89A992780B50895A8E1B0E042E077
:103CB00050E00C94751E262FF999FECF92BD81BD60
:103CC000F89A019700B4021639F01FBA20BD0FB65A
:103CD000F894FA9AF99A0FBE08950196272F0E9438
:103CE0005C1E0C945B1EDC01CB01FC01F999FECF3C
:103CF00006C0F2BDE1BDF89A319600B40D92415074
:0A3D00005040B8F70895F894FFCF83
:103D0A00FFBB072608BE07F307BF070101AF01295A
:103D1A0039596943636F5F4F1F0F3379537F493FA7
:0E3D2A003639FD04C7048E043A0453046C04B9
:00000001FF

+ 30
- 0
keyboard/tv44/tv44.c View File

@@ -0,0 +1,30 @@
#include "tv44.h"
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "progmem.h"

__attribute__ ((weak))
void matrix_init_user(void) {}

__attribute__ ((weak))
void matrix_scan_user(void) {}

__attribute__ ((weak))
void process_action_user(keyrecord_t *record) {}

void matrix_init_kb(void) {
#ifdef BACKLIGHT_ENABLE
backlight_init_ports();
#endif
matrix_init_user();
}

void matrix_scan_kb(void) {
matrix_scan_user();
bl_set();
}

void process_action_kb(keyrecord_t *record) {
process_action_user(record);
}

+ 21
- 0
keyboard/tv44/tv44.h View File

@@ -0,0 +1,21 @@
#ifndef TV44_H
#define TV44_H

#include "matrix.h"
#include "keymap_common.h"
#ifdef BACKLIGHT_ENABLE
#include "backlight.h"
#endif
#ifdef RGBLIGHT_ENABLE
#include "rgblight1.h"
#endif
#include <stddef.h>
#ifdef MIDI_ENABLE
#include <keymap_midi.h>
#endif

void matrix_init_user(void);
void matrix_scan_user(void);
void process_action_user(keyrecord_t *record);

#endif

+ 53
- 0
quantum/analog.c View File

@@ -0,0 +1,53 @@
// Simple analog to digitial conversion

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdint.h>
#include "analog.h"


static uint8_t aref = (1<<REFS0); // default to AREF = Vcc


void analogReference(uint8_t mode)
{
aref = mode & 0xC0;
}


// Arduino compatible pin input
int16_t analogRead(uint8_t pin)
{
#if defined(__AVR_ATmega32U4__)
static const uint8_t PROGMEM pin_to_mux[] = {
0x00, 0x01, 0x04, 0x05, 0x06, 0x07,
0x25, 0x24, 0x23, 0x22, 0x21, 0x20};
if (pin >= 12) return 0;
return adc_read(pgm_read_byte(pin_to_mux + pin));
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
if (pin >= 8) return 0;
return adc_read(pin);
#else
return 0;
#endif
}

// Mux input
int16_t adc_read(uint8_t mux)
{
#if defined(__AVR_AT90USB162__)
return 0;
#else
uint8_t low;

ADCSRA = (1<<ADEN) | ADC_PRESCALER; // enable ADC
ADCSRB = (1<<ADHSM) | (mux & 0x20); // high speed mode
ADMUX = aref | (mux & 0x1F); // configure mux input
ADCSRA = (1<<ADEN) | ADC_PRESCALER | (1<<ADSC); // start the conversion
while (ADCSRA & (1<<ADSC)) ; // wait for result
low = ADCL; // must read LSB first
return (ADCH << 8) | low; // must read MSB only once!
#endif
}



+ 36
- 0
quantum/analog.h View File

@@ -0,0 +1,36 @@
#ifndef _analog_h_included__
#define _analog_h_included__

#include <stdint.h>

void analogReference(uint8_t mode);
int16_t analogRead(uint8_t pin);
int16_t adc_read(uint8_t mux);

#define ADC_REF_POWER (1<<REFS0)
#define ADC_REF_INTERNAL ((1<<REFS1) | (1<<REFS0))
#define ADC_REF_EXTERNAL (0)

// These prescaler values are for high speed mode, ADHSM = 1
#if F_CPU == 16000000L
#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS1))
#elif F_CPU == 8000000L
#define ADC_PRESCALER ((1<<ADPS2) | (1<<ADPS0))
#elif F_CPU == 4000000L
#define ADC_PRESCALER ((1<<ADPS2))
#elif F_CPU == 2000000L
#define ADC_PRESCALER ((1<<ADPS1) | (1<<ADPS0))
#elif F_CPU == 1000000L
#define ADC_PRESCALER ((1<<ADPS1))
#else
#define ADC_PRESCALER ((1<<ADPS0))
#endif

// some avr-libc versions do not properly define ADHSM
#if defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#if !defined(ADHSM)
#define ADHSM (7)
#endif
#endif

#endif

+ 477
- 0
quantum/audio/audio.c View File

@@ -0,0 +1,477 @@
#include <stdio.h>
#include <string.h>
//#include <math.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include "print.h"
#include "audio.h"
#include "keymap_common.h"

#include "eeconfig.h"

#define CPU_PRESCALER 8

// -----------------------------------------------------------------------------
// Timer Abstractions
// -----------------------------------------------------------------------------

// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
// Turn on/off 3A interputs, stopping/enabling the ISR calls
#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)

// TCCR3A: Timer/Counter #3 Control Register
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));

// Fast PWM Mode Controls
#define TIMER_3_PERIOD ICR3
#define TIMER_3_DUTY_CYCLE OCR3A

// -----------------------------------------------------------------------------


int voices = 0;
int voice_place = 0;
float frequency = 0;
int volume = 0;
long position = 0;

float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
bool sliding = false;

float place = 0;

uint8_t * sample;
uint16_t sample_length = 0;

bool playing_notes = false;
bool playing_note = false;
float note_frequency = 0;
float note_length = 0;
uint8_t note_tempo = TEMPO_DEFAULT;
float note_timbre = TIMBRE_DEFAULT;
uint16_t note_position = 0;
float (* notes_pointer)[][2];
uint16_t notes_count;
bool notes_repeat;
float notes_rest;
bool note_resting = false;

uint8_t current_note = 0;
uint8_t rest_counter = 0;

#ifdef VIBRATO_ENABLE
float vibrato_counter = 0;
float vibrato_strength = .5;
float vibrato_rate = 0.125;
#endif

float polyphony_rate = 0;

static bool audio_initialized = false;

audio_config_t audio_config;

uint16_t envelope_index = 0;

void audio_init()
{

// Check EEPROM
if (!eeconfig_is_enabled())
{
eeconfig_init();
}
audio_config.raw = eeconfig_read_audio();

// Set port PC6 (OC3A and /OC4A) as output
DDRC |= _BV(PORTC6);

DISABLE_AUDIO_COUNTER_3_ISR;

// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
// Clock Select (CS3n) = 0b010 = Clock / 8
TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);

audio_initialized = true;
}

void stop_all_notes()
{
if (!audio_initialized) {
audio_init();
}
voices = 0;

DISABLE_AUDIO_COUNTER_3_ISR;
DISABLE_AUDIO_COUNTER_3_OUTPUT;

playing_notes = false;
playing_note = false;
frequency = 0;
volume = 0;

for (uint8_t i = 0; i < 8; i++)
{
frequencies[i] = 0;
volumes[i] = 0;
}
}

void stop_note(float freq)
{
if (playing_note) {
if (!audio_initialized) {
audio_init();
}
for (int i = 7; i >= 0; i--) {
if (frequencies[i] == freq) {
frequencies[i] = 0;
volumes[i] = 0;
for (int j = i; (j < 7); j++) {
frequencies[j] = frequencies[j+1];
frequencies[j+1] = 0;
volumes[j] = volumes[j+1];
volumes[j+1] = 0;
}
break;
}
}
voices--;
if (voices < 0)
voices = 0;
if (voice_place >= voices) {
voice_place = 0;
}
if (voices == 0) {
DISABLE_AUDIO_COUNTER_3_ISR;
DISABLE_AUDIO_COUNTER_3_OUTPUT;
frequency = 0;
volume = 0;
playing_note = false;
}
}
}

#ifdef VIBRATO_ENABLE

float mod(float a, int b)
{
float r = fmod(a, b);
return r < 0 ? r + b : r;
}

float vibrato(float average_freq) {
#ifdef VIBRATO_STRENGTH_ENABLE
float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
#else
float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
#endif
vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
return vibrated_freq;
}

#endif

ISR(TIMER3_COMPA_vect)
{
float freq;

if (playing_note) {
if (voices > 0) {
if (polyphony_rate > 0) {
if (voices > 1) {
voice_place %= voices;
if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
voice_place = (voice_place + 1) % voices;
place = 0.0;
}
}

#ifdef VIBRATO_ENABLE
if (vibrato_strength > 0) {
freq = vibrato(frequencies[voice_place]);
} else {
freq = frequencies[voice_place];
}
#else
freq = frequencies[voice_place];
#endif
} else {
if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
frequency = frequency * pow(2, 440/frequency/12/2);
} else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
frequency = frequency * pow(2, -440/frequency/12/2);
} else {
frequency = frequencies[voices - 1];
}

#ifdef VIBRATO_ENABLE
if (vibrato_strength > 0) {
freq = vibrato(frequency);
} else {
freq = frequency;
}
#else
freq = frequency;
#endif
}

if (envelope_index < 65535) {
envelope_index++;
}

freq = voice_envelope(freq);

if (freq < 30.517578125) {
freq = 30.52;
}

TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
}
}

if (playing_notes) {
if (note_frequency > 0) {
#ifdef VIBRATO_ENABLE
if (vibrato_strength > 0) {
freq = vibrato(note_frequency);
} else {
freq = note_frequency;
}
#else
freq = note_frequency;
#endif

if (envelope_index < 65535) {
envelope_index++;
}
freq = voice_envelope(freq);

TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER));
TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre);
} else {
TIMER_3_PERIOD = 0;
TIMER_3_DUTY_CYCLE = 0;
}

note_position++;
bool end_of_note = false;
if (TIMER_3_PERIOD > 0) {
end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF));
} else {
end_of_note = (note_position >= (note_length * 0x7FF));
}

if (end_of_note) {
current_note++;
if (current_note >= notes_count) {
if (notes_repeat) {
current_note = 0;
} else {
DISABLE_AUDIO_COUNTER_3_ISR;
DISABLE_AUDIO_COUNTER_3_OUTPUT;
playing_notes = false;
return;
}
}
if (!note_resting && (notes_rest > 0)) {
note_resting = true;
note_frequency = 0;
note_length = notes_rest;
current_note--;
} else {
note_resting = false;
envelope_index = 0;
note_frequency = (*notes_pointer)[current_note][0];
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
}

note_position = 0;
}
}

if (!audio_config.enable) {
playing_notes = false;
playing_note = false;
}
}

void play_note(float freq, int vol) {

if (!audio_initialized) {
audio_init();
}

if (audio_config.enable && voices < 8) {
DISABLE_AUDIO_COUNTER_3_ISR;

// Cancel notes if notes are playing
if (playing_notes)
stop_all_notes();

playing_note = true;

envelope_index = 0;

if (freq > 0) {
frequencies[voices] = freq;
volumes[voices] = vol;
voices++;
}

ENABLE_AUDIO_COUNTER_3_ISR;
ENABLE_AUDIO_COUNTER_3_OUTPUT;
}

}

void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
{

if (!audio_initialized) {
audio_init();
}

if (audio_config.enable) {

DISABLE_AUDIO_COUNTER_3_ISR;

// Cancel note if a note is playing
if (playing_note)
stop_all_notes();

playing_notes = true;

notes_pointer = np;
notes_count = n_count;
notes_repeat = n_repeat;
notes_rest = n_rest;

place = 0;
current_note = 0;

note_frequency = (*notes_pointer)[current_note][0];
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
note_position = 0;


ENABLE_AUDIO_COUNTER_3_ISR;
ENABLE_AUDIO_COUNTER_3_OUTPUT;
}

}

bool is_playing_notes(void) {
return playing_notes;
}

bool is_audio_on(void) {
return (audio_config.enable != 0);
}

void audio_toggle(void) {
audio_config.enable ^= 1;
eeconfig_update_audio(audio_config.raw);
if (audio_config.enable)
audio_on_user();
}

void audio_on(void) {
audio_config.enable = 1;
eeconfig_update_audio(audio_config.raw);
audio_on_user();
}

void audio_off(void) {
audio_config.enable = 0;
eeconfig_update_audio(audio_config.raw);
}

#ifdef VIBRATO_ENABLE

// Vibrato rate functions

void set_vibrato_rate(float rate) {
vibrato_rate = rate;
}

void increase_vibrato_rate(float change) {
vibrato_rate *= change;
}

void decrease_vibrato_rate(float change) {
vibrato_rate /= change;
}

#ifdef VIBRATO_STRENGTH_ENABLE

void set_vibrato_strength(float strength) {
vibrato_strength = strength;
}

void increase_vibrato_strength(float change) {
vibrato_strength *= change;
}

void decrease_vibrato_strength(float change) {
vibrato_strength /= change;
}

#endif /* VIBRATO_STRENGTH_ENABLE */

#endif /* VIBRATO_ENABLE */

// Polyphony functions

void set_polyphony_rate(float rate) {
polyphony_rate = rate;
}

void enable_polyphony() {
polyphony_rate = 5;
}

void disable_polyphony() {
polyphony_rate = 0;
}

void increase_polyphony_rate(float change) {
polyphony_rate *= change;
}

void decrease_polyphony_rate(float change) {
polyphony_rate /= change;
}

// Timbre function

void set_timbre(float timbre) {
note_timbre = timbre;
}

// Tempo functions

void set_tempo(uint8_t tempo) {
note_tempo = tempo;
}

void decrease_tempo(uint8_t tempo_change) {
note_tempo += tempo_change;
}

void increase_tempo(uint8_t tempo_change) {
if (note_tempo - tempo_change < 10) {
note_tempo = 10;
} else {
note_tempo -= tempo_change;
}
}

+ 91
- 0
quantum/audio/audio.h View File

@@ -0,0 +1,91 @@
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "musical_notes.h"
#include "song_list.h"
#include "voices.h"
#include "quantum.h"

#ifndef AUDIO_H
#define AUDIO_H

// Largely untested PWM audio mode (doesn't sound as good)
// #define PWM_AUDIO

// #define VIBRATO_ENABLE

// Enable vibrato strength/amplitude - slows down ISR too much
// #define VIBRATO_STRENGTH_ENABLE

typedef union {
uint8_t raw;
struct {
bool enable :1;
uint8_t level :7;
};
} audio_config_t;

bool is_audio_on(void);
void audio_toggle(void);
void audio_on(void);
void audio_off(void);

// Vibrato rate functions

#ifdef VIBRATO_ENABLE

void set_vibrato_rate(float rate);
void increase_vibrato_rate(float change);
void decrease_vibrato_rate(float change);

#ifdef VIBRATO_STRENGTH_ENABLE

void set_vibrato_strength(float strength);
void increase_vibrato_strength(float change);
void decrease_vibrato_strength(float change);

#endif

#endif

// Polyphony functions

void set_polyphony_rate(float rate);
void enable_polyphony(void);
void disable_polyphony(void);
void increase_polyphony_rate(float change);
void decrease_polyphony_rate(float change);

void set_timbre(float timbre);
void set_tempo(uint8_t tempo);

void increase_tempo(uint8_t tempo_change);
void decrease_tempo(uint8_t tempo_change);

void audio_init(void);

#ifdef PWM_AUDIO
void play_sample(uint8_t * s, uint16_t l, bool r);
#endif
void play_note(float freq, int vol);
void stop_note(float freq);
void stop_all_notes(void);
void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest);

#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }

// These macros are used to allow play_notes to play an array of indeterminate
// length. This works around the limitation of C's sizeof operation on pointers.
// The global float array for the song must be used here.
#define NOTE_ARRAY_SIZE(x) ((int16_t)(sizeof(x) / (sizeof(x[0]))))
#define PLAY_NOTE_ARRAY(note_array, note_repeat, note_rest_style) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style));


bool is_playing_notes(void);

#endif

+ 643
- 0
quantum/audio/audio_pwm.c View File

@@ -0,0 +1,643 @@
#include <stdio.h>
#include <string.h>
//#include <math.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include "print.h"
#include "audio.h"
#include "keymap_common.h"

#include "eeconfig.h"

#define PI 3.14159265

#define CPU_PRESCALER 8


// Timer Abstractions

// TIMSK3 - Timer/Counter #3 Interrupt Mask Register
// Turn on/off 3A interputs, stopping/enabling the ISR calls
#define ENABLE_AUDIO_COUNTER_3_ISR TIMSK3 |= _BV(OCIE3A)
#define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)


// TCCR3A: Timer/Counter #3 Control Register
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
#define ENABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A |= _BV(COM3A1);
#define DISABLE_AUDIO_COUNTER_3_OUTPUT TCCR3A &= ~(_BV(COM3A1) | _BV(COM3A0));


#define NOTE_PERIOD ICR3
#define NOTE_DUTY_CYCLE OCR3A


#ifdef PWM_AUDIO
#include "wave.h"
#define SAMPLE_DIVIDER 39
#define SAMPLE_RATE (2000000.0/SAMPLE_DIVIDER/2048)
// Resistor value of 1/ (2 * PI * 10nF * (2000000 hertz / SAMPLE_DIVIDER / 10)) for 10nF cap

float places[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint16_t place_int = 0;
bool repeat = true;
#endif

void delay_us(int count) {
while(count--) {
_delay_us(1);
}
}

int voices = 0;
int voice_place = 0;
float frequency = 0;
int volume = 0;
long position = 0;

float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
bool sliding = false;

float place = 0;

uint8_t * sample;
uint16_t sample_length = 0;
// float freq = 0;

bool playing_notes = false;
bool playing_note = false;
float note_frequency = 0;
float note_length = 0;
uint8_t note_tempo = TEMPO_DEFAULT;
float note_timbre = TIMBRE_DEFAULT;
uint16_t note_position = 0;
float (* notes_pointer)[][2];
uint16_t notes_count;
bool notes_repeat;
float notes_rest;
bool note_resting = false;

uint8_t current_note = 0;
uint8_t rest_counter = 0;

#ifdef VIBRATO_ENABLE
float vibrato_counter = 0;
float vibrato_strength = .5;
float vibrato_rate = 0.125;
#endif

float polyphony_rate = 0;

static bool audio_initialized = false;

audio_config_t audio_config;

uint16_t envelope_index = 0;

void audio_init() {

// Check EEPROM
if (!eeconfig_is_enabled())
{
eeconfig_init();
}
audio_config.raw = eeconfig_read_audio();

#ifdef PWM_AUDIO

PLLFRQ = _BV(PDIV2);
PLLCSR = _BV(PLLE);
while(!(PLLCSR & _BV(PLOCK)));
PLLFRQ |= _BV(PLLTM0); /* PCK 48MHz */

/* Init a fast PWM on Timer4 */
TCCR4A = _BV(COM4A0) | _BV(PWM4A); /* Clear OC4A on Compare Match */
TCCR4B = _BV(CS40); /* No prescaling => f = PCK/256 = 187500Hz */
OCR4A = 0;

/* Enable the OC4A output */
DDRC |= _BV(PORTC6);

DISABLE_AUDIO_COUNTER_3_ISR; // Turn off 3A interputs

TCCR3A = 0x0; // Options not needed
TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC
OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback

#else

// Set port PC6 (OC3A and /OC4A) as output
DDRC |= _BV(PORTC6);

DISABLE_AUDIO_COUNTER_3_ISR;

// TCCR3A / TCCR3B: Timer/Counter #3 Control Registers
// Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6
// Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A)
// Clock Select (CS3n) = 0b010 = Clock / 8
TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30);

#endif

audio_initialized = true;
}

void stop_all_notes() {
if (!audio_initialized) {
audio_init();
}
voices = 0;
#ifdef PWM_AUDIO
DISABLE_AUDIO_COUNTER_3_ISR;
#else
DISABLE_AUDIO_COUNTER_3_ISR;
DISABLE_AUDIO_COUNTER_3_OUTPUT;
#endif

playing_notes = false;
playing_note = false;
frequency = 0;
volume = 0;

for (uint8_t i = 0; i < 8; i++)
{
frequencies[i] = 0;
volumes[i] = 0;
}
}

void stop_note(float freq)
{
if (playing_note) {
if (!audio_initialized) {
audio_init();
}
#ifdef PWM_AUDIO
freq = freq / SAMPLE_RATE;
#endif
for (int i = 7; i >= 0; i--) {
if (frequencies[i] == freq) {
frequencies[i] = 0;
volumes[i] = 0;
for (int j = i; (j < 7); j++) {
frequencies[j] = frequencies[j+1];
frequencies[j+1] = 0;
volumes[j] = volumes[j+1];
volumes[j+1] = 0;
}
break;
}
}
voices--;
if (voices < 0)
voices = 0;
if (voice_place >= voices) {
voice_place = 0;
}
if (voices == 0) {
#ifdef PWM_AUDIO
DISABLE_AUDIO_COUNTER_3_ISR;
#else
DISABLE_AUDIO_COUNTER_3_ISR;
DISABLE_AUDIO_COUNTER_3_OUTPUT;
#endif
frequency = 0;
volume = 0;
playing_note = false;
}
}
}

#ifdef VIBRATO_ENABLE

float mod(float a, int b)
{
float r = fmod(a, b);
return r < 0 ? r + b : r;
}

float vibrato(float average_freq) {
#ifdef VIBRATO_STRENGTH_ENABLE
float vibrated_freq = average_freq * pow(vibrato_lut[(int)vibrato_counter], vibrato_strength);
#else
float vibrated_freq = average_freq * vibrato_lut[(int)vibrato_counter];
#endif
vibrato_counter = mod((vibrato_counter + vibrato_rate * (1.0 + 440.0/average_freq)), VIBRATO_LUT_LENGTH);
return vibrated_freq;
}

#endif

ISR(TIMER3_COMPA_vect)
{
if (playing_note) {
#ifdef PWM_AUDIO
if (voices == 1) {
// SINE
OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2;

// SQUARE
// if (((int)place) >= 1024){
// OCR4A = 0xFF >> 2;
// } else {
// OCR4A = 0x00;
// }

// SAWTOOTH
// OCR4A = (int)place / 4;

// TRIANGLE
// if (((int)place) >= 1024) {
// OCR4A = (int)place / 2;
// } else {
// OCR4A = 2048 - (int)place / 2;
// }

place += frequency;

if (place >= SINE_LENGTH)
place -= SINE_LENGTH;

} else {
int sum = 0;
for (int i = 0; i < voices; i++) {
// SINE
sum += pgm_read_byte(&sinewave[(uint16_t)places[i]]) >> 2;

// SQUARE
// if (((int)places[i]) >= 1024){
// sum += 0xFF >> 2;
// } else {
// sum += 0x00;
// }

places[i] += frequencies[i];

if (places[i] >= SINE_LENGTH)
places[i] -= SINE_LENGTH;
}
OCR4A = sum;
}
#else
if (voices > 0) {
float freq;
if (polyphony_rate > 0) {
if (voices > 1) {
voice_place %= voices;
if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) {
voice_place = (voice_place + 1) % voices;
place = 0.0;
}
}
#ifdef VIBRATO_ENABLE
if (vibrato_strength > 0) {
freq = vibrato(frequencies[voice_place]);
} else {
#else
{
#endif
freq = frequencies[voice_place];
}
} else {
if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) {
frequency = frequency * pow(2, 440/frequency/12/2);
} else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) {
frequency = frequency * pow(2, -440/frequency/12/2);
} else {
frequency = frequencies[voices - 1];
}


#ifdef VIBRATO_ENABLE
if (vibrato_strength > 0) {
freq = vibrato(frequency);
} else {
#else
{
#endif
freq = frequency;
}
}

if (envelope_index < 65535) {
envelope_index++;
}
freq = voice_envelope(freq);

if (freq < 30.517578125)
freq = 30.52;
NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
}
#endif
}

// SAMPLE
// OCR4A = pgm_read_byte(&sample[(uint16_t)place_int]);

// place_int++;

// if (place_int >= sample_length)
// if (repeat)
// place_int -= sample_length;
// else
// DISABLE_AUDIO_COUNTER_3_ISR;


if (playing_notes) {
#ifdef PWM_AUDIO
OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 0;

place += note_frequency;
if (place >= SINE_LENGTH)
place -= SINE_LENGTH;
#else
if (note_frequency > 0) {
float freq;

#ifdef VIBRATO_ENABLE
if (vibrato_strength > 0) {
freq = vibrato(note_frequency);
} else {
#else
{
#endif
freq = note_frequency;
}

if (envelope_index < 65535) {
envelope_index++;
}
freq = voice_envelope(freq);

NOTE_PERIOD = (int)(((double)F_CPU) / (freq * CPU_PRESCALER)); // Set max to the period
NOTE_DUTY_CYCLE = (int)((((double)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
} else {
NOTE_PERIOD = 0;
NOTE_DUTY_CYCLE = 0;
}
#endif


note_position++;
bool end_of_note = false;
if (NOTE_PERIOD > 0)
end_of_note = (note_position >= (note_length / NOTE_PERIOD * 0xFFFF));
else
end_of_note = (note_position >= (note_length * 0x7FF));
if (end_of_note) {
current_note++;
if (current_note >= notes_count) {
if (notes_repeat) {
current_note = 0;
} else {
#ifdef PWM_AUDIO
DISABLE_AUDIO_COUNTER_3_ISR;
#else
DISABLE_AUDIO_COUNTER_3_ISR;
DISABLE_AUDIO_COUNTER_3_OUTPUT;
#endif
playing_notes = false;
return;
}
}
if (!note_resting && (notes_rest > 0)) {
note_resting = true;
note_frequency = 0;
note_length = notes_rest;
current_note--;
} else {
note_resting = false;
#ifdef PWM_AUDIO
note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
#else
envelope_index = 0;
note_frequency = (*notes_pointer)[current_note][0];
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
#endif
}
note_position = 0;
}

}

if (!audio_config.enable) {
playing_notes = false;
playing_note = false;
}
}

void play_note(float freq, int vol) {

if (!audio_initialized) {
audio_init();
}

if (audio_config.enable && voices < 8) {
DISABLE_AUDIO_COUNTER_3_ISR;

// Cancel notes if notes are playing
if (playing_notes)
stop_all_notes();

playing_note = true;

envelope_index = 0;

#ifdef PWM_AUDIO
freq = freq / SAMPLE_RATE;
#endif
if (freq > 0) {
frequencies[voices] = freq;
volumes[voices] = vol;
voices++;
}

#ifdef PWM_AUDIO
ENABLE_AUDIO_COUNTER_3_ISR;
#else
ENABLE_AUDIO_COUNTER_3_ISR;
ENABLE_AUDIO_COUNTER_3_OUTPUT;
#endif
}

}

void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest)
{

if (!audio_initialized) {
audio_init();
}

if (audio_config.enable) {

DISABLE_AUDIO_COUNTER_3_ISR;

// Cancel note if a note is playing
if (playing_note)
stop_all_notes();

playing_notes = true;

notes_pointer = np;
notes_count = n_count;
notes_repeat = n_repeat;
notes_rest = n_rest;

place = 0;
current_note = 0;

#ifdef PWM_AUDIO
note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
note_length = (*notes_pointer)[current_note][1] * (((float)note_tempo) / 100);
#else
note_frequency = (*notes_pointer)[current_note][0];
note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100);
#endif
note_position = 0;


#ifdef PWM_AUDIO
ENABLE_AUDIO_COUNTER_3_ISR;
#else
ENABLE_AUDIO_COUNTER_3_ISR;
ENABLE_AUDIO_COUNTER_3_OUTPUT;
#endif
}

}

#ifdef PWM_AUDIO
void play_sample(uint8_t * s, uint16_t l, bool r) {
if (!audio_initialized) {
audio_init();
}

if (audio_config.enable) {
DISABLE_AUDIO_COUNTER_3_ISR;
stop_all_notes();
place_int = 0;
sample = s;
sample_length = l;
repeat = r;

ENABLE_AUDIO_COUNTER_3_ISR;
}
}
#endif


void audio_toggle(void) {
audio_config.enable ^= 1;
eeconfig_update_audio(audio_config.raw);
}

void audio_on(void) {
audio_config.enable = 1;
eeconfig_update_audio(audio_config.raw);
}

void audio_off(void) {
audio_config.enable = 0;
eeconfig_update_audio(audio_config.raw);
}

#ifdef VIBRATO_ENABLE

// Vibrato rate functions

void set_vibrato_rate(float rate) {
vibrato_rate = rate;
}

void increase_vibrato_rate(float change) {
vibrato_rate *= change;
}

void decrease_vibrato_rate(float change) {
vibrato_rate /= change;
}

#ifdef VIBRATO_STRENGTH_ENABLE

void set_vibrato_strength(float strength) {
vibrato_strength = strength;
}

void increase_vibrato_strength(float change) {
vibrato_strength *= change;
}

void decrease_vibrato_strength(float change) {
vibrato_strength /= change;
}

#endif /* VIBRATO_STRENGTH_ENABLE */

#endif /* VIBRATO_ENABLE */

// Polyphony functions

void set_polyphony_rate(float rate) {
polyphony_rate = rate;
}

void enable_polyphony() {
polyphony_rate = 5;
}

void disable_polyphony() {
polyphony_rate = 0;
}

void increase_polyphony_rate(float change) {
polyphony_rate *= change;
}

void decrease_polyphony_rate(float change) {
polyphony_rate /= change;
}

// Timbre function

void set_timbre(float timbre) {
note_timbre = timbre;
}

// Tempo functions

void set_tempo(uint8_t tempo) {
note_tempo = tempo;
}

void decrease_tempo(uint8_t tempo_change) {
note_tempo += tempo_change;
}

void increase_tempo(uint8_t tempo_change) {
if (note_tempo - tempo_change < 10) {
note_tempo = 10;
} else {
note_tempo -= tempo_change;
}
}


//------------------------------------------------------------------------------
// Override these functions in your keymap file to play different tunes on
// startup and bootloader jump
__attribute__ ((weak))
void play_startup_tone()
{
}

__attribute__ ((weak))
void play_goodbye_tone()
{
}
//------------------------------------------------------------------------------

+ 382
- 0
quantum/audio/luts.c View File

@@ -0,0 +1,382 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include "luts.h"

const float vibrato_lut[VIBRATO_LUT_LENGTH] =
{
1.0022336811487,
1.0042529943610,
1.0058584256028,
1.0068905285205,
1.0072464122237,
1.0068905285205,
1.0058584256028,
1.0042529943610,
1.0022336811487,
1.0000000000000,
0.9977712970630,
0.9957650169978,
0.9941756956510,
0.9931566259436,
0.9928057204913,
0.9931566259436,
0.9941756956510,
0.9957650169978,
0.9977712970630,
1.0000000000000,
};

const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH] =
{
0x8E0B,
0x8C02,
0x8A00,
0x8805,
0x8612,
0x8426,
0x8241,
0x8063,
0x7E8C,
0x7CBB,
0x7AF2,
0x792E,
0x7772,
0x75BB,
0x740B,
0x7261,
0x70BD,
0x6F20,
0x6D88,
0x6BF6,
0x6A69,
0x68E3,
0x6762,
0x65E6,
0x6470,
0x6300,
0x6194,
0x602E,
0x5ECD,
0x5D71,
0x5C1A,
0x5AC8,
0x597B,
0x5833,
0x56EF,
0x55B0,
0x5475,
0x533F,
0x520E,
0x50E1,
0x4FB8,
0x4E93,
0x4D73,
0x4C57,
0x4B3E,
0x4A2A,
0x491A,
0x480E,
0x4705,
0x4601,
0x4500,
0x4402,
0x4309,
0x4213,
0x4120,
0x4031,
0x3F46,
0x3E5D,
0x3D79,
0x3C97,
0x3BB9,
0x3ADD,
0x3A05,
0x3930,
0x385E,
0x3790,
0x36C4,
0x35FB,
0x3534,
0x3471,
0x33B1,
0x32F3,
0x3238,
0x3180,
0x30CA,
0x3017,
0x2F66,
0x2EB8,
0x2E0D,
0x2D64,
0x2CBD,
0x2C19,
0x2B77,
0x2AD8,
0x2A3A,
0x299F,
0x2907,
0x2870,
0x27DC,
0x2749,
0x26B9,
0x262B,
0x259F,
0x2515,
0x248D,
0x2407,
0x2382,
0x2300,
0x2280,
0x2201,
0x2184,
0x2109,
0x2090,
0x2018,
0x1FA3,
0x1F2E,
0x1EBC,
0x1E4B,
0x1DDC,
0x1D6E,
0x1D02,
0x1C98,
0x1C2F,
0x1BC8,
0x1B62,
0x1AFD,
0x1A9A,
0x1A38,
0x19D8,
0x1979,
0x191C,
0x18C0,
0x1865,
0x180B,
0x17B3,
0x175C,
0x1706,
0x16B2,
0x165E,
0x160C,
0x15BB,
0x156C,
0x151D,
0x14CF,
0x1483,
0x1438,
0x13EE,
0x13A4,
0x135C,
0x1315,
0x12CF,
0x128A,
0x1246,
0x1203,
0x11C1,
0x1180,
0x1140,
0x1100,
0x10C2,
0x1084,
0x1048,
0x100C,
0xFD1,
0xF97,
0xF5E,
0xF25,
0xEEE,
0xEB7,
0xE81,
0xE4C,
0xE17,
0xDE4,
0xDB1,
0xD7E,
0xD4D,
0xD1C,
0xCEC,
0xCBC,
0xC8E,
0xC60,
0xC32,
0xC05,
0xBD9,
0xBAE,
0xB83,
0xB59,
0xB2F,
0xB06,
0xADD,
0xAB6,
0xA8E,
0xA67,
0xA41,
0xA1C,
0x9F7,
0x9D2,
0x9AE,
0x98A,
0x967,
0x945,
0x923,
0x901,
0x8E0,
0x8C0,
0x8A0,
0x880,
0x861,
0x842,
0x824,
0x806,
0x7E8,
0x7CB,
0x7AF,
0x792,
0x777,
0x75B,
0x740,
0x726,
0x70B,
0x6F2,
0x6D8,
0x6BF,
0x6A6,
0x68E,
0x676,
0x65E,
0x647,
0x630,
0x619,
0x602,
0x5EC,
0x5D7,
0x5C1,
0x5AC,
0x597,
0x583,
0x56E,
0x55B,
0x547,
0x533,
0x520,
0x50E,
0x4FB,
0x4E9,
0x4D7,
0x4C5,
0x4B3,
0x4A2,
0x491,
0x480,
0x470,
0x460,
0x450,
0x440,
0x430,
0x421,
0x412,
0x403,
0x3F4,
0x3E5,
0x3D7,
0x3C9,
0x3BB,
0x3AD,
0x3A0,
0x393,
0x385,
0x379,
0x36C,
0x35F,
0x353,
0x347,
0x33B,
0x32F,
0x323,
0x318,
0x30C,
0x301,
0x2F6,
0x2EB,
0x2E0,
0x2D6,
0x2CB,
0x2C1,
0x2B7,
0x2AD,
0x2A3,
0x299,
0x290,
0x287,
0x27D,
0x274,
0x26B,
0x262,
0x259,
0x251,
0x248,
0x240,
0x238,
0x230,
0x228,
0x220,
0x218,
0x210,
0x209,
0x201,
0x1FA,
0x1F2,
0x1EB,
0x1E4,
0x1DD,
0x1D6,
0x1D0,
0x1C9,
0x1C2,
0x1BC,
0x1B6,
0x1AF,
0x1A9,
0x1A3,
0x19D,
0x197,
0x191,
0x18C,
0x186,
0x180,
0x17B,
0x175,
0x170,
0x16B,
0x165,
0x160,
0x15B,
0x156,
0x151,
0x14C,
0x148,
0x143,
0x13E,
0x13A,
0x135,
0x131,
0x12C,
0x128,
0x124,
0x120,
0x11C,
0x118,
0x114,
0x110,
0x10C,
0x108,
0x104,
0x100,
0xFD,
0xF9,
0xF5,
0xF2,
0xEE,
};


+ 15
- 0
quantum/audio/luts.h View File

@@ -0,0 +1,15 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#ifndef LUTS_H
#define LUTS_H

#define VIBRATO_LUT_LENGTH 20

#define FREQUENCY_LUT_LENGTH 349

extern const float vibrato_lut[VIBRATO_LUT_LENGTH];
extern const uint16_t frequency_lut[FREQUENCY_LUT_LENGTH];

#endif /* LUTS_H */

+ 217
- 0
quantum/audio/musical_notes.h View File

@@ -0,0 +1,217 @@
#ifndef MUSICAL_NOTES_H
#define MUSICAL_NOTES_H

// Tempo Placeholder
#define TEMPO_DEFAULT 100


#define SONG(notes...) { notes }


// Note Types
#define MUSICAL_NOTE(note, duration) {(NOTE##note), duration}
#define WHOLE_NOTE(note) MUSICAL_NOTE(note, 64)
#define HALF_NOTE(note) MUSICAL_NOTE(note, 32)
#define QUARTER_NOTE(note) MUSICAL_NOTE(note, 16)
#define EIGHTH_NOTE(note) MUSICAL_NOTE(note, 8)
#define SIXTEENTH_NOTE(note) MUSICAL_NOTE(note, 4)

#define WHOLE_DOT_NOTE(note) MUSICAL_NOTE(note, 64+32)
#define HALF_DOT_NOTE(note) MUSICAL_NOTE(note, 32+16)
#define QUARTER_DOT_NOTE(note) MUSICAL_NOTE(note, 16+8)
#define EIGHTH_DOT_NOTE(note) MUSICAL_NOTE(note, 8+4)
#define SIXTEENTH_DOT_NOTE(note) MUSICAL_NOTE(note, 4+2)

// Note Type Shortcuts
#define M__NOTE(note, duration) MUSICAL_NOTE(note, duration)
#define W__NOTE(n) WHOLE_NOTE(n)
#define H__NOTE(n) HALF_NOTE(n)
#define Q__NOTE(n) QUARTER_NOTE(n)
#define E__NOTE(n) EIGHTH_NOTE(n)
#define S__NOTE(n) SIXTEENTH_NOTE(n)
#define WD_NOTE(n) WHOLE_DOT_NOTE(n)
#define HD_NOTE(n) HALF_DOT_NOTE(n)
#define QD_NOTE(n) QUARTER_DOT_NOTE(n)
#define ED_NOTE(n) EIGHTH_DOT_NOTE(n)
#define SD_NOTE(n) SIXTEENTH_DOT_NOTE(n)

// Note Styles
// Staccato makes sure there is a rest between each note. Think: TA TA TA
// Legato makes notes flow together. Think: TAAA
#define STACCATO 0.01
#define LEGATO 0

// Note Timbre
// Changes how the notes sound
#define TIMBRE_12 0.125
#define TIMBRE_25 0.250
#define TIMBRE_50 0.500
#define TIMBRE_75 0.750
#define TIMBRE_DEFAULT TIMBRE_50


// Notes - # = Octave

#define NOTE_REST 0.00

/* These notes are currently bugged
#define NOTE_C0 16.35
#define NOTE_CS0 17.32
#define NOTE_D0 18.35
#define NOTE_DS0 19.45
#define NOTE_E0 20.60
#define NOTE_F0 21.83
#define NOTE_FS0 23.12
#define NOTE_G0 24.50
#define NOTE_GS0 25.96
#define NOTE_A0 27.50
#define NOTE_AS0 29.14
#define NOTE_B0 30.87
#define NOTE_C1 32.70
#define NOTE_CS1 34.65
#define NOTE_D1 36.71
#define NOTE_DS1 38.89
#define NOTE_E1 41.20
#define NOTE_F1 43.65
#define NOTE_FS1 46.25
#define NOTE_G1 49.00
#define NOTE_GS1 51.91
#define NOTE_A1 55.00
#define NOTE_AS1 58.27
*/

#define NOTE_B1 61.74
#define NOTE_C2 65.41
#define NOTE_CS2 69.30
#define NOTE_D2 73.42
#define NOTE_DS2 77.78
#define NOTE_E2 82.41
#define NOTE_F2 87.31
#define NOTE_FS2 92.50
#define NOTE_G2 98.00
#define NOTE_GS2 103.83
#define NOTE_A2 110.00
#define NOTE_AS2 116.54
#define NOTE_B2 123.47
#define NOTE_C3 130.81
#define NOTE_CS3 138.59
#define NOTE_D3 146.83
#define NOTE_DS3 155.56
#define NOTE_E3 164.81
#define NOTE_F3 174.61
#define NOTE_FS3 185.00
#define NOTE_G3 196.00
#define NOTE_GS3 207.65
#define NOTE_A3 220.00
#define NOTE_AS3 233.08
#define NOTE_B3 246.94
#define NOTE_C4 261.63
#define NOTE_CS4 277.18
#define NOTE_D4 293.66
#define NOTE_DS4 311.13
#define NOTE_E4 329.63
#define NOTE_F4 349.23
#define NOTE_FS4 369.99
#define NOTE_G4 392.00
#define NOTE_GS4 415.30
#define NOTE_A4 440.00
#define NOTE_AS4 466.16
#define NOTE_B4 493.88
#define NOTE_C5 523.25
#define NOTE_CS5 554.37
#define NOTE_D5 587.33
#define NOTE_DS5 622.25
#define NOTE_E5 659.26
#define NOTE_F5 698.46
#define NOTE_FS5 739.99
#define NOTE_G5 783.99
#define NOTE_GS5 830.61
#define NOTE_A5 880.00
#define NOTE_AS5 932.33
#define NOTE_B5 987.77
#define NOTE_C6 1046.50
#define NOTE_CS6 1108.73
#define NOTE_D6 1174.66
#define NOTE_DS6 1244.51
#define NOTE_E6 1318.51
#define NOTE_F6 1396.91
#define NOTE_FS6 1479.98
#define NOTE_G6 1567.98
#define NOTE_GS6 1661.22
#define NOTE_A6 1760.00
#define NOTE_AS6 1864.66
#define NOTE_B6 1975.53
#define NOTE_C7 2093.00
#define NOTE_CS7 2217.46
#define NOTE_D7 2349.32
#define NOTE_DS7 2489.02
#define NOTE_E7 2637.02
#define NOTE_F7 2793.83
#define NOTE_FS7 2959.96
#define NOTE_G7 3135.96
#define NOTE_GS7 3322.44
#define NOTE_A7 3520.00
#define NOTE_AS7 3729.31
#define NOTE_B7 3951.07
#define NOTE_C8 4186.01
#define NOTE_CS8 4434.92
#define NOTE_D8 4698.64
#define NOTE_DS8 4978.03
#define NOTE_E8 5274.04
#define NOTE_F8 5587.65
#define NOTE_FS8 5919.91
#define NOTE_G8 6271.93
#define NOTE_GS8 6644.88
#define NOTE_A8 7040.00
#define NOTE_AS8 7458.62
#define NOTE_B8 7902.13

// Flat Aliases
#define NOTE_DF0 NOTE_CS0
#define NOTE_EF0 NOTE_DS0
#define NOTE_GF0 NOTE_FS0
#define NOTE_AF0 NOTE_GS0
#define NOTE_BF0 NOTE_AS0
#define NOTE_DF1 NOTE_CS1
#define NOTE_EF1 NOTE_DS1
#define NOTE_GF1 NOTE_FS1
#define NOTE_AF1 NOTE_GS1
#define NOTE_BF1 NOTE_AS1
#define NOTE_DF2 NOTE_CS2
#define NOTE_EF2 NOTE_DS2
#define NOTE_GF2 NOTE_FS2
#define NOTE_AF2 NOTE_GS2
#define NOTE_BF2 NOTE_AS2
#define NOTE_DF3 NOTE_CS3
#define NOTE_EF3 NOTE_DS3
#define NOTE_GF3 NOTE_FS3
#define NOTE_AF3 NOTE_GS3
#define NOTE_BF3 NOTE_AS3
#define NOTE_DF4 NOTE_CS4
#define NOTE_EF4 NOTE_DS4
#define NOTE_GF4 NOTE_FS4
#define NOTE_AF4 NOTE_GS4
#define NOTE_BF4 NOTE_AS4
#define NOTE_DF5 NOTE_CS5
#define NOTE_EF5 NOTE_DS5
#define NOTE_GF5 NOTE_FS5
#define NOTE_AF5 NOTE_GS5
#define NOTE_BF5 NOTE_AS5
#define NOTE_DF6 NOTE_CS6
#define NOTE_EF6 NOTE_DS6
#define NOTE_GF6 NOTE_FS6
#define NOTE_AF6 NOTE_GS6
#define NOTE_BF6 NOTE_AS6
#define NOTE_DF7 NOTE_CS7
#define NOTE_EF7 NOTE_DS7
#define NOTE_GF7 NOTE_FS7
#define NOTE_AF7 NOTE_GS7
#define NOTE_BF7 NOTE_AS7
#define NOTE_DF8 NOTE_CS8
#define NOTE_EF8 NOTE_DS8
#define NOTE_GF8 NOTE_FS8
#define NOTE_AF8 NOTE_GS8
#define NOTE_BF8 NOTE_AS8


#endif

+ 117
- 0
quantum/audio/song_list.h View File

@@ -0,0 +1,117 @@
#include "musical_notes.h"

#ifndef SONG_LIST_H
#define SONG_LIST_H

#define ODE_TO_JOY \
Q__NOTE(_E4), Q__NOTE(_E4), Q__NOTE(_F4), Q__NOTE(_G4), \
Q__NOTE(_G4), Q__NOTE(_F4), Q__NOTE(_E4), Q__NOTE(_D4), \
Q__NOTE(_C4), Q__NOTE(_C4), Q__NOTE(_D4), Q__NOTE(_E4), \
QD_NOTE(_E4), E__NOTE(_D4), H__NOTE(_D4),

#define ROCK_A_BYE_BABY \
QD_NOTE(_B4), E__NOTE(_D4), Q__NOTE(_B5), \
H__NOTE(_A5), Q__NOTE(_G5), \
QD_NOTE(_B4), E__NOTE(_D5), Q__NOTE(_G5), \
H__NOTE(_FS5),

#define CLOSE_ENCOUNTERS_5_NOTE \
Q__NOTE(_D5), \
Q__NOTE(_E5), \
Q__NOTE(_C5), \
Q__NOTE(_C4), \
Q__NOTE(_G4),

#define DOE_A_DEER \
QD_NOTE(_C4), E__NOTE(_D4), \
QD_NOTE(_E4), E__NOTE(_C4), \
Q__NOTE(_E4), Q__NOTE(_C4), \
Q__NOTE(_E4),

#define GOODBYE_SOUND \
E__NOTE(_E7), \
E__NOTE(_A6), \
ED_NOTE(_E6),

#define STARTUP_SOUND \
ED_NOTE(_E7 ), \
E__NOTE(_CS7), \
E__NOTE(_E6 ), \
E__NOTE(_A6 ), \
M__NOTE(_CS7, 20),

#define QWERTY_SOUND \
E__NOTE(_GS6 ), \
E__NOTE(_A6 ), \
S__NOTE(_REST), \
Q__NOTE(_E7 ),

#define COLEMAK_SOUND \
E__NOTE(_GS6 ), \
E__NOTE(_A6 ), \
S__NOTE(_REST), \
ED_NOTE(_E7 ), \
S__NOTE(_REST), \
ED_NOTE(_GS7 ),

#define DVORAK_SOUND \
E__NOTE(_GS6 ), \
E__NOTE(_A6 ), \
S__NOTE(_REST), \
E__NOTE(_E7 ), \
S__NOTE(_REST), \
E__NOTE(_FS7 ), \
S__NOTE(_REST), \
E__NOTE(_E7 ),

#define PLOVER_SOUND \
E__NOTE(_GS6 ), \
E__NOTE(_A6 ), \
S__NOTE(_REST), \
ED_NOTE(_E7 ), \
S__NOTE(_REST), \
ED_NOTE(_A7 ),

#define PLOVER_GOODBYE_SOUND \
E__NOTE(_GS6 ), \
E__NOTE(_A6 ), \
S__NOTE(_REST), \
ED_NOTE(_A7 ), \
S__NOTE(_REST), \
ED_NOTE(_E7 ),

#define MUSIC_SCALE_SOUND \
E__NOTE(_A5 ), \
E__NOTE(_B5 ), \
E__NOTE(_CS6), \
E__NOTE(_D6 ), \
E__NOTE(_E6 ), \
E__NOTE(_FS6), \
E__NOTE(_GS6), \
E__NOTE(_A6 ),

#define CAPS_LOCK_ON_SOUND \
E__NOTE(_A3), \
E__NOTE(_B3),

#define CAPS_LOCK_OFF_SOUND \
E__NOTE(_B3), \
E__NOTE(_A3),

#define SCROLL_LOCK_ON_SOUND \
E__NOTE(_D4), \
E__NOTE(_E4),

#define SCROLL_LOCK_OFF_SOUND \
E__NOTE(_E4), \
E__NOTE(_D4),

#define NUM_LOCK_ON_SOUND \
E__NOTE(_D5), \
E__NOTE(_E5),

#define NUM_LOCK_OFF_SOUND \
E__NOTE(_E5), \
E__NOTE(_D5),

#endif

+ 165
- 0
quantum/audio/voices.c View File

@@ -0,0 +1,165 @@
#include "voices.h"
#include "audio.h"
#include "stdlib.h"

// these are imported from audio.c
extern uint16_t envelope_index;
extern float note_timbre;
extern float polyphony_rate;

voice_type voice = default_voice;

void set_voice(voice_type v) {
voice = v;
}

void voice_iterate() {
voice = (voice + 1) % number_of_voices;
}

void voice_deiterate() {
voice = (voice - 1) % number_of_voices;
}

float voice_envelope(float frequency) {
// envelope_index ranges from 0 to 0xFFFF, which is preserved at 880.0 Hz
uint16_t compensated_index = (uint16_t)((float)envelope_index * (880.0 / frequency));

switch (voice) {
case default_voice:
note_timbre = TIMBRE_50;
polyphony_rate = 0;
break;

case butts_fader:
polyphony_rate = 0;
switch (compensated_index) {
case 0 ... 9:
frequency = frequency / 4;
note_timbre = TIMBRE_12;
break;

case 10 ... 19:
frequency = frequency / 2;
note_timbre = TIMBRE_12;
break;

case 20 ... 200:
note_timbre = .125 - pow(((float)compensated_index - 20) / (200 - 20), 2)*.125;
break;

default:
note_timbre = 0;
break;
}
break;

// case octave_crunch:
// polyphony_rate = 0;
// switch (compensated_index) {
// case 0 ... 9:
// case 20 ... 24:
// case 30 ... 32:
// frequency = frequency / 2;
// note_timbre = TIMBRE_12;
// break;

// case 10 ... 19:
// case 25 ... 29:
// case 33 ... 35:
// frequency = frequency * 2;
// note_timbre = TIMBRE_12;
// break;

// default:
// note_timbre = TIMBRE_12;
// break;
// }
// break;

case duty_osc:
// This slows the loop down a substantial amount, so higher notes may freeze
polyphony_rate = 0;
switch (compensated_index) {
default:
#define OCS_SPEED 10
#define OCS_AMP .25
// sine wave is slow
// note_timbre = (sin((float)compensated_index/10000*OCS_SPEED) * OCS_AMP / 2) + .5;
// triangle wave is a bit faster
note_timbre = (float)abs((compensated_index*OCS_SPEED % 3000) - 1500) * ( OCS_AMP / 1500 ) + (1 - OCS_AMP) / 2;
break;
}
break;

case duty_octave_down:
polyphony_rate = 0;
note_timbre = (envelope_index % 2) * .125 + .375 * 2;
if ((envelope_index % 4) == 0)
note_timbre = 0.5;
if ((envelope_index % 8) == 0)
note_timbre = 0;
break;
case delayed_vibrato:
polyphony_rate = 0;
note_timbre = TIMBRE_50;
#define VOICE_VIBRATO_DELAY 150
#define VOICE_VIBRATO_SPEED 50
switch (compensated_index) {
case 0 ... VOICE_VIBRATO_DELAY:
break;
default:
frequency = frequency * vibrato_lut[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)];
break;
}
break;
// case delayed_vibrato_octave:
// polyphony_rate = 0;
// if ((envelope_index % 2) == 1) {
// note_timbre = 0.55;
// } else {
// note_timbre = 0.45;
// }
// #define VOICE_VIBRATO_DELAY 150
// #define VOICE_VIBRATO_SPEED 50
// switch (compensated_index) {
// case 0 ... VOICE_VIBRATO_DELAY:
// break;
// default:
// frequency = frequency * VIBRATO_LUT[(int)fmod((((float)compensated_index - (VOICE_VIBRATO_DELAY + 1))/1000*VOICE_VIBRATO_SPEED), VIBRATO_LUT_LENGTH)];
// break;
// }
// break;
// case duty_fifth_down:
// note_timbre = 0.5;
// if ((envelope_index % 3) == 0)
// note_timbre = 0.75;
// break;
// case duty_fourth_down:
// note_timbre = 0.0;
// if ((envelope_index % 12) == 0)
// note_timbre = 0.75;
// if (((envelope_index % 12) % 4) != 1)
// note_timbre = 0.75;
// break;
// case duty_third_down:
// note_timbre = 0.5;
// if ((envelope_index % 5) == 0)
// note_timbre = 0.75;
// break;
// case duty_fifth_third_down:
// note_timbre = 0.5;
// if ((envelope_index % 5) == 0)
// note_timbre = 0.75;
// if ((envelope_index % 3) == 0)
// note_timbre = 0.25;
// break;

default:
break;
}

return frequency;
}



+ 31
- 0
quantum/audio/voices.h View File

@@ -0,0 +1,31 @@
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
#include "luts.h"

#ifndef VOICES_H
#define VOICES_H

float voice_envelope(float frequency);

typedef enum {
default_voice,
butts_fader,
octave_crunch,
duty_osc,
duty_octave_down,
delayed_vibrato,
// delayed_vibrato_octave,
// duty_fifth_down,
// duty_fourth_down,
// duty_third_down,
// duty_fifth_third_down,
number_of_voices // important that this is last
} voice_type;

void set_voice(voice_type v);
void voice_iterate(void);
void voice_deiterate(void);

#endif

+ 265
- 0
quantum/audio/wave.h View File

@@ -0,0 +1,265 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>

#define SINE_LENGTH 2048

const uint8_t sinewave[] PROGMEM= //2048 values
{
0x80,0x80,0x80,0x81,0x81,0x81,0x82,0x82,
0x83,0x83,0x83,0x84,0x84,0x85,0x85,0x85,
0x86,0x86,0x87,0x87,0x87,0x88,0x88,0x88,
0x89,0x89,0x8a,0x8a,0x8a,0x8b,0x8b,0x8c,
0x8c,0x8c,0x8d,0x8d,0x8e,0x8e,0x8e,0x8f,
0x8f,0x8f,0x90,0x90,0x91,0x91,0x91,0x92,
0x92,0x93,0x93,0x93,0x94,0x94,0x95,0x95,
0x95,0x96,0x96,0x96,0x97,0x97,0x98,0x98,
0x98,0x99,0x99,0x9a,0x9a,0x9a,0x9b,0x9b,
0x9b,0x9c,0x9c,0x9d,0x9d,0x9d,0x9e,0x9e,
0x9e,0x9f,0x9f,0xa0,0xa0,0xa0,0xa1,0xa1,
0xa2,0xa2,0xa2,0xa3,0xa3,0xa3,0xa4,0xa4,
0xa5,0xa5,0xa5,0xa6,0xa6,0xa6,0xa7,0xa7,
0xa7,0xa8,0xa8,0xa9,0xa9,0xa9,0xaa,0xaa,
0xaa,0xab,0xab,0xac,0xac,0xac,0xad,0xad,
0xad,0xae,0xae,0xae,0xaf,0xaf,0xb0,0xb0,
0xb0,0xb1,0xb1,0xb1,0xb2,0xb2,0xb2,0xb3,
0xb3,0xb4,0xb4,0xb4,0xb5,0xb5,0xb5,0xb6,
0xb6,0xb6,0xb7,0xb7,0xb7,0xb8,0xb8,0xb8,
0xb9,0xb9,0xba,0xba,0xba,0xbb,0xbb,0xbb,
0xbc,0xbc,0xbc,0xbd,0xbd,0xbd,0xbe,0xbe,
0xbe,0xbf,0xbf,0xbf,0xc0,0xc0,0xc0,0xc1,
0xc1,0xc1,0xc2,0xc2,0xc2,0xc3,0xc3,0xc3,
0xc4,0xc4,0xc4,0xc5,0xc5,0xc5,0xc6,0xc6,
0xc6,0xc7,0xc7,0xc7,0xc8,0xc8,0xc8,0xc9,
0xc9,0xc9,0xca,0xca,0xca,0xcb,0xcb,0xcb,
0xcb,0xcc,0xcc,0xcc,0xcd,0xcd,0xcd,0xce,
0xce,0xce,0xcf,0xcf,0xcf,0xcf,0xd0,0xd0,
0xd0,0xd1,0xd1,0xd1,0xd2,0xd2,0xd2,0xd2,
0xd3,0xd3,0xd3,0xd4,0xd4,0xd4,0xd5,0xd5,
0xd5,0xd5,0xd6,0xd6,0xd6,0xd7,0xd7,0xd7,
0xd7,0xd8,0xd8,0xd8,0xd9,0xd9,0xd9,0xd9,
0xda,0xda,0xda,0xda,0xdb,0xdb,0xdb,0xdc,
0xdc,0xdc,0xdc,0xdd,0xdd,0xdd,0xdd,0xde,
0xde,0xde,0xde,0xdf,0xdf,0xdf,0xe0,0xe0,
0xe0,0xe0,0xe1,0xe1,0xe1,0xe1,0xe2,0xe2,
0xe2,0xe2,0xe3,0xe3,0xe3,0xe3,0xe4,0xe4,
0xe4,0xe4,0xe4,0xe5,0xe5,0xe5,0xe5,0xe6,
0xe6,0xe6,0xe6,0xe7,0xe7,0xe7,0xe7,0xe8,
0xe8,0xe8,0xe8,0xe8,0xe9,0xe9,0xe9,0xe9,
0xea,0xea,0xea,0xea,0xea,0xeb,0xeb,0xeb,
0xeb,0xeb,0xec,0xec,0xec,0xec,0xec,0xed,
0xed,0xed,0xed,0xed,0xee,0xee,0xee,0xee,
0xee,0xef,0xef,0xef,0xef,0xef,0xf0,0xf0,
0xf0,0xf0,0xf0,0xf0,0xf1,0xf1,0xf1,0xf1,
0xf1,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,0xf3,
0xf3,0xf3,0xf3,0xf3,0xf3,0xf4,0xf4,0xf4,
0xf4,0xf4,0xf4,0xf5,0xf5,0xf5,0xf5,0xf5,
0xf5,0xf5,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,
0xf6,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,
0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,
0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,
0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,
0xfa,0xfa,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,
0xfb,0xfb,0xfb,0xfb,0xfc,0xfc,0xfc,0xfc,
0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,
0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfe,0xfe,
0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
0xfe,0xfe,0xfe,0xfe,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfe,
0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,
0xfe,0xfe,0xfe,0xfd,0xfd,0xfd,0xfd,0xfd,
0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,0xfd,
0xfd,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,
0xfc,0xfc,0xfc,0xfc,0xfc,0xfb,0xfb,0xfb,
0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfb,0xfa,
0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,0xfa,
0xfa,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,0xf9,
0xf9,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,
0xf8,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,
0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf6,0xf5,
0xf5,0xf5,0xf5,0xf5,0xf5,0xf5,0xf4,0xf4,
0xf4,0xf4,0xf4,0xf4,0xf3,0xf3,0xf3,0xf3,
0xf3,0xf3,0xf2,0xf2,0xf2,0xf2,0xf2,0xf2,
0xf1,0xf1,0xf1,0xf1,0xf1,0xf0,0xf0,0xf0,
0xf0,0xf0,0xf0,0xef,0xef,0xef,0xef,0xef,
0xee,0xee,0xee,0xee,0xee,0xed,0xed,0xed,
0xed,0xed,0xec,0xec,0xec,0xec,0xec,0xeb,
0xeb,0xeb,0xeb,0xeb,0xea,0xea,0xea,0xea,
0xea,0xe9,0xe9,0xe9,0xe9,0xe8,0xe8,0xe8,
0xe8,0xe8,0xe7,0xe7,0xe7,0xe7,0xe6,0xe6,
0xe6,0xe6,0xe5,0xe5,0xe5,0xe5,0xe4,0xe4,
0xe4,0xe4,0xe4,0xe3,0xe3,0xe3,0xe3,0xe2,
0xe2,0xe2,0xe2,0xe1,0xe1,0xe1,0xe1,0xe0,
0xe0,0xe0,0xe0,0xdf,0xdf,0xdf,0xde,0xde,
0xde,0xde,0xdd,0xdd,0xdd,0xdd,0xdc,0xdc,
0xdc,0xdc,0xdb,0xdb,0xdb,0xda,0xda,0xda,
0xda,0xd9,0xd9,0xd9,0xd9,0xd8,0xd8,0xd8,
0xd7,0xd7,0xd7,0xd7,0xd6,0xd6,0xd6,0xd5,
0xd5,0xd5,0xd5,0xd4,0xd4,0xd4,0xd3,0xd3,
0xd3,0xd2,0xd2,0xd2,0xd2,0xd1,0xd1,0xd1,
0xd0,0xd0,0xd0,0xcf,0xcf,0xcf,0xcf,0xce,
0xce,0xce,0xcd,0xcd,0xcd,0xcc,0xcc,0xcc,
0xcb,0xcb,0xcb,0xcb,0xca,0xca,0xca,0xc9,
0xc9,0xc9,0xc8,0xc8,0xc8,0xc7,0xc7,0xc7,
0xc6,0xc6,0xc6,0xc5,0xc5,0xc5,0xc4,0xc4,
0xc4,0xc3,0xc3,0xc3,0xc2,0xc2,0xc2,0xc1,
0xc1,0xc1,0xc0,0xc0,0xc0,0xbf,0xbf,0xbf,
0xbe,0xbe,0xbe,0xbd,0xbd,0xbd,0xbc,0xbc,
0xbc,0xbb,0xbb,0xbb,0xba,0xba,0xba,0xb9,
0xb9,0xb8,0xb8,0xb8,0xb7,0xb7,0xb7,0xb6,
0xb6,0xb6,0xb5,0xb5,0xb5,0xb4,0xb4,0xb4,
0xb3,0xb3,0xb2,0xb2,0xb2,0xb1,0xb1,0xb1,
0xb0,0xb0,0xb0,0xaf,0xaf,0xae,0xae,0xae,
0xad,0xad,0xad,0xac,0xac,0xac,0xab,0xab,
0xaa,0xaa,0xaa,0xa9,0xa9,0xa9,0xa8,0xa8,
0xa7,0xa7,0xa7,0xa6,0xa6,0xa6,0xa5,0xa5,
0xa5,0xa4,0xa4,0xa3,0xa3,0xa3,0xa2,0xa2,
0xa2,0xa1,0xa1,0xa0,0xa0,0xa0,0x9f,0x9f,
0x9e,0x9e,0x9e,0x9d,0x9d,0x9d,0x9c,0x9c,
0x9b,0x9b,0x9b,0x9a,0x9a,0x9a,0x99,0x99,
0x98,0x98,0x98,0x97,0x97,0x96,0x96,0x96,
0x95,0x95,0x95,0x94,0x94,0x93,0x93,0x93,
0x92,0x92,0x91,0x91,0x91,0x90,0x90,0x8f,
0x8f,0x8f,0x8e,0x8e,0x8e,0x8d,0x8d,0x8c,
0x8c,0x8c,0x8b,0x8b,0x8a,0x8a,0x8a,0x89,
0x89,0x88,0x88,0x88,0x87,0x87,0x87,0x86,
0x86,0x85,0x85,0x85,0x84,0x84,0x83,0x83,
0x83,0x82,0x82,0x81,0x81,0x81,0x80,0x80,
0x80,0x7f,0x7f,0x7e,0x7e,0x7e,0x7d,0x7d,
0x7c,0x7c,0x7c,0x7b,0x7b,0x7a,0x7a,0x7a,
0x79,0x79,0x78,0x78,0x78,0x77,0x77,0x77,
0x76,0x76,0x75,0x75,0x75,0x74,0x74,0x73,
0x73,0x73,0x72,0x72,0x71,0x71,0x71,0x70,
0x70,0x70,0x6f,0x6f,0x6e,0x6e,0x6e,0x6d,
0x6d,0x6c,0x6c,0x6c,0x6b,0x6b,0x6a,0x6a,
0x6a,0x69,0x69,0x69,0x68,0x68,0x67,0x67,
0x67,0x66,0x66,0x65,0x65,0x65,0x64,0x64,
0x64,0x63,0x63,0x62,0x62,0x62,0x61,0x61,
0x61,0x60,0x60,0x5f,0x5f,0x5f,0x5e,0x5e,
0x5d,0x5d,0x5d,0x5c,0x5c,0x5c,0x5b,0x5b,
0x5a,0x5a,0x5a,0x59,0x59,0x59,0x58,0x58,
0x58,0x57,0x57,0x56,0x56,0x56,0x55,0x55,
0x55,0x54,0x54,0x53,0x53,0x53,0x52,0x52,
0x52,0x51,0x51,0x51,0x50,0x50,0x4f,0x4f,
0x4f,0x4e,0x4e,0x4e,0x4d,0x4d,0x4d,0x4c,
0x4c,0x4b,0x4b,0x4b,0x4a,0x4a,0x4a,0x49,
0x49,0x49,0x48,0x48,0x48,0x47,0x47,0x47,
0x46,0x46,0x45,0x45,0x45,0x44,0x44,0x44,
0x43,0x43,0x43,0x42,0x42,0x42,0x41,0x41,
0x41,0x40,0x40,0x40,0x3f,0x3f,0x3f,0x3e,
0x3e,0x3e,0x3d,0x3d,0x3d,0x3c,0x3c,0x3c,
0x3b,0x3b,0x3b,0x3a,0x3a,0x3a,0x39,0x39,
0x39,0x38,0x38,0x38,0x37,0x37,0x37,0x36,
0x36,0x36,0x35,0x35,0x35,0x34,0x34,0x34,
0x34,0x33,0x33,0x33,0x32,0x32,0x32,0x31,
0x31,0x31,0x30,0x30,0x30,0x30,0x2f,0x2f,
0x2f,0x2e,0x2e,0x2e,0x2d,0x2d,0x2d,0x2d,
0x2c,0x2c,0x2c,0x2b,0x2b,0x2b,0x2a,0x2a,
0x2a,0x2a,0x29,0x29,0x29,0x28,0x28,0x28,
0x28,0x27,0x27,0x27,0x26,0x26,0x26,0x26,
0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x23,
0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x21,
0x21,0x21,0x21,0x20,0x20,0x20,0x1f,0x1f,
0x1f,0x1f,0x1e,0x1e,0x1e,0x1e,0x1d,0x1d,
0x1d,0x1d,0x1c,0x1c,0x1c,0x1c,0x1b,0x1b,
0x1b,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x19,
0x19,0x19,0x19,0x18,0x18,0x18,0x18,0x17,
0x17,0x17,0x17,0x17,0x16,0x16,0x16,0x16,
0x15,0x15,0x15,0x15,0x15,0x14,0x14,0x14,
0x14,0x14,0x13,0x13,0x13,0x13,0x13,0x12,
0x12,0x12,0x12,0x12,0x11,0x11,0x11,0x11,
0x11,0x10,0x10,0x10,0x10,0x10,0xf,0xf,
0xf,0xf,0xf,0xf,0xe,0xe,0xe,0xe,
0xe,0xd,0xd,0xd,0xd,0xd,0xd,0xc,
0xc,0xc,0xc,0xc,0xc,0xb,0xb,0xb,
0xb,0xb,0xb,0xa,0xa,0xa,0xa,0xa,
0xa,0xa,0x9,0x9,0x9,0x9,0x9,0x9,
0x9,0x8,0x8,0x8,0x8,0x8,0x8,0x8,
0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,
0x6,0x6,0x6,0x6,0x6,0x6,0x6,0x6,
0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,
0x5,0x5,0x4,0x4,0x4,0x4,0x4,0x4,
0x4,0x4,0x4,0x4,0x3,0x3,0x3,0x3,
0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,
0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,
0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x1,
0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,
0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,
0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x2,
0x2,0x3,0x3,0x3,0x3,0x3,0x3,0x3,
0x3,0x3,0x3,0x3,0x3,0x4,0x4,0x4,
0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x5,
0x5,0x5,0x5,0x5,0x5,0x5,0x5,0x5,
0x5,0x6,0x6,0x6,0x6,0x6,0x6,0x6,
0x6,0x7,0x7,0x7,0x7,0x7,0x7,0x7,
0x7,0x8,0x8,0x8,0x8,0x8,0x8,0x8,
0x9,0x9,0x9,0x9,0x9,0x9,0x9,0xa,
0xa,0xa,0xa,0xa,0xa,0xa,0xb,0xb,
0xb,0xb,0xb,0xb,0xc,0xc,0xc,0xc,
0xc,0xc,0xd,0xd,0xd,0xd,0xd,0xd,
0xe,0xe,0xe,0xe,0xe,0xf,0xf,0xf,
0xf,0xf,0xf,0x10,0x10,0x10,0x10,0x10,
0x11,0x11,0x11,0x11,0x11,0x12,0x12,0x12,
0x12,0x12,0x13,0x13,0x13,0x13,0x13,0x14,
0x14,0x14,0x14,0x14,0x15,0x15,0x15,0x15,
0x15,0x16,0x16,0x16,0x16,0x17,0x17,0x17,
0x17,0x17,0x18,0x18,0x18,0x18,0x19,0x19,
0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,
0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1d,
0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1e,0x1f,
0x1f,0x1f,0x1f,0x20,0x20,0x20,0x21,0x21,
0x21,0x21,0x22,0x22,0x22,0x22,0x23,0x23,
0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,
0x25,0x26,0x26,0x26,0x26,0x27,0x27,0x27,
0x28,0x28,0x28,0x28,0x29,0x29,0x29,0x2a,
0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,
0x2c,0x2d,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,
0x2f,0x2f,0x2f,0x30,0x30,0x30,0x30,0x31,
0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,
0x34,0x34,0x34,0x34,0x35,0x35,0x35,0x36,
0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,
0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,
0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,
0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,
0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,
0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,
0x46,0x47,0x47,0x47,0x48,0x48,0x48,0x49,
0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,
0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,
0x4f,0x4f,0x4f,0x50,0x50,0x51,0x51,0x51,
0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,
0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,
0x58,0x58,0x58,0x59,0x59,0x59,0x5a,0x5a,
0x5a,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,
0x5d,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,
0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,
0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,
0x67,0x67,0x67,0x68,0x68,0x69,0x69,0x69,
0x6a,0x6a,0x6a,0x6b,0x6b,0x6c,0x6c,0x6c,
0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x70,
0x70,0x70,0x71,0x71,0x71,0x72,0x72,0x73,
0x73,0x73,0x74,0x74,0x75,0x75,0x75,0x76,
0x76,0x77,0x77,0x77,0x78,0x78,0x78,0x79,
0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7c,0x7c,
0x7c,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f
};

+ 119
- 0
quantum/config_common.h View File

@@ -0,0 +1,119 @@
#ifndef CONFIG_DEFINITIONS_H
#define CONFIG_DEFINITIONS_H

/* diode directions */
#define COL2ROW 0
#define ROW2COL 1
/* I/O pins */
#define B0 { .input_addr = 3, .bit = 0 }
#define B1 { .input_addr = 3, .bit = 1 }
#define B2 { .input_addr = 3, .bit = 2 }
#define B3 { .input_addr = 3, .bit = 3 }
#define B4 { .input_addr = 3, .bit = 4 }
#define B5 { .input_addr = 3, .bit = 5 }
#define B6 { .input_addr = 3, .bit = 6 }
#define B7 { .input_addr = 3, .bit = 7 }
#define C0 { .input_addr = 6, .bit = 0 }
#define C1 { .input_addr = 6, .bit = 1 }
#define C2 { .input_addr = 6, .bit = 2 }
#define C3 { .input_addr = 6, .bit = 3 }
#define C4 { .input_addr = 6, .bit = 4 }
#define C5 { .input_addr = 6, .bit = 5 }
#define C6 { .input_addr = 6, .bit = 6 }
#define C7 { .input_addr = 6, .bit = 7 }
#define D0 { .input_addr = 9, .bit = 0 }
#define D1 { .input_addr = 9, .bit = 1 }
#define D2 { .input_addr = 9, .bit = 2 }
#define D3 { .input_addr = 9, .bit = 3 }
#define D4 { .input_addr = 9, .bit = 4 }
#define D5 { .input_addr = 9, .bit = 5 }
#define D6 { .input_addr = 9, .bit = 6 }
#define D7 { .input_addr = 9, .bit = 7 }
#define E0 { .input_addr = 0xC, .bit = 0 }
#define E1 { .input_addr = 0xC, .bit = 1 }
#define E2 { .input_addr = 0xC, .bit = 2 }
#define E3 { .input_addr = 0xC, .bit = 3 }
#define E4 { .input_addr = 0xC, .bit = 4 }
#define E5 { .input_addr = 0xC, .bit = 5 }
#define E6 { .input_addr = 0xC, .bit = 6 }
#define E7 { .input_addr = 0xC, .bit = 7 }
#define F0 { .input_addr = 0xF, .bit = 0 }
#define F1 { .input_addr = 0xF, .bit = 1 }
#define F2 { .input_addr = 0xF, .bit = 2 }
#define F3 { .input_addr = 0xF, .bit = 3 }
#define F4 { .input_addr = 0xF, .bit = 4 }
#define F5 { .input_addr = 0xF, .bit = 5 }
#define F6 { .input_addr = 0xF, .bit = 6 }
#define F7 { .input_addr = 0xF, .bit = 7 }

/* USART configuration */
#ifdef BLUETOOTH_ENABLE
# ifdef __AVR_ATmega32U4__
# define SERIAL_UART_BAUD 9600
# define SERIAL_UART_DATA UDR1
# define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1)
# define SERIAL_UART_RXD_VECT USART1_RX_vect
# define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1))
# define SERIAL_UART_INIT() do { \
/* baud rate */ \
UBRR1L = SERIAL_UART_UBRR; \
/* baud rate */ \
UBRR1H = SERIAL_UART_UBRR >> 8; \
/* enable TX */ \
UCSR1B = _BV(TXEN1); \
/* 8-bit data */ \
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); \
sei(); \
} while(0)
# else
# error "USART configuration is needed."
#endif

// I'm fairly sure these aren't needed, but oh well - Jack

/*
* PS/2 Interrupt configuration
*/
#ifdef PS2_USE_INT
/* uses INT1 for clock line(ATMega32U4) */
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 1

#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0

#define PS2_INT_INIT() do { \
EICRA |= ((1<<ISC11) | \
(0<<ISC10)); \
} while (0)
#define PS2_INT_ON() do { \
EIMSK |= (1<<INT1); \
} while (0)
#define PS2_INT_OFF() do { \
EIMSK &= ~(1<<INT1); \
} while (0)
#define PS2_INT_VECT INT1_vect
#endif

/*
* PS/2 Busywait configuration
*/
#ifdef PS2_USE_BUSYWAIT
#define PS2_CLOCK_PORT PORTD
#define PS2_CLOCK_PIN PIND
#define PS2_CLOCK_DDR DDRD
#define PS2_CLOCK_BIT 1

#define PS2_DATA_PORT PORTD
#define PS2_DATA_PIN PIND
#define PS2_DATA_DDR DDRD
#define PS2_DATA_BIT 0
#endif

#endif

#endif

+ 323
- 0
quantum/keymap_common.c View File

@@ -0,0 +1,323 @@
/*
Copyright 2012,2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 "keymap_common.h"
#include "report.h"
#include "keycode.h"
#include "action_layer.h"
#include <util/delay.h>
#include "action.h"
#include "action_macro.h"
#include "debug.h"
#include "backlight.h"
#include "bootloader.h"
#include "eeconfig.h"
#include "quantum.h"

#ifdef MIDI_ENABLE
#include "keymap_midi.h"
#endif

extern keymap_config_t keymap_config;

#include <stdio.h>
#include <inttypes.h>
#ifdef AUDIO_ENABLE
#include "audio.h"
#endif /* AUDIO_ENABLE */

static action_t keycode_to_action(uint16_t keycode);

/* converts key to action */
action_t action_for_key(uint8_t layer, keypos_t key)
{
// 16bit keycodes - important
uint16_t keycode = keymap_key_to_keycode(layer, key);

switch (keycode) {
case KC_FN0 ... KC_FN31:
return keymap_fn_to_action(keycode);
case KC_CAPSLOCK:
case KC_LOCKING_CAPS:
if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
return keycode_to_action(KC_LCTL);
}
return keycode_to_action(keycode);
case KC_LCTL:
if (keymap_config.swap_control_capslock) {
return keycode_to_action(KC_CAPSLOCK);
}
return keycode_to_action(KC_LCTL);
case KC_LALT:
if (keymap_config.swap_lalt_lgui) {
if (keymap_config.no_gui) {
return keycode_to_action(ACTION_NO);
}
return keycode_to_action(KC_LGUI);
}
return keycode_to_action(KC_LALT);
case KC_LGUI:
if (keymap_config.swap_lalt_lgui) {
return keycode_to_action(KC_LALT);
}
if (keymap_config.no_gui) {
return keycode_to_action(ACTION_NO);
}
return keycode_to_action(KC_LGUI);
case KC_RALT:
if (keymap_config.swap_ralt_rgui) {
if (keymap_config.no_gui) {
return keycode_to_action(ACTION_NO);
}
return keycode_to_action(KC_RGUI);
}
return keycode_to_action(KC_RALT);
case KC_RGUI:
if (keymap_config.swap_ralt_rgui) {
return keycode_to_action(KC_RALT);
}
if (keymap_config.no_gui) {
return keycode_to_action(ACTION_NO);
}
return keycode_to_action(KC_RGUI);
case KC_GRAVE:
if (keymap_config.swap_grave_esc) {
return keycode_to_action(KC_ESC);
}
return keycode_to_action(KC_GRAVE);
case KC_ESC:
if (keymap_config.swap_grave_esc) {
return keycode_to_action(KC_GRAVE);
}
return keycode_to_action(KC_ESC);
case KC_BSLASH:
if (keymap_config.swap_backslash_backspace) {
return keycode_to_action(KC_BSPACE);
}
return keycode_to_action(KC_BSLASH);
case KC_BSPACE:
if (keymap_config.swap_backslash_backspace) {
return keycode_to_action(KC_BSLASH);
}
return keycode_to_action(KC_BSPACE);
default:
return keycode_to_action(keycode);
}
}


/* Macro */
__attribute__ ((weak))
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
return MACRO_NONE;
}

/* Function */
__attribute__ ((weak))
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
}

/* translates keycode to action */
static action_t keycode_to_action(uint16_t keycode)
{
action_t action;
switch (keycode) {
case KC_A ... KC_EXSEL:
case KC_LCTRL ... KC_RGUI:
action.code = ACTION_KEY(keycode);
break;
case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
break;
case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
break;
case KC_MS_UP ... KC_MS_ACCEL2:
action.code = ACTION_MOUSEKEY(keycode);
break;
case KC_TRNS:
action.code = ACTION_TRANSPARENT;
break;
case LCTL(0) ... 0x1FFF: ;
// Has a modifier
// Split it up
action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
break;
case FUNC(0) ... FUNC(0xFFF): ;
// Is a shortcut for function layer, pull last 12bits
// This means we have 4,096 FN macros at our disposal
return keymap_func_to_action(keycode & 0xFFF);
break;
case M(0) ... M(0xFF):
action.code = ACTION_MACRO(keycode & 0xFF);
break;
case LT(0, 0) ... LT(0xFF, 0xF):
action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
break;
#ifdef BACKLIGHT_ENABLE
case BL_0 ... BL_15:
action.code = ACTION_BACKLIGHT_LEVEL(keycode & 0x000F);
break;
case BL_DEC:
action.code = ACTION_BACKLIGHT_DECREASE();
break;
case BL_INC:
action.code = ACTION_BACKLIGHT_INCREASE();
break;
case BL_TOGG:
action.code = ACTION_BACKLIGHT_TOGGLE();
break;
case BL_STEP:
action.code = ACTION_BACKLIGHT_STEP();
break;
#endif
case RESET: ; // RESET is 0x5000, which is why this is here
clear_keyboard();
#ifdef AUDIO_ENABLE
stop_all_notes();
shutdown_user();
#endif
_delay_ms(250);
#ifdef ATREUS_ASTAR
*(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
#endif
bootloader_jump();
break;
case DEBUG: ; // DEBUG is 0x5001
print("\nDEBUG: enabled.\n");
debug_enable = true;
break;
case MAGIC_SWAP_CONTROL_CAPSLOCK ... MAGIC_UNSWAP_ALT_GUI:
// MAGIC actions (BOOTMAGIC without the boot)
if (!eeconfig_is_enabled()) {
eeconfig_init();
}
/* keymap config */
keymap_config.raw = eeconfig_read_keymap();
if (keycode == MAGIC_SWAP_CONTROL_CAPSLOCK) {
keymap_config.swap_control_capslock = 1;
} else if (keycode == MAGIC_CAPSLOCK_TO_CONTROL) {
keymap_config.capslock_to_control = 1;
} else if (keycode == MAGIC_SWAP_LALT_LGUI) {
keymap_config.swap_lalt_lgui = 1;
} else if (keycode == MAGIC_SWAP_RALT_RGUI) {
keymap_config.swap_ralt_rgui = 1;
} else if (keycode == MAGIC_NO_GUI) {
keymap_config.no_gui = 1;
} else if (keycode == MAGIC_SWAP_GRAVE_ESC) {
keymap_config.swap_grave_esc = 1;
} else if (keycode == MAGIC_SWAP_BACKSLASH_BACKSPACE) {
keymap_config.swap_backslash_backspace = 1;
} else if (keycode == MAGIC_HOST_NKRO) {
keymap_config.nkro = 1;
} else if (keycode == MAGIC_SWAP_ALT_GUI) {
keymap_config.swap_lalt_lgui = 1;
keymap_config.swap_ralt_rgui = 1;
}
/* UNs */
else if (keycode == MAGIC_UNSWAP_CONTROL_CAPSLOCK) {
keymap_config.swap_control_capslock = 0;
} else if (keycode == MAGIC_UNCAPSLOCK_TO_CONTROL) {
keymap_config.capslock_to_control = 0;
} else if (keycode == MAGIC_UNSWAP_LALT_LGUI) {
keymap_config.swap_lalt_lgui = 0;
} else if (keycode == MAGIC_UNSWAP_RALT_RGUI) {
keymap_config.swap_ralt_rgui = 0;
} else if (keycode == MAGIC_UNNO_GUI) {
keymap_config.no_gui = 0;
} else if (keycode == MAGIC_UNSWAP_GRAVE_ESC) {
keymap_config.swap_grave_esc = 0;
} else if (keycode == MAGIC_UNSWAP_BACKSLASH_BACKSPACE) {
keymap_config.swap_backslash_backspace = 0;
} else if (keycode == MAGIC_UNHOST_NKRO) {
keymap_config.nkro = 0;
} else if (keycode == MAGIC_UNSWAP_ALT_GUI) {
keymap_config.swap_lalt_lgui = 0;
keymap_config.swap_ralt_rgui = 0;
}
eeconfig_update_keymap(keymap_config.raw);
break;
case TO(0, 1) ... OSM(0xFF): ;
// Layer movement shortcuts
// See .h to see constraints/usage
int type = (keycode >> 0x8) & 0xF;
if (type == 0x1) {
// Layer set "GOTO"
int when = (keycode >> 0x4) & 0x3;
int layer = keycode & 0xF;
action.code = ACTION_LAYER_SET(layer, when);
} else if (type == 0x2) {
// Momentary layer
int layer = keycode & 0xFF;
action.code = ACTION_LAYER_MOMENTARY(layer);
} else if (type == 0x3) {
// Set default layer
int layer = keycode & 0xFF;
action.code = ACTION_DEFAULT_LAYER_SET(layer);
} else if (type == 0x4) {
// Set default layer
int layer = keycode & 0xFF;
action.code = ACTION_LAYER_TOGGLE(layer);
} else if (type == 0x5) {
// OSL(layer) - One-shot layer
int layer = keycode & 0xFF;
action.code = ACTION_LAYER_ONESHOT(layer);
} else if (type == 0x6) {
// OSM(mod) - One-shot mod
int mod = keycode & 0xFF;
action.code = ACTION_MODS_ONESHOT(mod);
}
break;
case MT(0, 0) ... MT(0xF, 0xFF):
action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
break;
default:
action.code = ACTION_NO;
break;
}
return action;
}


/* translates key to keycode */
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
{
// Read entire word (16bits)
return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
}

/* translates Fn keycode to action */
action_t keymap_fn_to_action(uint16_t keycode)
{
return (action_t){ .code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]) };
}

action_t keymap_func_to_action(uint16_t keycode)
{
// For FUNC without 8bit limit
return (action_t){ .code = pgm_read_word(&fn_actions[(int)keycode]) };
}

void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
layer_on(layer3);
} else {
layer_off(layer3);
}
}

+ 292
- 0
quantum/keymap_common.h View File

@@ -0,0 +1,292 @@
/*
Copyright 2012,2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/

#ifndef KEYMAP_H
#define KEYMAP_H

#include <stdint.h>
#include <stdbool.h>
#include "action.h"
#include <avr/pgmspace.h>
#include "keycode.h"
#include "keymap.h"
#include "action_macro.h"
#include "report.h"
#include "host.h"
// #include "print.h"
#include "debug.h"

/* NOTE: Not portable. Bit field order depends on implementation */
typedef union {
uint16_t raw;
struct {
bool swap_control_capslock:1;
bool capslock_to_control:1;
bool swap_lalt_lgui:1;
bool swap_ralt_rgui:1;
bool no_gui:1;
bool swap_grave_esc:1;
bool swap_backslash_backspace:1;
bool nkro:1;
};
} keymap_config_t;


/* translates key to keycode */
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);

/* translates Fn keycode to action */
action_t keymap_fn_to_action(uint16_t keycode);

/* translates Fn keycode to action */
action_t keymap_func_to_action(uint16_t keycode);

extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
extern const uint16_t fn_actions[];

// Ability to use mods in layouts
#define LCTL(kc) kc | 0x0100
#define LSFT(kc) kc | 0x0200
#define LALT(kc) kc | 0x0400
#define LGUI(kc) kc | 0x0800
#define HYPR(kc) kc | 0x0F00
#define MEH(kc) kc | 0x0700
#define LCAG(kc) kc | 0x0D00 // Modifier Ctrl Alt and GUI

#define MOD_HYPR 0xf
#define MOD_MEH 0x7

#define RCTL(kc) kc | 0x1100
#define RSFT(kc) kc | 0x1200
#define RALT(kc) kc | 0x1400
#define RGUI(kc) kc | 0x1800

// Aliases for shifted symbols
// Each key has a 4-letter code, and some have longer aliases too.
// While the long aliases are descriptive, the 4-letter codes
// make for nicer grid layouts (everything lines up), and are
// the preferred style for Quantum.
#define KC_TILD LSFT(KC_GRV) // ~
#define KC_TILDE KC_TILD

#define KC_EXLM LSFT(KC_1) // !
#define KC_EXCLAIM KC_EXLM

#define KC_AT LSFT(KC_2) // @

#define KC_HASH LSFT(KC_3) // #

#define KC_DLR LSFT(KC_4) // $
#define KC_DOLLAR KC_DLR

#define KC_PERC LSFT(KC_5) // %
#define KC_PERCENT KC_PERC

#define KC_CIRC LSFT(KC_6) // ^
#define KC_CIRCUMFLEX KC_CIRC

#define KC_AMPR LSFT(KC_7) // &
#define KC_AMPERSAND KC_AMPR

#define KC_ASTR LSFT(KC_8) // *
#define KC_ASTERISK KC_ASTR

#define KC_LPRN LSFT(KC_9) // (
#define KC_LEFT_PAREN KC_LPRN

#define KC_RPRN LSFT(KC_0) // )
#define KC_RIGHT_PAREN KC_RPRN

#define KC_UNDS LSFT(KC_MINS) // _
#define KC_UNDERSCORE KC_UNDS

#define KC_PLUS LSFT(KC_EQL) // +

#define KC_LCBR LSFT(KC_LBRC) // {
#define KC_LEFT_CURLY_BRACE KC_LCBR

#define KC_RCBR LSFT(KC_RBRC) // }
#define KC_RIGHT_CURLY_BRACE KC_RCBR

#define KC_LABK LSFT(KC_COMM) // <
#define KC_LEFT_ANGLE_BRACKET KC_LABK

#define KC_RABK LSFT(KC_DOT) // >
#define KC_RIGHT_ANGLE_BRACKET KC_RABK

#define KC_COLN LSFT(KC_SCLN) // :
#define KC_COLON KC_COLN

#define KC_PIPE LSFT(KC_BSLS) // |

#define KC_LT LSFT(KC_COMM) // <

#define KC_GT LSFT(KC_DOT) // >

#define KC_QUES LSFT(KC_SLSH) // ?
#define KC_QUESTION KC_QUES

#define KC_DQT LSFT(KC_QUOT) // "
#define KC_DOUBLE_QUOTE KC_DQT
#define KC_DQUO KC_DQT

#define KC_DELT KC_DELETE // Del key (four letter code)

// Alias for function layers than expand past FN31
#define FUNC(kc) kc | 0x2000

// Aliases
#define S(kc) LSFT(kc)
#define F(kc) FUNC(kc)

#define M(kc) (kc | 0x3000)

#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)

// 0x3100+ is free

// L-ayer, T-ap - 256 keycode max, 16 layer max
#define LT(layer, kc) (kc | 0x4000 | ((layer & 0xF) << 8))

#define RESET 0x5000
#define DEBUG 0x5001

// MAGIC keycodes
#define MAGIC_SWAP_CONTROL_CAPSLOCK 0x5002
#define MAGIC_UNSWAP_CONTROL_CAPSLOCK 0x5003
#define MAGIC_CAPSLOCK_TO_CONTROL 0x5004
#define MAGIC_UNCAPSLOCK_TO_CONTROL 0x5005
#define MAGIC_SWAP_LALT_LGUI 0x5006
#define MAGIC_UNSWAP_LALT_LGUI 0x5007
#define MAGIC_SWAP_RALT_RGUI 0x5008
#define MAGIC_UNSWAP_RALT_RGUI 0x5009
#define MAGIC_NO_GUI 0x500a
#define MAGIC_UNNO_GUI 0x500b
#define MAGIC_SWAP_GRAVE_ESC 0x500c
#define MAGIC_UNSWAP_GRAVE_ESC 0x500d
#define MAGIC_SWAP_BACKSLASH_BACKSPACE 0x500e
#define MAGIC_UNSWAP_BACKSLASH_BACKSPACE 0x500f
#define MAGIC_HOST_NKRO 0x5010
#define MAGIC_UNHOST_NKRO 0x5011
#define MAGIC_SWAP_ALT_GUI 0x5012
#define MAGIC_UNSWAP_ALT_GUI 0x5013

#define AG_SWAP MAGIC_SWAP_ALT_GUI
#define AG_NORM MAGIC_UNSWAP_ALT_GUI

#define KC_LEAD 0x5014

// Audio on/off
#define AU_ON 0x5020
#define AU_OFF 0x5021
#define AU_TOG 0x5022

// Music mode on/off
#define MU_ON 0x5023
#define MU_OFF 0x5024
#define MU_TOG 0x5025

// Music voice iterate
#define MUV_IN 0x5026
#define MUV_DE 0x5027

// Midi mode on/off
#define MI_ON 0x5028
#define MI_OFF 0x5029

// These affect the backlight (if your keyboard has one).
// We don't need to comment them out if your keyboard doesn't have a backlight,
// since they don't take up any space.
#define BL_ON 0x5079
#define BL_OFF 0x5070
#define BL_0 0x5070
#define BL_1 0x5071
#define BL_2 0x5072
#define BL_3 0x5073
#define BL_4 0x5074
#define BL_5 0x5075
#define BL_6 0x5076
#define BL_7 0x5077
#define BL_8 0x5078
#define BL_9 0x5079
#define BL_10 0x507A
#define BL_11 0x507B
#define BL_12 0x507C
#define BL_13 0x507D
#define BL_14 0x507E
#define BL_15 0x507F
#define BL_DEC 0x5080
#define BL_INC 0x5081
#define BL_TOGG 0x5082
#define BL_STEP 0x5083

#define KC_LSPO 0x5084 // Left shift, open parens when tapped
#define KC_RSPC 0x5085 // Right shift, close parens when tapped
// GOTO layer - 16 layers max
// when:
// ON_PRESS = 1
// ON_RELEASE = 2
// Unless you have a good reason not to do so, prefer ON_PRESS (1) as your default.
#define TO(layer, when) (layer | 0x5100 | (when << 0x4))

// Momentary switch layer - 256 layer max
#define MO(layer) (layer | 0x5200)

// Set default layer - 256 layer max
#define DF(layer) (layer | 0x5300)

// Toggle to layer - 256 layer max
#define TG(layer) (layer | 0x5400)

// One-shot layer - 256 layer max
#define OSL(layer) (layer | 0x5500)

// One-shot mod
#define OSM(layer) (layer | 0x5600)

// chording is currently at 0x57xx

// M-od, T-ap - 256 keycode max
#define MT(mod, kc) (kc | 0x7000 | ((mod & 0xF) << 8))
#define CTL_T(kc) MT(0x1, kc)
#define SFT_T(kc) MT(0x2, kc)
#define ALT_T(kc) MT(0x4, kc)
#define GUI_T(kc) MT(0x8, kc)
#define C_S_T(kc) MT(0x3, kc) // Control + Shift e.g. for gnome-terminal
#define MEH_T(kc) MT(0x7, kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
#define LCAG_T(kc) MT(0xD, kc) // Left control alt and gui
#define ALL_T(kc) MT(0xF, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/

// Dedicated keycode versions for Hyper and Meh, if you want to use them as standalone keys rather than mod-tap
#define KC_HYPR HYPR(KC_NO)
#define KC_MEH MEH(KC_NO)

#ifdef UNICODE_ENABLE
// For sending unicode codes.
// You may not send codes over 7FFF -- this supports most of UTF8.
// To have a key that sends out Œ, go UC(0x0152)
#define UNICODE(n) (n | 0x8000)
#define UC(n) UNICODE(n)
#endif

// For tri-layer
void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
#define IS_LAYER_ON(layer) (layer_state & (1UL << (layer)))
#define IS_LAYER_OFF(layer) (~layer_state & (1UL << (layer)))


#endif

+ 311
- 0
quantum/keymap_extras/keymap_bepo.h View File

@@ -0,0 +1,311 @@
/* Keymap macros for the French BÉPO layout - http://bepo.fr */
#ifndef KEYMAP_BEPO_H
#define KEYMAP_BEPO_H

#include "keymap_common.h"

// Alt gr
#ifndef ALTGR
#define ALTGR(kc) RALT(kc)
#endif
#ifndef ALGR
#define ALGR(kc) ALTGR(kc)
#endif
#define BP_ALGR KC_RALT

// Normal characters
// First row (on usual keyboards)
#define BP_DOLLAR KC_GRAVE // $
#define BP_DLR BP_DOLLAR
#define BP_DOUBLE_QUOTE KC_1 // "
#define BP_DQOT BP_DOUBLE_QUOTE
#define BP_LEFT_GUILLEMET KC_2 // «
#define BP_LGIL BP_LEFT_GUILLEMET
#define BP_RIGHT_GUILLEMET KC_3 // »
#define BP_RGIL BP_RIGHT_GUILLEMET
#define BP_LEFT_PAREN KC_4 // (
#define BP_LPRN BP_LEFT_PAREN
#define BP_RIGHT_PAREN KC_5 // )
#define BP_RPRN BP_RIGHT_PAREN
#define BP_AT KC_6 // @
#define BP_PLUS KC_7 // +
#define BP_MINUS KC_8 // -
#define BP_MINS BP_MINUS
#define BP_SLASH KC_9 // /
#define BP_SLSH BP_SLASH
#define BP_ASTERISK KC_0 // *
#define BP_ASTR BP_ASTERISK
#define BP_EQUAL KC_MINUS // =
#define BP_EQL BP_EQUAL
#define BP_PERCENT KC_EQUAL // %
#define BP_PERC BP_PERCENT

// Second row
#define BP_B KC_Q
#define BP_E_ACUTE KC_W // é
#define BP_ECUT BP_E_ACUTE
#define BP_P KC_E
#define BP_O KC_R
#define BP_E_GRAVE KC_T // è
#define BP_EGRV BP_E_GRAVE
#define BP_DEAD_CIRCUMFLEX KC_Y // dead ^
#define BP_DCRC BP_DEAD_CIRCUMFLEX
#define BP_V KC_U
#define BP_D KC_I
#define BP_L KC_O
#define BP_J KC_P
#define BP_Z KC_LBRACKET
#define BP_W KC_RBRACKET

// Third row
#define BP_A KC_A
#define BP_U KC_S
#define BP_I KC_D
#define BP_E KC_F
#define BP_COMMA KC_G // ,
#define BP_COMM BP_COMMA
#define BP_C KC_H
#define BP_T KC_J
#define BP_S KC_K
#define BP_R KC_L
#define BP_N KC_SCOLON
#define BP_M KC_QUOTE
#define BP_C_CEDILLA KC_BSLASH // ç
#define BP_CCED BP_C_CEDILLA

// Fourth row
#define BP_E_CIRCUMFLEX KC_NONUS_BSLASH // ê
#define BP_ECRC BP_E_CIRCUMFLEX
#define BP_A_GRAVE KC_Z // à
#define BP_AGRV BP_A_GRAVE
#define BP_Y KC_X
#define BP_X KC_C
#define BP_DOT KC_V // .
#define BP_K KC_B
#define BP_APOSTROPHE KC_N
#define BP_APOS BP_APOSTROPHE // '
#define BP_Q KC_M
#define BP_G KC_COMMA
#define BP_H KC_DOT
#define BP_F KC_SLASH

// Shifted characters
// First row
#define BP_HASH LSFT(BP_DOLLAR) // #
#define BP_1 LSFT(KC_1)
#define BP_2 LSFT(KC_2)
#define BP_3 LSFT(KC_3)
#define BP_4 LSFT(KC_4)
#define BP_5 LSFT(KC_5)
#define BP_6 LSFT(KC_6)
#define BP_7 LSFT(KC_7)
#define BP_8 LSFT(KC_8)
#define BP_9 LSFT(KC_9)
#define BP_0 LSFT(KC_0)
#define BP_DEGREE LSFT(BP_EQUAL) // °
#define BP_DEGR BP_DEGREE
#define BP_GRAVE LSFT(BP_PERCENT) // `
#define BP_GRV BP_GRAVE

// Second row
#define BP_EXCLAIM LSFT(BP_DEAD_CIRCUMFLEX) // !
#define BP_EXLM BP_EXCLAIM

// Third row
#define BP_SCOLON LSFT(BP_COMMA) // ;
#define BP_SCLN BP_SCOLON

// Fourth row
#define BP_COLON LSFT(BP_DOT) // :
#define BP_COLN BP_COLON
#define BP_QUESTION LSFT(BP_QUOTE) // ?
#define BP_QEST BP_QUESTION

// Space bar
#define BP_NON_BREAKING_SPACE LSFT(KC_SPACE)
#define BP_NBSP BP_NON_BREAKING_SPACE

// AltGr-ed characters
// First row
#define BP_EN_DASH ALTGR(BP_DOLLAR) // –
#define BP_NDSH BP_EN_DASH
#define BP_EM_DASH ALTGR(KC_1) // —
#define BP_MDSH BP_EM_DASH
#define BP_LESS ALTGR(KC_2) // <
#define BP_GREATER ALTGR(KC_3) // >
#define BP_GRTR BP_GREATER
#define BP_LBRACKET ALTGR(KC_4) // [
#define BP_LBRC BP_LBRACKET
#define BP_RBRACKET ALTGR(KC_5) // ]
#define BP_RBRC BP_RBRACKET
#define BP_CIRCUMFLEX ALTGR(KC_6) // ^
#define BP_CIRC BP_CIRCUMFLEX
#define BP_PLUS_MINUS ALTGR(KC_7) // ±
#define BP_PSMS BP_PLUS_MINUS
#define BP_MATH_MINUS ALTGR(KC_8) // −
#define BP_MMNS BP_MATH_MINUS
#define BP_OBELUS ALTGR(KC_9) // ÷
#define BP_OBEL BP_OBELUS
// more conventional name of the symbol
#define BP_DIVISION_SIGN BP_OBELUS
#define BP_DVSN BP_DIVISION_SIGN
#define BP_TIMES ALTGR(KC_0) // ×
#define BP_TIMS BP_TIMES
#define BP_DIFFERENT ALTGR(BP_EQUAL) // ≠
#define BP_DIFF BP_DIFFERENT
#define BP_PERMILLE ALTGR(BP_PERCENT) // ‰
#define BP_PMIL BP_PERMILLE

// Second row
#define BP_PIPE ALTGR(BP_B) // |
#define BP_DEAD_ACUTE ALTGR(BP_E_ACUTE) // dead ´
#define BP_DACT BP_DEAD_ACUTE
#define BP_AMPERSAND ALTGR(BP_P) // &
#define BP_AMPR BP_AMPERSAND
#define BP_OE_LIGATURE ALTGR(BP_O) // œ
#define BP_OE BP_OE_LIGATURE
#define BP_DEAD_GRAVE ALTGR(BP_E_GRAVE) // `
#define BP_DGRV BP_DEAD_GRAVE
#define BP_INVERTED_EXCLAIM ALTGR(BP_DEAD_CIRCUMFLEX) // ¡
#define BP_IXLM BP_INVERTED_EXCLAIM
#define BP_DEAD_CARON ALTGR(BP_V) // dead ˇ
#define BP_DCAR BP_DEAD_CARON
#define BP_ETH ALTGR(BP_D) // ð
#define BP_DEAD_SLASH ALTGR(BP_L) // dead /
#define BP_DSLH BP_DEAD_SLASH
#define BP_IJ_LIGATURE ALTGR(BP_J) // ij
#define BP_IJ BP_IJ_LIGATURE
#define BP_SCHWA ALTGR(BP_Z) // ə
#define BP_SCWA BP_SCHWA
#define BP_DEAD_BREVE ALTGR(BP_W) // dead ˘
#define BP_DBRV BP_DEAD_BREVE

// Third row
#define BP_AE_LIGATURE ALTGR(BP_A) // æ
#define BP_AE BP_AE_LIGATURE
#define BP_U_GRAVE AGR(BP_U) // ù
#define BP_UGRV BP_U_GRAVE
#define BP_DEAD_TREMA ALTGR(BP_I) // dead ¨ (trema/umlaut/diaresis)
#define BP_DTRM BP_DEAD_TREMA
#define BP_EURO ALTGR(BP_E) // €
#define BP_TYPOGRAPHICAL_APOSTROPHE ALTGR(BP_COMMMA) // ’
#define BP_TAPO BP_TYPOGRAPHICAL_APOSTROPHE
#define BP_COPYRIGHT ALTGR(BP_C) // ©
#define BP_CPRT BP_COPYRIGHT
#define BP_THORN ALTGR(BP_T) // þ
#define BP_THRN BP_THORN
#define BP_SHARP_S ALTGR(BP_S) // ß
#define BP_SRPS BP_SHARP_S
#define BP_REGISTERED_TRADEMARK ALTGR(BP_R) // ®
#define BP_RTM BP_REGISTERED_TRADEMARK
#define BP_DEAD_TILDE ALTGR(BP_N) // dead ~
#define BP_DTLD BP_DEAD_TILDE
#define BP_DEAD_MACRON ALTGR(BP_M) // dead ¯
#define BP_DMCR BP_DEAD_MACRON
#define BP_DEAD_CEDILLA ALTGR(BP_C_CEDILLA) // dead ¸
#define BP_DCED BP_DEAD_CEDILLA

// Fourth row
#define BP_NONUS_SLASH ALTGR(BP_E_CIRCUMFLEX) // / on non-us backslash key (102nd key, ê in bépo)
#define BP_NUSL BP_NONUS_SLASH
#define BP_BACKSLASH ALTGR(BP_A_GRAVE) /* \ */
#define BP_BSLS BP_BACKSLASH
#define BP_LEFT_CURLY_BRACE ALTGR(BP_Y) // {
#define BP_LCBR BP_LEFT_CURLY_BRACE
#define BP_RIGHT_CURLY_BRACE ALTGR(BP_X) // }
#define BP_RCBR BP_RIGHT_CURLY_BRACE
#define BP_ELLIPSIS ALTGR(BP_DOT) // …
#define BP_ELPS BP_ELLIPSIS
#define BP_TILDE ALTGR(BP_K) // ~
#define BP_TILD BP_TILDE
#define BP_INVERTED_QUESTION ALTGR(BP_QUESTION) // ¿
#define BP_IQST BP_INVERTED_QUESTION
#define BP_DEAD_RING ALTGR(BP_Q) // dead °
#define BP_DRNG BP_DEAD_RING
#define BP_DEAD_GREEK ALTGR(BP_G) // dead Greek key (following key will make a Greek letter)
#define BP_DGRK BP_DEAD_GREEK
#define BP_DAGGER ALTGR(BP_H) // †
#define BP_DAGR BP_DAGGER
#define BP_DEAD_OGONEK ALTGR(BP_F) // dead ˛
#define BP_DOGO BP_DEAD_OGONEK

// Space bar
#define BP_UNDERSCORE ALTGR(KC_SPACE) // _
#define BP_UNDS BP_UNDERSCORE

// AltGr-Shifted characters (different from capitalised AltGr-ed characters)
// First row
#define BP_PARAGRAPH ALTGR(BP_HASH) // ¶
#define BP_PARG BP_PARAGRAPH
#define BP_LOW_DOUBLE_QUOTE ALTGR(BP_1) // „
#define BP_LWQT BP_LOW_DOUBLE_QUOTE
#define BP_LEFT_DOUBLE_QUOTE ALTGR(BP_2) // “
#define BP_LDQT BP_LEFT_DOUBLE_QUOTE
#define BP_RIGHT_DOUBLE_QUOTE ALTGR(BP_3) // ”
#define BP_RDQT BP_RIGHT_DOUBLE_QUOTE
#define BP_LESS_OR_EQUAL ALTGR(BP_4) // ≤
#define BP_LEQL BP_LESS_OR_EQUAL
#define BP_GREATER_OR_EQUAL ALTGR(BP_5) // ≥
#define BP_GEQL BP_GREATER_OR_EQUAL
// nothing on ALTGR(BP_6)
#define BP_NEGATION ALTGR(BP_7) // ¬
#define BP_NEGT BP_NEGATION
#define BP_ONE_QUARTER ALTGR(BP_8) // ¼
#define BP_1QRT BP_ONE_QUARTER
#define BP_ONE_HALF ALTGR(BP_9) // ½
#define BP_1HLF BP_ONE_HALF
#define BP_THREE_QUARTERS ALTGR(BP_0) // ¾
#define BP_3QRT BP_THREE_QUARTERS
#define BP_MINUTES ALTGR(BP_DEGREE) // ′
#define BP_MNUT BP_MINUTES
#define BP_SECONDS ALTGR(BP_GRAVE) // ″
#define BP_SCND BP_SECONDS

// Second row
#define BP_BROKEN_PIPE LSFT(BP_PIPE) // ¦
#define BP_BPIP BP_BROKEN_PIPE
#define BP_DEAD_DOUBLE_ACUTE LSFT(BP_DEAD_ACUTE) // ˝
#define BP_DDCT BP_DEAD_DOUBLE_ACUTE
#define BP_SECTION ALTGR(LSFT(BP_P)) // §
#define BP_SECT BP_SECTION
// LSFT(BP_DEAD_GRAVE) is actually the same character as LSFT(BP_PERCENT)
#define BP_GRAVE_BIS LSFT(BP_DEAD_GRAVE) // `
#define BP_GRVB BP_GRAVE_BIS

// Third row
#define BP_DEAD_DOT_ABOVE LSFT(BP_DEAD_TREMA) // dead ˙
#define BP_DDTA BP_DEAD_DOT_ABOVE
#define BP_DEAD_CURRENCY LSFT(BP_EURO) // dead ¤ (next key will generate a currency code like ¥ or £)
#define BP_DCUR BP_DEAD_CURRENCY
#define BP_DEAD_HORN LSFT(ALTGR(BP_COMMA)) // dead ̛
#define BP_DHRN BP_DEAD_HORN
#define BP_LONG_S LSFT(ALTGR(BP_C)) // ſ
#define BP_LNGS BP_LONG_S
#define BP_TRADEMARK LSFT(BP_REGISTERED_TRADEMARK) // ™
#define BP_TM BP_TRADEMARK
#define BP_ORDINAL_INDICATOR_O LSFT(ALTGR(BP_M)) // º
#define BP_ORDO BP_ORDINAL_INDICATOR_O
#define BP_DEAD_COMMA LSFT(BP_DEAD_CEDILLA) // dead ˛
#define BP_DCOM BP_DEAD_COMMA

// Fourth row
#define BP_LEFT_QUOTE LSFT(ALTGR(BP_Y)) // ‘
#define BP_LQOT BP_LEFT_QUOTE
#define BP_RIGHT_QUOTE LSFT(ALTGR(BP_X)) // ’
#define BP_RQOT BP_RIGHT_QUOTE
#define BP_INTERPUNCT LSFT(ALTGR(BP_DOT)) // ·
#define BP_IPCT BP_INTERPUNCT
#define BP_DEAD_HOOK_ABOVE LSFT(ALTGR(BP_QUESTION)) // dead ̉
#define BP_DHKA BP_DEAD_HOOK_ABOVE
#define BP_DEAD_UNDERDOT LSFT(BP_DEAD_RING) // dead ̣
#define BP_DUDT BP_DEAD_UNDERDOT
#define BP_DOUBLE_DAGGER LSFT(BP_DAGGER) // ‡
#define BP_DDGR BP_DOUBLE_DAGGER
#define BP_ORDINAL_INDICATOR_A LSFT(ALTGR(BP_F)) // ª
#define BP_ORDA BP_ORDINAL_INDICATOR_A

// Space bar
#define BP_NARROW_NON_BREAKING_SPACE ALTGR(BP_NON_BREAKING_SPACE)
#define BP_NNBS BP_NARROW_NON_BREAKING_SPACE

#endif

+ 75
- 0
quantum/keymap_extras/keymap_colemak.h View File

@@ -0,0 +1,75 @@
#ifndef KEYMAP_COLEMAK_H
#define KEYMAP_COLEMAK_H

#include "keymap_common.h"
// For software implementation of colemak
#define CM_Q KC_Q
#define CM_W KC_W
#define CM_F KC_E
#define CM_P KC_R
#define CM_G KC_T
#define CM_J KC_Y
#define CM_L KC_U
#define CM_U KC_I
#define CM_Y KC_O
#define CM_SCLN KC_P

#define CM_A KC_A
#define CM_R KC_S
#define CM_S KC_D
#define CM_T KC_F
#define CM_D KC_G
#define CM_H KC_H
#define CM_N KC_J
#define CM_E KC_K
#define CM_I KC_L
#define CM_O KC_SCLN
#define CM_COLN LSFT(CM_SCLN)

#define CM_Z KC_Z
#define CM_X KC_X
#define CM_C KC_C
#define CM_V KC_V
#define CM_B KC_B
#define CM_K KC_N
#define CM_M KC_M
#define CM_COMM KC_COMM
#define CM_DOT KC_DOT
#define CM_SLSH KC_SLSH

// Make it easy to support these in macros
// TODO: change macro implementation so these aren't needed
#define KC_CM_Q CM_Q
#define KC_CM_W CM_W
#define KC_CM_F CM_F
#define KC_CM_P CM_P
#define KC_CM_G CM_G
#define KC_CM_J CM_J
#define KC_CM_L CM_L
#define KC_CM_U CM_U
#define KC_CM_Y CM_Y
#define KC_CM_SCLN CM_SCLN

#define KC_CM_A CM_A
#define KC_CM_R CM_R
#define KC_CM_S CM_S
#define KC_CM_T CM_T
#define KC_CM_D CM_D
#define KC_CM_H CM_H
#define KC_CM_N CM_N
#define KC_CM_E CM_E
#define KC_CM_I CM_I
#define KC_CM_O CM_O

#define KC_CM_Z CM_Z
#define KC_CM_X CM_X
#define KC_CM_C CM_C
#define KC_CM_V CM_V
#define KC_CM_B CM_B
#define KC_CM_K CM_K
#define KC_CM_M CM_M
#define KC_CM_COMM CM_COMM
#define KC_CM_DOT CM_DOT
#define KC_CM_SLSH CM_SLSH

#endif

+ 74
- 0
quantum/keymap_extras/keymap_dvorak.h View File

@@ -0,0 +1,74 @@
#ifndef KEYMAP_DVORAK_H
#define KEYMAP_DVORAK_H

#include "keymap_common.h"

// Normal characters
#define DV_GRV KC_GRV
#define DV_1 KC_1
#define DV_2 KC_2
#define DV_3 KC_3
#define DV_4 KC_4
#define DV_5 KC_5
#define DV_6 KC_6
#define DV_7 KC_7
#define DV_8 KC_8
#define DV_9 KC_9
#define DV_0 KC_0
#define DV_LBRC KC_MINS
#define DV_RBRC KC_EQL

#define DV_QUOT KC_Q
#define DV_COMM KC_W
#define DV_DOT KC_E
#define DV_P KC_R
#define DV_Y KC_T
#define DV_F KC_Y
#define DV_G KC_U
#define DV_C KC_I
#define DV_R KC_O
#define DV_L KC_P
#define DV_SLSH KC_LBRC
#define DV_EQL KC_RBRC

#define DV_A KC_A
#define DV_O KC_S
#define DV_E KC_D
#define DV_U KC_F
#define DV_I KC_G
#define DV_D KC_H
#define DV_H KC_J
#define DV_T KC_K
#define DV_N KC_L
#define DV_S KC_SCLN
#define DV_MINS KC_QUOT

#define DV_SCLN KC_Z
#define DV_Q KC_X
#define DV_J KC_C
#define DV_K KC_V
#define DV_X KC_B
#define DV_B KC_N
#define DV_M KC_M
#define DV_W KC_COMM
#define DV_V KC_DOT
#define DV_Z KC_SLSH

// Shifted characters
#define DV_TILD LSFT(DV_GRV)
#define DV_EXLM LSFT(DV_1)
#define DV_AT LSFT(DV_2)
#define DV_HASH LSFT(DV_3)
#define DV_DLR LSFT(DV_4)
#define DV_PERC LSFT(DV_5)
#define DV_CIRC LSFT(DV_6)
#define DV_AMPR LSFT(DV_7)
#define DV_ASTR LSFT(DV_8)
#define DV_LPRN LSFT(DV_9)
#define DV_RPRN LSFT(DV_0)
#define DV_LCBR LSFT(DV_LBRC)
#define DV_RCBR LSFT(DV_RBRC)
#define DV_UNDS LSFT(DV_MINS)
#define DV_PLUS LSFT(DV_EQL)

#endif

+ 98
- 0
quantum/keymap_extras/keymap_fr_ch.h View File

@@ -0,0 +1,98 @@
#ifndef KEYMAP_FR_CH
#define KEYMAP_FR_CH

#include "keymap_common.h"

// Alt gr
#define ALGR(kc) kc | 0x1400
#define FR_CH_ALGR KC_RALT

// normal characters
#define FR_CH_Z KC_Y
#define FR_CH_Y KC_Z

#define FR_CH_A KC_A
#define FR_CH_B KC_B
#define FR_CH_C KC_C
#define FR_CH_D KC_D
#define FR_CH_E KC_E
#define FR_CH_F KC_F
#define FR_CH_G KC_G
#define FR_CH_H KC_H
#define FR_CH_I KC_I
#define FR_CH_J KC_J
#define FR_CH_K KC_K
#define FR_CH_L KC_L
#define FR_CH_M KC_M
#define FR_CH_N KC_N
#define FR_CH_O KC_O
#define FR_CH_P KC_P
#define FR_CH_Q KC_Q
#define FR_CH_R KC_R
#define FR_CH_S KC_S
#define FR_CH_T KC_T
#define FR_CH_U KC_U
#define FR_CH_V KC_V
#define FR_CH_W KC_W
#define FR_CH_X KC_X

#define FR_CH_0 KC_0
#define FR_CH_1 KC_1
#define FR_CH_2 KC_2
#define FR_CH_3 KC_3
#define FR_CH_4 KC_4
#define FR_CH_5 KC_5
#define FR_CH_6 KC_6
#define FR_CH_7 KC_7
#define FR_CH_8 KC_8
#define FR_CH_9 KC_9

#define FR_CH_DOT KC_DOT
#define FR_CH_COMM KC_COMM

#define FR_CH_QUOT KC_MINS
#define FR_CH_AE KC_QUOT
#define FR_CH_UE KC_LBRC
#define FR_CH_OE KC_SCLN

#define FR_CH_CIRC KC_EQL // accent circumflex ^ and grave ` and ~
#define FR_CH_LESS KC_NUBS // < and > and backslash
#define FR_CH_MINS KC_SLSH // - and _
#define FR_CH_DLR KC_BSLS // $, £ and }
#define FR_CH_PARA KC_GRV // § and ring °
#define FR_CH_DIAE KC_RBRC // accent ¨

// shifted characters
#define FR_CH_RING LSFT(KC_GRV) // °
#define FR_CH_EXLM LSFT(KC_RBRC) // !
#define FR_CH_PLUS LSFT(KC_1) // +
#define FR_CH_DQOT LSFT(KC_2) // "
#define FR_CH_ASTR LSFT(KC_3) // *
#define FR_CH_PERC LSFT(KC_5) // %
#define FR_CH_AMPR LSFT(KC_6) // &
#define FR_CH_SLSH LSFT(KC_7) // /
#define FR_CH_LPRN LSFT(KC_8) // (
#define FR_CH_RPRN LSFT(KC_9) // )
#define FR_CH_EQL LSFT(KC_0) // =
#define FR_CH_QST LSFT(FR_CH_QUOT) // ?
#define FR_CH_MORE LSFT(FR_CH_LESS) // >
#define FR_CH_COLN LSFT(KC_DOT) // :
#define FR_CH_SCLN LSFT(KC_COMM) // ;
#define FR_CH_UNDS LSFT(FR_CH_MINS) // _
#define FR_CH_CCED LSFT(KC_4) // ç
#define FR_CH_GRV LSFT(FR_CH_CIRC) // accent grave `

// Alt Gr-ed characters
#define FR_CH_LCBR ALGR(KC_QUOT) // {
#define FR_CH_LBRC ALGR(KC_LBRC) // [
#define FR_CH_RBRC ALGR(KC_9) // ]
#define FR_CH_RCBR ALGR(KC_0) // }
#define FR_CH_BSLS ALGR(FR_CH_LESS) // backslash
#define FR_CH_AT ALGR(KC_2) // @
#define FR_CH_EURO ALGR(KC_E) // €
#define FR_CH_TILD ALGR(FR_CH_CIRC) // ~
#define FR_CH_PIPE ALGR(KC_1) // |
#define FR_CH_HASH ALGR(KC_3) // #
#define FR_CH_ACUT ALGR(FR_CH_QUOT) // accent acute ´

#endif

+ 83
- 0
quantum/keymap_extras/keymap_french.h View File

@@ -0,0 +1,83 @@
#ifndef KEYMAP_FRENCH_H
#define KEYMAP_FRENCH_H

#include "keymap_common.h"

// Alt gr
#define ALGR(kc) kc | 0x1400
#define NO_ALGR KC_RALT

// Normal characters
#define FR_SUP2 KC_GRV
#define FR_AMP KC_1
#define FR_EACU KC_2
#define FR_QUOT KC_3
#define FR_APOS KC_4
#define FR_LPRN KC_5
#define FR_MINS KC_6
#define FR_EGRV KC_7
#define FR_UNDS KC_8
#define FR_CCED KC_9
#define FR_AGRV KC_0
#define FR_RPRN KC_MINS
#define FR_EQL KC_EQL

#define FR_A KC_Q
#define FR_Z KC_W
#define FR_CIRC KC_LBRC
#define FR_DLR KC_RBRC

#define FR_Q KC_A
#define FR_M KC_SCLN
#define FR_UGRV KC_QUOT
#define FR_ASTR KC_NUHS

#define FR_LESS KC_NUBS
#define FR_W KC_Z
#define FR_COMM KC_M
#define FR_SCLN KC_COMM
#define FR_COLN KC_DOT
#define FR_EXLM KC_SLSH

// Shifted characters
#define FR_1 LSFT(KC_1)
#define FR_2 LSFT(KC_2)
#define FR_3 LSFT(KC_3)
#define FR_4 LSFT(KC_4)
#define FR_5 LSFT(KC_5)
#define FR_6 LSFT(KC_6)
#define FR_7 LSFT(KC_7)
#define FR_8 LSFT(KC_8)
#define FR_9 LSFT(KC_9)
#define FR_0 LSFT(KC_0)
#define FR_OVRR LSFT(FR_RPRN)
#define FR_PLUS LSFT(FR_EQL)

#define FR_UMLT LSFT(FR_CIRC)
#define FR_PND LSFT(FR_DLR)
#define FR_PERC LSFT(FR_UGRV)
#define FR_MU LSFT(FR_ASTR)

#define FR_GRTR LSFT(FR_LESS)
#define FR_QUES LSFT(FR_COMM)
#define FR_DOT LSFT(FR_SCLN)
#define FR_SLSH LSFT(FR_COLN)
#define FR_SECT LSFT(FR_EXLM)

// Alt Gr-ed characters
#define FR_TILD ALGR(KC_2)
#define FR_HASH ALGR(KC_3)
#define FR_LCBR ALGR(KC_4)
#define FR_LBRC ALGR(KC_5)
#define FR_PIPE ALGR(KC_6)
#define FR_GRV ALGR(KC_7)
#define FR_BSLS ALGR(KC_8)
#define FR_CIRC ALGR(KC_9)
#define FR_AT ALGR(KC_0)
#define FR_RBRC ALGR(FR_RPRN)
#define FR_RCBR ALGR(FR_EQL)

#define FR_EURO ALGR(KC_E)
#define FR_BULT ALGR(FR_DLR)

#endif

+ 77
- 0
quantum/keymap_extras/keymap_french_osx.h View File

@@ -0,0 +1,77 @@
#ifndef KEYMAP_FRENCH_OSX_H
#define KEYMAP_FRENCH_OSX_H

#include "keymap_common.h"

// Normal characters
#define FR_AT KC_GRV
#define FR_AMP KC_1
#define FR_EACU KC_2
#define FR_QUOT KC_3
#define FR_APOS KC_4
#define FR_LPRN KC_5
#define FR_SECT KC_6
#define FR_EGRV KC_7
#define FR_EXLM KC_8
#define FR_CCED KC_9
#define FR_AGRV KC_0
#define FR_RPRN KC_MINS
#define FR_MINS KC_EQL

#define FR_A KC_Q
#define FR_Z KC_W
#define FR_CIRC KC_LBRC
#define FR_DLR KC_RBRC

#define FR_Q KC_A
#define FR_M KC_SCLN
#define FR_UGRV KC_QUOT
#define FR_GRV KC_NUHS

#define FR_LESS KC_NUBS
#define FR_W KC_Z
#define FR_COMM KC_M
#define FR_SCLN KC_COMM
#define FR_COLN KC_DOT
#define FR_EQL KC_SLSH

// Shifted characters
#define FR_HASH LSFT(KC_GRV)
#define FR_1 LSFT(KC_1)
#define FR_2 LSFT(KC_2)
#define FR_3 LSFT(KC_3)
#define FR_4 LSFT(KC_4)
#define FR_5 LSFT(KC_5)
#define FR_6 LSFT(KC_6)
#define FR_7 LSFT(KC_7)
#define FR_8 LSFT(KC_8)
#define FR_9 LSFT(KC_9)
#define FR_0 LSFT(KC_0)
#define FR_UNDS LSFT(FR_MINS)

#define FR_UMLT LSFT(FR_CIRC)
#define FR_ASTR LSFT(FR_DLR)

#define FR_PERC LSFT(FR_UGRV)
#define FR_PND LSFT(FR_GRV)

#define FR_GRTR LSFT(FR_LESS)
#define FR_QUES LSFT(FR_COMM)
#define FR_DOT LSFT(FR_SCLN)
#define FR_SLSH LSFT(FR_COLN)
#define FR_PLUS LSFT(FR_EQL)

// Alted characters
#define FR_LCBR LALT(KC_5)
#define FR_RCBR LALT(FR_RPRN)
#define FR_EURO LALT(KC_E)
#define FR_BULT LALT(FR_DLR)
#define FR_TILD LALT(KC_N)

// Shift+Alt-ed characters
#define FR_LBRC LSFT(LALT(KC_5))
#define FR_RBRC LSFT(LALT(FR_RPRN))
#define FR_PIPE LSFT(LALT(KC_L))
#define FR_BSLS LSFT(LALT(FR_COLN))

#endif

+ 99
- 0
quantum/keymap_extras/keymap_german.h View File

@@ -0,0 +1,99 @@
#ifndef KEYMAP_GERMAN
#define KEYMAP_GERMAN

#include "keymap_common.h"

// Alt gr
#define ALGR(kc) kc | 0x1400
#define DE_ALGR KC_RALT

// normal characters
#define DE_Z KC_Y
#define DE_Y KC_Z

#define DE_A KC_A
#define DE_B KC_B
#define DE_C KC_C
#define DE_D KC_D
#define DE_E KC_E
#define DE_F KC_F
#define DE_G KC_G
#define DE_H KC_H
#define DE_I KC_I
#define DE_J KC_J
#define DE_K KC_K
#define DE_L KC_L
#define DE_M KC_M
#define DE_N KC_N
#define DE_O KC_O
#define DE_P KC_P
#define DE_Q KC_Q
#define DE_R KC_R
#define DE_S KC_S
#define DE_T KC_T
#define DE_U KC_U
#define DE_V KC_V
#define DE_W KC_W
#define DE_X KC_X

#define DE_0 KC_0
#define DE_1 KC_1
#define DE_2 KC_2
#define DE_3 KC_3
#define DE_4 KC_4
#define DE_5 KC_5
#define DE_6 KC_6
#define DE_7 KC_7
#define DE_8 KC_8
#define DE_9 KC_9

#define DE_DOT KC_DOT
#define DE_COMM KC_COMM

#define DE_SS KC_MINS
#define DE_AE KC_QUOT
#define DE_UE KC_LBRC
#define DE_OE KC_SCLN

#define DE_CIRC KC_GRAVE // accent circumflex ^ and ring °
#define DE_ACUT KC_EQL // accent acute ´ and grave `
#define DE_PLUS KC_RBRC // + and * and ~
#define DE_HASH KC_BSLS // # and '
#define DE_LESS KC_NUBS // < and > and |
#define DE_MINS KC_SLSH // - and _

// shifted characters
#define DE_RING LSFT(DE_CIRC) // °
#define DE_EXLM LSFT(KC_1) // !
#define DE_DQOT LSFT(KC_2) // "
#define DE_PARA LSFT(KC_3) // §
#define DE_DLR LSFT(KC_4) // $
#define DE_PERC LSFT(KC_5) // %
#define DE_AMPR LSFT(KC_6) // &
#define DE_SLSH LSFT(KC_7) // /
#define DE_LPRN LSFT(KC_8) // (
#define DE_RPRN LSFT(KC_9) // )
#define DE_EQL LSFT(KC_0) // =
#define DE_QST LSFT(DE_SS) // ?
#define DE_GRV LSFT(DE_ACUT) // `
#define DE_ASTR LSFT(DE_PLUS) // *
#define DE_QUOT LSFT(DE_HASH) // '
#define DE_MORE LSFT(DE_LESS) // >
#define DE_COLN LSFT(KC_DOT) // :
#define DE_SCLN LSFT(KC_COMM) // ;
#define DE_UNDS LSFT(DE_MINS) // _

// Alt Gr-ed characters
#define DE_SQ2 ALGR(KC_2) // ²
#define DE_SQ3 ALGR(KC_3) // ³
#define DE_LCBR ALGR(KC_7) // {
#define DE_LBRC ALGR(KC_8) // [
#define DE_RBRC ALGR(KC_9) // ]
#define DE_RCBR ALGR(KC_0) // }
#define DE_BSLS ALGR(DE_SS) // backslash
#define DE_AT ALGR(KC_Q) // @
#define DE_EURO ALGR(KC_E) // €
#define DE_TILD ALGR(DE_PLUS) // ~
#define DE_PIPE ALGR(DE_LESS) // |

#endif

+ 102
- 0
quantum/keymap_extras/keymap_german_ch.h View File

@@ -0,0 +1,102 @@
#ifndef KEYMAP_SWISS_GERMAN
#define KEYMAP_SWISS_GERMAN

#include "keymap_common.h"

// Alt gr
#define ALGR(kc) kc | 0x1400
#define CH_ALGR KC_RALT

// normal characters
#define CH_Z KC_Y
#define CH_Y KC_Z

#define CH_A KC_A
#define CH_B KC_B
#define CH_C KC_C
#define CH_D KC_D
#define CH_E KC_E
#define CH_F KC_F
#define CH_G KC_G
#define CH_H KC_H
#define CH_I KC_I
#define CH_J KC_J
#define CH_K KC_K
#define CH_L KC_L
#define CH_M KC_M
#define CH_N KC_N
#define CH_O KC_O
#define CH_P KC_P
#define CH_Q KC_Q
#define CH_R KC_R
#define CH_S KC_S
#define CH_T KC_T
#define CH_U KC_U
#define CH_V KC_V
#define CH_W KC_W
#define CH_X KC_X

#define CH_0 KC_0
#define CH_1 KC_1
#define CH_2 KC_2
#define CH_3 KC_3
#define CH_4 KC_4
#define CH_5 KC_5
#define CH_6 KC_6
#define CH_7 KC_7
#define CH_8 KC_8
#define CH_9 KC_9

#define CH_DOT KC_DOT
#define CH_COMM KC_COMM

#define CH_QUOT KC_MINS // ' ? ´
#define CH_AE KC_QUOT
#define CH_UE KC_LBRC
#define CH_OE KC_SCLN

#define CH_PARA KC_GRAVE // secction sign § and °
#define CH_CARR KC_EQL // carret ^ ` ~
#define CH_DIER KC_RBRC // dieresis ¨ ! ]
#define CH_DLR KC_BSLS // $ £ }
#define CH_LESS KC_NUBS // < and > and backslash
#define CH_MINS KC_SLSH // - and _

// shifted characters
#define CH_RING LSFT(CH_PARA) // °
#define CH_PLUS LSFT(KC_1) // +
#define CH_DQOT LSFT(KC_2) // "
#define CH_PAST LSFT(KC_3) // *
#define CH_CELA LSFT(KC_4) // ç
#define CH_PERC LSFT(KC_5) // %
#define CH_AMPR LSFT(KC_6) // &
#define CH_SLSH LSFT(KC_7) // /
#define CH_LPRN LSFT(KC_8) // (
#define CH_RPRN LSFT(KC_9) // )
#define CH_EQL LSFT(KC_0) // =
#define CH_QST LSFT(CH_QUOT) // ?
#define CH_GRV LSFT(CH_CARR) // `
#define CH_EXLM LSFT(CH_DIER) // !
#define CH_POND LSFT(CH_DLR) // £
#define CH_MORE LSFT(CH_LESS) // >
#define CH_COLN LSFT(KC_DOT) // :
#define CH_SCLN LSFT(KC_COMM) // ;
#define CH_UNDS LSFT(CH_MINS) // _

// Alt Gr-ed characters
#define CH_BRBR ALGR(KC_1) // ¦ brocken bar
#define CH_AT ALGR(KC_2) // @
#define CH_HASH ALGR(KC_3) // #
#define CH_NOTL ALGR(KC_6) // ¬ negative logic
#define CH_PIPE ALGR(KC_7) // |
#define CH_CENT ALGR(KC_8) // ¢ cent
#define CH_ACUT ALGR(CH_QUOT) // ´
#define CH_TILD ALGR(CH_CARR) // ~
#define CH_EURO ALGR(KC_E) // €
#define CH_LBRC ALGR(CH_UE) // [
#define CH_RBRC ALGR(CH_DIER) // ]
#define CH_LCBR ALGR(CH_AE) // {
#define CH_RCBR ALGR(CH_DLR) // }
#define CH_BSLS ALGR(CH_LESS) // backslash

#endif

+ 100
- 0
quantum/keymap_extras/keymap_german_osx.h View File

@@ -0,0 +1,100 @@
#ifndef KEYMAP_GERMAN_OSX
#define KEYMAP_GERMAN_OSX

#ifdef KEYMAP_GERMAN
#warning redefining german keys
#endif
#include "keymap_common.h"

// Alt gr

// normal characters
#define DE_OSX_Z KC_Y
#define DE_OSX_Y KC_Z

#define DE_OSX_A KC_A
#define DE_OSX_B KC_B
#define DE_OSX_C KC_C
#define DE_OSX_D KC_D
#define DE_OSX_E KC_E
#define DE_OSX_F KC_F
#define DE_OSX_G KC_G
#define DE_OSX_H KC_H
#define DE_OSX_I KC_I
#define DE_OSX_J KC_J
#define DE_OSX_K KC_K
#define DE_OSX_L KC_L
#define DE_OSX_M KC_M
#define DE_OSX_N KC_N
#define DE_OSX_O KC_O
#define DE_OSX_P KC_P
#define DE_OSX_Q KC_Q
#define DE_OSX_R KC_R
#define DE_OSX_S KC_S
#define DE_OSX_T KC_T
#define DE_OSX_U KC_U
#define DE_OSX_V KC_V
#define DE_OSX_W KC_W
#define DE_OSX_X KC_X

#define DE_OSX_0 KC_0
#define DE_OSX_1 KC_1
#define DE_OSX_2 KC_2
#define DE_OSX_3 KC_3
#define DE_OSX_4 KC_4
#define DE_OSX_5 KC_5
#define DE_OSX_6 KC_6
#define DE_OSX_7 KC_7
#define DE_OSX_8 KC_8
#define DE_OSX_9 KC_9

#define DE_OSX_DOT KC_DOT
#define DE_OSX_COMM KC_COMM

#define DE_OSX_SS KC_MINS
#define DE_OSX_AE KC_QUOT
#define DE_OSX_UE KC_LBRC
#define DE_OSX_OE KC_SCLN

#define DE_OSX_CIRC KC_NUBS // accent circumflex ^ and ring °
#define DE_OSX_ACUT KC_EQL // accent acute ´ and grave `
#define DE_OSX_PLUS KC_RBRC // + and * and ~
#define DE_OSX_HASH KC_BSLS // # and '
#define DE_OSX_LESS KC_GRV // < and > and |
#define DE_OSX_MINS KC_SLSH // - and _

// shifted characters
#define DE_OSX_RING LSFT(DE_OSX_CIRC) // °
#define DE_OSX_EXLM LSFT(KC_1) // !
#define DE_OSX_DQOT LSFT(KC_2) // "
#define DE_OSX_PARA LSFT(KC_3) // §
#define DE_OSX_DLR LSFT(KC_4) // $
#define DE_OSX_PERC LSFT(KC_5) // %
#define DE_OSX_AMPR LSFT(KC_6) // &
#define DE_OSX_SLSH LSFT(KC_7) // /
#define DE_OSX_LPRN LSFT(KC_8) // (
#define DE_OSX_RPRN LSFT(KC_9) // )
#define DE_OSX_EQL LSFT(KC_0) // =
#define DE_OSX_QST LSFT(DE_OSX_SS) // ?
#define DE_OSX_GRV LSFT(DE_OSX_ACUT) // `
#define DE_OSX_ASTR LSFT(DE_OSX_PLUS) // *
#define DE_OSX_QUOT LSFT(DE_OSX_HASH) // '
#define DE_OSX_MORE LSFT(DE_OSX_LESS) // >
#define DE_OSX_COLN LSFT(KC_DOT) // :
#define DE_OSX_SCLN LSFT(KC_COMM) // ;
#define DE_OSX_UNDS LSFT(DE_OSX_MINS) // _

// Alt-ed characters
//#define DE_OSX_SQ2 LALT(KC_2) // ²
//#define DE_OSX_SQ3 LALT(KC_3) // ³
#define DE_OSX_LCBR LALT(KC_8) // {
#define DE_OSX_LBRC LALT(KC_5) // [
#define DE_OSX_RBRC LALT(KC_6) // ]
#define DE_OSX_RCBR LALT(KC_9) // }
#define DE_OSX_BSLS LALT(LSFT(KC_7)) // backslash
#define DE_OSX_AT LALT(DE_OSX_L) // @
#define DE_OSX_EURO LALT(KC_E) // €
#define DE_OSX_TILD LALT(DE_OSX_N) // ~
#define DE_OSX_PIPE LALT(DE_OSX_7) // |

#endif

+ 63
- 0
quantum/keymap_extras/keymap_neo2.h View File

@@ -0,0 +1,63 @@
#ifndef KEYMAP_NEO2
#define KEYMAP_NEO2

#include "keymap_common.h"
#include "keymap_extras/keymap_german.h"

#define NEO_A KC_D
#define NEO_B KC_N
#define NEO_C KC_R
#define NEO_D DE_OE
#define NEO_E KC_F
#define NEO_F KC_O
#define NEO_G KC_I
#define NEO_H KC_U
#define NEO_I KC_S
#define NEO_J DE_MINS
#define NEO_K DE_Z
#define NEO_L KC_E
#define NEO_M KC_M
#define NEO_N KC_J
#define NEO_O KC_G
#define NEO_P KC_V
#define NEO_Q KC_P
#define NEO_R KC_K
#define NEO_S KC_H
#define NEO_T KC_L
#define NEO_U KC_A
#define NEO_V KC_W
#define NEO_W KC_T
#define NEO_X KC_Q
#define NEO_Y DE_AE
#define NEO_Z KC_B
#define NEO_AE KC_C
#define NEO_OE KC_X
#define NEO_UE DE_Y
#define NEO_SS DE_UE

#define NEO_DOT DE_DOT
#define NEO_COMM DE_COMM

#define NEO_1 DE_1
#define NEO_2 DE_2
#define NEO_3 DE_3
#define NEO_4 DE_4
#define NEO_5 DE_5
#define NEO_6 DE_6
#define NEO_7 DE_7
#define NEO_8 DE_8
#define NEO_9 DE_9
#define NEO_0 DE_0
#define NEO_MINS DE_SS

#define NEO_ACUT DE_PLUS
#define NEO_GRV DE_ACUT
#define NEO_CIRC DE_CIRC

#define NEO_L1_L KC_CAPS
#define NEO_L1_R DE_HASH

#define NEO_L2_L DE_LESS
#define NEO_L2_R DE_ALGR

#endif

+ 59
- 0
quantum/keymap_extras/keymap_nordic.h View File

@@ -0,0 +1,59 @@
#ifndef KEYMAP_NORDIC_H
#define KEYMAP_NORDIC_H

#include "keymap_common.h"

// Alt gr
#define ALGR(kc) kc | 0x1400
#define NO_ALGR KC_RALT

// Normal characters
#define NO_HALF KC_GRV
#define NO_PLUS KC_MINS
#define NO_ACUT KC_EQL

#define NO_AM KC_LBRC
#define NO_QUOT KC_RBRC
#define NO_AE KC_SCLN
#define NO_OSLH KC_QUOT
#define NO_APOS KC_NUHS

#define NO_LESS KC_NUBS
#define NO_MINS KC_SLSH

// Shifted characters
#define NO_SECT LSFT(NO_HALF)
#define NO_QUO2 LSFT(KC_2)
#define NO_BULT LSFT(KC_4)
#define NO_AMP LSFT(KC_6)
#define NO_SLSH LSFT(KC_7)
#define NO_LPRN LSFT(KC_8)
#define NO_RPRN LSFT(KC_9)
#define NO_EQL LSFT(KC_0)
#define NO_QUES LSFT(NO_PLUS)
#define NO_GRV LSFT(NO_ACUT)

#define NO_CIRC LSFT(NO_QUOT)

#define NO_GRTR LSFT(NO_LESS)
#define NO_SCLN LSFT(KC_COMM)
#define NO_COLN LSFT(KC_DOT)
#define NO_UNDS LSFT(NO_MINS)

// Alt Gr-ed characters
#define NO_AT ALGR(KC_2)
#define NO_PND ALGR(KC_3)
#define NO_DLR ALGR(KC_4)
#define NO_LCBR ALGR(KC_7)
#define NO_LBRC ALGR(KC_8)
#define NO_RBRC ALGR(KC_9)
#define NO_RCBR ALGR(KC_0)
#define NO_PIPE ALGR(KC_NUBS)

#define NO_EURO ALGR(KC_E)
#define NO_TILD ALGR(NO_QUOT)

#define NO_BSLS ALGR(KC_MINS)
#define NO_MU ALGR(KC_M)

#endif

+ 41
- 0
quantum/keymap_extras/keymap_norwegian.c View File

@@ -0,0 +1,41 @@
#ifndef KEYMAP_NORWEGIAN_H
#define KEYMAP_NORWEGIAN_H

#include "keymap_nordic.h"

// There are slight differrences in the keyboards in the nordic contries

// Norwegian redifinitions from the nordic keyset
#undef NO_ACUT
#define NO_ACUT ALGR(NO_BSLS) // ´
#undef NO_AE
#define NO_AE KC_QUOT // æ
#undef NO_BSLS
#define NO_BSLS KC_EQL // '\'
#undef NO_CIRC
#define NO_CIRC LSFT(C_RBRC) // ^
#undef NO_GRV
#define NO_GRV LSFT(NO_BSLS) //
#undef NO_OSLH
#define NO_OSLH KC_SCLN // ø
#undef NO_PIPE
#define NO_PIPE KC_GRV // |

// Additional norwegian keys not defined in the nordic keyset
#define NO_AA KC_LBRC // å
#define NO_ASTR LSFT(KC_BSLS) // *

// Norwegian unique MAC characters
#define NO_ACUT_MAC KC_EQL // =
#define NO_APOS_MAC KC_NUBS // '
#define NO_AT_MAC KC_BSLS // @
#define NO_BSLS_MAC ALGR(LSFT(KC_7)) // '\'
#define NO_DLR_MAC LSFT(KC_4) // $
#define NO_GRV_MAC ALGR(NO_BSLS) // `
#define NO_GRTR_MAC LSFT(KC_GRV) // >
#define NO_LCBR_MAC ALGR(LSFT(KC_8)) // }
#define NO_LESS_MAC KC_GRV // >
#define NO_PIPE_MAC ALGR(KC_7) // |
#define NO_RCBR_MAC ALGR(LSFT(KC_9)) // }

#endif

+ 32
- 0
quantum/keymap_extras/keymap_plover.h View File

@@ -0,0 +1,32 @@
#ifndef KEYMAP_PLOVER_H
#define KEYMAP_PLOVER_H

#include "keymap_common.h"

#define PV_NUM KC_1
#define PV_LS KC_Q
#define PV_LT KC_W
#define PV_LP KC_E
#define PV_LH KC_R
#define PV_LK KC_S
#define PV_LW KC_D
#define PV_LR KC_F

#define PV_STAR KC_Y
#define PV_RF KC_U
#define PV_RP KC_I
#define PV_RL KC_O
#define PV_RT KC_P
#define PV_RD KC_LBRC
#define PV_RR KC_J
#define PV_RB KC_K
#define PV_RG KC_L
#define PV_RS KC_SCLN
#define PV_RZ KC_QUOT

#define PV_A KC_C
#define PV_O KC_V
#define PV_E KC_N
#define PV_U KC_M

#endif

+ 62
- 0
quantum/keymap_extras/keymap_spanish.h View File

@@ -0,0 +1,62 @@
#ifndef KEYMAP_SPANISH_H
#define KEYMAP_SPANISH_H

#include "keymap_common.h"

// Alt gr
#define ALGR(kc) kc | 0x1400
#define NO_ALGR KC_RALT

// Normal characters
#define ES_OVRR KC_GRV
#define ES_APOS KC_MINS
#define ES_IEXL KC_EQL

#define ES_GRV KC_LBRC
#define ES_PLUS KC_RBRC

#define ES_NTIL KC_SCLN
#define ES_ACUT KC_QUOT
#define ES_CCED KC_NUHS

#define ES_LESS KC_NUBS
#define ES_MINS KC_SLSH

// Shifted characters
#define ES_ASML LSFT(ES_OVRR)
#define ES_QUOT LSFT(KC_2)
#define ES_OVDT LSFT(KC_3)
#define ES_AMPR LSFT(KC_6)
#define ES_SLSH LSFT(KC_7)
#define ES_LPRN LSFT(KC_8)
#define ES_RPRN LSFT(KC_9)
#define ES_EQL LSFT(KC_0)
#define ES_QUES LSFT(ES_APOS)
#define ES_IQUE LSFT(ES_IEXL)

#define ES_CIRC LSFT(ES_GRV)
#define ES_ASTR LSFT(ES_PLUS)

#define ES_UMLT LSFT(ES_GRV)

#define ES_GRTR LSFT(ES_LESS)
#define ES_SCLN LSFT(ES_COMM)
#define ES_COLN LSFT(ES_DOT)
#define ES_UNDS LSFT(ES_MINS)

// Alt Gr-ed characters
#define ES_BSLS ALGR(ES_OVRR)
#define ES_PIPE ALGR(KC_1)
#define ES_AT ALGR(KC_2)
#define ES_HASH ALGR(KC_3)
#define ES_TILD ALGR(KC_4)
#define ES_EURO ALGR(KC_5)
#define ES_NOT ALGR(KC_6)

#define ES_LBRC ALGR(ES_GRV)
#define ES_RBRC ALGR(ES_PLUS)

#define ES_LCBR ALGR(ES_ACUT)
#define ES_RCRB ALGR(ES_CCED)

#endif

+ 36
- 0
quantum/keymap_extras/keymap_uk.h View File

@@ -0,0 +1,36 @@
#ifndef KEYMAP_UK_H
#define KEYMAP_UK_H

#include "keymap_common.h"

// Alt gr
#define ALGR(kc) kc | 0x1400
#define NO_ALGR KC_RALT

// Normal characters
#define UK_HASH KC_NUHS

#define UK_BSLS KC_NUBS

// Shifted characters
#define UK_NOT LSFT(KC_GRV)
#define UK_QUOT LSFT(KC_2)
#define UK_PND LSFT(KC_3)

#define UK_AT LSFT(KC_QUOT)
#define UK_TILD LSFT(KC_NUHS)

#define UK_PIPE LSFT(KC_NUBS)

// Alt Gr-ed characters
#define UK_BRKP ALGR(KC_GRV)
#define UK_EURO ALGR(KC_4)

#define UK_EACT ALGR(KC_E)
#define UK_UACT ALGR(KC_U)
#define UK_IACT ALGR(KC_I)
#define UK_OACT ALGR(KC_O)

#define UK_AACT ALGR(KC_A)

#endif

+ 109
- 0
quantum/keymap_midi.c View File

@@ -0,0 +1,109 @@
/*
Copyright 2015 Jack Humbert <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 "keymap_common.h"
#include "keymap_midi.h"

uint8_t starting_note = 0x0C;
int offset = 7;

void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
if (id != 0) {
if (record->event.pressed) {
midi_send_noteon(&midi_device, opt, (id & 0xFF), 127);
} else {
midi_send_noteoff(&midi_device, opt, (id & 0xFF), 127);
}
}

if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) {
starting_note++;
play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
return;
} else {
stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
stop_all_notes();
return;
}
}
if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) {
starting_note--;
play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
return;
} else {
stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[0 + offset])/12.0+(MATRIX_ROWS - 1)));
stop_all_notes();
return;
}
}

if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
offset++;
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
stop_all_notes();
for (int i = 0; i <= 7; i++) {
play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
_delay_us(80000);
stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
_delay_us(8000);
}
return;
}
if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
offset--;
midi_send_cc(&midi_device, 0, 0x7B, 0);
midi_send_cc(&midi_device, 1, 0x7B, 0);
midi_send_cc(&midi_device, 2, 0x7B, 0);
midi_send_cc(&midi_device, 3, 0x7B, 0);
midi_send_cc(&midi_device, 4, 0x7B, 0);
stop_all_notes();
for (int i = 0; i <= 7; i++) {
play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)), 0xC);
_delay_us(80000);
stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[i + offset])/12.0+(MATRIX_ROWS - 1)));
_delay_us(8000);
}
return;
}

if (record->event.pressed) {
// midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
// midi_send_noteon(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
play_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF);
} else {
// midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
// midi_send_noteoff(&midi_device, 0, (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row), 127);
stop_note(((double)261.626)*pow(2.0, -1.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)));
}
}

+ 222
- 0
quantum/keymap_midi.h View File

@@ -0,0 +1,222 @@
/*
Copyright 2015 Jack Humbert <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/

#ifndef KEYMAP_MIDI_H
#define KEYMAP_MIDI_H

#include <lufa.h>

#define MIDI(n) ((n) | 0x6000)
#define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000

#define CHNL(note, channel) (note + (channel << 8))

#define SCALE (int8_t []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }

#define N_CN1 (0x600C + (12 * -1) + 0 )
#define N_CN1S (0x600C + (12 * -1) + 1 )
#define N_DN1F (0x600C + (12 * -1) + 1 )
#define N_DN1 (0x600C + (12 * -1) + 2 )
#define N_DN1S (0x600C + (12 * -1) + 3 )
#define N_EN1F (0x600C + (12 * -1) + 3 )
#define N_EN1 (0x600C + (12 * -1) + 4 )
#define N_FN1 (0x600C + (12 * -1) + 5 )
#define N_FN1S (0x600C + (12 * -1) + 6 )
#define N_GN1F (0x600C + (12 * -1) + 6 )
#define N_GN1 (0x600C + (12 * -1) + 7 )
#define N_GN1S (0x600C + (12 * -1) + 8 )
#define N_AN1F (0x600C + (12 * -1) + 8 )
#define N_AN1 (0x600C + (12 * -1) + 9 )
#define N_AN1S (0x600C + (12 * -1) + 10)
#define N_BN1F (0x600C + (12 * -1) + 10)
#define N_BN1 (0x600C + (12 * -1) + 11)
#define N_C0 (0x600C + (12 * 0) + 0 )
#define N_C0S (0x600C + (12 * 0) + 1 )
#define N_D0F (0x600C + (12 * 0) + 1 )
#define N_D0 (0x600C + (12 * 0) + 2 )
#define N_D0S (0x600C + (12 * 0) + 3 )
#define N_E0F (0x600C + (12 * 0) + 3 )
#define N_E0 (0x600C + (12 * 0) + 4 )
#define N_F0 (0x600C + (12 * 0) + 5 )
#define N_F0S (0x600C + (12 * 0) + 6 )
#define N_G0F (0x600C + (12 * 0) + 6 )
#define N_G0 (0x600C + (12 * 0) + 7 )
#define N_G0S (0x600C + (12 * 0) + 8 )
#define N_A0F (0x600C + (12 * 0) + 8 )
#define N_A0 (0x600C + (12 * 0) + 9 )
#define N_A0S (0x600C + (12 * 0) + 10)
#define N_B0F (0x600C + (12 * 0) + 10)
#define N_B0 (0x600C + (12 * 0) + 11)
#define N_C1 (0x600C + (12 * 1) + 0 )
#define N_C1S (0x600C + (12 * 1) + 1 )
#define N_D1F (0x600C + (12 * 1) + 1 )
#define N_D1 (0x600C + (12 * 1) + 2 )
#define N_D1S (0x600C + (12 * 1) + 3 )
#define N_E1F (0x600C + (12 * 1) + 3 )
#define N_E1 (0x600C + (12 * 1) + 4 )
#define N_F1 (0x600C + (12 * 1) + 5 )
#define N_F1S (0x600C + (12 * 1) + 6 )
#define N_G1F (0x600C + (12 * 1) + 6 )
#define N_G1 (0x600C + (12 * 1) + 7 )
#define N_G1S (0x600C + (12 * 1) + 8 )
#define N_A1F (0x600C + (12 * 1) + 8 )
#define N_A1 (0x600C + (12 * 1) + 9 )
#define N_A1S (0x600C + (12 * 1) + 10)
#define N_B1F (0x600C + (12 * 1) + 10)
#define N_B1 (0x600C + (12 * 1) + 11)
#define N_C2 (0x600C + (12 * 2) + 0 )
#define N_C2S (0x600C + (12 * 2) + 1 )
#define N_D2F (0x600C + (12 * 2) + 1 )
#define N_D2 (0x600C + (12 * 2) + 2 )
#define N_D2S (0x600C + (12 * 2) + 3 )
#define N_E2F (0x600C + (12 * 2) + 3 )
#define N_E2 (0x600C + (12 * 2) + 4 )
#define N_F2 (0x600C + (12 * 2) + 5 )
#define N_F2S (0x600C + (12 * 2) + 6 )
#define N_G2F (0x600C + (12 * 2) + 6 )
#define N_G2 (0x600C + (12 * 2) + 7 )
#define N_G2S (0x600C + (12 * 2) + 8 )
#define N_A2F (0x600C + (12 * 2) + 8 )
#define N_A2 (0x600C + (12 * 2) + 9 )
#define N_A2S (0x600C + (12 * 2) + 10)
#define N_B2F (0x600C + (12 * 2) + 10)
#define N_B2 (0x600C + (12 * 2) + 11)
#define N_C3 (0x600C + (12 * 3) + 0 )
#define N_C3S (0x600C + (12 * 3) + 1 )
#define N_D3F (0x600C + (12 * 3) + 1 )
#define N_D3 (0x600C + (12 * 3) + 2 )
#define N_D3S (0x600C + (12 * 3) + 3 )
#define N_E3F (0x600C + (12 * 3) + 3 )
#define N_E3 (0x600C + (12 * 3) + 4 )
#define N_F3 (0x600C + (12 * 3) + 5 )
#define N_F3S (0x600C + (12 * 3) + 6 )
#define N_G3F (0x600C + (12 * 3) + 6 )
#define N_G3 (0x600C + (12 * 3) + 7 )
#define N_G3S (0x600C + (12 * 3) + 8 )
#define N_A3F (0x600C + (12 * 3) + 8 )
#define N_A3 (0x600C + (12 * 3) + 9 )
#define N_A3S (0x600C + (12 * 3) + 10)
#define N_B3F (0x600C + (12 * 3) + 10)
#define N_B3 (0x600C + (12 * 3) + 11)
#define N_C4 (0x600C + (12 * 4) + 0 )
#define N_C4S (0x600C + (12 * 4) + 1 )
#define N_D4F (0x600C + (12 * 4) + 1 )
#define N_D4 (0x600C + (12 * 4) + 2 )
#define N_D4S (0x600C + (12 * 4) + 3 )
#define N_E4F (0x600C + (12 * 4) + 3 )
#define N_E4 (0x600C + (12 * 4) + 4 )
#define N_F4 (0x600C + (12 * 4) + 5 )
#define N_F4S (0x600C + (12 * 4) + 6 )
#define N_G4F (0x600C + (12 * 4) + 6 )
#define N_G4 (0x600C + (12 * 4) + 7 )
#define N_G4S (0x600C + (12 * 4) + 8 )
#define N_A4F (0x600C + (12 * 4) + 8 )
#define N_A4 (0x600C + (12 * 4) + 9 )
#define N_A4S (0x600C + (12 * 4) + 10)
#define N_B4F (0x600C + (12 * 4) + 10)
#define N_B4 (0x600C + (12 * 4) + 11)
#define N_C5 (0x600C + (12 * 5) + 0 )
#define N_C5S (0x600C + (12 * 5) + 1 )
#define N_D5F (0x600C + (12 * 5) + 1 )
#define N_D5 (0x600C + (12 * 5) + 2 )
#define N_D5S (0x600C + (12 * 5) + 3 )
#define N_E5F (0x600C + (12 * 5) + 3 )
#define N_E5 (0x600C + (12 * 5) + 4 )
#define N_F5 (0x600C + (12 * 5) + 5 )
#define N_F5S (0x600C + (12 * 5) + 6 )
#define N_G5F (0x600C + (12 * 5) + 6 )
#define N_G5 (0x600C + (12 * 5) + 7 )
#define N_G5S (0x600C + (12 * 5) + 8 )
#define N_A5F (0x600C + (12 * 5) + 8 )
#define N_A5 (0x600C + (12 * 5) + 9 )
#define N_A5S (0x600C + (12 * 5) + 10)
#define N_B5F (0x600C + (12 * 5) + 10)
#define N_B5 (0x600C + (12 * 5) + 11)
#define N_C6 (0x600C + (12 * 6) + 0 )
#define N_C6S (0x600C + (12 * 6) + 1 )
#define N_D6F (0x600C + (12 * 6) + 1 )
#define N_D6 (0x600C + (12 * 6) + 2 )
#define N_D6S (0x600C + (12 * 6) + 3 )
#define N_E6F (0x600C + (12 * 6) + 3 )
#define N_E6 (0x600C + (12 * 6) + 4 )
#define N_F6 (0x600C + (12 * 6) + 5 )
#define N_F6S (0x600C + (12 * 6) + 6 )
#define N_G6F (0x600C + (12 * 6) + 6 )
#define N_G6 (0x600C + (12 * 6) + 7 )
#define N_G6S (0x600C + (12 * 6) + 8 )
#define N_A6F (0x600C + (12 * 6) + 8 )
#define N_A6 (0x600C + (12 * 6) + 9 )
#define N_A6S (0x600C + (12 * 6) + 10)
#define N_B6F (0x600C + (12 * 6) + 10)
#define N_B6 (0x600C + (12 * 6) + 11)
#define N_C7 (0x600C + (12 * 7) + 0 )
#define N_C7S (0x600C + (12 * 7) + 1 )
#define N_D7F (0x600C + (12 * 7) + 1 )
#define N_D7 (0x600C + (12 * 7) + 2 )
#define N_D7S (0x600C + (12 * 7) + 3 )
#define N_E7F (0x600C + (12 * 7) + 3 )
#define N_E7 (0x600C + (12 * 7) + 4 )
#define N_F7 (0x600C + (12 * 7) + 5 )
#define N_F7S (0x600C + (12 * 7) + 6 )
#define N_G7F (0x600C + (12 * 7) + 6 )
#define N_G7 (0x600C + (12 * 7) + 7 )
#define N_G7S (0x600C + (12 * 7) + 8 )
#define N_A7F (0x600C + (12 * 7) + 8 )
#define N_A7 (0x600C + (12 * 7) + 9 )
#define N_A7S (0x600C + (12 * 7) + 10)
#define N_B7F (0x600C + (12 * 7) + 10)
#define N_B7 (0x600C + (12 * 7) + 11)
#define N_C8 (0x600C + (12 * 8) + 0 )
#define N_C8S (0x600C + (12 * 8) + 1 )
#define N_D8F (0x600C + (12 * 8) + 1 )
#define N_D8 (0x600C + (12 * 8) + 2 )
#define N_D8S (0x600C + (12 * 8) + 3 )
#define N_E8F (0x600C + (12 * 8) + 3 )
#define N_E8 (0x600C + (12 * 8) + 4 )
#define N_F8 (0x600C + (12 * 8) + 5 )
#define N_F8S (0x600C + (12 * 8) + 6 )
#define N_G8F (0x600C + (12 * 8) + 6 )
#define N_G8 (0x600C + (12 * 8) + 7 )
#define N_G8S (0x600C + (12 * 8) + 8 )
#define N_A8F (0x600C + (12 * 8) + 8 )
#define N_A8 (0x600C + (12 * 8) + 9 )
#define N_A8S (0x600C + (12 * 8) + 10)
#define N_B8F (0x600C + (12 * 8) + 10)
#define N_B8 (0x600C + (12 * 8) + 11)
#define N_C8 (0x600C + (12 * 8) + 0 )
#define N_C8S (0x600C + (12 * 8) + 1 )
#define N_D8F (0x600C + (12 * 8) + 1 )
#define N_D8 (0x600C + (12 * 8) + 2 )
#define N_D8S (0x600C + (12 * 8) + 3 )
#define N_E8F (0x600C + (12 * 8) + 3 )
#define N_E8 (0x600C + (12 * 8) + 4 )
#define N_F8 (0x600C + (12 * 8) + 5 )
#define N_F8S (0x600C + (12 * 8) + 6 )
#define N_G8F (0x600C + (12 * 8) + 6 )
#define N_G8 (0x600C + (12 * 8) + 7 )
#define N_G8S (0x600C + (12 * 8) + 8 )
#define N_A8F (0x600C + (12 * 8) + 8 )
#define N_A8 (0x600C + (12 * 8) + 9 )
#define N_A8S (0x600C + (12 * 8) + 10)
#define N_B8F (0x600C + (12 * 8) + 10)
#define N_B8 (0x600C + (12 * 8) + 11)

#endif

+ 48
- 0
quantum/led.c View File

@@ -0,0 +1,48 @@
/*
Copyright 2012 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 <avr/io.h>
#include "stdint.h"
#include "led.h"

__attribute__ ((weak))
void led_set_kb(uint8_t usb_led) {

}

__attribute__ ((weak))
void led_set(uint8_t usb_led)
{

// Example LED Code
//
// // Using PE6 Caps Lock LED
// if (usb_led & (1<<USB_LED_CAPS_LOCK))
// {
// // Output high.
// DDRE |= (1<<6);
// PORTE |= (1<<6);
// }
// else
// {
// // Output low.
// DDRE &= ~(1<<6);
// PORTE &= ~(1<<6);
// }

led_set_kb(usb_led);
}

+ 181
- 0
quantum/light_ws2812.c View File

@@ -0,0 +1,181 @@
/*
* light weight WS2812 lib V2.0b
*
* Controls WS2811/WS2812/WS2812B RGB-LEDs
* Author: Tim ([email protected])
*
* Jan 18th, 2014 v2.0b Initial Version
* Nov 29th, 2015 v2.3 Added SK6812RGBW support
*
* License: GNU GPL v2 (see License.txt)
*/

#include "light_ws2812.h"
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
#include "debug.h"

// Setleds for standard RGB
void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds)
{
ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
}

void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask)
{
ws2812_DDRREG |= pinmask; // Enable DDR
ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask);
_delay_us(50);
}

// Setleds for SK6812RGBW
void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds)
{
ws2812_DDRREG |= _BV(ws2812_pin); // Enable DDR
ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(ws2812_pin));
_delay_us(80);
}

void ws2812_sendarray(uint8_t *data,uint16_t datlen)
{
ws2812_sendarray_mask(data,datlen,_BV(ws2812_pin));
}

/*
This routine writes an array of bytes with RGB values to the Dataout pin
using the fast 800kHz clockless WS2811/2812 protocol.
*/

// Timing in ns
#define w_zeropulse 350
#define w_onepulse 900
#define w_totalperiod 1250

// Fixed cycles used by the inner loop
#define w_fixedlow 2
#define w_fixedhigh 4
#define w_fixedtotal 8

// Insert NOPs to match the timing, if possible
#define w_zerocycles (((F_CPU/1000)*w_zeropulse )/1000000)
#define w_onecycles (((F_CPU/1000)*w_onepulse +500000)/1000000)
#define w_totalcycles (((F_CPU/1000)*w_totalperiod +500000)/1000000)

// w1 - nops between rising edge and falling edge - low
#define w1 (w_zerocycles-w_fixedlow)
// w2 nops between fe low and fe high
#define w2 (w_onecycles-w_fixedhigh-w1)
// w3 nops to complete loop
#define w3 (w_totalcycles-w_fixedtotal-w1-w2)

#if w1>0
#define w1_nops w1
#else
#define w1_nops 0
#endif

// The only critical timing parameter is the minimum pulse length of the "0"
// Warn or throw error if this timing can not be met with current F_CPU settings.
#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000)
#if w_lowtime>550
#error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
#elif w_lowtime>450
#warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
#warning "Please consider a higher clockspeed, if possible"
#endif

#if w2>0
#define w2_nops w2
#else
#define w2_nops 0
#endif

#if w3>0
#define w3_nops w3
#else
#define w3_nops 0
#endif

#define w_nop1 "nop \n\t"
#define w_nop2 "rjmp .+0 \n\t"
#define w_nop4 w_nop2 w_nop2
#define w_nop8 w_nop4 w_nop4
#define w_nop16 w_nop8 w_nop8

void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
{
uint8_t curbyte,ctr,masklo;
uint8_t sreg_prev;

masklo =~maskhi&ws2812_PORTREG;
maskhi |= ws2812_PORTREG;
sreg_prev=SREG;
cli();

while (datlen--) {
curbyte=*data++;

asm volatile(
" ldi %0,8 \n\t"
"loop%=: \n\t"
" out %2,%3 \n\t" // '1' [01] '0' [01] - re
#if (w1_nops&1)
w_nop1
#endif
#if (w1_nops&2)
w_nop2
#endif
#if (w1_nops&4)
w_nop4
#endif
#if (w1_nops&8)
w_nop8
#endif
#if (w1_nops&16)
w_nop16
#endif
" sbrs %1,7 \n\t" // '1' [03] '0' [02]
" out %2,%4 \n\t" // '1' [--] '0' [03] - fe-low
" lsl %1 \n\t" // '1' [04] '0' [04]
#if (w2_nops&1)
w_nop1
#endif
#if (w2_nops&2)
w_nop2
#endif
#if (w2_nops&4)
w_nop4
#endif
#if (w2_nops&8)
w_nop8
#endif
#if (w2_nops&16)
w_nop16
#endif
" out %2,%4 \n\t" // '1' [+1] '0' [+1] - fe-high
#if (w3_nops&1)
w_nop1
#endif
#if (w3_nops&2)
w_nop2
#endif
#if (w3_nops&4)
w_nop4
#endif
#if (w3_nops&8)
w_nop8
#endif
#if (w3_nops&16)
w_nop16
#endif

" dec %0 \n\t" // '1' [+2] '0' [+2]
" brne loop%=\n\t" // '1' [+3] '0' [+4]
: "=&d" (ctr)
: "r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo)
);
}

SREG=sreg_prev;
}

+ 73
- 0
quantum/light_ws2812.h View File

@@ -0,0 +1,73 @@
/*
* light weight WS2812 lib include
*
* Version 2.3 - Nev 29th 2015
* Author: Tim ([email protected])
*
* Please do not change this file! All configuration is handled in "ws2812_config.h"
*
* License: GNU GPL v2 (see License.txt)
+
*/

#ifndef LIGHT_WS2812_H_
#define LIGHT_WS2812_H_

#include <avr/io.h>
#include <avr/interrupt.h>
//#include "ws2812_config.h"

/*
* Structure of the LED array
*
* cRGB: RGB for WS2812S/B/C/D, SK6812, SK6812Mini, SK6812WWA, APA104, APA106
* cRGBW: RGBW for SK6812RGBW
*/

struct cRGB { uint8_t g; uint8_t r; uint8_t b; };
struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;};



/* User Interface
*
* Input:
* ledarray: An array of GRB data describing the LED colors
* number_of_leds: The number of LEDs to write
* pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0)
*
* The functions will perform the following actions:
* - Set the data-out pin as output
* - Send out the LED data
* - Wait 50�s to reset the LEDs
*/

void ws2812_setleds (struct cRGB *ledarray, uint16_t number_of_leds);
void ws2812_setleds_pin (struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask);
void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t number_of_leds);

/*
* Old interface / Internal functions
*
* The functions take a byte-array and send to the data output as WS2812 bitstream.
* The length is the number of bytes to send - three per LED.
*/

void ws2812_sendarray (uint8_t *array,uint16_t length);
void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask);


/*
* Internal defines
*/
#ifndef CONCAT
#define CONCAT(a, b) a ## b
#endif
#ifndef CONCAT_EXP
#define CONCAT_EXP(a, b) CONCAT(a, b)
#endif

// #define ws2812_PORTREG CONCAT_EXP(PORT,ws2812_port)
// #define ws2812_DDRREG CONCAT_EXP(DDR,ws2812_port)

#endif /* LIGHT_WS2812_H_ */

+ 227
- 0
quantum/matrix.c View File

@@ -0,0 +1,227 @@
/*
Copyright 2012 Jun Wako
Copyright 2014 Jack Humbert

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include "wait.h"
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"

#ifdef MATRIX_HAS_GHOST
# error "The universal matrix.c file cannot be used for this keyboard."
#endif

#ifndef DEBOUNCING_DELAY
# define DEBOUNCING_DELAY 5
#endif

static const io_pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
static const io_pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
/* matrix state */
#if DIODE_DIRECTION == COL2ROW
static matrix_row_t matrix[MATRIX_ROWS];
#else
static matrix_col_t matrix[MATRIX_COLS];
#endif
static int8_t debouncing_delay = -1;

#if DIODE_DIRECTION == COL2ROW
static void toggle_row(uint8_t row);
static matrix_row_t read_cols(void);
#else
static void toggle_col(uint8_t col);
static matrix_col_t read_rows(void);
#endif

__attribute__ ((weak))
void matrix_init_quantum(void) {
}

__attribute__ ((weak))
void matrix_scan_quantum(void) {
}

uint8_t matrix_rows(void) {
return MATRIX_ROWS;
}

uint8_t matrix_cols(void) {
return MATRIX_COLS;
}

void matrix_init(void) {
/* frees PORTF by setting the JTD bit twice within four cycles */
#ifdef __AVR_ATmega32U4__
MCUCR |= _BV(JTD);
MCUCR |= _BV(JTD);
#endif
/* initializes the I/O pins */
#if DIODE_DIRECTION == COL2ROW
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
/* DDRxn */
_SFR_IO8(row_pins[r].input_addr + 1) |= _BV(row_pins[r].bit);
toggle_row(r);
}
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* PORTxn */
_SFR_IO8(col_pins[c].input_addr + 2) |= _BV(col_pins[c].bit);
}
#else
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* DDRxn */
_SFR_IO8(col_pins[c].input_addr + 1) |= _BV(col_pins[c].bit);
toggle_col(c);
}
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
/* PORTxn */
_SFR_IO8(row_pins[r].input_addr + 2) |= _BV(row_pins[r].bit);
}
#endif
matrix_init_quantum();
}

#if DIODE_DIRECTION == COL2ROW
uint8_t matrix_scan(void) {
static matrix_row_t debouncing_matrix[MATRIX_ROWS];
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
toggle_row(r);
matrix_row_t state = read_cols();
if (debouncing_matrix[r] != state) {
debouncing_matrix[r] = state;
debouncing_delay = DEBOUNCING_DELAY;
}
toggle_row(r);
}
if (debouncing_delay >= 0) {
dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
--debouncing_delay;
if (debouncing_delay >= 0) {
wait_ms(1);
}
else {
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
matrix[r] = debouncing_matrix[r];
}
}
}
matrix_scan_quantum();
return 1;
}

static void toggle_row(uint8_t row) {
/* PINxn */
_SFR_IO8(row_pins[row].input_addr) = _BV(row_pins[row].bit);
}

static matrix_row_t read_cols(void) {
matrix_row_t state = 0;
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
/* PINxn */
if (!(_SFR_IO8(col_pins[c].input_addr) & _BV(col_pins[c].bit))) {
state |= (matrix_row_t)1 << c;
}
}
return state;
}

matrix_row_t matrix_get_row(uint8_t row) {
return matrix[row];
}

#else
uint8_t matrix_scan(void) {
static matrix_col_t debouncing_matrix[MATRIX_COLS];
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
toggle_col(c);
matrix_col_t state = read_rows();
if (debouncing_matrix[c] != state) {
debouncing_matrix[c] = state;
debouncing_delay = DEBOUNCING_DELAY;
}
toggle_col(c);
}
if (debouncing_delay >= 0) {
dprintf("Debouncing delay remaining: %X\n", debouncing_delay);
--debouncing_delay;
if (debouncing_delay >= 0) {
wait_ms(1);
}
else {
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
matrix[c] = debouncing_matrix[c];
}
}
}
matrix_scan_quantum();
return 1;
}

static void toggle_col(uint8_t col) {
/* PINxn */
_SFR_IO8(col_pins[col].input_addr) = _BV(col_pins[col].bit);
}

static matrix_col_t read_rows(void) {
matrix_col_t state = 0;
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
/* PINxn */
if (!(_SFR_IO8(row_pins[r].input_addr) & _BV(row_pins[r].bit))) {
state |= (matrix_col_t)1 << r;
}
}
return state;
}

matrix_row_t matrix_get_row(uint8_t row) {
matrix_row_t state = 0;
matrix_col_t mask = (matrix_col_t)1 << row;
for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) {
if (matrix[c] & mask) {
state |= (matrix_row_t)1 << c;
}
}
return state;
}

#endif

bool matrix_is_modified(void) {
if (debouncing_delay >= 0) return false;
return true;
}

bool matrix_is_on(uint8_t row, uint8_t col) {
return matrix_get_row(row) & (matrix_row_t)1 << col;
}

void matrix_print(void) {
dprintln("Human-readable matrix state:");
for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r)));
}
}

uint8_t matrix_key_count(void) {
uint8_t count = 0;
for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) {
count += bitpop16(matrix_get_row(r));
}
return count;
}

+ 642
- 0
quantum/quantum.c View File

@@ -0,0 +1,642 @@
#include "quantum.h"
#include "timer.h"

__attribute__ ((weak))
void matrix_init_kb(void) {}

__attribute__ ((weak))
void matrix_scan_kb(void) {}

__attribute__ ((weak))
bool process_action_kb(keyrecord_t *record) {
return true;
}

__attribute__ ((weak))
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
return process_record_user(keycode, record);
}

__attribute__ ((weak))
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
return true;
}

__attribute__ ((weak))
void leader_start(void) {}

__attribute__ ((weak))
void leader_end(void) {}

uint8_t starting_note = 0x0C;
int offset = 7;


#ifdef AUDIO_ENABLE
bool music_activated = false;

// music sequencer
static bool music_sequence_recording = false;
static bool music_sequence_playing = false;
static float music_sequence[16] = {0};
static uint8_t music_sequence_count = 0;
static uint8_t music_sequence_position = 0;

static uint16_t music_sequence_timer = 0;
static uint16_t music_sequence_interval = 100;

#endif

#ifdef MIDI_ENABLE
bool midi_activated = false;
#endif

// Leader key stuff
bool leading = false;
uint16_t leader_time = 0;

uint16_t leader_sequence[3] = {0, 0, 0};
uint8_t leader_sequence_size = 0;

// Chording stuff
#define CHORDING_MAX 4
bool chording = false;

uint8_t chord_keys[CHORDING_MAX] = {0};
uint8_t chord_key_count = 0;
uint8_t chord_key_down = 0;

#ifdef UNICODE_ENABLE
static uint8_t input_mode;
#endif

static bool shift_interrupted[2] = {0, 0};

bool keys_chord(uint8_t keys[]) {
uint8_t keys_size = sizeof(keys)/sizeof(keys[0]);
bool pass = true;
uint8_t in = 0;
for (uint8_t i = 0; i < chord_key_count; i++) {
bool found = false;
for (uint8_t j = 0; j < keys_size; j++) {
if (chord_keys[i] == (keys[j] & 0xFF)) {
in++; // detects key in chord
found = true;
break;
}
}
if (found)
continue;
if (chord_keys[i] != 0) {
pass = false; // makes sure rest are blank
}
}
return (pass && (in == keys_size));
}

#ifdef UNICODE_ENABLE

uint16_t hex_to_keycode(uint8_t hex)
{
if (hex == 0x0) {
return KC_0;
} else if (hex < 0xA) {
return KC_1 + (hex - 0x1);
} else {
return KC_A + (hex - 0xA);
}
}

void set_unicode_mode(uint8_t os_target)
{
input_mode = os_target;
}

#endif

bool process_record_quantum(keyrecord_t *record) {

/* This gets the keycode from the key pressed */
keypos_t key = record->event.key;
uint16_t keycode;

#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
uint8_t layer;

if (record->event.pressed) {
layer = layer_switch_get_layer(key);
update_source_layers_cache(key, layer);
} else {
layer = read_source_layers_cache(key);
}
keycode = keymap_key_to_keycode(layer, key);
#else
keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key);
#endif

if (!process_record_kb(keycode, record))
return false;

// This is how you use actions here
// if (keycode == KC_LEAD) {
// action_t action;
// action.code = ACTION_DEFAULT_LAYER_SET(0);
// process_action(record, action);
// return false;
// }

#ifdef MIDI_ENABLE
if (keycode == MI_ON && record->event.pressed) {
midi_activated = true;
music_scale_user();
return false;
}

if (keycode == MI_OFF && record->event.pressed) {
midi_activated = false;
midi_send_cc(&midi_device, 0, 0x7B, 0);
return false;
}

if (midi_activated) {
if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) {
starting_note++; // Change key
midi_send_cc(&midi_device, 0, 0x7B, 0);
// midi_send_cc(&midi_device, 1, 0x7B, 0);
// midi_send_cc(&midi_device, 2, 0x7B, 0);
// midi_send_cc(&midi_device, 3, 0x7B, 0);
// midi_send_cc(&midi_device, 4, 0x7B, 0);
}
return false;
}
if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) {
if (record->event.pressed) {
starting_note--; // Change key
midi_send_cc(&midi_device, 0, 0x7B, 0);
// midi_send_cc(&midi_device, 1, 0x7B, 0);
// midi_send_cc(&midi_device, 2, 0x7B, 0);
// midi_send_cc(&midi_device, 3, 0x7B, 0);
// midi_send_cc(&midi_device, 4, 0x7B, 0);
}
return false;
}
if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
offset++; // Change scale
midi_send_cc(&midi_device, 0, 0x7B, 0);
// midi_send_cc(&midi_device, 1, 0x7B, 0);
// midi_send_cc(&midi_device, 2, 0x7B, 0);
// midi_send_cc(&midi_device, 3, 0x7B, 0);
// midi_send_cc(&midi_device, 4, 0x7B, 0);
return false;
}
if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) {
offset--; // Change scale
midi_send_cc(&midi_device, 0, 0x7B, 0);
// midi_send_cc(&midi_device, 1, 0x7B, 0);
// midi_send_cc(&midi_device, 2, 0x7B, 0);
// midi_send_cc(&midi_device, 3, 0x7B, 0);
// midi_send_cc(&midi_device, 4, 0x7B, 0);
return false;
}
// basic
// uint8_t note = (starting_note + SCALE[record->event.key.col + offset])+12*(MATRIX_ROWS - record->event.key.row);
// advanced
// uint8_t note = (starting_note + record->event.key.col + offset)+12*(MATRIX_ROWS - record->event.key.row);
// guitar
uint8_t note = (starting_note + record->event.key.col + offset)+5*(MATRIX_ROWS - record->event.key.row);
// violin
// uint8_t note = (starting_note + record->event.key.col + offset)+7*(MATRIX_ROWS - record->event.key.row);

if (record->event.pressed) {
// midi_send_noteon(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
midi_send_noteon(&midi_device, 0, note, 127);
} else {
// midi_send_noteoff(&midi_device, record->event.key.row, starting_note + SCALE[record->event.key.col], 127);
midi_send_noteoff(&midi_device, 0, note, 127);
}

if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
return false;
}
#endif

#ifdef AUDIO_ENABLE
if (keycode == AU_ON && record->event.pressed) {
audio_on();
return false;
}

if (keycode == AU_OFF && record->event.pressed) {
audio_off();
return false;
}

if (keycode == AU_TOG && record->event.pressed) {
if (is_audio_on())
{
audio_off();
}
else
{
audio_on();
}
return false;
}

if (keycode == MU_ON && record->event.pressed) {
music_on();
return false;
}

if (keycode == MU_OFF && record->event.pressed) {
music_off();
return false;
}

if (keycode == MU_TOG && record->event.pressed) {
if (music_activated)
{
music_off();
}
else
{
music_on();
}
return false;
}

if (keycode == MUV_IN && record->event.pressed) {
voice_iterate();
music_scale_user();
return false;
}

if (keycode == MUV_DE && record->event.pressed) {
voice_deiterate();
music_scale_user();
return false;
}

if (music_activated) {

if (keycode == KC_LCTL && record->event.pressed) { // Start recording
stop_all_notes();
music_sequence_recording = true;
music_sequence_playing = false;
music_sequence_count = 0;
return false;
}

if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
stop_all_notes();
music_sequence_recording = false;
music_sequence_playing = false;
return false;
}

if (keycode == KC_LGUI && record->event.pressed) { // Start playing
stop_all_notes();
music_sequence_recording = false;
music_sequence_playing = true;
music_sequence_position = 0;
music_sequence_timer = 0;
return false;
}

if (keycode == KC_UP) {
if (record->event.pressed)
music_sequence_interval-=10;
return false;
}

if (keycode == KC_DOWN) {
if (record->event.pressed)
music_sequence_interval+=10;
return false;
}

float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row));
if (record->event.pressed) {
play_note(freq, 0xF);
if (music_sequence_recording) {
music_sequence[music_sequence_count] = freq;
music_sequence_count++;
}
} else {
stop_note(freq);
}

if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
return false;
}
#endif

#ifndef DISABLE_LEADER
// Leader key set-up
if (record->event.pressed) {
if (!leading && keycode == KC_LEAD) {
leader_start();
leading = true;
leader_time = timer_read();
leader_sequence_size = 0;
leader_sequence[0] = 0;
leader_sequence[1] = 0;
leader_sequence[2] = 0;
return false;
}
if (leading && timer_elapsed(leader_time) < LEADER_TIMEOUT) {
leader_sequence[leader_sequence_size] = keycode;
leader_sequence_size++;
return false;
}
}
#endif

#define DISABLE_CHORDING
#ifndef DISABLE_CHORDING

if (keycode >= 0x5700 && keycode <= 0x57FF) {
if (record->event.pressed) {
if (!chording) {
chording = true;
for (uint8_t i = 0; i < CHORDING_MAX; i++)
chord_keys[i] = 0;
chord_key_count = 0;
chord_key_down = 0;
}
chord_keys[chord_key_count] = (keycode & 0xFF);
chord_key_count++;
chord_key_down++;
return false;
} else {
if (chording) {
chord_key_down--;
if (chord_key_down == 0) {
chording = false;
// Chord Dictionary
if (keys_chord((uint8_t[]){KC_ENTER, KC_SPACE})) {
register_code(KC_A);
unregister_code(KC_A);
return false;
}
for (uint8_t i = 0; i < chord_key_count; i++) {
register_code(chord_keys[i]);
unregister_code(chord_keys[i]);
return false;
}
}
}
}
}

#endif

#ifdef UNICODE_ENABLE

if (keycode > UNICODE(0) && record->event.pressed) {
uint16_t unicode = keycode & 0x7FFF;
switch(input_mode) {
case UC_OSX:
register_code(KC_LALT);
break;
case UC_LNX:
register_code(KC_LCTL);
register_code(KC_LSFT);
register_code(KC_U);
unregister_code(KC_U);
break;
case UC_WIN:
register_code(KC_LALT);
register_code(KC_PPLS);
unregister_code(KC_PPLS);
break;
}
for(int i = 3; i >= 0; i--) {
uint8_t digit = ((unicode >> (i*4)) & 0xF);
register_code(hex_to_keycode(digit));
unregister_code(hex_to_keycode(digit));
}
switch(input_mode) {
case UC_OSX:
case UC_WIN:
unregister_code(KC_LALT);
break;
case UC_LNX:
unregister_code(KC_LCTL);
unregister_code(KC_LSFT);
break;
}
}

#endif

switch(keycode) {
case KC_LSPO: {
if (record->event.pressed) {
shift_interrupted[0] = false;
register_mods(MOD_BIT(KC_LSFT));
}
else {
if (!shift_interrupted[0]) {
register_code(KC_9);
unregister_code(KC_9);
}
unregister_mods(MOD_BIT(KC_LSFT));
}
return false;
break;
}

case KC_RSPC: {
if (record->event.pressed) {
shift_interrupted[1] = false;
register_mods(MOD_BIT(KC_RSFT));
}
else {
if (!shift_interrupted[1]) {
register_code(KC_0);
unregister_code(KC_0);
}
unregister_mods(MOD_BIT(KC_RSFT));
}
return false;
break;
}
default: {
shift_interrupted[0] = true;
shift_interrupted[1] = true;
break;
}
}

return process_action_kb(record);
}

const bool ascii_to_qwerty_shift_lut[0x80] PROGMEM = {
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, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 1, 1,
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, 1, 1, 1, 1, 0
};

const uint8_t ascii_to_qwerty_keycode_lut[0x80] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0,
KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, KC_ESC, 0, 0, 0, 0,
KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
KC_8, KC_9, KC_SCLN, KC_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
KC_GRV, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
};

/* for users whose OSes are set to Colemak */
#if 0
#include "keymap_colemak.h"

const bool ascii_to_colemak_shift_lut[0x80] PROGMEM = {
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, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 0, 0, 0, 1, 1,
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, 1, 1, 1, 1, 0
};

const uint8_t ascii_to_colemak_keycode_lut[0x80] PROGMEM = {
0, 0, 0, 0, 0, 0, 0, 0,
KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, KC_ESC, 0, 0, 0, 0,
KC_SPC, KC_1, KC_QUOT, KC_3, KC_4, KC_5, KC_7, KC_QUOT,
KC_9, KC_0, KC_8, KC_EQL, KC_COMM, KC_MINS, KC_DOT, KC_SLSH,
KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
KC_8, KC_9, CM_SCLN, CM_SCLN, KC_COMM, KC_EQL, KC_DOT, KC_SLSH,
KC_2, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_6, KC_MINS,
KC_GRV, CM_A, CM_B, CM_C, CM_D, CM_E, CM_F, CM_G,
CM_H, CM_I, CM_J, CM_K, CM_L, CM_M, CM_N, CM_O,
CM_P, CM_Q, CM_R, CM_S, CM_T, CM_U, CM_V, CM_W,
CM_X, CM_Y, CM_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
};

#endif

void send_string(const char *str) {
while (1) {
uint8_t keycode;
uint8_t ascii_code = pgm_read_byte(str);
if (!ascii_code) break;
keycode = pgm_read_byte(&ascii_to_qwerty_keycode_lut[ascii_code]);
if (pgm_read_byte(&ascii_to_qwerty_shift_lut[ascii_code])) {
register_code(KC_LSFT);
register_code(keycode);
unregister_code(keycode);
unregister_code(KC_LSFT);
}
else {
register_code(keycode);
unregister_code(keycode);
}
++str;
}
}


void matrix_init_quantum() {
matrix_init_kb();
}

void matrix_scan_quantum() {
#ifdef AUDIO_ENABLE
if (music_sequence_playing) {
if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) {
music_sequence_timer = timer_read();
stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]);
play_note(music_sequence[music_sequence_position], 0xF);
music_sequence_position = (music_sequence_position + 1) % music_sequence_count;
}
}

#endif

matrix_scan_kb();
}
#ifdef AUDIO_ENABLE
bool is_music_on(void) {
return (music_activated != 0);
}

void music_toggle(void) {
if (!music_activated) {
music_on();
} else {
music_off();
}
}

void music_on(void) {
music_activated = 1;
music_on_user();
}

void music_off(void) {
music_activated = 0;
stop_all_notes();
}

#endif

//------------------------------------------------------------------------------
// Override these functions in your keymap file to play different tunes on
// different events such as startup and bootloader jump

__attribute__ ((weak))
void startup_user() {}

__attribute__ ((weak))
void shutdown_user() {}

__attribute__ ((weak))
void music_on_user() {}

__attribute__ ((weak))
void audio_on_user() {}

__attribute__ ((weak))
void music_scale_user() {}

//------------------------------------------------------------------------------

+ 85
- 0
quantum/quantum.h View File

@@ -0,0 +1,85 @@
#ifndef QUANTUM_H
#define QUANTUM_H

#include <avr/pgmspace.h>
#include "matrix.h"
#include "keymap_common.h"
#ifdef BACKLIGHT_ENABLE
#include "backlight.h"
#endif
#ifdef RGBLIGHT_ENABLE
#include "rgblight.h"
#endif
#ifdef AUDIO_ENABLE
#include "audio.h"
#endif
#ifdef MIDI_ENABLE
#include <lufa.h>
#endif
#ifdef UNICODE_ENABLE
#include "unicode.h"
#endif

#include "action_layer.h"
#include "eeconfig.h"
#include <stddef.h>
#include <avr/io.h>
#include <util/delay.h>

#define SEND_STRING(str) send_string(PSTR(str))

extern uint32_t default_layer_state;

#ifndef NO_ACTION_LAYER
extern uint32_t layer_state;
#endif

#ifdef AUDIO_ENABLE
bool music_activated;
#endif

#ifdef UNICODE_ENABLE
#define UC_OSX 0
#define UC_LNX 1
#define UC_WIN 2
#define UC_BSD 3

void set_unicode_input_mode(uint8_t os_target);
#endif

#ifndef DISABLE_LEADER
void leader_start(void);
void leader_end(void);

#ifndef LEADER_TIMEOUT
#define LEADER_TIMEOUT 200
#endif
#define SEQ_ONE_KEY(key) if (leader_sequence[0] == (key) && leader_sequence[1] == 0 && leader_sequence[2] == 0)
#define SEQ_TWO_KEYS(key1, key2) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == 0)
#define SEQ_THREE_KEYS(key1, key2, key3) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3))

#define LEADER_EXTERNS() extern bool leading; extern uint16_t leader_time; extern uint16_t leader_sequence[3]; extern uint8_t leader_sequence_size
#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT)
#endif

void send_string(const char *str);

void matrix_init_kb(void);
void matrix_scan_kb(void);
bool process_action_kb(keyrecord_t *record);
bool process_record_kb(uint16_t keycode, keyrecord_t *record);
bool process_record_user(uint16_t keycode, keyrecord_t *record);


bool is_music_on(void);
void music_toggle(void);
void music_on(void);
void music_off(void);

void startup_user(void);
void shutdown_user(void);
void audio_on_user(void);
void music_on_user(void);
void music_scale_user(void);

#endif

+ 58
- 0
quantum/quantum.mk View File

@@ -0,0 +1,58 @@
QUANTUM_DIR = quantum

ifndef VERBOSE
.SILENT:
endif

# # project specific files
SRC += $(QUANTUM_DIR)/quantum.c \
$(QUANTUM_DIR)/keymap_common.c \
$(QUANTUM_DIR)/led.c

# ifdef KEYMAP_FILE
# ifneq (,$(shell grep USING_MIDI '$(KEYMAP_FILE)'))
# MIDI_ENABLE=yes
# $(info * Overriding MIDI_ENABLE setting - $(KEYMAP_FILE) requires it)
# endif
# ifneq (,$(shell grep USING_UNICODE '$(KEYMAP_FILE)'))
# UNICODE_ENABLE=yes
# $(info * Overriding UNICODE_ENABLE setting - $(KEYMAP_FILE) requires it)
# endif
# ifneq (,$(shell grep USING_BACKLIGHT '$(KEYMAP_FILE)'))
# BACKLIGHT_ENABLE=yes
# $(info * Overriding BACKLIGHT_ENABLE setting - $(KEYMAP_FILE) requires it)
# endif
# endif

ifndef CUSTOM_MATRIX
SRC += $(QUANTUM_DIR)/matrix.c
endif

#ifeq ($(strip $(MIDI_ENABLE)), yes)
# SRC += $(QUANTUM_DIR)/keymap_midi.c
#endif

ifeq ($(strip $(AUDIO_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/audio/audio.c
SRC += $(QUANTUM_DIR)/audio/voices.c
SRC += $(QUANTUM_DIR)/audio/luts.c
endif

ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/light_ws2812.c
SRC += $(QUANTUM_DIR)/rgblight.c
OPT_DEFS += -DRGBLIGHT_ENABLE
endif

# Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax

# Search Path
VPATH += $(TOP_DIR)/$(QUANTUM_DIR)
VPATH += $(TOP_DIR)/$(QUANTUM_DIR)/keymap_extras
VPATH += $(TOP_DIR)/$(QUANTUM_DIR)/audio

include $(TMK_DIR)/protocol/lufa.mk

include $(TMK_DIR)/common.mk
include $(TMK_DIR)/rules.mk

+ 505
- 0
quantum/rgblight.c View File

@@ -0,0 +1,505 @@
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "progmem.h"
#include "timer.h"
#include "rgblight.h"
#include "debug.h"

const uint8_t DIM_CURVE[] PROGMEM = {
0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11,
11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15,
15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20,
20, 20, 21, 21, 22, 22, 22, 23, 23, 24, 24, 25, 25, 25, 26, 26,
27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 33, 33, 34, 35, 35,
36, 36, 37, 38, 38, 39, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47,
48, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
63, 64, 65, 66, 68, 69, 70, 71, 73, 74, 75, 76, 78, 79, 81, 82,
83, 85, 86, 88, 90, 91, 93, 94, 96, 98, 99, 101, 103, 105, 107, 109,
110, 112, 114, 116, 118, 121, 123, 125, 127, 129, 132, 134, 136, 139, 141, 144,
146, 149, 151, 154, 157, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 190,
193, 196, 200, 203, 207, 211, 214, 218, 222, 226, 230, 234, 238, 242, 248, 255,
};
const uint8_t RGBLED_BREATHING_TABLE[] PROGMEM = {0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,17,18,20,21,23,25,27,29,31,33,35,37,40,42,44,47,49,52,54,57,59,62,65,67,70,73,76,79,82,85,88,90,93,97,100,103,106,109,112,115,118,121,124,127,131,134,137,140,143,146,149,152,155,158,162,165,167,170,173,176,179,182,185,188,190,193,196,198,201,203,206,208,211,213,215,218,220,222,224,226,228,230,232,234,235,237,238,240,241,243,244,245,246,248,249,250,250,251,252,253,253,254,254,254,255,255,255,255,255,255,255,254,254,254,253,253,252,251,250,250,249,248,246,245,244,243,241,240,238,237,235,234,232,230,228,226,224,222,220,218,215,213,211,208,206,203,201,198,196,193,190,188,185,182,179,176,173,170,167,165,162,158,155,152,149,146,143,140,137,134,131,128,124,121,118,115,112,109,106,103,100,97,93,90,88,85,82,79,76,73,70,67,65,62,59,57,54,52,49,47,44,42,40,37,35,33,31,29,27,25,23,21,20,18,17,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0};
const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {100, 50, 20};

rgblight_config_t rgblight_config;
rgblight_config_t inmem_config;
struct cRGB led[RGBLED_NUM];
uint8_t rgblight_inited = 0;


void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1) {
/* convert hue, saturation and brightness ( HSB/HSV ) to RGB
The DIM_CURVE is used only on brightness/value and on saturation (inverted).
This looks the most natural.
*/
uint8_t r, g, b;

val = pgm_read_byte(&DIM_CURVE[val]);
sat = 255 - pgm_read_byte(&DIM_CURVE[255 - sat]);

uint8_t base;

if (sat == 0) { // Acromatic color (gray). Hue doesn't mind.
r = val;
g = val;
b = val;
} else {
base = ((255 - sat) * val) >> 8;

switch (hue / 60) {
case 0:
r = val;
g = (((val - base)*hue) / 60) + base;
b = base;
break;

case 1:
r = (((val - base)*(60 - (hue % 60))) / 60) + base;
g = val;
b = base;
break;

case 2:
r = base;
g = val;
b = (((val - base)*(hue % 60)) / 60) + base;
break;

case 3:
r = base;
g = (((val - base)*(60 - (hue % 60))) / 60) + base;
b = val;
break;

case 4:
r = (((val - base)*(hue % 60)) / 60) + base;
g = base;
b = val;
break;

case 5:
r = val;
g = base;
b = (((val - base)*(60 - (hue % 60))) / 60) + base;
break;
}
}
setrgb(r,g,b, led1);
}

void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1) {
(*led1).r = r;
(*led1).g = g;
(*led1).b = b;
}


uint32_t eeconfig_read_rgblight(void) {
return eeprom_read_dword(EECONFIG_RGBLIGHT);
}
void eeconfig_update_rgblight(uint32_t val) {
eeprom_update_dword(EECONFIG_RGBLIGHT, val);
}
void eeconfig_update_rgblight_default(void) {
dprintf("eeconfig_update_rgblight_default\n");
rgblight_config.enable = 1;
rgblight_config.mode = 1;
rgblight_config.hue = 200;
rgblight_config.sat = 204;
rgblight_config.val = 204;
eeconfig_update_rgblight(rgblight_config.raw);
}
void eeconfig_debug_rgblight(void) {
dprintf("rgblight_config eprom\n");
dprintf("rgblight_config.enable = %d\n", rgblight_config.enable);
dprintf("rghlight_config.mode = %d\n", rgblight_config.mode);
dprintf("rgblight_config.hue = %d\n", rgblight_config.hue);
dprintf("rgblight_config.sat = %d\n", rgblight_config.sat);
dprintf("rgblight_config.val = %d\n", rgblight_config.val);
}

void rgblight_init(void) {
debug_enable = 1; // Debug ON!
dprintf("rgblight_init called.\n");
rgblight_inited = 1;
dprintf("rgblight_init start!\n");
if (!eeconfig_is_enabled()) {
dprintf("rgblight_init eeconfig is not enabled.\n");
eeconfig_init();
eeconfig_update_rgblight_default();
}
rgblight_config.raw = eeconfig_read_rgblight();
if (!rgblight_config.mode) {
dprintf("rgblight_init rgblight_config.mode = 0. Write default values to EEPROM.\n");
eeconfig_update_rgblight_default();
rgblight_config.raw = eeconfig_read_rgblight();
}
eeconfig_debug_rgblight(); // display current eeprom values

rgblight_timer_init(); // setup the timer

if (rgblight_config.enable) {
rgblight_mode(rgblight_config.mode);
}
}

void rgblight_increase(void) {
uint8_t mode;
if (rgblight_config.mode < RGBLIGHT_MODES) {
mode = rgblight_config.mode + 1;
}
rgblight_mode(mode);
}

void rgblight_decrease(void) {
uint8_t mode;
if (rgblight_config.mode > 1) { //mode will never < 1, if mode is less than 1, eeprom need to be initialized.
mode = rgblight_config.mode-1;
}
rgblight_mode(mode);
}

void rgblight_step(void) {
uint8_t mode;
mode = rgblight_config.mode + 1;
if (mode > RGBLIGHT_MODES) {
mode = 1;
}
rgblight_mode(mode);
}

void rgblight_mode(uint8_t mode) {
if (!rgblight_config.enable) {
return;
}
if (mode<1) {
rgblight_config.mode = 1;
} else if (mode > RGBLIGHT_MODES) {
rgblight_config.mode = RGBLIGHT_MODES;
} else {
rgblight_config.mode = mode;
}
eeconfig_update_rgblight(rgblight_config.raw);
xprintf("rgblight mode: %u\n", rgblight_config.mode);
if (rgblight_config.mode == 1) {
rgblight_timer_disable();
} else if (rgblight_config.mode >=2 && rgblight_config.mode <=23) {
// MODE 2-5, breathing
// MODE 6-8, rainbow mood
// MODE 9-14, rainbow swirl
// MODE 15-20, snake
// MODE 21-23, knight
rgblight_timer_enable();
}
rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
}

void rgblight_toggle(void) {
rgblight_config.enable ^= 1;
eeconfig_update_rgblight(rgblight_config.raw);
xprintf("rgblight toggle: rgblight_config.enable = %u\n", rgblight_config.enable);
if (rgblight_config.enable) {
rgblight_mode(rgblight_config.mode);
} else {
rgblight_timer_disable();
_delay_ms(50);
rgblight_set();
}
}


void rgblight_increase_hue(void){
uint16_t hue;
hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360;
rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
}
void rgblight_decrease_hue(void){
uint16_t hue;
if (rgblight_config.hue-RGBLIGHT_HUE_STEP <0 ) {
hue = (rgblight_config.hue+360-RGBLIGHT_HUE_STEP) % 360;
} else {
hue = (rgblight_config.hue-RGBLIGHT_HUE_STEP) % 360;
}
rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
}
void rgblight_increase_sat(void) {
uint8_t sat;
if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) {
sat = 255;
} else {
sat = rgblight_config.sat+RGBLIGHT_SAT_STEP;
}
rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
}
void rgblight_decrease_sat(void){
uint8_t sat;
if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) {
sat = 0;
} else {
sat = rgblight_config.sat-RGBLIGHT_SAT_STEP;
}
rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
}
void rgblight_increase_val(void){
uint8_t val;
if (rgblight_config.val + RGBLIGHT_VAL_STEP > 255) {
val = 255;
} else {
val = rgblight_config.val+RGBLIGHT_VAL_STEP;
}
rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
}
void rgblight_decrease_val(void) {
uint8_t val;
if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) {
val = 0;
} else {
val = rgblight_config.val-RGBLIGHT_VAL_STEP;
}
rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
}

void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val){
inmem_config.raw = rgblight_config.raw;
if (rgblight_config.enable) {
struct cRGB tmp_led;
sethsv(hue, sat, val, &tmp_led);
inmem_config.hue = hue;
inmem_config.sat = sat;
inmem_config.val = val;
// dprintf("rgblight set hue [MEMORY]: %u,%u,%u\n", inmem_config.hue, inmem_config.sat, inmem_config.val);
rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
}
}
void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val){
if (rgblight_config.enable) {
if (rgblight_config.mode == 1) {
// same static color
rgblight_sethsv_noeeprom(hue, sat, val);
} else {
// all LEDs in same color
if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
// breathing mode, ignore the change of val, use in memory value instead
val = rgblight_config.val;
} else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
// rainbow mood and rainbow swirl, ignore the change of hue
hue = rgblight_config.hue;
}
}
rgblight_config.hue = hue;
rgblight_config.sat = sat;
rgblight_config.val = val;
eeconfig_update_rgblight(rgblight_config.raw);
xprintf("rgblight set hsv [EEPROM]: %u,%u,%u\n", rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
}
}

void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b){
// dprintf("rgblight set rgb: %u,%u,%u\n", r,g,b);
for (uint8_t i=0;i<RGBLED_NUM;i++) {
led[i].r = r;
led[i].g = g;
led[i].b = b;
}
rgblight_set();

}

void rgblight_set(void) {
if (rgblight_config.enable) {
ws2812_setleds(led, RGBLED_NUM);
} else {
for (uint8_t i=0;i<RGBLED_NUM;i++) {
led[i].r = 0;
led[i].g = 0;
led[i].b = 0;
}
ws2812_setleds(led, RGBLED_NUM);
}
}

// Animation timer -- AVR Timer3
void rgblight_timer_init(void) {
static uint8_t rgblight_timer_is_init = 0;
if (rgblight_timer_is_init) {
return;
}
rgblight_timer_is_init = 1;
/* Timer 3 setup */
TCCR3B = _BV(WGM32) //CTC mode OCR3A as TOP
| _BV(CS30); //Clock selelct: clk/1
/* Set TOP value */
uint8_t sreg = SREG;
cli();
OCR3AH = (RGBLED_TIMER_TOP>>8)&0xff;
OCR3AL = RGBLED_TIMER_TOP&0xff;
SREG = sreg;
}
void rgblight_timer_enable(void) {
TIMSK3 |= _BV(OCIE3A);
dprintf("TIMER3 enabled.\n");
}
void rgblight_timer_disable(void) {
TIMSK3 &= ~_BV(OCIE3A);
dprintf("TIMER3 disabled.\n");
}
void rgblight_timer_toggle(void) {
TIMSK3 ^= _BV(OCIE3A);
dprintf("TIMER3 toggled.\n");
}

ISR(TIMER3_COMPA_vect) {
// Mode = 1, static light, do nothing here
if (rgblight_config.mode>=2 && rgblight_config.mode<=5) {
// mode = 2 to 5, breathing mode
rgblight_effect_breathing(rgblight_config.mode-2);

} else if (rgblight_config.mode>=6 && rgblight_config.mode<=8) {
rgblight_effect_rainbow_mood(rgblight_config.mode-6);
} else if (rgblight_config.mode>=9 && rgblight_config.mode<=14) {
rgblight_effect_rainbow_swirl(rgblight_config.mode-9);
} else if (rgblight_config.mode>=15 && rgblight_config.mode<=20) {
rgblight_effect_snake(rgblight_config.mode-15);
} else if (rgblight_config.mode>=21 && rgblight_config.mode<=23) {
rgblight_effect_knight(rgblight_config.mode-21);
}
}

// effects
void rgblight_effect_breathing(uint8_t interval) {
static uint8_t pos = 0;
static uint16_t last_timer = 0;

if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_BREATHING_INTERVALS[interval])) return;
last_timer = timer_read();

rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, pgm_read_byte(&RGBLED_BREATHING_TABLE[pos]));
pos = (pos+1) % 256;
}

void rgblight_effect_rainbow_mood(uint8_t interval) {
static uint16_t current_hue=0;
static uint16_t last_timer = 0;

if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval])) return;
last_timer = timer_read();
rgblight_sethsv_noeeprom(current_hue, rgblight_config.sat, rgblight_config.val);
current_hue = (current_hue+1) % 360;
}

void rgblight_effect_rainbow_swirl(uint8_t interval) {
static uint16_t current_hue=0;
static uint16_t last_timer = 0;
uint16_t hue;
uint8_t i;
if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_RAINBOW_MOOD_INTERVALS[interval/2])) return;
last_timer = timer_read();
for (i=0; i<RGBLED_NUM; i++) {
hue = (360/RGBLED_NUM*i+current_hue)%360;
sethsv(hue, rgblight_config.sat, rgblight_config.val, &led[i]);
}
rgblight_set();

if (interval % 2) {
current_hue = (current_hue+1) % 360;
} else {
if (current_hue -1 < 0) {
current_hue = 359;
} else {
current_hue = current_hue - 1;
}

}
}
void rgblight_effect_snake(uint8_t interval) {
static uint8_t pos=0;
static uint16_t last_timer = 0;
uint8_t i,j;
int8_t k;
int8_t increament = 1;
if (interval%2) increament = -1;
if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_SNAKE_INTERVALS[interval/2])) return;
last_timer = timer_read();
for (i=0;i<RGBLED_NUM;i++) {
led[i].r=0;
led[i].g=0;
led[i].b=0;
for (j=0;j<RGBLIGHT_EFFECT_SNAKE_LENGTH;j++) {
k = pos+j*increament;
if (k<0) k = k+RGBLED_NUM;
if (i==k) {
sethsv(rgblight_config.hue, rgblight_config.sat, (uint8_t)(rgblight_config.val*(RGBLIGHT_EFFECT_SNAKE_LENGTH-j)/RGBLIGHT_EFFECT_SNAKE_LENGTH), &led[i]);
}
}
}
rgblight_set();
if (increament == 1) {
if (pos - 1 < 0) {
pos = RGBLED_NUM-1;
} else {
pos -= 1;
}
} else {
pos = (pos+1)%RGBLED_NUM;
}

}

void rgblight_effect_knight(uint8_t interval) {
static int8_t pos=0;
static uint16_t last_timer = 0;
uint8_t i,j,cur;
int8_t k;
struct cRGB preled[RGBLED_NUM];
static int8_t increament = -1;
if (timer_elapsed(last_timer)<pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) return;
last_timer = timer_read();
for (i=0;i<RGBLED_NUM;i++) {
preled[i].r=0;
preled[i].g=0;
preled[i].b=0;
for (j=0;j<RGBLIGHT_EFFECT_KNIGHT_LENGTH;j++) {
k = pos+j*increament;
if (k<0) k = 0;
if (k>=RGBLED_NUM) k=RGBLED_NUM-1;
if (i==k) {
sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, &preled[i]);
}
}
}
if (RGBLIGHT_EFFECT_KNIGHT_OFFSET) {
for (i=0;i<RGBLED_NUM;i++) {
cur = (i+RGBLIGHT_EFFECT_KNIGHT_OFFSET) % RGBLED_NUM;
led[i].r = preled[cur].r;
led[i].g = preled[cur].g;
led[i].b = preled[cur].b;
}
}
rgblight_set();
if (increament == 1) {
if (pos - 1 < 0 - RGBLIGHT_EFFECT_KNIGHT_LENGTH) {
pos = 0- RGBLIGHT_EFFECT_KNIGHT_LENGTH;
increament = -1;
} else {
pos -= 1;
}
} else {
if (pos+1>RGBLED_NUM+RGBLIGHT_EFFECT_KNIGHT_LENGTH) {
pos = RGBLED_NUM+RGBLIGHT_EFFECT_KNIGHT_LENGTH-1;
increament = 1;
} else {
pos += 1;
}
}

}

+ 87
- 0
quantum/rgblight.h View File

@@ -0,0 +1,87 @@
#ifndef RGBLIGHT_H
#define RGBLIGHT_H

#ifndef RGBLIGHT_MODES
#define RGBLIGHT_MODES 23
#endif

#ifndef RGBLIGHT_EFFECT_SNAKE_LENGTH
#define RGBLIGHT_EFFECT_SNAKE_LENGTH 7
#endif

#ifndef RGBLIGHT_EFFECT_KNIGHT_LENGTH
#define RGBLIGHT_EFFECT_KNIGHT_LENGTH 7
#endif
#ifndef RGBLIGHT_EFFECT_KNIGHT_OFFSET
#define RGBLIGHT_EFFECT_KNIGHT_OFFSET 9
#endif

#ifndef RGBLIGHT_EFFECT_DUALKNIGHT_LENGTH
#define RGBLIGHT_EFFECT_DUALKNIGHT_LENGTH 4
#endif

#ifndef RGBLIGHT_HUE_STEP
#define RGBLIGHT_HUE_STEP 10
#endif
#ifndef RGBLIGHT_SAT_STEP
#define RGBLIGHT_SAT_STEP 17
#endif
#ifndef RGBLIGHT_VAL_STEP
#define RGBLIGHT_VAL_STEP 17
#endif

#define RGBLED_TIMER_TOP F_CPU/(256*64)

#include <stdint.h>
#include <stdbool.h>
#include "eeconfig.h"
#include "light_ws2812.h"

typedef union {
uint32_t raw;
struct {
bool enable :1;
uint8_t mode :6;
uint16_t hue :9;
uint8_t sat :8;
uint8_t val :8;
};
} rgblight_config_t;

void rgblight_init(void);
void rgblight_increase(void);
void rgblight_decrease(void);
void rgblight_toggle(void);
void rgblight_step(void);
void rgblight_mode(uint8_t mode);
void rgblight_set(void);
void rgblight_increase_hue(void);
void rgblight_decrease_hue(void);
void rgblight_increase_sat(void);
void rgblight_decrease_sat(void);
void rgblight_increase_val(void);
void rgblight_decrease_val(void);
void rgblight_sethsv(uint16_t hue, uint8_t sat, uint8_t val);
void rgblight_setrgb(uint8_t r, uint8_t g, uint8_t b);

#define EECONFIG_RGBLIGHT (uint8_t *)7
uint32_t eeconfig_read_rgblight(void);
void eeconfig_update_rgblight(uint32_t val);
void eeconfig_update_rgblight_default(void);
void eeconfig_debug_rgblight(void);

void sethsv(uint16_t hue, uint8_t sat, uint8_t val, struct cRGB *led1);
void setrgb(uint8_t r, uint8_t g, uint8_t b, struct cRGB *led1);
void rgblight_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);

void rgblight_timer_init(void);
void rgblight_timer_enable(void);
void rgblight_timer_disable(void);
void rgblight_timer_toggle(void);
void rgblight_effect_breathing(uint8_t interval);
void rgblight_effect_rainbow_mood(uint8_t interval);
void rgblight_effect_rainbow_swirl(uint8_t interval);
void rgblight_effect_snake(uint8_t interval);
void rgblight_effect_knight(uint8_t interval);

#endif

+ 158
- 0
quantum/template/Makefile View File

@@ -0,0 +1,158 @@
#----------------------------------------------------------------------------
# On command line:
#
# make all = Make software.
#
# make clean = Clean out built project files.
#
# make coff = Convert ELF to AVR COFF.
#
# make extcoff = Convert ELF to AVR Extended COFF.
#
# make program = Download the hex file to the device.
# Please customize your programmer settings(PROGRAM_CMD)
#
# make teensy = Download the hex file to the device, using teensy_loader_cli.
# (must have teensy_loader_cli installed).
#
# make dfu = Download the hex file to the device, using dfu-programmer (must
# have dfu-programmer installed).
#
# make flip = Download the hex file to the device, using Atmel FLIP (must
# have Atmel FLIP installed).
#
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
# (must have dfu-programmer installed).
#
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
# (must have Atmel FLIP installed).
#
# make debug = Start either simulavr or avarice as specified for debugging,
# with avr-gdb or avr-insight as the front end for debugging.
#
# make filename.s = Just compile filename.c into the assembler code only.
#
# make filename.i = Create a preprocessed source file for use in submitting
# bug reports to the GCC project.
#
# To rebuild project do "make clean" then "make all".
#----------------------------------------------------------------------------

# Target file name (without extension).
TARGET = %KEYBOARD%


# Directory common source filess exist
TOP_DIR = ../..
TMK_DIR = ../../tmk_core

# Directory keyboard dependent files exist
TARGET_DIR = .

# # project specific files
SRC = %KEYBOARD%.c

ifdef KEYMAP
SRC := keymaps/$(KEYMAP).c $(SRC)
else
SRC := keymaps/default.c $(SRC)
endif

CONFIG_H = config.h

# MCU name
#MCU = at90usb1287
MCU = atmega32u4

# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency in Hz. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
#
# This will be an integer division of F_USB below, as it is sourced by
# F_USB after it has run through any CPU prescalers. Note that this value
# does not *change* the processor frequency - it should merely be updated to
# reflect the processor speed set externally so that the code can use accurate
# software delays.
F_CPU = 16000000


#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8

# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)

# Interrupt driven control endpoint task(+60)
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT


# Boot Section Size in *bytes*
# Teensy halfKay 512
# Teensy++ halfKay 1024
# Atmel DFU loader 4096
# LUFA bootloader 4096
# USBaspLoader 2048
OPT_DEFS += -DBOOTLOADER_SIZE=512


# Build Options
# change yes to no to disable
#
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = yes # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
KEYBOARD_LOCK_ENABLE = yes # Allow locking of keyboard via magic key
# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE
SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend
# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
NKRO_ENABLE = no # USB Nkey Rollover
BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality on B7 by default
MIDI_ENABLE = no # MIDI controls
UNICODE_ENABLE = no # Unicode
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
AUDIO_ENABLE = no # Audio output on port C6


ifdef KEYMAP

ifeq ("$(wildcard keymaps/$(KEYMAP).c)","")
ifneq ("$(wildcard keymaps/$(KEYMAP)/makefile.mk)","")
include keymaps/$(KEYMAP)/makefile.mk
endif
endif

else

ifneq ("$(wildcard keymaps/default/makefile.mk)","")
include keymaps/default/makefile.mk
endif

endif

# Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax

# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)
VPATH += $(TMK_DIR)

include $(TOP_DIR)/quantum/quantum.mk


+ 24
- 0
quantum/template/README.md View File

@@ -0,0 +1,24 @@
%KEYBOARD% keyboard firmware
======================

## Quantum MK Firmware

For the full Quantum feature list, see [the parent README.md](/README.md).

## Building

Download or clone the whole firmware and navigate to the keyboard/%KEYBOARD% folder. Once your dev env is setup, you'll be able to type `make` to generate your .hex - you can then use the Teensy Loader to program your .hex file.

Depending on which keymap you would like to use, you will have to compile slightly differently.

### Default
To build with the default keymap, simply run `make`.

### Other Keymaps
Several version of keymap are available in advance but you are recommended to define your favorite layout yourself. To define your own keymap create file named `<name>.c` in the keymaps folder, and see keymap document (you can find in top README.md) and existent keymap files.

To build the firmware binary hex file with a keymap just do `make` with `KEYMAP` option like:
```
$ make KEYMAP=[default|jack|<name>]
```
Keymaps follow the format **__\<name\>.c__** and are stored in the `keymaps` folder.

+ 158
- 0
quantum/template/config.h View File

@@ -0,0 +1,158 @@
/*
Copyright 2012 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/

#ifndef CONFIG_H
#define CONFIG_H

#include "config_common.h"

/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6060
#define DEVICE_VER 0x0001
#define MANUFACTURER You
#define PRODUCT %KEYBOARD%
#define DESCRIPTION A custom keyboard

/* key matrix size */
#define MATRIX_ROWS 2
#define MATRIX_COLS 3

/*
* Keyboard Matrix Assignments
*
* Change this to how you wired your keyboard
* COLS: AVR pins used for columns, left to right
* ROWS: AVR pins used for rows, top to bottom
* DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode)
* ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode)
*
*/
#define MATRIX_ROW_PINS { D0, D5 }
#define MATRIX_COL_PINS { F1, F0, B0 }
#define UNUSED_PINS

/* COL2ROW or ROW2COL */
#define DIODE_DIRECTION COL2ROW

/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
#define DEBOUNCING_DELAY 5

/* define if matrix has ghost (lacks anti-ghosting diodes) */
//#define MATRIX_HAS_GHOST

/* number of backlight levels */
#define BACKLIGHT_LEVELS 3

/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE

/*
* Force NKRO
*
* Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved
* state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the
* makefile for this to work.)
*
* If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N)
* until the next keyboard reset.
*
* NKRO may prevent your keystrokes from being detected in the BIOS, but it is
* fully operational during normal computer usage.
*
* For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N)
* or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by
* bootmagic, NKRO mode will always be enabled until it is toggled again during a
* power-up.
*
*/
//#define FORCE_NKRO

/*
* Magic Key Options
*
* Magic keys are hotkey commands that allow control over firmware functions of
* the keyboard. They are best used in combination with the HID Listen program,
* found here: https://www.pjrc.com/teensy/hid_listen.html
*
* The options below allow the magic key functionality to be changed. This is
* useful if your keyboard/keypad is missing keys and you want magic key support.
*
*/

/* key combination for magic key command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
)

/* control how magic key switches layers */
//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS true
//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS true
//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM false

/* override magic key keymap */
//#define MAGIC_KEY_SWITCH_LAYER_WITH_FKEYS
//#define MAGIC_KEY_SWITCH_LAYER_WITH_NKEYS
//#define MAGIC_KEY_SWITCH_LAYER_WITH_CUSTOM
//#define MAGIC_KEY_HELP1 H
//#define MAGIC_KEY_HELP2 SLASH
//#define MAGIC_KEY_DEBUG D
//#define MAGIC_KEY_DEBUG_MATRIX X
//#define MAGIC_KEY_DEBUG_KBD K
//#define MAGIC_KEY_DEBUG_MOUSE M
//#define MAGIC_KEY_VERSION V
//#define MAGIC_KEY_STATUS S
//#define MAGIC_KEY_CONSOLE C
//#define MAGIC_KEY_LAYER0_ALT1 ESC
//#define MAGIC_KEY_LAYER0_ALT2 GRAVE
//#define MAGIC_KEY_LAYER0 0
//#define MAGIC_KEY_LAYER1 1
//#define MAGIC_KEY_LAYER2 2
//#define MAGIC_KEY_LAYER3 3
//#define MAGIC_KEY_LAYER4 4
//#define MAGIC_KEY_LAYER5 5
//#define MAGIC_KEY_LAYER6 6
//#define MAGIC_KEY_LAYER7 7
//#define MAGIC_KEY_LAYER8 8
//#define MAGIC_KEY_LAYER9 9
//#define MAGIC_KEY_BOOTLOADER PAUSE
//#define MAGIC_KEY_LOCK CAPS
//#define MAGIC_KEY_EEPROM E
//#define MAGIC_KEY_NKRO N
//#define MAGIC_KEY_SLEEP_LED Z

/*
* Feature disable options
* These options are also useful to firmware size reduction.
*/

/* disable debug print */
//#define NO_DEBUG

/* disable print */
//#define NO_PRINT

/* disable action features */
//#define NO_ACTION_LAYER
//#define NO_ACTION_TAPPING
//#define NO_ACTION_ONESHOT
//#define NO_ACTION_MACRO
//#define NO_ACTION_FUNCTION

#endif

+ 30
- 0
quantum/template/keymaps/default.c View File

@@ -0,0 +1,30 @@
// This is the canonical layout file for the Quantum project. If you want to add another keyboard,
// this is the style you want to emulate.

#include "%KEYBOARD%.h"

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = KEYMAP( /* Base */
KC_A, KC_1, KC_H, \
KC_TAB, KC_SPC \
),
};

const uint16_t PROGMEM fn_actions[] = {

};

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
// MACRODOWN only works in this function
switch(id) {
case 0:
if (record->event.pressed) {
register_code(KC_RSFT);
} else {
unregister_code(KC_RSFT);
}
break;
}
return MACRO_NONE;
};

+ 110
- 0
quantum/template/template.c View File

@@ -0,0 +1,110 @@
#include "%KEYBOARD%.h"

__attribute__ ((weak))
void matrix_init_user(void) {
// leave this function blank - it can be defined in a keymap file
};

__attribute__ ((weak))
void matrix_scan_user(void) {
// leave this function blank - it can be defined in a keymap file
}

__attribute__ ((weak))
bool process_action_user(keyrecord_t *record) {
// leave this function blank - it can be defined in a keymap file
return true;
}

__attribute__ ((weak))
void led_set_user(uint8_t usb_led) {
// leave this function blank - it can be defined in a keymap file
}

void matrix_init_kb(void) {
// put your keyboard start-up code here
// runs once when the firmware starts up

matrix_init_user();
}

void matrix_scan_kb(void) {
// put your looping keyboard code here
// runs every cycle (a lot)

matrix_scan_user();
}

bool process_action_kb(keyrecord_t *record) {
// put your per-action keyboard code here
// runs for every action, just before processing by the firmware

return process_action_user(record);
}

void led_set_kb(uint8_t usb_led) {
// put your keyboard LED indicator (ex: Caps Lock LED) toggling code here

led_set_user(usb_led);
}

#ifdef BACKLIGHT_ENABLE
#define CHANNEL OCR1C

void backlight_init_ports()
{

// Setup PB7 as output and output low.
DDRB |= (1<<7);
PORTB &= ~(1<<7);
// Use full 16-bit resolution.
ICR1 = 0xFFFF;

// I could write a wall of text here to explain... but TL;DW
// Go read the ATmega32u4 datasheet.
// And this: http://blog.saikoled.com/post/43165849837/secret-konami-cheat-code-to-high-resolution-pwm-on
// Pin PB7 = OCR1C (Timer 1, Channel C)
// Compare Output Mode = Clear on compare match, Channel C = COM1C1=1 COM1C0=0
// (i.e. start high, go low when counter matches.)
// WGM Mode 14 (Fast PWM) = WGM13=1 WGM12=1 WGM11=1 WGM10=0
// Clock Select = clk/1 (no prescaling) = CS12=0 CS11=0 CS10=1
TCCR1A = _BV(COM1C1) | _BV(WGM11); // = 0b00001010;
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;

backlight_init();
}

void backlight_set(uint8_t level)
{
if ( level == 0 )
{
// Turn off PWM control on PB7, revert to output low.
TCCR1A &= ~(_BV(COM1C1));
CHANNEL = 0x0;
// Prevent backlight blink on lowest level
PORTB &= ~(_BV(PORTB7));
}
else if ( level == BACKLIGHT_LEVELS )
{
// Prevent backlight blink on lowest level
PORTB &= ~(_BV(PORTB7));
// Turn on PWM control of PB7
TCCR1A |= _BV(COM1C1);
// Set the brightness
CHANNEL = 0xFFFF;
}
else
{
// Prevent backlight blink on lowest level
PORTB &= ~(_BV(PORTB7));
// Turn on PWM control of PB7
TCCR1A |= _BV(COM1C1);
// Set the brightness
CHANNEL = 0xFFFF >> ((BACKLIGHT_LEVELS - level) * ((BACKLIGHT_LEVELS + 1) / 2));
}
}

#endif

+ 30
- 0
quantum/template/template.h View File

@@ -0,0 +1,30 @@
#ifndef %KEYBOARD_UPPERCASE%_H
#define %KEYBOARD_UPPERCASE%_H

#include "matrix.h"
#include "keymap_common.h"
#ifdef BACKLIGHT_ENABLE
#include "backlight.h"
#endif
#include <avr/io.h>
#include <stddef.h>

// This a shortcut to help you visually see your layout.
// The following is an example using the Planck MIT layout
// The first section contains all of the arguements
// The second converts the arguments into a two-dimensional array
#define KEYMAP( \
k00, k01, k02, \
k10, k11 \
) \
{ \
{ k00, k01, k02 }, \
{ k10, KC_NO, k11 }, \
}

void matrix_init_user(void);
void matrix_scan_user(void);
bool process_action_user(keyrecord_t *record);
void led_set_user(uint8_t usb_led);

#endif

+ 6
- 0
quantum/tools/README.md View File

@@ -0,0 +1,6 @@
`eeprom_reset.hex` is to reset the eeprom on the Atmega32u4, like this:

dfu-programmer atmega32u4 erase
dfu-programmer atmega32u4 flash --eeprom eeprom_reset.hex

You'll need to reflash afterwards, because DFU requires the flash to be erased before messing with the eeprom.

+ 9
- 0
quantum/tools/eeprom_reset.hex View File

@@ -0,0 +1,9 @@
:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
:00000001FF

+ 128
- 0
quantum/unicode.h View File

@@ -0,0 +1,128 @@
/*
Copyright 2016 Jack Humbert <[email protected]>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/

#ifndef UNICODE_H
#define UNICODE_H

#include "quantum.h"
#include <math.h>

#define UC_BSPC UC(0x0008)

#define UC_SPC UC(0x0020)

#define UC_EXLM UC(0x0021)
#define UC_DQUT UC(0x0022)
#define UC_HASH UC(0x0023)
#define UC_DLR UC(0x0024)
#define UC_PERC UC(0x0025)
#define UC_AMPR UC(0x0026)
#define UC_QUOT UC(0x0027)
#define UC_LPRN UC(0x0028)
#define UC_RPRN UC(0x0029)
#define UC_ASTR UC(0x002A)
#define UC_PLUS UC(0x002B)
#define UC_COMM UC(0x002C)
#define UC_DASH UC(0x002D)
#define UC_DOT UC(0x002E)
#define UC_SLSH UC(0x002F)

#define UC_0 UC(0x0030)
#define UC_1 UC(0x0031)
#define UC_2 UC(0x0032)
#define UC_3 UC(0x0033)
#define UC_4 UC(0x0034)
#define UC_5 UC(0x0035)
#define UC_6 UC(0x0036)
#define UC_7 UC(0x0037)
#define UC_8 UC(0x0038)
#define UC_9 UC(0x0039)

#define UC_COLN UC(0x003A)
#define UC_SCLN UC(0x003B)
#define UC_LT UC(0x003C)
#define UC_EQL UC(0x003D)
#define UC_GT UC(0x003E)
#define UC_QUES UC(0x003F)
#define UC_AT UC(0x0040)

#define UC_A UC(0x0041)
#define UC_B UC(0x0042)
#define UC_C UC(0x0043)
#define UC_D UC(0x0044)
#define UC_E UC(0x0045)
#define UC_F UC(0x0046)
#define UC_G UC(0x0047)
#define UC_H UC(0x0048)
#define UC_I UC(0x0049)
#define UC_J UC(0x004A)
#define UC_K UC(0x004B)
#define UC_L UC(0x004C)
#define UC_M UC(0x004D)
#define UC_N UC(0x004E)
#define UC_O UC(0x004F)
#define UC_P UC(0x0050)
#define UC_Q UC(0x0051)
#define UC_R UC(0x0052)
#define UC_S UC(0x0053)
#define UC_T UC(0x0054)
#define UC_U UC(0x0055)
#define UC_V UC(0x0056)
#define UC_W UC(0x0057)
#define UC_X UC(0x0058)
#define UC_Y UC(0x0059)
#define UC_Z UC(0x005A)

#define UC_LBRC UC(0x005B)
#define UC_BSLS UC(0x005C)
#define UC_RBRC UC(0x005D)
#define UC_CIRM UC(0x005E)
#define UC_UNDR UC(0x005F)

#define UC_GRV UC(0x0060)

#define UC_a UC(0x0061)
#define UC_b UC(0x0062)
#define UC_c UC(0x0063)
#define UC_d UC(0x0064)
#define UC_e UC(0x0065)
#define UC_f UC(0x0066)
#define UC_g UC(0x0067)
#define UC_h UC(0x0068)
#define UC_i UC(0x0069)
#define UC_j UC(0x006A)
#define UC_k UC(0x006B)
#define UC_l UC(0x006C)
#define UC_m UC(0x006D)
#define UC_n UC(0x006E)
#define UC_o UC(0x006F)
#define UC_p UC(0x0070)
#define UC_q UC(0x0071)
#define UC_r UC(0x0072)
#define UC_s UC(0x0073)
#define UC_t UC(0x0074)
#define UC_u UC(0x0075)
#define UC_v UC(0x0076)
#define UC_w UC(0x0077)
#define UC_x UC(0x0078)
#define UC_y UC(0x0079)
#define UC_z UC(0x007A)

#define UC_LCBR UC(0x007B)
#define UC_PIPE UC(0x007C)
#define UC_RCBR UC(0x007D)
#define UC_TILD UC(0x007E)
#define UC_DEL UC(0x007F)

#endif

+ 13
- 0
tmk_core/.gitignore View File

@@ -0,0 +1,13 @@
.dep
*.o
*.eep
*.elf
*.hex
*.lss
*.lst
*.map
*.sym
tags
*~
build/
*.bak

+ 0
- 0
tmk_core/.gitmodules View File


+ 146
- 0
tmk_core/README.md View File

@@ -0,0 +1,146 @@
TMK Keyboard Firmware Core Library
==================================
This is a keyboard firmware library with some useful features for Atmel AVR and Cortex-M.

Source code is available here: <https://github.com/tmk/tmk_keyboard/tree/core>


Features
--------
These features can be used in your keyboard.

* Multi-layer Keymap - Multiple keyboard layouts with layer switching
* Mouse key - Mouse control with keyboard
* System Control Key - Power Down, Sleep, Wake Up and USB Remote Wake up
* Media Control Key - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
* USB NKRO - 120 keys(+ 8 modifiers) simultaneously
* PS/2 mouse support - PS/2 mouse(TrackPoint) as composite device
* Keyboard protocols - PS/2, ADB, M0110, Sun and other old keyboard protocols
* User Function - Customizable function of key with writing code
* Macro - Very primitive at this time
* Keyboard Tricks - Oneshot modifier and modifier with tapping feature
* Debug Console - Messages for debug and interaction with firmware
* Virtual DIP Switch - Configurations stored EEPROM(Boot Magic)
* Locking CapsLock - Mechanical switch support for CapsLock
* Breathing Sleep LED - Sleep indicator with charm during USB suspend
* Backlight - Control backlight levels



Updates
-------
2015/04/22 separated with TMK Keyboard Firmware Collection



TMK Keyboard Firmware Collection
--------------------------------
Complete firmwares for various keyboards and protocol converters.

<https://github.com/tmk/tmk_keyboard>



License
-------
**GPLv2** or later. Some protocol files are under **Modified BSD License**.
LUFA, PJRC and V-USB stack have their own license respectively.



Build Firmware and Program Controller
-------------------------------------
See [doc/build.md](doc/build.md).



Start Your Own Project
-----------------------
**TBD**
### Config.h Options
#### 1. USB vendor/product ID and device description
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0xBEEF
#define MANUFACTURER t.m.k.
#define PRODUCT Macway mod
#define DESCRIPTION t.m.k. keyboard firmware for Macway mod

#### 2. Keyboard matrix configuration
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
#define MATRIX_HAS_GHOST



Architecture
------------
Architecture Diagram
+---------------+---------------+-------------+
| Host | Keyboard | Matrix, LED |
___________ |-----------+-+ +-------------+ | +-----------|
/ /| Keys/Mouse | Protocol |d| | Action | | | Protocol |
/__________/ |<-----------| LUFA |r| | Layer, Tap | | | Matrix |
|.--------.| | LED | V-USB |i| |-------------| | | PS/2,IBM | __________________
|| || |----------->| PJRC |v| | Keymap | | | ADB,M0110| Keys / /_/_/_/_/_/_/_/ /|
|| Host || | Console | iWRAP(BT)|e| | Mousekey | | | SUN/NEWS |<----------/ /_/_/_/_/_/_/_/ / /
||________||/.<-----------| UART |r| | Report | | | X68K/PC98| Control / /_/_/_/_/_/_/_/ / /
`_========_'/| |---------------------------------------------|-------->/___ /_______/ ___/ /
|_o______o_|/ | Sendchar, Print, Debug, Command, ... | |_________________|/
+---------------------------------------------+ Keyboard



Debugging
--------
Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack.

You can use xprintf() to display debug info on `hid_listen`, see `common/xprintf.h`.



Files and Directories
-------------------
### Top
* common/ - common codes
* protocol/ - keyboard protocol support
* doc/ - documents
* common.mk - Makefile for common
* protocol.mk - Makefile for protocol
* rules.mk - Makefile for build rules

### Common
* host.h
* host_driver.h
* keyboard.h
* command.h
* keymap.h
* action.h
* keycode.h
* matrix.h
* led.h
* mousekey.h
* report.h
* debug.h
* print.h
* bootloader.h
* sendchar.h
* timer.h
* util.h

### Keyboard Protocols
* lufa/ - LUFA USB stack
* pjrc/ - PJRC USB stack
* vusb/ - Objective Development V-USB
* iwrap/ - Bluetooth HID for Bluegiga iWRAP
* ps2.c - PS/2 protocol
* adb.c - Apple Desktop Bus protocol
* m0110.c - Macintosh 128K/512K/Plus keyboard protocol
* news.c - Sony NEWS keyboard protocol
* x68k.c - Sharp X68000 keyboard protocol
* serial_soft.c - Asynchronous Serial protocol implemented by software



Coding Style
-------------
- Doesn't use Tab to indent, use 4-spaces instead.

+ 104
- 0
tmk_core/common.mk View File

@@ -0,0 +1,104 @@
COMMON_DIR = common
SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/keyboard.c \
$(COMMON_DIR)/action.c \
$(COMMON_DIR)/action_tapping.c \
$(COMMON_DIR)/action_macro.c \
$(COMMON_DIR)/action_layer.c \
$(COMMON_DIR)/action_util.c \
$(COMMON_DIR)/keymap.c \
$(COMMON_DIR)/print.c \
$(COMMON_DIR)/debug.c \
$(COMMON_DIR)/util.c \
$(COMMON_DIR)/avr/suspend.c \
$(COMMON_DIR)/avr/xprintf.S \
$(COMMON_DIR)/avr/timer.c \
$(COMMON_DIR)/avr/bootloader.c


# Option modules
ifeq ($(strip $(BOOTMAGIC_ENABLE)), yes)
SRC += $(COMMON_DIR)/bootmagic.c
SRC += $(COMMON_DIR)/avr/eeconfig.c
OPT_DEFS += -DBOOTMAGIC_ENABLE
else
SRC += $(COMMON_DIR)/magic.c
SRC += $(COMMON_DIR)/avr/eeconfig.c
endif

ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
SRC += $(COMMON_DIR)/mousekey.c
OPT_DEFS += -DMOUSEKEY_ENABLE
OPT_DEFS += -DMOUSE_ENABLE
endif

ifeq ($(strip $(EXTRAKEY_ENABLE)), yes)
OPT_DEFS += -DEXTRAKEY_ENABLE
endif

ifeq ($(strip $(CONSOLE_ENABLE)), yes)
OPT_DEFS += -DCONSOLE_ENABLE
else
OPT_DEFS += -DNO_PRINT
OPT_DEFS += -DNO_DEBUG
endif

ifeq ($(strip $(COMMAND_ENABLE)), yes)
SRC += $(COMMON_DIR)/command.c
OPT_DEFS += -DCOMMAND_ENABLE
endif

ifeq ($(strip $(NKRO_ENABLE)), yes)
OPT_DEFS += -DNKRO_ENABLE
endif

ifeq ($(strip $(MIDI_ENABLE)), yes)
OPT_DEFS += -DMIDI_ENABLE
endif

ifeq ($(strip $(AUDIO_ENABLE)), yes)
OPT_DEFS += -DAUDIO_ENABLE
endif

ifeq ($(strip $(UNICODE_ENABLE)), yes)
OPT_DEFS += -DUNICODE_ENABLE
endif

ifeq ($(strip $(USB_6KRO_ENABLE)), yes)
OPT_DEFS += -DUSB_6KRO_ENABLE
endif

ifeq ($(strip $(SLEEP_LED_ENABLE)), yes)
SRC += $(COMMON_DIR)/sleep_led.c
OPT_DEFS += -DSLEEP_LED_ENABLE
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
endif

ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
SRC += $(COMMON_DIR)/backlight.c
SRC += $(COMMON_DIR)/avr/eeconfig.c
OPT_DEFS += -DBACKLIGHT_ENABLE
endif

ifeq ($(strip $(BLUETOOTH_ENABLE)), yes)
OPT_DEFS += -DBLUETOOTH_ENABLE
endif

ifeq ($(strip $(KEYMAP_SECTION_ENABLE)), yes)
OPT_DEFS += -DKEYMAP_SECTION_ENABLE

ifeq ($(strip $(MCU)),atmega32u2)
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr35.x
else ifeq ($(strip $(MCU)),atmega32u4)
EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
else
EXTRALDFLAGS = $(error no ldscript for keymap section)
endif
endif

# Version string
OPT_DEFS += -DVERSION=$(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)


# Search Path
VPATH += $(TMK_DIR)/common

+ 698
- 0
tmk_core/common/action.c View File

@@ -0,0 +1,698 @@
/*
Copyright 2012,2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 "host.h"
#include "keycode.h"
#include "keyboard.h"
#include "mousekey.h"
#include "command.h"
#include "led.h"
#include "backlight.h"
#include "action_layer.h"
#include "action_tapping.h"
#include "action_macro.h"
#include "action_util.h"
#include "action.h"

#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif


void action_exec(keyevent_t event)
{
if (!IS_NOEVENT(event)) {
dprint("\n---- action_exec: start -----\n");
dprint("EVENT: "); debug_event(event); dprintln();
}

keyrecord_t record = { .event = event };

#ifndef NO_ACTION_TAPPING
action_tapping_process(record);
#else
process_record(&record);
if (!IS_NOEVENT(record.event)) {
dprint("processed: "); debug_record(record); dprintln();
}
#endif
}

#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
bool disable_action_cache = false;

void process_record_nocache(keyrecord_t *record)
{
disable_action_cache = true;
process_record(record);
disable_action_cache = false;
}
#else
void process_record_nocache(keyrecord_t *record)
{
process_record(record);
}
#endif

__attribute__ ((weak))
bool process_record_quantum(keyrecord_t *record) {
return true;
}

void process_record(keyrecord_t *record)
{
if (IS_NOEVENT(record->event)) { return; }

if(!process_record_quantum(record))
return;

action_t action = store_or_get_action(record->event.pressed, record->event.key);
dprint("ACTION: "); debug_action(action);
#ifndef NO_ACTION_LAYER
dprint(" layer_state: "); layer_debug();
dprint(" default_layer_state: "); default_layer_debug();
#endif
dprintln();

process_action(record, action);
}

void process_action(keyrecord_t *record, action_t action)
{
bool do_release_oneshot = false;
keyevent_t event = record->event;
#ifndef NO_ACTION_TAPPING
uint8_t tap_count = record->tap.count;
#endif

#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
if (has_oneshot_layer_timed_out()) {
dprintf("Oneshot layer: timeout\n");
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
#endif

if (event.pressed) {
// clear the potential weak mods left by previously pressed keys
clear_weak_mods();
}

#ifndef NO_ACTION_ONESHOT
// notice we only clear the one shot layer if the pressed key is not a modifier.
if (is_oneshot_layer_active() && event.pressed && !IS_MOD(action.key.code)) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
do_release_oneshot = !is_oneshot_layer_active();
}
#endif

switch (action.kind.id) {
/* Key and Mods */
case ACT_LMODS:
case ACT_RMODS:
{
uint8_t mods = (action.kind.id == ACT_LMODS) ? action.key.mods :
action.key.mods<<4;
if (event.pressed) {
if (mods) {
if (IS_MOD(action.key.code)) {
// e.g. LSFT(KC_LGUI): we don't want the LSFT to be weak as it would make it useless.
// this also makes LSFT(KC_LGUI) behave exactly the same as LGUI(KC_LSFT)
add_mods(mods);
} else {
add_weak_mods(mods);
}
send_keyboard_report();
}
register_code(action.key.code);
} else {
unregister_code(action.key.code);
if (mods) {
if (IS_MOD(action.key.code)) {
del_mods(mods);
} else {
del_weak_mods(mods);
}
send_keyboard_report();
}
}
}
break;
#ifndef NO_ACTION_TAPPING
case ACT_LMODS_TAP:
case ACT_RMODS_TAP:
{
uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ? action.key.mods :
action.key.mods<<4;
switch (action.layer_tap.code) {
#ifndef NO_ACTION_ONESHOT
case MODS_ONESHOT:
// Oneshot modifier
if (event.pressed) {
if (tap_count == 0) {
dprint("MODS_TAP: Oneshot: 0\n");
register_mods(mods);
} else if (tap_count == 1) {
dprint("MODS_TAP: Oneshot: start\n");
set_oneshot_mods(mods);
#if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
} else if (tap_count == ONESHOT_TAP_TOGGLE) {
dprint("MODS_TAP: Toggling oneshot");
clear_oneshot_mods();
set_oneshot_locked_mods(mods);
register_mods(mods);
#endif
} else {
register_mods(mods);
}
} else {
if (tap_count == 0) {
clear_oneshot_mods();
unregister_mods(mods);
} else if (tap_count == 1) {
// Retain Oneshot mods
#if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
if (mods & get_mods()) {
clear_oneshot_locked_mods();
clear_oneshot_mods();
unregister_mods(mods);
}
} else if (tap_count == ONESHOT_TAP_TOGGLE) {
// Toggle Oneshot Layer
#endif
} else {
clear_oneshot_mods();
unregister_mods(mods);
}
}
break;
#endif
case MODS_TAP_TOGGLE:
if (event.pressed) {
if (tap_count <= TAPPING_TOGGLE) {
register_mods(mods);
}
} else {
if (tap_count < TAPPING_TOGGLE) {
unregister_mods(mods);
}
}
break;
default:
if (event.pressed) {
if (tap_count > 0) {
#ifndef IGNORE_MOD_TAP_INTERRUPT
if (record->tap.interrupted) {
dprint("mods_tap: tap: cancel: add_mods\n");
// ad hoc: set 0 to cancel tap
record->tap.count = 0;
register_mods(mods);
} else
#endif
{
dprint("MODS_TAP: Tap: register_code\n");
register_code(action.key.code);
}
} else {
dprint("MODS_TAP: No tap: add_mods\n");
register_mods(mods);
}
} else {
if (tap_count > 0) {
dprint("MODS_TAP: Tap: unregister_code\n");
unregister_code(action.key.code);
} else {
dprint("MODS_TAP: No tap: add_mods\n");
unregister_mods(mods);
}
}
break;
}
}
break;
#endif
#ifdef EXTRAKEY_ENABLE
/* other HID usage */
case ACT_USAGE:
switch (action.usage.page) {
case PAGE_SYSTEM:
if (event.pressed) {
host_system_send(action.usage.code);
} else {
host_system_send(0);
}
break;
case PAGE_CONSUMER:
if (event.pressed) {
host_consumer_send(action.usage.code);
} else {
host_consumer_send(0);
}
break;
}
break;
#endif
#ifdef MOUSEKEY_ENABLE
/* Mouse key */
case ACT_MOUSEKEY:
if (event.pressed) {
mousekey_on(action.key.code);
mousekey_send();
} else {
mousekey_off(action.key.code);
mousekey_send();
}
break;
#endif
#ifndef NO_ACTION_LAYER
case ACT_LAYER:
if (action.layer_bitop.on == 0) {
/* Default Layer Bitwise Operation */
if (!event.pressed) {
uint8_t shift = action.layer_bitop.part*4;
uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
switch (action.layer_bitop.op) {
case OP_BIT_AND: default_layer_and(bits | mask); break;
case OP_BIT_OR: default_layer_or(bits | mask); break;
case OP_BIT_XOR: default_layer_xor(bits | mask); break;
case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
}
}
} else {
/* Layer Bitwise Operation */
if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
(action.layer_bitop.on & ON_RELEASE)) {
uint8_t shift = action.layer_bitop.part*4;
uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
switch (action.layer_bitop.op) {
case OP_BIT_AND: layer_and(bits | mask); break;
case OP_BIT_OR: layer_or(bits | mask); break;
case OP_BIT_XOR: layer_xor(bits | mask); break;
case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
}
}
}
break;
#ifndef NO_ACTION_TAPPING
case ACT_LAYER_TAP:
case ACT_LAYER_TAP_EXT:
switch (action.layer_tap.code) {
case 0xe0 ... 0xef:
/* layer On/Off with modifiers(left only) */
if (event.pressed) {
layer_on(action.layer_tap.val);
register_mods(action.layer_tap.code & 0x0f);
} else {
layer_off(action.layer_tap.val);
unregister_mods(action.layer_tap.code & 0x0f);
}
break;
case OP_TAP_TOGGLE:
/* tap toggle */
if (event.pressed) {
if (tap_count < TAPPING_TOGGLE) {
layer_invert(action.layer_tap.val);
}
} else {
if (tap_count <= TAPPING_TOGGLE) {
layer_invert(action.layer_tap.val);
}
}
break;
case OP_ON_OFF:
event.pressed ? layer_on(action.layer_tap.val) :
layer_off(action.layer_tap.val);
break;
case OP_OFF_ON:
event.pressed ? layer_off(action.layer_tap.val) :
layer_on(action.layer_tap.val);
break;
case OP_SET_CLEAR:
event.pressed ? layer_move(action.layer_tap.val) :
layer_clear();
break;
#ifndef NO_ACTION_ONESHOT
case OP_ONESHOT:
// Oneshot modifier
#if defined(ONESHOT_TAP_TOGGLE) && ONESHOT_TAP_TOGGLE > 1
do_release_oneshot = false;
if (event.pressed) {
del_mods(get_oneshot_locked_mods());
if (get_oneshot_layer_state() == ONESHOT_TOGGLED) {
reset_oneshot_layer();
layer_off(action.layer_tap.val);
break;
} else if (tap_count < ONESHOT_TAP_TOGGLE) {
layer_on(action.layer_tap.val);
set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
}
} else {
add_mods(get_oneshot_locked_mods());
if (tap_count >= ONESHOT_TAP_TOGGLE) {
reset_oneshot_layer();
clear_oneshot_locked_mods();
set_oneshot_layer(action.layer_tap.val, ONESHOT_TOGGLED);
} else {
clear_oneshot_layer_state(ONESHOT_PRESSED);
}
}
#else
if (event.pressed) {
layer_on(action.layer_tap.val);
set_oneshot_layer(action.layer_tap.val, ONESHOT_START);
} else {
clear_oneshot_layer_state(ONESHOT_PRESSED);
if (tap_count > 1) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
}
}
#endif
break;
#endif
default:
/* tap key */
if (event.pressed) {
if (tap_count > 0) {
dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
register_code(action.layer_tap.code);
} else {
dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
layer_on(action.layer_tap.val);
}
} else {
if (tap_count > 0) {
dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
unregister_code(action.layer_tap.code);
} else {
dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
layer_off(action.layer_tap.val);
}
}
break;
}
break;
#endif
#endif
/* Extentions */
#ifndef NO_ACTION_MACRO
case ACT_MACRO:
action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
break;
#endif
#ifdef BACKLIGHT_ENABLE
case ACT_BACKLIGHT:
if (!event.pressed) {
switch (action.backlight.opt) {
case BACKLIGHT_INCREASE:
backlight_increase();
break;
case BACKLIGHT_DECREASE:
backlight_decrease();
break;
case BACKLIGHT_TOGGLE:
backlight_toggle();
break;
case BACKLIGHT_STEP:
backlight_step();
break;
case BACKLIGHT_LEVEL:
backlight_level(action.backlight.level);
break;
}
}
break;
#endif
case ACT_COMMAND:
break;
#ifndef NO_ACTION_FUNCTION
case ACT_FUNCTION:
action_function(record, action.func.id, action.func.opt);
break;
#endif
default:
break;
}

#ifndef NO_ACTION_ONESHOT
/* Because we switch layers after a oneshot event, we need to release the
* key before we leave the layer or no key up event will be generated.
*/
if (do_release_oneshot && !(get_oneshot_layer_state() & ONESHOT_PRESSED ) ) {
record->event.pressed = false;
layer_on(get_oneshot_layer());
process_record(record);
layer_off(get_oneshot_layer());
}
#endif
}




/*
* Utilities for actions.
*/
void register_code(uint8_t code)
{
if (code == KC_NO) {
return;
}

#ifdef LOCKING_SUPPORT_ENABLE
else if (KC_LOCKING_CAPS == code) {
#ifdef LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is on
if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
#endif
add_key(KC_CAPSLOCK);
send_keyboard_report();
del_key(KC_CAPSLOCK);
send_keyboard_report();
}

else if (KC_LOCKING_NUM == code) {
#ifdef LOCKING_RESYNC_ENABLE
if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
#endif
add_key(KC_NUMLOCK);
send_keyboard_report();
del_key(KC_NUMLOCK);
send_keyboard_report();
}

else if (KC_LOCKING_SCROLL == code) {
#ifdef LOCKING_RESYNC_ENABLE
if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
#endif
add_key(KC_SCROLLLOCK);
send_keyboard_report();
del_key(KC_SCROLLLOCK);
send_keyboard_report();
}
#endif

else if IS_KEY(code) {
// TODO: should push command_proc out of this block?
if (command_proc(code)) return;

#ifndef NO_ACTION_ONESHOT
/* TODO: remove
if (oneshot_state.mods && !oneshot_state.disabled) {
uint8_t tmp_mods = get_mods();
add_mods(oneshot_state.mods);

add_key(code);
send_keyboard_report();

set_mods(tmp_mods);
send_keyboard_report();
oneshot_cancel();
} else
*/
#endif
{
add_key(code);
send_keyboard_report();
}
}
else if IS_MOD(code) {
add_mods(MOD_BIT(code));
send_keyboard_report();
}
else if IS_SYSTEM(code) {
host_system_send(KEYCODE2SYSTEM(code));
}
else if IS_CONSUMER(code) {
host_consumer_send(KEYCODE2CONSUMER(code));
}
}

void unregister_code(uint8_t code)
{
if (code == KC_NO) {
return;
}

#ifdef LOCKING_SUPPORT_ENABLE
else if (KC_LOCKING_CAPS == code) {
#ifdef LOCKING_RESYNC_ENABLE
// Resync: ignore if caps lock already is off
if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
#endif
add_key(KC_CAPSLOCK);
send_keyboard_report();
del_key(KC_CAPSLOCK);
send_keyboard_report();
}

else if (KC_LOCKING_NUM == code) {
#ifdef LOCKING_RESYNC_ENABLE
if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
#endif
add_key(KC_NUMLOCK);
send_keyboard_report();
del_key(KC_NUMLOCK);
send_keyboard_report();
}

else if (KC_LOCKING_SCROLL == code) {
#ifdef LOCKING_RESYNC_ENABLE
if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
#endif
add_key(KC_SCROLLLOCK);
send_keyboard_report();
del_key(KC_SCROLLLOCK);
send_keyboard_report();
}
#endif

else if IS_KEY(code) {
del_key(code);
send_keyboard_report();
}
else if IS_MOD(code) {
del_mods(MOD_BIT(code));
send_keyboard_report();
}
else if IS_SYSTEM(code) {
host_system_send(0);
}
else if IS_CONSUMER(code) {
host_consumer_send(0);
}
}

void register_mods(uint8_t mods)
{
if (mods) {
add_mods(mods);
send_keyboard_report();
}
}

void unregister_mods(uint8_t mods)
{
if (mods) {
del_mods(mods);
send_keyboard_report();
}
}

void clear_keyboard(void)
{
clear_mods();
clear_keyboard_but_mods();
}

void clear_keyboard_but_mods(void)
{
clear_weak_mods();
clear_macro_mods();
clear_keys();
send_keyboard_report();
#ifdef MOUSEKEY_ENABLE
mousekey_clear();
mousekey_send();
#endif
#ifdef EXTRAKEY_ENABLE
host_system_send(0);
host_consumer_send(0);
#endif
}

bool is_tap_key(keypos_t key)
{
action_t action = layer_switch_get_action(key);

switch (action.kind.id) {
case ACT_LMODS_TAP:
case ACT_RMODS_TAP:
case ACT_LAYER_TAP:
case ACT_LAYER_TAP_EXT:
switch (action.layer_tap.code) {
case 0x00 ... 0xdf:
case OP_TAP_TOGGLE:
case OP_ONESHOT:
return true;
}
return false;
case ACT_MACRO:
case ACT_FUNCTION:
if (action.func.opt & FUNC_TAP) { return true; }
return false;
}
return false;
}


/*
* debug print
*/
void debug_event(keyevent_t event)
{
dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
}

void debug_record(keyrecord_t record)
{
debug_event(record.event);
#ifndef NO_ACTION_TAPPING
dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
#endif
}

void debug_action(action_t action)
{
switch (action.kind.id) {
case ACT_LMODS: dprint("ACT_LMODS"); break;
case ACT_RMODS: dprint("ACT_RMODS"); break;
case ACT_LMODS_TAP: dprint("ACT_LMODS_TAP"); break;
case ACT_RMODS_TAP: dprint("ACT_RMODS_TAP"); break;
case ACT_USAGE: dprint("ACT_USAGE"); break;
case ACT_MOUSEKEY: dprint("ACT_MOUSEKEY"); break;
case ACT_LAYER: dprint("ACT_LAYER"); break;
case ACT_LAYER_TAP: dprint("ACT_LAYER_TAP"); break;
case ACT_LAYER_TAP_EXT: dprint("ACT_LAYER_TAP_EXT"); break;
case ACT_MACRO: dprint("ACT_MACRO"); break;
case ACT_COMMAND: dprint("ACT_COMMAND"); break;
case ACT_FUNCTION: dprint("ACT_FUNCTION"); break;
default: dprint("UNKNOWN"); break;
}
dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
}

+ 90
- 0
tmk_core/common/action.h View File

@@ -0,0 +1,90 @@
/*
Copyright 2012,2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/
#ifndef ACTION_H
#define ACTION_H

#include <stdint.h>
#include <stdbool.h>
#include "keyboard.h"
#include "keycode.h"
#include "action_code.h"
#include "action_macro.h"


#ifdef __cplusplus
extern "C" {
#endif

/* tapping count and state */
typedef struct {
bool interrupted :1;
bool reserved2 :1;
bool reserved1 :1;
bool reserved0 :1;
uint8_t count :4;
} tap_t;

/* Key event container for recording */
typedef struct {
keyevent_t event;
#ifndef NO_ACTION_TAPPING
tap_t tap;
#endif
} keyrecord_t;

/* Execute action per keyevent */
void action_exec(keyevent_t event);

/* action for key */
action_t action_for_key(uint8_t layer, keypos_t key);

/* macro */
const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt);

/* user defined special function */
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);

/* keyboard-specific key event (pre)processing */
bool process_record_quantum(keyrecord_t *record);

/* Utilities for actions. */
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
extern bool disable_action_cache;
#endif
void process_record_nocache(keyrecord_t *record);
void process_record(keyrecord_t *record);
void process_action(keyrecord_t *record, action_t action);
void register_code(uint8_t code);
void unregister_code(uint8_t code);
void register_mods(uint8_t mods);
void unregister_mods(uint8_t mods);
//void set_mods(uint8_t mods);
void clear_keyboard(void);
void clear_keyboard_but_mods(void);
void layer_switch(uint8_t new_layer);
bool is_tap_key(keypos_t key);

/* debug */
void debug_event(keyevent_t event);
void debug_record(keyrecord_t record);
void debug_action(action_t action);

#ifdef __cplusplus
}
#endif

#endif /* ACTION_H */

+ 318
- 0
tmk_core/common/action_code.h View File

@@ -0,0 +1,318 @@
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/
#ifndef ACTION_CODE_H
#define ACTION_CODE_H

/* Action codes
* ============
* 16bit code: action_kind(4bit) + action_parameter(12bit)
*
*
* Key Actions(00xx)
* -----------------
* ACT_MODS(000r):
* 000r|0000|0000 0000 No action code
* 000r|0000|0000 0001 Transparent code
* 000r|0000| keycode Key
* 000r|mods|0000 0000 Modifiers
* 000r|mods| keycode Modifiers+Key(Modified key)
* r: Left/Right flag(Left:0, Right:1)
*
* ACT_MODS_TAP(001r):
* 001r|mods|0000 0000 Modifiers with OneShot
* 001r|mods|0000 0001 Modifiers with tap toggle
* 001r|mods|0000 00xx (reserved)
* 001r|mods| keycode Modifiers with Tap Key(Dual role)
*
*
* Other Keys(01xx)
* ----------------
* ACT_USAGE(0100): TODO: Not needed?
* 0100|00| usage(10) System control(0x80) - General Desktop page(0x01)
* 0100|01| usage(10) Consumer control(0x01) - Consumer page(0x0C)
* 0100|10| usage(10) (reserved)
* 0100|11| usage(10) (reserved)
*
* ACT_MOUSEKEY(0110): TODO: Not needed?
* 0101|xxxx| keycode Mouse key
*
* 011x|xxxx xxxx xxxx (reseved)
*
*
* Layer Actions(10xx)
* -------------------
* ACT_LAYER(1000):
* 1000|oo00|pppE BBBB Default Layer Bitwise operation
* oo: operation(00:AND, 01:OR, 10:XOR, 11:SET)
* ppp: 4-bit chunk part(0-7)
* EBBBB: bits and extra bit
* 1000|ooee|pppE BBBB Layer Bitwise Operation
* oo: operation(00:AND, 01:OR, 10:XOR, 11:SET)
* ppp: 4-bit chunk part(0-7)
* EBBBB: bits and extra bit
* ee: on event(01:press, 10:release, 11:both)
*
* 1001|xxxx|xxxx xxxx (reserved)
* 1001|oopp|BBBB BBBB 8-bit Bitwise Operation???
*
* ACT_LAYER_TAP(101x):
* 101E|LLLL| keycode On/Off with tap key (0x00-DF)[TAP]
* 101E|LLLL|1110 mods On/Off with modifiers (0xE0-EF)[NOT TAP]
* 101E|LLLL|1111 0000 Invert with tap toggle (0xF0) [TAP]
* 101E|LLLL|1111 0001 On/Off (0xF1) [NOT TAP]
* 101E|LLLL|1111 0010 Off/On (0xF2) [NOT TAP]
* 101E|LLLL|1111 0011 Set/Clear (0xF3) [NOT TAP]
* 101E|LLLL|1111 0100 One Shot Layer (0xF4) [TAP]
* 101E|LLLL|1111 xxxx Reserved (0xF5-FF)
* ELLLL: layer 0-31(E: extra bit for layer 16-31)
*
*
* Extensions(11xx)
* ----------------
* ACT_MACRO(1100):
* 1100|opt | id(8) Macro play?
* 1100|1111| id(8) Macro record?
*
* ACT_BACKLIGHT(1101):
* 1101|opt |level(8) Backlight commands
*
* ACT_COMMAND(1110):
* 1110|opt | id(8) Built-in Command exec
*
* ACT_FUNCTION(1111):
* 1111| address(12) Function?
* 1111|opt | id(8) Function?
*/
enum action_kind_id {
/* Key Actions */
ACT_MODS = 0b0000,
ACT_LMODS = 0b0000,
ACT_RMODS = 0b0001,
ACT_MODS_TAP = 0b0010,
ACT_LMODS_TAP = 0b0010,
ACT_RMODS_TAP = 0b0011,
/* Other Keys */
ACT_USAGE = 0b0100,
ACT_MOUSEKEY = 0b0101,
/* Layer Actions */
ACT_LAYER = 0b1000,
ACT_LAYER_TAP = 0b1010, /* Layer 0-15 */
ACT_LAYER_TAP_EXT = 0b1011, /* Layer 16-31 */
/* Extensions */
ACT_MACRO = 0b1100,
ACT_BACKLIGHT = 0b1101,
ACT_COMMAND = 0b1110,
ACT_FUNCTION = 0b1111
};


/* Action Code Struct
*
* NOTE:
* In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
* AVR looks like a little endian in avr-gcc.
* Not portable across compiler/endianness?
*
* Byte order and bit order of 0x1234:
* Big endian: Little endian:
* -------------------- --------------------
* FEDC BA98 7654 3210 0123 4567 89AB CDEF
* 0001 0010 0011 0100 0010 1100 0100 1000
* 0x12 0x34 0x34 0x12
*/
typedef union {
uint16_t code;
struct action_kind {
uint16_t param :12;
uint8_t id :4;
} kind;
struct action_key {
uint8_t code :8;
uint8_t mods :4;
uint8_t kind :4;
} key;
struct action_layer_bitop {
uint8_t bits :4;
uint8_t xbit :1;
uint8_t part :3;
uint8_t on :2;
uint8_t op :2;
uint8_t kind :4;
} layer_bitop;
struct action_layer_tap {
uint8_t code :8;
uint8_t val :5;
uint8_t kind :3;
} layer_tap;
struct action_usage {
uint16_t code :10;
uint8_t page :2;
uint8_t kind :4;
} usage;
struct action_backlight {
uint8_t level :8;
uint8_t opt :4;
uint8_t kind :4;
} backlight;
struct action_command {
uint8_t id :8;
uint8_t opt :4;
uint8_t kind :4;
} command;
struct action_function {
uint8_t id :8;
uint8_t opt :4;
uint8_t kind :4;
} func;
} action_t;


/* action utility */
#define ACTION_NO 0
#define ACTION_TRANSPARENT 1
#define ACTION(kind, param) ((kind)<<12 | (param))


/*
* Key Actions
*/
/* Mod bits: 43210
* bit 0 ||||+- Control
* bit 1 |||+-- Shift
* bit 2 ||+--- Alt
* bit 3 |+---- Gui
* bit 4 +----- LR flag(Left:0, Right:1)
*/
enum mods_bit {
MOD_LCTL = 0x01,
MOD_LSFT = 0x02,
MOD_LALT = 0x04,
MOD_LGUI = 0x08,
MOD_RCTL = 0x11,
MOD_RSFT = 0x12,
MOD_RALT = 0x14,
MOD_RGUI = 0x18,
};
enum mods_codes {
MODS_ONESHOT = 0x00,
MODS_TAP_TOGGLE = 0x01,
};
#define ACTION_KEY(key) ACTION(ACT_MODS, (key))
#define ACTION_MODS(mods) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | 0)
#define ACTION_MODS_KEY(mods, key) ACTION(ACT_MODS, ((mods)&0x1f)<<8 | (key))
#define ACTION_MODS_TAP_KEY(mods, key) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | (key))
#define ACTION_MODS_ONESHOT(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_ONESHOT)
#define ACTION_MODS_TAP_TOGGLE(mods) ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_TAP_TOGGLE)


/*
* Other Keys
*/
enum usage_pages {
PAGE_SYSTEM,
PAGE_CONSUMER
};
#define ACTION_USAGE_SYSTEM(id) ACTION(ACT_USAGE, PAGE_SYSTEM<<10 | (id))
#define ACTION_USAGE_CONSUMER(id) ACTION(ACT_USAGE, PAGE_CONSUMER<<10 | (id))
#define ACTION_MOUSEKEY(key) ACTION(ACT_MOUSEKEY, key)



/*
* Layer Actions
*/
enum layer_param_on {
ON_PRESS = 1,
ON_RELEASE = 2,
ON_BOTH = 3,
};
enum layer_param_bit_op {
OP_BIT_AND = 0,
OP_BIT_OR = 1,
OP_BIT_XOR = 2,
OP_BIT_SET = 3,
};
enum layer_pram_tap_op {
OP_TAP_TOGGLE = 0xF0,
OP_ON_OFF,
OP_OFF_ON,
OP_SET_CLEAR,
OP_ONESHOT,
};
#define ACTION_LAYER_BITOP(op, part, bits, on) (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))
#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
/* Default Layer */
#define ACTION_DEFAULT_LAYER_SET(layer) ACTION_DEFAULT_LAYER_BIT_SET((layer)/4, 1<<((layer)%4))
/* Layer Operation */
#define ACTION_LAYER_CLEAR(on) ACTION_LAYER_BIT_AND(0, 0, (on))
#define ACTION_LAYER_MOMENTARY(layer) ACTION_LAYER_ON_OFF(layer)
#define ACTION_LAYER_TOGGLE(layer) ACTION_LAYER_INVERT(layer, ON_RELEASE)
#define ACTION_LAYER_INVERT(layer, on) ACTION_LAYER_BIT_XOR((layer)/4, 1<<((layer)%4), (on))
#define ACTION_LAYER_ON(layer, on) ACTION_LAYER_BIT_OR( (layer)/4, 1<<((layer)%4), (on))
#define ACTION_LAYER_OFF(layer, on) ACTION_LAYER_BIT_AND((layer)/4, ~(1<<((layer)%4)), (on))
#define ACTION_LAYER_SET(layer, on) ACTION_LAYER_BIT_SET((layer)/4, 1<<((layer)%4), (on))
#define ACTION_LAYER_ON_OFF(layer) ACTION_LAYER_TAP((layer), OP_ON_OFF)
#define ACTION_LAYER_OFF_ON(layer) ACTION_LAYER_TAP((layer), OP_OFF_ON)
#define ACTION_LAYER_SET_CLEAR(layer) ACTION_LAYER_TAP((layer), OP_SET_CLEAR)
#define ACTION_LAYER_ONESHOT(layer) ACTION_LAYER_TAP((layer), OP_ONESHOT)
#define ACTION_LAYER_MODS(layer, mods) ACTION_LAYER_TAP((layer), 0xe0 | ((mods)&0x0f))
/* With Tapping */
#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
#define ACTION_LAYER_TAP_TOGGLE(layer) ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE)
/* Bitwise Operation */
#define ACTION_LAYER_BIT_AND(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on))
#define ACTION_LAYER_BIT_OR( part, bits, on) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), (on))
#define ACTION_LAYER_BIT_XOR(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on))
#define ACTION_LAYER_BIT_SET(part, bits, on) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on))
/* Default Layer Bitwise Operation */
#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits) ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0)
#define ACTION_DEFAULT_LAYER_BIT_OR( part, bits) ACTION_LAYER_BITOP(OP_BIT_OR, (part), (bits), 0)
#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits) ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0)
#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits) ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0)


/*
* Extensions
*/
enum backlight_opt {
BACKLIGHT_INCREASE = 0,
BACKLIGHT_DECREASE = 1,
BACKLIGHT_TOGGLE = 2,
BACKLIGHT_STEP = 3,
BACKLIGHT_LEVEL = 4,
};
/* Macro */
#define ACTION_MACRO(id) ACTION(ACT_MACRO, (id))
#define ACTION_MACRO_TAP(id) ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
#define ACTION_MACRO_OPT(id, opt) ACTION(ACT_MACRO, (opt)<<8 | (id))
/* Backlight */
#define ACTION_BACKLIGHT_INCREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE << 8)
#define ACTION_BACKLIGHT_DECREASE() ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
#define ACTION_BACKLIGHT_TOGGLE() ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
#define ACTION_BACKLIGHT_STEP() ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
#define ACTION_BACKLIGHT_LEVEL(level) ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | (level))
/* Command */
#define ACTION_COMMAND(id, opt) ACTION(ACT_COMMAND, (opt)<<8 | (addr))
/* Function */
enum function_opts {
FUNC_TAP = 0x8, /* indciates function is tappable */
};
#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id))
#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id))
#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt)<<8 | (id))

#endif /* ACTION_CODE_H */

+ 203
- 0
tmk_core/common/action_layer.c View File

@@ -0,0 +1,203 @@
#include <stdint.h>
#include "keyboard.h"
#include "action.h"
#include "util.h"
#include "action_layer.h"

#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif


/*
* Default Layer State
*/
uint32_t default_layer_state = 0;

static void default_layer_state_set(uint32_t state)
{
debug("default_layer_state: ");
default_layer_debug(); debug(" to ");
default_layer_state = state;
default_layer_debug(); debug("\n");
clear_keyboard_but_mods(); // To avoid stuck keys
}

void default_layer_debug(void)
{
dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
}

void default_layer_set(uint32_t state)
{
default_layer_state_set(state);
}

#ifndef NO_ACTION_LAYER
void default_layer_or(uint32_t state)
{
default_layer_state_set(default_layer_state | state);
}
void default_layer_and(uint32_t state)
{
default_layer_state_set(default_layer_state & state);
}
void default_layer_xor(uint32_t state)
{
default_layer_state_set(default_layer_state ^ state);
}
#endif


#ifndef NO_ACTION_LAYER
/*
* Keymap Layer State
*/
uint32_t layer_state = 0;

static void layer_state_set(uint32_t state)
{
dprint("layer_state: ");
layer_debug(); dprint(" to ");
layer_state = state;
layer_debug(); dprintln();
clear_keyboard_but_mods(); // To avoid stuck keys
}

void layer_clear(void)
{
layer_state_set(0);
}

void layer_move(uint8_t layer)
{
layer_state_set(1UL<<layer);
}

void layer_on(uint8_t layer)
{
layer_state_set(layer_state | (1UL<<layer));
}

void layer_off(uint8_t layer)
{
layer_state_set(layer_state & ~(1UL<<layer));
}

void layer_invert(uint8_t layer)
{
layer_state_set(layer_state ^ (1UL<<layer));
}

void layer_or(uint32_t state)
{
layer_state_set(layer_state | state);
}
void layer_and(uint32_t state)
{
layer_state_set(layer_state & state);
}
void layer_xor(uint32_t state)
{
layer_state_set(layer_state ^ state);
}

void layer_debug(void)
{
dprintf("%08lX(%u)", layer_state, biton32(layer_state));
}
#endif

#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {0};

void update_source_layers_cache(keypos_t key, uint8_t layer)
{
const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
const uint8_t storage_row = key_number / 8;
const uint8_t storage_bit = key_number % 8;

for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
source_layers_cache[storage_row][bit_number] ^=
(-((layer & (1U << bit_number)) != 0)
^ source_layers_cache[storage_row][bit_number])
& (1U << storage_bit);
}
}

uint8_t read_source_layers_cache(keypos_t key)
{
const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
const uint8_t storage_row = key_number / 8;
const uint8_t storage_bit = key_number % 8;
uint8_t layer = 0;

for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
layer |=
((source_layers_cache[storage_row][bit_number]
& (1U << storage_bit)) != 0)
<< bit_number;
}

return layer;
}
#endif

/*
* Make sure the action triggered when the key is released is the same
* one as the one triggered on press. It's important for the mod keys
* when the layer is switched after the down event but before the up
* event as they may get stuck otherwise.
*/
action_t store_or_get_action(bool pressed, keypos_t key)
{
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
if (disable_action_cache) {
return layer_switch_get_action(key);
}

uint8_t layer;

if (pressed) {
layer = layer_switch_get_layer(key);
update_source_layers_cache(key, layer);
}
else {
layer = read_source_layers_cache(key);
}
return action_for_key(layer, key);
#else
return layer_switch_get_action(key);
#endif
}


int8_t layer_switch_get_layer(keypos_t key)
{
action_t action;
action.code = ACTION_TRANSPARENT;

#ifndef NO_ACTION_LAYER
uint32_t layers = layer_state | default_layer_state;
/* check top layer first */
for (int8_t i = 31; i >= 0; i--) {
if (layers & (1UL<<i)) {
action = action_for_key(i, key);
if (action.code != ACTION_TRANSPARENT) {
return i;
}
}
}
/* fall back to layer 0 */
return 0;
#else
return biton32(default_layer_state);
#endif
}

action_t layer_switch_get_action(keypos_t key)
{
return action_for_key(layer_switch_get_layer(key), key);
}

+ 89
- 0
tmk_core/common/action_layer.h View File

@@ -0,0 +1,89 @@
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/
#ifndef ACTION_LAYER_H
#define ACTION_LAYER_H

#include <stdint.h>
#include "keyboard.h"
#include "action.h"


/*
* Default Layer
*/
extern uint32_t default_layer_state;
void default_layer_debug(void);
void default_layer_set(uint32_t state);

#ifndef NO_ACTION_LAYER
/* bitwise operation */
void default_layer_or(uint32_t state);
void default_layer_and(uint32_t state);
void default_layer_xor(uint32_t state);
#else
#define default_layer_or(state)
#define default_layer_and(state)
#define default_layer_xor(state)
#endif


/*
* Keymap Layer
*/
#ifndef NO_ACTION_LAYER
extern uint32_t layer_state;
void layer_debug(void);
void layer_clear(void);
void layer_move(uint8_t layer);
void layer_on(uint8_t layer);
void layer_off(uint8_t layer);
void layer_invert(uint8_t layer);
/* bitwise operation */
void layer_or(uint32_t state);
void layer_and(uint32_t state);
void layer_xor(uint32_t state);
#else
#define layer_state 0
#define layer_clear()
#define layer_move(layer)
#define layer_on(layer)
#define layer_off(layer)
#define layer_invert(layer)

#define layer_or(state)
#define layer_and(state)
#define layer_xor(state)
#define layer_debug()

#endif

/* pressed actions cache */
#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
/* The number of bits needed to represent the layer number: log2(32). */
#define MAX_LAYER_BITS 5
void update_source_layers_cache(keypos_t key, uint8_t layer);
uint8_t read_source_layers_cache(keypos_t key);
#endif
action_t store_or_get_action(bool pressed, keypos_t key);

/* return the topmost non-transparent layer currently associated with key */
int8_t layer_switch_get_layer(keypos_t key);

/* return action depending on current layer status */
action_t layer_switch_get_action(keypos_t key);

#endif

+ 85
- 0
tmk_core/common/action_macro.c View File

@@ -0,0 +1,85 @@
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 "action.h"
#include "action_util.h"
#include "action_macro.h"
#include "wait.h"

#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif


#ifndef NO_ACTION_MACRO

#define MACRO_READ() (macro = MACRO_GET(macro_p++))
void action_macro_play(const macro_t *macro_p)
{
macro_t macro = END;
uint8_t interval = 0;

if (!macro_p) return;
while (true) {
switch (MACRO_READ()) {
case KEY_DOWN:
MACRO_READ();
dprintf("KEY_DOWN(%02X)\n", macro);
if (IS_MOD(macro)) {
add_macro_mods(MOD_BIT(macro));
send_keyboard_report();
} else {
register_code(macro);
}
break;
case KEY_UP:
MACRO_READ();
dprintf("KEY_UP(%02X)\n", macro);
if (IS_MOD(macro)) {
del_macro_mods(MOD_BIT(macro));
send_keyboard_report();
} else {
unregister_code(macro);
}
break;
case WAIT:
MACRO_READ();
dprintf("WAIT(%u)\n", macro);
{ uint8_t ms = macro; while (ms--) wait_ms(1); }
break;
case INTERVAL:
interval = MACRO_READ();
dprintf("INTERVAL(%u)\n", interval);
break;
case 0x04 ... 0x73:
dprintf("DOWN(%02X)\n", macro);
register_code(macro);
break;
case 0x84 ... 0xF3:
dprintf("UP(%02X)\n", macro);
unregister_code(macro&0x7F);
break;
case END:
default:
return;
}
// interval
{ uint8_t ms = interval; while (ms--) wait_ms(1); }
}
}
#endif

+ 102
- 0
tmk_core/common/action_macro.h View File

@@ -0,0 +1,102 @@
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/
#ifndef ACTION_MACRO_H
#define ACTION_MACRO_H
#include <stdint.h>
#include "progmem.h"


#define MACRO_NONE 0
#define MACRO(...) ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
#define MACRO_GET(p) pgm_read_byte(p)

typedef uint8_t macro_t;


#ifndef NO_ACTION_MACRO
void action_macro_play(const macro_t *macro_p);
#else
#define action_macro_play(macro)
#endif



/* Macro commands
* code(0x04-73) // key down(1byte)
* code(0x04-73) | 0x80 // key up(1byte)
* { KEY_DOWN, code(0x04-0xff) } // key down(2bytes)
* { KEY_UP, code(0x04-0xff) } // key up(2bytes)
* WAIT // wait milli-seconds
* INTERVAL // set interval between macro commands
* END // stop macro execution
*
* Ideas(Not implemented):
* modifiers
* system usage
* consumer usage
* unicode usage
* function call
* conditionals
* loop
*/
enum macro_command_id{
/* 0x00 - 0x03 */
END = 0x00,
KEY_DOWN,
KEY_UP,

/* 0x04 - 0x73 (reserved for keycode down) */

/* 0x74 - 0x83 */
WAIT = 0x74,
INTERVAL,

/* 0x84 - 0xf3 (reserved for keycode up) */

/* 0xf4 - 0xff */
};


/* TODO: keycode:0x04-0x73 can be handled by 1byte command else 2bytes are needed
* if keycode between 0x04 and 0x73
* keycode / (keycode|0x80)
* else
* {KEY_DOWN, keycode} / {KEY_UP, keycode}
*/
#define DOWN(key) KEY_DOWN, (key)
#define UP(key) KEY_UP, (key)
#define TYPE(key) DOWN(key), UP(key)
#define WAIT(ms) WAIT, (ms)
#define INTERVAL(ms) INTERVAL, (ms)

/* key down */
#define D(key) DOWN(KC_##key)
/* key up */
#define U(key) UP(KC_##key)
/* key type */
#define T(key) TYPE(KC_##key)
/* wait */
#define W(ms) WAIT(ms)
/* interval */
#define I(ms) INTERVAL(ms)

/* for backward comaptibility */
#define MD(key) DOWN(KC_##key)
#define MU(key) UP(KC_##key)


#endif /* ACTION_MACRO_H */

+ 377
- 0
tmk_core/common/action_tapping.c View File

@@ -0,0 +1,377 @@
#include <stdint.h>
#include <stdbool.h>
#include "action.h"
#include "action_layer.h"
#include "action_tapping.h"
#include "keycode.h"
#include "timer.h"

#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif

#ifndef NO_ACTION_TAPPING

#define IS_TAPPING() !IS_NOEVENT(tapping_key.event)
#define IS_TAPPING_PRESSED() (IS_TAPPING() && tapping_key.event.pressed)
#define IS_TAPPING_RELEASED() (IS_TAPPING() && !tapping_key.event.pressed)
#define IS_TAPPING_KEY(k) (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
#define WITHIN_TAPPING_TERM(e) (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)


static keyrecord_t tapping_key = {};
static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
static uint8_t waiting_buffer_head = 0;
static uint8_t waiting_buffer_tail = 0;

static bool process_tapping(keyrecord_t *record);
static bool waiting_buffer_enq(keyrecord_t record);
static void waiting_buffer_clear(void);
static bool waiting_buffer_typed(keyevent_t event);
static bool waiting_buffer_has_anykey_pressed(void);
static void waiting_buffer_scan_tap(void);
static void debug_tapping_key(void);
static void debug_waiting_buffer(void);


void action_tapping_process(keyrecord_t record)
{
if (process_tapping(&record)) {
if (!IS_NOEVENT(record.event)) {
debug("processed: "); debug_record(record); debug("\n");
}
} else {
if (!waiting_buffer_enq(record)) {
// clear all in case of overflow.
debug("OVERFLOW: CLEAR ALL STATES\n");
clear_keyboard();
waiting_buffer_clear();
tapping_key = (keyrecord_t){};
}
}

// process waiting_buffer
if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
debug("---- action_exec: process waiting_buffer -----\n");
}
for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
} else {
break;
}
}
if (!IS_NOEVENT(record.event)) {
debug("\n");
}
}


/* Tapping
*
* Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
* (without interfering by typing other key)
*/
/* return true when key event is processed or consumed. */
bool process_tapping(keyrecord_t *keyp)
{
keyevent_t event = keyp->event;

// if tapping
if (IS_TAPPING_PRESSED()) {
if (WITHIN_TAPPING_TERM(event)) {
if (tapping_key.tap.count == 0) {
if (IS_TAPPING_KEY(event.key) && !event.pressed) {
// first tap!
debug("Tapping: First tap(0->1).\n");
tapping_key.tap.count = 1;
debug_tapping_key();
process_record(&tapping_key);

// copy tapping state
keyp->tap = tapping_key.tap;
// enqueue
return false;
}
#if TAPPING_TERM >= 500
/* Process a key typed within TAPPING_TERM
* This can register the key before settlement of tapping,
* useful for long TAPPING_TERM but may prevent fast typing.
*/
else if (IS_RELEASED(event) && waiting_buffer_typed(event)) {
debug("Tapping: End. No tap. Interfered by typing key\n");
process_record(&tapping_key);
tapping_key = (keyrecord_t){};
debug_tapping_key();
// enqueue
return false;
}
#endif
/* Process release event of a key pressed before tapping starts
* Without this unexpected repeating will occur with having fast repeating setting
* https://github.com/tmk/tmk_keyboard/issues/60
*/
else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
// Modifier should be retained till end of this tapping.
action_t action = layer_switch_get_action(event.key);
switch (action.kind.id) {
case ACT_LMODS:
case ACT_RMODS:
if (action.key.mods && !action.key.code) return false;
if (IS_MOD(action.key.code)) return false;
break;
case ACT_LMODS_TAP:
case ACT_RMODS_TAP:
if (action.key.mods && keyp->tap.count == 0) return false;
if (IS_MOD(action.key.code)) return false;
break;
}
// Release of key should be process immediately.
debug("Tapping: release event of a key pressed before tapping\n");
process_record(keyp);
return true;
}
else {
// set interrupted flag when other key preesed during tapping
if (event.pressed) {
tapping_key.tap.interrupted = true;
}
// enqueue
return false;
}
}
// tap_count > 0
else {
if (IS_TAPPING_KEY(event.key) && !event.pressed) {
debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n");
keyp->tap = tapping_key.tap;
process_record(keyp);
tapping_key = *keyp;
debug_tapping_key();
return true;
}
else if (is_tap_key(event.key) && event.pressed) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last tap(>1).\n");
// unregister key
process_record(&(keyrecord_t){
.tap = tapping_key.tap,
.event.key = tapping_key.event.key,
.event.time = event.time,
.event.pressed = false
});
} else {
debug("Tapping: Start while last tap(1).\n");
}
tapping_key = *keyp;
waiting_buffer_scan_tap();
debug_tapping_key();
return true;
}
else {
if (!IS_NOEVENT(event)) {
debug("Tapping: key event while last tap(>0).\n");
}
process_record(keyp);
return true;
}
}
}
// after TAPPING_TERM
else {
if (tapping_key.tap.count == 0) {
debug("Tapping: End. Timeout. Not tap(0): ");
debug_event(event); debug("\n");
process_record(&tapping_key);
tapping_key = (keyrecord_t){};
debug_tapping_key();
return false;
} else {
if (IS_TAPPING_KEY(event.key) && !event.pressed) {
debug("Tapping: End. last timeout tap release(>0).");
keyp->tap = tapping_key.tap;
process_record(keyp);
tapping_key = (keyrecord_t){};
return true;
}
else if (is_tap_key(event.key) && event.pressed) {
if (tapping_key.tap.count > 1) {
debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
// unregister key
process_record(&(keyrecord_t){
.tap = tapping_key.tap,
.event.key = tapping_key.event.key,
.event.time = event.time,
.event.pressed = false
});
} else {
debug("Tapping: Start while last timeout tap(1).\n");
}
tapping_key = *keyp;
waiting_buffer_scan_tap();
debug_tapping_key();
return true;
}
else {
if (!IS_NOEVENT(event)) {
debug("Tapping: key event while last timeout tap(>0).\n");
}
process_record(keyp);
return true;
}
}
}
} else if (IS_TAPPING_RELEASED()) {
if (WITHIN_TAPPING_TERM(event)) {
if (event.pressed) {
if (IS_TAPPING_KEY(event.key)) {
if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
// sequential tap.
keyp->tap = tapping_key.tap;
if (keyp->tap.count < 15) keyp->tap.count += 1;
debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
process_record(keyp);
tapping_key = *keyp;
debug_tapping_key();
return true;
} else {
// FIX: start new tap again
tapping_key = *keyp;
return true;
}
} else if (is_tap_key(event.key)) {
// Sequential tap can be interfered with other tap key.
debug("Tapping: Start with interfering other tap.\n");
tapping_key = *keyp;
waiting_buffer_scan_tap();
debug_tapping_key();
return true;
} else {
// should none in buffer
// FIX: interrupted when other key is pressed
tapping_key.tap.interrupted = true;
process_record(keyp);
return true;
}
} else {
if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
process_record(keyp);
return true;
}
} else {
// FIX: process_aciton here?
// timeout. no sequential tap.
debug("Tapping: End(Timeout after releasing last tap): ");
debug_event(event); debug("\n");
tapping_key = (keyrecord_t){};
debug_tapping_key();
return false;
}
}
// not tapping state
else {
if (event.pressed && is_tap_key(event.key)) {
debug("Tapping: Start(Press tap key).\n");
tapping_key = *keyp;
waiting_buffer_scan_tap();
debug_tapping_key();
return true;
} else {
process_record(keyp);
return true;
}
}
}


/*
* Waiting buffer
*/
bool waiting_buffer_enq(keyrecord_t record)
{
if (IS_NOEVENT(record.event)) {
return true;
}

if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
debug("waiting_buffer_enq: Over flow.\n");
return false;
}

waiting_buffer[waiting_buffer_head] = record;
waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;

debug("waiting_buffer_enq: "); debug_waiting_buffer();
return true;
}

void waiting_buffer_clear(void)
{
waiting_buffer_head = 0;
waiting_buffer_tail = 0;
}

bool waiting_buffer_typed(keyevent_t event)
{
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed != waiting_buffer[i].event.pressed) {
return true;
}
}
return false;
}

__attribute__((unused))
bool waiting_buffer_has_anykey_pressed(void)
{
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
if (waiting_buffer[i].event.pressed) return true;
}
return false;
}

/* scan buffer for tapping */
void waiting_buffer_scan_tap(void)
{
// tapping already is settled
if (tapping_key.tap.count > 0) return;
// invalid state: tapping_key released && tap.count == 0
if (!tapping_key.event.pressed) return;

for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
!waiting_buffer[i].event.pressed &&
WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
tapping_key.tap.count = 1;
waiting_buffer[i].tap.count = 1;
process_record(&tapping_key);

debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
debug_waiting_buffer();
return;
}
}
}


/*
* debug print
*/
static void debug_tapping_key(void)
{
debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
}

static void debug_waiting_buffer(void)
{
debug("{ ");
for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
}
debug("}\n");
}

#endif

+ 39
- 0
tmk_core/common/action_tapping.h View File

@@ -0,0 +1,39 @@
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/
#ifndef ACTION_TAPPING_H
#define ACTION_TAPPING_H



/* period of tapping(ms) */
#ifndef TAPPING_TERM
#define TAPPING_TERM 200
#endif

/* tap count needed for toggling a feature */
#ifndef TAPPING_TOGGLE
#define TAPPING_TOGGLE 5
#endif

#define WAITING_BUFFER_SIZE 8


#ifndef NO_ACTION_TAPPING
void action_tapping_process(keyrecord_t record);
#endif

#endif

+ 378
- 0
tmk_core/common/action_util.c View File

@@ -0,0 +1,378 @@
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 "host.h"
#include "report.h"
#include "debug.h"
#include "action_util.h"
#include "action_layer.h"
#include "timer.h"

static inline void add_key_byte(uint8_t code);
static inline void del_key_byte(uint8_t code);
#ifdef NKRO_ENABLE
static inline void add_key_bit(uint8_t code);
static inline void del_key_bit(uint8_t code);
#endif

static uint8_t real_mods = 0;
static uint8_t weak_mods = 0;
static uint8_t macro_mods = 0;

#ifdef USB_6KRO_ENABLE
#define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
#define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
#define RO_INC(a) RO_ADD(a, 1)
#define RO_DEC(a) RO_SUB(a, 1)
static int8_t cb_head = 0;
static int8_t cb_tail = 0;
static int8_t cb_count = 0;
#endif

// TODO: pointer variable is not needed
//report_keyboard_t keyboard_report = {};
report_keyboard_t *keyboard_report = &(report_keyboard_t){};

#ifndef NO_ACTION_ONESHOT
static int8_t oneshot_mods = 0;
static int8_t oneshot_locked_mods = 0;
int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; }
void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; }
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
static int16_t oneshot_time = 0;
inline bool has_oneshot_mods_timed_out() {
return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT;
}
#endif
#endif

/* oneshot layer */
#ifndef NO_ACTION_ONESHOT
/* oneshot_layer_data bits
* LLLL LSSS
* where:
* L => are layer bits
* S => oneshot state bits
*/
static int8_t oneshot_layer_data = 0;

inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }

#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
static int16_t oneshot_layer_time = 0;
inline bool has_oneshot_layer_timed_out() {
return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT &&
!(get_oneshot_layer_state() & ONESHOT_TOGGLED);
}
#endif

/* Oneshot layer */
void set_oneshot_layer(uint8_t layer, uint8_t state)
{
oneshot_layer_data = layer << 3 | state;
layer_on(layer);
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_layer_time = timer_read();
#endif
}
void reset_oneshot_layer(void) {
oneshot_layer_data = 0;
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_layer_time = 0;
#endif
}
void clear_oneshot_layer_state(oneshot_fullfillment_t state)
{
uint8_t start_state = oneshot_layer_data;
oneshot_layer_data &= ~state;
if (!get_oneshot_layer_state() && start_state != oneshot_layer_data) {
layer_off(get_oneshot_layer());
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_layer_time = 0;
#endif
}
}
bool is_oneshot_layer_active(void)
{
return get_oneshot_layer_state();
}
#endif

void send_keyboard_report(void) {
keyboard_report->mods = real_mods;
keyboard_report->mods |= weak_mods;
keyboard_report->mods |= macro_mods;
#ifndef NO_ACTION_ONESHOT
if (oneshot_mods) {
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
if (has_oneshot_mods_timed_out()) {
dprintf("Oneshot: timeout\n");
clear_oneshot_mods();
}
#endif
keyboard_report->mods |= oneshot_mods;
if (has_anykey()) {
clear_oneshot_mods();
}
}

#endif
host_keyboard_send(keyboard_report);
}

/* key */
void add_key(uint8_t key)
{
#ifdef NKRO_ENABLE
if (keyboard_protocol && keyboard_nkro) {
add_key_bit(key);
return;
}
#endif
add_key_byte(key);
}

void del_key(uint8_t key)
{
#ifdef NKRO_ENABLE
if (keyboard_protocol && keyboard_nkro) {
del_key_bit(key);
return;
}
#endif
del_key_byte(key);
}

void clear_keys(void)
{
// not clear mods
for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
keyboard_report->raw[i] = 0;
}
}


/* modifier */
uint8_t get_mods(void) { return real_mods; }
void add_mods(uint8_t mods) { real_mods |= mods; }
void del_mods(uint8_t mods) { real_mods &= ~mods; }
void set_mods(uint8_t mods) { real_mods = mods; }
void clear_mods(void) { real_mods = 0; }

/* weak modifier */
uint8_t get_weak_mods(void) { return weak_mods; }
void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
void set_weak_mods(uint8_t mods) { weak_mods = mods; }
void clear_weak_mods(void) { weak_mods = 0; }

/* macro modifier */
uint8_t get_macro_mods(void) { return macro_mods; }
void add_macro_mods(uint8_t mods) { macro_mods |= mods; }
void del_macro_mods(uint8_t mods) { macro_mods &= ~mods; }
void set_macro_mods(uint8_t mods) { macro_mods = mods; }
void clear_macro_mods(void) { macro_mods = 0; }

/* Oneshot modifier */
#ifndef NO_ACTION_ONESHOT
void set_oneshot_mods(uint8_t mods)
{
oneshot_mods = mods;
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_time = timer_read();
#endif
}
void clear_oneshot_mods(void)
{
oneshot_mods = 0;
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_time = 0;
#endif
}
uint8_t get_oneshot_mods(void)
{
return oneshot_mods;
}
#endif

/*
* inspect keyboard state
*/
uint8_t has_anykey(void)
{
uint8_t cnt = 0;
for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
if (keyboard_report->raw[i])
cnt++;
}
return cnt;
}

uint8_t has_anymod(void)
{
return bitpop(real_mods);
}

uint8_t get_first_key(void)
{
#ifdef NKRO_ENABLE
if (keyboard_protocol && keyboard_nkro) {
uint8_t i = 0;
for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
;
return i<<3 | biton(keyboard_report->nkro.bits[i]);
}
#endif
#ifdef USB_6KRO_ENABLE
uint8_t i = cb_head;
do {
if (keyboard_report->keys[i] != 0) {
break;
}
i = RO_INC(i);
} while (i != cb_tail);
return keyboard_report->keys[i];
#else
return keyboard_report->keys[0];
#endif
}



/* local functions */
static inline void add_key_byte(uint8_t code)
{
#ifdef USB_6KRO_ENABLE
int8_t i = cb_head;
int8_t empty = -1;
if (cb_count) {
do {
if (keyboard_report->keys[i] == code) {
return;
}
if (empty == -1 && keyboard_report->keys[i] == 0) {
empty = i;
}
i = RO_INC(i);
} while (i != cb_tail);
if (i == cb_tail) {
if (cb_tail == cb_head) {
// buffer is full
if (empty == -1) {
// pop head when has no empty space
cb_head = RO_INC(cb_head);
cb_count--;
}
else {
// left shift when has empty space
uint8_t offset = 1;
i = RO_INC(empty);
do {
if (keyboard_report->keys[i] != 0) {
keyboard_report->keys[empty] = keyboard_report->keys[i];
keyboard_report->keys[i] = 0;
empty = RO_INC(empty);
}
else {
offset++;
}
i = RO_INC(i);
} while (i != cb_tail);
cb_tail = RO_SUB(cb_tail, offset);
}
}
}
}
// add to tail
keyboard_report->keys[cb_tail] = code;
cb_tail = RO_INC(cb_tail);
cb_count++;
#else
int8_t i = 0;
int8_t empty = -1;
for (; i < KEYBOARD_REPORT_KEYS; i++) {
if (keyboard_report->keys[i] == code) {
break;
}
if (empty == -1 && keyboard_report->keys[i] == 0) {
empty = i;
}
}
if (i == KEYBOARD_REPORT_KEYS) {
if (empty != -1) {
keyboard_report->keys[empty] = code;
}
}
#endif
}

static inline void del_key_byte(uint8_t code)
{
#ifdef USB_6KRO_ENABLE
uint8_t i = cb_head;
if (cb_count) {
do {
if (keyboard_report->keys[i] == code) {
keyboard_report->keys[i] = 0;
cb_count--;
if (cb_count == 0) {
// reset head and tail
cb_tail = cb_head = 0;
}
if (i == RO_DEC(cb_tail)) {
// left shift when next to tail
do {
cb_tail = RO_DEC(cb_tail);
if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
break;
}
} while (cb_tail != cb_head);
}
break;
}
i = RO_INC(i);
} while (i != cb_tail);
}
#else
for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
if (keyboard_report->keys[i] == code) {
keyboard_report->keys[i] = 0;
}
}
#endif
}

#ifdef NKRO_ENABLE
static inline void add_key_bit(uint8_t code)
{
if ((code>>3) < KEYBOARD_REPORT_BITS) {
keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
} else {
dprintf("add_key_bit: can't add: %02X\n", code);
}
}

static inline void del_key_bit(uint8_t code)
{
if ((code>>3) < KEYBOARD_REPORT_BITS) {
keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
} else {
dprintf("del_key_bit: can't del: %02X\n", code);
}
}
#endif

+ 93
- 0
tmk_core/common/action_util.h View File

@@ -0,0 +1,93 @@
/*
Copyright 2013 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/
#ifndef ACTION_UTIL_H
#define ACTION_UTIL_H

#include <stdint.h>
#include "report.h"

#ifdef __cplusplus
extern "C" {
#endif

extern report_keyboard_t *keyboard_report;

void send_keyboard_report(void);

/* key */
void add_key(uint8_t key);
void del_key(uint8_t key);
void clear_keys(void);

/* modifier */
uint8_t get_mods(void);
void add_mods(uint8_t mods);
void del_mods(uint8_t mods);
void set_mods(uint8_t mods);
void clear_mods(void);

/* weak modifier */
uint8_t get_weak_mods(void);
void add_weak_mods(uint8_t mods);
void del_weak_mods(uint8_t mods);
void set_weak_mods(uint8_t mods);
void clear_weak_mods(void);

/* macro modifier */
uint8_t get_macro_mods(void);
void add_macro_mods(uint8_t mods);
void del_macro_mods(uint8_t mods);
void set_macro_mods(uint8_t mods);
void clear_macro_mods(void);

/* oneshot modifier */
void set_oneshot_mods(uint8_t mods);
uint8_t get_oneshot_mods(void);
void clear_oneshot_mods(void);
void oneshot_toggle(void);
void oneshot_enable(void);
void oneshot_disable(void);
bool has_oneshot_mods_timed_out(void);

int8_t get_oneshot_locked_mods(void);
void set_oneshot_locked_mods(int8_t mods);
void clear_oneshot_locked_mods(void);

typedef enum {
ONESHOT_PRESSED = 0b01,
ONESHOT_OTHER_KEY_PRESSED = 0b10,
ONESHOT_START = 0b11,
ONESHOT_TOGGLED = 0b100
} oneshot_fullfillment_t;
void set_oneshot_layer(uint8_t layer, uint8_t state);
uint8_t get_oneshot_layer(void);
void clear_oneshot_layer_state(oneshot_fullfillment_t state);
void reset_oneshot_layer(void);
bool is_oneshot_layer_active(void);
uint8_t get_oneshot_layer_state(void);
bool has_oneshot_layer_timed_out(void);

/* inspect */
uint8_t has_anykey(void);
uint8_t has_anymod(void);
uint8_t get_first_key(void);

#ifdef __cplusplus
}
#endif

#endif

+ 185
- 0
tmk_core/common/avr/bootloader.c View File

@@ -0,0 +1,185 @@
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include "bootloader.h"

#ifdef PROTOCOL_LUFA
#include <LUFA/Drivers/USB/USB.h>
#endif


/* Bootloader Size in *bytes*
*
* AVR Boot section size are defined by setting BOOTSZ fuse in fact. Consult with your MCU datasheet.
* Note that 'Word'(2 bytes) size and address are used in datasheet while TMK uses 'Byte'.
*
*
* Size of Bootloaders in bytes:
* Atmel DFU loader(ATmega32U4) 4096
* Atmel DFU loader(AT90USB128) 8192
* LUFA bootloader(ATmega32U4) 4096
* Arduino Caterina(ATmega32U4) 4096
* USBaspLoader(ATmega***) 2048
* Teensy halfKay(ATmega32U4) 512
* Teensy++ halfKay(AT90USB128) 1024
*
*
* AVR Boot section is located at the end of Flash memory like the followings.
*
*
* byte Atmel/LUFA(ATMega32u4) byte Atmel(AT90SUB128)
* 0x0000 +---------------+ 0x00000 +---------------+
* | | | |
* | | | |
* | Application | | Application |
* | | | |
* = = = =
* | | 32KB-4KB | | 128KB-8KB
* 0x6000 +---------------+ 0x1FC00 +---------------+
* | Bootloader | 4KB | Bootloader | 8KB
* 0x7FFF +---------------+ 0x1FFFF +---------------+
*
*
* byte Teensy(ATMega32u4) byte Teensy++(AT90SUB128)
* 0x0000 +---------------+ 0x00000 +---------------+
* | | | |
* | | | |
* | Application | | Application |
* | | | |
* = = = =
* | | 32KB-512B | | 128KB-1KB
* 0x7E00 +---------------+ 0x1FC00 +---------------+
* | Bootloader | 512B | Bootloader | 1KB
* 0x7FFF +---------------+ 0x1FFFF +---------------+
*/
#ifndef BOOTLOADER_SIZE
#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
#define BOOTLOADER_SIZE 4096
#endif

#define FLASH_SIZE (FLASHEND + 1L)
#define BOOTLOADER_START (FLASH_SIZE - BOOTLOADER_SIZE)


/*
* Entering the Bootloader via Software
* http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
*/
#define BOOTLOADER_RESET_KEY 0xB007B007
uint32_t reset_key __attribute__ ((section (".noinit")));

/* initialize MCU status by watchdog reset */
void bootloader_jump(void) {
#ifdef PROTOCOL_LUFA
USB_Disable();
cli();
_delay_ms(2000);
#endif

#ifdef PROTOCOL_PJRC
cli();
UDCON = 1;
USBCON = (1<<FRZCLK);
UCSR1B = 0;
_delay_ms(5);
#endif

// watchdog reset
reset_key = BOOTLOADER_RESET_KEY;
wdt_enable(WDTO_250MS);
for (;;);
}


/* this runs before main() */
void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
void bootloader_jump_after_watchdog_reset(void)
{
if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
reset_key = 0;

// My custom USBasploader requires this to come up.
MCUSR = 0;

// Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
MCUSR &= ~(1<<WDRF);
wdt_disable();

// This is compled into 'icall', address should be in word unit, not byte.
((void (*)(void))(BOOTLOADER_START/2))();
}
}


#if 0
/* Jumping To The Bootloader
* http://www.pjrc.com/teensy/jump_to_bootloader.html
*
* This method doen't work when using LUFA. idk why.
* - needs to initialize more regisers or interrupt setting?
*/
void bootloader_jump(void) {
#ifdef PROTOCOL_LUFA
USB_Disable();
cli();
_delay_ms(2000);
#endif

#ifdef PROTOCOL_PJRC
cli();
UDCON = 1;
USBCON = (1<<FRZCLK);
UCSR1B = 0;
_delay_ms(5);
#endif

/*
* Initialize
*/
#if defined(__AVR_AT90USB162__)
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
DDRB = 0; DDRC = 0; DDRD = 0;
PORTB = 0; PORTC = 0; PORTD = 0;
#elif defined(__AVR_ATmega32U4__)
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;
#elif defined(__AVR_AT90USB646__)
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#elif defined(__AVR_AT90USB1286__)
EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
#endif

/*
* USBaspLoader
*/
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
// This makes custom USBasploader come up.
MCUSR = 0;

// initialize ports
PORTB = 0; PORTC= 0; PORTD = 0;
DDRB = 0; DDRC= 0; DDRD = 0;

// disable interrupts
EIMSK = 0; EECR = 0; SPCR = 0;
ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
ADCSRA = 0; TWCR = 0; UCSR0B = 0;
#endif

// This is compled into 'icall', address should be in word unit, not byte.
((void (*)(void))(BOOTLOADER_START/2))();
}
#endif

+ 53
- 0
tmk_core/common/avr/eeconfig.c View File

@@ -0,0 +1,53 @@
#include <stdint.h>
#include <stdbool.h>
#include <avr/eeprom.h>
#include "eeconfig.h"

void eeconfig_init(void)
{
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
eeprom_update_byte(EECONFIG_DEBUG, 0);
eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
eeprom_update_byte(EECONFIG_KEYMAP, 0);
eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
#ifdef BACKLIGHT_ENABLE
eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
#endif
#ifdef AUDIO_ENABLE
eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
#endif
}

void eeconfig_enable(void)
{
eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
}

void eeconfig_disable(void)
{
eeprom_update_word(EECONFIG_MAGIC, 0xFFFF);
}

bool eeconfig_is_enabled(void)
{
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
}

uint8_t eeconfig_read_debug(void) { return eeprom_read_byte(EECONFIG_DEBUG); }
void eeconfig_update_debug(uint8_t val) { eeprom_update_byte(EECONFIG_DEBUG, val); }

uint8_t eeconfig_read_default_layer(void) { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); }
void eeconfig_update_default_layer(uint8_t val) { eeprom_update_byte(EECONFIG_DEFAULT_LAYER, val); }

uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMAP); }
void eeconfig_update_keymap(uint8_t val) { eeprom_update_byte(EECONFIG_KEYMAP, val); }

#ifdef BACKLIGHT_ENABLE
uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
#endif

#ifdef AUDIO_ENABLE
uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO); }
void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); }
#endif

+ 146
- 0
tmk_core/common/avr/suspend.c View File

@@ -0,0 +1,146 @@
#include <stdbool.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include "matrix.h"
#include "action.h"
#include "backlight.h"
#include "suspend_avr.h"
#include "suspend.h"
#include "timer.h"
#include "led.h"

#ifdef PROTOCOL_LUFA
#include "lufa.h"
#endif

#ifdef AUDIO_ENABLE
#include "audio.h"
#endif /* AUDIO_ENABLE */



#define wdt_intr_enable(value) \
__asm__ __volatile__ ( \
"in __tmp_reg__,__SREG__" "\n\t" \
"cli" "\n\t" \
"wdr" "\n\t" \
"sts %0,%1" "\n\t" \
"out __SREG__,__tmp_reg__" "\n\t" \
"sts %0,%2" "\n\t" \
: /* no outputs */ \
: "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
"r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
"r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
_BV(WDIE) | (value & 0x07)) ) \
: "r0" \
)


void suspend_idle(uint8_t time)
{
cli();
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
sei();
sleep_cpu();
sleep_disable();
}

/* Power down MCU with watchdog timer
* wdto: watchdog timer timeout defined in <avr/wdt.h>
* WDTO_15MS
* WDTO_30MS
* WDTO_60MS
* WDTO_120MS
* WDTO_250MS
* WDTO_500MS
* WDTO_1S
* WDTO_2S
* WDTO_4S
* WDTO_8S
*/
static uint8_t wdt_timeout = 0;
static void power_down(uint8_t wdto)
{
#ifdef PROTOCOL_LUFA
if (USB_DeviceState == DEVICE_STATE_Configured) return;
#endif
wdt_timeout = wdto;

// Watchdog Interrupt Mode
wdt_intr_enable(wdto);

#ifdef BACKLIGHT_ENABLE
backlight_set(0);
#endif

// Turn off LED indicators
led_set(0);

#ifdef AUDIO_ENABLE
// This sometimes disables the start-up noise, so it's been disabled
// stop_all_notes();
#endif /* AUDIO_ENABLE */

// TODO: more power saving
// See PicoPower application note
// - I/O port input with pullup
// - prescale clock
// - BOD disable
// - Power Reduction Register PRR
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei();
sleep_cpu();
sleep_disable();

// Disable watchdog after sleep
wdt_disable();
}

void suspend_power_down(void)
{
power_down(WDTO_15MS);
}

__attribute__ ((weak)) void matrix_power_up(void) {}
__attribute__ ((weak)) void matrix_power_down(void) {}
bool suspend_wakeup_condition(void)
{
#ifdef BACKLIGHT_ENABLE
backlight_set(0);
#endif
matrix_power_up();
matrix_scan();
matrix_power_down();
if (matrix_key_count()) return true;
return false;
}

// run immediately after wakeup
void suspend_wakeup_init(void)
{
// clear keyboard state
clear_keyboard();
#ifdef BACKLIGHT_ENABLE
backlight_set(0);
backlight_init();
#endif
led_set(host_keyboard_leds());
}

#ifndef NO_SUSPEND_POWER_DOWN
/* watchdog timeout */
ISR(WDT_vect)
{
// compensate timer for sleep
switch (wdt_timeout) {
case WDTO_15MS:
timer_count += 15 + 2; // WDTO_15MS + 2(from observation)
break;
default:
;
}
}
#endif

+ 27
- 0
tmk_core/common/avr/suspend_avr.h View File

@@ -0,0 +1,27 @@
#ifndef SUSPEND_AVR_H
#define SUSPEND_AVR_H

#include <stdint.h>
#include <stdbool.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>


#define wdt_intr_enable(value) \
__asm__ __volatile__ ( \
"in __tmp_reg__,__SREG__" "\n\t" \
"cli" "\n\t" \
"wdr" "\n\t" \
"sts %0,%1" "\n\t" \
"out __SREG__,__tmp_reg__" "\n\t" \
"sts %0,%2" "\n\t" \
: /* no outputs */ \
: "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
"r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
"r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
_BV(WDIE) | (value & 0x07)) ) \
: "r0" \
)

#endif

+ 117
- 0
tmk_core/common/avr/timer.c View File

@@ -0,0 +1,117 @@
/*
Copyright 2011 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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 <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include "timer_avr.h"
#include "timer.h"


// counter resolution 1ms
// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
volatile uint32_t timer_count = 0;

void timer_init(void)
{
// Timer0 CTC mode
TCCR0A = 0x02;

#if TIMER_PRESCALER == 1
TCCR0B = 0x01;
#elif TIMER_PRESCALER == 8
TCCR0B = 0x02;
#elif TIMER_PRESCALER == 64
TCCR0B = 0x03;
#elif TIMER_PRESCALER == 256
TCCR0B = 0x04;
#elif TIMER_PRESCALER == 1024
TCCR0B = 0x05;
#else
# error "Timer prescaler value is NOT vaild."
#endif

OCR0A = TIMER_RAW_TOP;
TIMSK0 = (1<<OCIE0A);
}

inline
void timer_clear(void)
{
uint8_t sreg = SREG;
cli();
timer_count = 0;
SREG = sreg;
}

inline
uint16_t timer_read(void)
{
uint32_t t;

uint8_t sreg = SREG;
cli();
t = timer_count;
SREG = sreg;

return (t & 0xFFFF);
}

inline
uint32_t timer_read32(void)
{
uint32_t t;

uint8_t sreg = SREG;
cli();
t = timer_count;
SREG = sreg;

return t;
}

inline
uint16_t timer_elapsed(uint16_t last)
{
uint32_t t;

uint8_t sreg = SREG;
cli();
t = timer_count;
SREG = sreg;

return TIMER_DIFF_16((t & 0xFFFF), last);
}

inline
uint32_t timer_elapsed32(uint32_t last)
{
uint32_t t;

uint8_t sreg = SREG;
cli();
t = timer_count;
SREG = sreg;

return TIMER_DIFF_32(t, last);
}

// excecuted once per 1ms.(excess for just timer count?)
ISR(TIMER0_COMPA_vect)
{
timer_count++;
}

+ 42
- 0
tmk_core/common/avr/timer_avr.h View File

@@ -0,0 +1,42 @@
/*
Copyright 2011 Jun Wako <[email protected]>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 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/>.
*/

#ifndef TIMER_AVR_H
#define TIMER_AVR_H 1

#include <stdint.h>

#ifndef TIMER_PRESCALER
# if F_CPU > 16000000
# define TIMER_PRESCALER 256
# elif F_CPU > 2000000
# define TIMER_PRESCALER 64
# elif F_CPU > 250000
# define TIMER_PRESCALER 8
# else
# define TIMER_PRESCALER 1
# endif
#endif
#define TIMER_RAW_FREQ (F_CPU/TIMER_PRESCALER)
#define TIMER_RAW TCNT0
#define TIMER_RAW_TOP (TIMER_RAW_FREQ/1000)

#if (TIMER_RAW_TOP > 255)
# error "Timer0 can't count 1ms at this clock freq. Use larger prescaler."
#endif

#endif

+ 500
- 0
tmk_core/common/avr/xprintf.S View File

@@ -0,0 +1,500 @@
;---------------------------------------------------------------------------;
; Extended itoa, puts, printf and atoi (C)ChaN, 2011
;---------------------------------------------------------------------------;

// Base size is 152 bytes
#define CR_CRLF 0 // Convert \n to \r\n (+10 bytes)
#define USE_XPRINTF 1 // Enable xprintf function (+194 bytes)
#define USE_XSPRINTF 0 // Add xsprintf function (+78 bytes)
#define USE_XFPRINTF 0 // Add xfprintf function (+54 bytes)
#define USE_XATOI 0 // Enable xatoi function (+182 bytes)


#if FLASHEND > 0x1FFFF
#error xitoa module does not support 256K devices
#endif

.nolist
#include <avr/io.h> // Include device specific definitions.
.list

#ifdef SPM_PAGESIZE // Recent devices have "lpm Rd,Z+" and "movw".
.macro _LPMI reg
lpm \reg, Z+
.endm
.macro _MOVW dh,dl, sh,sl
movw \dl, \sl
.endm
#else // Earlier devices do not have "lpm Rd,Z+" nor "movw".
.macro _LPMI reg
lpm
mov \reg, r0
adiw ZL, 1
.endm
.macro _MOVW dh,dl, sh,sl
mov \dl, \sl
mov \dh, \sh
.endm
#endif



;---------------------------------------------------------------------------
; Stub function to forward to user output function
;
;Prototype: void xputc (char chr // a character to be output
; );
;Size: 12/12 words

.section .bss
.global xfunc_out ; xfunc_out must be initialized before using this module.
xfunc_out: .ds.w 1
.section .text


.func xputc
.global xputc
xputc:
#if CR_CRLF
cpi r24, 10 ;LF --> CRLF
brne 1f ;
ldi r24, 13 ;
rcall 1f ;
ldi r24, 10 ;/
1:
#endif
push ZH
push ZL
lds ZL, xfunc_out+0 ;Pointer to the registered output function.
lds ZH, xfunc_out+1 ;/
sbiw ZL, 0 ;Skip if null
breq 2f ;/
icall
2: pop ZL
pop ZH
ret
.endfunc



;---------------------------------------------------------------------------
; Direct ROM string output
;
;Prototype: void xputs (const char *str_p // rom string to be output
; );

.func xputs
.global xputs
xputs:
_MOVW ZH,ZL, r25,r24 ; Z = pointer to rom string
1: _LPMI r24
cpi r24, 0
breq 2f
rcall xputc
rjmp 1b
2: ret
.endfunc


;---------------------------------------------------------------------------
; Extended direct numeral string output (32bit version)
;
;Prototype: void xitoa (long value, // value to be output
; char radix, // radix
; char width); // minimum width
;

.func xitoa
.global xitoa
xitoa:
;r25:r22 = value, r20 = base, r18 = digits
clr r31 ;r31 = stack level
ldi r30, ' ' ;r30 = sign
ldi r19, ' ' ;r19 = filler
sbrs r20, 7 ;When base indicates signd format and the value
rjmp 0f ;is minus, add a '-'.
neg r20 ;
sbrs r25, 7 ;
rjmp 0f ;
ldi r30, '-' ;
com r22 ;
com r23 ;
com r24 ;
com r25 ;
adc r22, r1 ;
adc r23, r1 ;
adc r24, r1 ;
adc r25, r1 ;/
0: sbrs r18, 7 ;When digits indicates zero filled,
rjmp 1f ;filler is '0'.
neg r18 ;
ldi r19, '0' ;/
;----- string conversion loop
1: ldi r21, 32 ;r26 = r25:r22 % r20
clr r26 ;r25:r22 /= r20
2: lsl r22 ;
rol r23 ;
rol r24 ;
rol r25 ;
rol r26 ;
cp r26, r20 ;
brcs 3f ;
sub r26, r20 ;
inc r22 ;
3: dec r21 ;
brne 2b ;/
cpi r26, 10 ;r26 is a numeral digit '0'-'F'
brcs 4f ;
subi r26, -7 ;
4: subi r26, -'0' ;/
push r26 ;Stack it
inc r31 ;/
cp r22, r1 ;Repeat until r25:r22 gets zero
cpc r23, r1 ;
cpc r24, r1 ;
cpc r25, r1 ;
brne 1b ;/

cpi r30, '-' ;Minus sign if needed
brne 5f ;
push r30 ;
inc r31 ;/
5: cp r31, r18 ;Filler
brcc 6f ;
push r19 ;
inc r31 ;
rjmp 5b ;/

6: pop r24 ;Flush stacked digits and exit
rcall xputc ;
dec r31 ;
brne 6b ;/

ret
.endfunc



;---------------------------------------------------------------------------;
; Formatted string output (16/32bit version)
;
;Prototype:
; void __xprintf (const char *format_p, ...);
; void __xsprintf(char*, const char *format_p, ...);
; void __xfprintf(void(*func)(char), const char *format_p, ...);
;

#if USE_XPRINTF

.func xvprintf
xvprintf:
ld ZL, Y+ ;Z = pointer to format string
ld ZH, Y+ ;/

0: _LPMI r24 ;Get a format char
cpi r24, 0 ;End of format string?
breq 90f ;/
cpi r24, '%' ;Is format?
breq 20f ;/
1: rcall xputc ;Put a normal character
rjmp 0b ;/
90: ret

20: ldi r18, 0 ;r18: digits
clt ;T: filler
_LPMI r21 ;Get flags
cpi r21, '%' ;Is a %?
breq 1b ;/
cpi r21, '0' ;Zero filled?
brne 23f ;
set ;/
22: _LPMI r21 ;Get width
23: cpi r21, '9'+1 ;
brcc 24f ;
subi r21, '0' ;
brcs 90b ;
lsl r18 ;
mov r0, r18 ;
lsl r18 ;
lsl r18 ;
add r18, r0 ;
add r18, r21 ;
rjmp 22b ;/

24: brtc 25f ;get value (low word)
neg r18 ;
25: ld r24, Y+ ;
ld r25, Y+ ;/
cpi r21, 'c' ;Is type character?
breq 1b ;/
cpi r21, 's' ;Is type RAM string?
breq 50f ;/
cpi r21, 'S' ;Is type ROM string?
breq 60f ;/
_MOVW r23,r22,r25,r24 ;r25:r22 = value
clr r24 ;
clr r25 ;
clt ;/
cpi r21, 'l' ;Is long int?
brne 26f ;
ld r24, Y+ ;get value (high word)
ld r25, Y+ ;
set ;
_LPMI r21 ;/
26: cpi r21, 'd' ;Is type signed decimal?
brne 27f ;/
ldi r20, -10 ;
brts 40f ;
sbrs r23, 7 ;
rjmp 40f ;
ldi r24, -1 ;
ldi r25, -1 ;
rjmp 40f ;/
27: cpi r21, 'u' ;Is type unsigned decimal?
ldi r20, 10 ;
breq 40f ;/
cpi r21, 'X' ;Is type hexdecimal?
ldi r20, 16 ;
breq 40f ;/
cpi r21, 'b' ;Is type binary?
ldi r20, 2 ;
breq 40f ;/
ret ;abort
40: push ZH ;Output the value
push ZL ;
rcall xitoa ;
42: pop ZL ;
pop ZH ;
rjmp 0b ;/

50: push ZH ;Put a string on the RAM
push ZL
_MOVW ZH,ZL, r25,r24
51: ld r24, Z+
cpi r24, 0
breq 42b
rcall xputc
rjmp 51b

60: push ZH ;Put a string on the ROM
push ZL
rcall xputs
rjmp 42b
.endfunc


.func __xprintf
.global __xprintf
__xprintf:
push YH
push YL
in YL, _SFR_IO_ADDR(SPL)
#ifdef SPH
in YH, _SFR_IO_ADDR(SPH)
#else
clr YH
#endif
adiw YL, 5 ;Y = pointer to arguments
rcall xvprintf
pop YL
pop YH
ret
.endfunc


#if USE_XSPRINTF

.func __xsprintf
putram:
_MOVW ZH,ZL, r15,r14
st Z+, r24
_MOVW r15,r14, ZH,ZL
ret
.global __xsprintf
__xsprintf:
push YH
push YL
in YL, _SFR_IO_ADDR(SPL)
#ifdef SPH
in YH, _SFR_IO_ADDR(SPH)
#else
clr YH
#endif
adiw YL, 5 ;Y = pointer to arguments
lds ZL, xfunc_out+0 ;Save registered output function
lds ZH, xfunc_out+1 ;
push ZL ;
push ZH ;/
ldi ZL, lo8(pm(putram));Set local output function
ldi ZH, hi8(pm(putram));
sts xfunc_out+0, ZL ;
sts xfunc_out+1, ZH ;/
push r15 ;Initialize pointer to string buffer
push r14 ;
ld r14, Y+ ;
ld r15, Y+ ;/
rcall xvprintf
_MOVW ZH,ZL, r15,r14 ;Terminate string
st Z, r1 ;
pop r14 ;
pop r15 ;/
pop ZH ;Restore registered output function
pop ZL ;
sts xfunc_out+0, ZL ;
sts xfunc_out+1, ZH ;/
pop YL
pop YH
ret
.endfunc
#endif


#if USE_XFPRINTF
.func __xfprintf
.global __xfprintf
__xfprintf:
push YH
push YL
in YL, _SFR_IO_ADDR(SPL)
#ifdef SPH
in YH, _SFR_IO_ADDR(SPH)
#else
clr YH
#endif
adiw YL, 5 ;Y = pointer to arguments
lds ZL, xfunc_out+0 ;Save registered output function
lds ZH, xfunc_out+1 ;
push ZL ;
push ZH ;/
ld ZL, Y+ ;Set output function
ld ZH, Y+ ;
sts xfunc_out+0, ZL ;
sts xfunc_out+1, ZH ;/
rcall xvprintf
pop ZH ;Restore registered output function
pop ZL ;
sts xfunc_out+0, ZL ;
sts xfunc_out+1, ZH ;/
pop YL
pop YH
ret
.endfunc
#endif

#endif



;---------------------------------------------------------------------------
; Extended numeral string input
;
;Prototype:
; char xatoi ( /* 1: Successful, 0: Failed */
; const char **str, /* pointer to pointer to source string */
; long *res /* result */
; );
;


#if USE_XATOI
.func xatoi
.global xatoi
xatoi:
_MOVW r1, r0, r23, r22
_MOVW XH, XL, r25, r24
ld ZL, X+
ld ZH, X+
clr r18 ;r21:r18 = 0;
clr r19 ;
clr r20 ;
clr r21 ;/
clt ;T = 0;

ldi r25, 10 ;r25 = 10;
rjmp 41f ;/
40: adiw ZL, 1 ;Z++;
41: ld r22, Z ;r22 = *Z;
cpi r22, ' ' ;if(r22 == ' ') continue
breq 40b ;/
brcs 70f ;if(r22 < ' ') error;
cpi r22, '-' ;if(r22 == '-') {
brne 42f ; T = 1;
set ; continue;
rjmp 40b ;}
42: cpi r22, '9'+1 ;if(r22 > '9') error;
brcc 70f ;/
cpi r22, '0' ;if(r22 < '0') error;
brcs 70f ;/
brne 51f ;if(r22 > '0') cv_start;
ldi r25, 8 ;r25 = 8;
adiw ZL, 1 ;r22 = *(++Z);
ld r22, Z ;/
cpi r22, ' '+1 ;if(r22 <= ' ') exit;
brcs 80f ;/
cpi r22, 'b' ;if(r22 == 'b') {
brne 43f ; r25 = 2;
ldi r25, 2 ; cv_start;
rjmp 50f ;}
43: cpi r22, 'x' ;if(r22 != 'x') error;
brne 51f ;/
ldi r25, 16 ;r25 = 16;

50: adiw ZL, 1 ;Z++;
ld r22, Z ;r22 = *Z;
51: cpi r22, ' '+1 ;if(r22 <= ' ') break;
brcs 80f ;/
cpi r22, 'a' ;if(r22 >= 'a') r22 =- 0x20;
brcs 52f ;
subi r22, 0x20 ;/
52: subi r22, '0' ;if((r22 -= '0') < 0) error;
brcs 70f ;/
cpi r22, 10 ;if(r22 >= 10) {
brcs 53f ; r22 -= 7;
subi r22, 7 ; if(r22 < 10)
cpi r22, 10 ;
brcs 70f ;}
53: cp r22, r25 ;if(r22 >= r25) error;
brcc 70f ;/
60: ldi r24, 33 ;r21:r18 *= r25;
sub r23, r23 ;
61: brcc 62f ;
add r23, r25 ;
62: lsr r23 ;
ror r21 ;
ror r20 ;
ror r19 ;
ror r18 ;
dec r24 ;
brne 61b ;/
add r18, r22 ;r21:r18 += r22;
adc r19, r24 ;
adc r20, r24 ;
adc r21, r24 ;/
rjmp 50b ;repeat

70: ldi r24, 0
rjmp 81f
80: ldi r24, 1
81: brtc 82f
clr r22
com r18
com r19
com r20
com r21
adc r18, r22
adc r19, r22
adc r20, r22
adc r21, r22
82: st -X, ZH
st -X, ZL
_MOVW XH, XL, r1, r0
st X+, r18
st X+, r19
st X+, r20
st X+, r21
clr r1
ret
.endfunc
#endif



+ 0
- 0
tmk_core/common/avr/xprintf.h View File


Some files were not shown because too many files changed in this diff