summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
authorAlex Ong <the.onga@gmail.com>2019-01-04 19:39:14 +1100
committerAlex Ong <the.onga@gmail.com>2019-01-04 19:39:14 +1100
commit47c91fc7f75ae0a477e55b687aa0fc30da0a283c (patch)
tree65ad39452748ff2e6d4a83ce54ede6ca22c9ada9 /quantum
parentac9b88e8ccbbf38762871504cd827ff0d941c426 (diff)
parent563ce3f225d981ce460c12ca5130dfe47af41df0 (diff)
Merge branch 'master' of https://github.com/qmk/qmk_firmware
Diffstat (limited to 'quantum')
-rw-r--r--quantum/api.h4
-rw-r--r--quantum/audio/audio.c8
-rw-r--r--quantum/audio/audio.h3
-rw-r--r--quantum/audio/audio_arm.c135
-rw-r--r--quantum/audio/song_list.h30
-rw-r--r--quantum/config_common.h257
-rw-r--r--quantum/dynamic_keymap.c230
-rw-r--r--quantum/dynamic_keymap.h63
-rw-r--r--quantum/encoder.c70
-rw-r--r--quantum/encoder.h (renamed from quantum/process_keycode/process_chording.h)21
-rw-r--r--quantum/keymap_common.c2
-rw-r--r--quantum/keymap_extras/keymap_belgian.h108
-rw-r--r--quantum/keymap_extras/keymap_bepo.h153
-rw-r--r--quantum/keymap_extras/keymap_canadian_multilingual.h49
-rw-r--r--quantum/keymap_extras/keymap_fr_ch.h4
-rw-r--r--quantum/keymap_extras/keymap_french.h6
-rw-r--r--quantum/keymap_extras/keymap_german.h4
-rw-r--r--quantum/keymap_extras/keymap_german_ch.h4
-rw-r--r--quantum/keymap_extras/keymap_hungarian.h4
-rw-r--r--quantum/keymap_extras/keymap_italian.h7
-rw-r--r--quantum/keymap_extras/keymap_jp.h3
-rw-r--r--quantum/keymap_extras/keymap_neo2.h2
-rw-r--r--quantum/keymap_extras/keymap_nordic.h4
-rw-r--r--quantum/keymap_extras/keymap_plover_dvorak.h47
-rw-r--r--quantum/keymap_extras/keymap_slovenian.h107
-rw-r--r--quantum/keymap_extras/keymap_spanish.h4
-rw-r--r--quantum/keymap_extras/keymap_swedish.h4
-rw-r--r--quantum/keymap_extras/keymap_uk.h4
-rw-r--r--quantum/keymap_extras/sendstring_german.h81
-rw-r--r--quantum/matrix.c49
-rw-r--r--quantum/process_keycode/process_auto_shift.c2
-rw-r--r--quantum/process_keycode/process_chording.c76
-rw-r--r--quantum/process_keycode/process_clicky.c72
-rw-r--r--quantum/process_keycode/process_clicky.h10
-rw-r--r--quantum/process_keycode/process_leader.c49
-rw-r--r--quantum/process_keycode/process_leader.h2
-rw-r--r--quantum/process_keycode/process_tap_dance.c6
-rw-r--r--quantum/process_keycode/process_tap_dance.h1
-rw-r--r--quantum/process_keycode/process_ucis.c8
-rw-r--r--quantum/process_keycode/process_ucis.h6
-rw-r--r--quantum/process_keycode/process_unicode.c7
-rw-r--r--quantum/process_keycode/process_unicode.h5
-rw-r--r--quantum/process_keycode/process_unicode_common.c223
-rw-r--r--quantum/process_keycode/process_unicode_common.h68
-rw-r--r--quantum/process_keycode/process_unicodemap.c4
-rw-r--r--quantum/process_keycode/process_unicodemap.h4
-rw-r--r--quantum/quantum.c149
-rw-r--r--quantum/quantum.h129
-rw-r--r--quantum/quantum_keycodes.h129
-rw-r--r--quantum/rgb_matrix.c426
-rw-r--r--quantum/rgb_matrix.h128
-rw-r--r--quantum/rgb_matrix_drivers.c82
-rw-r--r--quantum/rgblight.c343
-rw-r--r--quantum/rgblight.h147
-rw-r--r--quantum/rgblight_reconfig.h36
-rw-r--r--quantum/split_common/i2c.c3
-rw-r--r--quantum/split_common/matrix.c142
-rw-r--r--quantum/split_common/matrix.h31
-rw-r--r--quantum/split_common/serial.c548
-rw-r--r--quantum/split_common/serial.h78
-rw-r--r--quantum/split_common/split_util.c51
-rw-r--r--quantum/template/avr/config.h31
-rw-r--r--quantum/template/avr/readme.md (renamed from quantum/template/base/readme.md)2
-rw-r--r--quantum/template/avr/rules.mk25
-rw-r--r--quantum/template/avr/template.h14
-rw-r--r--quantum/template/base/keymaps/default/keymap.c54
-rw-r--r--quantum/template/ps2avrgb/config.h4
-rw-r--r--quantum/template/ps2avrgb/readme.md44
-rw-r--r--quantum/template/ps2avrgb/rules.mk4
-rw-r--r--quantum/template/ps2avrgb/template.h12
70 files changed, 3330 insertions, 1292 deletions
diff --git a/quantum/api.h b/quantum/api.h
index efc0ddca12..fc016391bc 100644
--- a/quantum/api.h
+++ b/quantum/api.h
@@ -17,7 +17,9 @@
#ifndef _API_H_
#define _API_H_
+#ifdef __AVR__
#include "lufa.h"
+#endif
enum MESSAGE_TYPE {
MT_GET_DATA = 0x10, // Get data from keyboard
@@ -28,7 +30,7 @@ enum MESSAGE_TYPE {
MT_SEND_DATA_ACK = 0x31, // returned data/action confirmation (ACK)
MT_EXE_ACTION = 0x40, // executing actions on keyboard
MT_EXE_ACTION_ACK =0x41, // return confirmation/value (ACK)
- MT_TYPE_ERROR = 0x80 // type not recofgnised (ACK)
+ MT_TYPE_ERROR = 0x80 // type not recognised (ACK)
};
enum DATA_TYPE {
diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c
index c948a60d6c..6d6833ec11 100644
--- a/quantum/audio/audio.c
+++ b/quantum/audio/audio.c
@@ -223,7 +223,7 @@ void audio_init()
TCCR1B = (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
TIMER_1_PERIOD = (uint16_t)(((float)F_CPU) / (440 * CPU_PRESCALER));
TIMER_1_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (440 * CPU_PRESCALER)) * note_timbre);
- #endif
+ #endif
audio_initialized = true;
}
@@ -231,7 +231,7 @@ void audio_init()
if (audio_config.enable) {
PLAY_SONG(startup_song);
}
-
+
}
void stop_all_notes()
@@ -464,7 +464,7 @@ ISR(TIMER3_AUDIO_vect)
note_position++;
bool end_of_note = false;
if (TIMER_3_PERIOD > 0) {
- if (!note_resting)
+ if (!note_resting)
end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF - 1));
else
end_of_note = (note_position >= (note_length));
@@ -604,7 +604,7 @@ ISR(TIMER1_AUDIO_vect)
note_position++;
bool end_of_note = false;
if (TIMER_1_PERIOD > 0) {
- if (!note_resting)
+ if (!note_resting)
end_of_note = (note_position >= (note_length / TIMER_1_PERIOD * 0xFFFF - 1));
else
end_of_note = (note_position >= (note_length));
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
index da09b2bcd2..8136c5b258 100644
--- a/quantum/audio/audio.h
+++ b/quantum/audio/audio.h
@@ -40,7 +40,8 @@ typedef union {
uint8_t raw;
struct {
bool enable :1;
- uint8_t level :7;
+ bool clicky_enable :1;
+ uint8_t level :6;
};
} audio_config_t;
diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c
index d38184f323..989f7a64be 100644
--- a/quantum/audio/audio_arm.c
+++ b/quantum/audio/audio_arm.c
@@ -80,6 +80,9 @@ float startup_song[][2] = STARTUP_SONG;
static void gpt_cb8(GPTDriver *gptp);
#define DAC_BUFFER_SIZE 720
+#ifndef DAC_SAMPLE_MAX
+#define DAC_SAMPLE_MAX 65535U
+#endif
#define START_CHANNEL_1() gptStart(&GPTD6, &gpt6cfg1); \
gptStartContinuous(&GPTD6, 2U)
@@ -202,132 +205,16 @@ GPTConfig gpt8cfg1 = {
// squarewave
static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = {
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ // First half is max, second half is 0
+ [0 ... DAC_BUFFER_SIZE/2-1] = DAC_SAMPLE_MAX,
+ [DAC_BUFFER_SIZE/2 ... DAC_BUFFER_SIZE -1] = 0,
};
// squarewave
static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = {
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047,
- 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047
+ // opposite of dac_buffer above
+ [0 ... DAC_BUFFER_SIZE/2-1] = 0,
+ [DAC_BUFFER_SIZE/2 ... DAC_BUFFER_SIZE -1] = DAC_SAMPLE_MAX,
};
/*
@@ -363,7 +250,7 @@ static void error_cb1(DACDriver *dacp, dacerror_t err) {
}
static const DACConfig dac1cfg1 = {
- .init = 2047U,
+ .init = DAC_SAMPLE_MAX,
.datamode = DAC_DHRM_12BIT_RIGHT
};
@@ -375,7 +262,7 @@ static const DACConversionGroup dacgrpcfg1 = {
};
static const DACConfig dac1cfg2 = {
- .init = 2047U,
+ .init = DAC_SAMPLE_MAX,
.datamode = DAC_DHRM_12BIT_RIGHT
};
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h
index e63616a994..9946084977 100644
--- a/quantum/audio/song_list.h
+++ b/quantum/audio/song_list.h
@@ -472,4 +472,34 @@
H__NOTE(_AS4), W__NOTE(_GS4), W__NOTE(_GS4), W__NOTE(_FS4), W__NOTE(_GS4), \
H__NOTE(_AS4), WD_NOTE(_DS4)
+#define RICK_ROLL \
+ Q__NOTE(_F4), \
+ Q__NOTE(_G4), \
+ Q__NOTE(_BF4), \
+ Q__NOTE(_G4), \
+ HD_NOTE(_D5), \
+ HD_NOTE(_D5), \
+ W__NOTE(_C5), \
+ S__NOTE(_REST), \
+ Q__NOTE(_F4), \
+ Q__NOTE(_G4), \
+ Q__NOTE(_BF4), \
+ Q__NOTE(_G4), \
+ HD_NOTE(_C5), \
+ HD_NOTE(_C5), \
+ W__NOTE(_BF4), \
+ S__NOTE(_REST), \
+ Q__NOTE(_F4), \
+ Q__NOTE(_G4), \
+ Q__NOTE(_BF4), \
+ Q__NOTE(_G4), \
+ W__NOTE(_BF4), \
+ H__NOTE(_C5), \
+ H__NOTE(_A4), \
+ H__NOTE(_A4), \
+ H__NOTE(_G4), \
+ H__NOTE(_F4), \
+ H__NOTE(_F4), \
+ W__NOTE(_C5), \
+ W__NOTE(_BF4),
#endif
diff --git a/quantum/config_common.h b/quantum/config_common.h
index f6f51b367d..cbff372eaf 100644
--- a/quantum/config_common.h
+++ b/quantum/config_common.h
@@ -1,4 +1,4 @@
-/* Copyright 2015-2017 Jack Humbert
+/* Copyright 2015-2018 Jack Humbert
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -14,8 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CONFIG_DEFINITIONS_H
-#define CONFIG_DEFINITIONS_H
+#pragma once
/* diode directions */
#define COL2ROW 0
@@ -23,57 +22,205 @@
#define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */
#ifdef __AVR__
- /* I/O pins */
- #ifndef F0
- #define B0 0x30
- #define B1 0x31
- #define B2 0x32
- #define B3 0x33
- #define B4 0x34
- #define B5 0x35
- #define B6 0x36
- #define B7 0x37
- #define C0 0x60
- #define C1 0x61
- #define C2 0x62
- #define C3 0x63
- #define C4 0x64
- #define C5 0x65
- #define C6 0x66
- #define C7 0x67
- #define D0 0x90
- #define D1 0x91
- #define D2 0x92
- #define D3 0x93
- #define D4 0x94
- #define D5 0x95
- #define D6 0x96
- #define D7 0x97
- #define E0 0xC0
- #define E1 0xC1
- #define E2 0xC2
- #define E3 0xC3
- #define E4 0xC4
- #define E5 0xC5
- #define E6 0xC6
- #define E7 0xC7
- #define F0 0xF0
- #define F1 0xF1
- #define F2 0xF2
- #define F3 0xF3
- #define F4 0xF4
- #define F5 0xF5
- #define F6 0xF6
- #define F7 0xF7
- #define A0 0x00
- #define A1 0x01
- #define A2 0x02
- #define A3 0x03
- #define A4 0x04
- #define A5 0x05
- #define A6 0x06
- #define A7 0x07
- #endif
+ #ifndef __ASSEMBLER__
+ #include <avr/io.h>
+ #endif
+ #define PORT_SHIFTER 4 // this may be 4 for all AVR chips
+
+ // If you want to add more to this list, reference the PINx definitions in these header
+ // files: https://github.com/vancegroup-mirrors/avr-libc/tree/master/avr-libc/include/avr
+
+ #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
+ #define ADDRESS_BASE 0x00
+ #define PINB_ADDRESS 0x3
+ #define PINC_ADDRESS 0x6
+ #define PIND_ADDRESS 0x9
+ #define PINE_ADDRESS 0xC
+ #define PINF_ADDRESS 0xF
+ #elif defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__)
+ #define ADDRESS_BASE 0x00
+ #define PINB_ADDRESS 0x3
+ #define PINC_ADDRESS 0x6
+ #define PIND_ADDRESS 0x9
+ #elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__)
+ #define ADDRESS_BASE 0x00
+ #define PINA_ADDRESS 0x0
+ #define PINB_ADDRESS 0x3
+ #define PINC_ADDRESS 0x6
+ #define PIND_ADDRESS 0x9
+ #define PINE_ADDRESS 0xC
+ #define PINF_ADDRESS 0xF
+ #elif defined(__AVR_ATmega32A__)
+ #define ADDRESS_BASE 0x10
+ #define PIND_ADDRESS 0x0
+ #define PINC_ADDRESS 0x3
+ #define PINB_ADDRESS 0x6
+ #define PINA_ADDRESS 0x9
+ #else
+ #error "Pins are not defined"
+ #endif
+
+ /* I/O pins */
+ #define PINDEF(port, pin) ((PIN##port##_ADDRESS << PORT_SHIFTER) | pin)
+
+ #ifdef PORTA
+ #define A0 PINDEF(A, 0)
+ #define A1 PINDEF(A, 1)
+ #define A2 PINDEF(A, 2)
+ #define A3 PINDEF(A, 3)
+ #define A4 PINDEF(A, 4)
+ #define A5 PINDEF(A, 5)
+ #define A6 PINDEF(A, 6)
+ #define A7 PINDEF(A, 7)
+ #endif
+ #ifdef PORTB
+ #define B0 PINDEF(B, 0)
+ #define B1 PINDEF(B, 1)
+ #define B2 PINDEF(B, 2)
+ #define B3 PINDEF(B, 3)
+ #define B4 PINDEF(B, 4)
+ #define B5 PINDEF(B, 5)
+ #define B6 PINDEF(B, 6)
+ #define B7 PINDEF(B, 7)
+ #endif
+ #ifdef PORTC
+ #define C0 PINDEF(C, 0)
+ #define C1 PINDEF(C, 1)
+ #define C2 PINDEF(C, 2)
+ #define C3 PINDEF(C, 3)
+ #define C4 PINDEF(C, 4)
+ #define C5 PINDEF(C, 5)
+ #define C6 PINDEF(C, 6)
+ #define C7 PINDEF(C, 7)
+ #endif
+ #ifdef PORTD
+ #define D0 PINDEF(D, 0)
+ #define D1 PINDEF(D, 1)
+ #define D2 PINDEF(D, 2)
+ #define D3 PINDEF(D, 3)
+ #define D4 PINDEF(D, 4)
+ #define D5 PINDEF(D, 5)
+ #define D6 PINDEF(D, 6)
+ #define D7 PINDEF(D, 7)
+ #endif
+ #ifdef PORTE
+ #define E0 PINDEF(E, 0)
+ #define E1 PINDEF(E, 1)
+ #define E2 PINDEF(E, 2)
+ #define E3 PINDEF(E, 3)
+ #define E4 PINDEF(E, 4)
+ #define E5 PINDEF(E, 5)
+ #define E6 PINDEF(E, 6)
+ #define E7 PINDEF(E, 7)
+ #endif
+ #ifdef PORTF
+ #define F0 PINDEF(F, 0)
+ #define F1 PINDEF(F, 1)
+ #define F2 PINDEF(F, 2)
+ #define F3 PINDEF(F, 3)
+ #define F4 PINDEF(F, 4)
+ #define F5 PINDEF(F, 5)
+ #define F6 PINDEF(F, 6)
+ #define F7 PINDEF(F, 7)
+ #endif
+
+#elif defined(PROTOCOL_CHIBIOS)
+ #define A0 PAL_LINE(GPIOA, 0)
+ #define A1 PAL_LINE(GPIOA, 1)
+ #define A2 PAL_LINE(GPIOA, 2)
+ #define A3 PAL_LINE(GPIOA, 3)
+ #define A4 PAL_LINE(GPIOA, 4)
+ #define A5 PAL_LINE(GPIOA, 5)
+ #define A6 PAL_LINE(GPIOA, 6)
+ #define A7 PAL_LINE(GPIOA, 7)
+ #define A8 PAL_LINE(GPIOA, 8)
+ #define A9 PAL_LINE(GPIOA, 9)
+ #define A10 PAL_LINE(GPIOA, 10)
+ #define A11 PAL_LINE(GPIOA, 11)
+ #define A12 PAL_LINE(GPIOA, 12)
+ #define A13 PAL_LINE(GPIOA, 13)
+ #define A14 PAL_LINE(GPIOA, 14)
+ #define A15 PAL_LINE(GPIOA, 15)
+ #define B0 PAL_LINE(GPIOB, 0)
+ #define B1 PAL_LINE(GPIOB, 1)
+ #define B2 PAL_LINE(GPIOB, 2)
+ #define B3 PAL_LINE(GPIOB, 3)
+ #define B4 PAL_LINE(GPIOB, 4)
+ #define B5 PAL_LINE(GPIOB, 5)
+ #define B6 PAL_LINE(GPIOB, 6)
+ #define B7 PAL_LINE(GPIOB, 7)
+ #define B8 PAL_LINE(GPIOB, 8)
+ #define B9 PAL_LINE(GPIOB, 9)
+ #define B10 PAL_LINE(GPIOB, 10)
+ #define B11 PAL_LINE(GPIOB, 11)
+ #define B12 PAL_LINE(GPIOB, 12)
+ #define B13 PAL_LINE(GPIOB, 13)
+ #define B14 PAL_LINE(GPIOB, 14)
+ #define B15 PAL_LINE(GPIOB, 15)
+ #define C0 PAL_LINE(GPIOC, 0)
+ #define C1 PAL_LINE(GPIOC, 1)
+ #define C2 PAL_LINE(GPIOC, 2)
+ #define C3 PAL_LINE(GPIOC, 3)
+ #define C4 PAL_LINE(GPIOC, 4)
+ #define C5 PAL_LINE(GPIOC, 5)
+ #define C6 PAL_LINE(GPIOC, 6)
+ #define C7 PAL_LINE(GPIOC, 7)
+ #define C8 PAL_LINE(GPIOC, 8)
+ #define C9 PAL_LINE(GPIOC, 9)
+ #define C10 PAL_LINE(GPIOC, 10)
+ #define C11 PAL_LINE(GPIOC, 11)
+ #define C12 PAL_LINE(GPIOC, 12)
+ #define C13 PAL_LINE(GPIOC, 13)
+ #define C14 PAL_LINE(GPIOC, 14)
+ #define C15 PAL_LINE(GPIOC, 15)
+ #define D0 PAL_LINE(GPIOD, 0)
+ #define D1 PAL_LINE(GPIOD, 1)
+ #define D2 PAL_LINE(GPIOD, 2)
+ #define D3 PAL_LINE(GPIOD, 3)
+ #define D4 PAL_LINE(GPIOD, 4)
+ #define D5 PAL_LINE(GPIOD, 5)
+ #define D6 PAL_LINE(GPIOD, 6)
+ #define D7 PAL_LINE(GPIOD, 7)
+ #define D8 PAL_LINE(GPIOD, 8)
+ #define D9 PAL_LINE(GPIOD, 9)
+ #define D10 PAL_LINE(GPIOD, 10)
+ #define D11 PAL_LINE(GPIOD, 11)
+ #define D12 PAL_LINE(GPIOD, 12)
+ #define D13 PAL_LINE(GPIOD, 13)
+ #define D14 PAL_LINE(GPIOD, 14)
+ #define D15 PAL_LINE(GPIOD, 15)
+ #define E0 PAL_LINE(GPIOE, 0)
+ #define E1 PAL_LINE(GPIOE, 1)
+ #define E2 PAL_LINE(GPIOE, 2)
+ #define E3 PAL_LINE(GPIOE, 3)
+ #define E4 PAL_LINE(GPIOE, 4)
+ #define E5 PAL_LINE(GPIOE, 5)
+ #define E6 PAL_LINE(GPIOE, 6)
+ #define E7 PAL_LINE(GPIOE, 7)
+ #define E8 PAL_LINE(GPIOE, 8)
+ #define E9 PAL_LINE(GPIOE, 9)
+ #define E10 PAL_LINE(GPIOE, 10)
+ #define E11 PAL_LINE(GPIOE, 11)
+ #define E12 PAL_LINE(GPIOE, 12)
+ #define E13 PAL_LINE(GPIOE, 13)
+ #define E14 PAL_LINE(GPIOE, 14)
+ #define E15 PAL_LINE(GPIOE, 15)
+ #define F0 PAL_LINE(GPIOF, 0)
+ #define F1 PAL_LINE(GPIOF, 1)
+ #define F2 PAL_LINE(GPIOF, 2)
+ #define F3 PAL_LINE(GPIOF, 3)
+ #define F4 PAL_LINE(GPIOF, 4)
+ #define F5 PAL_LINE(GPIOF, 5)
+ #define F6 PAL_LINE(GPIOF, 6)
+ #define F7 PAL_LINE(GPIOF, 7)
+ #define F8 PAL_LINE(GPIOF, 8)
+ #define F9 PAL_LINE(GPIOF, 9)
+ #define F10 PAL_LINE(GPIOF, 10)
+ #define F11 PAL_LINE(GPIOF, 11)
+ #define F12 PAL_LINE(GPIOF, 12)
+ #define F13 PAL_LINE(GPIOF, 13)
+ #define F14 PAL_LINE(GPIOF, 14)
+ #define F15 PAL_LINE(GPIOF, 15)
#endif
/* USART configuration */
@@ -103,5 +250,3 @@
#define API_SYSEX_MAX_SIZE 32
#include "song_list.h"
-
-#endif
diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
new file mode 100644
index 0000000000..14627a93d6
--- /dev/null
+++ b/quantum/dynamic_keymap.c
@@ -0,0 +1,230 @@
+/* Copyright 2017 Jason Williams (Wilba)
+ *
+ * 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 "config.h"
+#include "keymap.h" // to get keymaps[][][]
+#include "tmk_core/common/eeprom.h"
+#include "progmem.h" // to read default from flash
+#include "quantum.h" // for send_string()
+#include "dynamic_keymap.h"
+
+#ifdef DYNAMIC_KEYMAP_ENABLE
+
+#ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
+#error DYNAMIC_KEYMAP_EEPROM_ADDR not defined
+#endif
+
+#ifndef DYNAMIC_KEYMAP_LAYER_COUNT
+#error DYNAMIC_KEYMAP_LAYER_COUNT not defined
+#endif
+
+#ifndef DYNAMIC_KEYMAP_MACRO_COUNT
+#error DYNAMIC_KEYMAP_MACRO_COUNT not defined
+#endif
+
+#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR
+#error DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR not defined
+#endif
+
+#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE
+#error DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE not defined
+#endif
+
+uint8_t dynamic_keymap_get_layer_count(void)
+{
+ return DYNAMIC_KEYMAP_LAYER_COUNT;
+}
+
+void *dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column)
+{
+ // TODO: optimize this with some left shifts
+ return ((void*)DYNAMIC_KEYMAP_EEPROM_ADDR) + ( layer * MATRIX_ROWS * MATRIX_COLS * 2 ) +
+ ( row * MATRIX_COLS * 2 ) + ( column * 2 );
+}
+
+uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column)
+{
+ void *address = dynamic_keymap_key_to_eeprom_address(layer, row, column);
+ // Big endian, so we can read/write EEPROM directly from host if we want
+ uint16_t keycode = eeprom_read_byte(address) << 8;
+ keycode |= eeprom_read_byte(address + 1);
+ return keycode;
+}
+
+void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode)
+{
+ void *address = dynamic_keymap_key_to_eeprom_address(layer, row, column);
+ // Big endian, so we can read/write EEPROM directly from host if we want
+ eeprom_update_byte(address, (uint8_t)(keycode >> 8));
+ eeprom_update_byte(address+1, (uint8_t)(keycode & 0xFF));
+}
+
+void dynamic_keymap_reset(void)
+{
+ // Reset the keymaps in EEPROM to what is in flash.
+ // All keyboards using dynamic keymaps should define a layout
+ // for the same number of layers as DYNAMIC_KEYMAP_LAYER_COUNT.
+ for ( int layer = 0; layer < DYNAMIC_KEYMAP_LAYER_COUNT; layer++ ) {
+ for ( int row = 0; row < MATRIX_ROWS; row++ ) {
+ for ( int column = 0; column < MATRIX_COLS; column++ ) {
+ dynamic_keymap_set_keycode(layer, row, column, pgm_read_word(&keymaps[layer][row][column]));
+ }
+ }
+ }
+}
+
+void dynamic_keymap_get_buffer( uint16_t offset, uint16_t size, uint8_t *data )
+{
+ uint16_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2;
+ void *source = (void*)(DYNAMIC_KEYMAP_EEPROM_ADDR+offset);
+ uint8_t *target = data;
+ for ( uint16_t i = 0; i < size; i++ ) {
+ if ( offset + i < dynamic_keymap_eeprom_size ) {
+ *target = eeprom_read_byte(source);
+ } else {
+ *target = 0x00;
+ }
+ source++;
+ target++;
+ }
+}
+
+void dynamic_keymap_set_buffer( uint16_t offset, uint16_t size, uint8_t *data )
+{
+ uint16_t dynamic_keymap_eeprom_size = DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2;
+ void *target = (void*)(DYNAMIC_KEYMAP_EEPROM_ADDR+offset);
+ uint8_t *source = data;
+ for ( uint16_t i = 0; i < size; i++ ) {
+ if ( offset + i < dynamic_keymap_eeprom_size ) {
+ eeprom_update_byte(target, *source);
+ }
+ source++;
+ target++;
+ }
+}
+
+// This overrides the one in quantum/keymap_common.c
+uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
+{
+ if ( layer < DYNAMIC_KEYMAP_LAYER_COUNT &&
+ key.row < MATRIX_ROWS &&
+ key.col < MATRIX_COLS ) {
+ return dynamic_keymap_get_keycode(layer, key.row, key.col);
+ } else {
+ return KC_NO;
+ }
+}
+
+
+
+uint8_t dynamic_keymap_macro_get_count(void)
+{
+ return DYNAMIC_KEYMAP_MACRO_COUNT;
+}
+
+uint16_t dynamic_keymap_macro_get_buffer_size(void)
+{
+ return DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE;
+}
+
+void dynamic_keymap_macro_get_buffer( uint16_t offset, uint16_t size, uint8_t *data )
+{
+ void *source = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR+offset);
+ uint8_t *target = data;
+ for ( uint16_t i = 0; i < size; i++ ) {
+ if ( offset + i < DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE ) {
+ *target = eeprom_read_byte(source);
+ } else {
+ *target = 0x00;
+ }
+ source++;
+ target++;
+ }
+}
+
+void dynamic_keymap_macro_set_buffer( uint16_t offset, uint16_t size, uint8_t *data )
+{
+ void *target = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR+offset);
+ uint8_t *source = data;
+ for ( uint16_t i = 0; i < size; i++ ) {
+ if ( offset + i < DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE ) {
+ eeprom_update_byte(target, *source);
+ }
+ source++;
+ target++;
+ }
+}
+
+void dynamic_keymap_macro_reset(void)
+{
+ void *p = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR);
+ void *end = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR+DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE);
+ while ( p != end ) {
+ eeprom_update_byte(p, 0);
+ ++p;
+ }
+}
+
+void dynamic_keymap_macro_send( uint8_t id )
+{
+ if ( id >= DYNAMIC_KEYMAP_MACRO_COUNT ) {
+ return;
+ }
+
+ // Check the last byte of the buffer.
+ // If it's not zero, then we are in the middle
+ // of buffer writing, possibly an aborted buffer
+ // write. So do nothing.
+ void *p = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR+DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE-1);
+ if ( eeprom_read_byte(p) != 0 ) {
+ return;
+ }
+
+ // Skip N null characters
+ // p will then point to the Nth macro
+ p = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR);
+ void *end = (void*)(DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR+DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE);
+ while ( id > 0 ) {
+ // If we are past the end of the buffer, then the buffer
+ // contents are garbage, i.e. there were not DYNAMIC_KEYMAP_MACRO_COUNT
+ // nulls in the buffer.
+ if ( p == end ) {
+ return;
+ }
+ if ( eeprom_read_byte(p) == 0 ) {
+ --id;
+ }
+ ++p;
+ }
+
+ // Send the macro string one char at a time
+ // by making temporary 1 char strings
+ char data[2] = { 0, 0 };
+ // We already checked there was a null at the end of
+ // the buffer, so this cannot go past the end
+ while ( 1 ) {
+ data[0] = eeprom_read_byte(p);
+ // Stop at the null terminator of this macro string
+ if ( data[0] == 0 ) {
+ break;
+ }
+ send_string(data);
+ ++p;
+ }
+}
+
+#endif // DYNAMIC_KEYMAP_ENABLE
+
diff --git a/quantum/dynamic_keymap.h b/quantum/dynamic_keymap.h
new file mode 100644
index 0000000000..63653f6cb7
--- /dev/null
+++ b/quantum/dynamic_keymap.h
@@ -0,0 +1,63 @@
+/* Copyright 2017 Jason Williams (Wilba)
+ *
+ * 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 <stdint.h>
+#include <stdbool.h>
+
+uint8_t dynamic_keymap_get_layer_count(void);
+void *dynamic_keymap_key_to_eeprom_address(uint8_t layer, uint8_t row, uint8_t column);
+uint16_t dynamic_keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t column);
+void dynamic_keymap_set_keycode(uint8_t layer, uint8_t row, uint8_t column, uint16_t keycode);
+void dynamic_keymap_reset(void);
+// These get/set the keycodes as stored in the EEPROM buffer
+// Data is big-endian 16-bit values (the keycodes)
+// Order is by layer/row/column
+// Thus offset 0 = 0,0,0, offset MATRIX_COLS*2 = 0,1,0, offset MATRIX_ROWS*MATRIX_COLS*2 = 1,0,0
+// Note the *2, because offset is in bytes and keycodes are two bytes
+// This is only really useful for host applications that want to get a whole keymap fast,
+// by reading 14 keycodes (28 bytes) at a time, reducing the number of raw HID transfers by
+// a factor of 14.
+void dynamic_keymap_get_buffer( uint16_t offset, uint16_t size, uint8_t *data );
+void dynamic_keymap_set_buffer( uint16_t offset, uint16_t size, uint8_t *data );
+
+// This overrides the one in quantum/keymap_common.c
+// uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
+
+
+
+// Note regarding dynamic_keymap_macro_set_buffer():
+// The last byte of the buffer is used as a valid flag,
+// so macro sending is disabled during writing a new buffer,
+// should it happen during, or after an interrupted transfer.
+//
+// Users writing to the buffer must first set the last byte of the buffer
+// to non-zero (i.e. 0xFF). After (or during) the final write, set the
+// last byte of the buffer to zero.
+//
+// Since the contents of the buffer must be a list of null terminated
+// strings, the last byte must be a null when at maximum capacity,
+// and it not being null means the buffer can be considered in an
+// invalid state.
+
+uint8_t dynamic_keymap_macro_get_count(void);
+uint16_t dynamic_keymap_macro_get_buffer_size(void);
+void dynamic_keymap_macro_get_buffer( uint16_t offset, uint16_t size, uint8_t *data );
+void dynamic_keymap_macro_set_buffer( uint16_t offset, uint16_t size, uint8_t *data );
+void dynamic_keymap_macro_reset(void);
+
+void dynamic_keymap_macro_send( uint8_t id );
+
diff --git a/quantum/encoder.c b/quantum/encoder.c
new file mode 100644
index 0000000000..6629a098b8
--- /dev/null
+++ b/quantum/encoder.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
+ *
+ * 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 "encoder.h"
+
+#ifndef ENCODER_RESOLUTION
+ #define ENCODER_RESOLUTION 4
+#endif
+
+#ifndef NUMBER_OF_ENCODERS
+ #error "Number of encoders not defined by NUMBER_OF_ENCODERS"
+#endif
+
+#if !defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B)
+ #error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B"
+#endif
+
+static pin_t encoders_pad_a[NUMBER_OF_ENCODERS] = ENCODERS_PAD_A;
+static pin_t encoders_pad_b[NUMBER_OF_ENCODERS] = ENCODERS_PAD_B;
+
+static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 };
+
+static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0};
+static int8_t encoder_value[NUMBER_OF_ENCODERS] = {0};
+
+__attribute__ ((weak))
+void encoder_update_user(int8_t index, bool clockwise) { }
+
+__attribute__ ((weak))
+void encoder_update_kb(int8_t index, bool clockwise) {
+ encoder_update_user(index, clockwise);
+}
+
+void encoder_init(void) {
+ for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
+ setPinInputHigh(encoders_pad_a[i]);
+ setPinInputHigh(encoders_pad_b[i]);
+
+ encoder_state[i] = (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
+ }
+}
+
+void encoder_read(void) {
+ for (int i = 0; i < NUMBER_OF_ENCODERS; i++) {
+ encoder_state[i] <<= 2;
+ encoder_state[i] |= (readPin(encoders_pad_a[i]) << 0) | (readPin(encoders_pad_b[i]) << 1);
+ encoder_value[i] += encoder_LUT[encoder_state[i] & 0xF];
+ if (encoder_value[i] >= ENCODER_RESOLUTION) {
+ encoder_update_kb(i, COUNTRECLOCKWISE);
+ }
+ if (encoder_value[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise
+ encoder_update_kb(i, CLOCKWISE);
+ }
+ encoder_value[i] %= ENCODER_RESOLUTION;
+ }
+}
diff --git a/quantum/process_keycode/process_chording.h b/quantum/encoder.h
index 8c0f4862a8..2024fa303f 100644
--- a/quantum/process_keycode/process_chording.h
+++ b/quantum/encoder.h
@@ -1,4 +1,5 @@
-/* Copyright 2016 Jack Humbert
+/*
+ * Copyright 2018 Jack Humbert <jack.humb@gmail.com>
*
* 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
@@ -14,19 +15,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PROCESS_CHORDING_H
-#define PROCESS_CHORDING_H
+#pragma once
#include "quantum.h"
-// Chording stuff
-#define CHORDING_MAX 4
-bool chording = false;
+#define COUNTRECLOCKWISE 0
+#define CLOCKWISE 1
-uint8_t chord_keys[CHORDING_MAX] = {0};
-uint8_t chord_key_count = 0;
-uint8_t chord_key_down = 0;
+void encoder_init(void);
+void encoder_read(void);
-bool process_chording(uint16_t keycode, keyrecord_t *record);
-
-#endif
+void encoder_update_kb(int8_t index, bool clockwise);
+void encoder_update_user(int8_t index, bool clockwise);
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index 50af15d626..f6c8b70d28 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -64,7 +64,7 @@ action_t action_for_key(uint8_t layer, keypos_t key)
case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
break;
- case KC_AUDIO_MUTE ... KC_MEDIA_REWIND:
+ case KC_AUDIO_MUTE ... KC_BRIGHTNESS_DOWN:
action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
break;
case KC_MS_UP ... KC_MS_ACCEL2:
diff --git a/quantum/keymap_extras/keymap_belgian.h b/quantum/keymap_extras/keymap_belgian.h
new file mode 100644
index 0000000000..ab89fbabfe
--- /dev/null
+++ b/quantum/keymap_extras/keymap_belgian.h
@@ -0,0 +1,108 @@
+/* Copyright 2015-2016 Jack Humbert
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef KEYMAP_BELGIAN_H
+#define KEYMAP_BELGIAN_H
+
+#include "keymap.h"
+
+// Normal characters
+// Line 1
+#define BE_SUP2 KC_GRV
+#define BE_AMP KC_1
+#define BE_EACU KC_2
+#define BE_QUOT KC_3
+#define BE_APOS KC_4
+#define BE_LPRN KC_5
+#define BE_PARA KC_6
+#define BE_EGRV KC_7
+#define BE_EXLM KC_8
+#define BE_CCED KC_9
+#define BE_AGRV KC_0
+#define BE_RPRN KC_MINS
+#define BE_MINS KC_EQL
+
+// Line 2
+#define BE_A KC_Q
+#define BE_Z KC_W
+#define BE_CIRC KC_LBRC
+#define BE_DLR KC_RBRC
+
+// Line 3
+#define BE_Q KC_A
+#define BE_M KC_SCLN
+#define BE_UGRV KC_QUOT
+#define BE_MU KC_NUHS
+
+// Line 4
+#define BE_LESS KC_NUBS
+#define BE_W KC_Z
+#define BE_COMM KC_M
+#define BE_SCLN KC_COMM
+#define BE_COLN KC_DOT
+#define BE_EQL KC_SLSH
+
+// Shifted characters
+// Line 1
+#define BE_SUP3 KC_TILD
+#define BE_1 LSFT(KC_1)
+#define BE_2 LSFT(KC_2)
+#define BE_3 LSFT(KC_3)
+#define BE_4 LSFT(KC_4)
+#define BE_5 LSFT(KC_5)
+#define BE_6 LSFT(KC_6)
+#define BE_7 LSFT(KC_7)
+#define BE_8 LSFT(KC_8)
+#define BE_9 LSFT(KC_9)
+#define BE_0 LSFT(KC_0)
+#define BE_OVRR KC_UNDS
+#define BE_UNDS KC_PLUS
+
+// Line 2
+#define BE_UMLT LSFT(BE_CIRC)
+#define BE_PND LSFT(BE_DLR)
+
+// Line 3
+#define BE_PERC LSFT(BE_UGRV)
+
+// Line 4
+#define BE_GRTR LSFT(BE_LESS)
+#define BE_QUES LSFT(BE_COMM)
+#define BE_DOT LSFT(BE_SCLN)
+#define BE_SLSH LSFT(BE_COLN)
+#define BE_PLUS LSFT(BE_EQL)
+
+// Alt Gr-ed characters
+// Line 1
+#define BE_PIPE ALGR(KC_1)
+#define BE_AT ALGR(KC_2)
+#define BE_HASH ALGR(KC_3)
+#define BE_LCBR ALGR(KC_9)
+#define BE_RCBR ALGR(KC_0)
+
+// Line 2
+#define BE_EURO ALGR(KC_E)
+#define BE_LSBR ALGR(BE_CIRC)
+#define BE_RSBR ALGR(BE_DLR)
+
+// Line 3
+#define BE_ACUT ALGR(BE_UGRV)
+#define BE_GRV ALGR(BE_MU)
+
+// Line 4
+#define BE_BSLS ALGR(BE_LESS)
+#define BE_TILT ALGR(BE_EQL)
+
+#endif
diff --git a/quantum/keymap_extras/keymap_bepo.h b/quantum/keymap_extras/keymap_bepo.h
index 05fd2b0023..8d7b36ca3d 100644
--- a/quantum/keymap_extras/keymap_bepo.h
+++ b/quantum/keymap_extras/keymap_bepo.h
@@ -19,15 +19,6 @@
#include "keymap.h"
-// Alt gr
-#ifndef ALTGR
-#define ALTGR(kc) RALT(kc)
-#endif
-#ifndef ALGR
-#define ALGR(kc) ALTGR(kc)
-#endif
-#define BP_ALGR KC_RALT
-
// Normal characters
// First row (on usual keyboards)
#define BP_DOLLAR KC_GRAVE // $
@@ -142,138 +133,138 @@
// AltGr-ed characters
// First row
-#define BP_EN_DASH ALTGR(BP_DOLLAR) // –
+#define BP_EN_DASH ALGR(BP_DOLLAR) // –
#define BP_NDSH BP_EN_DASH
-#define BP_EM_DASH ALTGR(KC_1) // —
+#define BP_EM_DASH ALGR(KC_1) // —
#define BP_MDSH BP_EM_DASH
-#define BP_LESS ALTGR(KC_2) // <
-#define BP_GREATER ALTGR(KC_3) // >
+#define BP_LESS ALGR(KC_2) // <
+#define BP_GREATER ALGR(KC_3) // >
#define BP_GRTR BP_GREATER
-#define BP_LBRACKET ALTGR(KC_4) // [
+#define BP_LBRACKET ALGR(KC_4) // [
#define BP_LBRC BP_LBRACKET
-#define BP_RBRACKET ALTGR(KC_5) // ]
+#define BP_RBRACKET ALGR(KC_5) // ]
#define BP_RBRC BP_RBRACKET
-#define BP_CIRCUMFLEX ALTGR(KC_6) // ^
+#define BP_CIRCUMFLEX ALGR(KC_6) // ^
#define BP_CIRC BP_CIRCUMFLEX
-#define BP_PLUS_MINUS ALTGR(KC_7) // ±
+#define BP_PLUS_MINUS ALGR(KC_7) // ±
#define BP_PSMS BP_PLUS_MINUS
-#define BP_MATH_MINUS ALTGR(KC_8) // −
+#define BP_MATH_MINUS ALGR(KC_8) // −
#define BP_MMNS BP_MATH_MINUS
-#define BP_OBELUS ALTGR(KC_9) // ÷
+#define BP_OBELUS ALGR(KC_9) // ÷
#define BP_OBEL BP_OBELUS
// more conventional name of the symbol
#define BP_DIVISION_SIGN BP_OBELUS
#define BP_DVSN BP_DIVISION_SIGN
-#define BP_TIMES ALTGR(KC_0) // ×
+#define BP_TIMES ALGR(KC_0) // ×
#define BP_TIMS BP_TIMES
-#define BP_DIFFERENT ALTGR(BP_EQUAL) // ≠
+#define BP_DIFFERENT ALGR(BP_EQUAL) // ≠
#define BP_DIFF BP_DIFFERENT
-#define BP_PERMILLE ALTGR(BP_PERCENT) // ‰
+#define BP_PERMILLE ALGR(BP_PERCENT) // ‰
#define BP_PMIL BP_PERMILLE
// Second row
-#define BP_PIPE ALTGR(BP_B) // |
-#define BP_DEAD_ACUTE ALTGR(BP_E_ACUTE) // dead ´
+#define BP_PIPE ALGR(BP_B) // |
+#define BP_DEAD_ACUTE ALGR(BP_E_ACUTE) // dead ´
#define BP_DACT BP_DEAD_ACUTE
-#define BP_AMPERSAND ALTGR(BP_P) // &
+#define BP_AMPERSAND ALGR(BP_P) // &
#define BP_AMPR BP_AMPERSAND
-#define BP_OE_LIGATURE ALTGR(BP_O) // œ
+#define BP_OE_LIGATURE ALGR(BP_O) // œ
#define BP_OE BP_OE_LIGATURE
-#define BP_DEAD_GRAVE ALTGR(BP_E_GRAVE) // `
+#define BP_DEAD_GRAVE ALGR(BP_E_GRAVE) // `
#define BP_DGRV BP_DEAD_GRAVE
-#define BP_INVERTED_EXCLAIM ALTGR(BP_DEAD_CIRCUMFLEX) // ¡
+#define BP_INVERTED_EXCLAIM ALGR(BP_DEAD_CIRCUMFLEX) // ¡
#define BP_IXLM BP_INVERTED_EXCLAIM
-#define BP_DEAD_CARON ALTGR(BP_V) // dead ˇ
+#define BP_DEAD_CARON ALGR(BP_V) // dead ˇ
#define BP_DCAR BP_DEAD_CARON
-#define BP_ETH ALTGR(BP_D) // ð
-#define BP_DEAD_SLASH ALTGR(BP_L) // dead /
+#define BP_ETH ALGR(BP_D) // ð
+#define BP_DEAD_SLASH ALGR(BP_L) // dead /
#define BP_DSLH BP_DEAD_SLASH
-#define BP_IJ_LIGATURE ALTGR(BP_J) // ij
+#define BP_IJ_LIGATURE ALGR(BP_J) // ij
#define BP_IJ BP_IJ_LIGATURE
-#define BP_SCHWA ALTGR(BP_Z) // ə
+#define BP_SCHWA ALGR(BP_Z) // ə
#define BP_SCWA BP_SCHWA
-#define BP_DEAD_BREVE ALTGR(BP_W) // dead ˘
+#define BP_DEAD_BREVE ALGR(BP_W) // dead ˘
#define BP_DBRV BP_DEAD_BREVE
// Third row
-#define BP_AE_LIGATURE ALTGR(BP_A) // æ
+#define BP_AE_LIGATURE ALGR(BP_A) // æ
#define BP_AE BP_AE_LIGATURE
-#define BP_U_GRAVE ALTGR(BP_U) // ù
+#define BP_U_GRAVE ALGR(BP_U) // ù
#define BP_UGRV BP_U_GRAVE
-#define BP_DEAD_TREMA ALTGR(BP_I) // dead ¨ (trema/umlaut/diaresis)
+#define BP_DEAD_TREMA ALGR(BP_I) // dead ¨ (trema/umlaut/diaresis)
#define BP_DTRM BP_DEAD_TREMA
-#define BP_EURO ALTGR(BP_E) // €
-#define BP_TYPOGRAPHICAL_APOSTROPHE ALTGR(BP_COMMA) // ’
+#define BP_EURO ALGR(BP_E) // €
+#define BP_TYPOGRAPHICAL_APOSTROPHE ALGR(BP_COMMA) // ’
#define BP_TAPO BP_TYPOGRAPHICAL_APOSTROPHE
-#define BP_COPYRIGHT ALTGR(BP_C) // ©
+#define BP_COPYRIGHT ALGR(BP_C) // ©
#define BP_CPRT BP_COPYRIGHT
-#define BP_THORN ALTGR(BP_T) // þ
+#define BP_THORN ALGR(BP_T) // þ
#define BP_THRN BP_THORN
-#define BP_SHARP_S ALTGR(BP_S) // ß
+#define BP_SHARP_S ALGR(BP_S) // ß
#define BP_SRPS BP_SHARP_S
-#define BP_REGISTERED_TRADEMARK ALTGR(BP_R) // ®
+#define BP_REGISTERED_TRADEMARK ALGR(BP_R) // ®
#define BP_RTM BP_REGISTERED_TRADEMARK
-#define BP_DEAD_TILDE ALTGR(BP_N) // dead ~
+#define BP_DEAD_TILDE ALGR(BP_N) // dead ~
#define BP_DTLD BP_DEAD_TILDE
-#define BP_DEAD_MACRON ALTGR(BP_M) // dead ¯
+#define BP_DEAD_MACRON ALGR(BP_M) // dead ¯
#define BP_DMCR BP_DEAD_MACRON
-#define BP_DEAD_CEDILLA ALTGR(BP_C_CEDILLA) // dead ¸
+#define BP_DEAD_CEDILLA ALGR(BP_C_CEDILLA) // dead ¸
#define BP_DCED BP_DEAD_CEDILLA
// Fourth row
-#define BP_NONUS_SLASH ALTGR(BP_E_CIRCUMFLEX) // / on non-us backslash key (102nd key, ê in bépo)
+#define BP_NONUS_SLASH ALGR(BP_E_CIRCUMFLEX) // / on non-us backslash key (102nd key, ê in bépo)
#define BP_NUSL BP_NONUS_SLASH
-#define BP_BACKSLASH ALTGR(BP_A_GRAVE) /* \ */
+#define BP_BACKSLASH ALGR(BP_A_GRAVE) /* \ */
#define BP_BSLS BP_BACKSLASH
-#define BP_LEFT_CURLY_BRACE ALTGR(BP_Y) // {
+#define BP_LEFT_CURLY_BRACE ALGR(BP_Y) // {
#define BP_LCBR BP_LEFT_CURLY_BRACE
-#define BP_RIGHT_CURLY_BRACE ALTGR(BP_X) // }
+#define BP_RIGHT_CURLY_BRACE ALGR(BP_X) // }
#define BP_RCBR BP_RIGHT_CURLY_BRACE
-#define BP_ELLIPSIS ALTGR(BP_DOT) // …
+#define BP_ELLIPSIS ALGR(BP_DOT) // …
#define BP_ELPS BP_ELLIPSIS
-#define BP_TILDE ALTGR(BP_K) // ~
+#define BP_TILDE ALGR(BP_K) // ~
#define BP_TILD BP_TILDE
-#define BP_INVERTED_QUESTION ALTGR(BP_QUESTION) // ¿
+#define BP_INVERTED_QUESTION ALGR(BP_QUESTION) // ¿
#define BP_IQST BP_INVERTED_QUESTION
-#define BP_DEAD_RING ALTGR(BP_Q) // dead °
+#define BP_DEAD_RING ALGR(BP_Q) // dead °
#define BP_DRNG BP_DEAD_RING
-#define BP_DEAD_GREEK ALTGR(BP_G) // dead Greek key (following key will make a Greek letter)
+#define BP_DEAD_GREEK ALGR(BP_G) // dead Greek key (following key will make a Greek letter)
#define BP_DGRK BP_DEAD_GREEK
-#define BP_DAGGER ALTGR(BP_H) // †
+#define BP_DAGGER ALGR(BP_H) // †
#define BP_DAGR BP_DAGGER
-#define BP_DEAD_OGONEK ALTGR(BP_F) // dead ˛
+#define BP_DEAD_OGONEK ALGR(BP_F) // dead ˛
#define BP_DOGO BP_DEAD_OGONEK
// Space bar
-#define BP_UNDERSCORE ALTGR(KC_SPACE) // _
+#define BP_UNDERSCORE ALGR(KC_SPACE) // _
#define BP_UNDS BP_UNDERSCORE
// AltGr-Shifted characters (different from capitalised AltGr-ed characters)
// First row
-#define BP_PARAGRAPH ALTGR(BP_HASH) // ¶
+#define BP_PARAGRAPH ALGR(BP_HASH) // ¶
#define BP_PARG BP_PARAGRAPH
-#define BP_LOW_DOUBLE_QUOTE ALTGR(BP_1) // „
+#define BP_LOW_DOUBLE_QUOTE ALGR(BP_1) // „
#define BP_LWQT BP_LOW_DOUBLE_QUOTE
-#define BP_LEFT_DOUBLE_QUOTE ALTGR(BP_2) // “
+#define BP_LEFT_DOUBLE_QUOTE ALGR(BP_2) // “
#define BP_LDQT BP_LEFT_DOUBLE_QUOTE
-#define BP_RIGHT_DOUBLE_QUOTE ALTGR(BP_3) // ”
+#define BP_RIGHT_DOUBLE_QUOTE ALGR(BP_3) // ”
#define BP_RDQT BP_RIGHT_DOUBLE_QUOTE
-#define BP_LESS_OR_EQUAL ALTGR(BP_4) // ≤
+#define BP_LESS_OR_EQUAL ALGR(BP_4) // ≤
#define BP_LEQL BP_LESS_OR_EQUAL
-#define BP_GREATER_OR_EQUAL ALTGR(BP_5) // ≥
+#define BP_GREATER_OR_EQUAL ALGR(BP_5) // ≥
#define BP_GEQL BP_GREATER_OR_EQUAL
-// nothing on ALTGR(BP_6)
-#define BP_NEGATION ALTGR(BP_7) // ¬
+// nothing on ALGR(BP_6)
+#define BP_NEGATION ALGR(BP_7) // ¬
#define BP_NEGT BP_NEGATION
-#define BP_ONE_QUARTER ALTGR(BP_8) // ¼
+#define BP_ONE_QUARTER ALGR(BP_8) // ¼
#define BP_1QRT BP_ONE_QUARTER
-#define BP_ONE_HALF ALTGR(BP_9) // ½
+#define BP_ONE_HALF ALGR(BP_9) // ½
#define BP_1HLF BP_ONE_HALF
-#define BP_THREE_QUARTERS ALTGR(BP_0) // ¾
+#define BP_THREE_QUARTERS ALGR(BP_0) // ¾
#define BP_3QRT BP_THREE_QUARTERS
-#define BP_MINUTES ALTGR(BP_DEGREE) // ′
+#define BP_MINUTES ALGR(BP_DEGREE) // ′
#define BP_MNUT BP_MINUTES
-#define BP_SECONDS ALTGR(BP_GRAVE) // ″
+#define BP_SECONDS ALGR(BP_GRAVE) // ″
#define BP_SCND BP_SECONDS
// Second row
@@ -281,7 +272,7 @@
#define BP_BPIP BP_BROKEN_PIPE
#define BP_DEAD_DOUBLE_ACUTE LSFT(BP_DEAD_ACUTE) // ˝
#define BP_DDCT BP_DEAD_DOUBLE_ACUTE
-#define BP_SECTION ALTGR(LSFT(BP_P)) // §
+#define BP_SECTION ALGR(LSFT(BP_P)) // §
#define BP_SECT BP_SECTION
// LSFT(BP_DEAD_GRAVE) is actually the same character as LSFT(BP_PERCENT)
#define BP_GRAVE_BIS LSFT(BP_DEAD_GRAVE) // `
@@ -292,35 +283,35 @@
#define BP_DDTA BP_DEAD_DOT_ABOVE
#define BP_DEAD_CURRENCY LSFT(BP_EURO) // dead ¤ (next key will generate a currency code like ¥ or £)
#define BP_DCUR BP_DEAD_CURRENCY
-#define BP_DEAD_HORN LSFT(ALTGR(BP_COMMA)) // dead ̛
+#define BP_DEAD_HORN LSFT(ALGR(BP_COMMA)) // dead ̛
#define BP_DHRN BP_DEAD_HORN
-#define BP_LONG_S LSFT(ALTGR(BP_C)) // ſ
+#define BP_LONG_S LSFT(ALGR(BP_C)) // ſ
#define BP_LNGS BP_LONG_S
#define BP_TRADEMARK LSFT(BP_REGISTERED_TRADEMARK) // ™
#define BP_TM BP_TRADEMARK
-#define BP_ORDINAL_INDICATOR_O LSFT(ALTGR(BP_M)) // º
+#define BP_ORDINAL_INDICATOR_O LSFT(ALGR(BP_M)) // º
#define BP_ORDO BP_ORDINAL_INDICATOR_O
#define BP_DEAD_COMMA LSFT(BP_DEAD_CEDILLA) // dead ˛
#define BP_DCOM BP_DEAD_COMMA
// Fourth row
-#define BP_LEFT_QUOTE LSFT(ALTGR(BP_Y)) // ‘
+#define BP_LEFT_QUOTE LSFT(ALGR(BP_Y)) // ‘
#define BP_LQOT BP_LEFT_QUOTE
-#define BP_RIGHT_QUOTE LSFT(ALTGR(BP_X)) // ’
+#define BP_RIGHT_QUOTE LSFT(ALGR(BP_X)) // ’
#define BP_RQOT BP_RIGHT_QUOTE
-#define BP_INTERPUNCT LSFT(ALTGR(BP_DOT)) // ·
+#define BP_INTERPUNCT LSFT(ALGR(BP_DOT)) // ·
#define BP_IPCT BP_INTERPUNCT
-#define BP_DEAD_HOOK_ABOVE LSFT(ALTGR(BP_QUESTION)) // dead ̉
+#define BP_DEAD_HOOK_ABOVE LSFT(ALGR(BP_QUESTION)) // dead ̉
#define BP_DHKA BP_DEAD_HOOK_ABOVE
#define BP_DEAD_UNDERDOT LSFT(BP_DEAD_RING) // dead ̣
#define BP_DUDT BP_DEAD_UNDERDOT
#define BP_DOUBLE_DAGGER LSFT(BP_DAGGER) // ‡
#define BP_DDGR BP_DOUBLE_DAGGER
-#define BP_ORDINAL_INDICATOR_A LSFT(ALTGR(BP_F)) // ª
+#define BP_ORDINAL_INDICATOR_A LSFT(ALGR(BP_F)) // ª
#define BP_ORDA BP_ORDINAL_INDICATOR_A
// Space bar
-#define BP_NARROW_NON_BREAKING_SPACE ALTGR(BP_NON_BREAKING_SPACE)
+#define BP_NARROW_NON_BREAKING_SPACE ALGR(BP_NON_BREAKING_SPACE)
#define BP_NNBS BP_NARROW_NON_BREAKING_SPACE
#endif
diff --git a/quantum/keymap_extras/keymap_canadian_multilingual.h b/quantum/keymap_extras/keymap_canadian_multilingual.h
index 1d45bee32e..2b5b95d6fa 100644
--- a/quantum/keymap_extras/keymap_canadian_multilingual.h
+++ b/quantum/keymap_extras/keymap_canadian_multilingual.h
@@ -13,22 +13,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef KEYMAP_CANADIAN_MULTILINGUAG_H
-#define KEYMAP_CANADIAN_MULTILINGUAG_H
+#ifndef KEYMAP_CANADIAN_MULTILINGUAL_H
+#define KEYMAP_CANADIAN_MULTILINGUAL_H
#include "keymap.h"
-// Alt gr
-#ifndef ALTGR
-#define ALTGR(kc) RALT(kc)
-#endif
-#ifndef ALGR
-#define ALGR(kc) ALTGR(kc)
-#endif
-
-#define CSA_ALTGR KC_RALT
-#define CSA_ALGR CSA_ALTGR
-
#ifndef GR2A
#define GR2A(kc) RCTL(kc)
#endif
@@ -78,43 +67,43 @@
// Alt Gr-ed characters
// First row
-#define CSA_PIPE ALTGR(CSA_SLASH) // |
-#define CSA_CURRENCY ALTGR(KC_4) // ¤
+#define CSA_PIPE ALGR(CSA_SLASH) // |
+#define CSA_CURRENCY ALGR(KC_4) // ¤
#define CSA_CURR CSA_CURRENCY
-#define CSA_LEFT_CURLY_BRACE ALTGR(KC_7) // {
+#define CSA_LEFT_CURLY_BRACE ALGR(KC_7) // {
#define CSA_LCBR CSA_LEFT_CURLY_BRACE
-#define CSA_RIGHT_CURLY_BRACE ALTGR(KC_8) // }
+#define CSA_RIGHT_CURLY_BRACE ALGR(KC_8) // }
#define CSA_RCBR CSA_RIGHT_CURLY_BRACE
-#define CSA_LBRACKET ALTGR(KC_9) // [
+#define CSA_LBRACKET ALGR(KC_9) // [
#define CSA_LBRC CSA_LBRACKET
-#define CSA_RBRACKET ALTGR(KC_0) // ]
+#define CSA_RBRACKET ALGR(KC_0) // ]
#define CSA_RBRC CSA_RBRACKET
-#define CSA_NEGATION ALTGR(KC_EQUAL) // ¬
+#define CSA_NEGATION ALGR(KC_EQUAL) // ¬
#define CSA_NEGT CSA_NEGATION
// Second row
// euro symbol not available on Linux? (X.org)
-#define CSA_EURO ALTGR(KC_E) // €
-#define CSA_DEAD_GRAVE ALTGR(CSA_DEAD_CIRCUMFLEX)
+#define CSA_EURO ALGR(KC_E) // €
+#define CSA_DEAD_GRAVE ALGR(CSA_DEAD_CIRCUMFLEX)
#define CSA_DGRV CSA_DEAD_GRAVE // dead `
-#define CSA_DEAD_TILDE ALTGR(CSA_C_CEDILLA) // ~
+#define CSA_DEAD_TILDE ALGR(CSA_C_CEDILLA) // ~
#define CSA_DTLD CSA_DEAD_TILDE
// Third row
-#define CSA_DEGREE ALTGR(KC_SCOLON) // °
+#define CSA_DEGREE ALGR(KC_SCOLON) // °
#define CSA_DEGR CSA_DEGREE
// Fourth row
-#define CSA_LEFT_GUILLEMET ALTGR(KC_Z) // «
+#define CSA_LEFT_GUILLEMET ALGR(KC_Z) // «
#define CSA_LGIL CSA_LEFT_GUILLEMET
-#define CSA_RIGHT_GUILLEMET ALTGR(KC_X) // »
+#define CSA_RIGHT_GUILLEMET ALGR(KC_X) // »
#define CSA_RGIL CSA_RIGHT_GUILLEMET
-#define CSA_LESS ALTGR(KC_COMMA) // <
-#define CSA_GREATER ALTGR(KC_DOT) // >
+#define CSA_LESS ALGR(KC_COMMA) // <
+#define CSA_GREATER ALGR(KC_DOT) // >
#define CSA_GRTR CSA_GREATER
// Space bar
-#define CSA_NON_BREAKING_SPACE ALTGR(KC_SPACE)
+#define CSA_NON_BREAKING_SPACE ALGR(KC_SPACE)
#define CSA_NBSP CSA_NON_BREAKING_SPACE
// GR2A-ed characters
@@ -201,7 +190,7 @@
// nothing on 2
#define CSA_POUND GR2A(LSFT(KC_3)) // £
#define CSA_GBP CSA_POUND_SIGN
-// already on ALTGR(KC_E)
+// already on ALGR(KC_E)
#define CSA_EURO_BIS GR2A(LSFT(KC_4)) // €
#define CSA_EURB CSA_EURO_BIS
#define CSA_THREE_EIGHTHS GR2A(LSFT(KC_5)) // ⅜
diff --git a/quantum/keymap_extras/keymap_fr_ch.h b/quantum/keymap_extras/keymap_fr_ch.h
index c0ca832a6f..69f9547bb9 100644
--- a/quantum/keymap_extras/keymap_fr_ch.h
+++ b/quantum/keymap_extras/keymap_fr_ch.h
@@ -18,10 +18,6 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define FR_CH_ALGR KC_RALT
-
// normal characters
#define FR_CH_Z KC_Y
#define FR_CH_Y KC_Z
diff --git a/quantum/keymap_extras/keymap_french.h b/quantum/keymap_extras/keymap_french.h
index 3308dc5f77..bef7754707 100644
--- a/quantum/keymap_extras/keymap_french.h
+++ b/quantum/keymap_extras/keymap_french.h
@@ -18,12 +18,6 @@
#include "keymap.h"
-// Alt gr
-#ifndef ALGR
-#define ALGR(kc) RALT(kc)
-#endif
-#define NO_ALGR KC_RALT
-
// Normal characters
#define FR_SUP2 KC_GRV
#define FR_AMP KC_1
diff --git a/quantum/keymap_extras/keymap_german.h b/quantum/keymap_extras/keymap_german.h
index e007c26ef5..0ba3570df7 100644
--- a/quantum/keymap_extras/keymap_german.h
+++ b/quantum/keymap_extras/keymap_german.h
@@ -19,10 +19,6 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define DE_ALGR KC_RALT
-
// normal characters
#define DE_Z KC_Y
#define DE_Y KC_Z
diff --git a/quantum/keymap_extras/keymap_german_ch.h b/quantum/keymap_extras/keymap_german_ch.h
index 67350d6602..bd1ef89a19 100644
--- a/quantum/keymap_extras/keymap_german_ch.h
+++ b/quantum/keymap_extras/keymap_german_ch.h
@@ -18,10 +18,6 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define CH_ALGR KC_RALT
-
// normal characters
#define CH_Z KC_Y
#define CH_Y KC_Z
diff --git a/quantum/keymap_extras/keymap_hungarian.h b/quantum/keymap_extras/keymap_hungarian.h
index b372440928..ff43535f38 100644
--- a/quantum/keymap_extras/keymap_hungarian.h
+++ b/quantum/keymap_extras/keymap_hungarian.h
@@ -19,10 +19,6 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define HU_ALGR KC_RALT
-
// basic letters
#define HU_Z KC_Y
#define HU_Y KC_Z
diff --git a/quantum/keymap_extras/keymap_italian.h b/quantum/keymap_extras/keymap_italian.h
index 0ff6ce8762..fe0f5eb847 100644
--- a/quantum/keymap_extras/keymap_italian.h
+++ b/quantum/keymap_extras/keymap_italian.h
@@ -19,14 +19,7 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define IT_ALGR KC_RALT
-
// normal characters
-
-
-
#define IT_A KC_A
#define IT_B KC_B
#define IT_C KC_C
diff --git a/quantum/keymap_extras/keymap_jp.h b/quantum/keymap_extras/keymap_jp.h
index fb74bce8d4..b0235f1120 100644
--- a/quantum/keymap_extras/keymap_jp.h
+++ b/quantum/keymap_extras/keymap_jp.h
@@ -40,6 +40,9 @@
#define JP_HENK KC_INT4 // henkan
#define JP_KANA KC_INT2 // katakana/hiragana|ro-mazi
+#define JP_MKANA KC_LANG1 //kana on MacOSX
+#define JP_MEISU KC_LANG2 //eisu on MacOSX
+
//Aliases for shifted symbols
#define JP_DQT LSFT(KC_2) // "
diff --git a/quantum/keymap_extras/keymap_neo2.h b/quantum/keymap_extras/keymap_neo2.h
index 174f4a6eec..818a739c76 100644
--- a/quantum/keymap_extras/keymap_neo2.h
+++ b/quantum/keymap_extras/keymap_neo2.h
@@ -73,6 +73,6 @@
#define NEO_L1_R DE_HASH
#define NEO_L2_L DE_LESS
-#define NEO_L2_R DE_ALGR
+#define NEO_L2_R KC_ALGR
#endif
diff --git a/quantum/keymap_extras/keymap_nordic.h b/quantum/keymap_extras/keymap_nordic.h
index 6b34db5588..551a4212b2 100644
--- a/quantum/keymap_extras/keymap_nordic.h
+++ b/quantum/keymap_extras/keymap_nordic.h
@@ -18,10 +18,6 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define NO_ALGR KC_RALT
-
// Normal characters
#define NO_HALF KC_GRV
#define NO_PLUS KC_MINS
diff --git a/quantum/keymap_extras/keymap_plover_dvorak.h b/quantum/keymap_extras/keymap_plover_dvorak.h
new file mode 100644
index 0000000000..83bb1e8b87
--- /dev/null
+++ b/quantum/keymap_extras/keymap_plover_dvorak.h
@@ -0,0 +1,47 @@
+/* Copyright 2016 James Kay
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef KEYMAP_PLOVER_DVORAK_H
+#define KEYMAP_PLOVER_DVORAK_H
+
+#include "keymap_dvorak.h"
+
+#define PD_NUM DV_1
+#define PD_LS DV_Q
+#define PD_LT DV_W
+#define PD_LP DV_E
+#define PD_LH DV_R
+#define PD_LK DV_S
+#define PD_LW DV_D
+#define PD_LR DV_F
+
+#define PD_STAR DV_Y
+#define PD_RF DV_U
+#define PD_RP DV_I
+#define PD_RL DV_O
+#define PD_RT DV_P
+#define PD_RD DV_LBRC
+#define PD_RR DV_J
+#define PD_RB DV_K
+#define PD_RG DV_L
+#define PD_RS DV_SCLN
+#define PD_RZ DV_QUOT
+
+#define PD_A DV_C
+#define PD_O DV_V
+#define PD_E DV_N
+#define PD_U DV_M
+
+#endif
diff --git a/quantum/keymap_extras/keymap_slovenian.h b/quantum/keymap_extras/keymap_slovenian.h
new file mode 100644
index 0000000000..892283e702
--- /dev/null
+++ b/quantum/keymap_extras/keymap_slovenian.h
@@ -0,0 +1,107 @@
+/* Copyright 2018 Žan Pevec
+
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEYMAP_SLOVENIAN
+#define KEYMAP_SLOVENIAN
+
+#include "keymap.h"
+
+//Swapped Z and Y
+#define SI_Z KC_Y
+#define SI_Y KC_Z
+
+//Special characters
+#define SI_CV KC_SCLN
+#define SI_SV KC_LBRC
+#define SI_ZV KC_BSLS
+
+#define SI_A KC_A
+#define SI_B KC_B
+#define SI_C KC_C
+#define SI_D KC_D
+#define SI_E KC_E
+#define SI_F KC_F
+#define SI_G KC_G
+#define SI_H KC_H
+#define SI_I KC_I
+#define SI_J KC_J
+#define SI_K KC_K
+#define SI_L KC_L
+#define SI_M KC_M
+#define SI_N KC_N
+#define SI_O KC_O
+#define SI_P KC_P
+#define SI_Q KC_Q
+#define SI_R KC_R
+#define SI_S KC_S
+#define SI_T KC_T
+#define SI_U KC_U
+#define SI_V KC_V
+#define SI_W KC_W
+#define SI_X KC_X
+
+#define SI_0 KC_0
+#define SI_1 KC_1
+#define SI_2 KC_2
+#define SI_3 KC_3
+#define SI_4 KC_4
+#define SI_5 KC_5
+#define SI_6 KC_6
+#define SI_7 KC_7
+#define SI_8 KC_8
+#define SI_9 KC_9
+
+#define SI_DOT KC_DOT
+#define SI_COMM KC_COMM
+
+#define SI_PLUS KC_EQL // + and * and ~
+#define SI_QOT KC_MINS // Single quote
+#define SI_MINS KC_SLSH // - and _
+
+// shifted characters
+#define SI_EXLM LSFT(KC_1) // !
+#define SI_DQOT LSFT(KC_2) // "
+#define SI_HASH LSFT(KC_3) // #
+#define SI_DLR LSFT(KC_4) // $
+#define SI_PERC LSFT(KC_5) // %
+#define SI_AMPR LSFT(KC_6) // &
+#define SI_SLSH LSFT(KC_7) // /
+#define SI_LPRN LSFT(KC_8) // (
+#define SI_RPRN LSFT(KC_9) // )
+#define SI_EQL LSFT(KC_0) // =
+#define SI_QST LSFT(SI_QOT) // ?
+#define SI_ASTR LSFT(SI_PLUS) // *
+#define SI_COLN LSFT(KC_DOT) // :
+#define SI_SCLN LSFT(KC_COMM) // ;
+#define SI_UNDS LSFT(SI_MINS) // _
+
+// Alt Gr-ed characters
+#define SI_CIRC ALGR(KC_3) // ^
+#define SI_DEG ALGR(KC_5) // °
+#define SI_GRV ALGR(KC_7) // `
+#define SI_ACCU ALGR(KC_9) // ´
+#define SI_LCBR ALGR(KC_B) // {
+#define SI_RCBR ALGR(KC_N) // }
+#define SI_LBRC ALGR(KC_F) // [
+#define SI_RBRC ALGR(KC_G) // ]
+#define SI_BSLS ALGR(KC_Q) // backslash
+#define SI_AT ALGR(KC_V) // @
+#define SI_EURO ALGR(KC_E) // €
+#define SI_TILD ALGR(KC_1) // ~
+#define SI_PIPE ALGR(KC_W) // |
+
+#endif
diff --git a/quantum/keymap_extras/keymap_spanish.h b/quantum/keymap_extras/keymap_spanish.h
index 224db7be16..1f183327f9 100644
--- a/quantum/keymap_extras/keymap_spanish.h
+++ b/quantum/keymap_extras/keymap_spanish.h
@@ -18,10 +18,6 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define NO_ALGR KC_RALT
-
// Normal characters
#define ES_OVRR KC_GRV
#define ES_APOS KC_MINS
diff --git a/quantum/keymap_extras/keymap_swedish.h b/quantum/keymap_extras/keymap_swedish.h
index 9044bb74e7..d1a0f4f227 100644
--- a/quantum/keymap_extras/keymap_swedish.h
+++ b/quantum/keymap_extras/keymap_swedish.h
@@ -41,8 +41,8 @@
#define NO_DLR_MAC LSFT(KC_4) // $
#define NO_GRV_MAC ALGR(NO_BSLS) // `
#define NO_GRTR_MAC LSFT(KC_GRV) // >
-#define NO_LCBR_MAC ALGR(LSFT(KC_8)) // }
-#define NO_LESS_MAC KC_GRV // >
+#define NO_LCBR_MAC ALGR(LSFT(KC_8)) // {
+#define NO_LESS_MAC KC_GRV // <
#define NO_PIPE_MAC ALGR(KC_7) // |
#define NO_RCBR_MAC ALGR(LSFT(KC_9)) // }
diff --git a/quantum/keymap_extras/keymap_uk.h b/quantum/keymap_extras/keymap_uk.h
index de47103cb9..cc3d0039e2 100644
--- a/quantum/keymap_extras/keymap_uk.h
+++ b/quantum/keymap_extras/keymap_uk.h
@@ -18,10 +18,6 @@
#include "keymap.h"
-// Alt gr
-#define ALGR(kc) RALT(kc)
-#define NO_ALGR KC_RALT
-
// Normal characters
#define UK_HASH KC_NUHS
#define UK_BSLS KC_NUBS
diff --git a/quantum/keymap_extras/sendstring_german.h b/quantum/keymap_extras/sendstring_german.h
new file mode 100644
index 0000000000..1eaafee317
--- /dev/null
+++ b/quantum/keymap_extras/sendstring_german.h
@@ -0,0 +1,81 @@
+/* Copyright 2018 Patrick Hener
+ *
+ * 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/>.
+ */
+/* Sendstring definitions for the German layout */
+#ifndef SENDSTRING_GERMAN
+#define SENDSTRING_GERMAN
+
+#include "keymap_german.h"
+
+const bool ascii_to_shift_lut[0x80] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 0
+};
+
+/* Until an ALT table/functionality is added, the following symbols will not work:
+* § @ [ ] { } \ ~ äA öÖ ß ´
+* Following characters can be printed using other characters like so:
+* [ in makro will be ü
+* { in makro will be Ü
+* ~ in makro will be °
+*/
+const uint8_t ascii_to_keycode_lut[0x80] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ KC_BSPC, KC_TAB, KC_ENT, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, KC_ESC, 0, 0, 0, 0,
+
+ /* SPACE ! " # $ % & ' */
+ KC_SPC, KC_1, KC_2, DE_HASH, KC_4, KC_5, KC_6, DE_HASH,
+ /* ( ) * + , - . / */
+ KC_8, KC_9, DE_PLUS, DE_PLUS, KC_COMM, DE_MINS, KC_DOT, KC_7,
+ /* 0 1 2 3 4 5 6 7 */
+ KC_0, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7,
+ /* 8 9 : ; < = > ? */
+ KC_8, KC_9, KC_DOT, KC_COMM, DE_LESS, KC_0, DE_LESS, KC_MINS,
+ /* @ A B C D E F G */
+ KC_2, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
+ /* H I J K L M N O */
+ KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
+ /* P Q R S T U V W */
+ KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
+ /* X Y Z [ \ ] ^ _ */
+ KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, DE_CIRC, DE_MINS,
+ /* ` a b c d e f g */
+ DE_ACUT, KC_A, KC_B, KC_C, KC_D, KC_E, KC_F, KC_G,
+ /* h i j k l m n o */
+ KC_H, KC_I, KC_J, KC_K, KC_L, KC_M, KC_N, KC_O,
+ /* p q r s t u v w */
+ KC_P, KC_Q, KC_R, KC_S, KC_T, KC_U, KC_V, KC_W,
+ /* x y z { | } ~ DELETE */
+ KC_X, KC_Y, KC_Z, KC_LBRC, KC_BSLS, KC_RBRC, KC_GRV, KC_DEL
+};
+
+#endif
diff --git a/quantum/matrix.c b/quantum/matrix.c
index 3600d4e7b5..9b5ce33d23 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -1,5 +1,5 @@
/*
-Copyright 2012-2017 Jun Wako, Jack Humbert
+Copyright 2012-2018 Jun Wako, Jack Humbert, Yiancar
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
@@ -16,15 +16,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
-#if defined(__AVR__)
-#include <avr/io.h>
-#endif
#include "wait.h"
#include "print.h"
#include "debug.h"
#include "util.h"
#include "matrix.h"
#include "timer.h"
+#include "quantum.h"
/* Set 0 if debouncing isn't needed */
@@ -60,8 +58,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
#if (DIODE_DIRECTION == ROW2COL) || (DIODE_DIRECTION == COL2ROW)
-static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
-static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
+static const pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
+static const pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
#endif
/* matrix state(1:on, 0:off) */
@@ -271,9 +269,7 @@ uint8_t matrix_key_count(void)
static void init_cols(void)
{
for(uint8_t x = 0; x < MATRIX_COLS; x++) {
- uint8_t pin = col_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(col_pins[x]);
}
}
@@ -293,8 +289,7 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
// Select the col pin to read (active low)
- uint8_t pin = col_pins[col_index];
- uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
+ uint8_t pin_state = readPin(col_pins[col_index]);
// Populate the matrix row with the state of the col pin
current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
@@ -308,24 +303,19 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
static void select_row(uint8_t row)
{
- uint8_t pin = row_pins[row];
- _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
- _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+ setPinOutput(row_pins[row]);
+ writePinLow(row_pins[row]);
}
static void unselect_row(uint8_t row)
{
- uint8_t pin = row_pins[row];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(row_pins[row]);
}
static void unselect_rows(void)
{
for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
- uint8_t pin = row_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInput(row_pins[x]);
}
}
@@ -334,9 +324,7 @@ static void unselect_rows(void)
static void init_rows(void)
{
for(uint8_t x = 0; x < MATRIX_ROWS; x++) {
- uint8_t pin = row_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(row_pins[x]);
}
}
@@ -356,7 +344,7 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
matrix_row_t last_row_value = current_matrix[row_index];
// Check row pin state
- if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
+ if (readPin(row_pins[row_index]) == 0)
{
// Pin LO, set col bit
current_matrix[row_index] |= (ROW_SHIFTER << current_col);
@@ -382,24 +370,19 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
static void select_col(uint8_t col)
{
- uint8_t pin = col_pins[col];
- _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
- _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+ setPinOutput(col_pins[col]);
+ writePinLow(col_pins[col]);
}
static void unselect_col(uint8_t col)
{
- uint8_t pin = col_pins[col];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(col_pins[col]);
}
static void unselect_cols(void)
{
for(uint8_t x = 0; x < MATRIX_COLS; x++) {
- uint8_t pin = col_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(col_pins[x]);
}
}
diff --git a/quantum/process_keycode/process_auto_shift.c b/quantum/process_keycode/process_auto_shift.c
index 01d99445b0..0d0930ee67 100644
--- a/quantum/process_keycode/process_auto_shift.c
+++ b/quantum/process_keycode/process_auto_shift.c
@@ -173,6 +173,8 @@ bool process_auto_shift(uint16_t keycode, keyrecord_t *record) {
case KC_DOT:
case KC_SLSH:
case KC_GRAVE:
+ case KC_NONUS_BSLASH:
+ case KC_NONUS_HASH:
#endif
autoshift_flush();
diff --git a/quantum/process_keycode/process_chording.c b/quantum/process_keycode/process_chording.c
deleted file mode 100644
index 6c6ebe300a..0000000000
--- a/quantum/process_keycode/process_chording.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Copyright 2016 Jack Humbert
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "process_chording.h"
-
-bool keys_chord(uint8_t keys[]) {
- uint8_t keys_size = sizeof(keys)/sizeof(keys[0]);
- bool pass = true;
- uint8_t in = 0;
- for (uint8_t i = 0; i < chord_key_count; i++) {
- bool found = false;
- for (uint8_t j = 0; j < keys_size; j++) {
- if (chord_keys[i] == (keys[j] & 0xFF)) {
- in++; // detects key in chord
- found = true;
- break;
- }
- }
- if (found)
- continue;
- if (chord_keys[i] != 0) {
- pass = false; // makes sure rest are blank
- }
- }
- return (pass && (in == keys_size));
-}
-
-bool process_chording(uint16_t keycode, keyrecord_t *record) {
- if (keycode >= QK_CHORDING && keycode <= QK_CHORDING_MAX) {
- if (record->event.pressed) {
- if (!chording) {
- chording = true;
- for (uint8_t i = 0; i < CHORDING_MAX; i++)
- chord_keys[i] = 0;
- chord_key_count = 0;
- chord_key_down = 0;
- }
- chord_keys[chord_key_count] = (keycode & 0xFF);
- chord_key_count++;
- chord_key_down++;
- return false;
- } else {
- if (chording) {
- chord_key_down--;
- if (chord_key_down == 0) {
- chording = false;
- // Chord Dictionary
- if (keys_chord((uint8_t[]){KC_ENTER, KC_SPACE})) {
- register_code(KC_A);
- unregister_code(KC_A);
- return false;
- }
- for (uint8_t i = 0; i < chord_key_count; i++) {
- register_code(chord_keys[i]);
- unregister_code(chord_keys[i]);
- return false;
- }
- }
- }
- }
- }
- return true;
-}
diff --git a/quantum/process_keycode/process_clicky.c b/quantum/process_keycode/process_clicky.c
index 1e950d1113..8238c263f9 100644
--- a/quantum/process_keycode/process_clicky.c
+++ b/quantum/process_keycode/process_clicky.c
@@ -3,11 +3,6 @@
#ifdef AUDIO_CLICKY
-#ifdef AUDIO_CLICKY_ON
-bool clicky_enable = true;
-#else // AUDIO_CLICKY_ON
-bool clicky_enable = false;
-#endif // AUDIO_CLICKY_ON
#ifndef AUDIO_CLICKY_FREQ_DEFAULT
#define AUDIO_CLICKY_FREQ_DEFAULT 440.0f
#endif // !AUDIO_CLICKY_FREQ_DEFAULT
@@ -25,8 +20,11 @@ bool clicky_enable = false;
#endif // !AUDIO_CLICKY_FREQ_RANDOMNESS
float clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT;
+float clicky_rand = AUDIO_CLICKY_FREQ_RANDOMNESS;
float clicky_song[][2] = {{AUDIO_CLICKY_FREQ_DEFAULT, 3}, {AUDIO_CLICKY_FREQ_DEFAULT, 1}}; // 3 and 1 --> durations
+extern audio_config_t audio_config;
+
#ifndef NO_MUSIC_MODE
extern bool music_activated;
extern bool midi_activated;
@@ -36,31 +34,61 @@ void clicky_play(void) {
#ifndef NO_MUSIC_MODE
if (music_activated || midi_activated) return;
#endif // !NO_MUSIC_MODE
- clicky_song[0][0] = 2.0f * clicky_freq * (1.0f + AUDIO_CLICKY_FREQ_RANDOMNESS * ( ((float)rand()) / ((float)(RAND_MAX)) ) );
- clicky_song[1][0] = clicky_freq * (1.0f + AUDIO_CLICKY_FREQ_RANDOMNESS * ( ((float)rand()) / ((float)(RAND_MAX)) ) );
+ clicky_song[0][0] = 2.0f * clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) );
+ clicky_song[1][0] = clicky_freq * (1.0f + clicky_rand * ( ((float)rand()) / ((float)(RAND_MAX)) ) );
PLAY_SONG(clicky_song);
}
+void clicky_freq_up(void) {
+ float new_freq = clicky_freq * AUDIO_CLICKY_FREQ_FACTOR;
+ if (new_freq < AUDIO_CLICKY_FREQ_MAX) {
+ clicky_freq = new_freq;
+ }
+}
+
+void clicky_freq_down(void) {
+ float new_freq = clicky_freq / AUDIO_CLICKY_FREQ_FACTOR;
+ if (new_freq > AUDIO_CLICKY_FREQ_MIN) {
+ clicky_freq = new_freq;
+ }
+}
+
+void clicky_freq_reset(void) {
+ clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT;
+}
+
+void clicky_toggle(void) {
+ audio_config.clicky_enable ^= 1;
+ eeconfig_update_audio(audio_config.raw);
+}
+
+void clicky_on(void) {
+ audio_config.clicky_enable = 1;
+ eeconfig_update_audio(audio_config.raw);
+}
+
+void clicky_off(void) {
+ audio_config.clicky_enable = 0;
+ eeconfig_update_audio(audio_config.raw);
+}
+
+bool is_clicky_on(void) {
+ return (audio_config.clicky_enable != 0);
+}
+
bool process_clicky(uint16_t keycode, keyrecord_t *record) {
- if (keycode == CLICKY_TOGGLE && record->event.pressed) { clicky_enable = !clicky_enable; }
+ if (keycode == CLICKY_TOGGLE && record->event.pressed) { clicky_toggle(); }
- if (keycode == CLICKY_RESET && record->event.pressed) { clicky_freq = AUDIO_CLICKY_FREQ_DEFAULT; }
+ if (keycode == CLICKY_ENABLE && record->event.pressed) { clicky_on(); }
+ if (keycode == CLICKY_DISABLE && record->event.pressed) { clicky_off(); }
- if (keycode == CLICKY_UP && record->event.pressed) {
- float new_freq = clicky_freq * AUDIO_CLICKY_FREQ_FACTOR;
- if (new_freq < AUDIO_CLICKY_FREQ_MAX) {
- clicky_freq = new_freq;
- }
- }
- if (keycode == CLICKY_DOWN && record->event.pressed) {
- float new_freq = clicky_freq / AUDIO_CLICKY_FREQ_FACTOR;
- if (new_freq > AUDIO_CLICKY_FREQ_MIN) {
- clicky_freq = new_freq;
- }
- }
+ if (keycode == CLICKY_RESET && record->event.pressed) { clicky_freq_reset(); }
+
+ if (keycode == CLICKY_UP && record->event.pressed) { clicky_freq_up(); }
+ if (keycode == CLICKY_DOWN && record->event.pressed) { clicky_freq_down(); }
- if ( clicky_enable ) {
+ if ( audio_config.clicky_enable ) {
if (record->event.pressed) {
clicky_play();;
}
diff --git a/quantum/process_keycode/process_clicky.h b/quantum/process_keycode/process_clicky.h
index e274af56f1..f746edb951 100644
--- a/quantum/process_keycode/process_clicky.h
+++ b/quantum/process_keycode/process_clicky.h
@@ -4,4 +4,14 @@
void clicky_play(void);
bool process_clicky(uint16_t keycode, keyrecord_t *record);
+void clicky_freq_up(void);
+void clicky_freq_down(void);
+void clicky_freq_reset(void);
+
+void clicky_toggle(void);
+void clicky_on(void);
+void clicky_off(void);
+
+bool is_clicky_on(void);
+
#endif
diff --git a/quantum/process_keycode/process_leader.c b/quantum/process_keycode/process_leader.c
index c87ef115af..897e9eabf6 100644
--- a/quantum/process_keycode/process_leader.c
+++ b/quantum/process_keycode/process_leader.c
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DISABLE_LEADER
+#ifdef LEADER_ENABLE
#include "process_leader.h"
@@ -35,25 +35,40 @@ uint16_t leader_time = 0;
uint16_t leader_sequence[5] = {0, 0, 0, 0, 0};
uint8_t leader_sequence_size = 0;
+void qk_leader_start(void) {
+ if (leading) { return; }
+ leader_start();
+ leading = true;
+ leader_time = timer_read();
+ leader_sequence_size = 0;
+ leader_sequence[0] = 0;
+ leader_sequence[1] = 0;
+ leader_sequence[2] = 0;
+ leader_sequence[3] = 0;
+ leader_sequence[4] = 0;
+}
+
bool process_leader(uint16_t keycode, keyrecord_t *record) {
// Leader key set-up
if (record->event.pressed) {
- if (!leading && keycode == KC_LEAD) {
- leader_start();
- leading = true;
- leader_time = timer_read();
- leader_sequence_size = 0;
- leader_sequence[0] = 0;
- leader_sequence[1] = 0;
- leader_sequence[2] = 0;
- leader_sequence[3] = 0;
- leader_sequence[4] = 0;
- return false;
- }
- if (leading && timer_elapsed(leader_time) < LEADER_TIMEOUT) {
- leader_sequence[leader_sequence_size] = keycode;
- leader_sequence_size++;
- return false;
+ if (leading) {
+ if (timer_elapsed(leader_time) < LEADER_TIMEOUT) {
+#ifndef LEADER_KEY_STRICT_KEY_PROCESSING
+ if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) || (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) {
+ keycode = keycode & 0xFF;
+ }
+#endif // LEADER_KEY_STRICT_KEY_PROCESSING
+ leader_sequence[leader_sequence_size] = keycode;
+ leader_sequence_size++;
+#ifdef LEADER_PER_KEY_TIMING
+ leader_time = timer_read();
+#endif
+ return false;
+ }
+ } else {
+ if (keycode == KC_LEAD) {
+ qk_leader_start();
+ }
}
}
return true;
diff --git a/quantum/process_keycode/process_leader.h b/quantum/process_keycode/process_leader.h
index 59c3eed1be..15bccc3f67 100644
--- a/quantum/process_keycode/process_leader.h
+++ b/quantum/process_keycode/process_leader.h
@@ -24,7 +24,7 @@ bool process_leader(uint16_t keycode, keyrecord_t *record);
void leader_start(void);
void leader_end(void);
-
+void qk_leader_start(void);
#define SEQ_ONE_KEY(key) if (leader_sequence[0] == (key) && leader_sequence[1] == 0 && leader_sequence[2] == 0 && leader_sequence[3] == 0 && leader_sequence[4] == 0)
#define SEQ_TWO_KEYS(key1, key2) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == 0 && leader_sequence[3] == 0 && leader_sequence[4] == 0)
diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c
index 8337806912..16d33dddee 100644
--- a/quantum/process_keycode/process_tap_dance.c
+++ b/quantum/process_keycode/process_tap_dance.c
@@ -16,6 +16,10 @@
#include "quantum.h"
#include "action_tapping.h"
+#ifndef TAPPING_TERM
+#define TAPPING_TERM 200
+#endif
+
#ifndef NO_ACTION_ONESHOT
uint8_t get_oneshot_mods(void);
#endif
@@ -127,6 +131,7 @@ void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record) {
if (keycode == action->state.keycode && keycode == last_td)
continue;
action->state.interrupted = true;
+ action->state.interrupting_keycode = keycode;
process_tap_dance_action_on_dance_finished (action);
reset_tap_dance (&action->state);
}
@@ -205,5 +210,6 @@ void reset_tap_dance (qk_tap_dance_state_t *state) {
state->count = 0;
state->interrupted = false;
state->finished = false;
+ state->interrupting_keycode = 0;
last_td = 0;
}
diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h
index 8b0a47c49b..ca12f4746e 100644
--- a/quantum/process_keycode/process_tap_dance.h
+++ b/quantum/process_keycode/process_tap_dance.h
@@ -27,6 +27,7 @@ typedef struct
uint8_t oneshot_mods;
uint8_t weak_mods;
uint16_t keycode;
+ uint16_t interrupting_keycode;
uint16_t timer;
bool interrupted;
bool pressed;
diff --git a/quantum/process_keycode/process_ucis.c b/quantum/process_keycode/process_ucis.c
index 86c0937f5e..5de2e41fc3 100644
--- a/quantum/process_keycode/process_ucis.c
+++ b/quantum/process_keycode/process_ucis.c
@@ -32,6 +32,10 @@ void qk_ucis_start_user(void) {
unicode_input_finish();
}
+__attribute__((weak))
+void qk_ucis_success(uint8_t symbol_index) {
+}
+
static bool is_uni_seq(char *seq) {
uint8_t i;
@@ -142,6 +146,10 @@ bool process_ucis (uint16_t keycode, keyrecord_t *record) {
}
unicode_input_finish();
+ if (symbol_found) {
+ qk_ucis_success(i);
+ }
+
qk_ucis_state.in_progress = false;
return false;
}
diff --git a/quantum/process_keycode/process_ucis.h b/quantum/process_keycode/process_ucis.h
index 3f736a709f..b114d839ab 100644
--- a/quantum/process_keycode/process_ucis.h
+++ b/quantum/process_keycode/process_ucis.h
@@ -14,8 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PROCESS_UCIS_H
-#define PROCESS_UCIS_H
+#pragma once
#include "quantum.h"
#include "process_unicode_common.h"
@@ -45,7 +44,6 @@ extern const qk_ucis_symbol_t ucis_symbol_table[];
void qk_ucis_start(void);
void qk_ucis_start_user(void);
void qk_ucis_symbol_fallback (void);
+void qk_ucis_success(uint8_t symbol_index);
void register_ucis(const char *hex);
bool process_ucis (uint16_t keycode, keyrecord_t *record);
-
-#endif
diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c
index fd008eca12..19beb84520 100644
--- a/quantum/process_keycode/process_unicode.c
+++ b/quantum/process_keycode/process_unicode.c
@@ -17,14 +17,8 @@
#include "action_util.h"
#include "eeprom.h"
-static uint8_t first_flag = 0;
-
bool process_unicode(uint16_t keycode, keyrecord_t *record) {
if (keycode > QK_UNICODE && record->event.pressed) {
- if (first_flag == 0) {
- set_unicode_input_mode(eeprom_read_byte(EECONFIG_UNICODEMODE));
- first_flag = 1;
- }
uint16_t unicode = keycode & 0x7FFF;
unicode_input_start();
register_hex(unicode);
@@ -32,4 +26,3 @@ bool process_unicode(uint16_t keycode, keyrecord_t *record) {
}
return true;
}
-
diff --git a/quantum/process_keycode/process_unicode.h b/quantum/process_keycode/process_unicode.h
index c525b74f03..0913e99107 100644
--- a/quantum/process_keycode/process_unicode.h
+++ b/quantum/process_keycode/process_unicode.h
@@ -13,12 +13,9 @@
* 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 PROCESS_UNICODE_H
-#define PROCESS_UNICODE_H
+#pragma once
#include "quantum.h"
#include "process_unicode_common.h"
bool process_unicode(uint16_t keycode, keyrecord_t *record);
-
-#endif
diff --git a/quantum/process_keycode/process_unicode_common.c b/quantum/process_keycode/process_unicode_common.c
index 7f34ad57cf..3286f45b5d 100644
--- a/quantum/process_keycode/process_unicode_common.c
+++ b/quantum/process_keycode/process_unicode_common.c
@@ -16,94 +16,115 @@
#include "process_unicode_common.h"
#include "eeprom.h"
+#include <ctype.h>
+#include <string.h>
-static uint8_t input_mode;
-uint8_t mods;
+unicode_config_t unicode_config;
+#if UNICODE_SELECTED_MODES != -1
+static uint8_t selected[] = { UNICODE_SELECTED_MODES };
+static uint8_t selected_count = sizeof selected / sizeof *selected;
+static uint8_t selected_index;
+#endif
-void set_unicode_input_mode(uint8_t os_target)
-{
- input_mode = os_target;
- eeprom_update_byte(EECONFIG_UNICODEMODE, os_target);
+void unicode_input_mode_init(void) {
+ unicode_config.raw = eeprom_read_byte(EECONFIG_UNICODEMODE);
+#if UNICODE_SELECTED_MODES != -1
+ #if UNICODE_CYCLE_PERSIST
+ // Find input_mode in selected modes
+ uint8_t i;
+ for (i = 0; i < selected_count; i++) {
+ if (selected[i] == unicode_config.input_mode) {
+ selected_index = i;
+ break;
+ }
+ }
+ if (i == selected_count) {
+ // Not found: input_mode isn't selected, change to one that is
+ unicode_config.input_mode = selected[selected_index = 0];
+ }
+ #else
+ // Always change to the first selected input mode
+ unicode_config.input_mode = selected[selected_index = 0];
+ #endif
+#endif
+ dprintf("Unicode input mode init to: %u\n", unicode_config.input_mode);
}
uint8_t get_unicode_input_mode(void) {
- return input_mode;
+ return unicode_config.input_mode;
}
+void set_unicode_input_mode(uint8_t mode) {
+ unicode_config.input_mode = mode;
+ persist_unicode_input_mode();
+ dprintf("Unicode input mode set to: %u\n", unicode_config.input_mode);
+}
+
+void cycle_unicode_input_mode(uint8_t offset) {
+#if UNICODE_SELECTED_MODES != -1
+ selected_index = (selected_index + offset) % selected_count;
+ unicode_config.input_mode = selected[selected_index];
+ #if UNICODE_CYCLE_PERSIST
+ persist_unicode_input_mode();
+ #endif
+ dprintf("Unicode input mode cycle to: %u\n", unicode_config.input_mode);
+#endif
+}
+
+void persist_unicode_input_mode(void) {
+ eeprom_update_byte(EECONFIG_UNICODEMODE, unicode_config.input_mode);
+}
+
+static uint8_t saved_mods;
+
__attribute__((weak))
-void unicode_input_start (void) {
- // save current mods
- mods = keyboard_report->mods;
-
- // unregister all mods to start from clean state
- if (mods & MOD_BIT(KC_LSFT)) unregister_code(KC_LSFT);
- if (mods & MOD_BIT(KC_RSFT)) unregister_code(KC_RSFT);
- if (mods & MOD_BIT(KC_LCTL)) unregister_code(KC_LCTL);
- if (mods & MOD_BIT(KC_RCTL)) unregister_code(KC_RCTL);
- if (mods & MOD_BIT(KC_LALT)) unregister_code(KC_LALT);
- if (mods & MOD_BIT(KC_RALT)) unregister_code(KC_RALT);
- if (mods & MOD_BIT(KC_LGUI)) unregister_code(KC_LGUI);
- if (mods & MOD_BIT(KC_RGUI)) unregister_code(KC_RGUI);
-
- switch(input_mode) {
+void unicode_input_start(void) {
+ saved_mods = get_mods(); // Save current mods
+ clear_mods(); // Unregister mods to start from a clean state
+
+ switch (unicode_config.input_mode) {
case UC_OSX:
- register_code(KC_LALT);
- break;
- case UC_OSX_RALT:
- register_code(KC_RALT);
+ register_code(UNICODE_OSX_KEY);
break;
case UC_LNX:
register_code(KC_LCTL);
register_code(KC_LSFT);
- register_code(KC_U);
- unregister_code(KC_U);
+ tap_code(KC_U); // TODO: Replace with tap_code16(LCTL(LSFT(KC_U))); and test
unregister_code(KC_LSFT);
unregister_code(KC_LCTL);
break;
case UC_WIN:
register_code(KC_LALT);
- register_code(KC_PPLS);
- unregister_code(KC_PPLS);
+ tap_code(KC_PPLS);
break;
case UC_WINC:
- register_code(KC_RALT);
- unregister_code(KC_RALT);
- register_code(KC_U);
- unregister_code(KC_U);
+ tap_code(UNICODE_WINC_KEY);
+ tap_code(KC_U);
+ break;
}
+
wait_ms(UNICODE_TYPE_DELAY);
}
__attribute__((weak))
-void unicode_input_finish (void) {
- switch(input_mode) {
- case UC_OSX:
- case UC_WIN:
- unregister_code(KC_LALT);
- break;
- case UC_OSX_RALT:
- unregister_code(KC_RALT);
- break;
- case UC_LNX:
- register_code(KC_SPC);
- unregister_code(KC_SPC);
- break;
+void unicode_input_finish(void) {
+ switch (unicode_config.input_mode) {
+ case UC_OSX:
+ unregister_code(UNICODE_OSX_KEY);
+ break;
+ case UC_LNX:
+ tap_code(KC_SPC);
+ break;
+ case UC_WIN:
+ unregister_code(KC_LALT);
+ break;
}
- // reregister previously set mods
- if (mods & MOD_BIT(KC_LSFT)) register_code(KC_LSFT);
- if (mods & MOD_BIT(KC_RSFT)) register_code(KC_RSFT);
- if (mods & MOD_BIT(KC_LCTL)) register_code(KC_LCTL);
- if (mods & MOD_BIT(KC_RCTL)) register_code(KC_RCTL);
- if (mods & MOD_BIT(KC_LALT)) register_code(KC_LALT);
- if (mods & MOD_BIT(KC_RALT)) register_code(KC_RALT);
- if (mods & MOD_BIT(KC_LGUI)) register_code(KC_LGUI);
- if (mods & MOD_BIT(KC_RGUI)) register_code(KC_RGUI);
+ set_mods(saved_mods); // Reregister previously set mods
}
__attribute__((weak))
-uint16_t hex_to_keycode(uint8_t hex)
-{
+uint16_t hex_to_keycode(uint8_t hex) {
if (hex == 0x0) {
return KC_0;
} else if (hex < 0xA) {
@@ -116,7 +137,89 @@ uint16_t hex_to_keycode(uint8_t hex)
void register_hex(uint16_t hex) {
for(int i = 3; i >= 0; i--) {
uint8_t digit = ((hex >> (i*4)) & 0xF);
- register_code(hex_to_keycode(digit));
- unregister_code(hex_to_keycode(digit));
+ tap_code(hex_to_keycode(digit));
+ }
+}
+
+void send_unicode_hex_string(const char *str) {
+ if (!str) { return; }
+
+ while (*str) {
+ // Find the next code point (token) in the string
+ for (; *str == ' '; str++);
+ size_t n = strcspn(str, " "); // Length of the current token
+ char code_point[n+1];
+ strncpy(code_point, str, n);
+ code_point[n] = '\0'; // Make sure it's null-terminated
+
+ // Normalize the code point: make all hex digits lowercase
+ for (char *p = code_point; *p; p++) {
+ *p = tolower((unsigned char)*p);
+ }
+
+ // Send the code point as a Unicode input string
+ unicode_input_start();
+ send_string(code_point);
+ unicode_input_finish();
+
+ str += n; // Move to the first ' ' (or '\0') after the current token
+ }
+}
+
+bool process_unicode_common(uint16_t keycode, keyrecord_t *record) {
+ if (record->event.pressed) {
+ switch (keycode) {
+ case UNICODE_MODE_FORWARD:
+ cycle_unicode_input_mode(+1);
+ break;
+ case UNICODE_MODE_REVERSE:
+ cycle_unicode_input_mode(-1);
+ break;
+
+ case UNICODE_MODE_OSX:
+ set_unicode_input_mode(UC_OSX);
+#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_OSX)
+ static float song_osx[][2] = UNICODE_SONG_OSX;
+ PLAY_SONG(song_osx);
+#endif
+ break;
+ case UNICODE_MODE_LNX:
+ set_unicode_input_mode(UC_LNX);
+#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_LNX)
+ static float song_lnx[][2] = UNICODE_SONG_LNX;
+ PLAY_SONG(song_lnx);
+#endif
+ break;
+ case UNICODE_MODE_WIN:
+ set_unicode_input_mode(UC_WIN);
+#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WIN)
+ static float song_win[][2] = UNICODE_SONG_WIN;
+ PLAY_SONG(song_win);
+#endif
+ break;
+ case UNICODE_MODE_BSD:
+ set_unicode_input_mode(UC_BSD);
+#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_BSD)
+ static float song_bsd[][2] = UNICODE_SONG_BSD;
+ PLAY_SONG(song_bsd);
+#endif
+ break;
+ case UNICODE_MODE_WINC:
+ set_unicode_input_mode(UC_WINC);
+#if defined(AUDIO_ENABLE) && defined(UNICODE_SONG_WINC)
+ static float song_winc[][2] = UNICODE_SONG_WINC;
+ PLAY_SONG(song_winc);
+#endif
+ break;
+ }
}
+#if defined(UNICODE_ENABLE)
+ return process_unicode(keycode, record);
+#elif defined(UNICODEMAP_ENABLE)
+ return process_unicode_map(keycode, record);
+#elif defined(UCIS_ENABLE)
+ return process_ucis(keycode, record);
+#else
+ return true;
+#endif
}
diff --git a/quantum/process_keycode/process_unicode_common.h b/quantum/process_keycode/process_unicode_common.h
index 4d2b04fb39..e608ab76be 100644
--- a/quantum/process_keycode/process_unicode_common.h
+++ b/quantum/process_keycode/process_unicode_common.h
@@ -14,33 +14,71 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PROCESS_UNICODE_COMMON_H
-#define PROCESS_UNICODE_COMMON_H
+#pragma once
#include "quantum.h"
-#ifndef UNICODE_TYPE_DELAY
-#define UNICODE_TYPE_DELAY 10
+#if defined(UNICODE_ENABLE) + defined(UNICODEMAP_ENABLE) + defined(UCIS_ENABLE) > 1
+ #error "Cannot enable more than one Unicode method (UNICODE, UNICODEMAP, UCIS) at the same time"
+#endif
+
+// Keycodes used for starting Unicode input on different platforms
+#ifndef UNICODE_OSX_KEY
+ #define UNICODE_OSX_KEY KC_LALT
+#endif
+#ifndef UNICODE_WINC_KEY
+ #define UNICODE_WINC_KEY KC_RALT
#endif
-__attribute__ ((unused))
-static uint8_t input_mode;
+// Comma-delimited, ordered list of input modes selected for use (e.g. in cycle)
+// Example: #define UNICODE_SELECTED_MODES UC_WINC, UC_LNX
+#ifndef UNICODE_SELECTED_MODES
+ #define UNICODE_SELECTED_MODES -1
+#endif
+
+// Whether input mode changes in cycle should be written to EEPROM
+#ifndef UNICODE_CYCLE_PERSIST
+ #define UNICODE_CYCLE_PERSIST true
+#endif
-void set_unicode_input_mode(uint8_t os_target);
+// Delay between starting Unicode input and sending a sequence, in ms
+#ifndef UNICODE_TYPE_DELAY
+ #define UNICODE_TYPE_DELAY 10
+#endif
+
+enum unicode_input_modes {
+ UC_OSX, // Mac OS X using Unicode Hex Input
+ UC_LNX, // Linux using IBus
+ UC_WIN, // Windows using EnableHexNumpad
+ UC_BSD, // BSD (not implemented)
+ UC_WINC, // Windows using WinCompose (https://github.com/samhocevar/wincompose)
+ UC__COUNT // Number of available input modes (always leave at the end)
+};
+
+typedef union {
+ uint32_t raw;
+ struct {
+ uint8_t input_mode : 8;
+ };
+} unicode_config_t;
+
+extern unicode_config_t unicode_config;
+
+void unicode_input_mode_init(void);
uint8_t get_unicode_input_mode(void);
+void set_unicode_input_mode(uint8_t mode);
+void cycle_unicode_input_mode(uint8_t offset);
+void persist_unicode_input_mode(void);
+
void unicode_input_start(void);
void unicode_input_finish(void);
+
void register_hex(uint16_t hex);
+void send_unicode_hex_string(const char *str);
-#define UC_OSX 0 // Mac OS X
-#define UC_LNX 1 // Linux
-#define UC_WIN 2 // Windows 'HexNumpad'
-#define UC_BSD 3 // BSD (not implemented)
-#define UC_WINC 4 // WinCompose https://github.com/samhocevar/wincompose
-#define UC_OSX_RALT 5 // Mac OS X using Right Alt key for Unicode Compose
+bool process_unicode_common(uint16_t keycode, keyrecord_t *record);
#define UC_BSPC UC(0x0008)
-
#define UC_SPC UC(0x0020)
#define UC_EXLM UC(0x0021)
@@ -145,5 +183,3 @@ void register_hex(uint16_t hex);
#define UC_RCBR UC(0x007D)
#define UC_TILD UC(0x007E)
#define UC_DEL UC(0x007F)
-
-#endif
diff --git a/quantum/process_keycode/process_unicodemap.c b/quantum/process_keycode/process_unicodemap.c
index 47c27b9117..75f35112b1 100644
--- a/quantum/process_keycode/process_unicodemap.c
+++ b/quantum/process_keycode/process_unicodemap.c
@@ -50,7 +50,7 @@ bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
const uint32_t* map = unicode_map;
uint16_t index = keycode - QK_UNICODE_MAP;
uint32_t code = pgm_read_dword(&map[index]);
- if (code > 0xFFFF && code <= 0x10ffff && (input_mode == UC_OSX || input_mode == UC_OSX_RALT)) {
+ if (code > 0xFFFF && code <= 0x10ffff && input_mode == UC_OSX) {
// Convert to UTF-16 surrogate pair
code -= 0x10000;
uint32_t lo = code & 0x3ff;
@@ -59,7 +59,7 @@ bool process_unicode_map(uint16_t keycode, keyrecord_t *record) {
register_hex32(hi + 0xd800);
register_hex32(lo + 0xdc00);
unicode_input_finish();
- } else if ((code > 0x10ffff && (input_mode == UC_OSX || input_mode == UC_OSX_RALT)) || (code > 0xFFFFF && input_mode == UC_LNX)) {
+ } else if ((code > 0x10ffff && input_mode == UC_OSX) || (code > 0xFFFFF && input_mode == UC_LNX)) {
// when character is out of range supported by the OS
unicode_map_input_error();
} else {
diff --git a/quantum/process_keycode/process_unicodemap.h b/quantum/process_keycode/process_unicodemap.h
index 929c88c0b6..f6d64bb86b 100644
--- a/quantum/process_keycode/process_unicodemap.h
+++ b/quantum/process_keycode/process_unicodemap.h
@@ -14,12 +14,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PROCESS_UNICODEMAP_H
-#define PROCESS_UNICODEMAP_H
+#pragma once
#include "quantum.h"
#include "process_unicode_common.h"
void unicode_map_input_error(void);
bool process_unicode_map(uint16_t keycode, keyrecord_t *record);
-#endif
diff --git a/quantum/quantum.c b/quantum/quantum.c
index ab47fa48ff..85db100ab4 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -42,6 +42,11 @@ extern backlight_config_t backlight_config;
#include "process_midi.h"
#endif
+
+#ifdef ENCODER_ENABLE
+#include "encoder.h"
+#endif
+
#ifdef AUDIO_ENABLE
#ifndef GOODBYE_SONG
#define GOODBYE_SONG SONG(GOODBYE_SOUND)
@@ -127,6 +132,14 @@ void unregister_code16 (uint16_t code) {
}
}
+void tap_code16(uint16_t code) {
+ register_code16(code);
+ #if TAP_CODE_DELAY > 0
+ wait_ms(TAP_CODE_DELAY);
+ #endif
+ unregister_code16(code);
+}
+
__attribute__ ((weak))
bool process_action_kb(keyrecord_t *record) {
return true;
@@ -196,7 +209,7 @@ bool process_record_quantum(keyrecord_t *record) {
keypos_t key = record->event.key;
uint16_t keycode;
- #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+ #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
/* TODO: Use store_or_get_action() or a similar function. */
if (!disable_action_cache) {
uint8_t layer;
@@ -230,7 +243,7 @@ bool process_record_quantum(keyrecord_t *record) {
process_key_lock(&keycode, record) &&
#endif
#if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY)
- process_clicky(keycode, record) &&
+ process_clicky(keycode, record) &&
#endif //AUDIO_CLICKY
process_record_kb(keycode, record) &&
#if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_KEYPRESSES)
@@ -245,36 +258,27 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef STENO_ENABLE
process_steno(keycode, record) &&
#endif
- #if ( defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE)
+ #if (defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))) && !defined(NO_MUSIC_MODE)
process_music(keycode, record) &&
#endif
#ifdef TAP_DANCE_ENABLE
process_tap_dance(keycode, record) &&
#endif
- #ifndef DISABLE_LEADER
- process_leader(keycode, record) &&
+ #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
+ process_unicode_common(keycode, record) &&
#endif
- #ifndef DISABLE_CHORDING
- process_chording(keycode, record) &&
+ #ifdef LEADER_ENABLE
+ process_leader(keycode, record) &&
#endif
#ifdef COMBO_ENABLE
process_combo(keycode, record) &&
#endif
- #ifdef UNICODE_ENABLE
- process_unicode(keycode, record) &&
- #endif
- #ifdef UCIS_ENABLE
- process_ucis(keycode, record) &&
- #endif
#ifdef PRINTING_ENABLE
process_printer(keycode, record) &&
#endif
#ifdef AUTO_SHIFT_ENABLE
process_auto_shift(keycode, record) &&
#endif
- #ifdef UNICODEMAP_ENABLE
- process_unicode_map(keycode, record) &&
- #endif
#ifdef TERMINAL_ENABLE
process_terminal(keycode, record) &&
#endif
@@ -296,6 +300,11 @@ bool process_record_quantum(keyrecord_t *record) {
print("DEBUG: enabled.\n");
}
return false;
+ case EEPROM_RESET:
+ if (record->event.pressed) {
+ eeconfig_init();
+ }
+ return false;
#ifdef FAUXCLICKY_ENABLE
case FC_TOG:
if (record->event.pressed) {
@@ -445,75 +454,97 @@ bool process_record_quantum(keyrecord_t *record) {
return false;
case RGB_MODE_PLAIN:
if (record->event.pressed) {
- rgblight_mode(1);
+ rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
#ifdef SPLIT_KEYBOARD
RGB_DIRTY = true;
#endif
}
return false;
case RGB_MODE_BREATHE:
+ #ifdef RGBLIGHT_EFFECT_BREATHING
if (record->event.pressed) {
- if ((2 <= rgblight_get_mode()) && (rgblight_get_mode() < 5)) {
+ if ((RGBLIGHT_MODE_BREATHING <= rgblight_get_mode()) &&
+ (rgblight_get_mode() < RGBLIGHT_MODE_BREATHING_end)) {
rgblight_step();
} else {
- rgblight_mode(2);
+ rgblight_mode(RGBLIGHT_MODE_BREATHING);
}
}
+ #endif
return false;
case RGB_MODE_RAINBOW:
+ #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
if (record->event.pressed) {
- if ((6 <= rgblight_get_mode()) && (rgblight_get_mode() < 8)) {
+ if ((RGBLIGHT_MODE_RAINBOW_MOOD <= rgblight_get_mode()) &&
+ (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_MOOD_end)) {
rgblight_step();
} else {
- rgblight_mode(6);
+ rgblight_mode(RGBLIGHT_MODE_RAINBOW_MOOD);
}
}
+ #endif
return false;
case RGB_MODE_SWIRL:
+ #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
if (record->event.pressed) {
- if ((9 <= rgblight_get_mode()) && (rgblight_get_mode() < 14)) {
+ if ((RGBLIGHT_MODE_RAINBOW_SWIRL <= rgblight_get_mode()) &&
+ (rgblight_get_mode() < RGBLIGHT_MODE_RAINBOW_SWIRL_end)) {
rgblight_step();
} else {
- rgblight_mode(9);
+ rgblight_mode(RGBLIGHT_MODE_RAINBOW_SWIRL);
}
}
+ #endif
return false;
case RGB_MODE_SNAKE:
+ #ifdef RGBLIGHT_EFFECT_SNAKE
if (record->event.pressed) {
- if ((15 <= rgblight_get_mode()) && (rgblight_get_mode() < 20)) {
+ if ((RGBLIGHT_MODE_SNAKE <= rgblight_get_mode()) &&
+ (rgblight_get_mode() < RGBLIGHT_MODE_SNAKE_end)) {
rgblight_step();
} else {
- rgblight_mode(15);
+ rgblight_mode(RGBLIGHT_MODE_SNAKE);
}
}
+ #endif
return false;
case RGB_MODE_KNIGHT:
+ #ifdef RGBLIGHT_EFFECT_KNIGHT
if (record->event.pressed) {
- if ((21 <= rgblight_get_mode()) && (rgblight_get_mode() < 23)) {
+ if ((RGBLIGHT_MODE_KNIGHT <= rgblight_get_mode()) &&
+ (rgblight_get_mode() < RGBLIGHT_MODE_KNIGHT_end)) {
rgblight_step();
} else {
- rgblight_mode(21);
+ rgblight_mode(RGBLIGHT_MODE_KNIGHT);
}
}
+ #endif
return false;
case RGB_MODE_XMAS:
+ #ifdef RGBLIGHT_EFFECT_CHRISTMAS
if (record->event.pressed) {
- rgblight_mode(24);
+ rgblight_mode(RGBLIGHT_MODE_CHRISTMAS);
}
+ #endif
return false;
case RGB_MODE_GRADIENT:
+ #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
if (record->event.pressed) {
- if ((25 <= rgblight_get_mode()) && (rgblight_get_mode() < 34)) {
+ if ((RGBLIGHT_MODE_STATIC_GRADIENT <= rgblight_get_mode()) &&
+ (rgblight_get_mode() < RGBLIGHT_MODE_STATIC_GRADIENT_end)) {
rgblight_step();
} else {
- rgblight_mode(25);
+ rgblight_mode(RGBLIGHT_MODE_STATIC_GRADIENT);
}
}
+ #endif
return false;
case RGB_MODE_RGBTEST:
+ #ifdef RGBLIGHT_EFFECT_RGB_TEST
if (record->event.pressed) {
- rgblight_mode(35);
+ rgblight_mode(RGBLIGHT_MODE_RGB_TEST);
}
+ #endif
return false;
#endif // defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
#ifdef PROTOCOL_LUFA
@@ -607,6 +638,17 @@ bool process_record_quantum(keyrecord_t *record) {
PLAY_SONG(ag_norm_song);
#endif
break;
+ case MAGIC_TOGGLE_ALT_GUI:
+ keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
+ keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
+ #ifdef AUDIO_ENABLE
+ if (keymap_config.swap_ralt_rgui) {
+ PLAY_SONG(ag_swap_song);
+ } else {
+ PLAY_SONG(ag_norm_song);
+ }
+ #endif
+ break;
case MAGIC_TOGGLE_NKRO:
keymap_config.nkro = !keymap_config.nkro;
break;
@@ -914,7 +956,42 @@ void tap_random_base64(void) {
}
}
+__attribute__((weak))
+void bootmagic_lite(void) {
+ // The lite version of TMK's bootmagic based on Wilba.
+ // 100% less potential for accidentally making the
+ // keyboard do stupid things.
+
+ // We need multiple scans because debouncing can't be turned off.
+ matrix_scan();
+ #if defined(DEBOUNCING_DELAY) && DEBOUNCING_DELAY > 0
+ wait_ms(DEBOUNCING_DELAY * 2);
+ #elif defined(DEBOUNCE) && DEBOUNCE > 0
+ wait_ms(DEBOUNCE * 2);
+ #else
+ wait_ms(30);
+ #endif
+ matrix_scan();
+
+ // If the Esc and space bar are held down on power up,
+ // reset the EEPROM valid state and jump to bootloader.
+ // Assumes Esc is at [0,0].
+ // This isn't very generalized, but we need something that doesn't
+ // rely on user's keymaps in firmware or EEPROM.
+ if (matrix_get_row(BOOTMAGIC_LITE_ROW) & (1 << BOOTMAGIC_LITE_COLUMN)) {
+ eeconfig_disable();
+ // Jump to bootloader.
+ bootloader_jump();
+ }
+}
+
void matrix_init_quantum() {
+ #ifdef BOOTMAGIC_LITE
+ bootmagic_lite();
+ #endif
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
#ifdef BACKLIGHT_ENABLE
backlight_init_ports();
#endif
@@ -924,6 +1001,12 @@ void matrix_init_quantum() {
#ifdef RGB_MATRIX_ENABLE
rgb_matrix_init();
#endif
+ #ifdef ENCODER_ENABLE
+ encoder_init();
+ #endif
+ #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
+ unicode_input_mode_init();
+ #endif
matrix_init_kb();
}
@@ -958,6 +1041,10 @@ void matrix_scan_quantum() {
rgb_matrix_task_counter = ((rgb_matrix_task_counter + 1) % (RGB_MATRIX_SKIP_FRAMES + 1));
#endif
+ #ifdef ENCODER_ENABLE
+ encoder_read();
+ #endif
+
matrix_scan_kb();
}
#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 1db9846f04..f78915fdfb 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -1,4 +1,4 @@
-/* Copyright 2016-2017 Erez Zukerman, Jack Humbert
+/* Copyright 2016-2018 Erez Zukerman, Jack Humbert, Yiancar
*
* 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
@@ -17,9 +17,12 @@
#define QUANTUM_H
#if defined(__AVR__)
-#include <avr/pgmspace.h>
-#include <avr/io.h>
-#include <avr/interrupt.h>
+ #include <avr/pgmspace.h>
+ #include <avr/io.h>
+ #include <avr/interrupt.h>
+#endif
+#if defined(PROTOCOL_CHIBIOS)
+ #include "hal.h"
#endif
#include "wait.h"
#include "matrix.h"
@@ -32,6 +35,12 @@
#endif
#ifdef RGBLIGHT_ENABLE
#include "rgblight.h"
+#else
+ #ifdef RGB_MATRIX_ENABLE
+ /* dummy define RGBLIGHT_MODE_xxxx */
+ #define RGBLIGHT_H_DUMMY_DEFINE
+ #include "rgblight.h"
+ #endif
#endif
#ifdef SPLIT_KEYBOARD
@@ -39,7 +48,7 @@
#endif
#ifdef RGB_MATRIX_ENABLE
- #include "rgb_matrix.h"
+ #include "rgb_matrix.h"
#endif
#include "action_layer.h"
@@ -58,78 +67,119 @@
extern uint32_t default_layer_state;
#ifndef NO_ACTION_LAYER
- extern uint32_t layer_state;
+ extern uint32_t layer_state;
#endif
#ifdef MIDI_ENABLE
#ifdef MIDI_ADVANCED
- #include "process_midi.h"
+ #include "process_midi.h"
#endif
#endif // MIDI_ENABLE
#ifdef AUDIO_ENABLE
- #include "audio.h"
- #include "process_audio.h"
- #ifdef AUDIO_CLICKY
- #include "process_clicky.h"
- #endif // AUDIO_CLICKY
+ #include "audio.h"
+ #include "process_audio.h"
+ #ifdef AUDIO_CLICKY
+ #include "process_clicky.h"
+ #endif // AUDIO_CLICKY
#endif
#ifdef STENO_ENABLE
- #include "process_steno.h"
+ #include "process_steno.h"
#endif
#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
- #include "process_music.h"
-#endif
-
-#ifndef DISABLE_LEADER
- #include "process_leader.h"
+ #include "process_music.h"
#endif
-#define DISABLE_CHORDING
-#ifndef DISABLE_CHORDING
- #include "process_chording.h"
+#ifdef LEADER_ENABLE
+ #include "process_leader.h"
#endif
#ifdef UNICODE_ENABLE
- #include "process_unicode.h"
+ #include "process_unicode.h"
#endif
#ifdef UCIS_ENABLE
- #include "process_ucis.h"
+ #include "process_ucis.h"
#endif
#ifdef UNICODEMAP_ENABLE
- #include "process_unicodemap.h"
+ #include "process_unicodemap.h"
#endif
-#include "process_tap_dance.h"
+#ifdef TAP_DANCE_ENABLE
+ #include "process_tap_dance.h"
+#endif
#ifdef PRINTING_ENABLE
- #include "process_printer.h"
+ #include "process_printer.h"
#endif
#ifdef AUTO_SHIFT_ENABLE
- #include "process_auto_shift.h"
+ #include "process_auto_shift.h"
#endif
#ifdef COMBO_ENABLE
- #include "process_combo.h"
+ #include "process_combo.h"
#endif
#ifdef KEY_LOCK_ENABLE
- #include "process_key_lock.h"
+ #include "process_key_lock.h"
#endif
#ifdef TERMINAL_ENABLE
- #include "process_terminal.h"
+ #include "process_terminal.h"
#else
- #include "process_terminal_nop.h"
+ #include "process_terminal_nop.h"
#endif
#ifdef HD44780_ENABLE
- #include "hd44780.h"
+ #include "hd44780.h"
+#endif
+
+//Function substitutions to ease GPIO manipulation
+#ifdef __AVR__
+ #define PIN_ADDRESS(p, offset) _SFR_IO8(ADDRESS_BASE + (p >> PORT_SHIFTER) + offset)
+
+ #define pin_t uint8_t
+ #define setPinInput(pin) PIN_ADDRESS(pin, 1) &= ~ _BV(pin & 0xF)
+ #define setPinInputHigh(pin) ({\
+ PIN_ADDRESS(pin, 1) &= ~ _BV(pin & 0xF);\
+ PIN_ADDRESS(pin, 2) |= _BV(pin & 0xF);\
+ })
+ #define setPinInputLow(pin) _Static_assert(0, "AVR Processors cannot impliment an input as pull low")
+ #define setPinOutput(pin) PIN_ADDRESS(pin, 1) |= _BV(pin & 0xF)
+
+ #define writePinHigh(pin) PIN_ADDRESS(pin, 2) |= _BV(pin & 0xF)
+ #define writePinLow(pin) PIN_ADDRESS(pin, 2) &= ~_BV(pin & 0xF)
+ static inline void writePin(pin_t pin, uint8_t level){
+ if (level){
+ PIN_ADDRESS(pin, 2) |= _BV(pin & 0xF);
+ } else {
+ PIN_ADDRESS(pin, 2) &= ~_BV(pin & 0xF);
+ }
+ }
+
+ #define readPin(pin) ((bool)(PIN_ADDRESS(pin, 0) & _BV(pin & 0xF)))
+#elif defined(PROTOCOL_CHIBIOS)
+ #define pin_t ioline_t
+ #define setPinInput(pin) palSetLineMode(pin, PAL_MODE_INPUT)
+ #define setPinInputHigh(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLUP)
+ #define setPinInputLow(pin) palSetLineMode(pin, PAL_MODE_INPUT_PULLDOWN)
+ #define setPinOutput(pin) palSetLineMode(pin, PAL_MODE_OUTPUT_PUSHPULL)
+
+ #define writePinHigh(pin) palSetLine(pin)
+ #define writePinLow(pin) palClearLine(pin)
+ static inline void writePin(pin_t pin, uint8_t level){
+ if (level){
+ palSetLine(pin);
+ } else {
+ palClearLine(pin);
+ }
+ }
+
+ #define readPin(pin) palReadLine(pin)
#endif
#define STRINGIZE(z) #z
@@ -147,6 +197,7 @@ extern uint32_t default_layer_state;
#define SS_LALT(string) SS_DOWN(X_LALT) string SS_UP(X_LALT)
#define SS_LSFT(string) SS_DOWN(X_LSHIFT) string SS_UP(X_LSHIFT)
#define SS_RALT(string) SS_DOWN(X_RALT) string SS_UP(X_RALT)
+#define SS_ALGR(string) SS_RALT(string)
#define SEND_STRING(str) send_string_P(PSTR(str))
extern const bool ascii_to_shift_lut[0x80];
@@ -176,13 +227,23 @@ bool process_action_kb(keyrecord_t *record);
bool process_record_kb(uint16_t keycode, keyrecord_t *record);
bool process_record_user(uint16_t keycode, keyrecord_t *record);
+#ifndef BOOTMAGIC_LITE_COLUMN
+ #define BOOTMAGIC_LITE_COLUMN 0
+#endif
+#ifndef BOOTMAGIC_LITE_ROW
+ #define BOOTMAGIC_LITE_ROW 0
+#endif
+
+void bootmagic_lite(void);
+
void reset_keyboard(void);
void startup_user(void);
void shutdown_user(void);
-void register_code16 (uint16_t code);
-void unregister_code16 (uint16_t code);
+void register_code16(uint16_t code);
+void unregister_code16(uint16_t code);
+void tap_code16(uint16_t code);
#ifdef BACKLIGHT_ENABLE
void backlight_init_ports(void);
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index f2cdb8a3bf..2b309f4d52 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -63,10 +63,6 @@ enum quantum_keycodes {
QK_ONE_SHOT_LAYER_MAX = 0x54FF,
QK_ONE_SHOT_MOD = 0x5500,
QK_ONE_SHOT_MOD_MAX = 0x55FF,
-#ifndef DISABLE_CHORDING
- QK_CHORDING = 0x5600,
- QK_CHORDING_MAX = 0x56FF,
-#endif
QK_TAP_DANCE = 0x5700,
QK_TAP_DANCE_MAX = 0x57FF,
QK_LAYER_TAP_TOGGLE = 0x5800,
@@ -85,9 +81,6 @@ enum quantum_keycodes {
#endif
QK_MOD_TAP = 0x6000,
QK_MOD_TAP_MAX = 0x7FFF,
-#if defined(UNICODEMAP_ENABLE) && defined(UNICODE_ENABLE)
- #error "Cannot enable both UNICODEMAP && UNICODE"
-#endif
#ifdef UNICODE_ENABLE
QK_UNICODE = 0x8000,
QK_UNICODE_MAX = 0xFFFF,
@@ -120,10 +113,11 @@ enum quantum_keycodes {
MAGIC_UNHOST_NKRO,
MAGIC_UNSWAP_ALT_GUI,
MAGIC_TOGGLE_NKRO,
+ MAGIC_TOGGLE_ALT_GUI,
GRAVE_ESC,
// Leader key
-#ifndef DISABLE_LEADER
+#ifdef LEADER_ENABLE
KC_LEAD,
#endif
@@ -142,10 +136,13 @@ enum quantum_keycodes {
// Faux clicky as part of main audio feature
CLICKY_TOGGLE,
+ CLICKY_ENABLE,
+ CLICKY_DISABLE,
CLICKY_UP,
CLICKY_DOWN,
CLICKY_RESET,
+
#ifdef FAUXCLICKY_ENABLE
// Faux clicky
FC_ON,
@@ -454,32 +451,43 @@ enum quantum_keycodes {
TERM_OFF,
#endif
+ EEPROM_RESET,
+
+ UNICODE_MODE_FORWARD,
+ UNICODE_MODE_REVERSE,
+
+ UNICODE_MODE_OSX,
+ UNICODE_MODE_LNX,
+ UNICODE_MODE_WIN,
+ UNICODE_MODE_BSD,
+ UNICODE_MODE_WINC,
+
// always leave at the end
SAFE_RANGE
};
// Ability to use mods in layouts
-#define LCTL(kc) (kc | QK_LCTL)
-#define LSFT(kc) (kc | QK_LSFT)
-#define LALT(kc) (kc | QK_LALT)
-#define LGUI(kc) (kc | QK_LGUI)
+#define LCTL(kc) (QK_LCTL | (kc))
+#define LSFT(kc) (QK_LSFT | (kc))
+#define LALT(kc) (QK_LALT | (kc))
+#define LGUI(kc) (QK_LGUI | (kc))
#define LCMD(kc) LGUI(kc)
#define LWIN(kc) LGUI(kc)
-#define RCTL(kc) (kc | QK_RCTL)
-#define RSFT(kc) (kc | QK_RSFT)
-#define RALT(kc) (kc | QK_RALT)
-#define RGUI(kc) (kc | QK_RGUI)
+#define RCTL(kc) (QK_RCTL | (kc))
+#define RSFT(kc) (QK_RSFT | (kc))
+#define RALT(kc) (QK_RALT | (kc))
+#define ALGR(kc) RALT(kc)
+#define RGUI(kc) (QK_RGUI | (kc))
#define RCMD(kc) RGUI(kc)
#define RWIN(kc) RGUI(kc)
-#define HYPR(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI)
-#define MEH(kc) (kc | QK_LCTL | QK_LSFT | QK_LALT)
-#define LCAG(kc) (kc | QK_LCTL | QK_LALT | QK_LGUI)
-#define ALTG(kc) (kc | QK_RCTL | QK_RALT)
-#define SGUI(kc) (kc | QK_LGUI | QK_LSFT)
+#define HYPR(kc) (QK_LCTL | QK_LSFT | QK_LALT | QK_LGUI | (kc))
+#define MEH(kc) (QK_LCTL | QK_LSFT | QK_LALT | (kc))
+#define LCAG(kc) (QK_LCTL | QK_LALT | QK_LGUI | (kc))
+#define SGUI(kc) (QK_LGUI | QK_LSFT | (kc))
#define SCMD(kc) SGUI(kc)
#define SWIN(kc) SGUI(kc)
-#define LCA(kc) (kc | QK_LCTL | QK_LALT)
+#define LCA(kc) (QK_LCTL | QK_LALT | (kc))
#define MOD_HYPR 0xf
#define MOD_MEH 0x7
@@ -557,26 +565,29 @@ enum quantum_keycodes {
#define KC_DELT KC_DELETE // Del key (four letter code)
// Alias for function layers than expand past FN31
-#define FUNC(kc) (kc | QK_FUNCTION)
+#define FUNC(kc) (QK_FUNCTION | (kc))
// Aliases
#define S(kc) LSFT(kc)
#define F(kc) FUNC(kc)
-#define M(kc) (kc | QK_MACRO)
+#define M(kc) (QK_MACRO | (kc))
-#define MACROTAP(kc) (kc | QK_MACRO | FUNC_TAP<<8)
+#define MACROTAP(kc) (QK_MACRO | (FUNC_TAP << 8) | (kc))
#define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE)
#define KC_GESC GRAVE_ESC
+#define EEP_RST EEPROM_RESET
+
#define CK_TOGG CLICKY_TOGGLE
#define CK_RST CLICKY_RESET
#define CK_UP CLICKY_UP
#define CK_DOWN CLICKY_DOWN
+#define CK_ON CLICKY_ENABLE
+#define CK_OFF CLICKY_DISABLE
#define RGB_MOD RGB_MODE_FORWARD
-#define RGB_SMOD RGB_MODE_FORWARD
#define RGB_RMOD RGB_MODE_REVERSE
#define RGB_M_P RGB_MODE_PLAIN
@@ -590,10 +601,11 @@ enum quantum_keycodes {
#define RGB_M_T RGB_MODE_RGBTEST
// L-ayer, T-ap - 256 keycode max, 16 layer max
-#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
+#define LT(layer, kc) (QK_LAYER_TAP | ((layer & 0xF) << 8) | ((kc) & 0xFF))
#define AG_SWAP MAGIC_SWAP_ALT_GUI
#define AG_NORM MAGIC_UNSWAP_ALT_GUI
+#define AG_TOGG MAGIC_TOGGLE_ALT_GUI
// GOTO layer - 16 layers max
// when:
@@ -602,32 +614,32 @@ enum quantum_keycodes {
// Unless you have a good reason not to do so, prefer ON_PRESS (1) as your default.
// In fact, we changed it to assume ON_PRESS for sanity/simplicity. If needed, you can add your own
// keycode modeled after the old version, kept below for this.
-/* #define TO(layer, when) (layer | QK_TO | (when << 0x4)) */
-#define TO(layer) (layer | QK_TO | (ON_PRESS << 0x4))
+/* #define TO(layer, when) (QK_TO | (when << 0x4) | (layer & 0xFF)) */
+#define TO(layer) (QK_TO | (ON_PRESS << 0x4) | (layer & 0xFF))
// Momentary switch layer - 256 layer max
-#define MO(layer) (layer | QK_MOMENTARY)
+#define MO(layer) (QK_MOMENTARY | (layer & 0xFF))
// Set default layer - 256 layer max
-#define DF(layer) (layer | QK_DEF_LAYER)
+#define DF(layer) (QK_DEF_LAYER | (layer & 0xFF))
// Toggle to layer - 256 layer max
-#define TG(layer) (layer | QK_TOGGLE_LAYER)
+#define TG(layer) (QK_TOGGLE_LAYER | (layer & 0xFF))
// One-shot layer - 256 layer max
-#define OSL(layer) (layer | QK_ONE_SHOT_LAYER)
+#define OSL(layer) (QK_ONE_SHOT_LAYER | (layer & 0xFF))
// L-ayer M-od: Momentary switch layer with modifiers active - 16 layer max, left mods only
-#define LM(layer, mod) (QK_LAYER_MOD | (((layer) & 0xF) << 4) | ((mod) & 0xF))
+#define LM(layer, mod) (QK_LAYER_MOD | ((layer & 0xF) << 4) | ((mod) & 0xF))
// One-shot mod
-#define OSM(mod) ((mod) | QK_ONE_SHOT_MOD)
+#define OSM(mod) (QK_ONE_SHOT_MOD | ((mod) & 0xFF))
// Layer tap-toggle
-#define TT(layer) (layer | QK_LAYER_TAP_TOGGLE)
+#define TT(layer) (QK_LAYER_TAP_TOGGLE | (layer & 0xFF))
// M-od, T-ap - 256 keycode max
-#define MT(mod, kc) (kc | QK_MOD_TAP | (((mod) & 0x1F) << 8))
+#define MT(mod, kc) (QK_MOD_TAP | (((mod) & 0x1F) << 8) | ((kc) & 0xFF))
#define CTL_T(kc) MT(MOD_LCTL, kc)
#define LCTL_T(kc) MT(MOD_LCTL, kc)
@@ -640,7 +652,7 @@ enum quantum_keycodes {
#define ALT_T(kc) MT(MOD_LALT, kc)
#define LALT_T(kc) MT(MOD_LALT, kc)
#define RALT_T(kc) MT(MOD_RALT, kc)
-#define ALGR_T(kc) MT(MOD_RALT, kc) // dual-function AltGR
+#define ALGR_T(kc) RALT_T(kc)
#define GUI_T(kc) MT(MOD_LGUI, kc)
#define CMD_T(kc) GUI_T(kc)
@@ -652,15 +664,15 @@ enum quantum_keycodes {
#define RCMD_T(kc) RGUI_T(kc)
#define RWIN_T(kc) RGUI_T(kc)
-#define C_S_T(kc) MT((MOD_LCTL | MOD_LSFT), kc) // Control + Shift e.g. for gnome-terminal
-#define MEH_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT), kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
-#define LCAG_T(kc) MT((MOD_LCTL | MOD_LALT | MOD_LGUI), kc) // Left control alt and gui
-#define RCAG_T(kc) MT((MOD_RCTL | MOD_RALT | MOD_RGUI), kc) // Right control alt and gui
-#define ALL_T(kc) MT((MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI), kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
-#define SGUI_T(kc) MT((MOD_LGUI | MOD_LSFT), kc)
+#define C_S_T(kc) MT(MOD_LCTL | MOD_LSFT, kc) // Control + Shift e.g. for gnome-terminal
+#define MEH_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT, kc) // Meh is a less hyper version of the Hyper key -- doesn't include Win or Cmd, so just alt+shift+ctrl
+#define LCAG_T(kc) MT(MOD_LCTL | MOD_LALT | MOD_LGUI, kc) // Left control alt and gui
+#define RCAG_T(kc) MT(MOD_RCTL | MOD_RALT | MOD_RGUI, kc) // Right control alt and gui
+#define ALL_T(kc) MT(MOD_LCTL | MOD_LSFT | MOD_LALT | MOD_LGUI, kc) // see http://brettterpstra.com/2012/12/08/a-useful-caps-lock-key/
+#define SGUI_T(kc) MT(MOD_LGUI | MOD_LSFT, kc)
#define SCMD_T(kc) SGUI_T(kc)
#define SWIN_T(kc) SGUI_T(kc)
-#define LCA_T(kc) MT((MOD_LCTL | MOD_LALT), kc) // Left control and left alt
+#define LCA_T(kc) MT(MOD_LCTL | MOD_LALT, kc) // Left control and left alt
// Dedicated keycode versions for Hyper and Meh, if you want to use them as standalone keys rather than mod-tap
#define KC_HYPR HYPR(KC_NO)
@@ -670,22 +682,31 @@ enum quantum_keycodes {
// For sending unicode codes.
// You may not send codes over 7FFF -- this supports most of UTF8.
// To have a key that sends out Œ, go UC(0x0152)
- #define UNICODE(n) (n | QK_UNICODE)
+ #define UNICODE(n) (QK_UNICODE | (n))
#define UC(n) UNICODE(n)
#endif
#ifdef UNICODEMAP_ENABLE
- #define X(n) (n | QK_UNICODE_MAP)
+ #define X(n) (QK_UNICODE_MAP | (n))
#endif
+#define UC_MOD UNICODE_MODE_FORWARD
+#define UC_RMOD UNICODE_MODE_REVERSE
+
+#define UC_M_OS UNICODE_MODE_OSX
+#define UC_M_LN UNICODE_MODE_LNX
+#define UC_M_WI UNICODE_MODE_WIN
+#define UC_M_BS UNICODE_MODE_BSD
+#define UC_M_WC UNICODE_MODE_WINC
+
#ifdef SWAP_HANDS_ENABLE
- #define SH_T(key) (QK_SWAP_HANDS | key)
- #define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE)
- #define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE)
- #define SH_MON (QK_SWAP_HANDS | OP_SH_ON_OFF)
- #define SH_MOFF (QK_SWAP_HANDS | OP_SH_OFF_ON)
- #define SH_ON (QK_SWAP_HANDS | OP_SH_ON)
- #define SH_OFF (QK_SWAP_HANDS | OP_SH_OFF)
+ #define SH_T(kc) (QK_SWAP_HANDS | (kc))
+ #define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE)
+ #define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE)
+ #define SH_MON (QK_SWAP_HANDS | OP_SH_ON_OFF)
+ #define SH_MOFF (QK_SWAP_HANDS | OP_SH_OFF_ON)
+ #define SH_ON (QK_SWAP_HANDS | OP_SH_ON)
+ #define SH_OFF (QK_SWAP_HANDS | OP_SH_OFF)
#endif
#endif // QUANTUM_KEYCODES_H
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c
index b4bbc3dc07..2ed36304dc 100644
--- a/quantum/rgb_matrix.c
+++ b/quantum/rgb_matrix.c
@@ -1,5 +1,6 @@
/* Copyright 2017 Jason Williams
* Copyright 2017 Jack Humbert
+ * Copyright 2018 Yiancar
*
* 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
@@ -17,18 +18,22 @@
#include "rgb_matrix.h"
-#include <avr/io.h>
-#include "i2c_master.h"
-#include <util/delay.h>
-#include <avr/interrupt.h>
#include "progmem.h"
#include "config.h"
#include "eeprom.h"
-#include "lufa.h"
+#include <string.h>
#include <math.h>
rgb_config_t rgb_matrix_config;
+#ifndef MAX
+ #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
+#endif
+
+#ifndef MIN
+ #define MIN(a,b) ((a) < (b)? (a): (b))
+#endif
+
#ifndef RGB_DISABLE_AFTER_TIMEOUT
#define RGB_DISABLE_AFTER_TIMEOUT 0
#endif
@@ -45,6 +50,15 @@ rgb_config_t rgb_matrix_config;
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 255
#endif
+#ifndef RGB_DIGITAL_RAIN_DROPS
+ // lower the number for denser effect/wider keyboard
+ #define RGB_DIGITAL_RAIN_DROPS 24
+#endif
+
+#if !defined(DISABLE_RGB_MATRIX_RAINDROPS) || !defined(DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS) || !defined(DISABLE_RGB_MATRIX_DIGITAL_RAIN)
+ #define TRACK_PREVIOUS_EFFECT
+#endif
+
bool g_suspend_state = false;
// Global tick at 20 Hz
@@ -69,7 +83,12 @@ void eeconfig_update_rgb_matrix(uint32_t val) {
void eeconfig_update_rgb_matrix_default(void) {
dprintf("eeconfig_update_rgb_matrix_default\n");
rgb_matrix_config.enable = 1;
+#ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
rgb_matrix_config.mode = RGB_MATRIX_CYCLE_LEFT_RIGHT;
+#else
+ // fallback to solid colors if RGB_MATRIX_CYCLE_LEFT_RIGHT is disabled in userspace
+ rgb_matrix_config.mode = RGB_MATRIX_SOLID_COLOR;
+#endif
rgb_matrix_config.hue = 0;
rgb_matrix_config.sat = 255;
rgb_matrix_config.val = RGB_MATRIX_MAXIMUM_BRIGHTNESS;
@@ -106,16 +125,15 @@ void map_row_column_to_led( uint8_t row, uint8_t column, uint8_t *led_i, uint8_t
}
void rgb_matrix_update_pwm_buffers(void) {
- IS31FL3731_update_pwm_buffers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
- IS31FL3731_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+ rgb_matrix_driver.flush();
}
void rgb_matrix_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) {
- IS31FL3731_set_color( index, red, green, blue );
+ rgb_matrix_driver.set_color(index, red, green, blue);
}
void rgb_matrix_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) {
- IS31FL3731_set_color_all( red, green, blue );
+ rgb_matrix_driver.set_color_all(red, green, blue);
}
bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) {
@@ -178,47 +196,6 @@ void rgb_matrix_test(void) {
}
}
-// This tests the LEDs
-// Note that it will change the LED control registers
-// in the LED drivers, and leave them in an invalid
-// state for other backlight effects.
-// ONLY USE THIS FOR TESTING LEDS!
-void rgb_matrix_single_LED_test(void) {
- static uint8_t color = 0; // 0,1,2 for R,G,B
- static uint8_t row = 0;
- static uint8_t column = 0;
-
- static uint8_t tick = 0;
- tick++;
-
- if ( tick > 2 )
- {
- tick = 0;
- column++;
- }
- if ( column > MATRIX_COLS )
- {
- column = 0;
- row++;
- }
- if ( row > MATRIX_ROWS )
- {
- row = 0;
- color++;
- }
- if ( color > 2 )
- {
- color = 0;
- }
-
- uint8_t led[8], led_count;
- map_row_column_to_led(row,column,led,&led_count);
- for(uint8_t i = 0; i < led_count; i++) {
- rgb_matrix_set_color_all( 40, 40, 40 );
- rgb_matrix_test_led( led[i], color==0, color==1, color==2 );
- }
-}
-
// All LEDs off
void rgb_matrix_all_off(void) {
rgb_matrix_set_color_all( 0, 0, 0 );
@@ -420,10 +397,12 @@ void rgb_matrix_cycle_up_down(void) {
void rgb_matrix_dual_beacon(void) {
HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
RGB rgb;
- rgb_led led;
+ Point point;
+ double cos_value = cos(g_tick * PI / 128) / 32;
+ double sin_value = sin(g_tick * PI / 128) / 112;
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
- led = g_rgb_leds[i];
- hsv.h = ((led.point.y - 32.0)* cos(g_tick * PI / 128) / 32 + (led.point.x - 112.0) * sin(g_tick * PI / 128) / (112)) * (180) + rgb_matrix_config.hue;
+ point = g_rgb_leds[i].point;
+ hsv.h = ((point.y - 32.0)* cos_value + (point.x - 112.0) * sin_value) * (180) + rgb_matrix_config.hue;
rgb = hsv_to_rgb( hsv );
rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
}
@@ -432,10 +411,12 @@ void rgb_matrix_dual_beacon(void) {
void rgb_matrix_rainbow_beacon(void) {
HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
RGB rgb;
- rgb_led led;
+ Point point;
+ double cos_value = cos(g_tick * PI / 128);
+ double sin_value = sin(g_tick * PI / 128);
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
- led = g_rgb_leds[i];
- hsv.h = (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (led.point.y - 32.0)* cos(g_tick * PI / 128) + (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (led.point.x - 112.0) * sin(g_tick * PI / 128) + rgb_matrix_config.hue;
+ point = g_rgb_leds[i].point;
+ hsv.h = (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.y - 32.0)* cos_value + (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.x - 112.0) * sin_value + rgb_matrix_config.hue;
rgb = hsv_to_rgb( hsv );
rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
}
@@ -444,10 +425,12 @@ void rgb_matrix_rainbow_beacon(void) {
void rgb_matrix_rainbow_pinwheels(void) {
HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
RGB rgb;
- rgb_led led;
+ Point point;
+ double cos_value = cos(g_tick * PI / 128);
+ double sin_value = sin(g_tick * PI / 128);
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
- led = g_rgb_leds[i];
- hsv.h = (2 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (led.point.y - 32.0)* cos(g_tick * PI / 128) + (2 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (66 - abs(led.point.x - 112.0)) * sin(g_tick * PI / 128) + rgb_matrix_config.hue;
+ point = g_rgb_leds[i].point;
+ hsv.h = (2 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.y - 32.0)* cos_value + (2 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (66 - abs(point.x - 112.0)) * sin_value + rgb_matrix_config.hue;
rgb = hsv_to_rgb( hsv );
rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
}
@@ -456,12 +439,14 @@ void rgb_matrix_rainbow_pinwheels(void) {
void rgb_matrix_rainbow_moving_chevron(void) {
HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
RGB rgb;
- rgb_led led;
+ Point point;
+ uint8_t r = 128;
+ double cos_value = cos(r * PI / 128);
+ double sin_value = sin(r * PI / 128);
+ double multiplier = (g_tick / 256.0 * 224);
for (uint8_t i = 0; i < DRIVER_LED_TOTAL; i++) {
- led = g_rgb_leds[i];
- // uint8_t r = g_tick;
- uint8_t r = 32;
- hsv.h = (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * abs(led.point.y - 32.0)* sin(r * PI / 128) + (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (led.point.x - (g_tick / 256.0 * 224)) * cos(r * PI / 128) + rgb_matrix_config.hue;
+ point = g_rgb_leds[i].point;
+ hsv.h = (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * abs(point.y - 32.0)* sin_value + (1.5 * (rgb_matrix_config.speed == 0 ? 1 : rgb_matrix_config.speed)) * (point.x - multiplier) * cos_value + rgb_matrix_config.hue;
rgb = hsv_to_rgb( hsv );
rgb_matrix_set_color( i, rgb.r, rgb.g, rgb.b );
}
@@ -492,6 +477,68 @@ void rgb_matrix_jellybean_raindrops( bool initialize ) {
}
}
+void rgb_matrix_digital_rain( const bool initialize ) {
+ // algorithm ported from https://github.com/tremby/Kaleidoscope-LEDEffect-DigitalRain
+ const uint8_t drop_ticks = 28;
+ const uint8_t pure_green_intensity = 0xd0;
+ const uint8_t max_brightness_boost = 0xc0;
+ const uint8_t max_intensity = 0xff;
+
+ static uint8_t map[MATRIX_COLS][MATRIX_ROWS] = {{0}};
+ static uint8_t drop = 0;
+
+ if (initialize) {
+ rgb_matrix_set_color_all(0, 0, 0);
+ memset(map, 0, sizeof map);
+ drop = 0;
+ }
+ for (uint8_t col = 0; col < MATRIX_COLS; col++) {
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ if (row == 0 && drop == 0 && rand() < RAND_MAX / RGB_DIGITAL_RAIN_DROPS) {
+ // top row, pixels have just fallen and we're
+ // making a new rain drop in this column
+ map[col][row] = max_intensity;
+ }
+ else if (map[col][row] > 0 && map[col][row] < max_intensity) {
+ // neither fully bright nor dark, decay it
+ map[col][row]--;
+ }
+ // set the pixel colour
+ uint8_t led, led_count;
+ map_row_column_to_led(row, col, &led, &led_count);
+
+ if (map[col][row] > pure_green_intensity) {
+ const uint8_t boost = (uint8_t) ((uint16_t) max_brightness_boost
+ * (map[col][row] - pure_green_intensity) / (max_intensity - pure_green_intensity));
+ rgb_matrix_set_color(led, boost, max_intensity, boost);
+ }
+ else {
+ const uint8_t green = (uint8_t) ((uint16_t) max_intensity * map[col][row] / pure_green_intensity);
+ rgb_matrix_set_color(led, 0, green, 0);
+ }
+ }
+ }
+ if (++drop > drop_ticks) {
+ // reset drop timer
+ drop = 0;
+ for (uint8_t row = MATRIX_ROWS - 1; row > 0; row--) {
+ for (uint8_t col = 0; col < MATRIX_COLS; col++) {
+ // if ths is on the bottom row and bright allow decay
+ if (row == MATRIX_ROWS - 1 && map[col][row] == max_intensity) {
+ map[col][row]--;
+ }
+ // check if the pixel above is bright
+ if (map[col][row - 1] == max_intensity) {
+ // allow old bright pixel to decay
+ map[col][row - 1]--;
+ // make this pixel bright
+ map[col][row] = max_intensity;
+ }
+ }
+ }
+ }
+}
+
void rgb_matrix_multisplash(void) {
// if (g_any_key_hit < 0xFF) {
HSV hsv = { .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val };
@@ -580,11 +627,16 @@ void rgb_matrix_custom(void) {
}
void rgb_matrix_task(void) {
- static uint8_t toggle_enable_last = 255;
+ #ifdef TRACK_PREVIOUS_EFFECT
+ static uint8_t toggle_enable_last = 255;
+ #endif
if (!rgb_matrix_config.enable) {
- rgb_matrix_all_off();
- toggle_enable_last = rgb_matrix_config.enable;
- return;
+ rgb_matrix_all_off();
+ rgb_matrix_indicators();
+ #ifdef TRACK_PREVIOUS_EFFECT
+ toggle_enable_last = rgb_matrix_config.enable;
+ #endif
+ return;
}
// delay 1 second before driving LEDs or doing anything else
static uint8_t startup_tick = 0;
@@ -619,13 +671,16 @@ void rgb_matrix_task(void) {
(RGB_DISABLE_AFTER_TIMEOUT > 0 && g_any_key_hit > RGB_DISABLE_AFTER_TIMEOUT * 60 * 20));
uint8_t effect = suspend_backlight ? 0 : rgb_matrix_config.mode;
- // Keep track of the effect used last time,
- // detect change in effect, so each effect can
- // have an optional initialization.
- static uint8_t effect_last = 255;
- bool initialize = (effect != effect_last) || (rgb_matrix_config.enable != toggle_enable_last);
- effect_last = effect;
- toggle_enable_last = rgb_matrix_config.enable;
+ #ifdef TRACK_PREVIOUS_EFFECT
+ // Keep track of the effect used last time,
+ // detect change in effect, so each effect can
+ // have an optional initialization.
+
+ static uint8_t effect_last = 255;
+ bool initialize = (effect != effect_last) || (rgb_matrix_config.enable != toggle_enable_last);
+ effect_last = effect;
+ toggle_enable_last = rgb_matrix_config.enable;
+ #endif
// this gets ticked at 20 Hz.
// each effect can opt to do calculations
@@ -634,56 +689,93 @@ void rgb_matrix_task(void) {
case RGB_MATRIX_SOLID_COLOR:
rgb_matrix_solid_color();
break;
- case RGB_MATRIX_ALPHAS_MODS:
- rgb_matrix_alphas_mods();
- break;
- case RGB_MATRIX_DUAL_BEACON:
- rgb_matrix_dual_beacon();
- break;
- case RGB_MATRIX_GRADIENT_UP_DOWN:
- rgb_matrix_gradient_up_down();
- break;
- case RGB_MATRIX_RAINDROPS:
- rgb_matrix_raindrops( initialize );
- break;
- case RGB_MATRIX_CYCLE_ALL:
- rgb_matrix_cycle_all();
- break;
- case RGB_MATRIX_CYCLE_LEFT_RIGHT:
- rgb_matrix_cycle_left_right();
- break;
- case RGB_MATRIX_CYCLE_UP_DOWN:
- rgb_matrix_cycle_up_down();
- break;
- case RGB_MATRIX_RAINBOW_BEACON:
- rgb_matrix_rainbow_beacon();
- break;
- case RGB_MATRIX_RAINBOW_PINWHEELS:
- rgb_matrix_rainbow_pinwheels();
- break;
- case RGB_MATRIX_RAINBOW_MOVING_CHEVRON:
- rgb_matrix_rainbow_moving_chevron();
- break;
- case RGB_MATRIX_JELLYBEAN_RAINDROPS:
- rgb_matrix_jellybean_raindrops( initialize );
- break;
- #ifdef RGB_MATRIX_KEYPRESSES
- case RGB_MATRIX_SOLID_REACTIVE:
- rgb_matrix_solid_reactive();
+ #ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS
+ case RGB_MATRIX_ALPHAS_MODS:
+ rgb_matrix_alphas_mods();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_DUAL_BEACON
+ case RGB_MATRIX_DUAL_BEACON:
+ rgb_matrix_dual_beacon();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
+ case RGB_MATRIX_GRADIENT_UP_DOWN:
+ rgb_matrix_gradient_up_down();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_RAINDROPS
+ case RGB_MATRIX_RAINDROPS:
+ rgb_matrix_raindrops( initialize );
break;
- case RGB_MATRIX_SPLASH:
- rgb_matrix_splash();
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
+ case RGB_MATRIX_CYCLE_ALL:
+ rgb_matrix_cycle_all();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
+ case RGB_MATRIX_CYCLE_LEFT_RIGHT:
+ rgb_matrix_cycle_left_right();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
+ case RGB_MATRIX_CYCLE_UP_DOWN:
+ rgb_matrix_cycle_up_down();
break;
- case RGB_MATRIX_MULTISPLASH:
- rgb_matrix_multisplash();
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_RAINBOW_BEACON
+ case RGB_MATRIX_RAINBOW_BEACON:
+ rgb_matrix_rainbow_beacon();
break;
- case RGB_MATRIX_SOLID_SPLASH:
- rgb_matrix_solid_splash();
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
+ case RGB_MATRIX_RAINBOW_PINWHEELS:
+ rgb_matrix_rainbow_pinwheels();
break;
- case RGB_MATRIX_SOLID_MULTISPLASH:
- rgb_matrix_solid_multisplash();
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
+ case RGB_MATRIX_RAINBOW_MOVING_CHEVRON:
+ rgb_matrix_rainbow_moving_chevron();
break;
#endif
+ #ifndef DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
+ case RGB_MATRIX_JELLYBEAN_RAINDROPS:
+ rgb_matrix_jellybean_raindrops( initialize );
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_DIGITAL_RAIN
+ case RGB_MATRIX_DIGITAL_RAIN:
+ rgb_matrix_digital_rain( initialize );
+ break;
+ #endif
+ #ifdef RGB_MATRIX_KEYPRESSES
+ #ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
+ case RGB_MATRIX_SOLID_REACTIVE:
+ rgb_matrix_solid_reactive();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_SPLASH
+ case RGB_MATRIX_SPLASH:
+ rgb_matrix_splash();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_MULTISPLASH
+ case RGB_MATRIX_MULTISPLASH:
+ rgb_matrix_multisplash();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
+ case RGB_MATRIX_SOLID_SPLASH:
+ rgb_matrix_solid_splash();
+ break;
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
+ case RGB_MATRIX_SOLID_MULTISPLASH:
+ rgb_matrix_solid_multisplash();
+ break;
+ #endif
+ #endif
default:
rgb_matrix_custom();
break;
@@ -725,7 +817,7 @@ void rgb_matrix_indicators_user(void) {}
// }
void rgb_matrix_init(void) {
- rgb_matrix_setup_drivers();
+ rgb_matrix_driver.init();
// TODO: put the 1 second startup delay here?
@@ -749,29 +841,14 @@ void rgb_matrix_init(void) {
eeconfig_debug_rgb_matrix(); // display current eeprom values
}
-void rgb_matrix_setup_drivers(void) {
- // Initialize TWI
- i2c_init();
- IS31FL3731_init( DRIVER_ADDR_1 );
- IS31FL3731_init( DRIVER_ADDR_2 );
-
- for ( int index = 0; index < DRIVER_LED_TOTAL; index++ ) {
- bool enabled = true;
- // This only caches it for later
- IS31FL3731_set_led_control_register( index, enabled, enabled, enabled );
- }
- // This actually updates the LED drivers
- IS31FL3731_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
-}
-
// Deals with the messy details of incrementing an integer
-uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
+static uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
int16_t new_value = value;
new_value += step;
return MIN( MAX( new_value, min ), max );
}
-uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
+static uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
int16_t new_value = value;
new_value -= step;
return MIN( MAX( new_value, min ), max );
@@ -806,88 +883,109 @@ uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
// }
// }
-void rgb_matrix_test_led( uint8_t index, bool red, bool green, bool blue ) {
- for ( int i=0; i<DRIVER_LED_TOTAL; i++ )
- {
- if ( i == index )
- {
- IS31FL3731_set_led_control_register( i, red, green, blue );
- }
- else
- {
- IS31FL3731_set_led_control_register( i, false, false, false );
- }
- }
-}
-
uint32_t rgb_matrix_get_tick(void) {
return g_tick;
}
-void rgblight_toggle(void) {
+void rgb_matrix_toggle(void) {
rgb_matrix_config.enable ^= 1;
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_step(void) {
+void rgb_matrix_enable(void) {
+ rgb_matrix_config.enable = 1;
+ eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
+}
+
+void rgb_matrix_enable_noeeprom(void) {
+ rgb_matrix_config.enable = 1;
+}
+
+void rgb_matrix_disable(void) {
+ rgb_matrix_config.enable = 0;
+ eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
+}
+
+void rgb_matrix_disable_noeeprom(void) {
+ rgb_matrix_config.enable = 0;
+}
+
+void rgb_matrix_step(void) {
rgb_matrix_config.mode++;
if (rgb_matrix_config.mode >= RGB_MATRIX_EFFECT_MAX)
rgb_matrix_config.mode = 1;
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_step_reverse(void) {
+void rgb_matrix_step_reverse(void) {
rgb_matrix_config.mode--;
if (rgb_matrix_config.mode < 1)
rgb_matrix_config.mode = RGB_MATRIX_EFFECT_MAX - 1;
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_increase_hue(void) {
+void rgb_matrix_increase_hue(void) {
rgb_matrix_config.hue = increment( rgb_matrix_config.hue, 8, 0, 255 );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_decrease_hue(void) {
+void rgb_matrix_decrease_hue(void) {
rgb_matrix_config.hue = decrement( rgb_matrix_config.hue, 8, 0, 255 );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_increase_sat(void) {
+void rgb_matrix_increase_sat(void) {
rgb_matrix_config.sat = increment( rgb_matrix_config.sat, 8, 0, 255 );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_decrease_sat(void) {
+void rgb_matrix_decrease_sat(void) {
rgb_matrix_config.sat = decrement( rgb_matrix_config.sat, 8, 0, 255 );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_increase_val(void) {
+void rgb_matrix_increase_val(void) {
rgb_matrix_config.val = increment( rgb_matrix_config.val, 8, 0, RGB_MATRIX_MAXIMUM_BRIGHTNESS );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_decrease_val(void) {
+void rgb_matrix_decrease_val(void) {
rgb_matrix_config.val = decrement( rgb_matrix_config.val, 8, 0, RGB_MATRIX_MAXIMUM_BRIGHTNESS );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-void rgblight_increase_speed(void) {
+void rgb_matrix_increase_speed(void) {
rgb_matrix_config.speed = increment( rgb_matrix_config.speed, 1, 0, 3 );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);//EECONFIG needs to be increased to support this
}
-void rgblight_decrease_speed(void) {
+void rgb_matrix_decrease_speed(void) {
rgb_matrix_config.speed = decrement( rgb_matrix_config.speed, 1, 0, 3 );
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);//EECONFIG needs to be increased to support this
}
-void rgblight_mode(uint8_t mode) {
+void rgb_matrix_mode(uint8_t mode) {
rgb_matrix_config.mode = mode;
eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
}
-uint32_t rgblight_get_mode(void) {
+void rgb_matrix_mode_noeeprom(uint8_t mode) {
+ rgb_matrix_config.mode = mode;
+}
+
+uint8_t rgb_matrix_get_mode(void) {
return rgb_matrix_config.mode;
}
+
+void rgb_matrix_sethsv(uint16_t hue, uint8_t sat, uint8_t val) {
+ rgb_matrix_config.hue = hue;
+ rgb_matrix_config.sat = sat;
+ rgb_matrix_config.val = val;
+ eeconfig_update_rgb_matrix(rgb_matrix_config.raw);
+}
+
+void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val) {
+ rgb_matrix_config.hue = hue;
+ rgb_matrix_config.sat = sat;
+ rgb_matrix_config.val = val;
+}
diff --git a/quantum/rgb_matrix.h b/quantum/rgb_matrix.h
index 5769314002..e43532d11e 100644
--- a/quantum/rgb_matrix.h
+++ b/quantum/rgb_matrix.h
@@ -1,5 +1,6 @@
/* Copyright 2017 Jason Williams
* Copyright 2017 Jack Humbert
+ * Copyright 2018 Yiancar
*
* 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
@@ -21,9 +22,14 @@
#include <stdint.h>
#include <stdbool.h>
#include "color.h"
-#include "is31fl3731.h"
#include "quantum.h"
+#ifdef IS31FL3731
+ #include "is31fl3731.h"
+#elif defined (IS31FL3733)
+ #include "is31fl3733.h"
+#endif
+
typedef struct Point {
uint8_t x;
uint8_t y;
@@ -64,28 +70,64 @@ typedef union {
enum rgb_matrix_effects {
RGB_MATRIX_SOLID_COLOR = 1,
+#ifndef DISABLE_RGB_MATRIX_ALPHAS_MODS
RGB_MATRIX_ALPHAS_MODS,
+#endif
+#ifndef DISABLE_RGB_MATRIX_DUAL_BEACON
RGB_MATRIX_DUAL_BEACON,
+#endif
+#ifndef DISABLE_RGB_MATRIX_GRADIENT_UP_DOWN
RGB_MATRIX_GRADIENT_UP_DOWN,
+#endif
+#ifndef DISABLE_RGB_MATRIX_RAINDROPS
RGB_MATRIX_RAINDROPS,
+#endif
+#ifndef DISABLE_RGB_MATRIX_CYCLE_ALL
RGB_MATRIX_CYCLE_ALL,
+#endif
+#ifndef DISABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
RGB_MATRIX_CYCLE_LEFT_RIGHT,
+#endif
+#ifndef DISABLE_RGB_MATRIX_CYCLE_UP_DOWN
RGB_MATRIX_CYCLE_UP_DOWN,
+#endif
+#ifndef DISABLE_RGB_MATRIX_RAINBOW_BEACON
RGB_MATRIX_RAINBOW_BEACON,
+#endif
+#ifndef DISABLE_RGB_MATRIX_RAINBOW_PINWHEELS
RGB_MATRIX_RAINBOW_PINWHEELS,
+#endif
+#ifndef DISABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
RGB_MATRIX_RAINBOW_MOVING_CHEVRON,
+#endif
+#ifndef DISABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
RGB_MATRIX_JELLYBEAN_RAINDROPS,
+#endif
+#ifndef DISABLE_RGB_MATRIX_DIGITAL_RAIN
+ RGB_MATRIX_DIGITAL_RAIN,
+#endif
#ifdef RGB_MATRIX_KEYPRESSES
- RGB_MATRIX_SOLID_REACTIVE,
- RGB_MATRIX_SPLASH,
- RGB_MATRIX_MULTISPLASH,
- RGB_MATRIX_SOLID_SPLASH,
- RGB_MATRIX_SOLID_MULTISPLASH,
+ #ifndef DISABLE_RGB_MATRIX_SOLID_REACTIVE
+ RGB_MATRIX_SOLID_REACTIVE,
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_SPLASH
+ RGB_MATRIX_SPLASH,
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_MULTISPLASH
+ RGB_MATRIX_MULTISPLASH,
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_SOLID_SPLASH
+ RGB_MATRIX_SOLID_SPLASH,
+ #endif
+ #ifndef DISABLE_RGB_MATRIX_SOLID_MULTISPLASH
+ RGB_MATRIX_SOLID_MULTISPLASH,
+ #endif
#endif
RGB_MATRIX_EFFECT_MAX
};
void rgb_matrix_set_color( int index, uint8_t red, uint8_t green, uint8_t blue );
+void rgb_matrix_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
// This runs after another backlight effect and replaces
// colors already set
@@ -93,8 +135,6 @@ void rgb_matrix_indicators(void);
void rgb_matrix_indicators_kb(void);
void rgb_matrix_indicators_user(void);
-void rgb_matrix_single_LED_test(void);
-
void rgb_matrix_init(void);
void rgb_matrix_setup_drivers(void);
@@ -119,21 +159,65 @@ void rgb_matrix_decrease(void);
// void backlight_get_key_color( uint8_t led, HSV *hsv );
// void backlight_set_key_color( uint8_t row, uint8_t column, HSV hsv );
-void rgb_matrix_test_led( uint8_t index, bool red, bool green, bool blue );
uint32_t rgb_matrix_get_tick(void);
-void rgblight_toggle(void);
-void rgblight_step(void);
-void rgblight_step_reverse(void);
-void rgblight_increase_hue(void);
-void rgblight_decrease_hue(void);
-void rgblight_increase_sat(void);
-void rgblight_decrease_sat(void);
-void rgblight_increase_val(void);
-void rgblight_decrease_val(void);
-void rgblight_increase_speed(void);
-void rgblight_decrease_speed(void);
-void rgblight_mode(uint8_t mode);
-uint32_t rgblight_get_mode(void);
+void rgb_matrix_toggle(void);
+void rgb_matrix_enable(void);
+void rgb_matrix_enable_noeeprom(void);
+void rgb_matrix_disable(void);
+void rgb_matrix_disable_noeeprom(void);
+void rgb_matrix_step(void);
+void rgb_matrix_sethsv(uint16_t hue, uint8_t sat, uint8_t val);
+void rgb_matrix_sethsv_noeeprom(uint16_t hue, uint8_t sat, uint8_t val);
+void rgb_matrix_step_reverse(void);
+void rgb_matrix_increase_hue(void);
+void rgb_matrix_decrease_hue(void);
+void rgb_matrix_increase_sat(void);
+void rgb_matrix_decrease_sat(void);
+void rgb_matrix_increase_val(void);
+void rgb_matrix_decrease_val(void);
+void rgb_matrix_increase_speed(void);
+void rgb_matrix_decrease_speed(void);
+void rgb_matrix_mode(uint8_t mode);
+void rgb_matrix_mode_noeeprom(uint8_t mode);
+uint8_t rgb_matrix_get_mode(void);
+
+#ifndef RGBLIGHT_ENABLE
+#define rgblight_toggle() rgb_matrix_toggle()
+#define rgblight_enable() rgb_matrix_enable()
+#define rgblight_enable_noeeprom() rgb_matrix_enable_noeeprom()
+#define rgblight_disable() rgb_matrix_disable()
+#define rgblight_disable_noeeprom() rgb_matrix_disable_noeeprom()
+#define rgblight_step() rgb_matrix_step()
+#define rgblight_sethsv(hue, sat, val) rgb_matrix_sethsv(hue, sat, val)
+#define rgblight_sethsv_noeeprom(hue, sat, val) rgb_matrix_sethsv_noeeprom(hue, sat, val)
+#define rgblight_step_reverse() rgb_matrix_step_reverse()
+#define rgblight_increase_hue() rgb_matrix_increase_hue()
+#define rgblight_decrease_hue() rgb_matrix_decrease_hue()
+#define rgblight_increase_sat() rgb_matrix_increase_sat()
+#define rgblight_decrease_sat() rgb_matrix_decrease_sat()
+#define rgblight_increase_val() rgb_matrix_increase_val()
+#define rgblight_decrease_val() rgb_matrix_decrease_val()
+#define rgblight_increase_speed() rgb_matrix_increase_speed()
+#define rgblight_decrease_speed() rgb_matrix_decrease_speed()
+#define rgblight_mode(mode) rgb_matrix_mode(mode)
+#define rgblight_mode_noeeprom(mode) rgb_matrix_mode_noeeprom(mode)
+#define rgblight_get_mode() rgb_matrix_get_mode()
+
+#endif
+
+typedef struct {
+ /* Perform any initialisation required for the other driver functions to work. */
+ void (*init)(void);
+
+ /* Set the colour of a single LED in the buffer. */
+ void (*set_color)(int index, uint8_t r, uint8_t g, uint8_t b);
+ /* Set the colour of all LEDS on the keyboard in the buffer. */
+ void (*set_color_all)(uint8_t r, uint8_t g, uint8_t b);
+ /* Flush any buffered changes to the hardware. */
+ void (*flush)(void);
+} rgb_matrix_driver_t;
+
+extern const rgb_matrix_driver_t rgb_matrix_driver;
#endif
diff --git a/quantum/rgb_matrix_drivers.c b/quantum/rgb_matrix_drivers.c
new file mode 100644
index 0000000000..70b80293dd
--- /dev/null
+++ b/quantum/rgb_matrix_drivers.c
@@ -0,0 +1,82 @@
+/* Copyright 2018 James Laird-Wah
+ *
+ * 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 "rgb_matrix.h"
+
+/* Each driver needs to define the struct
+ * const rgb_matrix_driver_t rgb_matrix_driver;
+ * All members must be provided.
+ * Keyboard custom drivers can define this in their own files, it should only
+ * be here if shared between boards.
+ */
+
+#if defined(IS31FL3731) || defined(IS31FL3733)
+
+#include "i2c_master.h"
+
+static void init( void )
+{
+ i2c_init();
+#ifdef IS31FL3731
+ IS31FL3731_init( DRIVER_ADDR_1 );
+ IS31FL3731_init( DRIVER_ADDR_2 );
+#else
+ IS31FL3733_init( DRIVER_ADDR_1 );
+#endif
+ for ( int index = 0; index < DRIVER_LED_TOTAL; index++ ) {
+ bool enabled = true;
+ // This only caches it for later
+#ifdef IS31FL3731
+ IS31FL3731_set_led_control_register( index, enabled, enabled, enabled );
+#else
+ IS31FL3733_set_led_control_register( index, enabled, enabled, enabled );
+#endif
+ }
+ // This actually updates the LED drivers
+#ifdef IS31FL3731
+ IS31FL3731_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#else
+ IS31FL3733_update_led_control_registers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+#endif
+}
+
+#ifdef IS31FL3731
+static void flush( void )
+{
+ IS31FL3731_update_pwm_buffers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+}
+
+const rgb_matrix_driver_t rgb_matrix_driver = {
+ .init = init,
+ .flush = flush,
+ .set_color = IS31FL3731_set_color,
+ .set_color_all = IS31FL3731_set_color_all,
+};
+#else
+static void flush( void )
+{
+ IS31FL3733_update_pwm_buffers( DRIVER_ADDR_1, DRIVER_ADDR_2 );
+}
+
+const rgb_matrix_driver_t rgb_matrix_driver = {
+ .init = init,
+ .flush = flush,
+ .set_color = IS31FL3733_set_color,
+ .set_color_all = IS31FL3733_set_color_all,
+};
+#endif
+
+#endif
diff --git a/quantum/rgblight.c b/quantum/rgblight.c
index 4919ae4abf..23420ddd87 100644
--- a/quantum/rgblight.c
+++ b/quantum/rgblight.c
@@ -14,6 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
+#include <string.h>
#ifdef __AVR__
#include <avr/eeprom.h>
#include <avr/interrupt.h>
@@ -29,23 +30,27 @@
#define RGBLIGHT_LIMIT_VAL 255
#endif
+#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_SINGLE_DYNAMIC(sym)
+#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_MULTI_DYNAMIC(sym)
+#define _RGBM_TMP_STATIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_TMP_DYNAMIC(sym)
+static uint8_t static_effect_table [] = {
+#include "rgblight.h"
+};
+
+static inline int is_static_effect(uint8_t mode) {
+ return memchr(static_effect_table, mode, sizeof(static_effect_table)) != NULL;
+}
+
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
-__attribute__ ((weak))
-const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
-__attribute__ ((weak))
-const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
-__attribute__ ((weak))
-const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
-__attribute__ ((weak))
-const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
-__attribute__ ((weak))
-const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
+#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
__attribute__ ((weak))
const uint16_t RGBLED_GRADIENT_RANGES[] PROGMEM = {360, 240, 180, 120, 90};
-__attribute__ ((weak))
-const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
+#endif
rgblight_config_t rgblight_config;
@@ -129,7 +134,7 @@ void eeconfig_update_rgblight(uint32_t val) {
void eeconfig_update_rgblight_default(void) {
//dprintf("eeconfig_update_rgblight_default\n");
rgblight_config.enable = 1;
- rgblight_config.mode = 1;
+ rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
rgblight_config.hue = 0;
rgblight_config.sat = 255;
rgblight_config.val = RGBLIGHT_LIMIT_VAL;
@@ -163,9 +168,9 @@ void rgblight_init(void) {
}
eeconfig_debug_rgblight(); // display current eeprom values
- #ifdef RGBLIGHT_ANIMATIONS
+#ifdef RGBLIGHT_USE_TIMER
rgblight_timer_init(); // setup the timer
- #endif
+#endif
if (rgblight_config.enable) {
rgblight_mode_noeeprom(rgblight_config.mode);
@@ -178,9 +183,9 @@ void rgblight_update_dword(uint32_t dword) {
if (rgblight_config.enable)
rgblight_mode(rgblight_config.mode);
else {
- #ifdef RGBLIGHT_ANIMATIONS
+#ifdef RGBLIGHT_USE_TIMER
rgblight_timer_disable();
- #endif
+#endif
rgblight_set();
}
}
@@ -195,29 +200,41 @@ void rgblight_increase(void) {
void rgblight_decrease(void) {
uint8_t mode = 0;
// Mode will never be < 1. If it ever is, eeprom needs to be initialized.
- if (rgblight_config.mode > 1) {
+ if (rgblight_config.mode > RGBLIGHT_MODE_STATIC_LIGHT) {
mode = rgblight_config.mode - 1;
}
rgblight_mode(mode);
}
-void rgblight_step(void) {
+void rgblight_step_helper(bool write_to_eeprom) {
uint8_t mode = 0;
mode = rgblight_config.mode + 1;
if (mode > RGBLIGHT_MODES) {
mode = 1;
}
- rgblight_mode(mode);
+ rgblight_mode_eeprom_helper(mode, write_to_eeprom);
}
-void rgblight_step_reverse(void) {
+void rgblight_step_noeeprom(void) {
+ rgblight_step_helper(false);
+}
+void rgblight_step(void) {
+ rgblight_step_helper(true);
+}
+void rgblight_step_reverse_helper(bool write_to_eeprom) {
uint8_t mode = 0;
mode = rgblight_config.mode - 1;
if (mode < 1) {
mode = RGBLIGHT_MODES;
}
- rgblight_mode(mode);
+ rgblight_mode_eeprom_helper(mode, write_to_eeprom);
+}
+void rgblight_step_reverse_noeeprom(void) {
+ rgblight_step_reverse_helper(false);
+}
+void rgblight_step_reverse(void) {
+ rgblight_step_reverse_helper(true);
}
-uint32_t rgblight_get_mode(void) {
+uint8_t rgblight_get_mode(void) {
if (!rgblight_config.enable) {
return false;
}
@@ -229,8 +246,8 @@ void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
if (!rgblight_config.enable) {
return;
}
- if (mode < 1) {
- rgblight_config.mode = 1;
+ if (mode < RGBLIGHT_MODE_STATIC_LIGHT) {
+ rgblight_config.mode = RGBLIGHT_MODE_STATIC_LIGHT;
} else if (mode > RGBLIGHT_MODES) {
rgblight_config.mode = RGBLIGHT_MODES;
} else {
@@ -242,30 +259,14 @@ void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom) {
} else {
xprintf("rgblight mode [NOEEPROM]: %u\n", rgblight_config.mode);
}
- if (rgblight_config.mode == 1) {
- #ifdef RGBLIGHT_ANIMATIONS
+ if( is_static_effect(rgblight_config.mode) ) {
+#ifdef RGBLIGHT_USE_TIMER
rgblight_timer_disable();
- #endif
- } else if ((rgblight_config.mode >= 2 && rgblight_config.mode <= 24) ||
- rgblight_config.mode == 35 || rgblight_config.mode == 36) {
- // MODE 2-5, breathing
- // MODE 6-8, rainbow mood
- // MODE 9-14, rainbow swirl
- // MODE 15-20, snake
- // MODE 21-23, knight
- // MODE 24, xmas
- // MODE 35 RGB test
- // MODE 36, alterating
-
- #ifdef RGBLIGHT_ANIMATIONS
+#endif
+ } else {
+#ifdef RGBLIGHT_USE_TIMER
rgblight_timer_enable();
- #endif
- } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
- // MODE 25-34, static gradient
-
- #ifdef RGBLIGHT_ANIMATIONS
- rgblight_timer_disable();
- #endif
+#endif
}
rgblight_sethsv_noeeprom(rgblight_config.hue, rgblight_config.sat, rgblight_config.val);
}
@@ -317,9 +318,9 @@ void rgblight_disable(void) {
rgblight_config.enable = 0;
eeconfig_update_rgblight(rgblight_config.raw);
xprintf("rgblight disable [EEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
- #ifdef RGBLIGHT_ANIMATIONS
- rgblight_timer_disable();
- #endif
+#ifdef RGBLIGHT_USE_TIMER
+ rgblight_timer_disable();
+#endif
wait_ms(50);
rgblight_set();
}
@@ -327,76 +328,112 @@ void rgblight_disable(void) {
void rgblight_disable_noeeprom(void) {
rgblight_config.enable = 0;
xprintf("rgblight disable [noEEPROM]: rgblight_config.enable = %u\n", rgblight_config.enable);
- #ifdef RGBLIGHT_ANIMATIONS
+#ifdef RGBLIGHT_USE_TIMER
rgblight_timer_disable();
- #endif
+#endif
_delay_ms(50);
rgblight_set();
}
// Deals with the messy details of incrementing an integer
-uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
+static uint8_t increment( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
int16_t new_value = value;
new_value += step;
return MIN( MAX( new_value, min ), max );
}
-uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
+static uint8_t decrement( uint8_t value, uint8_t step, uint8_t min, uint8_t max ) {
int16_t new_value = value;
new_value -= step;
return MIN( MAX( new_value, min ), max );
}
-void rgblight_increase_hue(void) {
+void rgblight_increase_hue_helper(bool write_to_eeprom) {
uint16_t hue;
hue = (rgblight_config.hue+RGBLIGHT_HUE_STEP) % 360;
- rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
+ rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
}
-void rgblight_decrease_hue(void) {
+void rgblight_increase_hue_noeeprom(void) {
+ rgblight_increase_hue_helper(false);
+}
+void rgblight_increase_hue(void) {
+ rgblight_increase_hue_helper(true);
+}
+void rgblight_decrease_hue_helper(bool write_to_eeprom) {
uint16_t hue;
if (rgblight_config.hue-RGBLIGHT_HUE_STEP < 0) {
hue = (rgblight_config.hue + 360 - RGBLIGHT_HUE_STEP) % 360;
} else {
hue = (rgblight_config.hue - RGBLIGHT_HUE_STEP) % 360;
}
- rgblight_sethsv(hue, rgblight_config.sat, rgblight_config.val);
+ rgblight_sethsv_eeprom_helper(hue, rgblight_config.sat, rgblight_config.val, write_to_eeprom);
}
-void rgblight_increase_sat(void) {
+void rgblight_decrease_hue_noeeprom(void) {
+ rgblight_decrease_hue_helper(false);
+}
+void rgblight_decrease_hue(void) {
+ rgblight_decrease_hue_helper(true);
+}
+void rgblight_increase_sat_helper(bool write_to_eeprom) {
uint8_t sat;
if (rgblight_config.sat + RGBLIGHT_SAT_STEP > 255) {
sat = 255;
} else {
sat = rgblight_config.sat + RGBLIGHT_SAT_STEP;
}
- rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
+ rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
}
-void rgblight_decrease_sat(void) {
+void rgblight_increase_sat_noeeprom(void) {
+ rgblight_increase_sat_helper(false);
+}
+void rgblight_increase_sat(void) {
+ rgblight_increase_sat_helper(true);
+}
+void rgblight_decrease_sat_helper(bool write_to_eeprom) {
uint8_t sat;
if (rgblight_config.sat - RGBLIGHT_SAT_STEP < 0) {
sat = 0;
} else {
sat = rgblight_config.sat - RGBLIGHT_SAT_STEP;
}
- rgblight_sethsv(rgblight_config.hue, sat, rgblight_config.val);
+ rgblight_sethsv_eeprom_helper(rgblight_config.hue, sat, rgblight_config.val, write_to_eeprom);
}
-void rgblight_increase_val(void) {
+void rgblight_decrease_sat_noeeprom(void) {
+ rgblight_decrease_sat_helper(false);
+}
+void rgblight_decrease_sat(void) {
+ rgblight_decrease_sat_helper(true);
+}
+void rgblight_increase_val_helper(bool write_to_eeprom) {
uint8_t val;
if (rgblight_config.val + RGBLIGHT_VAL_STEP > RGBLIGHT_LIMIT_VAL) {
val = RGBLIGHT_LIMIT_VAL;
} else {
val = rgblight_config.val + RGBLIGHT_VAL_STEP;
}
- rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
+ rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
}
-void rgblight_decrease_val(void) {
+void rgblight_increase_val_noeeprom(void) {
+ rgblight_increase_val_helper(false);
+}
+void rgblight_increase_val(void) {
+ rgblight_increase_val_helper(true);
+}
+void rgblight_decrease_val_helper(bool write_to_eeprom) {
uint8_t val;
if (rgblight_config.val - RGBLIGHT_VAL_STEP < 0) {
val = 0;
} else {
val = rgblight_config.val - RGBLIGHT_VAL_STEP;
}
- rgblight_sethsv(rgblight_config.hue, rgblight_config.sat, val);
+ rgblight_sethsv_eeprom_helper(rgblight_config.hue, rgblight_config.sat, val, write_to_eeprom);
+}
+void rgblight_decrease_val_noeeprom(void) {
+ rgblight_decrease_val_helper(false);
+}
+void rgblight_decrease_val(void) {
+ rgblight_decrease_val_helper(true);
}
void rgblight_increase_speed(void) {
rgblight_config.speed = increment( rgblight_config.speed, 1, 0, 3 );
@@ -419,24 +456,43 @@ void rgblight_sethsv_noeeprom_old(uint16_t hue, uint8_t sat, uint8_t val) {
void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom) {
if (rgblight_config.enable) {
- if (rgblight_config.mode == 1) {
+ if (rgblight_config.mode == RGBLIGHT_MODE_STATIC_LIGHT) {
// same static color
LED_TYPE tmp_led;
sethsv(hue, sat, val, &tmp_led);
rgblight_setrgb(tmp_led.r, tmp_led.g, tmp_led.b);
} else {
// all LEDs in same color
- if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
+ if ( 1 == 0 ) { //dummy
+ }
+#ifdef RGBLIGHT_EFFECT_BREATHING
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_BREATHING &&
+ rgblight_config.mode <= RGBLIGHT_MODE_BREATHING_end) {
// breathing mode, ignore the change of val, use in memory value instead
val = rgblight_config.val;
- } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 14) {
- // rainbow mood and rainbow swirl, ignore the change of hue
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_MOOD &&
+ rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_MOOD_end) {
+ // rainbow mood, ignore the change of hue
hue = rgblight_config.hue;
- } else if (rgblight_config.mode >= 25 && rgblight_config.mode <= 34) {
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_SWIRL &&
+ rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_SWIRL_end) {
+ // rainbow swirl, ignore the change of hue
+ hue = rgblight_config.hue;
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_STATIC_GRADIENT &&
+ rgblight_config.mode <= RGBLIGHT_MODE_STATIC_GRADIENT_end) {
// static gradient
uint16_t _hue;
- int8_t direction = ((rgblight_config.mode - 25) % 2) ? -1 : 1;
- uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - 25) / 2]);
+ int8_t direction = ((rgblight_config.mode - RGBLIGHT_MODE_STATIC_GRADIENT) % 2) ? -1 : 1;
+ uint16_t range = pgm_read_word(&RGBLED_GRADIENT_RANGES[(rgblight_config.mode - RGBLIGHT_MODE_STATIC_GRADIENT) / 2]);
for (uint8_t i = 0; i < RGBLED_NUM; i++) {
_hue = (range / RGBLED_NUM * i * direction + hue + 360) % 360;
dprintf("rgblight rainbow set hsv: %u,%u,%d,%u\n", i, _hue, direction, range);
@@ -444,6 +500,7 @@ void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool
}
rgblight_set();
}
+#endif
}
rgblight_config.hue = hue;
rgblight_config.sat = sat;
@@ -528,7 +585,7 @@ void rgblight_set(void) {
}
#endif
-#ifdef RGBLIGHT_ANIMATIONS
+#ifdef RGBLIGHT_USE_TIMER
// Animation timer -- AVR Timer3
void rgblight_timer_init(void) {
@@ -564,41 +621,77 @@ void rgblight_timer_toggle(void) {
void rgblight_show_solid_color(uint8_t r, uint8_t g, uint8_t b) {
rgblight_enable();
- rgblight_mode(1);
+ rgblight_mode(RGBLIGHT_MODE_STATIC_LIGHT);
rgblight_setrgb(r, g, b);
}
void rgblight_task(void) {
if (rgblight_timer_enabled) {
- // mode = 1, static light, do nothing here
- if (rgblight_config.mode >= 2 && rgblight_config.mode <= 5) {
- // mode = 2 to 5, breathing mode
- rgblight_effect_breathing(rgblight_config.mode - 2);
- } else if (rgblight_config.mode >= 6 && rgblight_config.mode <= 8) {
- // mode = 6 to 8, rainbow mood mod
- rgblight_effect_rainbow_mood(rgblight_config.mode - 6);
- } else if (rgblight_config.mode >= 9 && rgblight_config.mode <= 14) {
- // mode = 9 to 14, rainbow swirl mode
- rgblight_effect_rainbow_swirl(rgblight_config.mode - 9);
- } else if (rgblight_config.mode >= 15 && rgblight_config.mode <= 20) {
- // mode = 15 to 20, snake mode
- rgblight_effect_snake(rgblight_config.mode - 15);
- } else if (rgblight_config.mode >= 21 && rgblight_config.mode <= 23) {
- // mode = 21 to 23, knight mode
- rgblight_effect_knight(rgblight_config.mode - 21);
- } else if (rgblight_config.mode == 24) {
- // mode = 24, christmas mode
+ // static light mode, do nothing here
+ if ( 1 == 0 ) { //dummy
+ }
+#ifdef RGBLIGHT_EFFECT_BREATHING
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_BREATHING &&
+ rgblight_config.mode <= RGBLIGHT_MODE_BREATHING_end) {
+ // breathing mode
+ rgblight_effect_breathing(rgblight_config.mode - RGBLIGHT_MODE_BREATHING );
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_MOOD &&
+ rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_MOOD_end) {
+ // rainbow mood mode
+ rgblight_effect_rainbow_mood(rgblight_config.mode - RGBLIGHT_MODE_RAINBOW_MOOD);
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_RAINBOW_SWIRL &&
+ rgblight_config.mode <= RGBLIGHT_MODE_RAINBOW_SWIRL_end) {
+ // rainbow swirl mode
+ rgblight_effect_rainbow_swirl(rgblight_config.mode - RGBLIGHT_MODE_RAINBOW_SWIRL);
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_SNAKE
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_SNAKE &&
+ rgblight_config.mode <= RGBLIGHT_MODE_SNAKE_end) {
+ // snake mode
+ rgblight_effect_snake(rgblight_config.mode - RGBLIGHT_MODE_SNAKE);
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_KNIGHT
+ else if (rgblight_config.mode >= RGBLIGHT_MODE_KNIGHT &&
+ rgblight_config.mode <= RGBLIGHT_MODE_KNIGHT_end) {
+ // knight mode
+ rgblight_effect_knight(rgblight_config.mode - RGBLIGHT_MODE_KNIGHT);
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_CHRISTMAS
+ else if (rgblight_config.mode == RGBLIGHT_MODE_CHRISTMAS) {
+ // christmas mode
rgblight_effect_christmas();
- } else if (rgblight_config.mode == 35) {
- // mode = 35, RGB test
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_RGB_TEST
+ else if (rgblight_config.mode == RGBLIGHT_MODE_RGB_TEST) {
+ // RGB test mode
rgblight_effect_rgbtest();
- } else if (rgblight_config.mode == 36){
+ }
+#endif
+#ifdef RGBLIGHT_EFFECT_ALTERNATING
+ else if (rgblight_config.mode == RGBLIGHT_MODE_ALTERNATING){
rgblight_effect_alternating();
}
+#endif
}
}
+#endif /* RGBLIGHT_USE_TIMER */
+
// Effects
+#ifdef RGBLIGHT_EFFECT_BREATHING
+__attribute__ ((weak))
+const uint8_t RGBLED_BREATHING_INTERVALS[] PROGMEM = {30, 20, 10, 5};
+
void rgblight_effect_breathing(uint8_t interval) {
static uint8_t pos = 0;
static uint16_t last_timer = 0;
@@ -609,12 +702,17 @@ void rgblight_effect_breathing(uint8_t interval) {
}
last_timer = timer_read();
-
// http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/
val = (exp(sin((pos/255.0)*M_PI)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)*(RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E));
rgblight_sethsv_noeeprom_old(rgblight_config.hue, rgblight_config.sat, val);
pos = (pos + 1) % 256;
}
+#endif
+
+#ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
+__attribute__ ((weak))
+const uint8_t RGBLED_RAINBOW_MOOD_INTERVALS[] PROGMEM = {120, 60, 30};
+
void rgblight_effect_rainbow_mood(uint8_t interval) {
static uint16_t current_hue = 0;
static uint16_t last_timer = 0;
@@ -626,6 +724,16 @@ void rgblight_effect_rainbow_mood(uint8_t interval) {
rgblight_sethsv_noeeprom_old(current_hue, rgblight_config.sat, rgblight_config.val);
current_hue = (current_hue + 1) % 360;
}
+#endif
+
+#ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
+#ifndef RGBLIGHT_RAINBOW_SWIRL_RANGE
+ #define RGBLIGHT_RAINBOW_SWIRL_RANGE 360
+#endif
+
+__attribute__ ((weak))
+const uint8_t RGBLED_RAINBOW_SWIRL_INTERVALS[] PROGMEM = {100, 50, 20};
+
void rgblight_effect_rainbow_swirl(uint8_t interval) {
static uint16_t current_hue = 0;
static uint16_t last_timer = 0;
@@ -636,7 +744,7 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) {
}
last_timer = timer_read();
for (i = 0; i < RGBLED_NUM; i++) {
- hue = (360 / RGBLED_NUM * i + current_hue) % 360;
+ hue = (RGBLIGHT_RAINBOW_SWIRL_RANGE / RGBLED_NUM * i + current_hue) % 360;
sethsv(hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
}
rgblight_set();
@@ -651,6 +759,12 @@ void rgblight_effect_rainbow_swirl(uint8_t interval) {
}
}
}
+#endif
+
+#ifdef RGBLIGHT_EFFECT_SNAKE
+__attribute__ ((weak))
+const uint8_t RGBLED_SNAKE_INTERVALS[] PROGMEM = {100, 50, 20};
+
void rgblight_effect_snake(uint8_t interval) {
static uint8_t pos = 0;
static uint16_t last_timer = 0;
@@ -689,6 +803,12 @@ void rgblight_effect_snake(uint8_t interval) {
pos = (pos + 1) % RGBLED_NUM;
}
}
+#endif
+
+#ifdef RGBLIGHT_EFFECT_KNIGHT
+__attribute__ ((weak))
+const uint8_t RGBLED_KNIGHT_INTERVALS[] PROGMEM = {127, 63, 31};
+
void rgblight_effect_knight(uint8_t interval) {
static uint16_t last_timer = 0;
if (timer_elapsed(last_timer) < pgm_read_byte(&RGBLED_KNIGHT_INTERVALS[interval])) {
@@ -730,8 +850,9 @@ void rgblight_effect_knight(uint8_t interval) {
increment = -increment;
}
}
+#endif
-
+#ifdef RGBLIGHT_EFFECT_CHRISTMAS
void rgblight_effect_christmas(void) {
static uint16_t current_offset = 0;
static uint16_t last_timer = 0;
@@ -748,6 +869,11 @@ void rgblight_effect_christmas(void) {
}
rgblight_set();
}
+#endif
+
+#ifdef RGBLIGHT_EFFECT_RGB_TEST
+__attribute__ ((weak))
+const uint16_t RGBLED_RGBTEST_INTERVALS[] PROGMEM = {1024};
void rgblight_effect_rgbtest(void) {
static uint8_t pos = 0;
@@ -774,7 +900,9 @@ void rgblight_effect_rgbtest(void) {
rgblight_setrgb(r, g, b);
pos = (pos + 1) % 3;
}
+#endif
+#ifdef RGBLIGHT_EFFECT_ALTERNATING
void rgblight_effect_alternating(void){
static uint16_t last_timer = 0;
static uint16_t pos = 0;
@@ -784,16 +912,15 @@ void rgblight_effect_alternating(void){
last_timer = timer_read();
for(int i = 0; i<RGBLED_NUM; i++){
- if(i<RGBLED_NUM/2 && pos){
- rgblight_sethsv_at(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, i);
- }else if (i>=RGBLED_NUM/2 && !pos){
- rgblight_sethsv_at(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, i);
- }else{
- rgblight_sethsv_at(rgblight_config.hue, rgblight_config.sat, 0, i);
- }
+ if(i<RGBLED_NUM/2 && pos){
+ sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
+ }else if (i>=RGBLED_NUM/2 && !pos){
+ sethsv(rgblight_config.hue, rgblight_config.sat, rgblight_config.val, (LED_TYPE *)&led[i]);
+ }else{
+ sethsv(rgblight_config.hue, rgblight_config.sat, 0, (LED_TYPE *)&led[i]);
+ }
}
rgblight_set();
pos = (pos + 1) % 2;
}
-
-#endif /* RGBLIGHT_ANIMATIONS */
+#endif
diff --git a/quantum/rgblight.h b/quantum/rgblight.h
index ba010dfae3..65dda3f521 100644
--- a/quantum/rgblight.h
+++ b/quantum/rgblight.h
@@ -16,11 +16,69 @@
#ifndef RGBLIGHT_H
#define RGBLIGHT_H
-#ifdef RGBLIGHT_ANIMATIONS
- #define RGBLIGHT_MODES 36
-#else
- #define RGBLIGHT_MODES 1
-#endif
+#include "rgblight_reconfig.h"
+
+/***** rgblight_mode(mode)/rgblight_mode_noeeprom(mode) ****
+
+ old mode number (before 0.6.117) to new mode name table
+
+|-----------------|-----------------------------------|
+| old mode number | new mode name |
+|-----------------|-----------------------------------|
+| 1 | RGBLIGHT_MODE_STATIC_LIGHT |
+| 2 | RGBLIGHT_MODE_BREATHING |
+| 3 | RGBLIGHT_MODE_BREATHING + 1 |
+| 4 | RGBLIGHT_MODE_BREATHING + 2 |
+| 5 | RGBLIGHT_MODE_BREATHING + 3 |
+| 6 | RGBLIGHT_MODE_RAINBOW_MOOD |
+| 7 | RGBLIGHT_MODE_RAINBOW_MOOD + 1 |
+| 8 | RGBLIGHT_MODE_RAINBOW_MOOD + 2 |
+| 9 | RGBLIGHT_MODE_RAINBOW_SWIRL |
+| 10 | RGBLIGHT_MODE_RAINBOW_SWIRL + 1 |
+| 11 | RGBLIGHT_MODE_RAINBOW_SWIRL + 2 |
+| 12 | RGBLIGHT_MODE_RAINBOW_SWIRL + 3 |
+| 13 | RGBLIGHT_MODE_RAINBOW_SWIRL + 4 |
+| 14 | RGBLIGHT_MODE_RAINBOW_SWIRL + 5 |
+| 15 | RGBLIGHT_MODE_SNAKE |
+| 16 | RGBLIGHT_MODE_SNAKE + 1 |
+| 17 | RGBLIGHT_MODE_SNAKE + 2 |
+| 18 | RGBLIGHT_MODE_SNAKE + 3 |
+| 19 | RGBLIGHT_MODE_SNAKE + 4 |
+| 20 | RGBLIGHT_MODE_SNAKE + 5 |
+| 21 | RGBLIGHT_MODE_KNIGHT |
+| 22 | RGBLIGHT_MODE_KNIGHT + 1 |
+| 23 | RGBLIGHT_MODE_KNIGHT + 2 |
+| 24 | RGBLIGHT_MODE_CHRISTMAS |
+| 25 | RGBLIGHT_MODE_STATIC_GRADIENT |
+| 26 | RGBLIGHT_MODE_STATIC_GRADIENT + 1 |
+| 27 | RGBLIGHT_MODE_STATIC_GRADIENT + 2 |
+| 28 | RGBLIGHT_MODE_STATIC_GRADIENT + 3 |
+| 29 | RGBLIGHT_MODE_STATIC_GRADIENT + 4 |
+| 30 | RGBLIGHT_MODE_STATIC_GRADIENT + 5 |
+| 31 | RGBLIGHT_MODE_STATIC_GRADIENT + 6 |
+| 32 | RGBLIGHT_MODE_STATIC_GRADIENT + 7 |
+| 33 | RGBLIGHT_MODE_STATIC_GRADIENT + 8 |
+| 34 | RGBLIGHT_MODE_STATIC_GRADIENT + 9 |
+| 35 | RGBLIGHT_MODE_RGB_TEST |
+| 36 | RGBLIGHT_MODE_ALTERNATING |
+|-----------------|-----------------------------------|
+ *****/
+
+#define _RGBM_SINGLE_STATIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_SINGLE_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_MULTI_STATIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_MULTI_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_TMP_STATIC(sym) RGBLIGHT_MODE_ ## sym,
+#define _RGBM_TMP_DYNAMIC(sym) RGBLIGHT_MODE_ ## sym,
+enum RGBLIGHT_EFFECT_MODE {
+ RGBLIGHT_MODE_zero = 0,
+#include "rgblight.h"
+ RGBLIGHT_MODE_last
+};
+
+#ifndef RGBLIGHT_H_DUMMY_DEFINE
+
+#define RGBLIGHT_MODES (RGBLIGHT_MODE_last-1)
#ifndef RGBLIGHT_EFFECT_BREATHE_CENTER
#define RGBLIGHT_EFFECT_BREATHE_CENTER 1.85 // 1-2.7
@@ -109,7 +167,7 @@ void rgblight_enable(void);
void rgblight_disable(void);
void rgblight_step(void);
void rgblight_step_reverse(void);
-uint32_t rgblight_get_mode(void);
+uint8_t rgblight_get_mode(void);
void rgblight_mode(uint8_t mode);
void rgblight_set(void);
void rgblight_update_dword(uint32_t dword);
@@ -145,6 +203,14 @@ void rgblight_mode_noeeprom(uint8_t mode);
void rgblight_toggle_noeeprom(void);
void rgblight_enable_noeeprom(void);
void rgblight_disable_noeeprom(void);
+void rgblight_step_noeeprom(void);
+void rgblight_step_reverse_noeeprom(void);
+void rgblight_increase_hue_noeeprom(void);
+void rgblight_decrease_hue_noeeprom(void);
+void rgblight_increase_sat_noeeprom(void);
+void rgblight_decrease_sat_noeeprom(void);
+void rgblight_increase_val_noeeprom(void);
+void rgblight_decrease_val_noeeprom(void);
void rgblight_sethsv_eeprom_helper(uint16_t hue, uint8_t sat, uint8_t val, bool write_to_eeprom);
void rgblight_mode_eeprom_helper(uint8_t mode, bool write_to_eeprom);
@@ -168,4 +234,73 @@ void rgblight_effect_christmas(void);
void rgblight_effect_rgbtest(void);
void rgblight_effect_alternating(void);
+#endif // #ifndef RGBLIGHT_H_DUMMY_DEFINE
+#endif // RGBLIGHT_H
+
+#ifdef _RGBM_SINGLE_STATIC
+ _RGBM_SINGLE_STATIC( STATIC_LIGHT )
+ #ifdef RGBLIGHT_EFFECT_BREATHING
+ _RGBM_MULTI_DYNAMIC( BREATHING )
+ _RGBM_TMP_DYNAMIC( breathing_3 )
+ _RGBM_TMP_DYNAMIC( breathing_4 )
+ _RGBM_TMP_DYNAMIC( BREATHING_end )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_RAINBOW_MOOD
+ _RGBM_MULTI_DYNAMIC( RAINBOW_MOOD )
+ _RGBM_TMP_DYNAMIC( rainbow_mood_7 )
+ _RGBM_TMP_DYNAMIC( RAINBOW_MOOD_end )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_RAINBOW_SWIRL
+ _RGBM_MULTI_DYNAMIC( RAINBOW_SWIRL )
+ _RGBM_TMP_DYNAMIC( rainbow_swirl_10 )
+ _RGBM_TMP_DYNAMIC( rainbow_swirl_11 )
+ _RGBM_TMP_DYNAMIC( rainbow_swirl_12 )
+ _RGBM_TMP_DYNAMIC( rainbow_swirl_13 )
+ _RGBM_TMP_DYNAMIC( RAINBOW_SWIRL_end )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_SNAKE
+ _RGBM_MULTI_DYNAMIC( SNAKE )
+ _RGBM_TMP_DYNAMIC( snake_16 )
+ _RGBM_TMP_DYNAMIC( snake_17 )
+ _RGBM_TMP_DYNAMIC( snake_18 )
+ _RGBM_TMP_DYNAMIC( snake_19 )
+ _RGBM_TMP_DYNAMIC( SNAKE_end )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_KNIGHT
+ _RGBM_MULTI_DYNAMIC( KNIGHT )
+ _RGBM_TMP_DYNAMIC( knight_22 )
+ _RGBM_TMP_DYNAMIC( KNIGHT_end )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_CHRISTMAS
+ _RGBM_SINGLE_DYNAMIC( CHRISTMAS )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_STATIC_GRADIENT
+ _RGBM_MULTI_STATIC( STATIC_GRADIENT )
+ _RGBM_TMP_STATIC( static_gradient_26 )
+ _RGBM_TMP_STATIC( static_gradient_27 )
+ _RGBM_TMP_STATIC( static_gradient_28 )
+ _RGBM_TMP_STATIC( static_gradient_29 )
+ _RGBM_TMP_STATIC( static_gradient_30 )
+ _RGBM_TMP_STATIC( static_gradient_31 )
+ _RGBM_TMP_STATIC( static_gradient_32 )
+ _RGBM_TMP_STATIC( static_gradient_33 )
+ _RGBM_TMP_STATIC( STATIC_GRADIENT_end )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_RGB_TEST
+ _RGBM_SINGLE_DYNAMIC( RGB_TEST )
+ #endif
+ #ifdef RGBLIGHT_EFFECT_ALTERNATING
+ _RGBM_SINGLE_DYNAMIC( ALTERNATING )
+ #endif
+ //// Add a new mode here.
+ // #ifdef RGBLIGHT_EFFECT_<name>
+ // _RGBM_<SINGLE|MULTI>_<STATIC|DYNAMIC>( <name> )
+ // #endif
#endif
+
+#undef _RGBM_SINGLE_STATIC
+#undef _RGBM_SINGLE_DYNAMIC
+#undef _RGBM_MULTI_STATIC
+#undef _RGBM_MULTI_DYNAMIC
+#undef _RGBM_TMP_STATIC
+#undef _RGBM_TMP_DYNAMIC
diff --git a/quantum/rgblight_reconfig.h b/quantum/rgblight_reconfig.h
new file mode 100644
index 0000000000..11bd4fd118
--- /dev/null
+++ b/quantum/rgblight_reconfig.h
@@ -0,0 +1,36 @@
+#ifndef RGBLIGHT_RECONFIG_H
+#define RGBLIGHT_RECONFIG_H
+
+#ifdef RGBLIGHT_ANIMATIONS
+ // for backward compatibility
+ #define RGBLIGHT_EFFECT_BREATHING
+ #define RGBLIGHT_EFFECT_RAINBOW_MOOD
+ #define RGBLIGHT_EFFECT_RAINBOW_SWIRL
+ #define RGBLIGHT_EFFECT_SNAKE
+ #define RGBLIGHT_EFFECT_KNIGHT
+ #define RGBLIGHT_EFFECT_CHRISTMAS
+ #define RGBLIGHT_EFFECT_STATIC_GRADIENT
+ #define RGBLIGHT_EFFECT_RGB_TEST
+ #define RGBLIGHT_EFFECT_ALTERNATING
+#endif
+
+#ifdef RGBLIGHT_STATIC_PATTERNS
+ #define RGBLIGHT_EFFECT_STATIC_GRADIENT
+#endif
+
+// check dynamic animation effects chose ?
+#if defined(RGBLIGHT_EFFECT_BREATHING) || \
+ defined(RGBLIGHT_EFFECT_RAINBOW_MOOD) || \
+ defined(RGBLIGHT_EFFECT_RAINBOW_SWIRL) || \
+ defined(RGBLIGHT_EFFECT_SNAKE) || \
+ defined(RGBLIGHT_EFFECT_KNIGHT) || \
+ defined(RGBLIGHT_EFFECT_CHRISTMAS) || \
+ defined(RGBLIGHT_EFFECT_RGB_TEST) || \
+ defined(RGBLIGHT_EFFECT_ALTERNATING)
+ #define RGBLIGHT_USE_TIMER
+ #ifndef RGBLIGHT_ANIMATIONS
+ #define RGBLIGHT_ANIMATIONS // for backward compatibility
+ #endif
+#endif
+
+#endif // RGBLIGHT_RECONFIG_H
diff --git a/quantum/split_common/i2c.c b/quantum/split_common/i2c.c
index b3d7fcc681..45e958b395 100644
--- a/quantum/split_common/i2c.c
+++ b/quantum/split_common/i2c.c
@@ -7,8 +7,6 @@
#include "i2c.h"
#include "split_flags.h"
-#if defined(USE_I2C) || defined(EH)
-
// Limits the amount of we wait for any one i2c transaction.
// Since were running SCL line 100kHz (=> 10μs/bit), and each transactions is
// 9 bits, a single transaction will take around 90μs to complete.
@@ -184,4 +182,3 @@ ISR(TWI_vect) {
// Reset everything, so we are ready for the next TWI interrupt
TWCR |= (1<<TWIE) | (1<<TWINT) | (ack<<TWEA) | (1<<TWEN);
}
-#endif
diff --git a/quantum/split_common/matrix.c b/quantum/split_common/matrix.c
index 0a79e42566..2c37053f88 100644
--- a/quantum/split_common/matrix.c
+++ b/quantum/split_common/matrix.c
@@ -20,21 +20,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
-#include <avr/io.h>
#include "wait.h"
-#include "print.h"
-#include "debug.h"
#include "util.h"
#include "matrix.h"
#include "split_util.h"
-#include "pro_micro.h"
#include "config.h"
#include "timer.h"
#include "split_flags.h"
+#include "quantum.h"
-#ifdef RGBLIGHT_ENABLE
-# include "rgblight.h"
-#endif
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
extern backlight_config_t backlight_config;
@@ -55,6 +49,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
static bool debouncing = false;
#endif
+#if defined(USE_I2C) || defined(EH)
+
#if (MATRIX_COLS <= 8)
# define print_matrix_header() print("\nr/c 01234567\n")
# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
@@ -63,6 +59,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#else
# error "Currently only supports 8 COLS"
#endif
+
+#else // USE_SERIAL
+
+#if (MATRIX_COLS <= 8)
+# define print_matrix_header() print("\nr/c 01234567\n")
+# define print_matrix_row(row) print_bin_reverse8(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop(matrix[i])
+# define ROW_SHIFTER ((uint8_t)1)
+#elif (MATRIX_COLS <= 16)
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse16(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop16(matrix[i])
+# define ROW_SHIFTER ((uint16_t)1)
+#elif (MATRIX_COLS <= 32)
+# define print_matrix_header() print("\nr/c 0123456789ABCDEF0123456789ABCDEF\n")
+# define print_matrix_row(row) print_bin_reverse32(matrix_get_row(row))
+# define matrix_bitpop(i) bitpop32(matrix[i])
+# define ROW_SHIFTER ((uint32_t)1)
+#endif
+
+#endif
static matrix_row_t matrix_debouncing[MATRIX_ROWS];
#define ERROR_DISCONNECT_COUNT 5
@@ -71,8 +88,8 @@ static matrix_row_t matrix_debouncing[MATRIX_ROWS];
static uint8_t error_count = 0;
-static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
-static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
+static pin_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS;
+static pin_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS;
/* matrix state(1:on, 0:off) */
static matrix_row_t matrix[MATRIX_ROWS];
@@ -128,15 +145,24 @@ uint8_t matrix_cols(void)
void matrix_init(void)
{
-#ifdef DISABLE_JTAG
- // JTAG disable for PORT F. write JTD bit twice within four cycles.
- MCUCR |= (1<<JTD);
- MCUCR |= (1<<JTD);
-#endif
-
debug_enable = true;
debug_matrix = true;
debug_mouse = true;
+
+ // Set pinout for right half if pinout for that half is defined
+ if (!isLeftHand) {
+#ifdef MATRIX_ROW_PINS_RIGHT
+ const uint8_t row_pins_right[MATRIX_ROWS] = MATRIX_ROW_PINS_RIGHT;
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++)
+ row_pins[i] = row_pins_right[i];
+#endif
+#ifdef MATRIX_COL_PINS_RIGHT
+ const uint8_t col_pins_right[MATRIX_COLS] = MATRIX_COL_PINS_RIGHT;
+ for (uint8_t i = 0; i < MATRIX_COLS; i++)
+ col_pins[i] = col_pins_right[i];
+#endif
+ }
+
// initialize row and col
#if (DIODE_DIRECTION == COL2ROW)
unselect_rows();
@@ -277,24 +303,48 @@ i2c_error: // the cable is disconnceted, or something else went wrong
#else // USE_SERIAL
+
+typedef struct _Serial_s2m_buffer_t {
+ // TODO: if MATRIX_COLS > 8 change to uint8_t packed_matrix[] for pack/unpack
+ matrix_row_t smatrix[ROWS_PER_HAND];
+} Serial_s2m_buffer_t;
+
+volatile Serial_s2m_buffer_t serial_s2m_buffer = {};
+volatile Serial_m2s_buffer_t serial_m2s_buffer = {};
+uint8_t volatile status0 = 0;
+
+SSTD_t transactions[] = {
+ { (uint8_t *)&status0,
+ sizeof(serial_m2s_buffer), (uint8_t *)&serial_m2s_buffer,
+ sizeof(serial_s2m_buffer), (uint8_t *)&serial_s2m_buffer
+ }
+};
+
+void serial_master_init(void)
+{ soft_serial_initiator_init(transactions, TID_LIMIT(transactions)); }
+
+void serial_slave_init(void)
+{ soft_serial_target_init(transactions, TID_LIMIT(transactions)); }
+
int serial_transaction(void) {
int slaveOffset = (isLeftHand) ? (ROWS_PER_HAND) : 0;
- if (serial_update_buffers()) {
+ if (soft_serial_transaction()) {
return 1;
}
+ // TODO: if MATRIX_COLS > 8 change to unpack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
- matrix[slaveOffset+i] = serial_slave_buffer[i];
+ matrix[slaveOffset+i] = serial_s2m_buffer.smatrix[i];
}
- #ifdef RGBLIGHT_ENABLE
+ #if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
// Code to send RGB over serial goes here (not implemented yet)
#endif
#ifdef BACKLIGHT_ENABLE
// Write backlight level for slave to read
- serial_master_buffer[SERIAL_BACKLIT_START] = backlight_config.enable ? backlight_config.level : 0;
+ serial_m2s_buffer.backlight_level = backlight_config.enable ? backlight_config.level : 0;
#endif
return 0;
@@ -337,8 +387,9 @@ void matrix_slave_scan(void) {
i2c_slave_buffer[I2C_KEYMAP_START+i] = matrix[offset+i];
}
#else // USE_SERIAL
+ // TODO: if MATRIX_COLS > 8 change to pack()
for (int i = 0; i < ROWS_PER_HAND; ++i) {
- serial_slave_buffer[i] = matrix[offset+i];
+ serial_s2m_buffer.smatrix[i] = matrix[offset+i];
}
#endif
matrix_slave_scan_user();
@@ -386,9 +437,7 @@ uint8_t matrix_key_count(void)
static void init_cols(void)
{
for(uint8_t x = 0; x < MATRIX_COLS; x++) {
- uint8_t pin = col_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(col_pins[x]);
}
}
@@ -406,13 +455,8 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
// For each col...
for(uint8_t col_index = 0; col_index < MATRIX_COLS; col_index++) {
-
- // Select the col pin to read (active low)
- uint8_t pin = col_pins[col_index];
- uint8_t pin_state = (_SFR_IO8(pin >> 4) & _BV(pin & 0xF));
-
// Populate the matrix row with the state of the col pin
- current_matrix[current_row] |= pin_state ? 0 : (ROW_SHIFTER << col_index);
+ current_matrix[current_row] |= readPin(col_pins[col_index]) ? 0 : (ROW_SHIFTER << col_index);
}
// Unselect row
@@ -423,24 +467,19 @@ static bool read_cols_on_row(matrix_row_t current_matrix[], uint8_t current_row)
static void select_row(uint8_t row)
{
- uint8_t pin = row_pins[row];
- _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
- _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+ writePinLow(row_pins[row]);
+ setPinOutput(row_pins[row]);
}
static void unselect_row(uint8_t row)
{
- uint8_t pin = row_pins[row];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(row_pins[row]);
}
static void unselect_rows(void)
{
for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
- uint8_t pin = row_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(row_pins[x]);
}
}
@@ -449,9 +488,7 @@ static void unselect_rows(void)
static void init_rows(void)
{
for(uint8_t x = 0; x < ROWS_PER_HAND; x++) {
- uint8_t pin = row_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(row_pins[x]);
}
}
@@ -471,15 +508,15 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
matrix_row_t last_row_value = current_matrix[row_index];
// Check row pin state
- if ((_SFR_IO8(row_pins[row_index] >> 4) & _BV(row_pins[row_index] & 0xF)) == 0)
+ if (readPin(row_pins[row_index]))
{
- // Pin LO, set col bit
- current_matrix[row_index] |= (ROW_SHIFTER << current_col);
+ // Pin HI, clear col bit
+ current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
}
else
{
- // Pin HI, clear col bit
- current_matrix[row_index] &= ~(ROW_SHIFTER << current_col);
+ // Pin LO, set col bit
+ current_matrix[row_index] |= (ROW_SHIFTER << current_col);
}
// Determine if the matrix changed state
@@ -497,24 +534,19 @@ static bool read_rows_on_col(matrix_row_t current_matrix[], uint8_t current_col)
static void select_col(uint8_t col)
{
- uint8_t pin = col_pins[col];
- _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); // OUT
- _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); // LOW
+ writePinLow(col_pins[col]);
+ setPinOutput(col_pins[col]);
}
static void unselect_col(uint8_t col)
{
- uint8_t pin = col_pins[col];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(col_pins[col]);
}
static void unselect_cols(void)
{
for(uint8_t x = 0; x < MATRIX_COLS; x++) {
- uint8_t pin = col_pins[x];
- _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); // IN
- _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); // HI
+ setPinInputHigh(col_pins[x]);
}
}
diff --git a/quantum/split_common/matrix.h b/quantum/split_common/matrix.h
new file mode 100644
index 0000000000..b5cb45baed
--- /dev/null
+++ b/quantum/split_common/matrix.h
@@ -0,0 +1,31 @@
+#ifndef SPLIT_COMMON_MATRIX_H
+#define SPLIT_COMMON_MATRIX_H
+
+#include <common/matrix.h>
+
+#ifdef RGBLIGHT_ENABLE
+# include "rgblight.h"
+#endif
+
+typedef struct _Serial_m2s_buffer_t {
+#ifdef BACKLIGHT_ENABLE
+ uint8_t backlight_level;
+#endif
+#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_SPLIT)
+ rgblight_config_t rgblight_config; //not yet use
+ //
+ // When MCUs on both sides drive their respective RGB LED chains,
+ // it is necessary to synchronize, so it is necessary to communicate RGB information.
+ // In that case, define the RGBLIGHT_SPLIT macro.
+ //
+ // Otherwise, if the master side MCU drives both sides RGB LED chains,
+ // there is no need to communicate.
+#endif
+} Serial_m2s_buffer_t;
+
+extern volatile Serial_m2s_buffer_t serial_m2s_buffer;
+
+void serial_master_init(void);
+void serial_slave_init(void);
+
+#endif
diff --git a/quantum/split_common/serial.c b/quantum/split_common/serial.c
index 74bcbb6bf6..1315377a34 100644
--- a/quantum/split_common/serial.c
+++ b/quantum/split_common/serial.c
@@ -1,5 +1,10 @@
/*
* WARNING: be careful changing this code, it is very timing dependent
+ *
+ * 2018-10-28 checked
+ * avr-gcc 4.9.2
+ * avr-gcc 5.4.0
+ * avr-gcc 7.3.0
*/
#ifndef F_CPU
@@ -9,220 +14,533 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
+#include <stddef.h>
#include <stdbool.h>
#include "serial.h"
+//#include <pro_micro.h>
+
+#ifdef SOFT_SERIAL_PIN
+
+#ifdef __AVR_ATmega32U4__
+ // if using ATmega32U4 I2C, can not use PD0 and PD1 in soft serial.
+ #ifdef USE_AVR_I2C
+ #if SOFT_SERIAL_PIN == D0 || SOFT_SERIAL_PIN == D1
+ #error Using ATmega32U4 I2C, so can not use PD0, PD1
+ #endif
+ #endif
+
+ #if SOFT_SERIAL_PIN >= D0 && SOFT_SERIAL_PIN <= D3
+ #define SERIAL_PIN_DDR DDRD
+ #define SERIAL_PIN_PORT PORTD
+ #define SERIAL_PIN_INPUT PIND
+ #if SOFT_SERIAL_PIN == D0
+ #define SERIAL_PIN_MASK _BV(PD0)
+ #define EIMSK_BIT _BV(INT0)
+ #define EICRx_BIT (~(_BV(ISC00) | _BV(ISC01)))
+ #define SERIAL_PIN_INTERRUPT INT0_vect
+ #elif SOFT_SERIAL_PIN == D1
+ #define SERIAL_PIN_MASK _BV(PD1)
+ #define EIMSK_BIT _BV(INT1)
+ #define EICRx_BIT (~(_BV(ISC10) | _BV(ISC11)))
+ #define SERIAL_PIN_INTERRUPT INT1_vect
+ #elif SOFT_SERIAL_PIN == D2
+ #define SERIAL_PIN_MASK _BV(PD2)
+ #define EIMSK_BIT _BV(INT2)
+ #define EICRx_BIT (~(_BV(ISC20) | _BV(ISC21)))
+ #define SERIAL_PIN_INTERRUPT INT2_vect
+ #elif SOFT_SERIAL_PIN == D3
+ #define SERIAL_PIN_MASK _BV(PD3)
+ #define EIMSK_BIT _BV(INT3)
+ #define EICRx_BIT (~(_BV(ISC30) | _BV(ISC31)))
+ #define SERIAL_PIN_INTERRUPT INT3_vect
+ #endif
+ #elif SOFT_SERIAL_PIN == E6
+ #define SERIAL_PIN_DDR DDRE
+ #define SERIAL_PIN_PORT PORTE
+ #define SERIAL_PIN_INPUT PINE
+ #define SERIAL_PIN_MASK _BV(PE6)
+ #define EIMSK_BIT _BV(INT6)
+ #define EICRx_BIT (~(_BV(ISC60) | _BV(ISC61)))
+ #define SERIAL_PIN_INTERRUPT INT6_vect
+ #else
+ #error invalid SOFT_SERIAL_PIN value
+ #endif
+
+#else
+ #error serial.c now support ATmega32U4 only
+#endif
-#ifndef USE_I2C
+#define ALWAYS_INLINE __attribute__((always_inline))
+#define NO_INLINE __attribute__((noinline))
+#define _delay_sub_us(x) __builtin_avr_delay_cycles(x)
+
+// parity check
+#define ODD_PARITY 1
+#define EVEN_PARITY 0
+#define PARITY EVEN_PARITY
+
+#ifdef SERIAL_DELAY
+ // custom setup in config.h
+ // #define TID_SEND_ADJUST 2
+ // #define SERIAL_DELAY 6 // micro sec
+ // #define READ_WRITE_START_ADJUST 30 // cycles
+ // #define READ_WRITE_WIDTH_ADJUST 8 // cycles
+#else
+// ============ Standard setups ============
+
+#ifndef SELECT_SOFT_SERIAL_SPEED
+#define SELECT_SOFT_SERIAL_SPEED 1
+// 0: about 189kbps (Experimental only)
+// 1: about 137kbps (default)
+// 2: about 75kbps
+// 3: about 39kbps
+// 4: about 26kbps
+// 5: about 20kbps
+#endif
-// Serial pulse period in microseconds. Its probably a bad idea to lower this
-// value.
-#define SERIAL_DELAY 24
+#if __GNUC__ < 6
+ #define TID_SEND_ADJUST 14
+#else
+ #define TID_SEND_ADJUST 2
+#endif
-uint8_t volatile serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH] = {0};
-uint8_t volatile serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH] = {0};
+#if SELECT_SOFT_SERIAL_SPEED == 0
+ // Very High speed
+ #define SERIAL_DELAY 4 // micro sec
+ #if __GNUC__ < 6
+ #define READ_WRITE_START_ADJUST 33 // cycles
+ #define READ_WRITE_WIDTH_ADJUST 3 // cycles
+ #else
+ #define READ_WRITE_START_ADJUST 34 // cycles
+ #define READ_WRITE_WIDTH_ADJUST 7 // cycles
+ #endif
+#elif SELECT_SOFT_SERIAL_SPEED == 1
+ // High speed
+ #define SERIAL_DELAY 6 // micro sec
+ #if __GNUC__ < 6
+ #define READ_WRITE_START_ADJUST 30 // cycles
+ #define READ_WRITE_WIDTH_ADJUST 3 // cycles
+ #else
+ #define READ_WRITE_START_ADJUST 33 // cycles
+ #define READ_WRITE_WIDTH_ADJUST 7 // cycles
+ #endif
+#elif SELECT_SOFT_SERIAL_SPEED == 2
+ // Middle speed
+ #define SERIAL_DELAY 12 // micro sec
+ #define READ_WRITE_START_ADJUST 30 // cycles
+ #if __GNUC__ < 6
+ #define READ_WRITE_WIDTH_ADJUST 3 // cycles
+ #else
+ #define READ_WRITE_WIDTH_ADJUST 7 // cycles
+ #endif
+#elif SELECT_SOFT_SERIAL_SPEED == 3
+ // Low speed
+ #define SERIAL_DELAY 24 // micro sec
+ #define READ_WRITE_START_ADJUST 30 // cycles
+ #if __GNUC__ < 6
+ #define READ_WRITE_WIDTH_ADJUST 3 // cycles
+ #else
+ #define READ_WRITE_WIDTH_ADJUST 7 // cycles
+ #endif
+#elif SELECT_SOFT_SERIAL_SPEED == 4
+ // Very Low speed
+ #define SERIAL_DELAY 36 // micro sec
+ #define READ_WRITE_START_ADJUST 30 // cycles
+ #if __GNUC__ < 6
+ #define READ_WRITE_WIDTH_ADJUST 3 // cycles
+ #else
+ #define READ_WRITE_WIDTH_ADJUST 7 // cycles
+ #endif
+#elif SELECT_SOFT_SERIAL_SPEED == 5
+ // Ultra Low speed
+ #define SERIAL_DELAY 48 // micro sec
+ #define READ_WRITE_START_ADJUST 30 // cycles
+ #if __GNUC__ < 6
+ #define READ_WRITE_WIDTH_ADJUST 3 // cycles
+ #else
+ #define READ_WRITE_WIDTH_ADJUST 7 // cycles
+ #endif
+#else
+#error invalid SELECT_SOFT_SERIAL_SPEED value
+#endif /* SELECT_SOFT_SERIAL_SPEED */
+#endif /* SERIAL_DELAY */
+
+#define SERIAL_DELAY_HALF1 (SERIAL_DELAY/2)
+#define SERIAL_DELAY_HALF2 (SERIAL_DELAY - SERIAL_DELAY/2)
+
+#define SLAVE_INT_WIDTH_US 1
+#ifndef SERIAL_USE_MULTI_TRANSACTION
+ #define SLAVE_INT_RESPONSE_TIME SERIAL_DELAY
+#else
+ #define SLAVE_INT_ACK_WIDTH_UNIT 2
+ #define SLAVE_INT_ACK_WIDTH 4
+#endif
-#define SLAVE_DATA_CORRUPT (1<<0)
-volatile uint8_t status = 0;
+static SSTD_t *Transaction_table = NULL;
+static uint8_t Transaction_table_size = 0;
+inline static void serial_delay(void) ALWAYS_INLINE;
inline static
void serial_delay(void) {
_delay_us(SERIAL_DELAY);
}
+inline static void serial_delay_half1(void) ALWAYS_INLINE;
+inline static
+void serial_delay_half1(void) {
+ _delay_us(SERIAL_DELAY_HALF1);
+}
+
+inline static void serial_delay_half2(void) ALWAYS_INLINE;
+inline static
+void serial_delay_half2(void) {
+ _delay_us(SERIAL_DELAY_HALF2);
+}
+
+inline static void serial_output(void) ALWAYS_INLINE;
inline static
void serial_output(void) {
SERIAL_PIN_DDR |= SERIAL_PIN_MASK;
}
// make the serial pin an input with pull-up resistor
+inline static void serial_input_with_pullup(void) ALWAYS_INLINE;
inline static
-void serial_input(void) {
+void serial_input_with_pullup(void) {
SERIAL_PIN_DDR &= ~SERIAL_PIN_MASK;
SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
}
+inline static uint8_t serial_read_pin(void) ALWAYS_INLINE;
inline static
uint8_t serial_read_pin(void) {
return !!(SERIAL_PIN_INPUT & SERIAL_PIN_MASK);
}
+inline static void serial_low(void) ALWAYS_INLINE;
inline static
void serial_low(void) {
SERIAL_PIN_PORT &= ~SERIAL_PIN_MASK;
}
+inline static void serial_high(void) ALWAYS_INLINE;
inline static
void serial_high(void) {
SERIAL_PIN_PORT |= SERIAL_PIN_MASK;
}
-void serial_master_init(void) {
- serial_output();
- serial_high();
+void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size)
+{
+ Transaction_table = sstd_table;
+ Transaction_table_size = (uint8_t)sstd_table_size;
+ serial_output();
+ serial_high();
}
-void serial_slave_init(void) {
- serial_input();
-
- // Enable INT0
- EIMSK |= _BV(INT0);
- // Trigger on falling edge of INT0
- EICRA &= ~(_BV(ISC00) | _BV(ISC01));
+void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size)
+{
+ Transaction_table = sstd_table;
+ Transaction_table_size = (uint8_t)sstd_table_size;
+ serial_input_with_pullup();
+
+ // Enable INT0-INT3,INT6
+ EIMSK |= EIMSK_BIT;
+#if SERIAL_PIN_MASK == _BV(PE6)
+ // Trigger on falling edge of INT6
+ EICRB &= EICRx_BIT;
+#else
+ // Trigger on falling edge of INT0-INT3
+ EICRA &= EICRx_BIT;
+#endif
}
-// Used by the master to synchronize timing with the slave.
+// Used by the sender to synchronize timing with the reciver.
+static void sync_recv(void) NO_INLINE;
static
void sync_recv(void) {
- serial_input();
- // This shouldn't hang if the slave disconnects because the
- // serial line will float to high if the slave does disconnect.
+ for (uint8_t i = 0; i < SERIAL_DELAY*5 && serial_read_pin(); i++ ) {
+ }
+ // This shouldn't hang if the target disconnects because the
+ // serial line will float to high if the target does disconnect.
while (!serial_read_pin());
- serial_delay();
}
-// Used by the slave to send a synchronization signal to the master.
+// Used by the reciver to send a synchronization signal to the sender.
+static void sync_send(void) NO_INLINE;
static
void sync_send(void) {
- serial_output();
-
serial_low();
serial_delay();
-
serial_high();
}
// Reads a byte from the serial line
-static
-uint8_t serial_read_byte(void) {
- uint8_t byte = 0;
- serial_input();
- for ( uint8_t i = 0; i < 8; ++i) {
- byte = (byte << 1) | serial_read_pin();
- serial_delay();
- _delay_us(1);
+static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) NO_INLINE;
+static uint8_t serial_read_chunk(uint8_t *pterrcount, uint8_t bit) {
+ uint8_t byte, i, p, pb;
+
+ _delay_sub_us(READ_WRITE_START_ADJUST);
+ for( i = 0, byte = 0, p = PARITY; i < bit; i++ ) {
+ serial_delay_half1(); // read the middle of pulses
+ if( serial_read_pin() ) {
+ byte = (byte << 1) | 1; p ^= 1;
+ } else {
+ byte = (byte << 1) | 0; p ^= 0;
+ }
+ _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
+ serial_delay_half2();
}
+ /* recive parity bit */
+ serial_delay_half1(); // read the middle of pulses
+ pb = serial_read_pin();
+ _delay_sub_us(READ_WRITE_WIDTH_ADJUST);
+ serial_delay_half2();
+
+ *pterrcount += (p != pb)? 1 : 0;
return byte;
}
// Sends a byte with MSB ordering
-static
-void serial_write_byte(uint8_t data) {
- uint8_t b = 8;
- serial_output();
- while( b-- ) {
- if(data & (1 << b)) {
- serial_high();
- } else {
- serial_low();
+void serial_write_chunk(uint8_t data, uint8_t bit) NO_INLINE;
+void serial_write_chunk(uint8_t data, uint8_t bit) {
+ uint8_t b, p;
+ for( p = PARITY, b = 1<<(bit-1); b ; b >>= 1) {
+ if(data & b) {
+ serial_high(); p ^= 1;
+ } else {
+ serial_low(); p ^= 0;
+ }
+ serial_delay();
}
+ /* send parity bit */
+ if(p & 1) { serial_high(); }
+ else { serial_low(); }
serial_delay();
- }
-}
-// interrupt handle to be used by the slave device
-ISR(SERIAL_PIN_INTERRUPT) {
- sync_send();
+ serial_low(); // sync_send() / senc_recv() need raise edge
+}
- uint8_t checksum = 0;
- for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
- serial_write_byte(serial_slave_buffer[i]);
+static void serial_send_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
+static
+void serial_send_packet(uint8_t *buffer, uint8_t size) {
+ for (uint8_t i = 0; i < size; ++i) {
+ uint8_t data;
+ data = buffer[i];
sync_send();
- checksum += serial_slave_buffer[i];
+ serial_write_chunk(data,8);
}
- serial_write_byte(checksum);
- sync_send();
+}
- // wait for the sync to finish sending
- serial_delay();
+static uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) NO_INLINE;
+static
+uint8_t serial_recive_packet(uint8_t *buffer, uint8_t size) {
+ uint8_t pecount = 0;
+ for (uint8_t i = 0; i < size; ++i) {
+ uint8_t data;
+ sync_recv();
+ data = serial_read_chunk(&pecount, 8);
+ buffer[i] = data;
+ }
+ return pecount == 0;
+}
- // read the middle of pulses
- _delay_us(SERIAL_DELAY/2);
+inline static
+void change_sender2reciver(void) {
+ sync_send(); //0
+ serial_delay_half1(); //1
+ serial_low(); //2
+ serial_input_with_pullup(); //2
+ serial_delay_half1(); //3
+}
- uint8_t checksum_computed = 0;
- for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
- serial_master_buffer[i] = serial_read_byte();
- sync_send();
- checksum_computed += serial_master_buffer[i];
+inline static
+void change_reciver2sender(void) {
+ sync_recv(); //0
+ serial_delay(); //1
+ serial_low(); //3
+ serial_output(); //3
+ serial_delay_half1(); //4
+}
+
+static inline uint8_t nibble_bits_count(uint8_t bits)
+{
+ bits = (bits & 0x5) + (bits >> 1 & 0x5);
+ bits = (bits & 0x3) + (bits >> 2 & 0x3);
+ return bits;
+}
+
+// interrupt handle to be used by the target device
+ISR(SERIAL_PIN_INTERRUPT) {
+
+#ifndef SERIAL_USE_MULTI_TRANSACTION
+ serial_low();
+ serial_output();
+ SSTD_t *trans = Transaction_table;
+#else
+ // recive transaction table index
+ uint8_t tid, bits;
+ uint8_t pecount = 0;
+ sync_recv();
+ bits = serial_read_chunk(&pecount,7);
+ tid = bits>>3;
+ bits = (bits&7) != nibble_bits_count(tid);
+ if( bits || pecount> 0 || tid > Transaction_table_size ) {
+ return;
}
- uint8_t checksum_received = serial_read_byte();
- sync_send();
+ serial_delay_half1();
- serial_input(); // end transaction
+ serial_high(); // response step1 low->high
+ serial_output();
+ _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT*SLAVE_INT_ACK_WIDTH);
+ SSTD_t *trans = &Transaction_table[tid];
+ serial_low(); // response step2 ack high->low
+#endif
- if ( checksum_computed != checksum_received ) {
- status |= SLAVE_DATA_CORRUPT;
+ // target send phase
+ if( trans->target2initiator_buffer_size > 0 )
+ serial_send_packet((uint8_t *)trans->target2initiator_buffer,
+ trans->target2initiator_buffer_size);
+ // target switch to input
+ change_sender2reciver();
+
+ // target recive phase
+ if( trans->initiator2target_buffer_size > 0 ) {
+ if (serial_recive_packet((uint8_t *)trans->initiator2target_buffer,
+ trans->initiator2target_buffer_size) ) {
+ *trans->status = TRANSACTION_ACCEPTED;
+ } else {
+ *trans->status = TRANSACTION_DATA_ERROR;
+ }
} else {
- status &= ~SLAVE_DATA_CORRUPT;
+ *trans->status = TRANSACTION_ACCEPTED;
}
-}
-inline
-bool serial_slave_DATA_CORRUPT(void) {
- return status & SLAVE_DATA_CORRUPT;
+ sync_recv(); //weit initiator output to high
}
-// Copies the serial_slave_buffer to the master and sends the
-// serial_master_buffer to the slave.
+/////////
+// start transaction by initiator
+//
+// int soft_serial_transaction(int sstd_index)
//
// Returns:
-// 0 => no error
-// 1 => slave did not respond
-int serial_update_buffers(void) {
- // this code is very time dependent, so we need to disable interrupts
+// TRANSACTION_END
+// TRANSACTION_NO_RESPONSE
+// TRANSACTION_DATA_ERROR
+// this code is very time dependent, so we need to disable interrupts
+#ifndef SERIAL_USE_MULTI_TRANSACTION
+int soft_serial_transaction(void) {
+ SSTD_t *trans = Transaction_table;
+#else
+int soft_serial_transaction(int sstd_index) {
+ if( sstd_index > Transaction_table_size )
+ return TRANSACTION_TYPE_ERROR;
+ SSTD_t *trans = &Transaction_table[sstd_index];
+#endif
cli();
- // signal to the slave that we want to start a transaction
+ // signal to the target that we want to start a transaction
serial_output();
serial_low();
- _delay_us(1);
+ _delay_us(SLAVE_INT_WIDTH_US);
- // wait for the slaves response
- serial_input();
- serial_high();
- _delay_us(SERIAL_DELAY);
+#ifndef SERIAL_USE_MULTI_TRANSACTION
+ // wait for the target response
+ serial_input_with_pullup();
+ _delay_us(SLAVE_INT_RESPONSE_TIME);
- // check if the slave is present
+ // check if the target is present
if (serial_read_pin()) {
- // slave failed to pull the line low, assume not present
+ // target failed to pull the line low, assume not present
+ serial_output();
+ serial_high();
+ *trans->status = TRANSACTION_NO_RESPONSE;
sei();
- return 1;
+ return TRANSACTION_NO_RESPONSE;
}
- // if the slave is present syncronize with it
- sync_recv();
-
- uint8_t checksum_computed = 0;
- // receive data from the slave
- for (int i = 0; i < SERIAL_SLAVE_BUFFER_LENGTH; ++i) {
- serial_slave_buffer[i] = serial_read_byte();
- sync_recv();
- checksum_computed += serial_slave_buffer[i];
+#else
+ // send transaction table index
+ int tid = (sstd_index<<3) | (7 & nibble_bits_count(sstd_index));
+ sync_send();
+ _delay_sub_us(TID_SEND_ADJUST);
+ serial_write_chunk(tid, 7);
+ serial_delay_half1();
+
+ // wait for the target response (step1 low->high)
+ serial_input_with_pullup();
+ while( !serial_read_pin() ) {
+ _delay_sub_us(2);
}
- uint8_t checksum_received = serial_read_byte();
- sync_recv();
- if (checksum_computed != checksum_received) {
- sei();
- return 1;
+ // check if the target is present (step2 high->low)
+ for( int i = 0; serial_read_pin(); i++ ) {
+ if (i > SLAVE_INT_ACK_WIDTH + 1) {
+ // slave failed to pull the line low, assume not present
+ serial_output();
+ serial_high();
+ *trans->status = TRANSACTION_NO_RESPONSE;
+ sei();
+ return TRANSACTION_NO_RESPONSE;
+ }
+ _delay_sub_us(SLAVE_INT_ACK_WIDTH_UNIT);
}
+#endif
- uint8_t checksum = 0;
- // send data to the slave
- for (int i = 0; i < SERIAL_MASTER_BUFFER_LENGTH; ++i) {
- serial_write_byte(serial_master_buffer[i]);
- sync_recv();
- checksum += serial_master_buffer[i];
+ // initiator recive phase
+ // if the target is present syncronize with it
+ if( trans->target2initiator_buffer_size > 0 ) {
+ if (!serial_recive_packet((uint8_t *)trans->target2initiator_buffer,
+ trans->target2initiator_buffer_size) ) {
+ serial_output();
+ serial_high();
+ *trans->status = TRANSACTION_DATA_ERROR;
+ sei();
+ return TRANSACTION_DATA_ERROR;
+ }
+ }
+
+ // initiator switch to output
+ change_reciver2sender();
+
+ // initiator send phase
+ if( trans->initiator2target_buffer_size > 0 ) {
+ serial_send_packet((uint8_t *)trans->initiator2target_buffer,
+ trans->initiator2target_buffer_size);
}
- serial_write_byte(checksum);
- sync_recv();
// always, release the line when not in use
- serial_output();
- serial_high();
+ sync_send();
+ *trans->status = TRANSACTION_END;
sei();
- return 0;
+ return TRANSACTION_END;
}
+#ifdef SERIAL_USE_MULTI_TRANSACTION
+int soft_serial_get_and_clean_status(int sstd_index) {
+ SSTD_t *trans = &Transaction_table[sstd_index];
+ cli();
+ int retval = *trans->status;
+ *trans->status = 0;;
+ sei();
+ return retval;
+}
+#endif
+
#endif
+
+// Helix serial.c history
+// 2018-1-29 fork from let's split and add PD2, modify sync_recv() (#2308, bceffdefc)
+// 2018-6-28 bug fix master to slave comm and speed up (#3255, 1038bbef4)
+// (adjusted with avr-gcc 4.9.2)
+// 2018-7-13 remove USE_SERIAL_PD2 macro (#3374, f30d6dd78)
+// (adjusted with avr-gcc 4.9.2)
+// 2018-8-11 add support multi-type transaction (#3608, feb5e4aae)
+// (adjusted with avr-gcc 4.9.2)
+// 2018-10-21 fix serial and RGB animation conflict (#4191, 4665e4fff)
+// (adjusted with avr-gcc 7.3.0)
+// 2018-10-28 re-adjust compiler depend value of delay (#4269, 8517f8a66)
+// (adjusted with avr-gcc 5.4.0, 7.3.0)
+// 2018-12-17 copy to TOP/quantum/split_common/ and remove backward compatibility code (#4669)
diff --git a/quantum/split_common/serial.h b/quantum/split_common/serial.h
index e566eb8a06..b6638b3bde 100644
--- a/quantum/split_common/serial.h
+++ b/quantum/split_common/serial.h
@@ -1,29 +1,65 @@
-#ifndef MY_SERIAL_H
-#define MY_SERIAL_H
+#ifndef SOFT_SERIAL_H
+#define SOFT_SERIAL_H
-#include "config.h"
#include <stdbool.h>
-/* TODO: some defines for interrupt setup */
-#define SERIAL_PIN_DDR DDRD
-#define SERIAL_PIN_PORT PORTD
-#define SERIAL_PIN_INPUT PIND
-#define SERIAL_PIN_MASK _BV(PD0)
-#define SERIAL_PIN_INTERRUPT INT0_vect
+// /////////////////////////////////////////////////////////////////
+// Need Soft Serial defines in config.h
+// /////////////////////////////////////////////////////////////////
+// ex.
+// #define SOFT_SERIAL_PIN ?? // ?? = D0,D1,D2,D3,E6
+// OPTIONAL: #define SELECT_SOFT_SERIAL_SPEED ? // ? = 1,2,3,4,5
+// // 1: about 137kbps (default)
+// // 2: about 75kbps
+// // 3: about 39kbps
+// // 4: about 26kbps
+// // 5: about 20kbps
+//
+// //// USE simple API (using signle-type transaction function)
+// /* nothing */
+// //// USE flexible API (using multi-type transaction function)
+// #define SERIAL_USE_MULTI_TRANSACTION
+//
+// /////////////////////////////////////////////////////////////////
-#define SERIAL_SLAVE_BUFFER_LENGTH MATRIX_ROWS/2
-#define SERIAL_MASTER_BUFFER_LENGTH 1
+// Soft Serial Transaction Descriptor
+typedef struct _SSTD_t {
+ uint8_t *status;
+ uint8_t initiator2target_buffer_size;
+ uint8_t *initiator2target_buffer;
+ uint8_t target2initiator_buffer_size;
+ uint8_t *target2initiator_buffer;
+} SSTD_t;
+#define TID_LIMIT( table ) (sizeof(table) / sizeof(SSTD_t))
-// Address location defines
-#define SERIAL_BACKLIT_START 0x00
+// initiator is transaction start side
+void soft_serial_initiator_init(SSTD_t *sstd_table, int sstd_table_size);
+// target is interrupt accept side
+void soft_serial_target_init(SSTD_t *sstd_table, int sstd_table_size);
-// Buffers for master - slave communication
-extern volatile uint8_t serial_slave_buffer[SERIAL_SLAVE_BUFFER_LENGTH];
-extern volatile uint8_t serial_master_buffer[SERIAL_MASTER_BUFFER_LENGTH];
-
-void serial_master_init(void);
-void serial_slave_init(void);
-int serial_update_buffers(void);
-bool serial_slave_data_corrupt(void);
+// initiator resullt
+#define TRANSACTION_END 0
+#define TRANSACTION_NO_RESPONSE 0x1
+#define TRANSACTION_DATA_ERROR 0x2
+#define TRANSACTION_TYPE_ERROR 0x4
+#ifndef SERIAL_USE_MULTI_TRANSACTION
+int soft_serial_transaction(void);
+#else
+int soft_serial_transaction(int sstd_index);
+#endif
+// target status
+// *SSTD_t.status has
+// initiator:
+// TRANSACTION_END
+// or TRANSACTION_NO_RESPONSE
+// or TRANSACTION_DATA_ERROR
+// target:
+// TRANSACTION_DATA_ERROR
+// or TRANSACTION_ACCEPTED
+#define TRANSACTION_ACCEPTED 0x8
+#ifdef SERIAL_USE_MULTI_TRANSACTION
+int soft_serial_get_and_clean_status(int sstd_index);
#endif
+
+#endif /* SOFT_SERIAL_H */
diff --git a/quantum/split_common/split_util.c b/quantum/split_common/split_util.c
index 13b09d5b81..e41b6f6386 100644
--- a/quantum/split_common/split_util.c
+++ b/quantum/split_common/split_util.c
@@ -1,31 +1,21 @@
-#include <avr/io.h>
-#include <avr/wdt.h>
-#include <avr/power.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-#include <avr/eeprom.h>
#include "split_util.h"
#include "matrix.h"
#include "keyboard.h"
#include "config.h"
#include "timer.h"
#include "split_flags.h"
+#include "quantum.h"
-#ifdef RGBLIGHT_ENABLE
-# include "rgblight.h"
+#ifdef EE_HANDS
+# include "tmk_core/common/eeprom.h"
#endif
+
#ifdef BACKLIGHT_ENABLE
# include "backlight.h"
#endif
-#ifdef SPLIT_HAND_PIN
-# include "pincontrol.h"
-#endif
-
#if defined(USE_I2C) || defined(EH)
# include "i2c.h"
-#else
-# include "serial.h"
#endif
volatile bool isLeftHand = true;
@@ -35,14 +25,13 @@ volatile uint8_t setTries = 0;
static void setup_handedness(void) {
#ifdef SPLIT_HAND_PIN
// Test pin SPLIT_HAND_PIN for High/Low, if low it's right hand
- pinMode(SPLIT_HAND_PIN, PinDirectionInput);
- isLeftHand = digitalRead(SPLIT_HAND_PIN);
+ setPinInput(SPLIT_HAND_PIN);
+ isLeftHand = readPin(SPLIT_HAND_PIN);
#else
#ifdef EE_HANDS
isLeftHand = eeprom_read_byte(EECONFIG_HANDEDNESS);
#else
- // I2C_MASTER_RIGHT is deprecated, use MASTER_RIGHT instead, since this works for both serial and i2c
- #if defined(I2C_MASTER_RIGHT) || defined(MASTER_RIGHT)
+ #ifdef MASTER_RIGHT
isLeftHand = !has_usb();
#else
isLeftHand = has_usb();
@@ -94,7 +83,7 @@ void split_keyboard_setup(void) {
void keyboard_slave_loop(void) {
matrix_init();
-
+
//Init RGB
#ifdef RGBLIGHT_ENABLE
rgblight_init();
@@ -103,17 +92,17 @@ void keyboard_slave_loop(void) {
while (1) {
// Matrix Slave Scan
matrix_slave_scan();
-
+
// Read Backlight Info
#ifdef BACKLIGHT_ENABLE
- if (BACKLIT_DIRTY) {
- #ifdef USE_I2C
+ #ifdef USE_I2C
+ if (BACKLIT_DIRTY) {
backlight_set(i2c_slave_buffer[I2C_BACKLIT_START]);
- #else // USE_SERIAL
- backlight_set(serial_master_buffer[SERIAL_BACKLIT_START]);
- #endif
- BACKLIT_DIRTY = false;
- }
+ BACKLIT_DIRTY = false;
+ }
+ #else // USE_SERIAL
+ backlight_set(serial_m2s_buffer.backlight_level);
+ #endif
#endif
// Read RGB Info
#ifdef RGBLIGHT_ENABLE
@@ -122,14 +111,14 @@ void keyboard_slave_loop(void) {
// Disable interupts (RGB data is big)
cli();
// Create new DWORD for RGB data
- uint32_t dword;
-
+ uint32_t dword;
+
// Fill the new DWORD with the data that was sent over
uint8_t *dword_dat = (uint8_t *)(&dword);
for (int i = 0; i < 4; i++) {
dword_dat[i] = i2c_slave_buffer[I2C_RGB_START+i];
}
-
+
// Update the RGB now with the new data and set RGB_DIRTY to false
rgblight_update_dword(dword);
RGB_DIRTY = false;
@@ -137,7 +126,9 @@ void keyboard_slave_loop(void) {
sei();
}
#else // USE_SERIAL
+ #ifdef RGBLIGHT_SPLIT
// Add serial implementation for RGB here
+ #endif
#endif
#endif
}
diff --git a/quantum/template/avr/config.h b/quantum/template/avr/config.h
index caa72af0c2..eed50e5c04 100644
--- a/quantum/template/avr/config.h
+++ b/quantum/template/avr/config.h
@@ -48,17 +48,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* COL2ROW, ROW2COL, or CUSTOM_MATRIX */
#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 SOFT_SERIAL_PIN D0 // or D1, D2, D3, E6
+
// #define BACKLIGHT_PIN B7
// #define BACKLIGHT_BREATHING
// #define BACKLIGHT_LEVELS 3
// #define RGB_DI_PIN E2
// #ifdef RGB_DI_PIN
-// #define RGBLIGHT_ANIMATIONS
-// #define RGBLED_NUM 16
-// #define RGBLIGHT_HUE_STEP 8
-// #define RGBLIGHT_SAT_STEP 8
-// #define RGBLIGHT_VAL_STEP 8
+// #define RGBLED_NUM 16
+// #define RGBLIGHT_HUE_STEP 8
+// #define RGBLIGHT_SAT_STEP 8
+// #define RGBLIGHT_VAL_STEP 8
+// #define RGBLIGHT_LIMIT_VAL 255 /* The maximum brightness level */
+// #define RGBLIGHT_SLEEP /* If defined, the RGB lighting will be switched off when the host goes to sleep */
+// /*== all animations enable ==*/
+// #define RGBLIGHT_ANIMATIONS
+// /*== or choose animations ==*/
+// #define RGBLIGHT_EFFECT_BREATHING
+// #define RGBLIGHT_EFFECT_RAINBOW_MOOD
+// #define RGBLIGHT_EFFECT_RAINBOW_SWIRL
+// #define RGBLIGHT_EFFECT_SNAKE
+// #define RGBLIGHT_EFFECT_KNIGHT
+// #define RGBLIGHT_EFFECT_CHRISTMAS
+// #define RGBLIGHT_EFFECT_STATIC_GRADIENT
+// #define RGBLIGHT_EFFECT_RGB_TEST
+// #define RGBLIGHT_EFFECT_ALTERNATING
// #endif
/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */
@@ -222,3 +240,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#endif
*/
+/* Bootmagic Lite key configuration */
+// #define BOOTMAGIC_LITE_ROW 0
+// #define BOOTMAGIC_LITE_COLUMN 0
diff --git a/quantum/template/base/readme.md b/quantum/template/avr/readme.md
index d9349811d0..d243c66a94 100644
--- a/quantum/template/base/readme.md
+++ b/quantum/template/avr/readme.md
@@ -12,4 +12,4 @@ Make example for this keyboard (after setting up your build environment):
make %KEYBOARD%:default
-See [build environment setup](https://docs.qmk.fm/build_environment_setup.html) then the [make instructions](https://docs.qmk.fm/make_instructions.html) for more information. \ No newline at end of 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).
diff --git a/quantum/template/avr/rules.mk b/quantum/template/avr/rules.mk
index 92f3a03a92..383a3594b4 100644
--- a/quantum/template/avr/rules.mk
+++ b/quantum/template/avr/rules.mk
@@ -39,13 +39,24 @@ F_USB = $(F_CPU)
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
-# Boot Section Size in *bytes*
-# Teensy halfKay 512
-# Teensy++ halfKay 1024
-# Atmel DFU loader 4096
-# LUFA bootloader 4096
-# USBaspLoader 2048
-OPT_DEFS += -DBOOTLOADER_SIZE=4096
+# Bootloader selection
+# Teensy halfkay
+# Pro Micro caterina
+# Atmel DFU atmel-dfu
+# LUFA DFU lufa-dfu
+# QMK DFU qmk-dfu
+# atmega32a bootloadHID
+BOOTLOADER = atmel-dfu
+
+
+# If you don't know the bootloader type, then you can specify the
+# Boot Section Size in *bytes* by uncommenting out the OPT_DEFS line
+# Teensy halfKay 512
+# Teensy++ halfKay 1024
+# Atmel DFU loader 4096
+# LUFA bootloader 4096
+# USBaspLoader 2048
+# OPT_DEFS += -DBOOTLOADER_SIZE=4096
# Build Options
diff --git a/quantum/template/avr/template.h b/quantum/template/avr/template.h
index 031efc9529..0d626ed50b 100644
--- a/quantum/template/avr/template.h
+++ b/quantum/template/avr/template.h
@@ -18,12 +18,14 @@
#include "quantum.h"
-// This a shortcut to help you visually see your layout.
-// The following is an example using the Planck MIT layout
-// The first section contains all of the arguments representing the physical
-// layout of the board and position of the keys
-// The second converts the arguments into a two-dimensional array which
-// represents the switch matrix.
+/* This a shortcut to help you visually see your layout.
+ *
+ * The first section contains all of the arguments representing the physical
+ * layout of the board and position of the keys.
+ *
+ * The second converts the arguments into a two-dimensional array which
+ * represents the switch matrix.
+ */
#define LAYOUT( \
K00, K01, K02, \
K10, K11 \
diff --git a/quantum/template/base/keymaps/default/keymap.c b/quantum/template/base/keymaps/default/keymap.c
index 14a8bc0f28..5f0730c8a9 100644
--- a/quantum/template/base/keymaps/default/keymap.c
+++ b/quantum/template/base/keymaps/default/keymap.c
@@ -15,32 +15,40 @@
*/
#include QMK_KEYBOARD_H
-const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
-[0] = LAYOUT( /* Base */
- KC_A, KC_1, KC_H, \
- KC_TAB, KC_SPC \
-),
+// Defines the keycodes used by our macros in process_record_user
+enum custom_keycodes {
+ QMKBEST = SAFE_RANGE,
+ QMKURL
};
-const uint16_t PROGMEM fn_actions[] = {
-
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [0] = LAYOUT( /* Base */
+ KC_A, KC_1, KC_H, \
+ KC_TAB, KC_SPC \
+ ),
};
-const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
-{
- // MACRODOWN only works in this function
- switch(id) {
- case 0:
- if (record->event.pressed) {
- register_code(KC_RSFT);
- } else {
- unregister_code(KC_RSFT);
- }
- break;
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+ switch (keycode) {
+ case QMKBEST:
+ if (record->event.pressed) {
+ // when keycode QMKBEST is pressed
+ SEND_STRING("QMK is the best thing ever!");
+ } else {
+ // when keycode QMKBEST is released
}
- return MACRO_NONE;
-};
-
+ break;
+ case QMKURL:
+ if (record->event.pressed) {
+ // when keycode QMKURL is pressed
+ SEND_STRING("https://qmk.fm/" SS_TAP(X_ENTER));
+ } else {
+ // when keycode QMKURL is released
+ }
+ break;
+ }
+ return true;
+}
void matrix_init_user(void) {
@@ -50,10 +58,6 @@ void matrix_scan_user(void) {
}
-bool process_record_user(uint16_t keycode, keyrecord_t *record) {
- return true;
-}
-
void led_set_user(uint8_t usb_led) {
}
diff --git a/quantum/template/ps2avrgb/config.h b/quantum/template/ps2avrgb/config.h
index d2c83781fa..4ff3513bc7 100644
--- a/quantum/template/ps2avrgb/config.h
+++ b/quantum/template/ps2avrgb/config.h
@@ -44,3 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* key combination for command */
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
+
+/* Bootmagic Lite key configuration */
+// #define BOOTMAGIC_LITE_ROW 0
+// #define BOOTMAGIC_LITE_COLUMN 0
diff --git a/quantum/template/ps2avrgb/readme.md b/quantum/template/ps2avrgb/readme.md
new file mode 100644
index 0000000000..feec722a52
--- /dev/null
+++ b/quantum/template/ps2avrgb/readme.md
@@ -0,0 +1,44 @@
+# %KEYBOARD%
+
+![%KEYBOARD%](imgur.com image replace me!)
+
+A short description of the keyboard/project
+
+Keyboard Maintainer: [You](https://github.com/yourusername)
+Hardware Supported: The PCBs, controllers supported
+Hardware Availability: links to where you can find this hardware
+
+Make example for this keyboard (after setting up your build environment):
+
+ make %KEYBOARD%:default
+
+Flashing
+
+ps2avr(GB) boards use an atmega32a microcontroller and a different bootloader. It is not flashable using the regular QMK methods.
+
+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 python
+ brew 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).
diff --git a/quantum/template/ps2avrgb/rules.mk b/quantum/template/ps2avrgb/rules.mk
index 68d50aec67..85603f955c 100644
--- a/quantum/template/ps2avrgb/rules.mk
+++ b/quantum/template/ps2avrgb/rules.mk
@@ -31,8 +31,8 @@ F_CPU = 12000000
BOOTLOADER = bootloadHID
# build options
-BOOTMAGIC_ENABLE = yes
-MOUSEKEY_ENABLE = yes
+BOOTMAGIC_ENABLE = full
+MOUSEKEY_ENABLE = no
EXTRAKEY_ENABLE = yes
CONSOLE_ENABLE = yes
COMMAND_ENABLE = yes
diff --git a/quantum/template/ps2avrgb/template.h b/quantum/template/ps2avrgb/template.h
index c3924ee71f..b4d6f46624 100644
--- a/quantum/template/ps2avrgb/template.h
+++ b/quantum/template/ps2avrgb/template.h
@@ -18,10 +18,14 @@
#include "quantum.h"
-// This a shortcut to help you visually see your layout.
-// The following is an example using the Planck MIT layout
-// The first section contains all of the arguments
-// The second converts the arguments into a two-dimensional array
+/* This a shortcut to help you visually see your layout.
+ *
+ * The first section contains all of the arguments representing the physical
+ * layout of the board and position of the keys.
+ *
+ * The second converts the arguments into a two-dimensional array which
+ * represents the switch matrix.
+ */
#define LAYOUT( \
k00, k01, k02, \
k10, k11 \