summaryrefslogtreecommitdiff
path: root/tmk_core/common
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/common')
-rw-r--r--tmk_core/common/action.c48
-rw-r--r--tmk_core/common/action.h5
-rw-r--r--tmk_core/common/action_layer.c316
-rw-r--r--tmk_core/common/action_layer.h8
-rw-r--r--tmk_core/common/action_util.c4
-rw-r--r--tmk_core/common/arm_atsam/bootloader.c51
-rw-r--r--tmk_core/common/arm_atsam/eeprom.c98
-rw-r--r--tmk_core/common/arm_atsam/printf.c66
-rw-r--r--tmk_core/common/arm_atsam/printf.h11
-rw-r--r--tmk_core/common/arm_atsam/suspend.c85
-rw-r--r--tmk_core/common/arm_atsam/timer.c43
-rw-r--r--tmk_core/common/avr/suspend.c41
-rw-r--r--tmk_core/common/backlight.c51
-rw-r--r--tmk_core/common/backlight.h7
-rwxr-xr-xtmk_core/common/chibios/eeprom_stm32.c215
-rwxr-xr-xtmk_core/common/chibios/eeprom_stm32.h81
-rw-r--r--tmk_core/common/chibios/eeprom_teensy.c (renamed from tmk_core/common/chibios/eeprom.c)0
-rwxr-xr-xtmk_core/common/chibios/flash_stm32.c203
-rwxr-xr-xtmk_core/common/chibios/flash_stm32.h54
-rw-r--r--tmk_core/common/command.c4
-rw-r--r--tmk_core/common/command.h5
-rw-r--r--tmk_core/common/eeconfig.c112
-rw-r--r--tmk_core/common/eeconfig.h29
-rw-r--r--tmk_core/common/eeprom.h1
-rw-r--r--tmk_core/common/host.c22
-rw-r--r--tmk_core/common/host.h11
-rw-r--r--tmk_core/common/keyboard.c24
-rw-r--r--tmk_core/common/keyboard.h4
-rw-r--r--tmk_core/common/keycode.h11
-rw-r--r--tmk_core/common/print.h42
-rw-r--r--tmk_core/common/progmem.h6
-rw-r--r--tmk_core/common/report.c21
-rw-r--r--tmk_core/common/report.h52
-rw-r--r--tmk_core/common/wait.h4
34 files changed, 1469 insertions, 266 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c
index f7c039f457..ec8d6ed7b9 100644
--- a/tmk_core/common/action.c
+++ b/tmk_core/common/action.c
@@ -120,7 +120,7 @@ void process_hand_swap(keyevent_t *event) {
}
#endif
-#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
bool disable_action_cache = false;
void process_record_nocache(keyrecord_t *record)
@@ -653,7 +653,7 @@ void process_action(keyrecord_t *record, action_t action)
#ifndef NO_ACTION_TAPPING
#ifdef RETRO_TAPPING
- if (!is_tap_key(record->event.key)) {
+ if (!is_tap_action(action)) {
retro_tapping_counter = 0;
} else {
if (event.pressed) {
@@ -773,6 +773,13 @@ void register_code(uint8_t code)
else if IS_CONSUMER(code) {
host_consumer_send(KEYCODE2CONSUMER(code));
}
+
+ #ifdef MOUSEKEY_ENABLE
+ else if IS_MOUSEKEY(code) {
+ mousekey_on(code);
+ mousekey_send();
+ }
+ #endif
}
/** \brief Utilities for actions. (FIXME: Needs better description)
@@ -832,6 +839,24 @@ void unregister_code(uint8_t code)
else if IS_CONSUMER(code) {
host_consumer_send(0);
}
+ #ifdef MOUSEKEY_ENABLE
+ else if IS_MOUSEKEY(code) {
+ mousekey_off(code);
+ mousekey_send();
+ }
+ #endif
+}
+
+/** \brief Utilities for actions. (FIXME: Needs better description)
+ *
+ * FIXME: Needs documentation.
+ */
+void tap_code(uint8_t code) {
+ register_code(code);
+ #if TAP_CODE_DELAY > 0
+ wait_ms(TAP_CODE_DELAY);
+ #endif
+ unregister_code(code);
}
/** \brief Utilities for actions. (FIXME: Needs better description)
@@ -874,9 +899,18 @@ void clear_keyboard(void)
*/
void clear_keyboard_but_mods(void)
{
+ clear_keys();
+ clear_keyboard_but_mods_and_keys();
+}
+
+/** \brief Utilities for actions. (FIXME: Needs better description)
+ *
+ * FIXME: Needs documentation.
+ */
+void clear_keyboard_but_mods_and_keys()
+{
clear_weak_mods();
clear_macro_mods();
- clear_keys();
send_keyboard_report();
#ifdef MOUSEKEY_ENABLE
mousekey_clear();
@@ -895,7 +929,15 @@ void clear_keyboard_but_mods(void)
bool is_tap_key(keypos_t key)
{
action_t action = layer_switch_get_action(key);
+ return is_tap_action(action);
+}
+/** \brief Utilities for actions. (FIXME: Needs better description)
+ *
+ * FIXME: Needs documentation.
+ */
+bool is_tap_action(action_t action)
+{
switch (action.kind.id) {
case ACT_LMODS_TAP:
case ACT_RMODS_TAP:
diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h
index acc55c7d38..799e3bb0ef 100644
--- a/tmk_core/common/action.h
+++ b/tmk_core/common/action.h
@@ -62,7 +62,7 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
bool process_record_quantum(keyrecord_t *record);
/* Utilities for actions. */
-#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
extern bool disable_action_cache;
#endif
@@ -88,13 +88,16 @@ void process_record(keyrecord_t *record);
void process_action(keyrecord_t *record, action_t action);
void register_code(uint8_t code);
void unregister_code(uint8_t code);
+void tap_code(uint8_t code);
void register_mods(uint8_t mods);
void unregister_mods(uint8_t mods);
//void set_mods(uint8_t mods);
void clear_keyboard(void);
void clear_keyboard_but_mods(void);
+void clear_keyboard_but_mods_and_keys(void);
void layer_switch(uint8_t new_layer);
bool is_tap_key(keypos_t key);
+bool is_tap_action(action_t action);
#ifndef NO_ACTION_TAPPING
void process_record_tap_hint(keyrecord_t *record);
diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c
index f3cd381ab0..6ff8c5549b 100644
--- a/tmk_core/common/action_layer.c
+++ b/tmk_core/common/action_layer.c
@@ -15,71 +15,78 @@
*/
uint32_t default_layer_state = 0;
+/** \brief Default Layer State Set At user Level
+ *
+ * Run user code on default layer state change
+ */
+__attribute__((weak))
+uint32_t default_layer_state_set_user(uint32_t state) {
+ return state;
+}
+
/** \brief Default Layer State Set At Keyboard Level
*
- * FIXME: Needs docs
+ * Run keyboard code on default layer state change
*/
__attribute__((weak))
uint32_t default_layer_state_set_kb(uint32_t state) {
- return state;
+ return default_layer_state_set_user(state);
}
/** \brief Default Layer State Set
*
- * FIXME: Needs docs
+ * Static function to set the default layer state, prints debug info and clears keys
*/
-static void default_layer_state_set(uint32_t state)
-{
- state = default_layer_state_set_kb(state);
- debug("default_layer_state: ");
- default_layer_debug(); debug(" to ");
- default_layer_state = state;
- default_layer_debug(); debug("\n");
- clear_keyboard_but_mods(); // To avoid stuck keys
+static void default_layer_state_set(uint32_t state) {
+ state = default_layer_state_set_kb(state);
+ debug("default_layer_state: ");
+ default_layer_debug(); debug(" to ");
+ default_layer_state = state;
+ default_layer_debug(); debug("\n");
+#ifdef STRICT_LAYER_RELEASE
+ clear_keyboard_but_mods(); // To avoid stuck keys
+#else
+ clear_keyboard_but_mods_and_keys(); // Don't reset held keys
+#endif
}
/** \brief Default Layer Print
*
- * FIXME: Needs docs
+ * Print out the hex value of the 32-bit default layer state, as well as the value of the highest bit.
*/
-void default_layer_debug(void)
-{
- dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
+void default_layer_debug(void) {
+ dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
}
/** \brief Default Layer Set
*
- * FIXME: Needs docs
+ * Sets the default layer state.
*/
-void default_layer_set(uint32_t state)
-{
- default_layer_state_set(state);
+void default_layer_set(uint32_t state) {
+ default_layer_state_set(state);
}
#ifndef NO_ACTION_LAYER
/** \brief Default Layer Or
*
- * FIXME: Needs docs
+ * Turns on the default layer based on matching bits between specifed layer and existing layer state
*/
-void default_layer_or(uint32_t state)
-{
- default_layer_state_set(default_layer_state | state);
+void default_layer_or(uint32_t state) {
+ default_layer_state_set(default_layer_state | state);
}
/** \brief Default Layer And
*
- * FIXME: Needs docs
+ * Turns on default layer based on matching enabled bits between specifed layer and existing layer state
*/
-void default_layer_and(uint32_t state)
-{
- default_layer_state_set(default_layer_state & state);
+void default_layer_and(uint32_t state) {
+ default_layer_state_set(default_layer_state & state);
}
/** \brief Default Layer Xor
*
- * FIXME: Needs docs
+ * Turns on default layer based on non-matching bits between specifed layer and existing layer state
*/
-void default_layer_xor(uint32_t state)
-{
- default_layer_state_set(default_layer_state ^ state);
+void default_layer_xor(uint32_t state) {
+ default_layer_state_set(default_layer_state ^ state);
}
#endif
@@ -91,166 +98,168 @@ uint32_t layer_state = 0;
/** \brief Layer state set user
*
- * FIXME: Needs docs
+ * Runs user code on layer state change
*/
__attribute__((weak))
uint32_t layer_state_set_user(uint32_t state) {
- return state;
+ return state;
}
/** \brief Layer state set keyboard
*
- * FIXME: Needs docs
+ * Runs keyboard code on layer state change
*/
__attribute__((weak))
uint32_t layer_state_set_kb(uint32_t state) {
- return layer_state_set_user(state);
+ return layer_state_set_user(state);
}
/** \brief Layer state set
*
- * FIXME: Needs docs
+ * Sets the layer to match the specifed state (a bitmask)
*/
-void layer_state_set(uint32_t state)
-{
- state = layer_state_set_kb(state);
- dprint("layer_state: ");
- layer_debug(); dprint(" to ");
- layer_state = state;
- layer_debug(); dprintln();
- clear_keyboard_but_mods(); // To avoid stuck keys
+void layer_state_set(uint32_t state) {
+ state = layer_state_set_kb(state);
+ dprint("layer_state: ");
+ layer_debug(); dprint(" to ");
+ layer_state = state;
+ layer_debug(); dprintln();
+#ifdef STRICT_LAYER_RELEASE
+ clear_keyboard_but_mods(); // To avoid stuck keys
+#else
+ clear_keyboard_but_mods_and_keys(); // Don't reset held keys
+#endif
}
/** \brief Layer clear
*
- * FIXME: Needs docs
+ * Turn off all layers
*/
-void layer_clear(void)
-{
- layer_state_set(0);
+void layer_clear(void) {
+ layer_state_set(0);
}
/** \brief Layer state is
*
- * FIXME: Needs docs
+ * Return whether the given state is on (it might still be shadowed by a higher state, though)
*/
-bool layer_state_is(uint8_t layer)
-{
- return layer_state_cmp(layer_state, layer);
+bool layer_state_is(uint8_t layer) {
+ return layer_state_cmp(layer_state, layer);
}
/** \brief Layer state compare
*
- * FIXME: Needs docs
+ * Used for comparing layers {mostly used for unit testing}
*/
bool layer_state_cmp(uint32_t cmp_layer_state, uint8_t layer) {
- if (!cmp_layer_state) { return layer == 0; }
- return (cmp_layer_state & (1UL<<layer)) != 0;
+ if (!cmp_layer_state) { return layer == 0; }
+ return (cmp_layer_state & (1UL<<layer)) != 0;
}
/** \brief Layer move
*
- * FIXME: Needs docs
+ * Turns on the given layer and turn off all other layers
*/
-void layer_move(uint8_t layer)
-{
- layer_state_set(1UL<<layer);
+void layer_move(uint8_t layer) {
+ layer_state_set(1UL<<layer);
}
/** \brief Layer on
*
- * FIXME: Needs docs
+ * Turns on given layer
*/
-void layer_on(uint8_t layer)
-{
- layer_state_set(layer_state | (1UL<<layer));
+void layer_on(uint8_t layer) {
+ layer_state_set(layer_state | (1UL<<layer));
}
/** \brief Layer off
*
- * FIXME: Needs docs
+ * Turns off given layer
*/
-void layer_off(uint8_t layer)
-{
- layer_state_set(layer_state & ~(1UL<<layer));
+void layer_off(uint8_t layer) {
+ layer_state_set(layer_state & ~(1UL<<layer));
}
/** \brief Layer invert
*
- * FIXME: Needs docs
+ * Toggle the given layer (set it if it's unset, or unset it if it's set)
*/
-void layer_invert(uint8_t layer)
-{
- layer_state_set(layer_state ^ (1UL<<layer));
+void layer_invert(uint8_t layer) {
+ layer_state_set(layer_state ^ (1UL<<layer));
}
/** \brief Layer or
*
- * FIXME: Needs docs
+ * Turns on layers based on matching bits between specifed layer and existing layer state
*/
-void layer_or(uint32_t state)
-{
- layer_state_set(layer_state | state);
+void layer_or(uint32_t state) {
+ layer_state_set(layer_state | state);
}
/** \brief Layer and
*
- * FIXME: Needs docs
+ * Turns on layers based on matching enabled bits between specifed layer and existing layer state
*/
-void layer_and(uint32_t state)
-{
- layer_state_set(layer_state & state);
+void layer_and(uint32_t state) {
+ layer_state_set(layer_state & state);
}
/** \brief Layer xor
*
- * FIXME: Needs docs
+ * Turns on layers based on non-matching bits between specifed layer and existing layer state
*/
-void layer_xor(uint32_t state)
-{
- layer_state_set(layer_state ^ state);
+void layer_xor(uint32_t state) {
+ layer_state_set(layer_state ^ state);
}
/** \brief Layer debug printing
*
- * FIXME: Needs docs
+ * Print out the hex value of the 32-bit layer state, as well as the value of the highest bit.
*/
-void layer_debug(void)
-{
- dprintf("%08lX(%u)", layer_state, biton32(layer_state));
+void layer_debug(void) {
+ dprintf("%08lX(%u)", layer_state, biton32(layer_state));
}
#endif
-#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
+/** \brief source layer cache
+ */
+
uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}};
-void update_source_layers_cache(keypos_t key, uint8_t layer)
-{
- const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
- const uint8_t storage_row = key_number / 8;
- const uint8_t storage_bit = key_number % 8;
-
- for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
- source_layers_cache[storage_row][bit_number] ^=
- (-((layer & (1U << bit_number)) != 0)
- ^ source_layers_cache[storage_row][bit_number])
- & (1U << storage_bit);
- }
+/** \brief update source layers cache
+ *
+ * Updates the cached keys when changing layers
+ */
+void update_source_layers_cache(keypos_t key, uint8_t layer) {
+ const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
+ const uint8_t storage_row = key_number / 8;
+ const uint8_t storage_bit = key_number % 8;
+
+ for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
+ source_layers_cache[storage_row][bit_number] ^=
+ (-((layer & (1U << bit_number)) != 0)
+ ^ source_layers_cache[storage_row][bit_number])
+ & (1U << storage_bit);
+ }
}
-uint8_t read_source_layers_cache(keypos_t key)
-{
- const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
- const uint8_t storage_row = key_number / 8;
- const uint8_t storage_bit = key_number % 8;
- uint8_t layer = 0;
-
- for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
- layer |=
- ((source_layers_cache[storage_row][bit_number]
- & (1U << storage_bit)) != 0)
- << bit_number;
- }
-
- return layer;
+/** \brief read source layers cache
+ *
+ * reads the cached keys stored when the layer was changed
+ */
+uint8_t read_source_layers_cache(keypos_t key) {
+ const uint8_t key_number = key.col + (key.row * MATRIX_COLS);
+ const uint8_t storage_row = key_number / 8;
+ const uint8_t storage_bit = key_number % 8;
+ uint8_t layer = 0;
+
+ for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) {
+ layer |=
+ ((source_layers_cache[storage_row][bit_number]
+ & (1U << storage_bit)) != 0)
+ << bit_number;
+ }
+
+ return layer;
}
#endif
@@ -261,61 +270,58 @@ uint8_t read_source_layers_cache(keypos_t key)
* when the layer is switched after the down event but before the up
* event as they may get stuck otherwise.
*/
-action_t store_or_get_action(bool pressed, keypos_t key)
-{
-#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
- if (disable_action_cache) {
- return layer_switch_get_action(key);
- }
-
- uint8_t layer;
-
- if (pressed) {
- layer = layer_switch_get_layer(key);
- update_source_layers_cache(key, layer);
- }
- else {
- layer = read_source_layers_cache(key);
- }
- return action_for_key(layer, key);
-#else
+action_t store_or_get_action(bool pressed, keypos_t key) {
+#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
+ if (disable_action_cache) {
return layer_switch_get_action(key);
+ }
+
+ uint8_t layer;
+
+ if (pressed) {
+ layer = layer_switch_get_layer(key);
+ update_source_layers_cache(key, layer);
+ }
+ else {
+ layer = read_source_layers_cache(key);
+ }
+ return action_for_key(layer, key);
+#else
+ return layer_switch_get_action(key);
#endif
}
/** \brief Layer switch get layer
*
- * FIXME: Needs docs
+ * Gets the layer based on key info
*/
-int8_t layer_switch_get_layer(keypos_t key)
-{
+int8_t layer_switch_get_layer(keypos_t key) {
#ifndef NO_ACTION_LAYER
- action_t action;
- action.code = ACTION_TRANSPARENT;
-
- uint32_t layers = layer_state | default_layer_state;
- /* check top layer first */
- for (int8_t i = 31; i >= 0; i--) {
- if (layers & (1UL<<i)) {
- action = action_for_key(i, key);
- if (action.code != ACTION_TRANSPARENT) {
- return i;
- }
- }
+ action_t action;
+ action.code = ACTION_TRANSPARENT;
+
+ uint32_t layers = layer_state | default_layer_state;
+ /* check top layer first */
+ for (int8_t i = 31; i >= 0; i--) {
+ if (layers & (1UL<<i)) {
+ action = action_for_key(i, key);
+ if (action.code != ACTION_TRANSPARENT) {
+ return i;
+ }
}
- /* fall back to layer 0 */
- return 0;
+ }
+ /* fall back to layer 0 */
+ return 0;
#else
- return biton32(default_layer_state);
+ return biton32(default_layer_state);
#endif
}
/** \brief Layer switch get layer
*
- * FIXME: Needs docs
+ * Gets action code based on key position
*/
-action_t layer_switch_get_action(keypos_t key)
-{
- return action_for_key(layer_switch_get_layer(key), key);
+action_t layer_switch_get_action(keypos_t key) {
+ return action_for_key(layer_switch_get_layer(key), key);
}
diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h
index 72a6bd8f68..f1551d2519 100644
--- a/tmk_core/common/action_layer.h
+++ b/tmk_core/common/action_layer.h
@@ -31,6 +31,8 @@ void default_layer_set(uint32_t state);
__attribute__((weak))
uint32_t default_layer_state_set_kb(uint32_t state);
+__attribute__((weak))
+uint32_t default_layer_state_set_user(uint32_t state);
#ifndef NO_ACTION_LAYER
/* bitwise operation */
@@ -80,15 +82,13 @@ void layer_xor(uint32_t state);
#define layer_or(state)
#define layer_and(state)
#define layer_xor(state)
+#endif
-__attribute__((weak))
uint32_t layer_state_set_user(uint32_t state);
-__attribute__((weak))
uint32_t layer_state_set_kb(uint32_t state);
-#endif
/* pressed actions cache */
-#if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS)
+#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
/* The number of bits needed to represent the layer number: log2(32). */
#define MAX_LAYER_BITS 5
void update_source_layers_cache(keypos_t key, uint8_t layer);
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c
index afd4ae8b25..58401ace55 100644
--- a/tmk_core/common/action_util.c
+++ b/tmk_core/common/action_util.c
@@ -54,7 +54,7 @@ int8_t get_oneshot_locked_mods(void) { return oneshot_locked_mods; }
void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; }
void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; }
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
-static int16_t oneshot_time = 0;
+static uint16_t oneshot_time = 0;
bool has_oneshot_mods_timed_out(void) {
return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT;
}
@@ -79,7 +79,7 @@ inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }
#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
-static int16_t oneshot_layer_time = 0;
+static uint16_t oneshot_layer_time = 0;
inline bool has_oneshot_layer_timed_out() {
return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT &&
!(get_oneshot_layer_state() & ONESHOT_TOGGLED);
diff --git a/tmk_core/common/arm_atsam/bootloader.c b/tmk_core/common/arm_atsam/bootloader.c
new file mode 100644
index 0000000000..ba71bfeb0b
--- /dev/null
+++ b/tmk_core/common/arm_atsam/bootloader.c
@@ -0,0 +1,51 @@
+/* Copyright 2017 Fred Sundvik
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "bootloader.h"
+#include "samd51j18a.h"
+#include "md_bootloader.h"
+
+//Set watchdog timer to reset. Directs the bootloader to stay in programming mode.
+void bootloader_jump(void) {
+#ifdef KEYBOARD_massdrop_ctrl
+ //CTRL keyboards released with bootloader version below must use RAM method. Otherwise use WDT method.
+ uint8_t ver_ram_method[] = "v2.18Jun 22 2018 17:28:08"; //The version to match (NULL terminated by compiler)
+ uint8_t *ver_check = ver_ram_method; //Pointer to version match string for traversal
+ uint8_t *ver_rom = (uint8_t *)0x21A0; //Pointer to address in ROM where this specific bootloader version would exist
+
+ while (*ver_check && *ver_rom == *ver_check) { //While there are check version characters to match and bootloader's version matches check's version
+ ver_check++; //Move check version pointer to next character
+ ver_rom++; //Move ROM version pointer to next character
+ }
+
+ if (!*ver_check) { //If check version pointer is NULL, all characters have matched
+ *MAGIC_ADDR = BOOTLOADER_MAGIC; //Set magic number into RAM
+ NVIC_SystemReset(); //Perform system reset
+ while (1) {} //Won't get here
+ }
+#endif
+
+ WDT->CTRLA.bit.ENABLE = 0;
+ while (WDT->SYNCBUSY.bit.ENABLE) {}
+ while (WDT->CTRLA.bit.ENABLE) {}
+ WDT->CONFIG.bit.WINDOW = 0;
+ WDT->CONFIG.bit.PER = 0;
+ WDT->EWCTRL.bit.EWOFFSET = 0;
+ WDT->CTRLA.bit.ENABLE = 1;
+ while (WDT->SYNCBUSY.bit.ENABLE) {}
+ while (!WDT->CTRLA.bit.ENABLE) {}
+ while (1) {} //Wait on timeout
+}
diff --git a/tmk_core/common/arm_atsam/eeprom.c b/tmk_core/common/arm_atsam/eeprom.c
new file mode 100644
index 0000000000..61cc039efa
--- /dev/null
+++ b/tmk_core/common/arm_atsam/eeprom.c
@@ -0,0 +1,98 @@
+/* Copyright 2017 Fred Sundvik
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "eeprom.h"
+
+#define EEPROM_SIZE 32
+
+static uint8_t buffer[EEPROM_SIZE];
+
+uint8_t eeprom_read_byte(const uint8_t *addr) {
+ uintptr_t offset = (uintptr_t)addr;
+ return buffer[offset];
+}
+
+void eeprom_write_byte(uint8_t *addr, uint8_t value) {
+ uintptr_t offset = (uintptr_t)addr;
+ buffer[offset] = value;
+}
+
+uint16_t eeprom_read_word(const uint16_t *addr) {
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
+}
+
+uint32_t eeprom_read_dword(const uint32_t *addr) {
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
+ | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
+ const uint8_t *p = (const uint8_t *)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ while (len--) {
+ *dest++ = eeprom_read_byte(p++);
+ }
+}
+
+void eeprom_write_word(uint16_t *addr, uint16_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_write_dword(uint32_t *addr, uint32_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
+
+void eeprom_update_byte(uint8_t *addr, uint8_t value) {
+ eeprom_write_byte(addr, value);
+}
+
+void eeprom_update_word(uint16_t *addr, uint16_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_update_dword(uint32_t *addr, uint32_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
diff --git a/tmk_core/common/arm_atsam/printf.c b/tmk_core/common/arm_atsam/printf.c
new file mode 100644
index 0000000000..7f298d1fda
--- /dev/null
+++ b/tmk_core/common/arm_atsam/printf.c
@@ -0,0 +1,66 @@
+/*
+Copyright 2018 Massdrop Inc.
+
+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/>.
+*/
+
+#ifdef CONSOLE_ENABLE
+
+#include "samd51j18a.h"
+#include "arm_atsam_protocol.h"
+#include "printf.h"
+#include <string.h>
+#include <stdarg.h>
+
+void console_printf(char *fmt, ...) {
+ while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete
+
+ static char console_printbuf[CONSOLE_PRINTBUF_SIZE]; //Print and send buffer
+ va_list va;
+ int result;
+
+ va_start(va, fmt);
+ result = vsnprintf(console_printbuf, CONSOLE_PRINTBUF_SIZE, fmt, va);
+ va_end(va);
+
+ uint32_t irqflags;
+ char *pconbuf = console_printbuf; //Pointer to start send from
+ int send_out = CONSOLE_EPSIZE; //Bytes to send per transfer
+
+ while (result > 0) { //While not error and bytes remain
+ while (udi_hid_con_b_report_trans_ongoing) {} //Wait for any previous transfers to complete
+
+ irqflags = __get_PRIMASK();
+ __disable_irq();
+ __DMB();
+
+ if (result < CONSOLE_EPSIZE) { //If remaining bytes are less than console epsize
+ memset(udi_hid_con_report, 0, CONSOLE_EPSIZE); //Clear the buffer
+ send_out = result; //Send remaining size
+ }
+
+ memcpy(udi_hid_con_report, pconbuf, send_out); //Copy data into the send buffer
+
+ udi_hid_con_b_report_valid = 1; //Set report valid
+ udi_hid_con_send_report(); //Send report
+
+ __DMB();
+ __set_PRIMASK(irqflags);
+
+ result -= send_out; //Decrement result by bytes sent
+ pconbuf += send_out; //Increment buffer point by bytes sent
+ }
+}
+
+#endif //CONSOLE_ENABLE
diff --git a/tmk_core/common/arm_atsam/printf.h b/tmk_core/common/arm_atsam/printf.h
new file mode 100644
index 0000000000..1f1c2280b5
--- /dev/null
+++ b/tmk_core/common/arm_atsam/printf.h
@@ -0,0 +1,11 @@
+#ifndef _PRINTF_H_
+#define _PRINTF_H_
+
+#define CONSOLE_PRINTBUF_SIZE 512
+
+void console_printf(char *fmt, ...);
+
+#define __xprintf console_printf
+
+#endif //_PRINTF_H_
+
diff --git a/tmk_core/common/arm_atsam/suspend.c b/tmk_core/common/arm_atsam/suspend.c
new file mode 100644
index 0000000000..e34965df64
--- /dev/null
+++ b/tmk_core/common/arm_atsam/suspend.c
@@ -0,0 +1,85 @@
+#include "matrix.h"
+#include "i2c_master.h"
+#include "led_matrix.h"
+#include "suspend.h"
+
+/** \brief Suspend idle
+ *
+ * FIXME: needs doc
+ */
+void suspend_idle(uint8_t time) {
+ /* Note: Not used anywhere currently */
+}
+
+/** \brief Run user level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__ ((weak))
+void suspend_power_down_user (void) {
+
+}
+
+/** \brief Run keyboard level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__ ((weak))
+void suspend_power_down_kb(void) {
+ suspend_power_down_user();
+}
+
+/** \brief Suspend power down
+ *
+ * FIXME: needs doc
+ */
+void suspend_power_down(void)
+{
+ I2C3733_Control_Set(0); //Disable LED driver
+
+ suspend_power_down_kb();
+}
+
+__attribute__ ((weak)) void matrix_power_up(void) {}
+__attribute__ ((weak)) void matrix_power_down(void) {}
+bool suspend_wakeup_condition(void) {
+ matrix_power_up();
+ matrix_scan();
+ matrix_power_down();
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ if (matrix_get_row(r)) return true;
+ }
+ return false;
+}
+
+/** \brief run user level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__ ((weak))
+void suspend_wakeup_init_user(void) {
+
+}
+
+/** \brief run keyboard level code immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+__attribute__ ((weak))
+void suspend_wakeup_init_kb(void) {
+ suspend_wakeup_init_user();
+}
+
+/** \brief run immediately after wakeup
+ *
+ * FIXME: needs doc
+ */
+void suspend_wakeup_init(void) {
+ /* If LEDs are set to enabled, enable the hardware */
+ if (led_enabled) {
+ I2C3733_Control_Set(1);
+ }
+
+ suspend_wakeup_init_kb();
+}
+
diff --git a/tmk_core/common/arm_atsam/timer.c b/tmk_core/common/arm_atsam/timer.c
new file mode 100644
index 0000000000..6c3905e308
--- /dev/null
+++ b/tmk_core/common/arm_atsam/timer.c
@@ -0,0 +1,43 @@
+#include "samd51j18a.h"
+#include "timer.h"
+#include "tmk_core/protocol/arm_atsam/clks.h"
+
+void set_time(uint64_t tset)
+{
+ ms_clk = tset;
+}
+
+void timer_init(void)
+{
+ timer_clear();
+}
+
+uint16_t timer_read(void)
+{
+ return (uint16_t)ms_clk;
+}
+
+uint32_t timer_read32(void)
+{
+ return (uint32_t)ms_clk;
+}
+
+uint64_t timer_read64(void)
+{
+ return ms_clk;
+}
+
+uint16_t timer_elapsed(uint16_t tlast)
+{
+ return TIMER_DIFF_16(timer_read(), tlast);
+}
+
+uint32_t timer_elapsed32(uint32_t tlast)
+{
+ return TIMER_DIFF_32(timer_read32(), tlast);
+}
+
+void timer_clear(void)
+{
+ set_time(0);
+}
diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c
index 3d4a48439b..5bca646854 100644
--- a/tmk_core/common/avr/suspend.c
+++ b/tmk_core/common/avr/suspend.c
@@ -10,6 +10,7 @@
#include "timer.h"
#include "led.h"
#include "host.h"
+#include "rgblight_reconfig.h"
#ifdef PROTOCOL_LUFA
#include "lufa.h"
@@ -55,6 +56,24 @@ void suspend_idle(uint8_t time)
sleep_disable();
}
+
+// TODO: This needs some cleanup
+
+/** \brief Run keyboard level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__ ((weak))
+void suspend_power_down_user (void) { }
+/** \brief Run keyboard level Power down
+ *
+ * FIXME: needs doc
+ */
+__attribute__ ((weak))
+void suspend_power_down_kb(void) {
+ suspend_power_down_user();
+}
+
#ifndef NO_SUSPEND_POWER_DOWN
/** \brief Power down MCU with watchdog timer
*
@@ -72,21 +91,6 @@ void suspend_idle(uint8_t time)
*/
static uint8_t wdt_timeout = 0;
-/** \brief Run keyboard level Power down
- *
- * FIXME: needs doc
- */
-__attribute__ ((weak))
-void suspend_power_down_user (void) { }
-/** \brief Run keyboard level Power down
- *
- * FIXME: needs doc
- */
-__attribute__ ((weak))
-void suspend_power_down_kb(void) {
- suspend_power_down_user();
-}
-
/** \brief Power down
*
* FIXME: needs doc
@@ -143,6 +147,8 @@ static void power_down(uint8_t wdto)
*/
void suspend_power_down(void)
{
+ suspend_power_down_kb();
+
#ifndef NO_SUSPEND_POWER_DOWN
power_down(WDTO_15MS);
#endif
@@ -189,12 +195,15 @@ void suspend_wakeup_init(void)
#endif
led_set(host_keyboard_leds());
#if defined(RGBLIGHT_SLEEP) && defined(RGBLIGHT_ENABLE)
+#ifdef BOOTLOADER_TEENSY
+ wait_ms(10);
+#endif
rgblight_enable_noeeprom();
#ifdef RGBLIGHT_ANIMATIONS
rgblight_timer_enable();
#endif
#endif
- suspend_wakeup_init_kb();
+ suspend_wakeup_init_kb();
}
#ifndef NO_SUSPEND_POWER_DOWN
diff --git a/tmk_core/common/backlight.c b/tmk_core/common/backlight.c
index 3e29aacc49..8ddacd98b6 100644
--- a/tmk_core/common/backlight.c
+++ b/tmk_core/common/backlight.c
@@ -76,12 +76,51 @@ void backlight_decrease(void)
*/
void backlight_toggle(void)
{
- backlight_config.enable ^= 1;
- if (backlight_config.raw == 1) // enabled but level = 0
- backlight_config.level = 1;
- eeconfig_update_backlight(backlight_config.raw);
- dprintf("backlight toggle: %u\n", backlight_config.enable);
- backlight_set(backlight_config.enable ? backlight_config.level : 0);
+ bool enabled = backlight_config.enable;
+ dprintf("backlight toggle: %u\n", enabled);
+ if (enabled)
+ backlight_disable();
+ else
+ backlight_enable();
+}
+
+/** \brief Enable backlight
+ *
+ * FIXME: needs doc
+ */
+void backlight_enable(void)
+{
+ if (backlight_config.enable) return; // do nothing if backlight is already on
+
+ backlight_config.enable = true;
+ if (backlight_config.raw == 1) // enabled but level == 0
+ backlight_config.level = 1;
+ eeconfig_update_backlight(backlight_config.raw);
+ dprintf("backlight enable\n");
+ backlight_set(backlight_config.level);
+}
+
+/** /brief Disable backlight
+ *
+ * FIXME: needs doc
+ */
+void backlight_disable(void)
+{
+ if (!backlight_config.enable) return; // do nothing if backlight is already off
+
+ backlight_config.enable = false;
+ eeconfig_update_backlight(backlight_config.raw);
+ dprintf("backlight disable\n");
+ backlight_set(0);
+}
+
+/** /brief Get the backlight status
+ *
+ * FIXME: needs doc
+ */
+bool is_backlight_enabled(void)
+{
+ return backlight_config.enable;
}
/** \brief Backlight step through levels
diff --git a/tmk_core/common/backlight.h b/tmk_core/common/backlight.h
index f573092674..420c9d19ed 100644
--- a/tmk_core/common/backlight.h
+++ b/tmk_core/common/backlight.h
@@ -15,8 +15,7 @@ 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 BACKLIGHT_H
-#define BACKLIGHT_H
+#pragma once
#include <stdint.h>
#include <stdbool.h>
@@ -33,9 +32,11 @@ void backlight_init(void);
void backlight_increase(void);
void backlight_decrease(void);
void backlight_toggle(void);
+void backlight_enable(void);
+void backlight_disable(void);
+bool is_backlight_enabled(void);
void backlight_step(void);
void backlight_set(uint8_t level);
void backlight_level(uint8_t level);
uint8_t get_backlight_level(void);
-#endif
diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c
new file mode 100755
index 0000000000..a15430d676
--- /dev/null
+++ b/tmk_core/common/chibios/eeprom_stm32.c
@@ -0,0 +1,215 @@
+/*
+ * This software is experimental and a work in progress.
+ * Under no circumstances should these files be used in relation to any critical system(s).
+ * Use of these files is at your own risk.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This files are free to use from http://engsta.com/stm32-flash-memory-eeprom-emulator/ by
+ * Artur F.
+ *
+ * Modifications for QMK and STM32F303 by Yiancar
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "eeprom_stm32.h"
+/*****************************************************************************
+ * Allows to use the internal flash to store non volatile data. To initialize
+ * the functionality use the EEPROM_Init() function. Be sure that by reprogramming
+ * of the controller just affected pages will be deleted. In other case the non
+ * volatile data will be lost.
+******************************************************************************/
+
+/* Private macro -------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Functions -----------------------------------------------------------------*/
+
+uint8_t DataBuf[FEE_PAGE_SIZE];
+/*****************************************************************************
+* Delete Flash Space used for user Data, deletes the whole space between
+* RW_PAGE_BASE_ADDRESS and the last uC Flash Page
+******************************************************************************/
+uint16_t EEPROM_Init(void) {
+ // unlock flash
+ FLASH_Unlock();
+
+ // Clear Flags
+ //FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR);
+
+ return FEE_DENSITY_BYTES;
+}
+/*****************************************************************************
+* Erase the whole reserved Flash Space used for user Data
+******************************************************************************/
+void EEPROM_Erase (void) {
+
+ int page_num = 0;
+
+ // delete all pages from specified start page to the last page
+ do {
+ FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE));
+ page_num++;
+ } while (page_num < FEE_DENSITY_PAGES);
+}
+/*****************************************************************************
+* Writes once data byte to flash on specified address. If a byte is already
+* written, the whole page must be copied to a buffer, the byte changed and
+* the manipulated buffer written after PageErase.
+*******************************************************************************/
+uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
+
+ FLASH_Status FlashStatus = FLASH_COMPLETE;
+
+ uint32_t page;
+ int i;
+
+ // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages)
+ if (Address > FEE_DENSITY_BYTES) {
+ return 0;
+ }
+
+ // calculate which page is affected (Pagenum1/Pagenum2...PagenumN)
+ page = (FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)) & 0x00000FFF;
+
+ if (page % FEE_PAGE_SIZE) page = page + FEE_PAGE_SIZE;
+ page = (page / FEE_PAGE_SIZE) - 1;
+
+ // if current data is 0xFF, the byte is empty, just overwrite with the new one
+ if ((*(__IO uint16_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) {
+
+ FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte));
+ }
+ else {
+
+ // Copy Page to a buffer
+ memcpy(DataBuf, (uint8_t*)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page
+
+ // check if new data is differ to current data, return if not, proceed if yes
+ if (DataByte == *(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) {
+ return 0;
+ }
+
+ // manipulate desired data byte in temp data array if new byte is differ to the current
+ DataBuf[FEE_ADDR_OFFSET(Address)] = DataByte;
+
+ //Erase Page
+ FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + page);
+
+ // Write new data (whole page) to flash if data has beed changed
+ for(i = 0; i < (FEE_PAGE_SIZE / 2); i++) {
+ if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) {
+ FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]));
+ }
+ }
+
+ }
+ return FlashStatus;
+}
+/*****************************************************************************
+* Read once data byte from a specified address.
+*******************************************************************************/
+uint8_t EEPROM_ReadDataByte (uint16_t Address) {
+
+ uint8_t DataByte = 0xFF;
+
+ // Get Byte from specified address
+ DataByte = (*(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)));
+
+ return DataByte;
+}
+
+/*****************************************************************************
+* Wrap library in AVR style functions.
+*******************************************************************************/
+uint8_t eeprom_read_byte (const uint8_t *Address)
+{
+ const uint16_t p = (const uint32_t) Address;
+ return EEPROM_ReadDataByte(p);
+}
+
+void eeprom_write_byte (uint8_t *Address, uint8_t Value)
+{
+ uint16_t p = (uint32_t) Address;
+ EEPROM_WriteDataByte(p, Value);
+}
+
+void eeprom_update_byte (uint8_t *Address, uint8_t Value)
+{
+ uint16_t p = (uint32_t) Address;
+ EEPROM_WriteDataByte(p, Value);
+}
+
+uint16_t eeprom_read_word (const uint16_t *Address)
+{
+ const uint16_t p = (const uint32_t) Address;
+ return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8);
+}
+
+void eeprom_write_word (uint16_t *Address, uint16_t Value)
+{
+ uint16_t p = (uint32_t) Address;
+ EEPROM_WriteDataByte(p, (uint8_t) Value);
+ EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
+}
+
+void eeprom_update_word (uint16_t *Address, uint16_t Value)
+{
+ uint16_t p = (uint32_t) Address;
+ EEPROM_WriteDataByte(p, (uint8_t) Value);
+ EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
+}
+
+uint32_t eeprom_read_dword (const uint32_t *Address)
+{
+ const uint16_t p = (const uint32_t) Address;
+ return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8)
+ | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24);
+}
+
+void eeprom_write_dword (uint32_t *Address, uint32_t Value)
+{
+ uint16_t p = (const uint32_t) Address;
+ EEPROM_WriteDataByte(p, (uint8_t) Value);
+ EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
+ EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
+ EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
+}
+
+void eeprom_update_dword (uint32_t *Address, uint32_t Value)
+{
+ uint16_t p = (const uint32_t) Address;
+ EEPROM_WriteDataByte(p, (uint8_t) Value);
+ EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
+ EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
+ EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
+ const uint8_t *p = (const uint8_t *)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ while (len--) {
+ *dest++ = eeprom_read_byte(p++);
+ }
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
+
+void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/tmk_core/common/chibios/eeprom_stm32.h
new file mode 100755
index 0000000000..892e417b7e
--- /dev/null
+++ b/tmk_core/common/chibios/eeprom_stm32.h
@@ -0,0 +1,81 @@
+/*
+ * This software is experimental and a work in progress.
+ * Under no circumstances should these files be used in relation to any critical system(s).
+ * Use of these files is at your own risk.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This files are free to use from http://engsta.com/stm32-flash-memory-eeprom-emulator/ by
+ * Artur F.
+ *
+ * Modifications for QMK and STM32F303 by Yiancar
+ *
+ * This library assumes 8-bit data locations. To add a new MCU, please provide the flash
+ * page size and the total flash size in Kb. The number of available pages must be a multiple
+ * of 2. Only half of the pages account for the total EEPROM size.
+ * This library also assumes that the pages are not used by the firmware.
+ */
+
+#ifndef __EEPROM_H
+#define __EEPROM_H
+
+#include "ch.h"
+#include "hal.h"
+#include "flash_stm32.h"
+
+// HACK ALERT. This definition may not match your processor
+// To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc
+#if defined(EEPROM_EMU_STM32F303xC)
+ #define MCU_STM32F303CC
+#elif defined(EEPROM_EMU_STM32F103xB)
+ #define MCU_STM32F103RB
+#else
+ #error "not implemented."
+#endif
+
+#ifndef EEPROM_PAGE_SIZE
+ #if defined (MCU_STM32F103RB)
+ #define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte
+ #define FEE_DENSITY_PAGES 2 // How many pages are used
+ #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC)
+ #define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte
+ #define FEE_DENSITY_PAGES 4 // How many pages are used
+ #else
+ #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
+ #endif
+#endif
+
+#ifndef EEPROM_START_ADDRESS
+ #if defined (MCU_STM32F103RB)
+ #define FEE_MCU_FLASH_SIZE 128 // Size in Kb
+ #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE)
+ #define FEE_MCU_FLASH_SIZE 512 // Size in Kb
+ #elif defined (MCU_STM32F103RD)
+ #define FEE_MCU_FLASH_SIZE 384 // Size in Kb
+ #elif defined (MCU_STM32F303CC)
+ #define FEE_MCU_FLASH_SIZE 256 // Size in Kb
+ #else
+ #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)."
+ #endif
+#endif
+
+// DONT CHANGE
+// Choose location for the first EEPROM Page address on the top of flash
+#define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE))
+#define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1)
+#define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES))
+#define FEE_EMPTY_WORD ((uint16_t)0xFFFF)
+#define FEE_ADDR_OFFSET(Address)(Address * 2) // 1Byte per Word will be saved to preserve Flash
+
+// Use this function to initialize the functionality
+uint16_t EEPROM_Init(void);
+void EEPROM_Erase (void);
+uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte);
+uint8_t EEPROM_ReadDataByte (uint16_t Address);
+
+#endif /* __EEPROM_H */
diff --git a/tmk_core/common/chibios/eeprom.c b/tmk_core/common/chibios/eeprom_teensy.c
index 9061b790c4..9061b790c4 100644
--- a/tmk_core/common/chibios/eeprom.c
+++ b/tmk_core/common/chibios/eeprom_teensy.c
diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c
new file mode 100755
index 0000000000..164654a15e
--- /dev/null
+++ b/tmk_core/common/chibios/flash_stm32.c
@@ -0,0 +1,203 @@
+/*
+ * This software is experimental and a work in progress.
+ * Under no circumstances should these files be used in relation to any critical system(s).
+ * Use of these files is at your own risk.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
+ * https://github.com/leaflabs/libmaple
+ *
+ * Modifications for QMK and STM32F303 by Yiancar
+ */
+
+#if defined(EEPROM_EMU_STM32F303xC)
+ #define STM32F303xC
+ #include "stm32f3xx.h"
+#elif defined(EEPROM_EMU_STM32F103xB)
+ #define STM32F103xB
+ #include "stm32f1xx.h"
+#else
+ #error "not implemented."
+#endif
+
+#include "flash_stm32.h"
+
+#if defined(EEPROM_EMU_STM32F103xB)
+ #define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
+#endif
+
+/* Delay definition */
+#define EraseTimeout ((uint32_t)0x00000FFF)
+#define ProgramTimeout ((uint32_t)0x0000001F)
+
+#define ASSERT(exp) (void)((0))
+
+/**
+ * @brief Inserts a time delay.
+ * @param None
+ * @retval None
+ */
+static void delay(void)
+{
+ __IO uint32_t i = 0;
+ for(i = 0xFF; i != 0; i--) { }
+}
+
+/**
+ * @brief Returns the FLASH Status.
+ * @param None
+ * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
+ * FLASH_ERROR_WRP or FLASH_COMPLETE
+ */
+FLASH_Status FLASH_GetStatus(void)
+{
+ if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)
+ return FLASH_BUSY;
+
+ if ((FLASH->SR & FLASH_SR_PGERR) != 0)
+ return FLASH_ERROR_PG;
+
+ if ((FLASH->SR & FLASH_SR_WRPERR) != 0 )
+ return FLASH_ERROR_WRP;
+
+ if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 )
+ return FLASH_ERROR_OPT;
+
+ return FLASH_COMPLETE;
+}
+
+/**
+ * @brief Waits for a Flash operation to complete or a TIMEOUT to occur.
+ * @param Timeout: FLASH progamming Timeout
+ * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
+ * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
+ */
+FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
+{
+ FLASH_Status status;
+
+ /* Check for the Flash Status */
+ status = FLASH_GetStatus();
+ /* Wait for a Flash operation to complete or a TIMEOUT to occur */
+ while ((status == FLASH_BUSY) && (Timeout != 0x00))
+ {
+ delay();
+ status = FLASH_GetStatus();
+ Timeout--;
+ }
+ if (Timeout == 0)
+ status = FLASH_TIMEOUT;
+ /* Return the operation status */
+ return status;
+}
+
+/**
+ * @brief Erases a specified FLASH page.
+ * @param Page_Address: The page address to be erased.
+ * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
+ * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
+ */
+FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
+{
+ FLASH_Status status = FLASH_COMPLETE;
+ /* Check the parameters */
+ ASSERT(IS_FLASH_ADDRESS(Page_Address));
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(EraseTimeout);
+
+ if(status == FLASH_COMPLETE)
+ {
+ /* if the previous operation is completed, proceed to erase the page */
+ FLASH->CR |= FLASH_CR_PER;
+ FLASH->AR = Page_Address;
+ FLASH->CR |= FLASH_CR_STRT;
+
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(EraseTimeout);
+ if(status != FLASH_TIMEOUT)
+ {
+ /* if the erase operation is completed, disable the PER Bit */
+ FLASH->CR &= ~FLASH_CR_PER;
+ }
+ FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
+ }
+ /* Return the Erase Status */
+ return status;
+}
+
+/**
+ * @brief Programs a half word at a specified address.
+ * @param Address: specifies the address to be programmed.
+ * @param Data: specifies the data to be programmed.
+ * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
+ * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
+ */
+FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
+{
+ FLASH_Status status = FLASH_BAD_ADDRESS;
+
+ if (IS_FLASH_ADDRESS(Address))
+ {
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(ProgramTimeout);
+ if(status == FLASH_COMPLETE)
+ {
+ /* if the previous operation is completed, proceed to program the new data */
+ FLASH->CR |= FLASH_CR_PG;
+ *(__IO uint16_t*)Address = Data;
+ /* Wait for last operation to be completed */
+ status = FLASH_WaitForLastOperation(ProgramTimeout);
+ if(status != FLASH_TIMEOUT)
+ {
+ /* if the program operation is completed, disable the PG Bit */
+ FLASH->CR &= ~FLASH_CR_PG;
+ }
+ FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief Unlocks the FLASH Program Erase Controller.
+ * @param None
+ * @retval None
+ */
+void FLASH_Unlock(void)
+{
+ /* Authorize the FPEC Access */
+ FLASH->KEYR = FLASH_KEY1;
+ FLASH->KEYR = FLASH_KEY2;
+}
+
+/**
+ * @brief Locks the FLASH Program Erase Controller.
+ * @param None
+ * @retval None
+ */
+void FLASH_Lock(void)
+{
+ /* Set the Lock Bit to lock the FPEC and the FCR */
+ FLASH->CR |= FLASH_CR_LOCK;
+}
+
+/**
+ * @brief Clears the FLASH's pending flags.
+ * @param FLASH_FLAG: specifies the FLASH flags to clear.
+ * This parameter can be any combination of the following values:
+ * @arg FLASH_FLAG_PGERR: FLASH Programming error flag flag
+ * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag
+ * @arg FLASH_FLAG_EOP: FLASH End of Programming flag
+ * @retval None
+ */
+void FLASH_ClearFlag(uint32_t FLASH_FLAG)
+{
+ /* Clear the flags */
+ FLASH->SR = FLASH_FLAG;
+}
diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h
new file mode 100755
index 0000000000..3c99cc566a
--- /dev/null
+++ b/tmk_core/common/chibios/flash_stm32.h
@@ -0,0 +1,54 @@
+/*
+ * This software is experimental and a work in progress.
+ * Under no circumstances should these files be used in relation to any critical system(s).
+ * Use of these files is at your own risk.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and
+ * https://github.com/leaflabs/libmaple
+ *
+ * Modifications for QMK and STM32F303 by Yiancar
+ */
+
+#ifndef __FLASH_STM32_H
+#define __FLASH_STM32_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "ch.h"
+#include "hal.h"
+
+typedef enum
+ {
+ FLASH_BUSY = 1,
+ FLASH_ERROR_PG,
+ FLASH_ERROR_WRP,
+ FLASH_ERROR_OPT,
+ FLASH_COMPLETE,
+ FLASH_TIMEOUT,
+ FLASH_BAD_ADDRESS
+ } FLASH_Status;
+
+#define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF))
+
+FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
+FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
+FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
+
+void FLASH_Unlock(void);
+void FLASH_Lock(void);
+void FLASH_ClearFlag(uint32_t FLASH_FLAG);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FLASH_STM32_H */
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
index f79d5a257b..aab99290d2 100644
--- a/tmk_core/common/command.c
+++ b/tmk_core/common/command.c
@@ -181,7 +181,11 @@ static void print_version(void)
print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
"PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
"VER: " STR(DEVICE_VER) "\n");
+#ifdef SKIP_VERSION
+ print("BUILD: (" __DATE__ ")\n");
+#else
print("BUILD: " STR(QMK_VERSION) " (" __TIME__ " " __DATE__ ")\n");
+#endif
/* build options */
print("OPTIONS:"
diff --git a/tmk_core/common/command.h b/tmk_core/common/command.h
index d9d89ba0f1..c38f2b9e80 100644
--- a/tmk_core/common/command.h
+++ b/tmk_core/common/command.h
@@ -15,8 +15,7 @@ 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 COMMAND_H
-#define COMMAND
+#pragma once
/* FIXME: Add doxygen comments for the behavioral defines in here. */
@@ -155,5 +154,3 @@ bool command_proc(uint8_t code);
#define XMAGIC_KC(key) KC_##key
#define MAGIC_KC(key) XMAGIC_KC(key)
-
-#endif
diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c
index 3e5987ee3b..59b2bffbc7 100644
--- a/tmk_core/common/eeconfig.c
+++ b/tmk_core/common/eeconfig.c
@@ -3,29 +3,59 @@
#include "eeprom.h"
#include "eeconfig.h"
-/** \brief eeconfig initialization
+#ifdef STM32_EEPROM_ENABLE
+#include "hal.h"
+#include "eeprom_stm32.h"
+#endif
+
+extern uint32_t default_layer_state;
+/** \brief eeconfig enable
*
* FIXME: needs doc
*/
-void eeconfig_init(void)
-{
- eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
- eeprom_update_byte(EECONFIG_DEBUG, 0);
- eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
- eeprom_update_byte(EECONFIG_KEYMAP, 0);
- eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
-#ifdef BACKLIGHT_ENABLE
- eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
-#endif
-#ifdef AUDIO_ENABLE
- eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
-#endif
-#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
- eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
-#endif
-#ifdef STENO_ENABLE
- eeprom_update_byte(EECONFIG_STENOMODE, 0);
+__attribute__ ((weak))
+void eeconfig_init_user(void) {
+ // Reset user EEPROM value to blank, rather than to a set value
+ eeconfig_update_user(0);
+}
+
+__attribute__ ((weak))
+void eeconfig_init_kb(void) {
+ // Reset Keyboard EEPROM value to blank, rather than to a set value
+ eeconfig_update_kb(0);
+
+ eeconfig_init_user();
+}
+
+
+/*
+ * FIXME: needs doc
+ */
+void eeconfig_init_quantum(void) {
+#ifdef STM32_EEPROM_ENABLE
+ EEPROM_Erase();
#endif
+ eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
+ eeprom_update_byte(EECONFIG_DEBUG, 0);
+ eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
+ default_layer_state = 0;
+ eeprom_update_byte(EECONFIG_KEYMAP, 0);
+ eeprom_update_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
+ eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
+ eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
+ eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
+ eeprom_update_byte(EECONFIG_STENOMODE, 0);
+
+ eeconfig_init_kb();
+}
+
+/** \brief eeconfig initialization
+ *
+ * FIXME: needs doc
+ */
+void eeconfig_init(void) {
+
+ eeconfig_init_quantum();
}
/** \brief eeconfig enable
@@ -43,7 +73,10 @@ void eeconfig_enable(void)
*/
void eeconfig_disable(void)
{
- eeprom_update_word(EECONFIG_MAGIC, 0xFFFF);
+#ifdef STM32_EEPROM_ENABLE
+ EEPROM_Erase();
+#endif
+ eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF);
}
/** \brief eeconfig is enabled
@@ -55,6 +88,15 @@ bool eeconfig_is_enabled(void)
return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
}
+/** \brief eeconfig is disabled
+ *
+ * FIXME: needs doc
+ */
+bool eeconfig_is_disabled(void)
+{
+ return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER_OFF);
+}
+
/** \brief eeconfig read debug
*
* FIXME: needs doc
@@ -88,7 +130,6 @@ uint8_t eeconfig_read_keymap(void) { return eeprom_read_byte(EECONFIG_KEYMA
*/
void eeconfig_update_keymap(uint8_t val) { eeprom_update_byte(EECONFIG_KEYMAP, val); }
-#ifdef BACKLIGHT_ENABLE
/** \brief eeconfig read backlight
*
* FIXME: needs doc
@@ -99,9 +140,8 @@ uint8_t eeconfig_read_backlight(void) { return eeprom_read_byte(EECONFIG_BA
* FIXME: needs doc
*/
void eeconfig_update_backlight(uint8_t val) { eeprom_update_byte(EECONFIG_BACKLIGHT, val); }
-#endif
-#ifdef AUDIO_ENABLE
+
/** \brief eeconfig read audio
*
* FIXME: needs doc
@@ -112,4 +152,28 @@ uint8_t eeconfig_read_audio(void) { return eeprom_read_byte(EECONFIG_AUDIO)
* FIXME: needs doc
*/
void eeconfig_update_audio(uint8_t val) { eeprom_update_byte(EECONFIG_AUDIO, val); }
-#endif
+
+
+/** \brief eeconfig read kb
+ *
+ * FIXME: needs doc
+ */
+uint32_t eeconfig_read_kb(void) { return eeprom_read_dword(EECONFIG_KEYBOARD); }
+/** \brief eeconfig update kb
+ *
+ * FIXME: needs doc
+ */
+
+void eeconfig_update_kb(uint32_t val) { eeprom_update_dword(EECONFIG_KEYBOARD, val); }
+/** \brief eeconfig read user
+ *
+ * FIXME: needs doc
+ */
+uint32_t eeconfig_read_user(void) { return eeprom_read_dword(EECONFIG_USER); }
+/** \brief eeconfig update user
+ *
+ * FIXME: needs doc
+ */
+void eeconfig_update_user(uint32_t val) { eeprom_update_dword(EECONFIG_USER, val); }
+
+
diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h
index 1397a90c79..eedd67602c 100644
--- a/tmk_core/common/eeconfig.h
+++ b/tmk_core/common/eeconfig.h
@@ -23,21 +23,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED
+#define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
-/* eeprom parameteter address */
+/* EEPROM parameter address */
#define EECONFIG_MAGIC (uint16_t *)0
-#define EECONFIG_DEBUG (uint8_t *)2
-#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
-#define EECONFIG_KEYMAP (uint8_t *)4
-#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
-#define EECONFIG_BACKLIGHT (uint8_t *)6
-#define EECONFIG_AUDIO (uint8_t *)7
+#define EECONFIG_DEBUG (uint8_t *)2
+#define EECONFIG_DEFAULT_LAYER (uint8_t *)3
+#define EECONFIG_KEYMAP (uint8_t *)4
+#define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)5
+#define EECONFIG_BACKLIGHT (uint8_t *)6
+#define EECONFIG_AUDIO (uint8_t *)7
#define EECONFIG_RGBLIGHT (uint32_t *)8
#define EECONFIG_UNICODEMODE (uint8_t *)12
#define EECONFIG_STENOMODE (uint8_t *)13
// EEHANDS for two handed boards
-#define EECONFIG_HANDEDNESS (uint8_t *)14
-
+#define EECONFIG_HANDEDNESS (uint8_t *)14
+#define EECONFIG_KEYBOARD (uint32_t *)15
+#define EECONFIG_USER (uint32_t *)19
/* debug bit */
#define EECONFIG_DEBUG_ENABLE (1<<0)
@@ -57,8 +59,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
bool eeconfig_is_enabled(void);
+bool eeconfig_is_disabled(void);
void eeconfig_init(void);
+void eeconfig_init_quantum(void);
+void eeconfig_init_kb(void);
+void eeconfig_init_user(void);
void eeconfig_enable(void);
@@ -83,4 +89,9 @@ uint8_t eeconfig_read_audio(void);
void eeconfig_update_audio(uint8_t val);
#endif
+uint32_t eeconfig_read_kb(void);
+void eeconfig_update_kb(uint32_t val);
+uint32_t eeconfig_read_user(void);
+void eeconfig_update_user(uint32_t val);
+
#endif
diff --git a/tmk_core/common/eeprom.h b/tmk_core/common/eeprom.h
index 3696d0df3f..5ae0f6eebd 100644
--- a/tmk_core/common/eeprom.h
+++ b/tmk_core/common/eeprom.h
@@ -20,5 +20,4 @@ void eeprom_update_dword (uint32_t *__p, uint32_t __value);
void eeprom_update_block (const void *__src, void *__dst, uint32_t __n);
#endif
-
#endif /* TMK_CORE_COMMON_EEPROM_H_ */
diff --git a/tmk_core/common/host.c b/tmk_core/common/host.c
index e12b622165..f5d0416996 100644
--- a/tmk_core/common/host.c
+++ b/tmk_core/common/host.c
@@ -22,6 +22,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "util.h"
#include "debug.h"
+#ifdef NKRO_ENABLE
+ #include "keycode_config.h"
+ extern keymap_config_t keymap_config;
+#endif
+
static host_driver_t *driver;
static uint16_t last_system_report = 0;
static uint16_t last_consumer_report = 0;
@@ -46,6 +51,20 @@ uint8_t host_keyboard_leds(void)
void host_keyboard_send(report_keyboard_t *report)
{
if (!driver) return;
+#if defined(NKRO_ENABLE) && defined(NKRO_SHARED_EP)
+ if (keyboard_protocol && keymap_config.nkro) {
+ /* The callers of this function assume that report->mods is where mods go in.
+ * But report->nkro.mods can be at a different offset if core keyboard does not have a report ID.
+ */
+ report->nkro.mods = report->mods;
+ report->nkro.report_id = REPORT_ID_NKRO;
+ } else
+#endif
+ {
+#ifdef KEYBOARD_SHARED_EP
+ report->report_id = REPORT_ID_KEYBOARD;
+#endif
+ }
(*driver->send_keyboard)(report);
if (debug_keyboard) {
@@ -60,6 +79,9 @@ void host_keyboard_send(report_keyboard_t *report)
void host_mouse_send(report_mouse_t *report)
{
if (!driver) return;
+#ifdef MOUSE_SHARED_EP
+ report->report_id = REPORT_ID_MOUSE;
+#endif
(*driver->send_mouse)(report);
}
diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h
index aeabba7107..3d172eed66 100644
--- a/tmk_core/common/host.h
+++ b/tmk_core/common/host.h
@@ -15,14 +15,18 @@ 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 HOST_H
-#define HOST_H
+#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "report.h"
#include "host_driver.h"
+#define IS_LED_ON(leds, led_name) ( (leds) & (1 << (led_name)))
+#define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name)))
+
+#define IS_HOST_LED_ON(led_name) IS_LED_ON(host_keyboard_leds(), led_name)
+#define IS_HOST_LED_OFF(led_name) IS_LED_OFF(host_keyboard_leds(), led_name)
#ifdef __cplusplus
extern "C" {
@@ -31,7 +35,6 @@ extern "C" {
extern uint8_t keyboard_idle;
extern uint8_t keyboard_protocol;
-
/* host driver */
void host_set_driver(host_driver_t *driver);
host_driver_t *host_get_driver(void);
@@ -49,5 +52,3 @@ uint16_t host_last_consumer_report(void);
#ifdef __cplusplus
}
#endif
-
-#endif
diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c
index 13b3cb4c0c..6f659b2440 100644
--- a/tmk_core/common/keyboard.c
+++ b/tmk_core/common/keyboard.c
@@ -72,6 +72,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifdef HD44780_ENABLE
# include "hd44780.h"
#endif
+#ifdef QWIIC_ENABLE
+# include "qwiic.h"
+#endif
#ifdef MATRIX_HAS_GHOST
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
@@ -120,6 +123,14 @@ static inline bool has_ghost_in_row(uint8_t row, matrix_row_t rowdata)
#endif
+void disable_jtag(void) {
+// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
+#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
+ MCUCR |= _BV(JTD);
+ MCUCR |= _BV(JTD);
+#endif
+}
+
/** \brief matrix_setup
*
* FIXME: needs doc
@@ -133,6 +144,7 @@ void matrix_setup(void) {
* FIXME: needs doc
*/
void keyboard_setup(void) {
+ disable_jtag();
matrix_setup();
}
@@ -151,12 +163,10 @@ bool is_keyboard_master(void) {
*/
void keyboard_init(void) {
timer_init();
-// To use PORTF disable JTAG with writing JTD bit twice within four cycles.
-#if (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) || defined(__AVR_ATmega32U4__))
- MCUCR |= _BV(JTD);
- MCUCR |= _BV(JTD);
-#endif
matrix_init();
+#ifdef QWIIC_ENABLE
+ qwiic_init();
+#endif
#ifdef PS2_MOUSE_ENABLE
ps2_mouse_init();
#endif
@@ -266,6 +276,10 @@ void keyboard_task(void)
MATRIX_LOOP_END:
+#ifdef QWIIC_ENABLE
+ qwiic_task();
+#endif
+
#ifdef MOUSEKEY_ENABLE
// mousekey repeat & acceleration
mousekey_task();
diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h
index f17003c2ff..ea2f336e9d 100644
--- a/tmk_core/common/keyboard.h
+++ b/tmk_core/common/keyboard.h
@@ -57,6 +57,8 @@ static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) &&
.time = (timer_read() | 1) \
}
+void disable_jtag(void);
+
/* it runs once at early stage of startup before keyboard_init. */
void keyboard_setup(void);
/* it runs once after initializing host side protocol, debug and MCU peripherals. */
@@ -65,6 +67,8 @@ void keyboard_init(void);
void keyboard_task(void);
/* it runs when host LED status is updated */
void keyboard_set_leds(uint8_t leds);
+/* it runs whenever code has to behave differently on a slave */
+bool is_keyboard_master(void);
#ifdef __cplusplus
}
diff --git a/tmk_core/common/keycode.h b/tmk_core/common/keycode.h
index 61642ae84f..fd975dd6ad 100644
--- a/tmk_core/common/keycode.h
+++ b/tmk_core/common/keycode.h
@@ -33,7 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define IS_SPECIAL(code) ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
#define IS_SYSTEM(code) (KC_PWR <= (code) && (code) <= KC_WAKE)
-#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_MRWD)
+#define IS_CONSUMER(code) (KC_MUTE <= (code) && (code) <= KC_BRID)
#define IS_FN(code) (KC_FN0 <= (code) && (code) <= KC_FN31)
@@ -140,6 +140,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_LWIN KC_LGUI
#define KC_RCTL KC_RCTRL
#define KC_RSFT KC_RSHIFT
+#define KC_ALGR KC_RALT
#define KC_RCMD KC_RGUI
#define KC_RWIN KC_RGUI
@@ -170,6 +171,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define KC_WFAV KC_WWW_FAVORITES
#define KC_MFFD KC_MEDIA_FAST_FORWARD
#define KC_MRWD KC_MEDIA_REWIND
+#define KC_BRIU KC_BRIGHTNESS_UP
+#define KC_BRID KC_BRIGHTNESS_DOWN
+
+/* System Specific */
+#define KC_BRMU KC_PAUSE
+#define KC_BRMD KC_SCROLLLOCK
/* Mouse Keys */
#define KC_MS_U KC_MS_UP
@@ -457,6 +464,8 @@ enum internal_special_keycodes {
KC_WWW_FAVORITES,
KC_MEDIA_FAST_FORWARD,
KC_MEDIA_REWIND,
+ KC_BRIGHTNESS_UP,
+ KC_BRIGHTNESS_DOWN,
/* Fn keys */
KC_FN0 = 0xC0,
diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h
index 8836c0fc7c..2d7184bd0d 100644
--- a/tmk_core/common/print.h
+++ b/tmk_core/common/print.h
@@ -29,7 +29,7 @@
#include <stdbool.h>
#include "util.h"
-#if defined(PROTOCOL_CHIBIOS)
+#if defined(PROTOCOL_CHIBIOS) || defined(PROTOCOL_ARM_ATSAM)
#define PSTR(x) x
#endif
@@ -60,7 +60,7 @@
# define println(s) xputs(PSTR(s "\r\n"))
# define uprint(s) print(s)
# define uprintln(s) println(s)
-# define uprintf(fmt, ...) xprintf(fmt, ...)
+# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
# endif /* USER_PRINT / NORMAL PRINT */
@@ -73,7 +73,9 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
#elif defined(PROTOCOL_CHIBIOS) /* PROTOCOL_CHIBIOS */
+#ifndef TERMINAL_ENABLE
# include "chibios/printf.h"
+#endif
# ifdef USER_PRINT /* USER_PRINT */
@@ -99,6 +101,34 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
# endif /* USER_PRINT / NORMAL PRINT */
+#elif defined(PROTOCOL_ARM_ATSAM) /* PROTOCOL_ARM_ATSAM */
+
+# include "arm_atsam/printf.h"
+
+# ifdef USER_PRINT /* USER_PRINT */
+
+// Remove normal print defines
+# define print(s)
+# define println(s)
+# define xprintf(fmt, ...)
+
+// Create user print defines
+# define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
+# define uprint(s) xprintf(s)
+# define uprintln(s) xprintf(s "\r\n")
+
+# else /* NORMAL PRINT */
+
+// Create user & normal print defines
+# define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
+# define print(s) xprintf(s)
+# define println(s) xprintf(s "\r\n")
+# define uprint(s) print(s)
+# define uprintln(s) println(s)
+# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
+
+# endif /* USER_PRINT / NORMAL PRINT */
+
#elif defined(__arm__) /* __arm__ */
# include "mbed/xprintf.h"
@@ -111,26 +141,26 @@ void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
# define xprintf(fmt, ...)
// Create user print defines
-# define uprintf(fmt, ...) __xprintf(fmt, ...)
+# define uprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define uprint(s) xprintf(s)
# define uprintln(s) xprintf(s "\r\n")
# else /* NORMAL PRINT */
// Create user & normal print defines
-# define xprintf(fmt, ...) __xprintf(fmt, ...)
+# define xprintf(fmt, ...) __xprintf(fmt, ##__VA_ARGS__)
# define print(s) xprintf(s)
# define println(s) xprintf(s "\r\n")
# define uprint(s) print(s)
# define uprintln(s) println(s)
-# define uprintf(fmt, ...) xprintf(fmt, ...)
+# define uprintf(fmt, ...) xprintf(fmt, ##__VA_ARGS__)
# endif /* USER_PRINT / NORMAL PRINT */
/* TODO: to select output destinations: UART/USBSerial */
# define print_set_sendchar(func)
-#endif /* __AVR__ / PROTOCOL_CHIBIOS / __arm__ */
+#endif /* __AVR__ / PROTOCOL_CHIBIOS / PROTOCOL_ARM_ATSAM / __arm__ */
// User print disables the normal print messages in the body of QMK/TMK code and
// is meant as a lightweight alternative to NOPRINT. Use it when you only want to do
diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h
index dcc9efb3ce..de93138397 100644
--- a/tmk_core/common/progmem.h
+++ b/tmk_core/common/progmem.h
@@ -5,9 +5,9 @@
# include <avr/pgmspace.h>
#else
# define PROGMEM
-# define pgm_read_byte(p) *((unsigned char*)p)
-# define pgm_read_word(p) *((uint16_t*)p)
-# define pgm_read_dword(p) *((uint32_t*)p)
+# define pgm_read_byte(p) *((unsigned char*)(p))
+# define pgm_read_word(p) *((uint16_t*)(p))
+# define pgm_read_dword(p) *((uint32_t*)(p))
#endif
#endif
diff --git a/tmk_core/common/report.c b/tmk_core/common/report.c
index eb3b44312f..6a06b70c60 100644
--- a/tmk_core/common/report.c
+++ b/tmk_core/common/report.c
@@ -19,6 +19,7 @@
#include "keycode_config.h"
#include "debug.h"
#include "util.h"
+#include <string.h>
/** \brief has_anykey
*
@@ -27,8 +28,16 @@
uint8_t has_anykey(report_keyboard_t* keyboard_report)
{
uint8_t cnt = 0;
- for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
- if (keyboard_report->raw[i])
+ uint8_t *p = keyboard_report->keys;
+ uint8_t lp = sizeof(keyboard_report->keys);
+#ifdef NKRO_ENABLE
+ if (keyboard_protocol && keymap_config.nkro) {
+ p = keyboard_report->nkro.bits;
+ lp = sizeof(keyboard_report->nkro.bits);
+ }
+#endif
+ while (lp--) {
+ if (*p++)
cnt++;
}
return cnt;
@@ -237,7 +246,11 @@ void del_key_from_report(report_keyboard_t* keyboard_report, uint8_t key)
void clear_keys_from_report(report_keyboard_t* keyboard_report)
{
// not clear mods
- for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
- keyboard_report->raw[i] = 0;
+#ifdef NKRO_ENABLE
+ if (keyboard_protocol && keymap_config.nkro) {
+ memset(keyboard_report->nkro.bits, 0, sizeof(keyboard_report->nkro.bits));
+ return;
}
+#endif
+ memset(keyboard_report->keys, 0, sizeof(keyboard_report->keys));
}
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
index 6c27eb9dc6..e7c31bd376 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/common/report.h
@@ -23,9 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* report id */
-#define REPORT_ID_MOUSE 1
-#define REPORT_ID_SYSTEM 2
-#define REPORT_ID_CONSUMER 3
+#define REPORT_ID_KEYBOARD 1
+#define REPORT_ID_MOUSE 2
+#define REPORT_ID_SYSTEM 3
+#define REPORT_ID_CONSUMER 4
+#define REPORT_ID_NKRO 5
/* mouse buttons */
#define MOUSE_BTN1 (1<<0)
@@ -36,6 +38,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Consumer Page(0x0C)
* following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
+ * see also https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/display-brightness-control
*/
#define AUDIO_MUTE 0x00E2
#define AUDIO_VOL_UP 0x00E9
@@ -45,6 +48,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define TRANSPORT_STOP 0x00B7
#define TRANSPORT_STOP_EJECT 0x00CC
#define TRANSPORT_PLAY_PAUSE 0x00CD
+#define BRIGHTNESS_UP 0x006F
+#define BRIGHTNESS_DOWN 0x0070
/* application launch */
#define AL_CC_CONFIG 0x0183
#define AL_EMAIL 0x018A
@@ -72,27 +77,35 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define SYSTEM_WAKE_UP 0x0083
+#define NKRO_SHARED_EP
/* key report size(NKRO or boot mode) */
#if defined(NKRO_ENABLE)
- #if defined(PROTOCOL_PJRC)
- #include "usb.h"
- #define KEYBOARD_REPORT_SIZE KBD2_SIZE
- #define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
- #define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
- #elif defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
+ #if defined(PROTOCOL_LUFA) || defined(PROTOCOL_CHIBIOS)
#include "protocol/usb_descriptor.h"
- #define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
- #define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
+ #define KEYBOARD_REPORT_BITS (SHARED_EPSIZE - 2)
+ #elif defined(PROTOCOL_ARM_ATSAM)
+ #include "protocol/arm_atsam/usb/udi_device_epsize.h"
#define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
+ #undef NKRO_SHARED_EP
+ #undef MOUSE_SHARED_EP
#else
#error "NKRO not supported with this protocol"
+ #endif
#endif
+#ifdef KEYBOARD_SHARED_EP
+# define KEYBOARD_REPORT_SIZE 9
#else
# define KEYBOARD_REPORT_SIZE 8
-# define KEYBOARD_REPORT_KEYS 6
#endif
+#define KEYBOARD_REPORT_KEYS 6
+
+/* VUSB hardcodes keyboard and mouse+extrakey only */
+#if defined(PROTOCOL_VUSB)
+ #undef KEYBOARD_SHARED_EP
+ #undef MOUSE_SHARED_EP
+#endif
#ifdef __cplusplus
extern "C" {
@@ -121,12 +134,18 @@ extern "C" {
typedef union {
uint8_t raw[KEYBOARD_REPORT_SIZE];
struct {
+#ifdef KEYBOARD_SHARED_EP
+ uint8_t report_id;
+#endif
uint8_t mods;
uint8_t reserved;
uint8_t keys[KEYBOARD_REPORT_KEYS];
};
#ifdef NKRO_ENABLE
- struct {
+ struct nkro_report {
+#ifdef NKRO_SHARED_EP
+ uint8_t report_id;
+#endif
uint8_t mods;
uint8_t bits[KEYBOARD_REPORT_BITS];
} nkro;
@@ -134,6 +153,9 @@ typedef union {
} __attribute__ ((packed)) report_keyboard_t;
typedef struct {
+#ifdef MOUSE_SHARED_EP
+ uint8_t report_id;
+#endif
uint8_t buttons;
int8_t x;
int8_t y;
@@ -170,7 +192,9 @@ typedef struct {
(key == KC_WWW_FORWARD ? AC_FORWARD : \
(key == KC_WWW_STOP ? AC_STOP : \
(key == KC_WWW_REFRESH ? AC_REFRESH : \
- (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))
+ (key == KC_BRIGHTNESS_UP ? BRIGHTNESS_UP : \
+ (key == KC_BRIGHTNESS_DOWN ? BRIGHTNESS_DOWN : \
+ (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0)))))))))))))))))))))))
uint8_t has_anykey(report_keyboard_t* keyboard_report);
uint8_t get_first_key(report_keyboard_t* keyboard_report);
diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h
index a7cded9420..a77840bcef 100644
--- a/tmk_core/common/wait.h
+++ b/tmk_core/common/wait.h
@@ -15,6 +15,10 @@ extern "C" {
# include "ch.h"
# define wait_ms(ms) chThdSleepMilliseconds(ms)
# define wait_us(us) chThdSleepMicroseconds(us)
+#elif defined PROTOCOL_ARM_ATSAM
+# include "clks.h"
+# define wait_ms(ms) CLK_delay_ms(ms)
+# define wait_us(us) CLK_delay_us(us)
#elif defined(__arm__)
# include "wait_api.h"
#else // Unit tests