Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38aefaf78e | ||
|
|
60b2a9a5ea | ||
|
|
537623c9db | ||
|
|
ec053c8283 | ||
|
|
c5ffd182c8 | ||
|
|
93bce83255 | ||
|
|
b0b433f3cf | ||
|
|
3e6f7bc6bf | ||
|
|
f166a22c98 | ||
|
|
41b9be560d | ||
|
|
4f01c8623f |
No files matched your search
+21
-2
@@ -229,13 +229,32 @@ ifeq ($(strip $(LCD_ENABLE)), yes)
|
|||||||
CIE1931_CURVE = yes
|
CIE1931_CURVE = yes
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
|
# backward compat
|
||||||
|
ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
|
||||||
|
BACKLIGHT_ENABLE = custom
|
||||||
|
endif
|
||||||
|
|
||||||
|
VALID_BACKLIGHT_TYPES := yes custom
|
||||||
|
|
||||||
|
BACKLIGHT_ENABLE ?= no
|
||||||
|
ifneq ($(strip $(BACKLIGHT_ENABLE)), no)
|
||||||
|
ifeq ($(filter $(BACKLIGHT_ENABLE),$(VALID_BACKLIGHT_TYPES)),)
|
||||||
|
$(error BACKLIGHT_ENABLE="$(BACKLIGHT_ENABLE)" is not a valid backlight type)
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
|
ifeq ($(strip $(VISUALIZER_ENABLE)), yes)
|
||||||
CIE1931_CURVE = yes
|
CIE1931_CURVE = yes
|
||||||
endif
|
endif
|
||||||
ifeq ($(strip $(BACKLIGHT_CUSTOM_DRIVER)), yes)
|
|
||||||
|
ifeq ($(strip $(BACKLIGHT_ENABLE)), custom)
|
||||||
OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
|
OPT_DEFS += -DBACKLIGHT_CUSTOM_DRIVER
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(PLATFORM),AVR)
|
||||||
|
SRC += $(QUANTUM_DIR)/backlight/backlight_avr.c
|
||||||
|
else
|
||||||
|
SRC += $(QUANTUM_DIR)/backlight/backlight_arm.c
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(CIE1931_CURVE)), yes)
|
ifeq ($(strip $(CIE1931_CURVE)), yes)
|
||||||
|
|||||||
+37
-13
@@ -1,6 +1,8 @@
|
|||||||
# Backlighting
|
# Backlighting
|
||||||
|
|
||||||
Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. QMK is able to control the brightness of these LEDs by switching them on and off rapidly in a certain ratio, a technique known as *Pulse Width Modulation*, or PWM. By altering the duty cycle of the PWM signal, it creates the illusion of dimming.
|
Many keyboards support backlit keys by way of individual LEDs placed through or underneath the keyswitches. This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously install multiple different single coloured LEDs on a keyboard.
|
||||||
|
|
||||||
|
QMK is able to control the brightness of these LEDs by switching them on and off rapidly in a certain ratio, a technique known as *Pulse Width Modulation*, or PWM. By altering the duty cycle of the PWM signal, it creates the illusion of dimming.
|
||||||
|
|
||||||
The MCU can only supply so much current to its GPIO pins. Instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
|
The MCU can only supply so much current to its GPIO pins. Instead of powering the backlight directly from the MCU, the backlight pin is connected to a transistor or MOSFET that switches the power to the LEDs.
|
||||||
|
|
||||||
@@ -12,9 +14,8 @@ Most keyboards have backlighting enabled by default if they support it, but if i
|
|||||||
BACKLIGHT_ENABLE = yes
|
BACKLIGHT_ENABLE = yes
|
||||||
```
|
```
|
||||||
|
|
||||||
You should then be able to use the keycodes below to change the backlight level.
|
|
||||||
|
|
||||||
## Keycodes
|
## Keycodes
|
||||||
|
Once enabled the following keycodes below can be used to change the backlight level.
|
||||||
|
|
||||||
|Key |Description |
|
|Key |Description |
|
||||||
|---------|------------------------------------------|
|
|---------|------------------------------------------|
|
||||||
@@ -26,9 +27,9 @@ You should then be able to use the keycodes below to change the backlight level.
|
|||||||
|`BL_DEC` |Decrease the backlight level |
|
|`BL_DEC` |Decrease the backlight level |
|
||||||
|`BL_BRTG`|Toggle backlight breathing |
|
|`BL_BRTG`|Toggle backlight breathing |
|
||||||
|
|
||||||
## Caveats
|
## AVR driver
|
||||||
|
|
||||||
This feature is distinct from both the [RGB underglow](feature_rgblight.md) and [RGB matrix](feature_rgb_matrix.md) features as it usually allows for only a single colour per switch, though you can obviously use multiple different coloured LEDs on a keyboard.
|
### Caveats
|
||||||
|
|
||||||
Hardware PWM is supported according to the following table:
|
Hardware PWM is supported according to the following table:
|
||||||
|
|
||||||
@@ -58,9 +59,9 @@ All other pins will use software PWM. If the [Audio](feature_audio.md) feature i
|
|||||||
|
|
||||||
When both timers are in use for Audio, the backlight PWM will not use a hardware timer, but will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
|
When both timers are in use for Audio, the backlight PWM will not use a hardware timer, but will instead be triggered during the matrix scan. In this case, breathing is not supported, and the backlight might flicker, because the PWM computation may not be called with enough timing precision.
|
||||||
|
|
||||||
## Configuration
|
### AVR Configuration
|
||||||
|
|
||||||
To change the behaviour of the backlighting, `#define` these in your `config.h`:
|
To change the behavior of the backlighting, `#define` these in your `config.h`:
|
||||||
|
|
||||||
|Define |Default |Description |
|
|Define |Default |Description |
|
||||||
|---------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
|---------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
||||||
@@ -72,14 +73,14 @@ To change the behaviour of the backlighting, `#define` these in your `config.h`:
|
|||||||
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|
||||||
|`BACKLIGHT_ON_STATE` |`0` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
|
|`BACKLIGHT_ON_STATE` |`0` |The state of the backlight pin when the backlight is "on" - `1` for high, `0` for low |
|
||||||
|
|
||||||
## Backlight On State
|
### Backlight On State
|
||||||
|
|
||||||
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
|
Most backlight circuits are driven by an N-channel MOSFET or NPN transistor. This means that to turn the transistor *on* and light the LEDs, you must drive the backlight pin, connected to the gate or base, *high*.
|
||||||
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
|
Sometimes, however, a P-channel MOSFET, or a PNP transistor is used. In this case, when the transistor is on, the pin is driven *low* instead.
|
||||||
|
|
||||||
This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
|
This functionality is configured at the keyboard level with the `BACKLIGHT_ON_STATE` define.
|
||||||
|
|
||||||
## Multiple backlight pins
|
### Multiple backlight pins
|
||||||
|
|
||||||
Most keyboards have only one backlight pin which control all backlight LEDs (especially if the backlight is connected to an hardware PWM pin).
|
Most keyboards have only one backlight pin which control all backlight LEDs (especially if the backlight is connected to an hardware PWM pin).
|
||||||
In software PWM, it is possible to define multiple backlight pins. All those pins will be turned on and off at the same time during the PWM duty cycle.
|
In software PWM, it is possible to define multiple backlight pins. All those pins will be turned on and off at the same time during the PWM duty cycle.
|
||||||
@@ -87,13 +88,13 @@ This feature allows to set for instance the Caps Lock LED (or any other controll
|
|||||||
|
|
||||||
To activate multiple backlight pins, you need to add something like this to your user `config.h`:
|
To activate multiple backlight pins, you need to add something like this to your user `config.h`:
|
||||||
|
|
||||||
~~~c
|
```c
|
||||||
#define BACKLIGHT_LED_COUNT 2
|
#define BACKLIGHT_LED_COUNT 2
|
||||||
#undef BACKLIGHT_PIN
|
#undef BACKLIGHT_PIN
|
||||||
#define BACKLIGHT_PINS { F5, B2 }
|
#define BACKLIGHT_PINS { F5, B2 }
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Hardware PWM Implementation
|
### Hardware PWM Implementation
|
||||||
|
|
||||||
When using the supported pins for backlighting, QMK will use a hardware timer configured to output a PWM signal. This timer will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
|
When using the supported pins for backlighting, QMK will use a hardware timer configured to output a PWM signal. This timer will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
|
||||||
The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the backlight pin will go low, and is pulled high again when the counter resets.
|
The desired brightness is calculated and stored in the `OCRxx` register. When the counter reaches this value, the backlight pin will go low, and is pulled high again when the counter resets.
|
||||||
@@ -102,7 +103,7 @@ In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus th
|
|||||||
The breathing effect is achieved by registering an interrupt handler for `TIMER1_OVF_vect` that is called whenever the counter resets, roughly 244 times per second.
|
The breathing effect is achieved by registering an interrupt handler for `TIMER1_OVF_vect` that is called whenever the counter resets, roughly 244 times per second.
|
||||||
In this handler, the value of an incrementing counter is mapped onto a precomputed brightness curve. To turn off breathing, the interrupt handler is simply disabled, and the brightness reset to the level stored in EEPROM.
|
In this handler, the value of an incrementing counter is mapped onto a precomputed brightness curve. To turn off breathing, the interrupt handler is simply disabled, and the brightness reset to the level stored in EEPROM.
|
||||||
|
|
||||||
## Software PWM Implementation
|
### Software PWM Implementation
|
||||||
|
|
||||||
When `BACKLIGHT_PIN` is not set to a hardware backlight pin, QMK will use a hardware timer configured to trigger software interrupts. This time will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
|
When `BACKLIGHT_PIN` is not set to a hardware backlight pin, QMK will use a hardware timer configured to trigger software interrupts. This time will count up to `ICRx` (by default `0xFFFF`) before resetting to 0.
|
||||||
When resetting to 0, the CPU will fire an OVF (overflow) interrupt that will turn the LEDs on, starting the duty cycle.
|
When resetting to 0, the CPU will fire an OVF (overflow) interrupt that will turn the LEDs on, starting the duty cycle.
|
||||||
@@ -111,6 +112,29 @@ In this way `OCRxx` essentially controls the duty cycle of the LEDs, and thus th
|
|||||||
|
|
||||||
The breathing effect is the same as in the hardware PWM implementation.
|
The breathing effect is the same as in the hardware PWM implementation.
|
||||||
|
|
||||||
|
## ARM Driver
|
||||||
|
|
||||||
|
### Caveats
|
||||||
|
|
||||||
|
Currently only hardware PWM is supported, and does not provide automatic configuration.
|
||||||
|
|
||||||
|
?> STMF072 support is being investigated.
|
||||||
|
|
||||||
|
### ARM Configuration
|
||||||
|
|
||||||
|
To change the behavior of the backlighting, `#define` these in your `config.h`:
|
||||||
|
|
||||||
|
|Define |Default |Description |
|
||||||
|
|------------------------|-------------|-------------------------------------------------------------------------------------------------------------|
|
||||||
|
|`BACKLIGHT_PIN` |`B7` |The pin that controls the LEDs. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||||
|
|`BACKLIGHT_PWM_DRIVER` |`PWMD4` |The PWM driver to use, see ST datasheets for pin to PWM timer mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||||
|
|`BACKLIGHT_PWM_CHANNEL` |`3` |The PWM channel to use, see ST datasheets for pin to PWM channel mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||||
|
|`BACKLIGHT_PAL_MODE` |`2` |The pin alternative function to use, see ST datasheets for pin AF mapping. Unless you are designing your own keyboard, you shouldn't need to change this|
|
||||||
|
|`BACKLIGHT_LEVELS` |`3` |The number of brightness levels (maximum 31 excluding off) |
|
||||||
|
|`BACKLIGHT_CAPS_LOCK` |*Not defined*|Enable Caps Lock indicator using backlight (for keyboards without dedicated LED) |
|
||||||
|
|`BACKLIGHT_BREATHING` |*Not defined*|Enable backlight breathing, if supported |
|
||||||
|
|`BREATHING_PERIOD` |`6` |The length of one backlight "breath" in seconds |
|
||||||
|
|
||||||
## Backlight Functions
|
## Backlight Functions
|
||||||
|
|
||||||
|Function |Description |
|
|Function |Description |
|
||||||
|
|||||||
Executable
+51
@@ -0,0 +1,51 @@
|
|||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
enum layer_names {
|
||||||
|
HOME,
|
||||||
|
MODS,
|
||||||
|
MODS2,
|
||||||
|
OTHER,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum custom_keycodes {
|
||||||
|
MACRO1 = SAFE_RANGE
|
||||||
|
};
|
||||||
|
|
||||||
|
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
if (record->event.pressed) {
|
||||||
|
switch (keycode) {
|
||||||
|
case MACRO1:
|
||||||
|
SEND_STRING("I'm so sorry... -PyroL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[HOME] = LAYOUT(
|
||||||
|
KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, MT(MOD_LCTL,KC_P),
|
||||||
|
KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, MT(MOD_LSFT,KC_ENT),
|
||||||
|
KC_Z, KC_X, KC_C, LT(MODS2,KC_V), LT(MODS, KC_SPC), LT(OTHER,KC_B), KC_N, KC_M),
|
||||||
|
|
||||||
|
[MODS] = LAYOUT(
|
||||||
|
KC_TAB, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_BSPC,
|
||||||
|
KC_LSFT, KC_ESC, _______, KC_SCLN, KC_QUOT, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, _______,
|
||||||
|
KC_LCTL, KC_LGUI, KC_LALT, _______, _______, KC_COMM, KC_DOT, KC_SLSH),
|
||||||
|
|
||||||
|
[MODS2] = LAYOUT(
|
||||||
|
KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,
|
||||||
|
KC_LSFT, KC_ESC, _______, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, KC_GRV, _______,
|
||||||
|
RGB_VAI, RGB_VAD, RGB_HUI, _______, _______, KC_MPLY, KC_VOLD, KC_VOLU),
|
||||||
|
|
||||||
|
[OTHER] = LAYOUT(
|
||||||
|
KC_ESC, RESET, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_DEL,
|
||||||
|
KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, _______,
|
||||||
|
KC_F10, KC_F11, KC_F12, _______, _______, KC_NO, KC_NO, KC_NO),
|
||||||
|
};
|
||||||
|
|
||||||
|
void matrix_init_user(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_scan_user(void) {
|
||||||
|
}
|
||||||
@@ -33,51 +33,52 @@ enum macro_keycodes {
|
|||||||
|
|
||||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
[_QWERTY] = LAYOUT( \
|
[_QWERTY] = LAYOUT( \
|
||||||
//,-----------------------------------------. ,-----------------------------------------.
|
//,-----------------------------------------------------. ,-----------------------------------------------------.
|
||||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,KC_BSPC,\
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,\
|
||||||
//|------+------+------+------+------+------| |------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
|
||||||
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L,KC_SCLN,KC_QUOT,\
|
KC_LCTL, 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,KC_RSFT,\
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT,\
|
||||||
//|------+------+------+------+------+------+------| |------+------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
|
||||||
KC_LGUI, LOWER,KC_SPC, KC_ENT, RAISE,KC_RALT \
|
KC_LGUI, LOWER, KC_SPC, KC_ENT, RAISE, KC_RALT \
|
||||||
//`--------------------' `--------------------'
|
//`--------------------------' `--------------------------'
|
||||||
|
|
||||||
),
|
),
|
||||||
|
|
||||||
[_LOWER] = LAYOUT( \
|
[_LOWER] = LAYOUT( \
|
||||||
//,-----------------------------------------. ,-----------------------------------------.
|
//,-----------------------------------------------------. ,-----------------------------------------------------.
|
||||||
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,KC_BSPC,\
|
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC,\
|
||||||
//|------+------+------+------+------+------| |------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
|
||||||
KC_LCTL, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_LEFT,KC_DOWN,KC_UP, KC_RIGHT,KC_NO,KC_NO,\
|
KC_LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_LEFT, KC_DOWN, KC_UP,KC_RIGHT, XXXXXXX, XXXXXXX,\
|
||||||
//|------+------+------+------+------+------| |------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
|
||||||
KC_LSFT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
|
KC_LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\
|
||||||
//|------+------+------+------+------+------+------| |------+------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
|
||||||
KC_LGUI, LOWER,KC_SPC, KC_ENT, RAISE,KC_RALT \
|
KC_LGUI, LOWER, KC_SPC, KC_ENT, RAISE, KC_RALT \
|
||||||
//`--------------------' `--------------------'
|
//`--------------------------' `--------------------------'
|
||||||
),
|
),
|
||||||
|
|
||||||
[_RAISE] = LAYOUT( \
|
[_RAISE] = LAYOUT( \
|
||||||
//,-----------------------------------------. ,-----------------------------------------.
|
//,-----------------------------------------------------. ,-----------------------------------------------------.
|
||||||
KC_ESC,KC_EXLM,KC_AT,KC_HASH,KC_DLR,KC_PERC, KC_CIRC,KC_AMPR,KC_ASTR,KC_LPRN,KC_RPRN,KC_BSPC,\
|
KC_ESC, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC,\
|
||||||
//|------+------+------+------+------+------| |------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
|
||||||
KC_LCTL, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_MINS,KC_EQL,KC_LCBR,KC_RCBR,KC_PIPE,KC_GRV,\
|
KC_LCTL, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_MINS, KC_EQL, KC_LCBR, KC_RCBR, KC_PIPE, KC_GRV,\
|
||||||
//|------+------+------+------+------+------| |------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
|
||||||
KC_LSFT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_UNDS,KC_PLUS,KC_LBRC,KC_RBRC,KC_BSLS,KC_TILD,\
|
KC_LSFT, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, KC_UNDS, KC_PLUS, KC_LBRC, KC_RBRC, KC_BSLS, KC_TILD,\
|
||||||
//|------+------+------+------+------+------+------| |------+------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
|
||||||
KC_LGUI, LOWER,KC_SPC, KC_ENT, RAISE,KC_RALT \
|
KC_LGUI, LOWER, KC_SPC, KC_ENT, RAISE, KC_RALT \
|
||||||
//`--------------------' `--------------------'
|
//`--------------------------' `--------------------------'
|
||||||
),
|
),
|
||||||
|
|
||||||
[_ADJUST] = LAYOUT( \
|
[_ADJUST] = LAYOUT( \
|
||||||
//,-----------------------------------------. ,-----------------------------------------.
|
//,-----------------------------------------------------. ,-----------------------------------------------------.
|
||||||
RESET,RGBRST, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
|
RESET, RGBRST, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\
|
||||||
//|------+------+------+------+------+------| |------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
|
||||||
RGB_TOG,RGB_HUI,RGB_SAI,RGB_VAI,KC_NO,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
|
RGB_TOG, RGB_HUI, RGB_SAI, RGB_VAI, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\
|
||||||
//|------+------+------+------+------+------| |------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
|
||||||
RGB_MOD,RGB_HUD,RGB_SAD,RGB_VAD,KC_NO,KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,\
|
RGB_MOD, RGB_HUD, RGB_SAD, RGB_VAD, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX, XXXXXXX,\
|
||||||
//|------+------+------+------+------+------+------| |------+------+------+------+------+------+------|
|
//|--------+--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------+--------|
|
||||||
KC_LGUI, LOWER,KC_SPC, KC_ENT, RAISE,KC_RALT \
|
KC_LGUI, LOWER, KC_SPC, KC_ENT, RAISE, KC_RALT \
|
||||||
//`--------------------' `--------------------'
|
//`--------------------------' `--------------------------'
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"keyboard_name": "Duck Orion V3",
|
||||||
|
"url": "",
|
||||||
|
"maintainer": "qmk",
|
||||||
|
"width": 18.25,
|
||||||
|
"height": 6.5,
|
||||||
|
"layouts": {
|
||||||
|
"LAYOUT_tkl_ansi": {
|
||||||
|
"layout": [{"x":0, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":6.5, "y":0}, {"x":7.5, "y":0}, {"x":8.5, "y":0}, {"x":9.5, "y":0}, {"x":11, "y":0}, {"x":12, "y":0}, {"x":13, "y":0}, {"x":14, "y":0}, {"x":15.25, "y":0}, {"x":16.25, "y":0}, {"x":17.25, "y":0}, {"x":0, "y":1.5}, {"x":1, "y":1.5}, {"x":2, "y":1.5}, {"x":3, "y":1.5}, {"x":4, "y":1.5}, {"x":5, "y":1.5}, {"x":6, "y":1.5}, {"x":7, "y":1.5}, {"x":8, "y":1.5}, {"x":9, "y":1.5}, {"x":10, "y":1.5}, {"x":11, "y":1.5}, {"x":12, "y":1.5}, {"x":13, "y":1.5, "w":2}, {"x":15.25, "y":1.5}, {"x":16.25, "y":1.5}, {"x":17.25, "y":1.5}, {"x":0, "y":2.5, "w":1.5}, {"x":1.5, "y":2.5}, {"x":2.5, "y":2.5}, {"x":3.5, "y":2.5}, {"x":4.5, "y":2.5}, {"x":5.5, "y":2.5}, {"x":6.5, "y":2.5}, {"x":7.5, "y":2.5}, {"x":8.5, "y":2.5}, {"x":9.5, "y":2.5}, {"x":10.5, "y":2.5}, {"x":11.5, "y":2.5}, {"x":12.5, "y":2.5}, {"x":13.5, "y":2.5, "w":1.5}, {"x":15.25, "y":2.5}, {"x":16.25, "y":2.5}, {"x":17.25, "y":2.5}, {"x":0, "y":3.5, "w":1.75}, {"x":1.75, "y":3.5}, {"x":2.75, "y":3.5}, {"x":3.75, "y":3.5}, {"x":4.75, "y":3.5}, {"x":5.75, "y":3.5}, {"x":6.75, "y":3.5}, {"x":7.75, "y":3.5}, {"x":8.75, "y":3.5}, {"x":9.75, "y":3.5}, {"x":10.75, "y":3.5}, {"x":11.75, "y":3.5}, {"x":12.75, "y":3.5, "w":2.25}, {"x":0, "y":4.5, "w":2.25}, {"x":2.25, "y":4.5}, {"x":3.25, "y":4.5}, {"x":4.25, "y":4.5}, {"x":5.25, "y":4.5}, {"x":6.25, "y":4.5}, {"x":7.25, "y":4.5}, {"x":8.25, "y":4.5}, {"x":9.25, "y":4.5}, {"x":10.25, "y":4.5}, {"x":11.25, "y":4.5}, {"x":12.25, "y":4.5, "w":2.75}, {"x":16.25, "y":4.5}, {"x":0, "y":5.5, "w":1.25}, {"x":1.25, "y":5.5, "w":1.25}, {"x":2.5, "y":5.5, "w":1.25}, {"x":3.75, "y":5.5, "w":6.25}, {"x":10, "y":5.5, "w":1.25}, {"x":11.25, "y":5.5, "w":1.25}, {"x":12.5, "y":5.5, "w":1.25}, {"x":13.75, "y":5.5, "w":1.25}, {"x":15.25, "y":5.5}, {"x":16.25, "y":5.5}, {"x":17.25, "y":5.5}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# Duck Orion
|
||||||
|
|
||||||
|
Non official firmware for custom TKL Korean keyboard made by Duck.
|
||||||
|
|
||||||
|
Newest version is the [Orion V3](http://duck0113.tistory.com/127)
|
||||||
|
|
||||||
|
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DEFAULT_FOLDER = duck/orion/v3
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 MechMerlin <[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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config_common.h"
|
||||||
|
|
||||||
|
/* USB Device descriptor parameter */
|
||||||
|
#define VENDOR_ID 0x444B // Duck ("DK")
|
||||||
|
#define PRODUCT_ID 0x4F52 // Orion ("OR")
|
||||||
|
#define DEVICE_VER 0x0002
|
||||||
|
#define MANUFACTURER Duck
|
||||||
|
#define PRODUCT Orion V3
|
||||||
|
#define DESCRIPTION TKL Korean custom keyboard
|
||||||
|
|
||||||
|
/* key matrix size */
|
||||||
|
#define MATRIX_ROWS 6
|
||||||
|
#define MATRIX_COLS 18
|
||||||
|
|
||||||
|
#define DIODE_DIRECTION COL2ROW
|
||||||
|
|
||||||
|
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
|
||||||
|
#define DEBOUNCE 5
|
||||||
|
|
||||||
|
/* number of backlight levels */
|
||||||
|
#define BACKLIGHT_LEVELS 3
|
||||||
|
|
||||||
|
#define RGBLIGHT_ANIMATIONS
|
||||||
|
#define RGB_DI_PIN D6
|
||||||
|
#define RGBLED_NUM 17
|
||||||
|
|
||||||
|
/* Set to top left most key */
|
||||||
|
#define BOOTMAGIC_LITE_ROW 4
|
||||||
|
#define BOOTMAGIC_LITE_COLUMN 10
|
||||||
|
|
||||||
|
#define TAPPING_TERM 200
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 MechMerlin <[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/interrupt.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include "indicator_leds.h"
|
||||||
|
#include "duck_led/duck_led.h"
|
||||||
|
|
||||||
|
#define LED_T1H 600
|
||||||
|
#define LED_T1L 650
|
||||||
|
#define LED_T0H 250
|
||||||
|
#define LED_T0L 1000
|
||||||
|
|
||||||
|
void send_bit_d4(bool bitVal) {
|
||||||
|
if(bitVal) {
|
||||||
|
asm volatile (
|
||||||
|
"sbi %[port], %[bit] \n\t"
|
||||||
|
".rept %[onCycles] \n\t"
|
||||||
|
"nop \n\t"
|
||||||
|
".endr \n\t"
|
||||||
|
"cbi %[port], %[bit] \n\t"
|
||||||
|
".rept %[offCycles] \n\t"
|
||||||
|
"nop \n\t"
|
||||||
|
".endr \n\t"
|
||||||
|
::
|
||||||
|
[port] "I" (_SFR_IO_ADDR(PORTD)),
|
||||||
|
[bit] "I" (4),
|
||||||
|
[onCycles] "I" (NS_TO_CYCLES(LED_T1H) - 2),
|
||||||
|
[offCycles] "I" (NS_TO_CYCLES(LED_T1L) - 2));
|
||||||
|
} else {
|
||||||
|
asm volatile (
|
||||||
|
"sbi %[port], %[bit] \n\t"
|
||||||
|
".rept %[onCycles] \n\t"
|
||||||
|
"nop \n\t"
|
||||||
|
".endr \n\t"
|
||||||
|
"cbi %[port], %[bit] \n\t"
|
||||||
|
".rept %[offCycles] \n\t"
|
||||||
|
"nop \n\t"
|
||||||
|
".endr \n\t"
|
||||||
|
::
|
||||||
|
[port] "I" (_SFR_IO_ADDR(PORTD)),
|
||||||
|
[bit] "I" (4),
|
||||||
|
[onCycles] "I" (NS_TO_CYCLES(LED_T0H) - 2),
|
||||||
|
[offCycles] "I" (NS_TO_CYCLES(LED_T0L) - 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_value(uint8_t byte, enum Device device) {
|
||||||
|
for(uint8_t b = 0; b < 8; b++) {
|
||||||
|
if(device == Device_STATUSLED) {
|
||||||
|
send_bit_d4(byte & 0b10000000);
|
||||||
|
byte <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the LED indicators to the WS2811S chips
|
||||||
|
void indicator_leds_set(bool leds[8]) {
|
||||||
|
uint8_t led_cnt;
|
||||||
|
|
||||||
|
cli();
|
||||||
|
for(led_cnt = 0; led_cnt < 8; led_cnt++)
|
||||||
|
send_value(leds[led_cnt] ? 255 : 0, Device_STATUSLED);
|
||||||
|
sei();
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
void indicator_leds_set(bool leds[8]);
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/* Copyright 2019 MechMerlin <[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 QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[0] = LAYOUT_tkl_ansi(\
|
||||||
|
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR,KC_SLCK,KC_PAUS, \
|
||||||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,KC_MINS, KC_EQL,KC_BSPC, KC_INS ,KC_HOME,KC_PGUP, \
|
||||||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,KC_LBRC,KC_RBRC,KC_BSLS, KC_DEL ,KC_END ,KC_PGDN, \
|
||||||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L,KC_SCLN,KC_QUOT, KC_ENT, \
|
||||||
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M,KC_COMM, KC_DOT,KC_SLSH, KC_RSFT, KC_UP, \
|
||||||
|
KC_LCTL,KC_LGUI,KC_LALT, KC_SPC, KC_RALT,KC_RGUI, KC_APP,KC_RCTL, KC_LEFT,KC_DOWN,KC_RGHT) \
|
||||||
|
};
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 MechMerlin <[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 <util/delay.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "matrix.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
static uint8_t debouncing = DEBOUNCE;
|
||||||
|
|
||||||
|
/* matrix state(1:on, 0:off) */
|
||||||
|
static matrix_row_t matrix[MATRIX_ROWS];
|
||||||
|
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
|
||||||
|
|
||||||
|
static uint8_t read_rows(uint8_t col);
|
||||||
|
static void init_rows(void);
|
||||||
|
static void unselect_cols(void);
|
||||||
|
static void select_col(uint8_t col);
|
||||||
|
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void matrix_init_kb(void) {
|
||||||
|
matrix_init_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void matrix_scan_kb(void) {
|
||||||
|
matrix_scan_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void matrix_init_user(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void matrix_scan_user(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_init_ports(void)
|
||||||
|
{
|
||||||
|
DDRD |= 0b11010000;
|
||||||
|
PORTD &= ~0b01010000;
|
||||||
|
PORTD |= 0b10000000;
|
||||||
|
DDRB |= 0b00011111;
|
||||||
|
PORTB &= ~0b00001110;
|
||||||
|
PORTB |= 0b00010001;
|
||||||
|
DDRE |= 0b01000000;
|
||||||
|
PORTE &= ~0b01000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_init(void) {
|
||||||
|
backlight_init_ports();
|
||||||
|
unselect_cols();
|
||||||
|
init_rows();
|
||||||
|
|
||||||
|
for (uint8_t i=0; i < MATRIX_ROWS; i++) {
|
||||||
|
matrix[i] = 0;
|
||||||
|
matrix_debouncing[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix_init_quantum();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t matrix_scan(void) {
|
||||||
|
for (uint8_t col = 0; col < MATRIX_COLS; col++) {
|
||||||
|
select_col(col);
|
||||||
|
_delay_us(3);
|
||||||
|
|
||||||
|
uint8_t rows = read_rows(col);
|
||||||
|
|
||||||
|
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
||||||
|
bool prev_bit = matrix_debouncing[row] & ((matrix_row_t)1<<col);
|
||||||
|
bool curr_bit = rows & (1<<row);
|
||||||
|
if (prev_bit != curr_bit) {
|
||||||
|
matrix_debouncing[row] ^= ((matrix_row_t)1<<col);
|
||||||
|
if (debouncing) {
|
||||||
|
dprint("bounce!: "); dprintf("%02X", debouncing); dprintln();
|
||||||
|
}
|
||||||
|
debouncing = DEBOUNCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unselect_cols();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debouncing) {
|
||||||
|
if (--debouncing) {
|
||||||
|
_delay_ms(1);
|
||||||
|
} else {
|
||||||
|
for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
|
||||||
|
matrix[i] = matrix_debouncing[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
matrix_scan_quantum();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline matrix_row_t matrix_get_row(uint8_t row) {
|
||||||
|
return matrix[row];
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_print(void) {
|
||||||
|
print("\nr/c 0123456789ABCDEF\n");
|
||||||
|
for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
|
||||||
|
xprintf("%02X: %032lb\n", row, bitrev32(matrix_get_row(row)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Row pin configuration - diode connected
|
||||||
|
* row: 0 1 2 3 4 5
|
||||||
|
* pin: PD0 PD1 PD2 PD3 PD5 PB7
|
||||||
|
*
|
||||||
|
* Backspace uses its own pin PE2 on the column pin, row pin is grounded
|
||||||
|
*/
|
||||||
|
static void init_rows(void) {
|
||||||
|
DDRD &= ~0b00101111;
|
||||||
|
PORTD &= ~0b00101111;
|
||||||
|
|
||||||
|
DDRB &= ~0b10000000;
|
||||||
|
PORTB &= ~0b10000000;
|
||||||
|
|
||||||
|
DDRE &= ~0b00000100;
|
||||||
|
PORTE |= 0b00000100;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t read_rows(uint8_t col) {
|
||||||
|
|
||||||
|
return (PIND&(1<<0) ? (1<<0) : 0) |
|
||||||
|
(PIND&(1<<1) ? (1<<1) : 0) |
|
||||||
|
(PIND&(1<<2) ? (1<<2) : 0) |
|
||||||
|
(PIND&(1<<3) ? (1<<3) : 0) |
|
||||||
|
(PIND&(1<<5) ? (1<<4) : 0) |
|
||||||
|
(PINB&(1<<7) ? (1<<5) : 0) |
|
||||||
|
(col== 17 ? ((PINE&(1<<2) ? 0 : (1<<1))) : 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read_fwkey(void)
|
||||||
|
{
|
||||||
|
return PINE&(1<<2) ? 0 : (1<<2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Columns 0 - 15
|
||||||
|
*
|
||||||
|
* atmega32u4 decoder pin
|
||||||
|
* PC6 U1 E3
|
||||||
|
* PB6 U2 E3
|
||||||
|
* PF0 U1, U2 A0
|
||||||
|
* PF1 U1, U2 A1
|
||||||
|
* PC7 U1, U2 A2
|
||||||
|
*
|
||||||
|
* These columns uses two 74HC237D 3 to 8 bit demultiplexers.
|
||||||
|
* col / pin: PC6 PB6 PF0 PF1 PC7 Decoder Pin
|
||||||
|
* 0: 1 0 0 0 0 U1 Y0
|
||||||
|
* 1: 1 0 1 0 0 U1 Y1
|
||||||
|
* 2: 1 0 0 1 0 U1 Y2
|
||||||
|
* 3: 1 0 1 1 0 U1 Y3
|
||||||
|
* 4: 1 0 0 0 1 U1 Y4
|
||||||
|
* 5: 1 0 1 0 1 U1 Y5
|
||||||
|
* 6: 1 0 0 1 1 U1 Y6
|
||||||
|
* 7: 1 0 1 1 1 U1 Y7
|
||||||
|
*
|
||||||
|
* 8: 0 1 0 0 0 U2 Y0
|
||||||
|
* 9: 0 1 1 0 0 U2 Y1
|
||||||
|
* 10: 0 1 0 1 0 U2 Y2
|
||||||
|
* 11: 0 1 1 1 0 U2 Y3
|
||||||
|
* 12: 0 1 0 0 1 U2 Y4
|
||||||
|
* 13: 0 1 1 0 1 U2 Y5
|
||||||
|
* 14: 0 1 0 1 1 U2 Y6
|
||||||
|
* 15: 0 1 1 1 1 U2 Y7
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void unselect_cols(void) {
|
||||||
|
DDRB |= 0b01100000;
|
||||||
|
PORTB &= ~0b01100000;
|
||||||
|
|
||||||
|
DDRC |= 0b11000000;
|
||||||
|
PORTC &= ~0b11000000;
|
||||||
|
|
||||||
|
DDRF |= 0b00000011;
|
||||||
|
PORTF &= ~0b00000011;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void select_col(uint8_t col) {
|
||||||
|
|
||||||
|
switch (col) {
|
||||||
|
case 0:
|
||||||
|
PORTC |= 0b01000000;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
PORTC |= 0b01000000;
|
||||||
|
PORTF |= 0b00000001;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
PORTC |= 0b01000000;
|
||||||
|
PORTF |= 0b00000010;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
PORTC |= 0b01000000;
|
||||||
|
PORTF |= 0b00000011;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
PORTC |= 0b11000000;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
PORTC |= 0b11000000;
|
||||||
|
PORTF |= 0b00000001;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
PORTC |= 0b11000000;
|
||||||
|
PORTF |= 0b00000010;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
PORTC |= 0b11000000;
|
||||||
|
PORTF |= 0b00000011;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
PORTF |= 0b00000001;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
PORTF |= 0b00000010;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
PORTF |= 0b00000011;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
PORTC |= 0b10000000;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
PORTF |= 0b00000001;
|
||||||
|
PORTC |= 0b10000000;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
PORTF |= 0b00000010;
|
||||||
|
PORTC |= 0b10000000;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
PORTB |= 0b01000000;
|
||||||
|
PORTF |= 0b00000011;
|
||||||
|
PORTC |= 0b10000000;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
PORTB |= 0b00100000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Duck Orion V3
|
||||||
|
|
||||||
|
Non official firmware for custom TKL Korean keyboard made by Duck.
|
||||||
|
Group buy was run December 2018 via [geekhack](https://geekhack.org/index.php?topic=98581.0) with 100 keyboards total.
|
||||||
|
|
||||||
|
Keyboard Maintainer: [MechMerlin](https://github.com/mechmerlin)
|
||||||
|
Hardware Supported: Duck Eagle/Viper PCB Ver 2.0, Atmega32u4
|
||||||
|
Hardware Availability: Wait until GB of the next revision
|
||||||
|
|
||||||
|
Make example for this keyboard (after setting up your build environment):
|
||||||
|
|
||||||
|
make duck/orion/v3:default
|
||||||
|
|
||||||
|
**Reset Key:** To put the Orion V3 into reset, hold Backspace key (`K4N`) while plugging in.
|
||||||
|
|
||||||
|
**CAUTION:** At this time 10/03/19 lighting has not been tested fully and may not properly work.
|
||||||
|
|
||||||
|
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||||
|
|
||||||
|
## Hardware Notes
|
||||||
|
|
||||||
|
The Orion V3 PCB consists of:
|
||||||
|
|
||||||
|
### Microchips
|
||||||
|
2 74HC237D 3-to-8 line decoders
|
||||||
|
1 Atmega32u4 microcontroller
|
||||||
|
2 WS2811 LED controller
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
Special thanks to Marcus aka Keebology for doing this remotely and mapping the matrix.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# MCU name
|
||||||
|
MCU = atmega32u4
|
||||||
|
|
||||||
|
# Bootloader selection
|
||||||
|
# Teensy halfkay
|
||||||
|
# Pro Micro caterina
|
||||||
|
# Atmel DFU atmel-dfu
|
||||||
|
# LUFA DFU lufa-dfu
|
||||||
|
# QMK DFU qmk-dfu
|
||||||
|
# ATmega32A bootloadHID
|
||||||
|
# ATmega328P USBasp
|
||||||
|
BOOTLOADER = atmel-dfu
|
||||||
|
|
||||||
|
|
||||||
|
# Build Options
|
||||||
|
# change yes to no to disable
|
||||||
|
#
|
||||||
|
BOOTMAGIC_ENABLE = lite # 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
|
||||||
|
# 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 = yes # USB Nkey Rollover
|
||||||
|
BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality on B7 by default
|
||||||
|
MIDI_ENABLE = no # MIDI support (+2400 to 4200, depending on config)
|
||||||
|
UNICODE_ENABLE = no # Unicode
|
||||||
|
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
|
||||||
|
AUDIO_ENABLE = no # Audio output on port C6
|
||||||
|
FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
|
||||||
|
RGBLIGHT_ENABLE = yes
|
||||||
|
|
||||||
|
CUSTOM_MATRIX = yes
|
||||||
|
SRC += indicator_leds.c \
|
||||||
|
matrix.c duck_led/duck_led.c
|
||||||
|
|
||||||
|
LAYOUTS = tkl_ansi
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/* Copyright 2019 MechMerlin <[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 "v3.h"
|
||||||
|
#include "indicator_leds.h"
|
||||||
|
|
||||||
|
enum BACKLIGHT_AREAS {
|
||||||
|
BACKLIGHT_ALPHAS = 0b00000010,
|
||||||
|
BACKLIGHT_MODNUM = 0b00001000
|
||||||
|
};
|
||||||
|
|
||||||
|
void backlight_set(uint8_t level) {
|
||||||
|
switch(level) {
|
||||||
|
case 0:
|
||||||
|
PORTB |= BACKLIGHT_ALPHAS;
|
||||||
|
PORTB |= BACKLIGHT_MODNUM;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
PORTB &= ~BACKLIGHT_ALPHAS;
|
||||||
|
PORTB |= BACKLIGHT_MODNUM;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
PORTB |= BACKLIGHT_ALPHAS;
|
||||||
|
PORTB &= ~BACKLIGHT_MODNUM;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
PORTB &= ~BACKLIGHT_ALPHAS;
|
||||||
|
PORTB &= ~BACKLIGHT_MODNUM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port from backlight_update_state
|
||||||
|
void led_set_kb(uint8_t usb_led) {
|
||||||
|
bool status[8] = {
|
||||||
|
IS_HOST_LED_ON(USB_LED_SCROLL_LOCK), /* LED 3 */
|
||||||
|
IS_HOST_LED_ON(USB_LED_CAPS_LOCK), /* LED 2 */
|
||||||
|
IS_HOST_LED_ON(USB_LED_NUM_LOCK), /* LED 1 */
|
||||||
|
|
||||||
|
layer_state & (1<<2), /* LED 6 */
|
||||||
|
layer_state & (1<<1), /* LED 5 */
|
||||||
|
layer_state & (1<<0) ? 0: 1, /* LED 4 */
|
||||||
|
|
||||||
|
layer_state & (1<<5), /* LED 8 */
|
||||||
|
layer_state & (1<<4) /* LED 7 */
|
||||||
|
};
|
||||||
|
|
||||||
|
indicator_leds_set(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
return process_record_user(keycode, record);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* Copyright 2019 MechMerlin <[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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
#define ___ KC_NO
|
||||||
|
|
||||||
|
#define LAYOUT_tkl_ansi( \
|
||||||
|
K5A, K5C, K5D, K5E, K5F, K5G, K5H, K5I, K5J, K5K, K5L, K5M, K5N, K5O, K5P, K5Q, \
|
||||||
|
K4A, K4B, K4C, K4D, K4E, K4F, K4G, K4H, K4I, K4J, K4K, K4L, K4M, K4R, K4O, K4P, K4Q, \
|
||||||
|
K3A, K3B, K3C, K3D, K3E, K3F, K3G, K3H, K3I, K3J, K3K, K3L, K3M, K3N, K3O, K3P, K3Q, \
|
||||||
|
K2A, K2B, K2C, K2D, K2E, K2F, K2G, K2H, K2I, K2J, K2K, K2L, K2N, \
|
||||||
|
K1A, K1B, K1C, K1D, K1E, K1F, K1G, K1H, K1I, K1J, K1K, K1N, K1P, \
|
||||||
|
K0A, K0B, K0C, K0F, K0I, K0K, K0M, K0N, K0O, K0P, K0Q \
|
||||||
|
) { \
|
||||||
|
{ K5A, ___, K5C, K5D, K5E, K5F, K5G, K5H, K5I, K5J, K5K, K5L, K5M, K5N, K5O, K5P, K5Q, ___ }, \
|
||||||
|
{ K4A, K4B, K4C, K4D, K4E, K4F, K4G, K4H, K4I, K4J, K4K, K4L, K4M, ___, K4O, K4P, K4Q, K4R }, \
|
||||||
|
{ K3A, K3B, K3C, K3D, K3E, K3F, K3G, K3H, K3I, K3J, K3K, K3L, K3M, K3N, K3O, K3P, K3Q, ___ }, \
|
||||||
|
{ K2A, K2B, K2C, K2D, K2E, K2F, K2G, K2H, K2I, K2J, K2K, K2L, ___, K2N, ___, ___, ___, ___ }, \
|
||||||
|
{ K1A, K1B, K1C, K1D, K1E, K1F, K1G, K1H, K1I, K1J, K1K, ___, ___, K1N, ___, K1P, ___, ___ }, \
|
||||||
|
{ K0A, K0B, K0C, ___, ___, K0F, ___, ___, K0I, ___, K0K, ___, K0M, K0N, K0O, K0P, K0Q, ___ } \
|
||||||
|
}
|
||||||
@@ -1,20 +1,6 @@
|
|||||||
#include QMK_KEYBOARD_H
|
#include QMK_KEYBOARD_H
|
||||||
#include "debug.h"
|
|
||||||
#include "action_layer.h"
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "layers.h"
|
||||||
enum custom_layers {
|
|
||||||
_QWERTY,
|
|
||||||
_WORKMAN,
|
|
||||||
_DVORAK,
|
|
||||||
_COLEMAK,
|
|
||||||
_LOWER,
|
|
||||||
_RAISE,
|
|
||||||
_ADJUST,
|
|
||||||
_GAME,
|
|
||||||
_MOUSE,
|
|
||||||
_NUM,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum custom_keycodes {
|
enum custom_keycodes {
|
||||||
QWERTY = SAFE_RANGE,
|
QWERTY = SAFE_RANGE,
|
||||||
@@ -39,41 +25,41 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* | Tab | Q | W | E | R | T | [{ | | ]} | Y | U | I | O | P | BSPC |
|
* | Tab | Q | W | E | R | T | [{ | | ]} | Y | U | I | O | P | BSPC |
|
||||||
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | ESC | A | S | D | F | G |------| |------| H | J | K | L | ; | ' |
|
* | ESC | A | S | D | F | G |------| |------| H | J | K | L | ; | ' |
|
||||||
* |--------+-----+-----+-----+-----+-----| L1 | | L1 |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | LShift | Z | X | C | V | B | | | | N | M | , | . | / | Enter |
|
* | LShift | Z | X | C | V | B | | | | N | M | , | . | / | Enter |
|
||||||
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
||||||
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
||||||
* `------------------------------' `------------------------------'
|
* `------------------------------' `------------------------------'
|
||||||
* ,------------. ,------------.
|
* ,------------. ,------------.
|
||||||
* |Play |Mouse | | Num |Mouse|
|
* |Play | | | |Play |
|
||||||
* ,----|-----|------| |------+-----+-----.
|
* ,-----|-----|------| |------+-----+-----.
|
||||||
* | | | Alt | | Alt | | |
|
* | | | Alt | | Alt | | |
|
||||||
* |BSPC|LOWER|------| |------|RAISE|Space|
|
* |Space|LOWER|------| |------|RAISE|Space|
|
||||||
* | | | LGUI | | LGUI | | |
|
* | | | LGUI | | LGUI | | |
|
||||||
* `-----------------' `------------------'
|
* `------------------' `------------------'
|
||||||
*/
|
*/
|
||||||
[_QWERTY] = LAYOUT_ergodox(
|
[_QWERTY] = LAYOUT_ergodox(
|
||||||
// left hand
|
// left hand
|
||||||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
||||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LBRACKET,
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_LBRACKET,
|
||||||
KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G,
|
KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G,
|
||||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_FN1,
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, _______,
|
||||||
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
||||||
|
|
||||||
KC_MPLY, TG(_MOUSE),
|
KC_MPLY, _______,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_BSPACE, LOWER, KC_LGUI,
|
KC_SPACE, LOWER, KC_LGUI,
|
||||||
|
|
||||||
// right hand
|
// right hand
|
||||||
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
||||||
KC_RBRACKET, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPACE,
|
KC_RBRACKET, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPACE,
|
||||||
KC_H, KC_J, KC_K, KC_L, KC_SCOLON, KC_QUOTE,
|
KC_H, KC_J, KC_K, KC_L, KC_SCOLON, KC_QUOTE,
|
||||||
KC_FN1, KC_N, KC_M, KC_COMM, KC_DOT, LT(_MOUSE, KC_SLSH), RSFT_T(KC_ENT),
|
_______, KC_N, KC_M, KC_COMM, KC_DOT, LT(_MOUSE, KC_SLSH), RSFT_T(KC_ENT),
|
||||||
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
||||||
|
|
||||||
TT(_NUM), TG(_MOUSE),
|
_______, KC_MPLY,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_LGUI, RAISE, KC_SPACE
|
KC_LGUI, RAISE, KC_SPACE
|
||||||
),
|
),
|
||||||
|
|
||||||
/* Keymap 0: Basic Workman layer
|
/* Keymap 0: Basic Workman layer
|
||||||
@@ -84,41 +70,41 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* | Tab | Q | D | R | W | B | [{ | | ]} | J | F | U | P | ; | BSPC |
|
* | Tab | Q | D | R | W | B | [{ | | ]} | J | F | U | P | ; | BSPC |
|
||||||
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | ESC | A | S | H | T | G |------| |------| Y | N | E | O | I | ' |
|
* | ESC | A | S | H | T | G |------| |------| Y | N | E | O | I | ' |
|
||||||
* |--------+-----+-----+-----+-----+-----| L1 | | L1 |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | LShift | Z | X | M | C | V | | | | K | L | , | . | / | Enter |
|
* | LShift | Z | X | M | C | V | | | | K | L | , | . | / | Enter |
|
||||||
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
||||||
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
||||||
* `------------------------------' `------------------------------'
|
* `------------------------------' `------------------------------'
|
||||||
* ,------------. ,------------.
|
* ,------------. ,------------.
|
||||||
* |Play |Mouse | | Num |Mouse|
|
* |Play | | | |Play |
|
||||||
* ,----|-----|------| |------+-----+-----.
|
* ,-----|-----|------| |------+-----+-----.
|
||||||
* | | | Alt | | Alt | | |
|
* | | | Alt | | Alt | | |
|
||||||
* |BSPC|LOWER|------| |------|RAISE|Space|
|
* |Space|LOWER|------| |------|RAISE|Space|
|
||||||
* | | | LGUI | | LGUI | | |
|
* | | | LGUI | | LGUI | | |
|
||||||
* `-----------------' `------------------'
|
* `------------------' `------------------'
|
||||||
*/
|
*/
|
||||||
[_WORKMAN] = LAYOUT_ergodox(
|
[_WORKMAN] = LAYOUT_ergodox(
|
||||||
// left hand
|
// left hand
|
||||||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
||||||
KC_TAB, KC_Q, KC_D, KC_R, KC_W, KC_B, KC_LBRACKET,
|
KC_TAB, KC_Q, KC_D, KC_R, KC_W, KC_B, KC_LBRACKET,
|
||||||
KC_ESC, KC_A, KC_S, KC_H, KC_T, KC_G,
|
KC_ESC, KC_A, KC_S, KC_H, KC_T, KC_G,
|
||||||
KC_LSFT, KC_Z, KC_X, KC_M, KC_C, KC_V, KC_FN1,
|
KC_LSFT, KC_Z, KC_X, KC_M, KC_C, KC_V, _______,
|
||||||
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
||||||
|
|
||||||
KC_MPLY, TG(_MOUSE),
|
KC_MPLY, _______,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_BSPACE, LOWER, KC_LGUI,
|
KC_SPACE, LOWER, KC_LGUI,
|
||||||
|
|
||||||
// right hand
|
// right hand
|
||||||
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
||||||
KC_RBRACKET, KC_J, KC_F, KC_U, KC_P, KC_SCOLON, KC_BSPACE,
|
KC_RBRACKET, KC_J, KC_F, KC_U, KC_P, KC_SCOLON, KC_BSPACE,
|
||||||
KC_Y, KC_N, KC_E, KC_O, KC_I, KC_QUOTE,
|
KC_Y, KC_N, KC_E, KC_O, KC_I, KC_QUOTE,
|
||||||
KC_FN1, KC_K, KC_L, KC_COMM, KC_DOT, LT(_MOUSE, KC_SLSH), RSFT_T(KC_ENT),
|
_______, KC_K, KC_L, KC_COMM, KC_DOT, LT(_MOUSE, KC_SLSH), RSFT_T(KC_ENT),
|
||||||
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
||||||
|
|
||||||
TT(_NUM), TG(_MOUSE),
|
_______, KC_MPLY,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_LGUI, RAISE, KC_SPACE
|
KC_LGUI, RAISE, KC_SPACE
|
||||||
),
|
),
|
||||||
|
|
||||||
/* Keymap 0: Basic Dvorak layer
|
/* Keymap 0: Basic Dvorak layer
|
||||||
@@ -129,41 +115,41 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* | Tab | ' | , | . | P | Y | [{ | | ]} | F | G | C | R | L | BSPC |
|
* | Tab | ' | , | . | P | Y | [{ | | ]} | F | G | C | R | L | BSPC |
|
||||||
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | ESC | A | O | E | U | I |------| |------| D | H | T | N | S | / |
|
* | ESC | A | O | E | U | I |------| |------| D | H | T | N | S | / |
|
||||||
* |--------+-----+-----+-----+-----+-----| L1 | | L1 |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | LShift | ; | Q | J | K | X | | | | B | M | W | V | Z | Enter |
|
* | LShift | ; | Q | J | K | X | | | | B | M | W | V | Z | Enter |
|
||||||
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
||||||
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
||||||
* `------------------------------' `------------------------------'
|
* `------------------------------' `------------------------------'
|
||||||
* ,------------. ,------------.
|
* ,------------. ,------------.
|
||||||
* |Play |Mouse | | Num |Mouse|
|
* |Play | | | |Play |
|
||||||
* ,----|-----|------| |------+-----+-----.
|
* ,-----|-----|------| |------+-----+-----.
|
||||||
* | | | Alt | | Alt | | |
|
* | | | Alt | | Alt | | |
|
||||||
* |BSPC|LOWER|------| |------|RAISE|Space|
|
* |Space|LOWER|------| |------|RAISE|Space|
|
||||||
* | | | LGUI | | LGUI | | |
|
* | | | LGUI | | LGUI | | |
|
||||||
* `-----------------' `------------------'
|
* `------------------' `------------------'
|
||||||
*/
|
*/
|
||||||
[_DVORAK] = LAYOUT_ergodox(
|
[_DVORAK] = LAYOUT_ergodox(
|
||||||
// left hand
|
// left hand
|
||||||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
||||||
KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_LBRACKET,
|
KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_LBRACKET,
|
||||||
KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I,
|
KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I,
|
||||||
KC_LSFT, KC_SCOLON, KC_Q, KC_J, KC_K, KC_X, KC_FN1,
|
KC_LSFT, KC_SCOLON, KC_Q, KC_J, KC_K, KC_X, _______,
|
||||||
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
||||||
|
|
||||||
KC_MPLY, TG(_MOUSE),
|
KC_MPLY, _______,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_BSPACE, LOWER, KC_LGUI,
|
KC_SPACE, LOWER, KC_LGUI,
|
||||||
|
|
||||||
// right hand
|
// right hand
|
||||||
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
||||||
KC_RBRACKET, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPACE,
|
KC_RBRACKET, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPACE,
|
||||||
KC_D, KC_H, KC_T, KC_N, KC_S, LT(MOUSE, KC_SLSH),
|
KC_D, KC_H, KC_T, KC_N, KC_S, LT(MOUSE, KC_SLSH),
|
||||||
KC_FN1, KC_B, KC_M, KC_W, KC_V, KC_Z, RSFT_T(KC_ENT),
|
_______, KC_B, KC_M, KC_W, KC_V, KC_Z, RSFT_T(KC_ENT),
|
||||||
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
||||||
|
|
||||||
TT(_NUM), TG(_MOUSE),
|
_______, KC_MPLY,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_LGUI, RAISE, KC_SPACE
|
KC_LGUI, RAISE, KC_SPACE
|
||||||
),
|
),
|
||||||
|
|
||||||
/* Keymap 0: Basic Colemak layer
|
/* Keymap 0: Basic Colemak layer
|
||||||
@@ -174,41 +160,41 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* | Tab | Q | W | F | P | G | [{ | | ]} | J | L | U | Y | ; | BSPC |
|
* | Tab | Q | W | F | P | G | [{ | | ]} | J | L | U | Y | ; | BSPC |
|
||||||
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | ESC | A | R | S | T | D |------| |------| H | N | E | I | O | ' |
|
* | ESC | A | R | S | T | D |------| |------| H | N | E | I | O | ' |
|
||||||
* |--------+-----+-----+-----+-----+-----| L1 | | L1 |-----+-----+-----+-----+-----+--------|
|
* |--------+-----+-----+-----+-----+-----| | | |-----+-----+-----+-----+-----+--------|
|
||||||
* | LShift | Z | X | C | V | B | | | | K | M | , | . | / | Enter |
|
* | LShift | Z | X | C | V | B | | | | K | M | , | . | / | Enter |
|
||||||
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
* `--------+-----+-----+-----+-----+------------' `------------+-----+-----+-----+-----+--------'
|
||||||
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
* | Num |Ctrl | Alt |LGUI |Lower| |Raise|Left |Down | Up |Right |
|
||||||
* `------------------------------' `------------------------------'
|
* `------------------------------' `------------------------------'
|
||||||
* ,------------. ,------------.
|
* ,------------. ,------------.
|
||||||
* |Play |Mouse | | Num |Mouse|
|
* |Play | | | |Play |
|
||||||
* ,----|-----|------| |------+-----+-----.
|
* ,-----|-----|------| |------+-----+-----.
|
||||||
* | | | Alt | | Alt | | |
|
* | | | Alt | | Alt | | |
|
||||||
* |BSPC|LOWER|------| |------|RAISE|Space|
|
* |Space|LOWER|------| |------|RAISE|Space|
|
||||||
* | | | LGUI | | LGUI | | |
|
* | | | LGUI | | LGUI | | |
|
||||||
* `-----------------' `------------------'
|
* `------------------' `------------------'
|
||||||
*/
|
*/
|
||||||
[_COLEMAK] = LAYOUT_ergodox(
|
[_COLEMAK] = LAYOUT_ergodox(
|
||||||
// left hand
|
// left hand
|
||||||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_ESC,
|
||||||
KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_LBRACKET,
|
KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_LBRACKET,
|
||||||
KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D,
|
KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D,
|
||||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_FN1,
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, _______,
|
||||||
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
TT(_NUM), KC_LCTL, KC_LALT, KC_LGUI, LOWER,
|
||||||
|
|
||||||
KC_MPLY, TG(_MOUSE),
|
KC_MPLY, _______,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_BSPACE, LOWER, KC_LGUI,
|
KC_SPACE, LOWER, KC_LGUI,
|
||||||
|
|
||||||
// right hand
|
// right hand
|
||||||
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
KC_ESC, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
||||||
KC_RBRACKET, KC_J, KC_L, KC_U, KC_Y, KC_SCOLON, KC_BSPACE,
|
KC_RBRACKET, KC_J, KC_L, KC_U, KC_Y, KC_SCOLON, KC_BSPACE,
|
||||||
KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOTE,
|
KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOTE,
|
||||||
KC_FN1, KC_K, KC_M, KC_COMM, KC_DOT, LT(_MOUSE, KC_SLSH), RSFT_T(KC_ENT),
|
_______, KC_K, KC_M, KC_COMM, KC_DOT, LT(_MOUSE, KC_SLSH), RSFT_T(KC_ENT),
|
||||||
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT,
|
||||||
|
|
||||||
TT(_NUM), TG(_MOUSE),
|
_______, KC_MPLY,
|
||||||
KC_LALT,
|
KC_LALT,
|
||||||
KC_LGUI, RAISE, KC_SPACE
|
KC_LGUI, RAISE, KC_SPACE
|
||||||
),
|
),
|
||||||
|
|
||||||
/* Lower
|
/* Lower
|
||||||
@@ -216,19 +202,19 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* ,---------------------------------------------------. ,--------------------------------------------------.
|
* ,---------------------------------------------------. ,--------------------------------------------------.
|
||||||
* | Version | F1 | F2 | F3 | F4 | F5 | F11 | | F12 | F6 | F7 | F8 | F9 | F10 | |
|
* | Version | F1 | F2 | F3 | F4 | F5 | F11 | | F12 | F6 | F7 | F8 | F9 | F10 | |
|
||||||
* |---------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
|
* |---------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
|
||||||
* | ~ | ! | @ | # | $ | % | | | | ^ | & | * | ( | ) | |
|
* | ~ | ! | @ | # | $ | % | F6 | | F5 | ^ | & | * | ( | ) | |
|
||||||
* |---------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
* |---------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||||
* | Del | F1 | F2 | F3 | F4 | F5 |------| |------| F6 | _ | + | { | } | | |
|
* | Del | F1 | F2 | F3 | F4 | F5 |------| |------| F6 | _ | + | { | } | | |
|
||||||
* |---------+------+------+------+------+------| L2 | | L2 |------+------+------+------+------+--------|
|
* |---------+------+------+------+------+------| F12 | | F11 |------+------+------+------+------+--------|
|
||||||
* | | F7 | F8 | F9 | F10 | F11 | | | | F12 |ISO ~ |ISO | | Home | End | |
|
* | | F7 | F8 | F9 | F10 | F11 | | | | F12 |ISO ~ |ISO | | Home | End | |
|
||||||
* `---------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
* `---------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
||||||
* | | | | | | | | Play | Vol- | Vol+ | Next |
|
* | | | | | | | | Play | Vol- | Vol+ | Next |
|
||||||
* `-----------------------------------' `----------------------------------'
|
* `-----------------------------------' `----------------------------------'
|
||||||
* ,-------------. ,-------------.
|
* ,-------------. ,-------------.
|
||||||
* |Animat| | |Toggle|Solid |
|
* | | | | | |
|
||||||
* ,------|------|------| |------+------+------.
|
* ,------|------|------| |------+------+------.
|
||||||
* |Bright|Bright| | | |Hue- |Hue+ |
|
* | | | | | | | |
|
||||||
* |ness- |ness+ |------| |------| | |
|
* | | |------| |------| | |
|
||||||
* | | | | | | | |
|
* | | | | | | | |
|
||||||
* `--------------------' `--------------------'
|
* `--------------------' `--------------------'
|
||||||
*/
|
*/
|
||||||
@@ -261,10 +247,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* ,---------------------------------------------------. ,--------------------------------------------------.
|
* ,---------------------------------------------------. ,--------------------------------------------------.
|
||||||
* | Version | F1 | F2 | F3 | F4 | F5 | F11 | | F12 | F6 | F7 | F8 | F9 | F10 | F11 |
|
* | Version | F1 | F2 | F3 | F4 | F5 | F11 | | F12 | F6 | F7 | F8 | F9 | F10 | F11 |
|
||||||
* |---------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
|
* |---------+------+------+------+------+------+------| |------+------+------+------+------+------+--------|
|
||||||
* | ` | 1 | 2 | 3 | 4 | 5 | | | | 6 | 7 | 8 | 9 | 0 | |
|
* | ` | 1 | 2 | 3 | 4 | 5 | F6 | | F5 | 6 | 7 | 8 | 9 | 0 | |
|
||||||
* |---------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
* |---------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||||
* | Del | F1 | F2 | F3 | F4 | F5 |------| |------| F6 | - | = | [ | ] | \ |
|
* | Del | F1 | F2 | F3 | F4 | F5 |------| |------| F6 | - | = | [ | ] | \ |
|
||||||
* |---------+------+------+------+------+------| L2 | | L2 |------+------+------+------+------+--------|
|
* |---------+------+------+------+------+------| F12 | | F11 |------+------+------+------+------+--------|
|
||||||
* | | F7 | F8 | F9 | F10 | F11 | | | | F12 |ISO # |ISO / |Pg Up |Pg Dn | |
|
* | | F7 | F8 | F9 | F10 | F11 | | | | F12 |ISO # |ISO / |Pg Up |Pg Dn | |
|
||||||
* `---------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
* `---------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
||||||
* | | | | | | | | Play | Vol- | Vol+ | Next |
|
* | | | | | | | | Play | Vol- | Vol+ | Next |
|
||||||
@@ -308,7 +294,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
|
* |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------|
|
||||||
* | |Reset |Debug | | | | | | | |TRM on|TRMoff| | | Del |
|
* | |Reset |Debug | | | | | | | |TRM on|TRMoff| | | Del |
|
||||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||||
* | CPSLCK | | | | |AG Nrm|------| |------|AG Swp|QWERTY|Wrkman|Dvorak| | |
|
* | CPSLCK | | | | |AG Nrm|------| |------|AG Swp|QWERTY|Wrkman|Dvorak|Colmak| |
|
||||||
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
* |--------+------+------+------+------+------| | | |------+------+------+------+------+--------|
|
||||||
* | | | | | | | | | | | | Prev | Next | | |
|
* | | | | | | | | | | | | Prev | Next | | |
|
||||||
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
* `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------'
|
||||||
@@ -325,7 +311,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
[_ADJUST] = LAYOUT_ergodox(
|
[_ADJUST] = LAYOUT_ergodox(
|
||||||
// left hand
|
// left hand
|
||||||
VRSN, _______, _______, _______, _______, _______, _______,
|
VRSN, _______, _______, _______, _______, _______, _______,
|
||||||
_______, RESET, DEBUG, _______, _______, _______, _______,
|
_______, RESET, DEBUG, BL_TOGG, BL_STEP, _______, _______,
|
||||||
KC_CAPS, _______, _______, _______, _______, AG_NORM,
|
KC_CAPS, _______, _______, _______, _______, AG_NORM,
|
||||||
_______, _______, _______, _______, _______, _______, _______,
|
_______, _______, _______, _______, _______, _______, _______,
|
||||||
_______, _______, _______, _______, _______,
|
_______, _______, _______, _______, _______,
|
||||||
@@ -502,6 +488,11 @@ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
|
|||||||
return MACRO_NONE;
|
return MACRO_NONE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void matrix_init_user() {
|
||||||
|
backlight_enable();
|
||||||
|
backlight_level(BACKLIGHT_LEVELS);
|
||||||
|
}
|
||||||
|
|
||||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
switch (keycode) {
|
switch (keycode) {
|
||||||
case QWERTY:
|
case QWERTY:
|
||||||
@@ -576,34 +567,3 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs just one time when the keyboard initializes.
|
|
||||||
*/
|
|
||||||
void matrix_init_user(void) {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs constantly in the background, in a loop.
|
|
||||||
*/
|
|
||||||
void matrix_scan_user(void) {
|
|
||||||
uint8_t layer = biton32(layer_state);
|
|
||||||
|
|
||||||
ergodox_board_led_off();
|
|
||||||
ergodox_led_lower_off();
|
|
||||||
ergodox_led_raise_off();
|
|
||||||
ergodox_led_adjust_off();
|
|
||||||
|
|
||||||
switch (layer) {
|
|
||||||
case _LOWER:
|
|
||||||
ergodox_led_lower_on();
|
|
||||||
break;
|
|
||||||
case _RAISE:
|
|
||||||
ergodox_led_raise_on();
|
|
||||||
break;
|
|
||||||
case _ADJUST:
|
|
||||||
ergodox_led_adjust_on();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
enum custom_layers {
|
||||||
|
_QWERTY,
|
||||||
|
_WORKMAN,
|
||||||
|
_DVORAK,
|
||||||
|
_COLEMAK,
|
||||||
|
_LOWER,
|
||||||
|
_RAISE,
|
||||||
|
_ADJUST,
|
||||||
|
_GAME,
|
||||||
|
_MOUSE,
|
||||||
|
_NUM,
|
||||||
|
};
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
/* Copyright 2017 Fred Sundvik
|
||||||
|
*
|
||||||
|
* 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 KEYBOARDS_ERGODOX_INFINITY_SIMPLE_VISUALIZER_H_
|
||||||
|
#define KEYBOARDS_ERGODOX_INFINITY_SIMPLE_VISUALIZER_H_
|
||||||
|
|
||||||
|
// Currently we are assuming that both the backlight and LCD are enabled
|
||||||
|
// But it's entirely possible to write a custom visualizer that use only
|
||||||
|
// one of them
|
||||||
|
#ifndef LCD_BACKLIGHT_ENABLE
|
||||||
|
#error This visualizer needs that LCD backlight is enabled
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LCD_ENABLE
|
||||||
|
#error This visualizer needs that LCD is enabled
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "visualizer.h"
|
||||||
|
#include "visualizer_keyframes.h"
|
||||||
|
#include "lcd_keyframes.h"
|
||||||
|
#include "lcd_backlight_keyframes.h"
|
||||||
|
#include "system/serial_link.h"
|
||||||
|
#include "led.h"
|
||||||
|
#include "default_animations.h"
|
||||||
|
|
||||||
|
static const uint32_t logo_background_color = LCD_COLOR(0x00, 0x00, 0xFF);
|
||||||
|
static const uint32_t initial_color = LCD_COLOR(0, 0, 0);
|
||||||
|
|
||||||
|
static bool initial_update = true;
|
||||||
|
|
||||||
|
// Feel free to modify the animations below, or even add new ones if needed
|
||||||
|
|
||||||
|
static keyframe_animation_t lcd_layer_display = {
|
||||||
|
.num_frames = 1,
|
||||||
|
.loop = false,
|
||||||
|
.frame_lengths = {gfxMillisecondsToTicks(0)},
|
||||||
|
.frame_functions = {lcd_keyframe_display_layer_and_led_states}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The color animation animates the LCD color when you change layers
|
||||||
|
static keyframe_animation_t color_animation = {
|
||||||
|
.num_frames = 2,
|
||||||
|
.loop = false,
|
||||||
|
// Note that there's a 200 ms no-operation frame,
|
||||||
|
// this prevents the color from changing when activating the layer
|
||||||
|
// momentarily
|
||||||
|
.frame_lengths = {gfxMillisecondsToTicks(1), gfxMillisecondsToTicks(5)},
|
||||||
|
.frame_functions = {keyframe_no_operation, lcd_backlight_keyframe_animate_color},
|
||||||
|
};
|
||||||
|
|
||||||
|
void initialize_user_visualizer(visualizer_state_t* state) {
|
||||||
|
// The brightness will be dynamically adjustable in the future
|
||||||
|
// But for now, change it here.
|
||||||
|
lcd_backlight_brightness(130);
|
||||||
|
state->current_lcd_color = initial_color;
|
||||||
|
state->target_lcd_color = logo_background_color;
|
||||||
|
initial_update = true;
|
||||||
|
start_keyframe_animation(&default_startup_animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This function should be implemented by the keymap visualizer
|
||||||
|
// Don't change anything else than state->target_lcd_color and state->layer_text as that's the only thing
|
||||||
|
// that the simple_visualizer assumes that you are updating
|
||||||
|
// Also make sure that the buffer passed to state->layer_text remains valid until the previous animation is
|
||||||
|
// stopped. This can be done by either double buffering it or by using constant strings
|
||||||
|
static void get_visualizer_layer_and_color(visualizer_state_t* state);
|
||||||
|
|
||||||
|
void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) {
|
||||||
|
// Add more tests, change the colors and layer texts here
|
||||||
|
// Usually you want to check the high bits (higher layers first)
|
||||||
|
// because that's the order layers are processed for keypresses
|
||||||
|
// You can for check for example:
|
||||||
|
// state->status.layer
|
||||||
|
// state->status.default_layer
|
||||||
|
// state->status.leds (see led.h for available statuses)
|
||||||
|
|
||||||
|
uint32_t prev_color = state->target_lcd_color;
|
||||||
|
const char* prev_layer_text = state->layer_text;
|
||||||
|
|
||||||
|
get_visualizer_layer_and_color(state);
|
||||||
|
|
||||||
|
if (initial_update || prev_color != state->target_lcd_color) {
|
||||||
|
start_keyframe_animation(&color_animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initial_update || prev_layer_text != state->layer_text) {
|
||||||
|
start_keyframe_animation(&lcd_layer_display);
|
||||||
|
}
|
||||||
|
// You can also stop existing animations, and start your custom ones here
|
||||||
|
// remember that you should normally have only one animation for the LCD
|
||||||
|
// and one for the background. But you can also combine them if you want.
|
||||||
|
}
|
||||||
|
|
||||||
|
void user_visualizer_suspend(visualizer_state_t* state) {
|
||||||
|
state->layer_text = "Suspending...";
|
||||||
|
uint8_t hue = LCD_HUE(state->current_lcd_color);
|
||||||
|
uint8_t sat = LCD_SAT(state->current_lcd_color);
|
||||||
|
state->target_lcd_color = LCD_COLOR(hue, sat, 0);
|
||||||
|
start_keyframe_animation(&default_suspend_animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void user_visualizer_resume(visualizer_state_t* state) {
|
||||||
|
state->current_lcd_color = initial_color;
|
||||||
|
state->target_lcd_color = logo_background_color;
|
||||||
|
initial_update = true;
|
||||||
|
start_keyframe_animation(&default_startup_animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* KEYBOARDS_ERGODOX_INFINITY_SIMPLE_VISUALIZER_H_ */
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2016 Fred Sundvik <[email protected]>
|
Copyright 2017 Fred Sundvik
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -15,331 +15,65 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
#include "./simple_visualizer.h"
|
||||||
* Currently we are assuming that both the backlight and LCD are enabled
|
#include "util.h"
|
||||||
* But it's entirely possible to write a custom visualizer that use only
|
#include "layers.h"
|
||||||
* one of them
|
|
||||||
*/
|
|
||||||
#ifndef LCD_BACKLIGHT_ENABLE
|
|
||||||
#error This visualizer needs that LCD backlight is enabled
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LCD_ENABLE
|
// This function should be implemented by the keymap visualizer
|
||||||
#error This visualizer needs that LCD is enabled
|
// Don't change anything else than state->target_lcd_color and state->layer_text as that's the only thing
|
||||||
#endif
|
// that the simple_visualizer assumes that you are updating
|
||||||
|
// Also make sure that the buffer passed to state->layer_text remains valid until the previous animation is
|
||||||
#include "./visualizer.h"
|
// stopped. This can be done by either double buffering it or by using constant strings
|
||||||
#include "visualizer_keyframes.h"
|
static void get_visualizer_layer_and_color(visualizer_state_t* state) {
|
||||||
#include "lcd_keyframes.h"
|
switch(biton32(default_layer_state)) {
|
||||||
#include "lcd_backlight_keyframes.h"
|
case _QWERTY:
|
||||||
#include "system/serial_link.h"
|
state->layer_text = "QWERTY";
|
||||||
#include "default_animations.h"
|
state->target_lcd_color = LCD_COLOR(0, 255, 128);
|
||||||
|
break;
|
||||||
static const uint32_t logo_background_color = LCD_COLOR(0, 0, 255);
|
case _WORKMAN:
|
||||||
static const uint32_t initial_color = LCD_COLOR(84, 255, 255);
|
state->layer_text = "Workman";
|
||||||
|
state->target_lcd_color = LCD_COLOR(80, 255, 128);
|
||||||
static const uint32_t led_emulation_colors[4] = {
|
break;
|
||||||
LCD_COLOR(0, 0, 255),
|
case _DVORAK:
|
||||||
LCD_COLOR(141, 255, 255),
|
state->layer_text = "Dvorak";
|
||||||
LCD_COLOR(18, 255, 255),
|
state->target_lcd_color = LCD_COLOR(194, 255, 128);
|
||||||
LCD_COLOR(194, 255, 255),
|
break;
|
||||||
};
|
case _COLEMAK:
|
||||||
|
state->layer_text = "Colemak";
|
||||||
static uint32_t next_led_target_color = 0;
|
state->target_lcd_color = LCD_COLOR(18, 255, 128);
|
||||||
|
break;
|
||||||
typedef enum {
|
|
||||||
LCD_STATE_INITIAL,
|
|
||||||
LCD_STATE_LAYER_BITMAP,
|
|
||||||
LCD_STATE_BITMAP_AND_LEDS,
|
|
||||||
} lcd_state_t;
|
|
||||||
|
|
||||||
static lcd_state_t lcd_state = LCD_STATE_INITIAL;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t led_on;
|
|
||||||
uint8_t led1;
|
|
||||||
uint8_t led2;
|
|
||||||
uint8_t led3;
|
|
||||||
} visualizer_user_data_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Don't access from visualization function, use the visualizer state instead
|
|
||||||
*/
|
|
||||||
static visualizer_user_data_t user_data_keyboard = {
|
|
||||||
.led_on = 0,
|
|
||||||
.led1 = LED_BRIGHTNESS_HI,
|
|
||||||
.led2 = LED_BRIGHTNESS_HI,
|
|
||||||
.led3 = LED_BRIGHTNESS_HI,
|
|
||||||
};
|
|
||||||
|
|
||||||
_Static_assert(sizeof(visualizer_user_data_t) <= VISUALIZER_USER_DATA_SIZE,
|
|
||||||
"Please increase the VISUALIZER_USER_DATA_SIZE");
|
|
||||||
|
|
||||||
// Feel free to modify the animations below, or even add new ones if needed
|
|
||||||
|
|
||||||
// The color animation animates the LCD color when you change layers
|
|
||||||
static keyframe_animation_t one_led_color = {
|
|
||||||
.num_frames = 1,
|
|
||||||
.loop = false,
|
|
||||||
.frame_lengths = {gfxMillisecondsToTicks(0)},
|
|
||||||
.frame_functions = {lcd_backlight_keyframe_set_color},
|
|
||||||
};
|
|
||||||
|
|
||||||
bool swap_led_target_color(keyframe_animation_t* animation, visualizer_state_t* state) {
|
|
||||||
uint32_t temp = next_led_target_color;
|
|
||||||
next_led_target_color = state->target_lcd_color;
|
|
||||||
state->target_lcd_color = temp;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The color animation animates the LCD color when you change layers
|
|
||||||
static keyframe_animation_t two_led_colors = {
|
|
||||||
.num_frames = 2,
|
|
||||||
.loop = true,
|
|
||||||
.frame_lengths = {gfxMillisecondsToTicks(1000), gfxMillisecondsToTicks(0)},
|
|
||||||
.frame_functions = {lcd_backlight_keyframe_set_color, swap_led_target_color},
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The LCD animation alternates between the layer name display and a
|
|
||||||
* bitmap that displays all active layers
|
|
||||||
*/
|
|
||||||
static keyframe_animation_t lcd_bitmap_animation = {
|
|
||||||
.num_frames = 1,
|
|
||||||
.loop = false,
|
|
||||||
.frame_lengths = {gfxMillisecondsToTicks(0)},
|
|
||||||
.frame_functions = {lcd_keyframe_display_layer_bitmap},
|
|
||||||
};
|
|
||||||
|
|
||||||
static keyframe_animation_t lcd_bitmap_leds_animation = {
|
|
||||||
.num_frames = 2,
|
|
||||||
.loop = true,
|
|
||||||
.frame_lengths = {gfxMillisecondsToTicks(2000), gfxMillisecondsToTicks(2000)},
|
|
||||||
.frame_functions = {lcd_keyframe_display_layer_bitmap, lcd_keyframe_display_led_states},
|
|
||||||
};
|
|
||||||
|
|
||||||
void initialize_user_visualizer(visualizer_state_t* state) {
|
|
||||||
/**
|
|
||||||
* The brightness will be dynamically adjustable in the future
|
|
||||||
* But for now, change it here.
|
|
||||||
*/
|
|
||||||
lcd_backlight_brightness(180);
|
|
||||||
state->current_lcd_color = initial_color;
|
|
||||||
state->target_lcd_color = logo_background_color;
|
|
||||||
lcd_state = LCD_STATE_INITIAL;
|
|
||||||
start_keyframe_animation(&default_startup_animation);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool is_led_on(visualizer_user_data_t* user_data, uint8_t num) {
|
|
||||||
return user_data->led_on & (1u << num);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t get_led_index_master(visualizer_user_data_t* user_data) {
|
|
||||||
for (int i=0; i < 4; i++) {
|
|
||||||
if (is_led_on(user_data, i)) {
|
|
||||||
return i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t get_led_index_slave(visualizer_user_data_t* user_data) {
|
|
||||||
uint8_t master_index = get_led_index_master(user_data);
|
|
||||||
if (master_index!=0) {
|
|
||||||
for (int i=master_index; i < 4; i++) {
|
|
||||||
if (is_led_on(user_data, i)) {
|
|
||||||
return i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
switch(biton32(state->status.layer)) {
|
||||||
}
|
case _LOWER:
|
||||||
|
state->layer_text = "Lower";
|
||||||
static uint8_t get_secondary_led_index(visualizer_user_data_t* user_data) {
|
state->target_lcd_color = LCD_COLOR(141, 255, 255);
|
||||||
if (
|
break;
|
||||||
is_led_on(user_data, 0) &&
|
case _RAISE:
|
||||||
is_led_on(user_data, 1) &&
|
state->layer_text = "Raise";
|
||||||
is_led_on(user_data, 2)
|
state->target_lcd_color = LCD_COLOR(18, 255, 255);
|
||||||
) {
|
break;
|
||||||
return 3;
|
case _ADJUST:
|
||||||
}
|
state->layer_text = "Adjust";
|
||||||
return 0;
|
state->target_lcd_color = LCD_COLOR(194, 255, 255);
|
||||||
}
|
break;
|
||||||
|
case _NUM:
|
||||||
static uint8_t get_brightness(visualizer_user_data_t* user_data, uint8_t index) {
|
state->layer_text = "Numpad";
|
||||||
switch (index) {
|
state->target_lcd_color = LCD_COLOR(80, 255, 255);
|
||||||
case 1:
|
break;
|
||||||
return user_data->led1;
|
case _MOUSE:
|
||||||
case 2:
|
state->layer_text = "Mouse";
|
||||||
return user_data->led2;
|
state->target_lcd_color = LCD_COLOR(300, 255, 255);
|
||||||
case 3:
|
break;
|
||||||
return user_data->led3;
|
case _GAME:
|
||||||
}
|
state->layer_text = "Game";
|
||||||
return 0;
|
state->target_lcd_color = LCD_COLOR(300, 255, 255);
|
||||||
}
|
break;
|
||||||
|
case _QWERTY: case _WORKMAN: case _DVORAK: case _COLEMAK:
|
||||||
static void update_emulated_leds(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) {
|
break;
|
||||||
visualizer_user_data_t* user_data_new = (visualizer_user_data_t*)state->status.user_data;
|
default:
|
||||||
visualizer_user_data_t* user_data_old = (visualizer_user_data_t*)prev_status->user_data;
|
state->layer_text = "NONE";
|
||||||
|
state->target_lcd_color = LCD_COLOR(0, 255, 255);
|
||||||
uint8_t new_index;
|
break;
|
||||||
uint8_t old_index;
|
|
||||||
|
|
||||||
if (true || is_serial_link_master()) {
|
|
||||||
new_index = get_led_index_master(user_data_new);
|
|
||||||
old_index = get_led_index_master(user_data_old);
|
|
||||||
} else {
|
|
||||||
new_index = get_led_index_slave(user_data_new);
|
|
||||||
old_index = get_led_index_slave(user_data_old);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t new_secondary_index = get_secondary_led_index(user_data_new);
|
|
||||||
uint8_t old_secondary_index = get_secondary_led_index(user_data_old);
|
|
||||||
|
|
||||||
uint8_t new_brightness = get_brightness(user_data_new, new_index);
|
|
||||||
uint8_t old_brightness = get_brightness(user_data_old, old_index);
|
|
||||||
|
|
||||||
uint8_t new_secondary_brightness = get_brightness(user_data_new, new_secondary_index);
|
|
||||||
uint8_t old_secondary_brightness = get_brightness(user_data_old, old_secondary_index);
|
|
||||||
|
|
||||||
if (
|
|
||||||
lcd_state == LCD_STATE_INITIAL ||
|
|
||||||
new_index != old_index ||
|
|
||||||
new_secondary_index != old_secondary_index ||
|
|
||||||
new_brightness != old_brightness ||
|
|
||||||
new_secondary_brightness != old_secondary_brightness
|
|
||||||
) {
|
|
||||||
if (new_secondary_index != 0) {
|
|
||||||
state->target_lcd_color = change_lcd_color_intensity(
|
|
||||||
led_emulation_colors[new_index], new_brightness);
|
|
||||||
next_led_target_color = change_lcd_color_intensity(
|
|
||||||
led_emulation_colors[new_secondary_index], new_secondary_brightness);
|
|
||||||
|
|
||||||
stop_keyframe_animation(&one_led_color);
|
|
||||||
start_keyframe_animation(&two_led_colors);
|
|
||||||
} else {
|
|
||||||
state->target_lcd_color = change_lcd_color_intensity(
|
|
||||||
led_emulation_colors[new_index], new_brightness);
|
|
||||||
|
|
||||||
stop_keyframe_animation(&two_led_colors);
|
|
||||||
start_keyframe_animation(&one_led_color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update_lcd_text(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) {
|
|
||||||
if (state->status.leds) {
|
|
||||||
if (
|
|
||||||
lcd_state != LCD_STATE_BITMAP_AND_LEDS ||
|
|
||||||
state->status.leds != prev_status->leds ||
|
|
||||||
state->status.layer != prev_status->layer ||
|
|
||||||
state->status.default_layer != prev_status->default_layer
|
|
||||||
) {
|
|
||||||
// NOTE: that it doesn't matter if the animation isn't playing, stop will do nothing in that case
|
|
||||||
stop_keyframe_animation(&lcd_bitmap_animation);
|
|
||||||
|
|
||||||
lcd_state = LCD_STATE_BITMAP_AND_LEDS;
|
|
||||||
/**
|
|
||||||
* For information:
|
|
||||||
* The logic in this function makes sure that this doesn't happen, but if you call start on an
|
|
||||||
* animation that is already playing it will be restarted.
|
|
||||||
*/
|
|
||||||
start_keyframe_animation(&lcd_bitmap_leds_animation);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
lcd_state != LCD_STATE_LAYER_BITMAP ||
|
|
||||||
state->status.layer != prev_status->layer ||
|
|
||||||
state->status.default_layer != prev_status->default_layer
|
|
||||||
) {
|
|
||||||
stop_keyframe_animation(&lcd_bitmap_leds_animation);
|
|
||||||
|
|
||||||
lcd_state = LCD_STATE_LAYER_BITMAP;
|
|
||||||
start_keyframe_animation(&lcd_bitmap_animation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_user_visualizer_state(visualizer_state_t* state, visualizer_keyboard_status_t* prev_status) {
|
|
||||||
/**
|
|
||||||
* Check the status here to start and stop animations
|
|
||||||
* You might have to save some state, like the current animation here so that you can start the right
|
|
||||||
* This function is called every time the status changes
|
|
||||||
*
|
|
||||||
* NOTE that this is called from the visualizer thread, so don't access anything else outside the status
|
|
||||||
* This is also important because the slave won't have access to the active layer for example outside the
|
|
||||||
* status.
|
|
||||||
*/
|
|
||||||
|
|
||||||
update_emulated_leds(state, prev_status);
|
|
||||||
update_lcd_text(state, prev_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_visualizer_suspend(visualizer_state_t* state) {
|
|
||||||
state->layer_text = "Suspending...";
|
|
||||||
uint8_t hue = LCD_HUE(state->current_lcd_color);
|
|
||||||
uint8_t sat = LCD_SAT(state->current_lcd_color);
|
|
||||||
state->target_lcd_color = LCD_COLOR(hue, sat, 0);
|
|
||||||
start_keyframe_animation(&default_suspend_animation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void user_visualizer_resume(visualizer_state_t* state) {
|
|
||||||
state->current_lcd_color = initial_color;
|
|
||||||
state->target_lcd_color = logo_background_color;
|
|
||||||
lcd_state = LCD_STATE_INITIAL;
|
|
||||||
start_keyframe_animation(&default_startup_animation);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_board_led_on(void){
|
|
||||||
// No board led support
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_lower_on(void){
|
|
||||||
user_data_keyboard.led_on |= (1u << 0);
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_raise_on(void){
|
|
||||||
user_data_keyboard.led_on |= (1u << 1);
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_adjust_on(void){
|
|
||||||
user_data_keyboard.led_on |= (1u << 2);
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_board_led_off(void){
|
|
||||||
// No board led support
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_lower_off(void){
|
|
||||||
user_data_keyboard.led_on &= ~(1u << 0);
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_raise_off(void){
|
|
||||||
user_data_keyboard.led_on &= ~(1u << 1);
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_adjust_off(void){
|
|
||||||
user_data_keyboard.led_on &= ~(1u << 2);
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_lower_set(uint8_t n) {
|
|
||||||
user_data_keyboard.led1 = n;
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_raise_set(uint8_t n) {
|
|
||||||
user_data_keyboard.led2 = n;
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ergodox_led_adjust_set(uint8_t n) {
|
|
||||||
user_data_keyboard.led3 = n;
|
|
||||||
visualizer_set_user_data(&user_data_keyboard);
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,7 @@ extern keymap_config_t keymap_config;
|
|||||||
#define KC_MU KC_MS_UP
|
#define KC_MU KC_MS_UP
|
||||||
#define KC_MD KC_MS_DOWN
|
#define KC_MD KC_MS_DOWN
|
||||||
#define KC_MB1 KC_MS_BTN1
|
#define KC_MB1 KC_MS_BTN1
|
||||||
#define KC_MB2 KC_MS_BTN1
|
#define KC_MB2 KC_MS_BTN2
|
||||||
|
|
||||||
#define RAISE MO(_RAISE)
|
#define RAISE MO(_RAISE)
|
||||||
#define LOWER MO(_LOWER)
|
#define LOWER MO(_LOWER)
|
||||||
@@ -44,7 +44,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* '------+------' '------+------'
|
* '------+------' '------+------'
|
||||||
* | TAB | HOME | | END | DEL |
|
* | TAB | HOME | | END | DEL |
|
||||||
* '------+------' '------+------'
|
* '------+------' '------+------'
|
||||||
* | Lower| ~ | | GUI | Raise|
|
* | Raise| ~ | | GUI | Lower|
|
||||||
* '------+------' '------+------'
|
* '------+------' '------+------'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|||||||
* ,----------------------------------, ,----------------------------------,
|
* ,----------------------------------, ,----------------------------------,
|
||||||
* | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 |
|
* | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 |
|
||||||
* |------+------+------+------+------| |-------------+------+------+------|
|
* |------+------+------+------+------| |-------------+------+------+------|
|
||||||
* | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 10 |
|
* | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 |
|
||||||
* |------+------+------+------+------| |------|------+------+------+------|
|
* |------+------+------+------+------| |------|------+------+------+------|
|
||||||
* | ! | @ | # | $ | % | | ^ | & | * | ( | ) |
|
* | ! | @ | # | $ | % | | ^ | & | * | ( | ) |
|
||||||
* |------+------+------+-------------, ,-------------+------+------+------,
|
* |------+------+------+-------------, ,-------------+------+------+------,
|
||||||
|
|||||||
@@ -21,3 +21,7 @@
|
|||||||
#define MATRIX_COL_PINS { B0 }
|
#define MATRIX_COL_PINS { B0 }
|
||||||
#define MATRIX_ROW_PINS { A7 }
|
#define MATRIX_ROW_PINS { A7 }
|
||||||
#define UNUSED_PINS
|
#define UNUSED_PINS
|
||||||
|
|
||||||
|
#define BACKLIGHT_PIN A0
|
||||||
|
#define BACKLIGHT_PWM_DRIVER PWMD2
|
||||||
|
#define BACKLIGHT_PWM_CHANNEL 1
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
* @brief Enables the SPI subsystem.
|
* @brief Enables the SPI subsystem.
|
||||||
*/
|
*/
|
||||||
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
|
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
|
||||||
#define HAL_USE_SPI TRUE
|
#define HAL_USE_SPI FALSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -132,8 +132,8 @@
|
|||||||
* PWM driver system settings.
|
* PWM driver system settings.
|
||||||
*/
|
*/
|
||||||
#define STM32_PWM_USE_ADVANCED FALSE
|
#define STM32_PWM_USE_ADVANCED FALSE
|
||||||
#define STM32_PWM_USE_TIM1 TRUE
|
#define STM32_PWM_USE_TIM1 FALSE
|
||||||
#define STM32_PWM_USE_TIM2 FALSE
|
#define STM32_PWM_USE_TIM2 TRUE
|
||||||
#define STM32_PWM_USE_TIM3 FALSE
|
#define STM32_PWM_USE_TIM3 FALSE
|
||||||
#define STM32_PWM_USE_TIM4 FALSE
|
#define STM32_PWM_USE_TIM4 FALSE
|
||||||
#define STM32_PWM_USE_TIM5 FALSE
|
#define STM32_PWM_USE_TIM5 FALSE
|
||||||
@@ -168,7 +168,7 @@
|
|||||||
* SPI driver system settings.
|
* SPI driver system settings.
|
||||||
*/
|
*/
|
||||||
#define STM32_SPI_USE_SPI1 FALSE
|
#define STM32_SPI_USE_SPI1 FALSE
|
||||||
#define STM32_SPI_USE_SPI2 TRUE
|
#define STM32_SPI_USE_SPI2 FALSE
|
||||||
#define STM32_SPI_USE_SPI3 FALSE
|
#define STM32_SPI_USE_SPI3 FALSE
|
||||||
#define STM32_SPI_SPI1_DMA_PRIORITY 1
|
#define STM32_SPI_SPI1_DMA_PRIORITY 1
|
||||||
#define STM32_SPI_SPI2_DMA_PRIORITY 1
|
#define STM32_SPI_SPI2_DMA_PRIORITY 1
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
# GENERIC STM32F103C8T6 board - stm32duino bootloader
|
# GENERIC STM32F103C8T6 board - stm32duino bootloader
|
||||||
|
BOARD = GENERIC_STM32_F103
|
||||||
|
|
||||||
OPT_DEFS = -DCORTEX_VTOR_INIT=0x2000
|
OPT_DEFS = -DCORTEX_VTOR_INIT=0x2000
|
||||||
MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
|
MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
|
||||||
BOARD = GENERIC_STM32_F103
|
|
||||||
|
DFU_ARGS = -d 1eaf:0003 -a2 -R
|
||||||
|
DFU_SUFFIX_ARGS ?= -v 1eaf -p 0003
|
||||||
|
|
||||||
# OPT_DEFS =
|
# OPT_DEFS =
|
||||||
# MCU_LDSCRIPT = STM32F103x8
|
# MCU_LDSCRIPT = STM32F103x8
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
/* Set 0 if debouncing isn't needed */
|
/* Set 0 if debouncing isn't needed */
|
||||||
#define DEBOUNCE 5
|
#define DEBOUNCE 5
|
||||||
|
|
||||||
|
#define TAPPING_TERM 500
|
||||||
|
|
||||||
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
|
/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
|
||||||
#define LOCKING_SUPPORT_ENABLE
|
#define LOCKING_SUPPORT_ENABLE
|
||||||
/* Locking resynchronize hack */
|
/* Locking resynchronize hack */
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define BACKLIGHT_BREATHING
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
//Tap Dance Declarations
|
||||||
|
enum {
|
||||||
|
TD_BL = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
void dance_cln_finished (qk_tap_dance_state_t *state, void *user_data) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
|
||||||
|
void dance_cln_reset (qk_tap_dance_state_t *state, void *user_data) {
|
||||||
|
switch (state->count) {
|
||||||
|
case 1:
|
||||||
|
// single tap - step through backlight
|
||||||
|
backlight_step();
|
||||||
|
break;
|
||||||
|
#ifdef BACKLIGHT_BREATHING
|
||||||
|
case 2:
|
||||||
|
// double tap - toggle breathing
|
||||||
|
breathing_toggle();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
//tripple tap - do some pulse stuff
|
||||||
|
breathing_pulse();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
// more - nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qk_tap_dance_action_t tap_dance_actions[] = {
|
||||||
|
[TD_BL] = ACTION_TAP_DANCE_FN_ADVANCED (NULL, dance_cln_finished, dance_cln_reset)
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
LAYOUT( TD(TD_BL) )
|
||||||
|
};
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
BACKLIGHT_ENABLE = yes
|
||||||
|
TAP_DANCE_ENABLE = yes
|
||||||
@@ -21,3 +21,8 @@
|
|||||||
#define MATRIX_COL_PINS { A3 }
|
#define MATRIX_COL_PINS { A3 }
|
||||||
#define MATRIX_ROW_PINS { A2 }
|
#define MATRIX_ROW_PINS { A2 }
|
||||||
#define UNUSED_PINS
|
#define UNUSED_PINS
|
||||||
|
|
||||||
|
#define BACKLIGHT_PIN B8
|
||||||
|
#define BACKLIGHT_PWM_DRIVER PWMD4
|
||||||
|
#define BACKLIGHT_PWM_CHANNEL 3
|
||||||
|
#define BACKLIGHT_PAL_MODE 2
|
||||||
@@ -21,3 +21,8 @@
|
|||||||
#define MATRIX_COL_PINS { B4 }
|
#define MATRIX_COL_PINS { B4 }
|
||||||
#define MATRIX_ROW_PINS { B5 }
|
#define MATRIX_ROW_PINS { B5 }
|
||||||
#define UNUSED_PINS
|
#define UNUSED_PINS
|
||||||
|
|
||||||
|
#define BACKLIGHT_PIN C8
|
||||||
|
#define BACKLIGHT_PWM_DRIVER PWMD3
|
||||||
|
#define BACKLIGHT_PWM_CHANNEL 3
|
||||||
|
#define BACKLIGHT_PAL_MODE 0
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
### Massdrop Alt Layout
|
||||||
|
|
||||||
|
This layout is for the [Massdrop Alt
|
||||||
|
Keyboard](https://drop.com/buy/massdrop-alt-mechanical-keyboard)
|
||||||
|
and targets MacOS machines.
|
||||||
|
|
||||||
|
Some features:
|
||||||
|
|
||||||
|
* Tap space for space, hold for cmd
|
||||||
|
* Tap caps lock for esc, hold for ctrl
|
||||||
|
* Dedicated key for entering default mode of [yabai window
|
||||||
|
manager](https://github.com/koekeishiya/yabai)
|
||||||
|
* Who needs arrow keys, anyways???
|
||||||
|
* Method for clearing all stuck-down mods
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 Griffin Rademacher <[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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// toggle one-shot layer keys after this many presses
|
||||||
|
#define ONESHOT_TAP_TOGGLE 3
|
||||||
|
|
||||||
|
// set time held before Mod-Tap key sends mod code
|
||||||
|
#define TAPPING_TERM 1000
|
||||||
|
|
||||||
|
// permissive hold: if holding down a Mod-Tap key while pressing another, it
|
||||||
|
// acts as a mod, even within the tapping term
|
||||||
|
#define PERMISSIVE_HOLD
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
#include QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
enum alt_keycodes {
|
||||||
|
U_T_AUTO = SAFE_RANGE, //USB Extra Port Toggle Auto Detect / Always Active
|
||||||
|
U_T_AGCR, //USB Toggle Automatic GCR control
|
||||||
|
DBG_TOG, //DEBUG Toggle On / Off
|
||||||
|
DBG_MTRX, //DEBUG Toggle Matrix Prints
|
||||||
|
DBG_KBD, //DEBUG Toggle Keyboard Prints
|
||||||
|
DBG_MOU, //DEBUG Toggle Mouse Prints
|
||||||
|
MD_BOOT, //Restart into bootloader after hold timeout
|
||||||
|
HK_COSL, //Clear held-down keys
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TG_NKRO MAGIC_TOGGLE_NKRO //Toggle 6KRO / NKRO mode
|
||||||
|
#define CTL_ESC LCTL_T(KC_ESC)
|
||||||
|
#define TP_LSFT OSM(MOD_LSFT)
|
||||||
|
#define TP_RSFT OSM(MOD_RSFT)
|
||||||
|
#define TP_LALT OSM(MOD_LALT)
|
||||||
|
#define TP_RALT OSM(MOD_RALT)
|
||||||
|
#define KC_YBAI LCTL(KC_SPC)
|
||||||
|
#define GUI_SPC LGUI_T(KC_SPC)
|
||||||
|
#define KC_SPOT LGUI(KC_SPC)
|
||||||
|
|
||||||
|
//TODO default layer vim-like binds that work with WM, i to type??? this leads
|
||||||
|
//to layers of vim modes - what's the best way to deal with that?
|
||||||
|
//also need to deal with shift not working for other mods, add to shift layer
|
||||||
|
//most likely
|
||||||
|
//
|
||||||
|
//TODO tap/toggle for layers
|
||||||
|
|
||||||
|
keymap_config_t keymap_config;
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[0] = LAYOUT(
|
||||||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_SPOT,
|
||||||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_HOME,
|
||||||
|
CTL_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_MUTE,
|
||||||
|
TP_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_VOLU, KC_MPLY,
|
||||||
|
TP_LALT, TG(2), KC_YBAI, GUI_SPC, TP_RALT, TG(1), KC_MRWD, KC_VOLD, KC_MFFD
|
||||||
|
),
|
||||||
|
[1] = LAYOUT(
|
||||||
|
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______, KC_DEL,
|
||||||
|
_______, RGB_SPD, RGB_VAI, RGB_SPI, RGB_HUI, RGB_SAI, _______, U_T_AUTO,U_T_AGCR,_______, KC_PSCR, KC_SLCK, KC_PAUS, _______, KC_HOME,
|
||||||
|
_______, RGB_RMOD,RGB_VAD, RGB_MOD, RGB_HUD, RGB_SAD, _______, KC_MRWD, KC_MFFD, _______, _______, _______, _______, KC_PGUP,
|
||||||
|
_______, RGB_TOG, _______, _______, _______, MD_BOOT, TG_NKRO, DBG_TOG, _______, _______, _______, _______, KC_UP, KC_PGDN,
|
||||||
|
_______, _______, _______, HK_COSL, _______, TG(1), KC_LEFT, KC_DOWN, KC_RGHT
|
||||||
|
),
|
||||||
|
/*
|
||||||
|
[X] = LAYOUT(
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||||
|
_______, _______, _______, _______, _______, _______, _______, _______, _______
|
||||||
|
),
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
// Runs just one time when the keyboard initializes.
|
||||||
|
void matrix_init_user(void) {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Runs constantly in the background, in a loop.
|
||||||
|
void matrix_scan_user(void) {
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MODS_SHIFT (get_mods() & MOD_MASK_SHIFT)
|
||||||
|
#define MODS_CTRL (get_mods() & MOD_MASK_CTRL)
|
||||||
|
#define MODS_ALT (get_mods() & MOD_MASK_ALT)
|
||||||
|
|
||||||
|
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||||
|
static uint32_t key_timer;
|
||||||
|
|
||||||
|
switch (keycode) {
|
||||||
|
case HK_COSL:
|
||||||
|
clear_keyboard();
|
||||||
|
reset_oneshot_layer();
|
||||||
|
return true;
|
||||||
|
case U_T_AUTO:
|
||||||
|
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
|
||||||
|
TOGGLE_FLAG_AND_PRINT(usb_extra_manual, "USB extra port manual mode");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case U_T_AGCR:
|
||||||
|
if (record->event.pressed && MODS_SHIFT && MODS_CTRL) {
|
||||||
|
TOGGLE_FLAG_AND_PRINT(usb_gcr_auto, "USB GCR auto mode");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case DBG_TOG:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
TOGGLE_FLAG_AND_PRINT(debug_enable, "Debug mode");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case DBG_MTRX:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
TOGGLE_FLAG_AND_PRINT(debug_matrix, "Debug matrix");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case DBG_KBD:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
TOGGLE_FLAG_AND_PRINT(debug_keyboard, "Debug keyboard");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case DBG_MOU:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
TOGGLE_FLAG_AND_PRINT(debug_mouse, "Debug mouse");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MD_BOOT:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
key_timer = timer_read32();
|
||||||
|
} else {
|
||||||
|
if (timer_elapsed32(key_timer) >= 500) {
|
||||||
|
reset_keyboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case RGB_TOG:
|
||||||
|
if (record->event.pressed) {
|
||||||
|
switch (rgb_matrix_get_flags()) {
|
||||||
|
case LED_FLAG_ALL: {
|
||||||
|
rgb_matrix_set_flags(LED_FLAG_KEYLIGHT);
|
||||||
|
rgb_matrix_set_color_all(0, 0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_FLAG_KEYLIGHT: {
|
||||||
|
rgb_matrix_set_flags(LED_FLAG_UNDERGLOW);
|
||||||
|
rgb_matrix_set_color_all(0, 0, 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_FLAG_UNDERGLOW: {
|
||||||
|
rgb_matrix_set_flags(LED_FLAG_NONE);
|
||||||
|
rgb_matrix_disable_noeeprom();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
rgb_matrix_set_flags(LED_FLAG_ALL);
|
||||||
|
rgb_matrix_enable_noeeprom();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true; //Process all other keycodes normally
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
# Pulse 4k
|
# Pulse 4k
|
||||||
A four-key macropad with two rotary encoders, developed by Maxr1998, [fully open-source](https://github.com/Maxr1998/Pulse_4k).
|
A four-key macropad with two rotary encoders, developed by Maxr1998, [fully open-source](https://github.com/Maxr1998/Pulse_4k).
|
||||||
|
|
||||||
|
<p align="center"><img width="60%" src="https://i.imgur.com/g1QyqxS.jpg"></p>
|
||||||
|
|
||||||
Keyboard Maintainer: [Maxr1998](https://github.com/Maxr1998)
|
Keyboard Maintainer: [Maxr1998](https://github.com/Maxr1998)
|
||||||
Hardware Availability: DIY from the [open-source design files](https://github.com/Maxr1998/Pulse_4k), potential official distribution in the future
|
Hardware Availability: DIY from the [open-source design files](https://github.com/Maxr1998/Pulse_4k), potential official distribution in the future
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 Luiz Ribeiro <[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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config_common.h"
|
||||||
|
|
||||||
|
#define VENDOR_ID 0x20A0
|
||||||
|
#define PRODUCT_ID 0x422D
|
||||||
|
#define MANUFACTURER Percent
|
||||||
|
#define PRODUCT Skog Lite
|
||||||
|
|
||||||
|
#define RGBLED_NUM 18
|
||||||
|
|
||||||
|
#define MATRIX_ROWS 7
|
||||||
|
#define MATRIX_COLS 15
|
||||||
|
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E
|
||||||
|
#define MATRIX_ROW_PINS { B0, B1, B2, B3, B4, B6, B5 }
|
||||||
|
#define MATRIX_COL_PINS { C4, C2, D7, C7, C6, A0, A1, A2, A3, A7, A6, A5, A4, C5, C3}
|
||||||
|
#define UNUSED_PINS
|
||||||
|
|
||||||
|
#define DIODE_DIRECTION COL2ROW
|
||||||
|
#define DEBOUNCE 5
|
||||||
|
|
||||||
|
#define BACKLIGHT_LEVELS 1
|
||||||
|
#define RGBLIGHT_ANIMATIONS
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"keyboard_name": "Skog Lite",
|
||||||
|
"url": "",
|
||||||
|
"maintainer": "qmk",
|
||||||
|
"width": 18.25,
|
||||||
|
"height": 6.5,
|
||||||
|
"layouts": {
|
||||||
|
"LAYOUT_tkl_ansi": {
|
||||||
|
"layout": [{"x":0, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":6.5, "y":0}, {"x":7.5, "y":0}, {"x":8.5, "y":0}, {"x":9.5, "y":0}, {"x":11, "y":0}, {"x":12, "y":0}, {"x":13, "y":0}, {"x":14, "y":0}, {"x":15.25, "y":0}, {"x":16.25, "y":0}, {"x":17.25, "y":0}, {"x":0, "y":1.5}, {"x":1, "y":1.5}, {"x":2, "y":1.5}, {"x":3, "y":1.5}, {"x":4, "y":1.5}, {"x":5, "y":1.5}, {"x":6, "y":1.5}, {"x":7, "y":1.5}, {"x":8, "y":1.5}, {"x":9, "y":1.5}, {"x":10, "y":1.5}, {"x":11, "y":1.5}, {"x":12, "y":1.5}, {"x":13, "y":1.5, "w":2}, {"x":15.25, "y":1.5}, {"x":16.25, "y":1.5}, {"x":17.25, "y":1.5}, {"x":0, "y":2.5, "w":1.5}, {"x":1.5, "y":2.5}, {"x":2.5, "y":2.5}, {"x":3.5, "y":2.5}, {"x":4.5, "y":2.5}, {"x":5.5, "y":2.5}, {"x":6.5, "y":2.5}, {"x":7.5, "y":2.5}, {"x":8.5, "y":2.5}, {"x":9.5, "y":2.5}, {"x":10.5, "y":2.5}, {"x":11.5, "y":2.5}, {"x":12.5, "y":2.5}, {"x":13.5, "y":2.5, "w":1.5}, {"x":15.25, "y":2.5}, {"x":16.25, "y":2.5}, {"x":17.25, "y":2.5}, {"x":0, "y":3.5, "w":1.75}, {"x":1.75, "y":3.5}, {"x":2.75, "y":3.5}, {"x":3.75, "y":3.5}, {"x":4.75, "y":3.5}, {"x":5.75, "y":3.5}, {"x":6.75, "y":3.5}, {"x":7.75, "y":3.5}, {"x":8.75, "y":3.5}, {"x":9.75, "y":3.5}, {"x":10.75, "y":3.5}, {"x":11.75, "y":3.5}, {"x":12.75, "y":3.5, "w":2.25}, {"x":0, "y":4.5, "w":2.25}, {"x":2.25, "y":4.5}, {"x":3.25, "y":4.5}, {"x":4.25, "y":4.5}, {"x":5.25, "y":4.5}, {"x":6.25, "y":4.5}, {"x":7.25, "y":4.5}, {"x":8.25, "y":4.5}, {"x":9.25, "y":4.5}, {"x":10.25, "y":4.5}, {"x":11.25, "y":4.5}, {"x":12.25, "y":4.5, "w":2.75}, {"x":16.25, "y":4.5}, {"x":0, "y":5.5, "w":1.25}, {"x":1.25, "y":5.5, "w":1.25}, {"x":2.5, "y":5.5, "w":1.25}, {"x":3.75, "y":5.5, "w":6.25}, {"x":10, "y":5.5, "w":1.25}, {"x":11.25, "y":5.5, "w":1.25}, {"x":12.5, "y":5.5, "w":1.25}, {"x":13.75, "y":5.5, "w":1.25}, {"x":15.25, "y":5.5}, {"x":16.25, "y":5.5}, {"x":17.25, "y":5.5}]
|
||||||
|
},
|
||||||
|
|
||||||
|
"LAYOUT_tkl_7u_ansi": {
|
||||||
|
"layout": [{"x":0, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":6.5, "y":0}, {"x":7.5, "y":0}, {"x":8.5, "y":0}, {"x":9.5, "y":0}, {"x":11, "y":0}, {"x":12, "y":0}, {"x":13, "y":0}, {"x":14, "y":0}, {"x":15.25, "y":0}, {"x":16.25, "y":0}, {"x":17.25, "y":0}, {"x":0, "y":1.5}, {"x":1, "y":1.5}, {"x":2, "y":1.5}, {"x":3, "y":1.5}, {"x":4, "y":1.5}, {"x":5, "y":1.5}, {"x":6, "y":1.5}, {"x":7, "y":1.5}, {"x":8, "y":1.5}, {"x":9, "y":1.5}, {"x":10, "y":1.5}, {"x":11, "y":1.5}, {"x":12, "y":1.5}, {"x":13, "y":1.5, "w":2}, {"x":15.25, "y":1.5}, {"x":16.25, "y":1.5}, {"x":17.25, "y":1.5}, {"x":0, "y":2.5, "w":1.5}, {"x":1.5, "y":2.5}, {"x":2.5, "y":2.5}, {"x":3.5, "y":2.5}, {"x":4.5, "y":2.5}, {"x":5.5, "y":2.5}, {"x":6.5, "y":2.5}, {"x":7.5, "y":2.5}, {"x":8.5, "y":2.5}, {"x":9.5, "y":2.5}, {"x":10.5, "y":2.5}, {"x":11.5, "y":2.5}, {"x":12.5, "y":2.5}, {"x":13.5, "y":2.5, "w":1.5}, {"x":15.25, "y":2.5}, {"x":16.25, "y":2.5}, {"x":17.25, "y":2.5}, {"x":0, "y":3.5, "w":1.75}, {"x":1.75, "y":3.5}, {"x":2.75, "y":3.5}, {"x":3.75, "y":3.5}, {"x":4.75, "y":3.5}, {"x":5.75, "y":3.5}, {"x":6.75, "y":3.5}, {"x":7.75, "y":3.5}, {"x":8.75, "y":3.5}, {"x":9.75, "y":3.5}, {"x":10.75, "y":3.5}, {"x":11.75, "y":3.5}, {"x":12.75, "y":3.5, "w":2.25}, {"x":0, "y":4.5, "w":2.25}, {"x":2.25, "y":4.5}, {"x":3.25, "y":4.5}, {"x":4.25, "y":4.5}, {"x":5.25, "y":4.5}, {"x":6.25, "y":4.5}, {"x":7.25, "y":4.5}, {"x":8.25, "y":4.5}, {"x":9.25, "y":4.5}, {"x":10.25, "y":4.5}, {"x":11.25, "y":4.5}, {"x":12.25, "y":4.5, "w":2.75}, {"x":16.25, "y":4.5}, {"x":0, "y":5.5, "w":1.5}, {"x":1.5, "y":5.5}, {"x":2.5, "y":5.5, "w":1.5}, {"x":4, "y":5.5, "w":7}, {"x":11, "y":5.5, "w":1.5}, {"x":12.5, "y":5.5}, {"x":13.5, "y":5.5, "w":1.5}, {"x":15.25, "y":5.5}, {"x":16.25, "y":5.5}, {"x":17.25, "y":5.5}]
|
||||||
|
},
|
||||||
|
|
||||||
|
"LAYOUT_tkl_7u_ansi_blocker": {
|
||||||
|
"layout": [{"x":0, "y":0}, {"x":2, "y":0}, {"x":3, "y":0}, {"x":4, "y":0}, {"x":5, "y":0}, {"x":6.5, "y":0}, {"x":7.5, "y":0}, {"x":8.5, "y":0}, {"x":9.5, "y":0}, {"x":11, "y":0}, {"x":12, "y":0}, {"x":13, "y":0}, {"x":14, "y":0}, {"x":15.25, "y":0}, {"x":16.25, "y":0}, {"x":17.25, "y":0}, {"x":0, "y":1.5}, {"x":1, "y":1.5}, {"x":2, "y":1.5}, {"x":3, "y":1.5}, {"x":4, "y":1.5}, {"x":5, "y":1.5}, {"x":6, "y":1.5}, {"x":7, "y":1.5}, {"x":8, "y":1.5}, {"x":9, "y":1.5}, {"x":10, "y":1.5}, {"x":11, "y":1.5}, {"x":12, "y":1.5}, {"x":13, "y":1.5, "w":2}, {"x":15.25, "y":1.5}, {"x":16.25, "y":1.5}, {"x":17.25, "y":1.5}, {"x":0, "y":2.5, "w":1.5}, {"x":1.5, "y":2.5}, {"x":2.5, "y":2.5}, {"x":3.5, "y":2.5}, {"x":4.5, "y":2.5}, {"x":5.5, "y":2.5}, {"x":6.5, "y":2.5}, {"x":7.5, "y":2.5}, {"x":8.5, "y":2.5}, {"x":9.5, "y":2.5}, {"x":10.5, "y":2.5}, {"x":11.5, "y":2.5}, {"x":12.5, "y":2.5}, {"x":13.5, "y":2.5, "w":1.5}, {"x":15.25, "y":2.5}, {"x":16.25, "y":2.5}, {"x":17.25, "y":2.5}, {"x":0, "y":3.5, "w":1.75}, {"x":1.75, "y":3.5}, {"x":2.75, "y":3.5}, {"x":3.75, "y":3.5}, {"x":4.75, "y":3.5}, {"x":5.75, "y":3.5}, {"x":6.75, "y":3.5}, {"x":7.75, "y":3.5}, {"x":8.75, "y":3.5}, {"x":9.75, "y":3.5}, {"x":10.75, "y":3.5}, {"x":11.75, "y":3.5}, {"x":12.75, "y":3.5, "w":2.25}, {"x":0, "y":4.5, "w":2.25}, {"x":2.25, "y":4.5}, {"x":3.25, "y":4.5}, {"x":4.25, "y":4.5}, {"x":5.25, "y":4.5}, {"x":6.25, "y":4.5}, {"x":7.25, "y":4.5}, {"x":8.25, "y":4.5}, {"x":9.25, "y":4.5}, {"x":10.25, "y":4.5}, {"x":11.25, "y":4.5}, {"x":12.25, "y":4.5, "w":2.75}, {"x":16.25, "y":4.5}, {"x":0, "y":5.5, "w":1.5}, {"x":2.5, "y":5.5, "w":1.5}, {"x":4, "y":5.5, "w":7}, {"x":11, "y":5.5, "w":1.5}, {"x":13.5, "y":5.5, "w":1.5}, {"x":15.25, "y":5.5}, {"x":16.25, "y":5.5}, {"x":17.25, "y":5.5}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/* Copyright 2019 mechmerlin
|
||||||
|
*
|
||||||
|
* 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 QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[0] = LAYOUT_tkl_ansi(\
|
||||||
|
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR,KC_SLCK,KC_PAUS, \
|
||||||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0,KC_MINS, KC_EQL,KC_BSPC, KC_INS ,KC_HOME,KC_PGUP, \
|
||||||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P,KC_LBRC,KC_RBRC,KC_BSLS, KC_DEL ,KC_END ,KC_PGDN, \
|
||||||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L,KC_SCLN,KC_QUOT, KC_ENT, \
|
||||||
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M,KC_COMM, KC_DOT,KC_SLSH, KC_RSFT, KC_UP, \
|
||||||
|
KC_LCTL,KC_LGUI,KC_LALT, KC_SPC, KC_RALT,KC_RGUI, KC_APP,KC_RCTL, KC_LEFT,KC_DOWN,KC_RGHT) \
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# The default keymap for Skog Lite
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Skog Lite
|
||||||
|
|
||||||
|
TKL Custom Keyboard.
|
||||||
|
|
||||||
|
|
||||||
|
Keyboard Maintainer: [mechmerlin](https://github.com/mechmerlin)
|
||||||
|
Hardware Supported: Skog Lite PCB
|
||||||
|
Hardware Availability: [Kono Store](https://kono.store/products/skog-lite)
|
||||||
|
|
||||||
|
|
||||||
|
Make example for this keyboard (after setting up your build environment):
|
||||||
|
|
||||||
|
make percent/skog_lite:default
|
||||||
|
|
||||||
|
Flashing
|
||||||
|
|
||||||
|
ps2avr(GB) boards use an atmega32a microcontroller and a different bootloader. It is not flashable using the regular QMK methods.
|
||||||
|
|
||||||
|
**Reset Key:** Hold down the key located at `K05`, commonly programmed as `F5` while plugging in the keyboard.
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
1. Download [HIDBootFlash](http://vusb.wikidot.com/project:hidbootflash).
|
||||||
|
2. Place your keyboard into reset.
|
||||||
|
3. Press the `Find Device` button and ensure that your keyboard is found.
|
||||||
|
4. Press the `Open .hex File` button and locate the `.hex` file you created.
|
||||||
|
5. Press the `Flash Device` button and wait for the process to complete.
|
||||||
|
|
||||||
|
macOS:
|
||||||
|
1. Install homebrew by typing the following:
|
||||||
|
```
|
||||||
|
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||||
|
```
|
||||||
|
2. Install `crosspack-avr`.
|
||||||
|
```
|
||||||
|
brew cask install crosspack-avr
|
||||||
|
```
|
||||||
|
3. Install the following packages:
|
||||||
|
```
|
||||||
|
brew install python3
|
||||||
|
pip3 install pyusb
|
||||||
|
brew install --HEAD https://raw.githubusercontent.com/robertgzr/homebrew-tap/master/bootloadhid.rb
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Place your keyboard into reset.
|
||||||
|
5. Flash the board by typing `bootloadHID -r` followed by the path to your `.hex` file.
|
||||||
|
|
||||||
|
|
||||||
|
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Copyright 2017 Luiz Ribeiro <[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/>.
|
||||||
|
|
||||||
|
# MCU name
|
||||||
|
MCU = atmega32a
|
||||||
|
|
||||||
|
# Bootloader selection
|
||||||
|
# Teensy halfkay
|
||||||
|
# Pro Micro caterina
|
||||||
|
# Atmel DFU atmel-dfu
|
||||||
|
# LUFA DFU lufa-dfu
|
||||||
|
# QMK DFU qmk-dfu
|
||||||
|
# ATmega32A bootloadHID
|
||||||
|
# ATmega328P USBasp
|
||||||
|
BOOTLOADER = bootloadHID
|
||||||
|
|
||||||
|
# build options
|
||||||
|
BOOTMAGIC_ENABLE = no
|
||||||
|
MOUSEKEY_ENABLE = yes
|
||||||
|
EXTRAKEY_ENABLE = yes
|
||||||
|
CONSOLE_ENABLE = yes
|
||||||
|
COMMAND_ENABLE = yes
|
||||||
|
BACKLIGHT_ENABLE = yes
|
||||||
|
RGBLIGHT_ENABLE = yes
|
||||||
|
RGBLIGHT_CUSTOM_DRIVER = yes
|
||||||
|
|
||||||
|
OPT_DEFS = -DDEBUG_LEVEL=0
|
||||||
|
|
||||||
|
SRC = i2c_master.c
|
||||||
|
|
||||||
|
LAYOUTS = tkl_ansi
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright 2019 mechmerlin
|
||||||
|
*
|
||||||
|
* 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 "rgblight.h"
|
||||||
|
#include "i2c_master.h"
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
#ifdef RGBLIGHT_ENABLE
|
||||||
|
extern rgblight_config_t rgblight_config;
|
||||||
|
|
||||||
|
void rgblight_set(void) {
|
||||||
|
if (!rgblight_config.enable) {
|
||||||
|
for (uint8_t i = 0; i < RGBLED_NUM; i++) {
|
||||||
|
led[i].r = 0;
|
||||||
|
led[i].g = 0;
|
||||||
|
led[i].b = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_init();
|
||||||
|
i2c_transmit(0xb0, (uint8_t*)led, 3 * RGBLED_NUM, 100);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void matrix_init_kb(void) {
|
||||||
|
#ifdef RGBLIGHT_ENABLE
|
||||||
|
if (rgblight_config.enable) {
|
||||||
|
i2c_init();
|
||||||
|
i2c_transmit(0xb0, (uint8_t*)led, 3 * RGBLED_NUM, 100);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// call user level keymaps, if any
|
||||||
|
matrix_init_user();
|
||||||
|
}
|
||||||
|
|
||||||
|
void matrix_scan_kb(void) {
|
||||||
|
#ifdef RGBLIGHT_ENABLE
|
||||||
|
rgblight_task();
|
||||||
|
#endif
|
||||||
|
matrix_scan_user();
|
||||||
|
/* Nothing else for now. */
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((weak))
|
||||||
|
void matrix_scan_user(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_init_ports(void) {
|
||||||
|
// initialize pins D0, D1, D4 and D6 as output
|
||||||
|
setPinOutput(D0);
|
||||||
|
setPinOutput(D1);
|
||||||
|
setPinOutput(D4);
|
||||||
|
setPinOutput(D6);
|
||||||
|
|
||||||
|
// turn backlight LEDs on
|
||||||
|
writePinHigh(D0);
|
||||||
|
writePinHigh(D1);
|
||||||
|
writePinHigh(D4);
|
||||||
|
writePinHigh(D6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_set(uint8_t level) {
|
||||||
|
if (level == 0) {
|
||||||
|
// turn backlight LEDs off
|
||||||
|
writePinLow(D0);
|
||||||
|
writePinLow(D1);
|
||||||
|
writePinLow(D4);
|
||||||
|
writePinLow(D6);
|
||||||
|
} else {
|
||||||
|
// turn backlight LEDs on
|
||||||
|
writePinHigh(D0);
|
||||||
|
writePinHigh(D1);
|
||||||
|
writePinHigh(D4);
|
||||||
|
writePinHigh(D6);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/* Copyright 2019 mechmerlin
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
#define ___ KC_NO
|
||||||
|
|
||||||
|
// This a shortcut to help you visually see your layout.
|
||||||
|
// The first section contains all of the arguments
|
||||||
|
// The second converts the arguments into a two-dimensional array
|
||||||
|
|
||||||
|
#define LAYOUT_tkl_ansi( \
|
||||||
|
k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, k6c, \
|
||||||
|
k10, k1e, k11, k12, k13, k14, k1d, k15, k16, k17, k18, k19, k1a, k1b, k1c, k6b, k6a, \
|
||||||
|
k20, k2e, k21, k22, k23, k24, k2d, k25, k26, k27, k28, k29, k2a, k2b, k2c, k69, k68, \
|
||||||
|
k30, k3e, k31, k32, k33, k34, k3d, k35, k36, k37, k38, k39, k3a, \
|
||||||
|
k40, k4e, k41, k42, k43, k44, k4d, k45, k46, k47, k48, k4b, k4c, \
|
||||||
|
k50, k5e, k51, k54, k56, k57, k58, k5b, k5a, k5c, k67 \
|
||||||
|
){ \
|
||||||
|
{ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e }, \
|
||||||
|
{ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, k1e }, \
|
||||||
|
{ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2d, k2e }, \
|
||||||
|
{ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, ___, ___, k3d, k3e }, \
|
||||||
|
{ k40, k41, k42, k43, k44, k45, k46, k47, k48, ___, ___, k4b, k4c, k4d, k4e }, \
|
||||||
|
{ k50, k51, ___, ___, k54, ___, k56, k57, k58, ___, k5a, k5b, k5c, ___, k5e }, \
|
||||||
|
{ ___, ___, ___, ___, ___, ___, ___, k67, k68, k69, k6a, k6b, k6c, ___, ___ }, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LAYOUT_tkl_7u_ansi( \
|
||||||
|
k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, k6c, \
|
||||||
|
k10, k1e, k11, k12, k13, k14, k1d, k15, k16, k17, k18, k19, k1a, k1b, k1c, k6b, k6a, \
|
||||||
|
k20, k2e, k21, k22, k23, k24, k2d, k25, k26, k27, k28, k29, k2a, k2b, k2c, k69, k68, \
|
||||||
|
k30, k3e, k31, k32, k33, k34, k3d, k35, k36, k37, k38, k39, k3a, \
|
||||||
|
k40, k4e, k41, k42, k43, k44, k4d, k45, k46, k47, k48, k4b, k4c, \
|
||||||
|
k50, k5e, k51, k54, k57, k58, k5b, k5a, k5c, k67 \
|
||||||
|
){ \
|
||||||
|
{ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e }, \
|
||||||
|
{ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, k1e }, \
|
||||||
|
{ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2d, k2e }, \
|
||||||
|
{ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, ___, ___, k3d, k3e }, \
|
||||||
|
{ k40, k41, k42, k43, k44, k45, k46, k47, k48, ___, ___, k4b, k4c, k4d, k4e }, \
|
||||||
|
{ k50, k51, ___, ___, k54, ___, ___, k57, k58, ___, k5a, k5b, k5c, ___, k5e }, \
|
||||||
|
{ ___, ___, ___, ___, ___, ___, ___, k67, k68, k69, k6a, k6b, k6c, ___, ___ }, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LAYOUT_tkl_7u_ansi_blocker( \
|
||||||
|
k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, k6c, \
|
||||||
|
k10, k1e, k11, k12, k13, k14, k1d, k15, k16, k17, k18, k19, k1a, k1b, k1c, k6b, k6a, \
|
||||||
|
k20, k2e, k21, k22, k23, k24, k2d, k25, k26, k27, k28, k29, k2a, k2b, k2c, k69, k68, \
|
||||||
|
k30, k3e, k31, k32, k33, k34, k3d, k35, k36, k37, k38, k39, k3a, \
|
||||||
|
k40, k4e, k41, k42, k43, k44, k4d, k45, k46, k47, k48, k4b, k4c, \
|
||||||
|
k50, k51, k54, k57, k5b, k5a, k5c, k67 \
|
||||||
|
){ \
|
||||||
|
{ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e }, \
|
||||||
|
{ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, k1e }, \
|
||||||
|
{ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2d, k2e }, \
|
||||||
|
{ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, ___, ___, k3d, k3e }, \
|
||||||
|
{ k40, k41, k42, k43, k44, k45, k46, k47, k48, ___, ___, k4b, k4c, k4d, k4e }, \
|
||||||
|
{ k50, k51, ___, ___, k54, ___, ___, k57, ___, ___, k5a, k5b, k5c, ___, ___ }, \
|
||||||
|
{ ___, ___, ___, ___, ___, ___, ___, k67, k68, k69, k6a, k6b, k6c, ___, ___ }, \
|
||||||
|
}
|
||||||
@@ -0,0 +1,393 @@
|
|||||||
|
/* Name: usbconfig.h
|
||||||
|
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
|
||||||
|
* Author: Christian Starkjohann
|
||||||
|
* Creation Date: 2005-04-01
|
||||||
|
* Tabsize: 4
|
||||||
|
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
|
||||||
|
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
|
||||||
|
* This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
General Description:
|
||||||
|
This file is an example configuration (with inline documentation) for the USB
|
||||||
|
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
|
||||||
|
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
|
||||||
|
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
|
||||||
|
other hardware interrupt, as long as it is the highest level interrupt, see
|
||||||
|
section at the end of this file).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ---------------------------- Hardware Config ---------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_IOPORTNAME D
|
||||||
|
/* This is the port where the USB bus is connected. When you configure it to
|
||||||
|
* "B", the registers PORTB, PINB and DDRB will be used.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DMINUS_BIT 3
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
|
||||||
|
* This may be any bit in the port.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DPLUS_BIT 2
|
||||||
|
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
|
||||||
|
* This may be any bit in the port. Please note that D+ must also be connected
|
||||||
|
* to interrupt pin INT0! [You can also use other interrupts, see section
|
||||||
|
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
|
||||||
|
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
|
||||||
|
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
|
||||||
|
* markers every millisecond.]
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
|
||||||
|
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
|
||||||
|
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code
|
||||||
|
* require no crystal, they tolerate +/- 1% deviation from the nominal
|
||||||
|
* frequency. All other rates require a precision of 2000 ppm and thus a
|
||||||
|
* crystal!
|
||||||
|
* Since F_CPU should be defined to your actual clock rate anyway, you should
|
||||||
|
* not need to modify this setting.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CHECK_CRC 0
|
||||||
|
/* Define this to 1 if you want that the driver checks integrity of incoming
|
||||||
|
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
|
||||||
|
* currently only available for 18 MHz crystal clock. You must choose
|
||||||
|
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Optional Hardware Config ------------------------ */
|
||||||
|
|
||||||
|
/* #define USB_CFG_PULLUP_IOPORTNAME D */
|
||||||
|
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
|
||||||
|
* V+, you can connect and disconnect the device from firmware by calling
|
||||||
|
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
|
||||||
|
* This constant defines the port on which the pullup resistor is connected.
|
||||||
|
*/
|
||||||
|
/* #define USB_CFG_PULLUP_BIT 4 */
|
||||||
|
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
|
||||||
|
* above) where the 1.5k pullup resistor is connected. See description
|
||||||
|
* above for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* --------------------------- Functional Range ---------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT 1
|
||||||
|
/* Define this to 1 if you want to compile a version with two endpoints: The
|
||||||
|
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
|
||||||
|
* number).
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1
|
||||||
|
/* Define this to 1 if you want to compile a version with three endpoints: The
|
||||||
|
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
|
||||||
|
* configured below) and a catch-all default interrupt-in endpoint as above.
|
||||||
|
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_EP3_NUMBER 3
|
||||||
|
/* If the so-called endpoint 3 is used, it can now be configured to any other
|
||||||
|
* endpoint number (except 0) with this macro. Default if undefined is 3.
|
||||||
|
*/
|
||||||
|
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
|
||||||
|
/* The above macro defines the startup condition for data toggling on the
|
||||||
|
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
|
||||||
|
* Since the token is toggled BEFORE sending any data, the first packet is
|
||||||
|
* sent with the oposite value of this configuration!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_HALT 0
|
||||||
|
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
|
||||||
|
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
|
||||||
|
* it is required by the standard. We have made it a config option because it
|
||||||
|
* bloats the code considerably.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_SUPPRESS_INTR_CODE 0
|
||||||
|
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
|
||||||
|
* want to send any data over them. If this macro is defined to 1, functions
|
||||||
|
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
|
||||||
|
* you need the interrupt-in endpoints in order to comply to an interface
|
||||||
|
* (e.g. HID), but never want to send any data. This option saves a couple
|
||||||
|
* of bytes in flash memory and the transmit buffers in RAM.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTR_POLL_INTERVAL 1
|
||||||
|
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
|
||||||
|
* interval. The value is in milliseconds and must not be less than 10 ms for
|
||||||
|
* low speed devices.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IS_SELF_POWERED 0
|
||||||
|
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
|
||||||
|
* device is powered from the USB bus.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_MAX_BUS_POWER 500
|
||||||
|
/* Set this variable to the maximum USB bus power consumption of your device.
|
||||||
|
* The value is in milliamperes. [It will be divided by two since USB
|
||||||
|
* communicates power requirements in units of 2 mA.]
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITE 1
|
||||||
|
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
|
||||||
|
* transfers. Set it to 0 if you don't need it and want to save a couple of
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_READ 0
|
||||||
|
/* Set this to 1 if you need to send control replies which are generated
|
||||||
|
* "on the fly" when usbFunctionRead() is called. If you only want to send
|
||||||
|
* data from a static buffer, set it to 0 and return the data from
|
||||||
|
* usbFunctionSetup(). This saves a couple of bytes.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0
|
||||||
|
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
|
||||||
|
* You must implement the function usbFunctionWriteOut() which receives all
|
||||||
|
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
|
||||||
|
* can be found in 'usbRxToken'.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_FLOWCONTROL 0
|
||||||
|
/* Define this to 1 if you want flowcontrol over USB data. See the definition
|
||||||
|
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
|
||||||
|
* usbdrv.h.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DRIVER_FLASH_PAGE 0
|
||||||
|
/* If the device has more than 64 kBytes of flash, define this to the 64 k page
|
||||||
|
* where the driver's constants (descriptors) are located. Or in other words:
|
||||||
|
* Define this to 1 for boot loaders on the ATMega128.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_LONG_TRANSFERS 0
|
||||||
|
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
|
||||||
|
* in a single control-in or control-out transfer. Note that the capability
|
||||||
|
* for long transfers increases the driver size.
|
||||||
|
*/
|
||||||
|
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
|
||||||
|
/* This macro is a hook if you want to do unconventional things. If it is
|
||||||
|
* defined, it's inserted at the beginning of received message processing.
|
||||||
|
* If you eat the received message and don't want default processing to
|
||||||
|
* proceed, do a return after doing your things. One possible application
|
||||||
|
* (besides debugging) is to flash a status LED on each packet.
|
||||||
|
*/
|
||||||
|
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
|
||||||
|
/* This macro is a hook if you need to know when an USB RESET occurs. It has
|
||||||
|
* one parameter which distinguishes between the start of RESET state and its
|
||||||
|
* end.
|
||||||
|
*/
|
||||||
|
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
|
||||||
|
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
|
||||||
|
* received.
|
||||||
|
*/
|
||||||
|
#define USB_COUNT_SOF 1
|
||||||
|
/* define this macro to 1 if you need the global variable "usbSofCount" which
|
||||||
|
* counts SOF packets. This feature requires that the hardware interrupt is
|
||||||
|
* connected to D- instead of D+.
|
||||||
|
*/
|
||||||
|
/* #ifdef __ASSEMBLER__
|
||||||
|
* macro myAssemblerMacro
|
||||||
|
* in YL, TCNT0
|
||||||
|
* sts timer0Snapshot, YL
|
||||||
|
* endm
|
||||||
|
* #endif
|
||||||
|
* #define USB_SOF_HOOK myAssemblerMacro
|
||||||
|
* This macro (if defined) is executed in the assembler module when a
|
||||||
|
* Start Of Frame condition is detected. It is recommended to define it to
|
||||||
|
* the name of an assembler macro which is defined here as well so that more
|
||||||
|
* than one assembler instruction can be used. The macro may use the register
|
||||||
|
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
|
||||||
|
* immediately after an SOF pulse may be lost and must be retried by the host.
|
||||||
|
* What can you do with this hook? Since the SOF signal occurs exactly every
|
||||||
|
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
|
||||||
|
* designs running on the internal RC oscillator.
|
||||||
|
* Please note that Start Of Frame detection works only if D- is wired to the
|
||||||
|
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_CHECK_DATA_TOGGLING 0
|
||||||
|
/* define this macro to 1 if you want to filter out duplicate data packets
|
||||||
|
* sent by the host. Duplicates occur only as a consequence of communication
|
||||||
|
* errors, when the host does not receive an ACK. Please note that you need to
|
||||||
|
* implement the filtering yourself in usbFunctionWriteOut() and
|
||||||
|
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
|
||||||
|
* for each control- and out-endpoint to check for duplicate packets.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
|
||||||
|
/* define this macro to 1 if you want the function usbMeasureFrameLength()
|
||||||
|
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
|
||||||
|
*/
|
||||||
|
#define USB_USE_FAST_CRC 0
|
||||||
|
/* The assembler module has two implementations for the CRC algorithm. One is
|
||||||
|
* faster, the other is smaller. This CRC routine is only used for transmitted
|
||||||
|
* messages where timing is not critical. The faster routine needs 31 cycles
|
||||||
|
* per byte while the smaller one needs 61 to 69 cycles. The faster routine
|
||||||
|
* may be worth the 32 bytes bigger code size if you transmit lots of data and
|
||||||
|
* run the AVR close to its limit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------- Device Description --------------------------- */
|
||||||
|
|
||||||
|
#define USB_CFG_VENDOR_ID (VENDOR_ID & 0xFF), ((VENDOR_ID >> 8) & 0xFF)
|
||||||
|
/* USB vendor ID for the device, low byte first. If you have registered your
|
||||||
|
* own Vendor ID, define it here. Otherwise you may use one of obdev's free
|
||||||
|
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_ID (PRODUCT_ID & 0xFF), ((PRODUCT_ID >> 8) & 0xFF)
|
||||||
|
/* This is the ID of the product, low byte first. It is interpreted in the
|
||||||
|
* scope of the vendor ID. If you have registered your own VID with usb.org
|
||||||
|
* or if you have licensed a PID from somebody else, define it here. Otherwise
|
||||||
|
* you may use one of obdev's free shared VID/PID pairs. See the file
|
||||||
|
* USB-IDs-for-free.txt for details!
|
||||||
|
* *** IMPORTANT NOTE ***
|
||||||
|
* This template uses obdev's shared VID/PID pair for Vendor Class devices
|
||||||
|
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
|
||||||
|
* the implications!
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_VERSION 0x00, 0x02
|
||||||
|
/* Version number of the device: Minor number first, then major number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_VENDOR_NAME 'w', 'i', 'n', 'k', 'e', 'y', 'l', 'e', 's', 's', '.', 'k', 'r'
|
||||||
|
#define USB_CFG_VENDOR_NAME_LEN 13
|
||||||
|
/* These two values define the vendor name returned by the USB device. The name
|
||||||
|
* must be given as a list of characters under single quotes. The characters
|
||||||
|
* are interpreted as Unicode (UTF-16) entities.
|
||||||
|
* If you don't want a vendor name string, undefine these macros.
|
||||||
|
* ALWAYS define a vendor name containing your Internet domain name if you use
|
||||||
|
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
|
||||||
|
* details.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_NAME 'p', 's', '2', 'a', 'v', 'r', 'G', 'B'
|
||||||
|
#define USB_CFG_DEVICE_NAME_LEN 8
|
||||||
|
/* Same as above for the device name. If you don't want a device name, undefine
|
||||||
|
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
|
||||||
|
* you use a shared VID/PID.
|
||||||
|
*/
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
|
||||||
|
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
|
||||||
|
/* Same as above for the serial number. If you don't want a serial number,
|
||||||
|
* undefine the macros.
|
||||||
|
* It may be useful to provide the serial number through other means than at
|
||||||
|
* compile time. See the section about descriptor properties below for how
|
||||||
|
* to fine tune control over USB descriptors such as the string descriptor
|
||||||
|
* for the serial number.
|
||||||
|
*/
|
||||||
|
#define USB_CFG_DEVICE_CLASS 0
|
||||||
|
#define USB_CFG_DEVICE_SUBCLASS 0
|
||||||
|
/* See USB specification if you want to conform to an existing device class.
|
||||||
|
* Class 0xff is "vendor specific".
|
||||||
|
*/
|
||||||
|
#define USB_CFG_INTERFACE_CLASS 3 /* HID */
|
||||||
|
#define USB_CFG_INTERFACE_SUBCLASS 1 /* Boot */
|
||||||
|
#define USB_CFG_INTERFACE_PROTOCOL 1 /* Keyboard */
|
||||||
|
/* See USB specification if you want to conform to an existing device class or
|
||||||
|
* protocol. The following classes must be set at interface level:
|
||||||
|
* HID class is 3, no subclass and protocol required (but may be useful!)
|
||||||
|
* CDC class is 2, use subclass 2 and protocol 1 for ACM
|
||||||
|
*/
|
||||||
|
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0
|
||||||
|
/* Define this to the length of the HID report descriptor, if you implement
|
||||||
|
* an HID device. Otherwise don't define it or define it to 0.
|
||||||
|
* If you use this define, you must add a PROGMEM character array named
|
||||||
|
* "usbHidReportDescriptor" to your code which contains the report descriptor.
|
||||||
|
* Don't forget to keep the array and this define in sync!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #define USB_PUBLIC static */
|
||||||
|
/* Use the define above if you #include usbdrv.c instead of linking against it.
|
||||||
|
* This technique saves a couple of bytes in flash memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ------------------- Fine Control over USB Descriptors ------------------- */
|
||||||
|
/* If you don't want to use the driver's default USB descriptors, you can
|
||||||
|
* provide our own. These can be provided as (1) fixed length static data in
|
||||||
|
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
|
||||||
|
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
|
||||||
|
* information about this function.
|
||||||
|
* Descriptor handling is configured through the descriptor's properties. If
|
||||||
|
* no properties are defined or if they are 0, the default descriptor is used.
|
||||||
|
* Possible properties are:
|
||||||
|
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
|
||||||
|
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
|
||||||
|
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
|
||||||
|
* you want RAM pointers.
|
||||||
|
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
|
||||||
|
* in static memory is in RAM, not in flash memory.
|
||||||
|
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
|
||||||
|
* the driver must know the descriptor's length. The descriptor itself is
|
||||||
|
* found at the address of a well known identifier (see below).
|
||||||
|
* List of static descriptor names (must be declared PROGMEM if in flash):
|
||||||
|
* char usbDescriptorDevice[];
|
||||||
|
* char usbDescriptorConfiguration[];
|
||||||
|
* char usbDescriptorHidReport[];
|
||||||
|
* char usbDescriptorString0[];
|
||||||
|
* int usbDescriptorStringVendor[];
|
||||||
|
* int usbDescriptorStringDevice[];
|
||||||
|
* int usbDescriptorStringSerialNumber[];
|
||||||
|
* Other descriptors can't be provided statically, they must be provided
|
||||||
|
* dynamically at runtime.
|
||||||
|
*
|
||||||
|
* Descriptor properties are or-ed or added together, e.g.:
|
||||||
|
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
|
||||||
|
*
|
||||||
|
* The following descriptors are defined:
|
||||||
|
* USB_CFG_DESCR_PROPS_DEVICE
|
||||||
|
* USB_CFG_DESCR_PROPS_CONFIGURATION
|
||||||
|
* USB_CFG_DESCR_PROPS_STRINGS
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_0
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_VENDOR
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
|
||||||
|
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
|
||||||
|
* USB_CFG_DESCR_PROPS_HID
|
||||||
|
* USB_CFG_DESCR_PROPS_HID_REPORT
|
||||||
|
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
|
||||||
|
*
|
||||||
|
* Note about string descriptors: String descriptors are not just strings, they
|
||||||
|
* are Unicode strings prefixed with a 2 byte header. Example:
|
||||||
|
* int serialNumberDescriptor[] = {
|
||||||
|
* USB_STRING_DESCRIPTOR_HEADER(6),
|
||||||
|
* 'S', 'e', 'r', 'i', 'a', 'l'
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_CFG_DESCR_PROPS_DEVICE 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC
|
||||||
|
//#define USB_CFG_DESCR_PROPS_CONFIGURATION 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRINGS 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_0 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC
|
||||||
|
//#define USB_CFG_DESCR_PROPS_HID 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC
|
||||||
|
//#define USB_CFG_DESCR_PROPS_HID_REPORT 0
|
||||||
|
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
|
||||||
|
|
||||||
|
#define usbMsgPtr_t unsigned short
|
||||||
|
/* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We define it to
|
||||||
|
* a scalar type here because gcc generates slightly shorter code for scalar
|
||||||
|
* arithmetics than for pointer arithmetics. Remove this define for backward
|
||||||
|
* type compatibility or define it to an 8 bit type if you use data in RAM only
|
||||||
|
* and all RAM is below 256 bytes (tiny memory model in IAR CC).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ----------------------- Optional MCU Description ------------------------ */
|
||||||
|
|
||||||
|
/* The following configurations have working defaults in usbdrv.h. You
|
||||||
|
* usually don't need to set them explicitly. Only if you want to run
|
||||||
|
* the driver on a device which is not yet supported or with a compiler
|
||||||
|
* which is not fully supported (such as IAR C) or if you use a differnt
|
||||||
|
* interrupt than INT0, you may have to define some of these.
|
||||||
|
*/
|
||||||
|
/* #define USB_INTR_CFG MCUCR */
|
||||||
|
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
|
||||||
|
/* #define USB_INTR_CFG_CLR 0 */
|
||||||
|
/* #define USB_INTR_ENABLE GIMSK */
|
||||||
|
/* #define USB_INTR_ENABLE_BIT INT0 */
|
||||||
|
/* #define USB_INTR_PENDING GIFR */
|
||||||
|
/* #define USB_INTR_PENDING_BIT INTF0 */
|
||||||
|
/* #define USB_INTR_VECTOR INT0_vect */
|
||||||
|
|
||||||
|
/* Set INT1 for D- falling edge to count SOF */
|
||||||
|
/* #define USB_INTR_CFG EICRA */
|
||||||
|
#define USB_INTR_CFG_SET ((1 << ISC11) | (0 << ISC10))
|
||||||
|
/* #define USB_INTR_CFG_CLR 0 */
|
||||||
|
/* #define USB_INTR_ENABLE EIMSK */
|
||||||
|
#define USB_INTR_ENABLE_BIT INT1
|
||||||
|
/* #define USB_INTR_PENDING EIFR */
|
||||||
|
#define USB_INTR_PENDING_BIT INTF1
|
||||||
|
#define USB_INTR_VECTOR INT1_vect
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 HnahKB
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config_common.h"
|
||||||
|
|
||||||
|
/* USB Device descriptor parameter */
|
||||||
|
#define VENDOR_ID 0xFEED
|
||||||
|
#define PRODUCT_ID 0x0000
|
||||||
|
#define DEVICE_VER 0x0001
|
||||||
|
#define MANUFACTURER HnahKB
|
||||||
|
#define PRODUCT Stella
|
||||||
|
#define DESCRIPTION Custom PCB TKL keyboard for vgs community
|
||||||
|
|
||||||
|
/* key matrix size */
|
||||||
|
#define MATRIX_ROWS 10
|
||||||
|
#define MATRIX_COLS 10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 { D3, B2, B1, B0, E6, F0, D2, D5, F4, F1 }
|
||||||
|
#define MATRIX_COL_PINS { B4, D7, D6, D4, B5, C7, C6, F5, F6, F7 }
|
||||||
|
#define UNUSED_PINS
|
||||||
|
|
||||||
|
/* COL2ROW, ROW2COL*/
|
||||||
|
#define DIODE_DIRECTION COL2ROW
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Split Keyboard specific options, make sure you have 'SPLIT_KEYBOARD = yes' in your rules.mk, and define SOFT_SERIAL_PIN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define BACKLIGHT_PIN B6
|
||||||
|
#define BACKLIGHT_BREATHING
|
||||||
|
#define BACKLIGHT_LEVELS 3
|
||||||
|
|
||||||
|
|
||||||
|
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
|
||||||
|
#define DEBOUNCE 5
|
||||||
|
|
||||||
|
|
||||||
|
#define RGB_DI_PIN E2
|
||||||
|
#define RGBLED_NUM 14
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"keyboard_name": "Stella",
|
||||||
|
"url": "",
|
||||||
|
"maintainer": "VGS",
|
||||||
|
"width": 18.25,
|
||||||
|
"height": 6.5,
|
||||||
|
"layouts": {
|
||||||
|
"LAYOUT_all": {
|
||||||
|
"layout": [{"label":"Esc", "x":0, "y":0.25}, {"label":"F1", "x":2, "y":0.25}, {"label":"F2", "x":3, "y":0.25}, {"label":"F3", "x":4, "y":0.25}, {"label":"F4", "x":5, "y":0.25}, {"label":"F5", "x":6.5, "y":0.25}, {"label":"F6", "x":7.5, "y":0.25}, {"label":"F7", "x":8.5, "y":0.25}, {"label":"F8", "x":9.5, "y":0.25}, {"label":"F9", "x":11, "y":0.25}, {"label":"F10", "x":12, "y":0.25}, {"label":"F11", "x":13, "y":0.25}, {"label":"F12", "x":14, "y":0.25}, {"label":"PrtSc", "x":15.25, "y":0.25}, {"label":"Scroll Lock", "x":16.25, "y":0.25}, {"label":"Pause", "x":17.25, "y":0.25}, {"label":"~", "x":0, "y":1.5}, {"label":"!", "x":1, "y":1.5}, {"label":"@", "x":2, "y":1.5}, {"label":"#", "x":3, "y":1.5}, {"label":"$", "x":4, "y":1.5}, {"label":"%", "x":5, "y":1.5}, {"label":"^", "x":6, "y":1.5}, {"label":"&", "x":7, "y":1.5}, {"label":"*", "x":8, "y":1.5}, {"label":"(", "x":9, "y":1.5}, {"label":")", "x":10, "y":1.5}, {"label":"_", "x":11, "y":1.5}, {"label":"+", "x":12, "y":1.5}, {"label":"Backspace", "x":13, "y":1.5}, {"label":"Backspace2", "x":14, "y":1.5}, {"label":"Insert", "x":15.25, "y":1.5}, {"label":"Home", "x":16.25, "y":1.5}, {"label":"PgUp", "x":17.25, "y":1.5}, {"label":"Tab", "x":0, "y":2.5, "w":1.5}, {"label":"Q", "x":1.5, "y":2.5}, {"label":"W", "x":2.5, "y":2.5}, {"label":"E", "x":3.5, "y":2.5}, {"label":"R", "x":4.5, "y":2.5}, {"label":"T", "x":5.5, "y":2.5}, {"label":"Y", "x":6.5, "y":2.5}, {"label":"U", "x":7.5, "y":2.5}, {"label":"I", "x":8.5, "y":2.5}, {"label":"O", "x":9.5, "y":2.5}, {"label":"P", "x":10.5, "y":2.5}, {"label":"{", "x":11.5, "y":2.5}, {"label":"}", "x":12.5, "y":2.5}, {"label":"|", "x":13.5, "y":2.5, "w":1.5}, {"label":"Delete", "x":15.25, "y":2.5}, {"label":"End", "x":16.25, "y":2.5}, {"label":"PgDn", "x":17.25, "y":2.5}, {"label":"Caps Lock", "x":0, "y":3.5, "w":1.75}, {"label":"A", "x":1.75, "y":3.5}, {"label":"S", "x":2.75, "y":3.5}, {"label":"D", "x":3.75, "y":3.5}, {"label":"F", "x":4.75, "y":3.5}, {"label":"G", "x":5.75, "y":3.5}, {"label":"H", "x":6.75, "y":3.5}, {"label":"J", "x":7.75, "y":3.5}, {"label":"K", "x":8.75, "y":3.5}, {"label":"L", "x":9.75, "y":3.5}, {"label":":", "x":10.75, "y":3.5}, {"label":"\"", "x":11.75, "y":3.5}, {"label":"~", "x":12.75, "y":3.5}, {"label":"Enter", "x":13.75, "y":3.5, "w":1.25}, {"label":"Shift", "x":0, "y":4.5, "w":1.25}, {"label":"|", "x":1.25, "y":4.5}, {"label":"Z", "x":2.25, "y":4.5}, {"label":"X", "x":3.25, "y":4.5}, {"label":"C", "x":4.25, "y":4.5}, {"label":"V", "x":5.25, "y":4.5}, {"label":"B", "x":6.25, "y":4.5}, {"label":"N", "x":7.25, "y":4.5}, {"label":"M", "x":8.25, "y":4.5}, {"label":"<", "x":9.25, "y":4.5}, {"label":">", "x":10.25, "y":4.5}, {"label":"?", "x":11.25, "y":4.5}, {"label":"JP Ro", "x":12.25, "y":4.5}, {"label":"Shift", "x":13.25, "y":4.5, "w":1.75}, {"label":"\u2191", "x":16.25, "y":4.5}, {"label":"Ctrl", "x":0, "y":5.5, "w":1.25}, {"label":"Win", "x":1.25, "y":5.5, "w":1.25}, {"label":"Alt", "x":2.5, "y":5.5, "w":1.25}, {"label":"Space", "x":3.75, "y":5.5, "w":6.25}, {"label":"Alt", "x":10, "y":5.5, "w":1.25}, {"label":"Win", "x":11.25, "y":5.5, "w":1.25}, {"label":"Menu", "x":12.5, "y":5.5, "w":1.25}, {"label":"Ctrl", "x":13.75, "y":5.5, "w":1.25}, {"label":"\u2190", "x":15.25, "y":5.5}, {"label":"\u2193", "x":16.25, "y":5.5}, {"label":"\u2192", "x":17.25, "y":5.5}]
|
||||||
|
},
|
||||||
|
"LAYOUT_tkl_ansi": {
|
||||||
|
"layout": [{"label":"Esc", "x":0, "y":0.25}, {"label":"F1", "x":2, "y":0.25}, {"label":"F2", "x":3, "y":0.25}, {"label":"F3", "x":4, "y":0.25}, {"label":"F4", "x":5, "y":0.25}, {"label":"F5", "x":6.5, "y":0.25}, {"label":"F6", "x":7.5, "y":0.25}, {"label":"F7", "x":8.5, "y":0.25}, {"label":"F8", "x":9.5, "y":0.25}, {"label":"F9", "x":11, "y":0.25}, {"label":"F10", "x":12, "y":0.25}, {"label":"F11", "x":13, "y":0.25}, {"label":"F12", "x":14, "y":0.25}, {"label":"PrtSc", "x":15.25, "y":0.25}, {"label":"Scroll Lock", "x":16.25, "y":0.25}, {"label":"Pause", "x":17.25, "y":0.25}, {"label":"~", "x":0, "y":1.5}, {"label":"!", "x":1, "y":1.5}, {"label":"@", "x":2, "y":1.5}, {"label":"#", "x":3, "y":1.5}, {"label":"$", "x":4, "y":1.5}, {"label":"%", "x":5, "y":1.5}, {"label":"^", "x":6, "y":1.5}, {"label":"&", "x":7, "y":1.5}, {"label":"*", "x":8, "y":1.5}, {"label":"(", "x":9, "y":1.5}, {"label":")", "x":10, "y":1.5}, {"label":"_", "x":11, "y":1.5}, {"label":"+", "x":12, "y":1.5}, {"label":"Backspace", "x":13, "y":1.5, "w":2}, {"label":"Insert", "x":15.25, "y":1.5}, {"label":"Home", "x":16.25, "y":1.5}, {"label":"PgUp", "x":17.25, "y":1.5}, {"label":"Tab", "x":0, "y":2.5, "w":1.5}, {"label":"Q", "x":1.5, "y":2.5}, {"label":"W", "x":2.5, "y":2.5}, {"label":"E", "x":3.5, "y":2.5}, {"label":"R", "x":4.5, "y":2.5}, {"label":"T", "x":5.5, "y":2.5}, {"label":"Y", "x":6.5, "y":2.5}, {"label":"U", "x":7.5, "y":2.5}, {"label":"I", "x":8.5, "y":2.5}, {"label":"O", "x":9.5, "y":2.5}, {"label":"P", "x":10.5, "y":2.5}, {"label":"{", "x":11.5, "y":2.5}, {"label":"}", "x":12.5, "y":2.5}, {"label":"|", "x":13.5, "y":2.5, "w":1.5}, {"label":"Delete", "x":15.25, "y":2.5}, {"label":"End", "x":16.25, "y":2.5}, {"label":"PgDn", "x":17.25, "y":2.5}, {"label":"Caps Lock", "x":0, "y":3.5, "w":1.75}, {"label":"A", "x":1.75, "y":3.5}, {"label":"S", "x":2.75, "y":3.5}, {"label":"D", "x":3.75, "y":3.5}, {"label":"F", "x":4.75, "y":3.5}, {"label":"G", "x":5.75, "y":3.5}, {"label":"H", "x":6.75, "y":3.5}, {"label":"J", "x":7.75, "y":3.5}, {"label":"K", "x":8.75, "y":3.5}, {"label":"L", "x":9.75, "y":3.5}, {"label":":", "x":10.75, "y":3.5}, {"label":"\"", "x":11.75, "y":3.5}, {"label":"Enter", "x":12.75, "y":3.5, "w":2.25}, {"label":"Shift", "x":0, "y":4.5, "w":2.25}, {"label":"Z", "x":2.25, "y":4.5}, {"label":"X", "x":3.25, "y":4.5}, {"label":"C", "x":4.25, "y":4.5}, {"label":"V", "x":5.25, "y":4.5}, {"label":"B", "x":6.25, "y":4.5}, {"label":"N", "x":7.25, "y":4.5}, {"label":"M", "x":8.25, "y":4.5}, {"label":"<", "x":9.25, "y":4.5}, {"label":">", "x":10.25, "y":4.5}, {"label":"?", "x":11.25, "y":4.5}, {"label":"Shift", "x":12.25, "y":4.5, "w":2.75}, {"label":"\u2191", "x":16.25, "y":4.5}, {"label":"Ctrl", "x":0, "y":5.5, "w":1.25}, {"label":"Win", "x":1.25, "y":5.5, "w":1.25}, {"label":"Alt", "x":2.5, "y":5.5, "w":1.25}, {"x":3.75, "y":5.5, "w":6.25}, {"label":"Alt", "x":10, "y":5.5, "w":1.25}, {"label":"Win", "x":11.25, "y":5.5, "w":1.25}, {"label":"Menu", "x":12.5, "y":5.5, "w":1.25}, {"label":"Ctrl", "x":13.75, "y":5.5, "w":1.25}, {"label":"\u2190", "x":15.25, "y":5.5}, {"label":"\u2193", "x":16.25, "y":5.5}, {"label":"\u2192", "x":17.25, "y":5.5}]
|
||||||
|
},
|
||||||
|
"LAYOUT_tkl_iso": {
|
||||||
|
"layout": [{"label":"Esc", "x":0, "y":0.25}, {"label":"F1", "x":2, "y":0.25}, {"label":"F2", "x":3, "y":0.25}, {"label":"F3", "x":4, "y":0.25}, {"label":"F4", "x":5, "y":0.25}, {"label":"F5", "x":6.5, "y":0.25}, {"label":"F6", "x":7.5, "y":0.25}, {"label":"F7", "x":8.5, "y":0.25}, {"label":"F8", "x":9.5, "y":0.25}, {"label":"F9", "x":11, "y":0.25}, {"label":"F10", "x":12, "y":0.25}, {"label":"F11", "x":13, "y":0.25}, {"label":"F12", "x":14, "y":0.25}, {"label":"PrtSc", "x":15.25, "y":0.25}, {"label":"Scroll Lock", "x":16.25, "y":0.25}, {"label":"Pause", "x":17.25, "y":0.25}, {"label":"\u00ac", "x":0, "y":1.5}, {"label":"!", "x":1, "y":1.5}, {"label":"\"", "x":2, "y":1.5}, {"label":"\u00a3", "x":3, "y":1.5}, {"label":"$", "x":4, "y":1.5}, {"label":"%", "x":5, "y":1.5}, {"label":"^", "x":6, "y":1.5}, {"label":"&", "x":7, "y":1.5}, {"label":"*", "x":8, "y":1.5}, {"label":"(", "x":9, "y":1.5}, {"label":")", "x":10, "y":1.5}, {"label":"_", "x":11, "y":1.5}, {"label":"+", "x":12, "y":1.5}, {"label":"Backspace", "x":13, "y":1.5, "w":2}, {"label":"Insert", "x":15.25, "y":1.5}, {"label":"Home", "x":16.25, "y":1.5}, {"label":"PgUp", "x":17.25, "y":1.5}, {"label":"Tab", "x":0, "y":2.5, "w":1.5}, {"label":"Q", "x":1.5, "y":2.5}, {"label":"W", "x":2.5, "y":2.5}, {"label":"E", "x":3.5, "y":2.5}, {"label":"R", "x":4.5, "y":2.5}, {"label":"T", "x":5.5, "y":2.5}, {"label":"Y", "x":6.5, "y":2.5}, {"label":"U", "x":7.5, "y":2.5}, {"label":"I", "x":8.5, "y":2.5}, {"label":"O", "x":9.5, "y":2.5}, {"label":"P", "x":10.5, "y":2.5}, {"label":"{", "x":11.5, "y":2.5}, {"label":"}", "x":12.5, "y":2.5}, {"label":"Delete", "x":15.25, "y":2.5}, {"label":"End", "x":16.25, "y":2.5}, {"label":"PgDn", "x":17.25, "y":2.5}, {"label":"Caps Lock", "x":0, "y":3.5, "w":1.75}, {"label":"A", "x":1.75, "y":3.5}, {"label":"S", "x":2.75, "y":3.5}, {"label":"D", "x":3.75, "y":3.5}, {"label":"F", "x":4.75, "y":3.5}, {"label":"G", "x":5.75, "y":3.5}, {"label":"H", "x":6.75, "y":3.5}, {"label":"J", "x":7.75, "y":3.5}, {"label":"K", "x":8.75, "y":3.5}, {"label":"L", "x":9.75, "y":3.5}, {"label":":", "x":10.75, "y":3.5}, {"label":"@", "x":11.75, "y":3.5}, {"label":"~", "x":12.75, "y":3.5}, {"label":"Enter", "x":13.75, "y":2.5, "w":1.25, "h":2}, {"label":"Shift", "x":0, "y":4.5, "w":1.25}, {"label":"|", "x":1.25, "y":4.5}, {"label":"Z", "x":2.25, "y":4.5}, {"label":"X", "x":3.25, "y":4.5}, {"label":"C", "x":4.25, "y":4.5}, {"label":"V", "x":5.25, "y":4.5}, {"label":"B", "x":6.25, "y":4.5}, {"label":"N", "x":7.25, "y":4.5}, {"label":"M", "x":8.25, "y":4.5}, {"label":"<", "x":9.25, "y":4.5}, {"label":">", "x":10.25, "y":4.5}, {"label":"?", "x":11.25, "y":4.5}, {"label":"Shift", "x":12.25, "y":4.5, "w":2.75}, {"label":"\u2191", "x":16.25, "y":4.5}, {"label":"Ctrl", "x":0, "y":5.5, "w":1.25}, {"label":"Win", "x":1.25, "y":5.5, "w":1.25}, {"label":"Alt", "x":2.5, "y":5.5, "w":1.25}, {"x":3.75, "y":5.5, "w":6.25}, {"label":"AltGr", "x":10, "y":5.5, "w":1.25}, {"label":"Win", "x":11.25, "y":5.5, "w":1.25}, {"label":"Menu", "x":12.5, "y":5.5, "w":1.25}, {"label":"Ctrl", "x":13.75, "y":5.5, "w":1.25}, {"label":"\u2190", "x":15.25, "y":5.5}, {"label":"\u2193", "x":16.25, "y":5.5}, {"label":"\u2192", "x":17.25, "y":5.5}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/* Copyright 2019 HnahKB
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// place overrides here
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/* Copyright 2019 HnahKB
|
||||||
|
*
|
||||||
|
* 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 QMK_KEYBOARD_H
|
||||||
|
|
||||||
|
enum hnah_layers{
|
||||||
|
_QWERTY,
|
||||||
|
_LOWER
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LOWER MO(_LOWER)
|
||||||
|
|
||||||
|
|
||||||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||||
|
[_QWERTY] = LAYOUT_tkl_iso(
|
||||||
|
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_PSCR, KC_SLCK, KC_PAUS ,
|
||||||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_INS, KC_HOME, KC_PGUP,
|
||||||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_DEL, KC_END, KC_PGDN,
|
||||||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT,
|
||||||
|
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
|
||||||
|
KC_LCTL, KC_LGUI, KC_LALT, KC_SPACE, KC_RALT, KC_APP, LOWER, KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
|
||||||
|
),
|
||||||
|
[_LOWER] = LAYOUT_tkl_iso(
|
||||||
|
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_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_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_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_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_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
# The default keymap for stella
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# stella
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A cusom keyboard design for VGS community
|
||||||
|
|
||||||
|
Keyboard Maintainer: [HnahKB](https://github.com/vuhopkep)
|
||||||
|
Hardware Supported: Stella Keyboard
|
||||||
|
Hardware Availability: [VGS](https://www.facebook.com/groups/vietnamgamingsetup/permalink/2403066473102277)
|
||||||
|
|
||||||
|
Make example for this keyboard (after setting up your build environment):
|
||||||
|
|
||||||
|
make stella:default
|
||||||
|
|
||||||
|
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# MCU name
|
||||||
|
MCU = atmega32u4
|
||||||
|
|
||||||
|
|
||||||
|
# Bootloader selection
|
||||||
|
# Teensy halfkay
|
||||||
|
# Pro Micro caterina
|
||||||
|
# Atmel DFU atmel-dfu
|
||||||
|
# LUFA DFU lufa-dfu
|
||||||
|
# QMK DFU qmk-dfu
|
||||||
|
# atmega32a bootloadHID
|
||||||
|
BOOTLOADER = atmel-dfu
|
||||||
|
|
||||||
|
|
||||||
|
# Build Options
|
||||||
|
# change yes to no to disable
|
||||||
|
#
|
||||||
|
BOOTMAGIC_ENABLE = lite # Virtual DIP switch configuration(+1000)
|
||||||
|
MOUSEKEY_ENABLE = no # 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
|
||||||
|
# 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 = yes # Enable keyboard backlight functionality
|
||||||
|
RGBLIGHT_ENABLE = yes # Enable keyboard RGB underglow
|
||||||
|
MIDI_ENABLE = no # MIDI support (+2400 to 4200, depending on config)
|
||||||
|
UNICODE_ENABLE = no # Unicode
|
||||||
|
BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID
|
||||||
|
AUDIO_ENABLE = no # Audio output on port C6
|
||||||
|
FAUXCLICKY_ENABLE = no # Use buzzer to emulate clicky switches
|
||||||
|
HD44780_ENABLE = no # Enable support for HD44780 based LCDs (+400)
|
||||||
|
|
||||||
|
# Supported layouts
|
||||||
|
LAYOUTS = tkl_ansi tkl_iso
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/* Copyright 2019 HnahKB
|
||||||
|
*
|
||||||
|
* 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 "stella.h"
|
||||||
|
|
||||||
|
|
||||||
|
void matrix_init_kb(void) {
|
||||||
|
matrix_init_user();
|
||||||
|
led_init_ports();
|
||||||
|
};
|
||||||
|
|
||||||
|
void led_init_ports(void) {
|
||||||
|
setPinOutput(B3);
|
||||||
|
setPinOutput(B7);
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_set_kb(uint8_t usb_led) {
|
||||||
|
if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
|
||||||
|
// Turn Caps Lock LED on
|
||||||
|
writePinLow(B3);
|
||||||
|
} else {
|
||||||
|
// Turn Caps Lock LED off
|
||||||
|
writePinHigh(B3);
|
||||||
|
}
|
||||||
|
if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) {
|
||||||
|
// Turn Scroll Lock LED on
|
||||||
|
writePinLow(B7);
|
||||||
|
} else {
|
||||||
|
// Turn Scroll Lock LED off
|
||||||
|
writePinHigh(B7);
|
||||||
|
}
|
||||||
|
led_set_user(usb_led);
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/* Copyright 2019 HnahKB
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "quantum.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define LAYOUT_all( \
|
||||||
|
k00, k01, k02, k03, k04, k06, k07, k08,k09, k60, k61, k62, k63, k64, k65, k66, \
|
||||||
|
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k70, k71, k72, k73, k74, k75, k76, k67, \
|
||||||
|
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k80, k81, k82, k83, k78, k77, k68, \
|
||||||
|
k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k90, k91, k92, k84, \
|
||||||
|
k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k95, k94, k85, k93, k79, \
|
||||||
|
k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k69 \
|
||||||
|
) { \
|
||||||
|
{ k00, k01, k02, k03, k04, KC_NO, k06, k07, k08, k09 }, \
|
||||||
|
{ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19 }, \
|
||||||
|
{ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29 }, \
|
||||||
|
{ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39 }, \
|
||||||
|
{ k40, k41, k42, k43, k44, k45, k46, k47, k48, k49}, \
|
||||||
|
{ k50, k51, k52, k53, k54, k55, k56, k57, k58, k59 }, \
|
||||||
|
{ k60, k61, k62, k63, k64, k65, k66, k67, k68, k69 }, \
|
||||||
|
{ k70, k71, k72, k73, k74, k75, k76, k77, k78, k79 }, \
|
||||||
|
{ k80, k81, k82, k83, k84, k85, KC_NO, KC_NO, KC_NO, KC_NO }, \
|
||||||
|
{ k90, k91, k92, k93, k94, k95, KC_NO, KC_NO, KC_NO, KC_NO } \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LAYOUT_tkl_ansi( \
|
||||||
|
k00, k01, k02, k03, k04, k06, k07, k08,k09, k60, k61, k62, k63, k64, k65, k66, \
|
||||||
|
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k70, k71, k72, k73, k75, k76, k67, \
|
||||||
|
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k80, k81, k82, k83, k78, k77, k68, \
|
||||||
|
k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k90, k91, k84, \
|
||||||
|
k40, k42, k43, k44, k45, k46, k47, k48, k49, k95, k94, k93, k79, \
|
||||||
|
k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k69 \
|
||||||
|
) LAYOUT_all( \
|
||||||
|
k00, k01, k02, k03, k04, k06, k07, k08,k09, k60, k61, k62, k63, k64, k65, k66, \
|
||||||
|
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k70, k71, k72, k73, KC_NO, k75, k76, k67, \
|
||||||
|
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k80, k81, k82, k83, k78, k77, k68, \
|
||||||
|
k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k90, k91, KC_NO, k84, \
|
||||||
|
k40, KC_NO, k42, k43, k44, k45, k46, k47, k48, k49, k95, k94, KC_NO, k93, k79, \
|
||||||
|
k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k69 \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define LAYOUT_tkl_iso( \
|
||||||
|
k00, k01, k02, k03, k04, k06, k07, k08,k09, k60, k61, k62, k63, k64, k65, k66, \
|
||||||
|
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k70, k71, k72, k73, k75, k76, k67, \
|
||||||
|
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k80, k81, k82, k78, k77, k68, \
|
||||||
|
k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k90, k91, k92, k84, \
|
||||||
|
k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k95, k94, k93, k79, \
|
||||||
|
k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k69 \
|
||||||
|
) LAYOUT_all( \
|
||||||
|
k00, k01, k02, k03, k04, k06, k07, k08,k09, k60, k61, k62, k63, k64, k65, k66, \
|
||||||
|
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k70, k71, k72, k73, KC_NO, k75, k76, k67, \
|
||||||
|
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k80, k81, k82, KC_NO, k78, k77, k68, \
|
||||||
|
k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k90, k91, k92, k84, \
|
||||||
|
k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k95, k94, KC_NO, k93, k79, \
|
||||||
|
k50, k51, k52, k53, k54, k55, k56, k57, k58, k59, k69 \
|
||||||
|
)
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// TODO: Add common code here, for example cie_lightness implementation
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
#include "quantum.h"
|
||||||
|
#include "backlight.h"
|
||||||
|
#include <hal.h>
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
// TODO: remove short term bodge when refactoring BACKLIGHT_CUSTOM_DRIVER out
|
||||||
|
#ifdef BACKLIGHT_PIN
|
||||||
|
|
||||||
|
# if defined(STM32F0XX) || defined(STM32F0xx)
|
||||||
|
# error "Backlight support for STMF072 is not available. Please disable."
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if defined(STM32F1XX) || defined(STM32F1xx)
|
||||||
|
# define USE_GPIOV1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// GPIOV2 && GPIOV3
|
||||||
|
# ifndef BACKLIGHT_PAL_MODE
|
||||||
|
# define BACKLIGHT_PAL_MODE 2
|
||||||
|
# endif
|
||||||
|
|
||||||
|
// GENERIC
|
||||||
|
# ifndef BACKLIGHT_PWM_DRIVER
|
||||||
|
# define BACKLIGHT_PWM_DRIVER PWMD4
|
||||||
|
# endif
|
||||||
|
# ifndef BACKLIGHT_PWM_CHANNEL
|
||||||
|
# define BACKLIGHT_PWM_CHANNEL 3
|
||||||
|
# endif
|
||||||
|
|
||||||
|
static void breathing_callback(PWMDriver *pwmp);
|
||||||
|
|
||||||
|
static PWMConfig pwmCFG = {0xFFFF, /* PWM clock frequency */
|
||||||
|
256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
|
||||||
|
NULL, /* No Callback */
|
||||||
|
{ /* Default all channels to disabled - Channels will be configured durring init */
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL},
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL},
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL},
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL}},
|
||||||
|
0, /* HW dependent part.*/
|
||||||
|
0};
|
||||||
|
|
||||||
|
static PWMConfig pwmCFG_breathing = {0xFFFF, /** PWM clock frequency */
|
||||||
|
256, /* PWM period (in ticks) 1S (1/10kHz=0.1mS 0.1ms*10000 ticks=1S) */
|
||||||
|
breathing_callback, /* Breathing Callback */
|
||||||
|
{ /* Default all channels to disabled - Channels will be configured durring init */
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL},
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL},
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL},
|
||||||
|
{PWM_OUTPUT_DISABLED, NULL}},
|
||||||
|
0, /* HW dependent part.*/
|
||||||
|
0};
|
||||||
|
|
||||||
|
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||||
|
static uint16_t cie_lightness(uint16_t v) {
|
||||||
|
if (v <= 5243) // if below 8% of max
|
||||||
|
return v / 9; // same as dividing by 900%
|
||||||
|
else {
|
||||||
|
uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
||||||
|
// to get a useful result with integer division, we shift left in the expression above
|
||||||
|
// and revert what we've done again after squaring.
|
||||||
|
y = y * y * y >> 8;
|
||||||
|
if (y > 0xFFFFUL) // prevent overflow
|
||||||
|
return 0xFFFFU;
|
||||||
|
else
|
||||||
|
return (uint16_t)y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_init_ports(void) {
|
||||||
|
// printf("backlight_init_ports()\n");
|
||||||
|
|
||||||
|
# ifdef USE_GPIOV1
|
||||||
|
palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_STM32_ALTERNATE_PUSHPULL);
|
||||||
|
# else
|
||||||
|
palSetPadMode(PAL_PORT(BACKLIGHT_PIN), PAL_PAD(BACKLIGHT_PIN), PAL_MODE_ALTERNATE(BACKLIGHT_PAL_MODE));
|
||||||
|
# endif
|
||||||
|
|
||||||
|
pwmCFG.channels[BACKLIGHT_PWM_CHANNEL - 1].mode = PWM_OUTPUT_ACTIVE_HIGH;
|
||||||
|
pwmCFG_breathing.channels[BACKLIGHT_PWM_CHANNEL - 1].mode = PWM_OUTPUT_ACTIVE_HIGH;
|
||||||
|
pwmStart(&BACKLIGHT_PWM_DRIVER, &pwmCFG);
|
||||||
|
|
||||||
|
backlight_set(get_backlight_level());
|
||||||
|
if (is_backlight_breathing()) {
|
||||||
|
breathing_enable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_set(uint8_t level) {
|
||||||
|
// printf("backlight_set(%d)\n", level);
|
||||||
|
if (level == 0) {
|
||||||
|
// Turn backlight off
|
||||||
|
pwmDisableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1);
|
||||||
|
} else {
|
||||||
|
// Turn backlight on
|
||||||
|
if (!is_breathing()) {
|
||||||
|
uint32_t duty = (uint32_t)(cie_lightness(0xFFFF * (uint32_t)level / BACKLIGHT_LEVELS));
|
||||||
|
// printf("duty: (%d)\n", duty);
|
||||||
|
pwmEnableChannel(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t backlight_tick = 0;
|
||||||
|
|
||||||
|
void backlight_task(void) {}
|
||||||
|
|
||||||
|
# define BREATHING_NO_HALT 0
|
||||||
|
# define BREATHING_HALT_OFF 1
|
||||||
|
# define BREATHING_HALT_ON 2
|
||||||
|
# define BREATHING_STEPS 128
|
||||||
|
|
||||||
|
static uint8_t breathing_period = BREATHING_PERIOD;
|
||||||
|
static uint8_t breathing_halt = BREATHING_NO_HALT;
|
||||||
|
static uint16_t breathing_counter = 0;
|
||||||
|
|
||||||
|
bool is_breathing(void) { return BACKLIGHT_PWM_DRIVER.config == &pwmCFG_breathing; }
|
||||||
|
|
||||||
|
static inline void breathing_min(void) { breathing_counter = 0; }
|
||||||
|
|
||||||
|
static inline void breathing_max(void) { breathing_counter = breathing_period * 256 / 2; }
|
||||||
|
|
||||||
|
void breathing_interrupt_enable(void) {
|
||||||
|
pwmStop(&BACKLIGHT_PWM_DRIVER);
|
||||||
|
pwmStart(&BACKLIGHT_PWM_DRIVER, &pwmCFG_breathing);
|
||||||
|
chSysLockFromISR();
|
||||||
|
pwmEnablePeriodicNotification(&BACKLIGHT_PWM_DRIVER);
|
||||||
|
pwmEnableChannelI(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, 0xFFFF));
|
||||||
|
chSysUnlockFromISR();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_interrupt_disable(void) {
|
||||||
|
pwmStop(&BACKLIGHT_PWM_DRIVER);
|
||||||
|
pwmStart(&BACKLIGHT_PWM_DRIVER, &pwmCFG);
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_enable(void) {
|
||||||
|
breathing_counter = 0;
|
||||||
|
breathing_halt = BREATHING_NO_HALT;
|
||||||
|
breathing_interrupt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_pulse(void) {
|
||||||
|
if (get_backlight_level() == 0)
|
||||||
|
breathing_min();
|
||||||
|
else
|
||||||
|
breathing_max();
|
||||||
|
breathing_halt = BREATHING_HALT_ON;
|
||||||
|
breathing_interrupt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_disable(void) {
|
||||||
|
// printf("breathing_disable()\n");
|
||||||
|
breathing_interrupt_disable();
|
||||||
|
// Restore backlight level
|
||||||
|
backlight_set(get_backlight_level());
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_self_disable(void) {
|
||||||
|
if (get_backlight_level() == 0)
|
||||||
|
breathing_halt = BREATHING_HALT_OFF;
|
||||||
|
else
|
||||||
|
breathing_halt = BREATHING_HALT_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_toggle(void) {
|
||||||
|
if (is_breathing())
|
||||||
|
breathing_disable();
|
||||||
|
else
|
||||||
|
breathing_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_set(uint8_t value) {
|
||||||
|
if (!value) value = 1;
|
||||||
|
breathing_period = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); }
|
||||||
|
|
||||||
|
void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); }
|
||||||
|
|
||||||
|
void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); }
|
||||||
|
|
||||||
|
/* To generate breathing curve in python:
|
||||||
|
* from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
|
||||||
|
*/
|
||||||
|
static const uint8_t breathing_table[BREATHING_STEPS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// Use this before the cie_lightness function.
|
||||||
|
static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS * get_backlight_level(); }
|
||||||
|
|
||||||
|
static void breathing_callback(PWMDriver *pwmp) {
|
||||||
|
(void)pwmp;
|
||||||
|
uint16_t interval = (uint16_t)breathing_period * 256 / BREATHING_STEPS;
|
||||||
|
// resetting after one period to prevent ugly reset at overflow.
|
||||||
|
breathing_counter = (breathing_counter + 1) % (breathing_period * 256);
|
||||||
|
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
|
||||||
|
|
||||||
|
if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) {
|
||||||
|
breathing_interrupt_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t duty = cie_lightness(scale_backlight(breathing_table[index] * 256));
|
||||||
|
|
||||||
|
chSysLockFromISR();
|
||||||
|
pwmEnableChannelI(&BACKLIGHT_PWM_DRIVER, BACKLIGHT_PWM_CHANNEL - 1, PWM_FRACTION_TO_WIDTH(&BACKLIGHT_PWM_DRIVER, 0xFFFF, duty));
|
||||||
|
chSysUnlockFromISR();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
__attribute__((weak)) void backlight_init_ports(void) {}
|
||||||
|
|
||||||
|
__attribute__((weak)) void backlight_set(uint8_t level) {}
|
||||||
|
|
||||||
|
__attribute__((weak)) void backlight_task(void) {}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,509 @@
|
|||||||
|
#include "quantum.h"
|
||||||
|
#include "backlight.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS))
|
||||||
|
|
||||||
|
// This logic is a bit complex, we support 3 setups:
|
||||||
|
//
|
||||||
|
// 1. Hardware PWM when backlight is wired to a PWM pin.
|
||||||
|
// Depending on this pin, we use a different output compare unit.
|
||||||
|
// 2. Software PWM with hardware timers, but the used timer
|
||||||
|
// depends on the Audio setup (Audio wins over Backlight).
|
||||||
|
// 3. Full software PWM, driven by the matrix scan, if both timers are used by Audio.
|
||||||
|
|
||||||
|
# if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) && (BACKLIGHT_PIN == B5 || BACKLIGHT_PIN == B6 || BACKLIGHT_PIN == B7)
|
||||||
|
# define HARDWARE_PWM
|
||||||
|
# define ICRx ICR1
|
||||||
|
# define TCCRxA TCCR1A
|
||||||
|
# define TCCRxB TCCR1B
|
||||||
|
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
||||||
|
# define TIMSKx TIMSK1
|
||||||
|
# define TOIEx TOIE1
|
||||||
|
|
||||||
|
# if BACKLIGHT_PIN == B5
|
||||||
|
# define COMxx1 COM1A1
|
||||||
|
# define OCRxx OCR1A
|
||||||
|
# elif BACKLIGHT_PIN == B6
|
||||||
|
# define COMxx1 COM1B1
|
||||||
|
# define OCRxx OCR1B
|
||||||
|
# elif BACKLIGHT_PIN == B7
|
||||||
|
# define COMxx1 COM1C1
|
||||||
|
# define OCRxx OCR1C
|
||||||
|
# endif
|
||||||
|
# elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) && (BACKLIGHT_PIN == C4 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6)
|
||||||
|
# define HARDWARE_PWM
|
||||||
|
# define ICRx ICR3
|
||||||
|
# define TCCRxA TCCR3A
|
||||||
|
# define TCCRxB TCCR3B
|
||||||
|
# define TIMERx_OVF_vect TIMER3_OVF_vect
|
||||||
|
# define TIMSKx TIMSK3
|
||||||
|
# define TOIEx TOIE3
|
||||||
|
|
||||||
|
# if BACKLIGHT_PIN == C4
|
||||||
|
# if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
|
||||||
|
# error This MCU has no C4 pin!
|
||||||
|
# else
|
||||||
|
# define COMxx1 COM3C1
|
||||||
|
# define OCRxx OCR3C
|
||||||
|
# endif
|
||||||
|
# elif BACKLIGHT_PIN == C5
|
||||||
|
# if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
|
||||||
|
# error This MCU has no C5 pin!
|
||||||
|
# else
|
||||||
|
# define COMxx1 COM3B1
|
||||||
|
# define OCRxx OCR3B
|
||||||
|
# endif
|
||||||
|
# elif BACKLIGHT_PIN == C6
|
||||||
|
# define COMxx1 COM3A1
|
||||||
|
# define OCRxx OCR3A
|
||||||
|
# endif
|
||||||
|
# elif (defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)) && (BACKLIGHT_PIN == B7 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6)
|
||||||
|
# define HARDWARE_PWM
|
||||||
|
# define ICRx ICR1
|
||||||
|
# define TCCRxA TCCR1A
|
||||||
|
# define TCCRxB TCCR1B
|
||||||
|
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
||||||
|
# define TIMSKx TIMSK1
|
||||||
|
# define TOIEx TOIE1
|
||||||
|
|
||||||
|
# if BACKLIGHT_PIN == B7
|
||||||
|
# define COMxx1 COM1C1
|
||||||
|
# define OCRxx OCR1C
|
||||||
|
# elif BACKLIGHT_PIN == C5
|
||||||
|
# define COMxx1 COM1B1
|
||||||
|
# define OCRxx OCR1B
|
||||||
|
# elif BACKLIGHT_PIN == C6
|
||||||
|
# define COMxx1 COM1A1
|
||||||
|
# define OCRxx OCR1A
|
||||||
|
# endif
|
||||||
|
# elif defined(__AVR_ATmega32A__) && (BACKLIGHT_PIN == D4 || BACKLIGHT_PIN == D5)
|
||||||
|
# define HARDWARE_PWM
|
||||||
|
# define ICRx ICR1
|
||||||
|
# define TCCRxA TCCR1A
|
||||||
|
# define TCCRxB TCCR1B
|
||||||
|
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
||||||
|
# define TIMSKx TIMSK
|
||||||
|
# define TOIEx TOIE1
|
||||||
|
|
||||||
|
# if BACKLIGHT_PIN == D4
|
||||||
|
# define COMxx1 COM1B1
|
||||||
|
# define OCRxx OCR1B
|
||||||
|
# elif BACKLIGHT_PIN == D5
|
||||||
|
# define COMxx1 COM1A1
|
||||||
|
# define OCRxx OCR1A
|
||||||
|
# endif
|
||||||
|
# elif defined(__AVR_ATmega328P__) && (BACKLIGHT_PIN == B1 || BACKLIGHT_PIN == B2)
|
||||||
|
# define HARDWARE_PWM
|
||||||
|
# define ICRx ICR1
|
||||||
|
# define TCCRxA TCCR1A
|
||||||
|
# define TCCRxB TCCR1B
|
||||||
|
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
||||||
|
# define TIMSKx TIMSK1
|
||||||
|
# define TOIEx TOIE1
|
||||||
|
|
||||||
|
# if BACKLIGHT_PIN == B1
|
||||||
|
# define COMxx1 COM1A1
|
||||||
|
# define OCRxx OCR1A
|
||||||
|
# elif BACKLIGHT_PIN == B2
|
||||||
|
# define COMxx1 COM1B1
|
||||||
|
# define OCRxx OCR1B
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# if !defined(BACKLIGHT_CUSTOM_DRIVER)
|
||||||
|
# if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO)
|
||||||
|
// Timer 1 is not in use by Audio feature, Backlight can use it
|
||||||
|
# pragma message "Using hardware timer 1 with software PWM"
|
||||||
|
# define HARDWARE_PWM
|
||||||
|
# define BACKLIGHT_PWM_TIMER
|
||||||
|
# define ICRx ICR1
|
||||||
|
# define TCCRxA TCCR1A
|
||||||
|
# define TCCRxB TCCR1B
|
||||||
|
# define TIMERx_COMPA_vect TIMER1_COMPA_vect
|
||||||
|
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
||||||
|
# if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
|
||||||
|
# define TIMSKx TIMSK
|
||||||
|
# else
|
||||||
|
# define TIMSKx TIMSK1
|
||||||
|
# endif
|
||||||
|
# define TOIEx TOIE1
|
||||||
|
|
||||||
|
# define OCIExA OCIE1A
|
||||||
|
# define OCRxx OCR1A
|
||||||
|
# elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO)
|
||||||
|
# pragma message "Using hardware timer 3 with software PWM"
|
||||||
|
// Timer 3 is not in use by Audio feature, Backlight can use it
|
||||||
|
# define HARDWARE_PWM
|
||||||
|
# define BACKLIGHT_PWM_TIMER
|
||||||
|
# define ICRx ICR1
|
||||||
|
# define TCCRxA TCCR3A
|
||||||
|
# define TCCRxB TCCR3B
|
||||||
|
# define TIMERx_COMPA_vect TIMER3_COMPA_vect
|
||||||
|
# define TIMERx_OVF_vect TIMER3_OVF_vect
|
||||||
|
# define TIMSKx TIMSK3
|
||||||
|
# define TOIEx TOIE3
|
||||||
|
|
||||||
|
# define OCIExA OCIE3A
|
||||||
|
# define OCRxx OCR3A
|
||||||
|
# else
|
||||||
|
# pragma message "Audio in use - using pure software PWM"
|
||||||
|
# define NO_HARDWARE_PWM
|
||||||
|
# endif
|
||||||
|
# else
|
||||||
|
# pragma message "Custom driver defined - using pure software PWM"
|
||||||
|
# define NO_HARDWARE_PWM
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef BACKLIGHT_ON_STATE
|
||||||
|
# define BACKLIGHT_ON_STATE 0
|
||||||
|
# endif
|
||||||
|
|
||||||
|
void backlight_on(uint8_t backlight_pin) {
|
||||||
|
# if BACKLIGHT_ON_STATE == 0
|
||||||
|
writePinLow(backlight_pin);
|
||||||
|
# else
|
||||||
|
writePinHigh(backlight_pin);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_off(uint8_t backlight_pin) {
|
||||||
|
# if BACKLIGHT_ON_STATE == 0
|
||||||
|
writePinHigh(backlight_pin);
|
||||||
|
# else
|
||||||
|
writePinLow(backlight_pin);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
# if defined(NO_HARDWARE_PWM) || defined(BACKLIGHT_PWM_TIMER) // pwm through software
|
||||||
|
|
||||||
|
// we support multiple backlight pins
|
||||||
|
# ifndef BACKLIGHT_LED_COUNT
|
||||||
|
# define BACKLIGHT_LED_COUNT 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if BACKLIGHT_LED_COUNT == 1
|
||||||
|
# define BACKLIGHT_PIN_INIT \
|
||||||
|
{ BACKLIGHT_PIN }
|
||||||
|
# else
|
||||||
|
# define BACKLIGHT_PIN_INIT BACKLIGHT_PINS
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define FOR_EACH_LED(x) \
|
||||||
|
for (uint8_t i = 0; i < BACKLIGHT_LED_COUNT; i++) { \
|
||||||
|
uint8_t backlight_pin = backlight_pins[i]; \
|
||||||
|
{ x } \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint8_t backlight_pins[BACKLIGHT_LED_COUNT] = BACKLIGHT_PIN_INIT;
|
||||||
|
|
||||||
|
# else // full hardware PWM
|
||||||
|
|
||||||
|
// we support only one backlight pin
|
||||||
|
static const uint8_t backlight_pin = BACKLIGHT_PIN;
|
||||||
|
# define FOR_EACH_LED(x) x
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef NO_HARDWARE_PWM
|
||||||
|
__attribute__((weak)) void backlight_init_ports(void) {
|
||||||
|
// Setup backlight pin as output and output to on state.
|
||||||
|
FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);)
|
||||||
|
|
||||||
|
# ifdef BACKLIGHT_BREATHING
|
||||||
|
if (is_backlight_breathing()) {
|
||||||
|
breathing_enable();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((weak)) void backlight_set(uint8_t level) {}
|
||||||
|
|
||||||
|
uint8_t backlight_tick = 0;
|
||||||
|
|
||||||
|
# ifndef BACKLIGHT_CUSTOM_DRIVER
|
||||||
|
void backlight_task(void) {
|
||||||
|
if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
|
||||||
|
FOR_EACH_LED(backlight_on(backlight_pin);)
|
||||||
|
} else {
|
||||||
|
FOR_EACH_LED(backlight_off(backlight_pin);)
|
||||||
|
}
|
||||||
|
backlight_tick = (backlight_tick + 1) % 16;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef BACKLIGHT_BREATHING
|
||||||
|
# ifndef BACKLIGHT_CUSTOM_DRIVER
|
||||||
|
# error "Backlight breathing only available with hardware PWM. Please disable."
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# else // hardware pwm through timer
|
||||||
|
|
||||||
|
# ifdef BACKLIGHT_PWM_TIMER
|
||||||
|
|
||||||
|
// The idea of software PWM assisted by hardware timers is the following
|
||||||
|
// we use the hardware timer in fast PWM mode like for hardware PWM, but
|
||||||
|
// instead of letting the Output Match Comparator control the led pin
|
||||||
|
// (which is not possible since the backlight is not wired to PWM pins on the
|
||||||
|
// CPU), we do the LED on/off by oursleves.
|
||||||
|
// The timer is setup to count up to 0xFFFF, and we set the Output Compare
|
||||||
|
// register to the current 16bits backlight level (after CIE correction).
|
||||||
|
// This means the CPU will trigger a compare match interrupt when the counter
|
||||||
|
// reaches the backlight level, where we turn off the LEDs,
|
||||||
|
// but also an overflow interrupt when the counter rolls back to 0,
|
||||||
|
// in which we're going to turn on the LEDs.
|
||||||
|
// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz.
|
||||||
|
|
||||||
|
// Triggered when the counter reaches the OCRx value
|
||||||
|
ISR(TIMERx_COMPA_vect) { FOR_EACH_LED(backlight_off(backlight_pin);) }
|
||||||
|
|
||||||
|
// Triggered when the counter reaches the TOP value
|
||||||
|
// this one triggers at F_CPU/65536 =~ 244 Hz
|
||||||
|
ISR(TIMERx_OVF_vect) {
|
||||||
|
# ifdef BACKLIGHT_BREATHING
|
||||||
|
if (is_breathing()) {
|
||||||
|
breathing_task();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
// for very small values of OCRxx (or backlight level)
|
||||||
|
// we can't guarantee this whole code won't execute
|
||||||
|
// at the same time as the compare match interrupt
|
||||||
|
// which means that we might turn on the leds while
|
||||||
|
// trying to turn them off, leading to flickering
|
||||||
|
// artifacts (especially while breathing, because breathing_task
|
||||||
|
// takes many computation cycles).
|
||||||
|
// so better not turn them on while the counter TOP is very low.
|
||||||
|
if (OCRxx > 256) {
|
||||||
|
FOR_EACH_LED(backlight_on(backlight_pin);)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define TIMER_TOP 0xFFFFU
|
||||||
|
|
||||||
|
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
||||||
|
static uint16_t cie_lightness(uint16_t v) {
|
||||||
|
if (v <= 5243) // if below 8% of max
|
||||||
|
return v / 9; // same as dividing by 900%
|
||||||
|
else {
|
||||||
|
uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
||||||
|
// to get a useful result with integer division, we shift left in the expression above
|
||||||
|
// and revert what we've done again after squaring.
|
||||||
|
y = y * y * y >> 8;
|
||||||
|
if (y > 0xFFFFUL) // prevent overflow
|
||||||
|
return 0xFFFFU;
|
||||||
|
else
|
||||||
|
return (uint16_t)y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
|
||||||
|
static inline void set_pwm(uint16_t val) { OCRxx = val; }
|
||||||
|
|
||||||
|
# ifndef BACKLIGHT_CUSTOM_DRIVER
|
||||||
|
__attribute__((weak)) void backlight_set(uint8_t level) {
|
||||||
|
if (level > BACKLIGHT_LEVELS) level = BACKLIGHT_LEVELS;
|
||||||
|
|
||||||
|
if (level == 0) {
|
||||||
|
# ifdef BACKLIGHT_PWM_TIMER
|
||||||
|
if (OCRxx) {
|
||||||
|
TIMSKx &= ~(_BV(OCIExA));
|
||||||
|
TIMSKx &= ~(_BV(TOIEx));
|
||||||
|
FOR_EACH_LED(backlight_off(backlight_pin);)
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
// Turn off PWM control on backlight pin
|
||||||
|
TCCRxA &= ~(_BV(COMxx1));
|
||||||
|
# endif
|
||||||
|
} else {
|
||||||
|
# ifdef BACKLIGHT_PWM_TIMER
|
||||||
|
if (!OCRxx) {
|
||||||
|
TIMSKx |= _BV(OCIExA);
|
||||||
|
TIMSKx |= _BV(TOIEx);
|
||||||
|
}
|
||||||
|
# else
|
||||||
|
// Turn on PWM control of backlight pin
|
||||||
|
TCCRxA |= _BV(COMxx1);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
// Set the brightness
|
||||||
|
set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS));
|
||||||
|
}
|
||||||
|
|
||||||
|
void backlight_task(void) {}
|
||||||
|
# endif // BACKLIGHT_CUSTOM_DRIVER
|
||||||
|
|
||||||
|
# ifdef BACKLIGHT_BREATHING
|
||||||
|
|
||||||
|
# define BREATHING_NO_HALT 0
|
||||||
|
# define BREATHING_HALT_OFF 1
|
||||||
|
# define BREATHING_HALT_ON 2
|
||||||
|
# define BREATHING_STEPS 128
|
||||||
|
|
||||||
|
static uint8_t breathing_period = BREATHING_PERIOD;
|
||||||
|
static uint8_t breathing_halt = BREATHING_NO_HALT;
|
||||||
|
static uint16_t breathing_counter = 0;
|
||||||
|
|
||||||
|
# ifdef BACKLIGHT_PWM_TIMER
|
||||||
|
static bool breathing = false;
|
||||||
|
|
||||||
|
bool is_breathing(void) { return breathing; }
|
||||||
|
|
||||||
|
# define breathing_interrupt_enable() \
|
||||||
|
do { \
|
||||||
|
breathing = true; \
|
||||||
|
} while (0)
|
||||||
|
# define breathing_interrupt_disable() \
|
||||||
|
do { \
|
||||||
|
breathing = false; \
|
||||||
|
} while (0)
|
||||||
|
# else
|
||||||
|
|
||||||
|
bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); }
|
||||||
|
|
||||||
|
# define breathing_interrupt_enable() \
|
||||||
|
do { \
|
||||||
|
TIMSKx |= _BV(TOIEx); \
|
||||||
|
} while (0)
|
||||||
|
# define breathing_interrupt_disable() \
|
||||||
|
do { \
|
||||||
|
TIMSKx &= ~_BV(TOIEx); \
|
||||||
|
} while (0)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# define breathing_min() \
|
||||||
|
do { \
|
||||||
|
breathing_counter = 0; \
|
||||||
|
} while (0)
|
||||||
|
# define breathing_max() \
|
||||||
|
do { \
|
||||||
|
breathing_counter = breathing_period * 244 / 2; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void breathing_enable(void) {
|
||||||
|
breathing_counter = 0;
|
||||||
|
breathing_halt = BREATHING_NO_HALT;
|
||||||
|
breathing_interrupt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_pulse(void) {
|
||||||
|
if (get_backlight_level() == 0)
|
||||||
|
breathing_min();
|
||||||
|
else
|
||||||
|
breathing_max();
|
||||||
|
breathing_halt = BREATHING_HALT_ON;
|
||||||
|
breathing_interrupt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_disable(void) {
|
||||||
|
breathing_interrupt_disable();
|
||||||
|
// Restore backlight level
|
||||||
|
backlight_set(get_backlight_level());
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_self_disable(void) {
|
||||||
|
if (get_backlight_level() == 0)
|
||||||
|
breathing_halt = BREATHING_HALT_OFF;
|
||||||
|
else
|
||||||
|
breathing_halt = BREATHING_HALT_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_toggle(void) {
|
||||||
|
if (is_breathing())
|
||||||
|
breathing_disable();
|
||||||
|
else
|
||||||
|
breathing_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_set(uint8_t value) {
|
||||||
|
if (!value) value = 1;
|
||||||
|
breathing_period = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); }
|
||||||
|
|
||||||
|
void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); }
|
||||||
|
|
||||||
|
void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); }
|
||||||
|
|
||||||
|
/* To generate breathing curve in python:
|
||||||
|
* from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
|
||||||
|
*/
|
||||||
|
static const uint8_t breathing_table[BREATHING_STEPS] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// Use this before the cie_lightness function.
|
||||||
|
static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS * get_backlight_level(); }
|
||||||
|
|
||||||
|
# ifdef BACKLIGHT_PWM_TIMER
|
||||||
|
void breathing_task(void)
|
||||||
|
# else
|
||||||
|
/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
|
||||||
|
* about 244 times per second.
|
||||||
|
*/
|
||||||
|
ISR(TIMERx_OVF_vect)
|
||||||
|
# endif
|
||||||
|
{
|
||||||
|
uint16_t interval = (uint16_t)breathing_period * 244 / BREATHING_STEPS;
|
||||||
|
// resetting after one period to prevent ugly reset at overflow.
|
||||||
|
breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
|
||||||
|
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
|
||||||
|
|
||||||
|
if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) {
|
||||||
|
breathing_interrupt_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
set_pwm(cie_lightness(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * 0x0101U)));
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif // BACKLIGHT_BREATHING
|
||||||
|
|
||||||
|
__attribute__((weak)) void backlight_init_ports(void) {
|
||||||
|
// Setup backlight pin as output and output to on state.
|
||||||
|
FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
# ifdef BACKLIGHT_PWM_TIMER
|
||||||
|
// TimerX setup, Fast PWM mode count to TOP set in ICRx
|
||||||
|
TCCRxA = _BV(WGM11); // = 0b00000010;
|
||||||
|
// clock select clk/1
|
||||||
|
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||||
|
# else // hardware PWM
|
||||||
|
// 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
|
||||||
|
|
||||||
|
/*
|
||||||
|
14.8.3:
|
||||||
|
"In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]."
|
||||||
|
"In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)."
|
||||||
|
*/
|
||||||
|
TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
|
||||||
|
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
||||||
|
# endif
|
||||||
|
// Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
|
||||||
|
ICRx = TIMER_TOP;
|
||||||
|
|
||||||
|
backlight_init();
|
||||||
|
# ifdef BACKLIGHT_BREATHING
|
||||||
|
if (is_backlight_breathing()) {
|
||||||
|
breathing_enable();
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
# endif // hardware backlight
|
||||||
|
|
||||||
|
#else // no backlight
|
||||||
|
|
||||||
|
__attribute__((weak)) void backlight_init_ports(void) {}
|
||||||
|
|
||||||
|
__attribute__((weak)) void backlight_set(uint8_t level) {}
|
||||||
|
|
||||||
|
#endif // backlight
|
||||||
@@ -24,10 +24,6 @@
|
|||||||
# include "outputselect.h"
|
# include "outputselect.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef BREATHING_PERIOD
|
|
||||||
# define BREATHING_PERIOD 6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "backlight.h"
|
#include "backlight.h"
|
||||||
extern backlight_config_t backlight_config;
|
extern backlight_config_t backlight_config;
|
||||||
|
|
||||||
@@ -1019,511 +1015,6 @@ void matrix_scan_quantum() {
|
|||||||
|
|
||||||
matrix_scan_kb();
|
matrix_scan_kb();
|
||||||
}
|
}
|
||||||
#if defined(BACKLIGHT_ENABLE) && (defined(BACKLIGHT_PIN) || defined(BACKLIGHT_PINS))
|
|
||||||
|
|
||||||
// This logic is a bit complex, we support 3 setups:
|
|
||||||
//
|
|
||||||
// 1. Hardware PWM when backlight is wired to a PWM pin.
|
|
||||||
// Depending on this pin, we use a different output compare unit.
|
|
||||||
// 2. Software PWM with hardware timers, but the used timer
|
|
||||||
// depends on the Audio setup (Audio wins over Backlight).
|
|
||||||
// 3. Full software PWM, driven by the matrix scan, if both timers are used by Audio.
|
|
||||||
|
|
||||||
# if (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) && (BACKLIGHT_PIN == B5 || BACKLIGHT_PIN == B6 || BACKLIGHT_PIN == B7)
|
|
||||||
# define HARDWARE_PWM
|
|
||||||
# define ICRx ICR1
|
|
||||||
# define TCCRxA TCCR1A
|
|
||||||
# define TCCRxB TCCR1B
|
|
||||||
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
|
||||||
# define TIMSKx TIMSK1
|
|
||||||
# define TOIEx TOIE1
|
|
||||||
|
|
||||||
# if BACKLIGHT_PIN == B5
|
|
||||||
# define COMxx1 COM1A1
|
|
||||||
# define OCRxx OCR1A
|
|
||||||
# elif BACKLIGHT_PIN == B6
|
|
||||||
# define COMxx1 COM1B1
|
|
||||||
# define OCRxx OCR1B
|
|
||||||
# elif BACKLIGHT_PIN == B7
|
|
||||||
# define COMxx1 COM1C1
|
|
||||||
# define OCRxx OCR1C
|
|
||||||
# endif
|
|
||||||
# elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__)) && (BACKLIGHT_PIN == C4 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6)
|
|
||||||
# define HARDWARE_PWM
|
|
||||||
# define ICRx ICR3
|
|
||||||
# define TCCRxA TCCR3A
|
|
||||||
# define TCCRxB TCCR3B
|
|
||||||
# define TIMERx_OVF_vect TIMER3_OVF_vect
|
|
||||||
# define TIMSKx TIMSK3
|
|
||||||
# define TOIEx TOIE3
|
|
||||||
|
|
||||||
# if BACKLIGHT_PIN == C4
|
|
||||||
# if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
|
|
||||||
# error This MCU has no C4 pin!
|
|
||||||
# else
|
|
||||||
# define COMxx1 COM3C1
|
|
||||||
# define OCRxx OCR3C
|
|
||||||
# endif
|
|
||||||
# elif BACKLIGHT_PIN == C5
|
|
||||||
# if (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
|
|
||||||
# error This MCU has no C5 pin!
|
|
||||||
# else
|
|
||||||
# define COMxx1 COM3B1
|
|
||||||
# define OCRxx OCR3B
|
|
||||||
# endif
|
|
||||||
# elif BACKLIGHT_PIN == C6
|
|
||||||
# define COMxx1 COM3A1
|
|
||||||
# define OCRxx OCR3A
|
|
||||||
# endif
|
|
||||||
# elif (defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__)) && (BACKLIGHT_PIN == B7 || BACKLIGHT_PIN == C5 || BACKLIGHT_PIN == C6)
|
|
||||||
# define HARDWARE_PWM
|
|
||||||
# define ICRx ICR1
|
|
||||||
# define TCCRxA TCCR1A
|
|
||||||
# define TCCRxB TCCR1B
|
|
||||||
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
|
||||||
# define TIMSKx TIMSK1
|
|
||||||
# define TOIEx TOIE1
|
|
||||||
|
|
||||||
# if BACKLIGHT_PIN == B7
|
|
||||||
# define COMxx1 COM1C1
|
|
||||||
# define OCRxx OCR1C
|
|
||||||
# elif BACKLIGHT_PIN == C5
|
|
||||||
# define COMxx1 COM1B1
|
|
||||||
# define OCRxx OCR1B
|
|
||||||
# elif BACKLIGHT_PIN == C6
|
|
||||||
# define COMxx1 COM1A1
|
|
||||||
# define OCRxx OCR1A
|
|
||||||
# endif
|
|
||||||
# elif defined(__AVR_ATmega32A__) && (BACKLIGHT_PIN == D4 || BACKLIGHT_PIN == D5)
|
|
||||||
# define HARDWARE_PWM
|
|
||||||
# define ICRx ICR1
|
|
||||||
# define TCCRxA TCCR1A
|
|
||||||
# define TCCRxB TCCR1B
|
|
||||||
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
|
||||||
# define TIMSKx TIMSK
|
|
||||||
# define TOIEx TOIE1
|
|
||||||
|
|
||||||
# if BACKLIGHT_PIN == D4
|
|
||||||
# define COMxx1 COM1B1
|
|
||||||
# define OCRxx OCR1B
|
|
||||||
# elif BACKLIGHT_PIN == D5
|
|
||||||
# define COMxx1 COM1A1
|
|
||||||
# define OCRxx OCR1A
|
|
||||||
# endif
|
|
||||||
# elif defined(__AVR_ATmega328P__) && (BACKLIGHT_PIN == B1 || BACKLIGHT_PIN == B2)
|
|
||||||
# define HARDWARE_PWM
|
|
||||||
# define ICRx ICR1
|
|
||||||
# define TCCRxA TCCR1A
|
|
||||||
# define TCCRxB TCCR1B
|
|
||||||
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
|
||||||
# define TIMSKx TIMSK1
|
|
||||||
# define TOIEx TOIE1
|
|
||||||
|
|
||||||
# if BACKLIGHT_PIN == B1
|
|
||||||
# define COMxx1 COM1A1
|
|
||||||
# define OCRxx OCR1A
|
|
||||||
# elif BACKLIGHT_PIN == B2
|
|
||||||
# define COMxx1 COM1B1
|
|
||||||
# define OCRxx OCR1B
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# if !defined(BACKLIGHT_CUSTOM_DRIVER)
|
|
||||||
# if !defined(B5_AUDIO) && !defined(B6_AUDIO) && !defined(B7_AUDIO)
|
|
||||||
// Timer 1 is not in use by Audio feature, Backlight can use it
|
|
||||||
# pragma message "Using hardware timer 1 with software PWM"
|
|
||||||
# define HARDWARE_PWM
|
|
||||||
# define BACKLIGHT_PWM_TIMER
|
|
||||||
# define ICRx ICR1
|
|
||||||
# define TCCRxA TCCR1A
|
|
||||||
# define TCCRxB TCCR1B
|
|
||||||
# define TIMERx_COMPA_vect TIMER1_COMPA_vect
|
|
||||||
# define TIMERx_OVF_vect TIMER1_OVF_vect
|
|
||||||
# if defined(__AVR_ATmega32A__) // This MCU has only one TIMSK register
|
|
||||||
# define TIMSKx TIMSK
|
|
||||||
# else
|
|
||||||
# define TIMSKx TIMSK1
|
|
||||||
# endif
|
|
||||||
# define TOIEx TOIE1
|
|
||||||
|
|
||||||
# define OCIExA OCIE1A
|
|
||||||
# define OCRxx OCR1A
|
|
||||||
# elif !defined(C6_AUDIO) && !defined(C5_AUDIO) && !defined(C4_AUDIO)
|
|
||||||
# pragma message "Using hardware timer 3 with software PWM"
|
|
||||||
// Timer 3 is not in use by Audio feature, Backlight can use it
|
|
||||||
# define HARDWARE_PWM
|
|
||||||
# define BACKLIGHT_PWM_TIMER
|
|
||||||
# define ICRx ICR1
|
|
||||||
# define TCCRxA TCCR3A
|
|
||||||
# define TCCRxB TCCR3B
|
|
||||||
# define TIMERx_COMPA_vect TIMER3_COMPA_vect
|
|
||||||
# define TIMERx_OVF_vect TIMER3_OVF_vect
|
|
||||||
# define TIMSKx TIMSK3
|
|
||||||
# define TOIEx TOIE3
|
|
||||||
|
|
||||||
# define OCIExA OCIE3A
|
|
||||||
# define OCRxx OCR3A
|
|
||||||
# else
|
|
||||||
# pragma message "Audio in use - using pure software PWM"
|
|
||||||
# define NO_HARDWARE_PWM
|
|
||||||
# endif
|
|
||||||
# else
|
|
||||||
# pragma message "Custom driver defined - using pure software PWM"
|
|
||||||
# define NO_HARDWARE_PWM
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifndef BACKLIGHT_ON_STATE
|
|
||||||
# define BACKLIGHT_ON_STATE 0
|
|
||||||
# endif
|
|
||||||
|
|
||||||
void backlight_on(uint8_t backlight_pin) {
|
|
||||||
# if BACKLIGHT_ON_STATE == 0
|
|
||||||
writePinLow(backlight_pin);
|
|
||||||
# else
|
|
||||||
writePinHigh(backlight_pin);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void backlight_off(uint8_t backlight_pin) {
|
|
||||||
# if BACKLIGHT_ON_STATE == 0
|
|
||||||
writePinHigh(backlight_pin);
|
|
||||||
# else
|
|
||||||
writePinLow(backlight_pin);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
# if defined(NO_HARDWARE_PWM) || defined(BACKLIGHT_PWM_TIMER) // pwm through software
|
|
||||||
|
|
||||||
// we support multiple backlight pins
|
|
||||||
# ifndef BACKLIGHT_LED_COUNT
|
|
||||||
# define BACKLIGHT_LED_COUNT 1
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if BACKLIGHT_LED_COUNT == 1
|
|
||||||
# define BACKLIGHT_PIN_INIT \
|
|
||||||
{ BACKLIGHT_PIN }
|
|
||||||
# else
|
|
||||||
# define BACKLIGHT_PIN_INIT BACKLIGHT_PINS
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define FOR_EACH_LED(x) \
|
|
||||||
for (uint8_t i = 0; i < BACKLIGHT_LED_COUNT; i++) { \
|
|
||||||
uint8_t backlight_pin = backlight_pins[i]; \
|
|
||||||
{ x } \
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8_t backlight_pins[BACKLIGHT_LED_COUNT] = BACKLIGHT_PIN_INIT;
|
|
||||||
|
|
||||||
# else // full hardware PWM
|
|
||||||
|
|
||||||
// we support only one backlight pin
|
|
||||||
static const uint8_t backlight_pin = BACKLIGHT_PIN;
|
|
||||||
# define FOR_EACH_LED(x) x
|
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef NO_HARDWARE_PWM
|
|
||||||
__attribute__((weak)) void backlight_init_ports(void) {
|
|
||||||
// Setup backlight pin as output and output to on state.
|
|
||||||
FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);)
|
|
||||||
|
|
||||||
# ifdef BACKLIGHT_BREATHING
|
|
||||||
if (is_backlight_breathing()) {
|
|
||||||
breathing_enable();
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) void backlight_set(uint8_t level) {}
|
|
||||||
|
|
||||||
uint8_t backlight_tick = 0;
|
|
||||||
|
|
||||||
# ifndef BACKLIGHT_CUSTOM_DRIVER
|
|
||||||
void backlight_task(void) {
|
|
||||||
if ((0xFFFF >> ((BACKLIGHT_LEVELS - get_backlight_level()) * ((BACKLIGHT_LEVELS + 1) / 2))) & (1 << backlight_tick)) {
|
|
||||||
FOR_EACH_LED(backlight_on(backlight_pin);)
|
|
||||||
} else {
|
|
||||||
FOR_EACH_LED(backlight_off(backlight_pin);)
|
|
||||||
}
|
|
||||||
backlight_tick = (backlight_tick + 1) % 16;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef BACKLIGHT_BREATHING
|
|
||||||
# ifndef BACKLIGHT_CUSTOM_DRIVER
|
|
||||||
# error "Backlight breathing only available with hardware PWM. Please disable."
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# else // hardware pwm through timer
|
|
||||||
|
|
||||||
# ifdef BACKLIGHT_PWM_TIMER
|
|
||||||
|
|
||||||
// The idea of software PWM assisted by hardware timers is the following
|
|
||||||
// we use the hardware timer in fast PWM mode like for hardware PWM, but
|
|
||||||
// instead of letting the Output Match Comparator control the led pin
|
|
||||||
// (which is not possible since the backlight is not wired to PWM pins on the
|
|
||||||
// CPU), we do the LED on/off by oursleves.
|
|
||||||
// The timer is setup to count up to 0xFFFF, and we set the Output Compare
|
|
||||||
// register to the current 16bits backlight level (after CIE correction).
|
|
||||||
// This means the CPU will trigger a compare match interrupt when the counter
|
|
||||||
// reaches the backlight level, where we turn off the LEDs,
|
|
||||||
// but also an overflow interrupt when the counter rolls back to 0,
|
|
||||||
// in which we're going to turn on the LEDs.
|
|
||||||
// The LED will then be on for OCRxx/0xFFFF time, adjusted every 244Hz.
|
|
||||||
|
|
||||||
// Triggered when the counter reaches the OCRx value
|
|
||||||
ISR(TIMERx_COMPA_vect) { FOR_EACH_LED(backlight_off(backlight_pin);) }
|
|
||||||
|
|
||||||
// Triggered when the counter reaches the TOP value
|
|
||||||
// this one triggers at F_CPU/65536 =~ 244 Hz
|
|
||||||
ISR(TIMERx_OVF_vect) {
|
|
||||||
# ifdef BACKLIGHT_BREATHING
|
|
||||||
if (is_breathing()) {
|
|
||||||
breathing_task();
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
// for very small values of OCRxx (or backlight level)
|
|
||||||
// we can't guarantee this whole code won't execute
|
|
||||||
// at the same time as the compare match interrupt
|
|
||||||
// which means that we might turn on the leds while
|
|
||||||
// trying to turn them off, leading to flickering
|
|
||||||
// artifacts (especially while breathing, because breathing_task
|
|
||||||
// takes many computation cycles).
|
|
||||||
// so better not turn them on while the counter TOP is very low.
|
|
||||||
if (OCRxx > 256) {
|
|
||||||
FOR_EACH_LED(backlight_on(backlight_pin);)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define TIMER_TOP 0xFFFFU
|
|
||||||
|
|
||||||
// See http://jared.geek.nz/2013/feb/linear-led-pwm
|
|
||||||
static uint16_t cie_lightness(uint16_t v) {
|
|
||||||
if (v <= 5243) // if below 8% of max
|
|
||||||
return v / 9; // same as dividing by 900%
|
|
||||||
else {
|
|
||||||
uint32_t y = (((uint32_t)v + 10486) << 8) / (10486 + 0xFFFFUL); // add 16% of max and compare
|
|
||||||
// to get a useful result with integer division, we shift left in the expression above
|
|
||||||
// and revert what we've done again after squaring.
|
|
||||||
y = y * y * y >> 8;
|
|
||||||
if (y > 0xFFFFUL) // prevent overflow
|
|
||||||
return 0xFFFFU;
|
|
||||||
else
|
|
||||||
return (uint16_t)y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// range for val is [0..TIMER_TOP]. PWM pin is high while the timer count is below val.
|
|
||||||
static inline void set_pwm(uint16_t val) { OCRxx = val; }
|
|
||||||
|
|
||||||
# ifndef BACKLIGHT_CUSTOM_DRIVER
|
|
||||||
__attribute__((weak)) void backlight_set(uint8_t level) {
|
|
||||||
if (level > BACKLIGHT_LEVELS) level = BACKLIGHT_LEVELS;
|
|
||||||
|
|
||||||
if (level == 0) {
|
|
||||||
# ifdef BACKLIGHT_PWM_TIMER
|
|
||||||
if (OCRxx) {
|
|
||||||
TIMSKx &= ~(_BV(OCIExA));
|
|
||||||
TIMSKx &= ~(_BV(TOIEx));
|
|
||||||
FOR_EACH_LED(backlight_off(backlight_pin);)
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
// Turn off PWM control on backlight pin
|
|
||||||
TCCRxA &= ~(_BV(COMxx1));
|
|
||||||
# endif
|
|
||||||
} else {
|
|
||||||
# ifdef BACKLIGHT_PWM_TIMER
|
|
||||||
if (!OCRxx) {
|
|
||||||
TIMSKx |= _BV(OCIExA);
|
|
||||||
TIMSKx |= _BV(TOIEx);
|
|
||||||
}
|
|
||||||
# else
|
|
||||||
// Turn on PWM control of backlight pin
|
|
||||||
TCCRxA |= _BV(COMxx1);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
// Set the brightness
|
|
||||||
set_pwm(cie_lightness(TIMER_TOP * (uint32_t)level / BACKLIGHT_LEVELS));
|
|
||||||
}
|
|
||||||
|
|
||||||
void backlight_task(void) {}
|
|
||||||
# endif // BACKLIGHT_CUSTOM_DRIVER
|
|
||||||
|
|
||||||
# ifdef BACKLIGHT_BREATHING
|
|
||||||
|
|
||||||
# define BREATHING_NO_HALT 0
|
|
||||||
# define BREATHING_HALT_OFF 1
|
|
||||||
# define BREATHING_HALT_ON 2
|
|
||||||
# define BREATHING_STEPS 128
|
|
||||||
|
|
||||||
static uint8_t breathing_period = BREATHING_PERIOD;
|
|
||||||
static uint8_t breathing_halt = BREATHING_NO_HALT;
|
|
||||||
static uint16_t breathing_counter = 0;
|
|
||||||
|
|
||||||
# ifdef BACKLIGHT_PWM_TIMER
|
|
||||||
static bool breathing = false;
|
|
||||||
|
|
||||||
bool is_breathing(void) { return breathing; }
|
|
||||||
|
|
||||||
# define breathing_interrupt_enable() \
|
|
||||||
do { \
|
|
||||||
breathing = true; \
|
|
||||||
} while (0)
|
|
||||||
# define breathing_interrupt_disable() \
|
|
||||||
do { \
|
|
||||||
breathing = false; \
|
|
||||||
} while (0)
|
|
||||||
# else
|
|
||||||
|
|
||||||
bool is_breathing(void) { return !!(TIMSKx & _BV(TOIEx)); }
|
|
||||||
|
|
||||||
# define breathing_interrupt_enable() \
|
|
||||||
do { \
|
|
||||||
TIMSKx |= _BV(TOIEx); \
|
|
||||||
} while (0)
|
|
||||||
# define breathing_interrupt_disable() \
|
|
||||||
do { \
|
|
||||||
TIMSKx &= ~_BV(TOIEx); \
|
|
||||||
} while (0)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# define breathing_min() \
|
|
||||||
do { \
|
|
||||||
breathing_counter = 0; \
|
|
||||||
} while (0)
|
|
||||||
# define breathing_max() \
|
|
||||||
do { \
|
|
||||||
breathing_counter = breathing_period * 244 / 2; \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
void breathing_enable(void) {
|
|
||||||
breathing_counter = 0;
|
|
||||||
breathing_halt = BREATHING_NO_HALT;
|
|
||||||
breathing_interrupt_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void breathing_pulse(void) {
|
|
||||||
if (get_backlight_level() == 0)
|
|
||||||
breathing_min();
|
|
||||||
else
|
|
||||||
breathing_max();
|
|
||||||
breathing_halt = BREATHING_HALT_ON;
|
|
||||||
breathing_interrupt_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void breathing_disable(void) {
|
|
||||||
breathing_interrupt_disable();
|
|
||||||
// Restore backlight level
|
|
||||||
backlight_set(get_backlight_level());
|
|
||||||
}
|
|
||||||
|
|
||||||
void breathing_self_disable(void) {
|
|
||||||
if (get_backlight_level() == 0)
|
|
||||||
breathing_halt = BREATHING_HALT_OFF;
|
|
||||||
else
|
|
||||||
breathing_halt = BREATHING_HALT_ON;
|
|
||||||
}
|
|
||||||
|
|
||||||
void breathing_toggle(void) {
|
|
||||||
if (is_breathing())
|
|
||||||
breathing_disable();
|
|
||||||
else
|
|
||||||
breathing_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void breathing_period_set(uint8_t value) {
|
|
||||||
if (!value) value = 1;
|
|
||||||
breathing_period = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void breathing_period_default(void) { breathing_period_set(BREATHING_PERIOD); }
|
|
||||||
|
|
||||||
void breathing_period_inc(void) { breathing_period_set(breathing_period + 1); }
|
|
||||||
|
|
||||||
void breathing_period_dec(void) { breathing_period_set(breathing_period - 1); }
|
|
||||||
|
|
||||||
/* To generate breathing curve in python:
|
|
||||||
* from math import sin, pi; [int(sin(x/128.0*pi)**4*255) for x in range(128)]
|
|
||||||
*/
|
|
||||||
static const uint8_t breathing_table[BREATHING_STEPS] PROGMEM = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17, 20, 24, 28, 32, 36, 41, 46, 51, 57, 63, 70, 76, 83, 91, 98, 106, 113, 121, 129, 138, 146, 154, 162, 170, 178, 185, 193, 200, 207, 213, 220, 225, 231, 235, 240, 244, 247, 250, 252, 253, 254, 255, 254, 253, 252, 250, 247, 244, 240, 235, 231, 225, 220, 213, 207, 200, 193, 185, 178, 170, 162, 154, 146, 138, 129, 121, 113, 106, 98, 91, 83, 76, 70, 63, 57, 51, 46, 41, 36, 32, 28, 24, 20, 17, 15, 12, 10, 8, 6, 5, 4, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
|
|
||||||
// Use this before the cie_lightness function.
|
|
||||||
static inline uint16_t scale_backlight(uint16_t v) { return v / BACKLIGHT_LEVELS * get_backlight_level(); }
|
|
||||||
|
|
||||||
# ifdef BACKLIGHT_PWM_TIMER
|
|
||||||
void breathing_task(void)
|
|
||||||
# else
|
|
||||||
/* Assuming a 16MHz CPU clock and a timer that resets at 64k (ICR1), the following interrupt handler will run
|
|
||||||
* about 244 times per second.
|
|
||||||
*/
|
|
||||||
ISR(TIMERx_OVF_vect)
|
|
||||||
# endif
|
|
||||||
{
|
|
||||||
uint16_t interval = (uint16_t)breathing_period * 244 / BREATHING_STEPS;
|
|
||||||
// resetting after one period to prevent ugly reset at overflow.
|
|
||||||
breathing_counter = (breathing_counter + 1) % (breathing_period * 244);
|
|
||||||
uint8_t index = breathing_counter / interval % BREATHING_STEPS;
|
|
||||||
|
|
||||||
if (((breathing_halt == BREATHING_HALT_ON) && (index == BREATHING_STEPS / 2)) || ((breathing_halt == BREATHING_HALT_OFF) && (index == BREATHING_STEPS - 1))) {
|
|
||||||
breathing_interrupt_disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
set_pwm(cie_lightness(scale_backlight((uint16_t)pgm_read_byte(&breathing_table[index]) * 0x0101U)));
|
|
||||||
}
|
|
||||||
|
|
||||||
# endif // BACKLIGHT_BREATHING
|
|
||||||
|
|
||||||
__attribute__((weak)) void backlight_init_ports(void) {
|
|
||||||
// Setup backlight pin as output and output to on state.
|
|
||||||
FOR_EACH_LED(setPinOutput(backlight_pin); backlight_on(backlight_pin);)
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
# ifdef BACKLIGHT_PWM_TIMER
|
|
||||||
// TimerX setup, Fast PWM mode count to TOP set in ICRx
|
|
||||||
TCCRxA = _BV(WGM11); // = 0b00000010;
|
|
||||||
// clock select clk/1
|
|
||||||
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
|
||||||
# else // hardware PWM
|
|
||||||
// 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
|
|
||||||
|
|
||||||
/*
|
|
||||||
14.8.3:
|
|
||||||
"In fast PWM mode, the compare units allow generation of PWM waveforms on the OCnx pins. Setting the COMnx1:0 bits to two will produce a non-inverted PWM [..]."
|
|
||||||
"In fast PWM mode the counter is incremented until the counter value matches either one of the fixed values 0x00FF, 0x01FF, or 0x03FF (WGMn3:0 = 5, 6, or 7), the value in ICRn (WGMn3:0 = 14), or the value in OCRnA (WGMn3:0 = 15)."
|
|
||||||
*/
|
|
||||||
TCCRxA = _BV(COMxx1) | _BV(WGM11); // = 0b00001010;
|
|
||||||
TCCRxB = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // = 0b00011001;
|
|
||||||
# endif
|
|
||||||
// Use full 16-bit resolution. Counter counts to ICR1 before reset to 0.
|
|
||||||
ICRx = TIMER_TOP;
|
|
||||||
|
|
||||||
backlight_init();
|
|
||||||
# ifdef BACKLIGHT_BREATHING
|
|
||||||
if (is_backlight_breathing()) {
|
|
||||||
breathing_enable();
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
# endif // hardware backlight
|
|
||||||
|
|
||||||
#else // no backlight
|
|
||||||
|
|
||||||
__attribute__((weak)) void backlight_init_ports(void) {}
|
|
||||||
|
|
||||||
__attribute__((weak)) void backlight_set(uint8_t level) {}
|
|
||||||
|
|
||||||
#endif // backlight
|
|
||||||
|
|
||||||
#ifdef HD44780_ENABLED
|
#ifdef HD44780_ENABLED
|
||||||
# include "hd44780.h"
|
# include "hd44780.h"
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
# error "Maximum value of BACKLIGHT_LEVELS is 31"
|
# error "Maximum value of BACKLIGHT_LEVELS is 31"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BREATHING_PERIOD
|
||||||
|
# define BREATHING_PERIOD 6
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint8_t raw;
|
uint8_t raw;
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
#define STR(s) XSTR(s)
|
#define STR(s) XSTR(s)
|
||||||
#define XSTR(s) #s
|
#define XSTR(s) #s
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
uint8_t bitpop(uint8_t bits);
|
uint8_t bitpop(uint8_t bits);
|
||||||
uint8_t bitpop16(uint16_t bits);
|
uint8_t bitpop16(uint16_t bits);
|
||||||
uint8_t bitpop32(uint32_t bits);
|
uint8_t bitpop32(uint32_t bits);
|
||||||
@@ -39,4 +43,8 @@ uint8_t bitrev(uint8_t bits);
|
|||||||
uint16_t bitrev16(uint16_t bits);
|
uint16_t bitrev16(uint16_t bits);
|
||||||
uint32_t bitrev32(uint32_t bits);
|
uint32_t bitrev32(uint32_t bits);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in new issue
Block a user