diff options
| author | Alex Ong <the.onga@gmail.com> | 2019-01-26 12:13:19 +1100 |
|---|---|---|
| committer | Alex Ong <the.onga@gmail.com> | 2019-01-26 12:13:19 +1100 |
| commit | c9ba618654417ec115809a031d315f8327c79ad4 (patch) | |
| tree | cd5b907af5bebde7062897ff847e473232ed1214 /tmk_core | |
| parent | 2bb2977c133646c4e056960e72029270d77cc1eb (diff) | |
| parent | d977daa8dc9136746425f9e1414e1f93cb161877 (diff) | |
| download | qmk_firmware-c9ba618654417ec115809a031d315f8327c79ad4.tar.gz qmk_firmware-c9ba618654417ec115809a031d315f8327c79ad4.zip | |
DO NOT USE Merge branch 'master' into debounce_refactor
Merged, however now there are two debounce.h and debounce.c to mess around with and coalesce.
# Conflicts:
# quantum/matrix.c
Diffstat (limited to 'tmk_core')
30 files changed, 450 insertions, 952 deletions
diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index b99c2acaa..ec8d6ed7b 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c | |||
| @@ -653,7 +653,7 @@ void process_action(keyrecord_t *record, action_t action) | |||
| 653 | 653 | ||
| 654 | #ifndef NO_ACTION_TAPPING | 654 | #ifndef NO_ACTION_TAPPING |
| 655 | #ifdef RETRO_TAPPING | 655 | #ifdef RETRO_TAPPING |
| 656 | if (!is_tap_key(record->event.key)) { | 656 | if (!is_tap_action(action)) { |
| 657 | retro_tapping_counter = 0; | 657 | retro_tapping_counter = 0; |
| 658 | } else { | 658 | } else { |
| 659 | if (event.pressed) { | 659 | if (event.pressed) { |
| @@ -929,7 +929,15 @@ void clear_keyboard_but_mods_and_keys() | |||
| 929 | bool is_tap_key(keypos_t key) | 929 | bool is_tap_key(keypos_t key) |
| 930 | { | 930 | { |
| 931 | action_t action = layer_switch_get_action(key); | 931 | action_t action = layer_switch_get_action(key); |
| 932 | return is_tap_action(action); | ||
| 933 | } | ||
| 932 | 934 | ||
| 935 | /** \brief Utilities for actions. (FIXME: Needs better description) | ||
| 936 | * | ||
| 937 | * FIXME: Needs documentation. | ||
| 938 | */ | ||
| 939 | bool is_tap_action(action_t action) | ||
| 940 | { | ||
| 933 | switch (action.kind.id) { | 941 | switch (action.kind.id) { |
| 934 | case ACT_LMODS_TAP: | 942 | case ACT_LMODS_TAP: |
| 935 | case ACT_RMODS_TAP: | 943 | case ACT_RMODS_TAP: |
diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index 8e47e5339..799e3bb0e 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h | |||
| @@ -97,6 +97,7 @@ void clear_keyboard_but_mods(void); | |||
| 97 | void clear_keyboard_but_mods_and_keys(void); | 97 | void clear_keyboard_but_mods_and_keys(void); |
| 98 | void layer_switch(uint8_t new_layer); | 98 | void layer_switch(uint8_t new_layer); |
| 99 | bool is_tap_key(keypos_t key); | 99 | bool is_tap_key(keypos_t key); |
| 100 | bool is_tap_action(action_t action); | ||
| 100 | 101 | ||
| 101 | #ifndef NO_ACTION_TAPPING | 102 | #ifndef NO_ACTION_TAPPING |
| 102 | void process_record_tap_hint(keyrecord_t *record); | 103 | 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 120ce3f51..6ff8c5549 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c | |||
| @@ -17,82 +17,76 @@ uint32_t default_layer_state = 0; | |||
| 17 | 17 | ||
| 18 | /** \brief Default Layer State Set At user Level | 18 | /** \brief Default Layer State Set At user Level |
| 19 | * | 19 | * |
| 20 | * FIXME: Needs docs | 20 | * Run user code on default layer state change |
| 21 | */ | 21 | */ |
| 22 | __attribute__((weak)) | 22 | __attribute__((weak)) |
| 23 | uint32_t default_layer_state_set_user(uint32_t state) { | 23 | uint32_t default_layer_state_set_user(uint32_t state) { |
| 24 | return state; | 24 | return state; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | /** \brief Default Layer State Set At Keyboard Level | 27 | /** \brief Default Layer State Set At Keyboard Level |
| 28 | * | 28 | * |
| 29 | * FIXME: Needs docs | 29 | * Run keyboard code on default layer state change |
| 30 | */ | 30 | */ |
| 31 | __attribute__((weak)) | 31 | __attribute__((weak)) |
| 32 | uint32_t default_layer_state_set_kb(uint32_t state) { | 32 | uint32_t default_layer_state_set_kb(uint32_t state) { |
| 33 | return default_layer_state_set_user(state); | 33 | return default_layer_state_set_user(state); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | /** \brief Default Layer State Set | 36 | /** \brief Default Layer State Set |
| 37 | * | 37 | * |
| 38 | * FIXME: Needs docs | 38 | * Static function to set the default layer state, prints debug info and clears keys |
| 39 | */ | 39 | */ |
| 40 | static void default_layer_state_set(uint32_t state) | 40 | static void default_layer_state_set(uint32_t state) { |
| 41 | { | 41 | state = default_layer_state_set_kb(state); |
| 42 | state = default_layer_state_set_kb(state); | 42 | debug("default_layer_state: "); |
| 43 | debug("default_layer_state: "); | 43 | default_layer_debug(); debug(" to "); |
| 44 | default_layer_debug(); debug(" to "); | 44 | default_layer_state = state; |
| 45 | default_layer_state = state; | 45 | default_layer_debug(); debug("\n"); |
| 46 | default_layer_debug(); debug("\n"); | ||
| 47 | #ifdef STRICT_LAYER_RELEASE | 46 | #ifdef STRICT_LAYER_RELEASE |
| 48 | clear_keyboard_but_mods(); // To avoid stuck keys | 47 | clear_keyboard_but_mods(); // To avoid stuck keys |
| 49 | #else | 48 | #else |
| 50 | clear_keyboard_but_mods_and_keys(); // Don't reset held keys | 49 | clear_keyboard_but_mods_and_keys(); // Don't reset held keys |
| 51 | #endif | 50 | #endif |
| 52 | } | 51 | } |
| 53 | 52 | ||
| 54 | /** \brief Default Layer Print | 53 | /** \brief Default Layer Print |
| 55 | * | 54 | * |
| 56 | * FIXME: Needs docs | 55 | * Print out the hex value of the 32-bit default layer state, as well as the value of the highest bit. |
| 57 | */ | 56 | */ |
| 58 | void default_layer_debug(void) | 57 | void default_layer_debug(void) { |
| 59 | { | 58 | dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state)); |
| 60 | dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state)); | ||
| 61 | } | 59 | } |
| 62 | 60 | ||
| 63 | /** \brief Default Layer Set | 61 | /** \brief Default Layer Set |
| 64 | * | 62 | * |
| 65 | * FIXME: Needs docs | 63 | * Sets the default layer state. |
| 66 | */ | 64 | */ |
| 67 | void default_layer_set(uint32_t state) | 65 | void default_layer_set(uint32_t state) { |
| 68 | { | 66 | default_layer_state_set(state); |
| 69 | default_layer_state_set(state); | ||
| 70 | } | 67 | } |
| 71 | 68 | ||
| 72 | #ifndef NO_ACTION_LAYER | 69 | #ifndef NO_ACTION_LAYER |
| 73 | /** \brief Default Layer Or | 70 | /** \brief Default Layer Or |
| 74 | * | 71 | * |
| 75 | * FIXME: Needs docs | 72 | * Turns on the default layer based on matching bits between specifed layer and existing layer state |
| 76 | */ | 73 | */ |
| 77 | void default_layer_or(uint32_t state) | 74 | void default_layer_or(uint32_t state) { |
| 78 | { | 75 | default_layer_state_set(default_layer_state | state); |
| 79 | default_layer_state_set(default_layer_state | state); | ||
| 80 | } | 76 | } |
| 81 | /** \brief Default Layer And | 77 | /** \brief Default Layer And |
| 82 | * | 78 | * |
| 83 | * FIXME: Needs docs | 79 | * Turns on default layer based on matching enabled bits between specifed layer and existing layer state |
| 84 | */ | 80 | */ |
| 85 | void default_layer_and(uint32_t state) | 81 | void default_layer_and(uint32_t state) { |
| 86 | { | 82 | default_layer_state_set(default_layer_state & state); |
| 87 | default_layer_state_set(default_layer_state & state); | ||
| 88 | } | 83 | } |
| 89 | /** \brief Default Layer Xor | 84 | /** \brief Default Layer Xor |
| 90 | * | 85 | * |
| 91 | * FIXME: Needs docs | 86 | * Turns on default layer based on non-matching bits between specifed layer and existing layer state |
| 92 | */ | 87 | */ |
| 93 | void default_layer_xor(uint32_t state) | 88 | void default_layer_xor(uint32_t state) { |
| 94 | { | 89 | default_layer_state_set(default_layer_state ^ state); |
| 95 | default_layer_state_set(default_layer_state ^ state); | ||
| 96 | } | 90 | } |
| 97 | #endif | 91 | #endif |
| 98 | 92 | ||
| @@ -104,170 +98,168 @@ uint32_t layer_state = 0; | |||
| 104 | 98 | ||
| 105 | /** \brief Layer state set user | 99 | /** \brief Layer state set user |
| 106 | * | 100 | * |
| 107 | * FIXME: Needs docs | 101 | * Runs user code on layer state change |
| 108 | */ | 102 | */ |
| 109 | __attribute__((weak)) | 103 | __attribute__((weak)) |
| 110 | uint32_t layer_state_set_user(uint32_t state) { | 104 | uint32_t layer_state_set_user(uint32_t state) { |
| 111 | return state; | 105 | return state; |
| 112 | } | 106 | } |
| 113 | 107 | ||
| 114 | /** \brief Layer state set keyboard | 108 | /** \brief Layer state set keyboard |
| 115 | * | 109 | * |
| 116 | * FIXME: Needs docs | 110 | * Runs keyboard code on layer state change |
| 117 | */ | 111 | */ |
| 118 | __attribute__((weak)) | 112 | __attribute__((weak)) |
| 119 | uint32_t layer_state_set_kb(uint32_t state) { | 113 | uint32_t layer_state_set_kb(uint32_t state) { |
| 120 | return layer_state_set_user(state); | 114 | return layer_state_set_user(state); |
| 121 | } | 115 | } |
| 122 | 116 | ||
| 123 | /** \brief Layer state set | 117 | /** \brief Layer state set |
| 124 | * | 118 | * |
| 125 | * FIXME: Needs docs | 119 | * Sets the layer to match the specifed state (a bitmask) |
| 126 | */ | 120 | */ |
| 127 | void layer_state_set(uint32_t state) | 121 | void layer_state_set(uint32_t state) { |
| 128 | { | 122 | state = layer_state_set_kb(state); |
| 129 | state = layer_state_set_kb(state); | 123 | dprint("layer_state: "); |
| 130 | dprint("layer_state: "); | 124 | layer_debug(); dprint(" to "); |
| 131 | layer_debug(); dprint(" to "); | 125 | layer_state = state; |
| 132 | layer_state = state; | 126 | layer_debug(); dprintln(); |
| 133 | layer_debug(); dprintln(); | ||
| 134 | #ifdef STRICT_LAYER_RELEASE | 127 | #ifdef STRICT_LAYER_RELEASE |
| 135 | clear_keyboard_but_mods(); // To avoid stuck keys | 128 | clear_keyboard_but_mods(); // To avoid stuck keys |
| 136 | #else | 129 | #else |
| 137 | clear_keyboard_but_mods_and_keys(); // Don't reset held keys | 130 | clear_keyboard_but_mods_and_keys(); // Don't reset held keys |
| 138 | #endif | 131 | #endif |
| 139 | } | 132 | } |
| 140 | 133 | ||
| 141 | /** \brief Layer clear | 134 | /** \brief Layer clear |
| 142 | * | 135 | * |
| 143 | * FIXME: Needs docs | 136 | * Turn off all layers |
| 144 | */ | 137 | */ |
| 145 | void layer_clear(void) | 138 | void layer_clear(void) { |
| 146 | { | 139 | layer_state_set(0); |
| 147 | layer_state_set(0); | ||
| 148 | } | 140 | } |
| 149 | 141 | ||
| 150 | /** \brief Layer state is | 142 | /** \brief Layer state is |
| 151 | * | 143 | * |
| 152 | * FIXME: Needs docs | 144 | * Return whether the given state is on (it might still be shadowed by a higher state, though) |
| 153 | */ | 145 | */ |
| 154 | bool layer_state_is(uint8_t layer) | 146 | bool layer_state_is(uint8_t layer) { |
| 155 | { | 147 | return layer_state_cmp(layer_state, layer); |
| 156 | return layer_state_cmp(layer_state, layer); | ||
| 157 | } | 148 | } |
| 158 | 149 | ||
| 159 | /** \brief Layer state compare | 150 | /** \brief Layer state compare |
| 160 | * | 151 | * |
| 161 | * FIXME: Needs docs | 152 | * Used for comparing layers {mostly used for unit testing} |
| 162 | */ | 153 | */ |
| 163 | bool layer_state_cmp(uint32_t cmp_layer_state, uint8_t layer) { | 154 | bool layer_state_cmp(uint32_t cmp_layer_state, uint8_t layer) { |
| 164 | if (!cmp_layer_state) { return layer == 0; } | 155 | if (!cmp_layer_state) { return layer == 0; } |
| 165 | return (cmp_layer_state & (1UL<<layer)) != 0; | 156 | return (cmp_layer_state & (1UL<<layer)) != 0; |
| 166 | } | 157 | } |
| 167 | 158 | ||
| 168 | /** \brief Layer move | 159 | /** \brief Layer move |
| 169 | * | 160 | * |
| 170 | * FIXME: Needs docs | 161 | * Turns on the given layer and turn off all other layers |
| 171 | */ | 162 | */ |
| 172 | void layer_move(uint8_t layer) | 163 | void layer_move(uint8_t layer) { |
| 173 | { | 164 | layer_state_set(1UL<<layer); |
| 174 | layer_state_set(1UL<<layer); | ||
| 175 | } | 165 | } |
| 176 | 166 | ||
| 177 | /** \brief Layer on | 167 | /** \brief Layer on |
| 178 | * | 168 | * |
| 179 | * FIXME: Needs docs | 169 | * Turns on given layer |
| 180 | */ | 170 | */ |
| 181 | void layer_on(uint8_t layer) | 171 | void layer_on(uint8_t layer) { |
| 182 | { | 172 | layer_state_set(layer_state | (1UL<<layer)); |
| 183 | layer_state_set(layer_state | (1UL<<layer)); | ||
| 184 | } | 173 | } |
| 185 | 174 | ||
| 186 | /** \brief Layer off | 175 | /** \brief Layer off |
| 187 | * | 176 | * |
| 188 | * FIXME: Needs docs | 177 | * Turns off given layer |
| 189 | */ | 178 | */ |
| 190 | void layer_off(uint8_t layer) | 179 | void layer_off(uint8_t layer) { |
| 191 | { | 180 | layer_state_set(layer_state & ~(1UL<<layer)); |
| 192 | layer_state_set(layer_state & ~(1UL<<layer)); | ||
| 193 | } | 181 | } |
| 194 | 182 | ||
| 195 | /** \brief Layer invert | 183 | /** \brief Layer invert |
| 196 | * | 184 | * |
| 197 | * FIXME: Needs docs | 185 | * Toggle the given layer (set it if it's unset, or unset it if it's set) |
| 198 | */ | 186 | */ |
| 199 | void layer_invert(uint8_t layer) | 187 | void layer_invert(uint8_t layer) { |
| 200 | { | 188 | layer_state_set(layer_state ^ (1UL<<layer)); |
| 201 | layer_state_set(layer_state ^ (1UL<<layer)); | ||
| 202 | } | 189 | } |
| 203 | 190 | ||
| 204 | /** \brief Layer or | 191 | /** \brief Layer or |
| 205 | * | 192 | * |
| 206 | * FIXME: Needs docs | 193 | * Turns on layers based on matching bits between specifed layer and existing layer state |
| 207 | */ | 194 | */ |
| 208 | void layer_or(uint32_t state) | 195 | void layer_or(uint32_t state) { |
| 209 | { | 196 | layer_state_set(layer_state | state); |
| 210 | layer_state_set(layer_state | state); | ||
| 211 | } | 197 | } |
| 212 | /** \brief Layer and | 198 | /** \brief Layer and |
| 213 | * | 199 | * |
| 214 | * FIXME: Needs docs | 200 | * Turns on layers based on matching enabled bits between specifed layer and existing layer state |
| 215 | */ | 201 | */ |
| 216 | void layer_and(uint32_t state) | 202 | void layer_and(uint32_t state) { |
| 217 | { | 203 | layer_state_set(layer_state & state); |
| 218 | layer_state_set(layer_state & state); | ||
| 219 | } | 204 | } |
| 220 | /** \brief Layer xor | 205 | /** \brief Layer xor |
| 221 | * | 206 | * |
| 222 | * FIXME: Needs docs | 207 | * Turns on layers based on non-matching bits between specifed layer and existing layer state |
| 223 | */ | 208 | */ |
| 224 | void layer_xor(uint32_t state) | 209 | void layer_xor(uint32_t state) { |
| 225 | { | 210 | layer_state_set(layer_state ^ state); |
| 226 | layer_state_set(layer_state ^ state); | ||
| 227 | } | 211 | } |
| 228 | 212 | ||
| 229 | /** \brief Layer debug printing | 213 | /** \brief Layer debug printing |
| 230 | * | 214 | * |
| 231 | * FIXME: Needs docs | 215 | * Print out the hex value of the 32-bit layer state, as well as the value of the highest bit. |
| 232 | */ | 216 | */ |
| 233 | void layer_debug(void) | 217 | void layer_debug(void) { |
| 234 | { | 218 | dprintf("%08lX(%u)", layer_state, biton32(layer_state)); |
| 235 | dprintf("%08lX(%u)", layer_state, biton32(layer_state)); | ||
| 236 | } | 219 | } |
| 237 | #endif | 220 | #endif |
| 238 | 221 | ||
| 239 | #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) | 222 | #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) |
| 223 | /** \brief source layer cache | ||
| 224 | */ | ||
| 225 | |||
| 240 | uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}}; | 226 | uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}}; |
| 241 | 227 | ||
| 242 | void update_source_layers_cache(keypos_t key, uint8_t layer) | 228 | /** \brief update source layers cache |
| 243 | { | 229 | * |
| 244 | const uint8_t key_number = key.col + (key.row * MATRIX_COLS); | 230 | * Updates the cached keys when changing layers |
| 245 | const uint8_t storage_row = key_number / 8; | 231 | */ |
| 246 | const uint8_t storage_bit = key_number % 8; | 232 | void update_source_layers_cache(keypos_t key, uint8_t layer) { |
| 247 | 233 | const uint8_t key_number = key.col + (key.row * MATRIX_COLS); | |
| 248 | for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { | 234 | const uint8_t storage_row = key_number / 8; |
| 249 | source_layers_cache[storage_row][bit_number] ^= | 235 | const uint8_t storage_bit = key_number % 8; |
| 250 | (-((layer & (1U << bit_number)) != 0) | 236 | |
| 251 | ^ source_layers_cache[storage_row][bit_number]) | 237 | for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { |
| 252 | & (1U << storage_bit); | 238 | source_layers_cache[storage_row][bit_number] ^= |
| 253 | } | 239 | (-((layer & (1U << bit_number)) != 0) |
| 240 | ^ source_layers_cache[storage_row][bit_number]) | ||
| 241 | & (1U << storage_bit); | ||
| 242 | } | ||
| 254 | } | 243 | } |
| 255 | 244 | ||
| 256 | uint8_t read_source_layers_cache(keypos_t key) | 245 | /** \brief read source layers cache |
| 257 | { | 246 | * |
| 258 | const uint8_t key_number = key.col + (key.row * MATRIX_COLS); | 247 | * reads the cached keys stored when the layer was changed |
| 259 | const uint8_t storage_row = key_number / 8; | 248 | */ |
| 260 | const uint8_t storage_bit = key_number % 8; | 249 | uint8_t read_source_layers_cache(keypos_t key) { |
| 261 | uint8_t layer = 0; | 250 | const uint8_t key_number = key.col + (key.row * MATRIX_COLS); |
| 262 | 251 | const uint8_t storage_row = key_number / 8; | |
| 263 | for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { | 252 | const uint8_t storage_bit = key_number % 8; |
| 264 | layer |= | 253 | uint8_t layer = 0; |
| 265 | ((source_layers_cache[storage_row][bit_number] | 254 | |
| 266 | & (1U << storage_bit)) != 0) | 255 | for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { |
| 267 | << bit_number; | 256 | layer |= |
| 268 | } | 257 | ((source_layers_cache[storage_row][bit_number] |
| 269 | 258 | & (1U << storage_bit)) != 0) | |
| 270 | return layer; | 259 | << bit_number; |
| 260 | } | ||
| 261 | |||
| 262 | return layer; | ||
| 271 | } | 263 | } |
| 272 | #endif | 264 | #endif |
| 273 | 265 | ||
| @@ -278,61 +270,58 @@ uint8_t read_source_layers_cache(keypos_t key) | |||
| 278 | * when the layer is switched after the down event but before the up | 270 | * when the layer is switched after the down event but before the up |
| 279 | * event as they may get stuck otherwise. | 271 | * event as they may get stuck otherwise. |
| 280 | */ | 272 | */ |
| 281 | action_t store_or_get_action(bool pressed, keypos_t key) | 273 | action_t store_or_get_action(bool pressed, keypos_t key) { |
| 282 | { | ||
| 283 | #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) | 274 | #if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE) |
| 284 | if (disable_action_cache) { | 275 | if (disable_action_cache) { |
| 285 | return layer_switch_get_action(key); | ||
| 286 | } | ||
| 287 | |||
| 288 | uint8_t layer; | ||
| 289 | |||
| 290 | if (pressed) { | ||
| 291 | layer = layer_switch_get_layer(key); | ||
| 292 | update_source_layers_cache(key, layer); | ||
| 293 | } | ||
| 294 | else { | ||
| 295 | layer = read_source_layers_cache(key); | ||
| 296 | } | ||
| 297 | return action_for_key(layer, key); | ||
| 298 | #else | ||
| 299 | return layer_switch_get_action(key); | 276 | return layer_switch_get_action(key); |
| 277 | } | ||
| 278 | |||
| 279 | uint8_t layer; | ||
| 280 | |||
| 281 | if (pressed) { | ||
| 282 | layer = layer_switch_get_layer(key); | ||
| 283 | update_source_layers_cache(key, layer); | ||
| 284 | } | ||
| 285 | else { | ||
| 286 | layer = read_source_layers_cache(key); | ||
| 287 | } | ||
| 288 | return action_for_key(layer, key); | ||
| 289 | #else | ||
| 290 | return layer_switch_get_action(key); | ||
| 300 | #endif | 291 | #endif |
| 301 | } | 292 | } |
| 302 | 293 | ||
| 303 | 294 | ||
| 304 | /** \brief Layer switch get layer | 295 | /** \brief Layer switch get layer |
| 305 | * | 296 | * |
| 306 | * FIXME: Needs docs | 297 | * Gets the layer based on key info |
| 307 | */ | 298 | */ |
| 308 | int8_t layer_switch_get_layer(keypos_t key) | 299 | int8_t layer_switch_get_layer(keypos_t key) { |
| 309 | { | ||
| 310 | #ifndef NO_ACTION_LAYER | 300 | #ifndef NO_ACTION_LAYER |
| 311 | action_t action; | 301 | action_t action; |
| 312 | action.code = ACTION_TRANSPARENT; | 302 | action.code = ACTION_TRANSPARENT; |
| 313 | 303 | ||
| 314 | uint32_t layers = layer_state | default_layer_state; | 304 | uint32_t layers = layer_state | default_layer_state; |
| 315 | /* check top layer first */ | 305 | /* check top layer first */ |
| 316 | for (int8_t i = 31; i >= 0; i--) { | 306 | for (int8_t i = 31; i >= 0; i--) { |
| 317 | if (layers & (1UL<<i)) { | 307 | if (layers & (1UL<<i)) { |
| 318 | action = action_for_key(i, key); | 308 | action = action_for_key(i, key); |
| 319 | if (action.code != ACTION_TRANSPARENT) { | 309 | if (action.code != ACTION_TRANSPARENT) { |
| 320 | return i; | 310 | return i; |
| 321 | } | 311 | } |
| 322 | } | ||
| 323 | } | 312 | } |
| 324 | /* fall back to layer 0 */ | 313 | } |
| 325 | return 0; | 314 | /* fall back to layer 0 */ |
| 315 | return 0; | ||
| 326 | #else | 316 | #else |
| 327 | return biton32(default_layer_state); | 317 | return biton32(default_layer_state); |
| 328 | #endif | 318 | #endif |
| 329 | } | 319 | } |
| 330 | 320 | ||
| 331 | /** \brief Layer switch get layer | 321 | /** \brief Layer switch get layer |
| 332 | * | 322 | * |
| 333 | * FIXME: Needs docs | 323 | * Gets action code based on key position |
| 334 | */ | 324 | */ |
| 335 | action_t layer_switch_get_action(keypos_t key) | 325 | action_t layer_switch_get_action(keypos_t key) { |
| 336 | { | 326 | return action_for_key(layer_switch_get_layer(key), key); |
| 337 | return action_for_key(layer_switch_get_layer(key), key); | ||
| 338 | } | 327 | } |
diff --git a/tmk_core/common/action_util.c b/tmk_core/common/action_util.c index afd4ae8b2..58401ace5 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; } | |||
| 54 | void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; } | 54 | void set_oneshot_locked_mods(int8_t mods) { oneshot_locked_mods = mods; } |
| 55 | void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; } | 55 | void clear_oneshot_locked_mods(void) { oneshot_locked_mods = 0; } |
| 56 | #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) | 56 | #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) |
| 57 | static int16_t oneshot_time = 0; | 57 | static uint16_t oneshot_time = 0; |
| 58 | bool has_oneshot_mods_timed_out(void) { | 58 | bool has_oneshot_mods_timed_out(void) { |
| 59 | return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; | 59 | return TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT; |
| 60 | } | 60 | } |
| @@ -79,7 +79,7 @@ inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; } | |||
| 79 | inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } | 79 | inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; } |
| 80 | 80 | ||
| 81 | #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) | 81 | #if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)) |
| 82 | static int16_t oneshot_layer_time = 0; | 82 | static uint16_t oneshot_layer_time = 0; |
| 83 | inline bool has_oneshot_layer_timed_out() { | 83 | inline bool has_oneshot_layer_timed_out() { |
| 84 | return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && | 84 | return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && |
| 85 | !(get_oneshot_layer_state() & ONESHOT_TOGGLED); | 85 | !(get_oneshot_layer_state() & ONESHOT_TOGGLED); |
diff --git a/tmk_core/common/arm_atsam/timer.c b/tmk_core/common/arm_atsam/timer.c index bcfe5002c..6c3905e30 100644 --- a/tmk_core/common/arm_atsam/timer.c +++ b/tmk_core/common/arm_atsam/timer.c | |||
| @@ -9,7 +9,7 @@ void set_time(uint64_t tset) | |||
| 9 | 9 | ||
| 10 | void timer_init(void) | 10 | void timer_init(void) |
| 11 | { | 11 | { |
| 12 | ms_clk = 0; | 12 | timer_clear(); |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | uint16_t timer_read(void) | 15 | uint16_t timer_read(void) |
| @@ -37,23 +37,7 @@ uint32_t timer_elapsed32(uint32_t tlast) | |||
| 37 | return TIMER_DIFF_32(timer_read32(), tlast); | 37 | return TIMER_DIFF_32(timer_read32(), tlast); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | uint32_t timer_elapsed64(uint32_t tlast) | ||
| 41 | { | ||
| 42 | uint64_t tnow = timer_read64(); | ||
| 43 | return (tnow >= tlast ? tnow - tlast : UINT64_MAX - tlast + tnow); | ||
| 44 | } | ||
| 45 | |||
| 46 | void timer_clear(void) | 40 | void timer_clear(void) |
| 47 | { | 41 | { |
| 48 | ms_clk = 0; | 42 | set_time(0); |
| 49 | } | ||
| 50 | |||
| 51 | void wait_ms(uint64_t msec) | ||
| 52 | { | ||
| 53 | CLK_delay_ms(msec); | ||
| 54 | } | ||
| 55 | |||
| 56 | void wait_us(uint16_t usec) | ||
| 57 | { | ||
| 58 | CLK_delay_us(usec); | ||
| 59 | } | 43 | } |
diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c index a86998550..a15430d67 100755 --- a/tmk_core/common/chibios/eeprom_stm32.c +++ b/tmk_core/common/chibios/eeprom_stm32.c | |||
| @@ -10,664 +10,206 @@ | |||
| 10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 11 | * DEALINGS IN THE SOFTWARE. | 11 | * DEALINGS IN THE SOFTWARE. |
| 12 | * | 12 | * |
| 13 | * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and | 13 | * This files are free to use from http://engsta.com/stm32-flash-memory-eeprom-emulator/ by |
| 14 | * https://github.com/leaflabs/libmaple | 14 | * Artur F. |
| 15 | * | 15 | * |
| 16 | * Modifications for QMK and STM32F303 by Yiancar | 16 | * Modifications for QMK and STM32F303 by Yiancar |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <stdio.h> | ||
| 20 | #include <string.h> | ||
| 19 | #include "eeprom_stm32.h" | 21 | #include "eeprom_stm32.h" |
| 22 | /***************************************************************************** | ||
| 23 | * Allows to use the internal flash to store non volatile data. To initialize | ||
| 24 | * the functionality use the EEPROM_Init() function. Be sure that by reprogramming | ||
| 25 | * of the controller just affected pages will be deleted. In other case the non | ||
| 26 | * volatile data will be lost. | ||
| 27 | ******************************************************************************/ | ||
| 28 | |||
| 29 | /* Private macro -------------------------------------------------------------*/ | ||
| 30 | /* Private variables ---------------------------------------------------------*/ | ||
| 31 | /* Functions -----------------------------------------------------------------*/ | ||
| 32 | |||
| 33 | uint8_t DataBuf[FEE_PAGE_SIZE]; | ||
| 34 | /***************************************************************************** | ||
| 35 | * Delete Flash Space used for user Data, deletes the whole space between | ||
| 36 | * RW_PAGE_BASE_ADDRESS and the last uC Flash Page | ||
| 37 | ******************************************************************************/ | ||
| 38 | uint16_t EEPROM_Init(void) { | ||
| 39 | // unlock flash | ||
| 40 | FLASH_Unlock(); | ||
| 20 | 41 | ||
| 21 | FLASH_Status EE_ErasePage(uint32_t); | 42 | // Clear Flags |
| 22 | 43 | //FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR); | |
| 23 | uint16_t EE_CheckPage(uint32_t, uint16_t); | ||
| 24 | uint16_t EE_CheckErasePage(uint32_t, uint16_t); | ||
| 25 | uint16_t EE_Format(void); | ||
| 26 | uint32_t EE_FindValidPage(void); | ||
| 27 | uint16_t EE_GetVariablesCount(uint32_t, uint16_t); | ||
| 28 | uint16_t EE_PageTransfer(uint32_t, uint32_t, uint16_t); | ||
| 29 | uint16_t EE_VerifyPageFullWriteVariable(uint16_t, uint16_t); | ||
| 30 | |||
| 31 | uint32_t PageBase0 = EEPROM_PAGE0_BASE; | ||
| 32 | uint32_t PageBase1 = EEPROM_PAGE1_BASE; | ||
| 33 | uint32_t PageSize = EEPROM_PAGE_SIZE; | ||
| 34 | uint16_t Status = EEPROM_NOT_INIT; | ||
| 35 | |||
| 36 | // See http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf | ||
| 37 | |||
| 38 | /** | ||
| 39 | * @brief Check page for blank | ||
| 40 | * @param page base address | ||
| 41 | * @retval Success or error | ||
| 42 | * EEPROM_BAD_FLASH: page not empty after erase | ||
| 43 | * EEPROM_OK: page blank | ||
| 44 | */ | ||
| 45 | uint16_t EE_CheckPage(uint32_t pageBase, uint16_t status) | ||
| 46 | { | ||
| 47 | uint32_t pageEnd = pageBase + (uint32_t)PageSize; | ||
| 48 | |||
| 49 | // Page Status not EEPROM_ERASED and not a "state" | ||
| 50 | if ((*(__IO uint16_t*)pageBase) != EEPROM_ERASED && (*(__IO uint16_t*)pageBase) != status) | ||
| 51 | return EEPROM_BAD_FLASH; | ||
| 52 | for(pageBase += 4; pageBase < pageEnd; pageBase += 4) | ||
| 53 | if ((*(__IO uint32_t*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty | ||
| 54 | return EEPROM_BAD_FLASH; | ||
| 55 | return EEPROM_OK; | ||
| 56 | } | ||
| 57 | |||
| 58 | /** | ||
| 59 | * @brief Erase page with increment erase counter (page + 2) | ||
| 60 | * @param page base address | ||
| 61 | * @retval Success or error | ||
| 62 | * FLASH_COMPLETE: success erase | ||
| 63 | * - Flash error code: on write Flash error | ||
| 64 | */ | ||
| 65 | FLASH_Status EE_ErasePage(uint32_t pageBase) | ||
| 66 | { | ||
| 67 | FLASH_Status FlashStatus; | ||
| 68 | uint16_t data = (*(__IO uint16_t*)(pageBase)); | ||
| 69 | if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA)) | ||
| 70 | data = (*(__IO uint16_t*)(pageBase + 2)) + 1; | ||
| 71 | else | ||
| 72 | data = 0; | ||
| 73 | |||
| 74 | FlashStatus = FLASH_ErasePage(pageBase); | ||
| 75 | if (FlashStatus == FLASH_COMPLETE) | ||
| 76 | FlashStatus = FLASH_ProgramHalfWord(pageBase + 2, data); | ||
| 77 | |||
| 78 | return FlashStatus; | ||
| 79 | } | ||
| 80 | 44 | ||
| 81 | /** | 45 | return FEE_DENSITY_BYTES; |
| 82 | * @brief Check page for blank and erase it | ||
| 83 | * @param page base address | ||
| 84 | * @retval Success or error | ||
| 85 | * - Flash error code: on write Flash error | ||
| 86 | * - EEPROM_BAD_FLASH: page not empty after erase | ||
| 87 | * - EEPROM_OK: page blank | ||
| 88 | */ | ||
| 89 | uint16_t EE_CheckErasePage(uint32_t pageBase, uint16_t status) | ||
| 90 | { | ||
| 91 | uint16_t FlashStatus; | ||
| 92 | if (EE_CheckPage(pageBase, status) != EEPROM_OK) | ||
| 93 | { | ||
| 94 | FlashStatus = EE_ErasePage(pageBase); | ||
| 95 | if (FlashStatus != FLASH_COMPLETE) | ||
| 96 | return FlashStatus; | ||
| 97 | return EE_CheckPage(pageBase, status); | ||
| 98 | } | ||
| 99 | return EEPROM_OK; | ||
| 100 | } | 46 | } |
| 47 | /***************************************************************************** | ||
| 48 | * Erase the whole reserved Flash Space used for user Data | ||
| 49 | ******************************************************************************/ | ||
| 50 | void EEPROM_Erase (void) { | ||
| 101 | 51 | ||
| 102 | /** | 52 | int page_num = 0; |
| 103 | * @brief Find valid Page for write or read operation | ||
| 104 | * @param Page0: Page0 base address | ||
| 105 | * Page1: Page1 base address | ||
| 106 | * @retval Valid page address (PAGE0 or PAGE1) or NULL in case of no valid page was found | ||
| 107 | */ | ||
| 108 | uint32_t EE_FindValidPage(void) | ||
| 109 | { | ||
| 110 | uint16_t status0 = (*(__IO uint16_t*)PageBase0); // Get Page0 actual status | ||
| 111 | uint16_t status1 = (*(__IO uint16_t*)PageBase1); // Get Page1 actual status | ||
| 112 | |||
| 113 | if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED) | ||
| 114 | return PageBase0; | ||
| 115 | if (status1 == EEPROM_VALID_PAGE && status0 == EEPROM_ERASED) | ||
| 116 | return PageBase1; | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | 53 | ||
| 121 | /** | 54 | // delete all pages from specified start page to the last page |
| 122 | * @brief Calculate unique variables in EEPROM | 55 | do { |
| 123 | * @param start: address of first slot to check (page + 4) | 56 | FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE)); |
| 124 | * @param end: page end address | 57 | page_num++; |
| 125 | * @param address: 16 bit virtual address of the variable to excluse (or 0XFFFF) | 58 | } while (page_num < FEE_DENSITY_PAGES); |
| 126 | * @retval count of variables | ||
| 127 | */ | ||
| 128 | uint16_t EE_GetVariablesCount(uint32_t pageBase, uint16_t skipAddress) | ||
| 129 | { | ||
| 130 | uint16_t varAddress, nextAddress; | ||
| 131 | uint32_t idx; | ||
| 132 | uint32_t pageEnd = pageBase + (uint32_t)PageSize; | ||
| 133 | uint16_t count = 0; | ||
| 134 | |||
| 135 | for (pageBase += 6; pageBase < pageEnd; pageBase += 4) | ||
| 136 | { | ||
| 137 | varAddress = (*(__IO uint16_t*)pageBase); | ||
| 138 | if (varAddress == 0xFFFF || varAddress == skipAddress) | ||
| 139 | continue; | ||
| 140 | |||
| 141 | count++; | ||
| 142 | for(idx = pageBase + 4; idx < pageEnd; idx += 4) | ||
| 143 | { | ||
| 144 | nextAddress = (*(__IO uint16_t*)idx); | ||
| 145 | if (nextAddress == varAddress) | ||
| 146 | { | ||
| 147 | count--; | ||
| 148 | break; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | } | ||
| 152 | return count; | ||
| 153 | } | 59 | } |
| 60 | /***************************************************************************** | ||
| 61 | * Writes once data byte to flash on specified address. If a byte is already | ||
| 62 | * written, the whole page must be copied to a buffer, the byte changed and | ||
| 63 | * the manipulated buffer written after PageErase. | ||
| 64 | *******************************************************************************/ | ||
| 65 | uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) { | ||
| 154 | 66 | ||
| 155 | /** | 67 | FLASH_Status FlashStatus = FLASH_COMPLETE; |
| 156 | * @brief Transfers last updated variables data from the full Page to an empty one. | ||
| 157 | * @param newPage: new page base address | ||
| 158 | * @param oldPage: old page base address | ||
| 159 | * @param SkipAddress: 16 bit virtual address of the variable (or 0xFFFF) | ||
| 160 | * @retval Success or error status: | ||
| 161 | * - FLASH_COMPLETE: on success | ||
| 162 | * - EEPROM_OUT_SIZE: if valid new page is full | ||
| 163 | * - Flash error code: on write Flash error | ||
| 164 | */ | ||
| 165 | uint16_t EE_PageTransfer(uint32_t newPage, uint32_t oldPage, uint16_t SkipAddress) | ||
| 166 | { | ||
| 167 | uint32_t oldEnd, newEnd; | ||
| 168 | uint32_t oldIdx, newIdx, idx; | ||
| 169 | uint16_t address, data, found; | ||
| 170 | FLASH_Status FlashStatus; | ||
| 171 | |||
| 172 | // Transfer process: transfer variables from old to the new active page | ||
| 173 | newEnd = newPage + ((uint32_t)PageSize); | ||
| 174 | |||
| 175 | // Find first free element in new page | ||
| 176 | for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4) | ||
| 177 | if ((*(__IO uint32_t*)newIdx) == 0xFFFFFFFF) // Verify if element | ||
| 178 | break; // contents are 0xFFFFFFFF | ||
| 179 | if (newIdx >= newEnd) | ||
| 180 | return EEPROM_OUT_SIZE; | ||
| 181 | |||
| 182 | oldEnd = oldPage + 4; | ||
| 183 | oldIdx = oldPage + (uint32_t)(PageSize - 2); | ||
| 184 | |||
| 185 | for (; oldIdx > oldEnd; oldIdx -= 4) | ||
| 186 | { | ||
| 187 | address = *(__IO uint16_t*)oldIdx; | ||
| 188 | if (address == 0xFFFF || address == SkipAddress) | ||
| 189 | continue; // it's means that power off after write data | ||
| 190 | |||
| 191 | found = 0; | ||
| 192 | for (idx = newPage + 6; idx < newIdx; idx += 4) | ||
| 193 | if ((*(__IO uint16_t*)(idx)) == address) | ||
| 194 | { | ||
| 195 | found = 1; | ||
| 196 | break; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (found) | ||
| 200 | continue; | ||
| 201 | |||
| 202 | if (newIdx < newEnd) | ||
| 203 | { | ||
| 204 | data = (*(__IO uint16_t*)(oldIdx - 2)); | ||
| 205 | |||
| 206 | FlashStatus = FLASH_ProgramHalfWord(newIdx, data); | ||
| 207 | if (FlashStatus != FLASH_COMPLETE) | ||
| 208 | return FlashStatus; | ||
| 209 | 68 | ||
| 210 | FlashStatus = FLASH_ProgramHalfWord(newIdx + 2, address); | 69 | uint32_t page; |
| 211 | if (FlashStatus != FLASH_COMPLETE) | 70 | int i; |
| 212 | return FlashStatus; | ||
| 213 | 71 | ||
| 214 | newIdx += 4; | 72 | // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages) |
| 215 | } | 73 | if (Address > FEE_DENSITY_BYTES) { |
| 216 | else | 74 | return 0; |
| 217 | return EEPROM_OUT_SIZE; | ||
| 218 | } | 75 | } |
| 219 | 76 | ||
| 220 | // Erase the old Page: Set old Page status to EEPROM_EEPROM_ERASED status | 77 | // calculate which page is affected (Pagenum1/Pagenum2...PagenumN) |
| 221 | data = EE_CheckErasePage(oldPage, EEPROM_ERASED); | 78 | page = (FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)) & 0x00000FFF; |
| 222 | if (data != EEPROM_OK) | ||
| 223 | return data; | ||
| 224 | 79 | ||
| 225 | // Set new Page status | 80 | if (page % FEE_PAGE_SIZE) page = page + FEE_PAGE_SIZE; |
| 226 | FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_VALID_PAGE); | 81 | page = (page / FEE_PAGE_SIZE) - 1; |
| 227 | if (FlashStatus != FLASH_COMPLETE) | ||
| 228 | return FlashStatus; | ||
| 229 | 82 | ||
| 230 | return EEPROM_OK; | 83 | // if current data is 0xFF, the byte is empty, just overwrite with the new one |
| 231 | } | 84 | if ((*(__IO uint16_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) { |
| 232 | 85 | ||
| 233 | /** | 86 | FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte)); |
| 234 | * @brief Verify if active page is full and Writes variable in EEPROM. | ||
| 235 | * @param Address: 16 bit virtual address of the variable | ||
| 236 | * @param Data: 16 bit data to be written as variable value | ||
| 237 | * @retval Success or error status: | ||
| 238 | * - FLASH_COMPLETE: on success | ||
| 239 | * - EEPROM_PAGE_FULL: if valid page is full (need page transfer) | ||
| 240 | * - EEPROM_NO_VALID_PAGE: if no valid page was found | ||
| 241 | * - EEPROM_OUT_SIZE: if EEPROM size exceeded | ||
| 242 | * - Flash error code: on write Flash error | ||
| 243 | */ | ||
| 244 | uint16_t EE_VerifyPageFullWriteVariable(uint16_t Address, uint16_t Data) | ||
| 245 | { | ||
| 246 | FLASH_Status FlashStatus; | ||
| 247 | uint32_t idx, pageBase, pageEnd, newPage; | ||
| 248 | uint16_t count; | ||
| 249 | |||
| 250 | // Get valid Page for write operation | ||
| 251 | pageBase = EE_FindValidPage(); | ||
| 252 | if (pageBase == 0) | ||
| 253 | return EEPROM_NO_VALID_PAGE; | ||
| 254 | |||
| 255 | // Get the valid Page end Address | ||
| 256 | pageEnd = pageBase + PageSize; // Set end of page | ||
| 257 | |||
| 258 | for (idx = pageEnd - 2; idx > pageBase; idx -= 4) | ||
| 259 | { | ||
| 260 | if ((*(__IO uint16_t*)idx) == Address) // Find last value for address | ||
| 261 | { | ||
| 262 | count = (*(__IO uint16_t*)(idx - 2)); // Read last data | ||
| 263 | if (count == Data) | ||
| 264 | return EEPROM_OK; | ||
| 265 | if (count == 0xFFFF) | ||
| 266 | { | ||
| 267 | FlashStatus = FLASH_ProgramHalfWord(idx - 2, Data); // Set variable data | ||
| 268 | if (FlashStatus == FLASH_COMPLETE) | ||
| 269 | return EEPROM_OK; | ||
| 270 | } | ||
| 271 | break; | ||
| 272 | } | ||
| 273 | } | 87 | } |
| 88 | else { | ||
| 274 | 89 | ||
| 275 | // Check each active page address starting from begining | 90 | // Copy Page to a buffer |
| 276 | for (idx = pageBase + 4; idx < pageEnd; idx += 4) | 91 | memcpy(DataBuf, (uint8_t*)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page |
| 277 | if ((*(__IO uint32_t*)idx) == 0xFFFFFFFF) // Verify if element | ||
| 278 | { // contents are 0xFFFFFFFF | ||
| 279 | FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data | ||
| 280 | if (FlashStatus != FLASH_COMPLETE) | ||
| 281 | return FlashStatus; | ||
| 282 | FlashStatus = FLASH_ProgramHalfWord(idx + 2, Address); // Set variable virtual address | ||
| 283 | if (FlashStatus != FLASH_COMPLETE) | ||
| 284 | return FlashStatus; | ||
| 285 | return EEPROM_OK; | ||
| 286 | } | ||
| 287 | |||
| 288 | // Empty slot not found, need page transfer | ||
| 289 | // Calculate unique variables in page | ||
| 290 | count = EE_GetVariablesCount(pageBase, Address) + 1; | ||
| 291 | if (count >= (PageSize / 4 - 1)) | ||
| 292 | return EEPROM_OUT_SIZE; | ||
| 293 | |||
| 294 | if (pageBase == PageBase1) | ||
| 295 | newPage = PageBase0; // New page address where variable will be moved to | ||
| 296 | else | ||
| 297 | newPage = PageBase1; | ||
| 298 | |||
| 299 | // Set the new Page status to RECEIVE_DATA status | ||
| 300 | FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_RECEIVE_DATA); | ||
| 301 | if (FlashStatus != FLASH_COMPLETE) | ||
| 302 | return FlashStatus; | ||
| 303 | |||
| 304 | // Write the variable passed as parameter in the new active page | ||
| 305 | FlashStatus = FLASH_ProgramHalfWord(newPage + 4, Data); | ||
| 306 | if (FlashStatus != FLASH_COMPLETE) | ||
| 307 | return FlashStatus; | ||
| 308 | |||
| 309 | FlashStatus = FLASH_ProgramHalfWord(newPage + 6, Address); | ||
| 310 | if (FlashStatus != FLASH_COMPLETE) | ||
| 311 | return FlashStatus; | ||
| 312 | |||
| 313 | return EE_PageTransfer(newPage, pageBase, Address); | ||
| 314 | } | ||
| 315 | |||
| 316 | /*EEPROMClass::EEPROMClass(void) | ||
| 317 | { | ||
| 318 | PageBase0 = EEPROM_PAGE0_BASE; | ||
| 319 | PageBase1 = EEPROM_PAGE1_BASE; | ||
| 320 | PageSize = EEPROM_PAGE_SIZE; | ||
| 321 | Status = EEPROM_NOT_INIT; | ||
| 322 | }*/ | ||
| 323 | /* | ||
| 324 | uint16_t EEPROM_init(uint32_t pageBase0, uint32_t pageBase1, uint32_t pageSize) | ||
| 325 | { | ||
| 326 | PageBase0 = pageBase0; | ||
| 327 | PageBase1 = pageBase1; | ||
| 328 | PageSize = pageSize; | ||
| 329 | return EEPROM_init(); | ||
| 330 | }*/ | ||
| 331 | 92 | ||
| 332 | uint16_t EEPROM_init(void) | 93 | // check if new data is differ to current data, return if not, proceed if yes |
| 333 | { | 94 | if (DataByte == *(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) { |
| 334 | uint16_t status0 = 6, status1 = 6; | 95 | return 0; |
| 335 | FLASH_Status FlashStatus; | 96 | } |
| 336 | 97 | ||
| 337 | FLASH_Unlock(); | 98 | // manipulate desired data byte in temp data array if new byte is differ to the current |
| 338 | Status = EEPROM_NO_VALID_PAGE; | 99 | DataBuf[FEE_ADDR_OFFSET(Address)] = DataByte; |
| 339 | 100 | ||
| 340 | status0 = (*(__IO uint16_t *)PageBase0); | 101 | //Erase Page |
| 341 | status1 = (*(__IO uint16_t *)PageBase1); | 102 | FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + page); |
| 342 | 103 | ||
| 343 | switch (status0) | 104 | // Write new data (whole page) to flash if data has beed changed |
| 344 | { | 105 | for(i = 0; i < (FEE_PAGE_SIZE / 2); i++) { |
| 345 | /* | 106 | if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) { |
| 346 | Page0 Page1 | 107 | FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)])); |
| 347 | ----- ----- | ||
| 348 | EEPROM_ERASED EEPROM_VALID_PAGE Page1 valid, Page0 erased | ||
| 349 | EEPROM_RECEIVE_DATA Page1 need set to valid, Page0 erased | ||
| 350 | EEPROM_ERASED make EE_Format | ||
| 351 | any Error: EEPROM_NO_VALID_PAGE | ||
| 352 | */ | ||
| 353 | case EEPROM_ERASED: | ||
| 354 | if (status1 == EEPROM_VALID_PAGE) // Page0 erased, Page1 valid | ||
| 355 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); | ||
| 356 | else if (status1 == EEPROM_RECEIVE_DATA) // Page0 erased, Page1 receive | ||
| 357 | { | ||
| 358 | FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); | ||
| 359 | if (FlashStatus != FLASH_COMPLETE) | ||
| 360 | Status = FlashStatus; | ||
| 361 | else | ||
| 362 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); | ||
| 363 | } | ||
| 364 | else if (status1 == EEPROM_ERASED) // Both in erased state so format EEPROM | ||
| 365 | Status = EEPROM_format(); | ||
| 366 | break; | ||
| 367 | /* | ||
| 368 | Page0 Page1 | ||
| 369 | ----- ----- | ||
| 370 | EEPROM_RECEIVE_DATA EEPROM_VALID_PAGE Transfer Page1 to Page0 | ||
| 371 | EEPROM_ERASED Page0 need set to valid, Page1 erased | ||
| 372 | any EEPROM_NO_VALID_PAGE | ||
| 373 | */ | ||
| 374 | case EEPROM_RECEIVE_DATA: | ||
| 375 | if (status1 == EEPROM_VALID_PAGE) // Page0 receive, Page1 valid | ||
| 376 | Status = EE_PageTransfer(PageBase0, PageBase1, 0xFFFF); | ||
| 377 | else if (status1 == EEPROM_ERASED) // Page0 receive, Page1 erased | ||
| 378 | { | ||
| 379 | Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); | ||
| 380 | if (Status == EEPROM_OK) | ||
| 381 | { | ||
| 382 | FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); | ||
| 383 | if (FlashStatus != FLASH_COMPLETE) | ||
| 384 | Status = FlashStatus; | ||
| 385 | else | ||
| 386 | Status = EEPROM_OK; | ||
| 387 | } | 108 | } |
| 388 | } | 109 | } |
| 389 | break; | ||
| 390 | /* | ||
| 391 | Page0 Page1 | ||
| 392 | ----- ----- | ||
| 393 | EEPROM_VALID_PAGE EEPROM_VALID_PAGE Error: EEPROM_NO_VALID_PAGE | ||
| 394 | EEPROM_RECEIVE_DATA Transfer Page0 to Page1 | ||
| 395 | any Page0 valid, Page1 erased | ||
| 396 | */ | ||
| 397 | case EEPROM_VALID_PAGE: | ||
| 398 | if (status1 == EEPROM_VALID_PAGE) // Both pages valid | ||
| 399 | Status = EEPROM_NO_VALID_PAGE; | ||
| 400 | else if (status1 == EEPROM_RECEIVE_DATA) | ||
| 401 | Status = EE_PageTransfer(PageBase1, PageBase0, 0xFFFF); | ||
| 402 | else | ||
| 403 | Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); | ||
| 404 | break; | ||
| 405 | /* | ||
| 406 | Page0 Page1 | ||
| 407 | ----- ----- | ||
| 408 | any EEPROM_VALID_PAGE Page1 valid, Page0 erased | ||
| 409 | EEPROM_RECEIVE_DATA Page1 valid, Page0 erased | ||
| 410 | any EEPROM_NO_VALID_PAGE | ||
| 411 | */ | ||
| 412 | default: | ||
| 413 | if (status1 == EEPROM_VALID_PAGE) | ||
| 414 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); // Check/Erase Page0 | ||
| 415 | else if (status1 == EEPROM_RECEIVE_DATA) | ||
| 416 | { | ||
| 417 | FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); | ||
| 418 | if (FlashStatus != FLASH_COMPLETE) | ||
| 419 | Status = FlashStatus; | ||
| 420 | else | ||
| 421 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); | ||
| 422 | } | ||
| 423 | break; | ||
| 424 | } | ||
| 425 | return Status; | ||
| 426 | } | ||
| 427 | |||
| 428 | /** | ||
| 429 | * @brief Erases PAGE0 and PAGE1 and writes EEPROM_VALID_PAGE / 0 header to PAGE0 | ||
| 430 | * @param PAGE0 and PAGE1 base addresses | ||
| 431 | * @retval Status of the last operation (Flash write or erase) done during EEPROM formating | ||
| 432 | */ | ||
| 433 | uint16_t EEPROM_format(void) | ||
| 434 | { | ||
| 435 | uint16_t status; | ||
| 436 | FLASH_Status FlashStatus; | ||
| 437 | 110 | ||
| 438 | FLASH_Unlock(); | ||
| 439 | |||
| 440 | // Erase Page0 | ||
| 441 | status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE); | ||
| 442 | if (status != EEPROM_OK) | ||
| 443 | return status; | ||
| 444 | if ((*(__IO uint16_t*)PageBase0) == EEPROM_ERASED) | ||
| 445 | { | ||
| 446 | // Set Page0 as valid page: Write VALID_PAGE at Page0 base address | ||
| 447 | FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); | ||
| 448 | if (FlashStatus != FLASH_COMPLETE) | ||
| 449 | return FlashStatus; | ||
| 450 | } | 111 | } |
| 451 | // Erase Page1 | 112 | return FlashStatus; |
| 452 | return EE_CheckErasePage(PageBase1, EEPROM_ERASED); | ||
| 453 | } | ||
| 454 | |||
| 455 | /** | ||
| 456 | * @brief Returns the erase counter for current page | ||
| 457 | * @param Data: Global variable contains the read variable value | ||
| 458 | * @retval Success or error status: | ||
| 459 | * - EEPROM_OK: if erases counter return. | ||
| 460 | * - EEPROM_NO_VALID_PAGE: if no valid page was found. | ||
| 461 | */ | ||
| 462 | uint16_t EEPROM_erases(uint16_t *Erases) | ||
| 463 | { | ||
| 464 | uint32_t pageBase; | ||
| 465 | if (Status != EEPROM_OK) | ||
| 466 | if (EEPROM_init() != EEPROM_OK) | ||
| 467 | return Status; | ||
| 468 | |||
| 469 | // Get active Page for read operation | ||
| 470 | pageBase = EE_FindValidPage(); | ||
| 471 | if (pageBase == 0) | ||
| 472 | return EEPROM_NO_VALID_PAGE; | ||
| 473 | |||
| 474 | *Erases = (*(__IO uint16_t*)pageBase+2); | ||
| 475 | return EEPROM_OK; | ||
| 476 | } | ||
| 477 | |||
| 478 | /** | ||
| 479 | * @brief Returns the last stored variable data, if found, | ||
| 480 | * which correspond to the passed virtual address | ||
| 481 | * @param Address: Variable virtual address | ||
| 482 | * @retval Data for variable or EEPROM_DEFAULT_DATA, if any errors | ||
| 483 | */ | ||
| 484 | /* | ||
| 485 | uint16_t EEPROM_read (uint16_t Address) | ||
| 486 | { | ||
| 487 | uint16_t data; | ||
| 488 | EEPROM_read(Address, &data); | ||
| 489 | return data; | ||
| 490 | }*/ | ||
| 491 | |||
| 492 | /** | ||
| 493 | * @brief Returns the last stored variable data, if found, | ||
| 494 | * which correspond to the passed virtual address | ||
| 495 | * @param Address: Variable virtual address | ||
| 496 | * @param Data: Pointer to data variable | ||
| 497 | * @retval Success or error status: | ||
| 498 | * - EEPROM_OK: if variable was found | ||
| 499 | * - EEPROM_BAD_ADDRESS: if the variable was not found | ||
| 500 | * - EEPROM_NO_VALID_PAGE: if no valid page was found. | ||
| 501 | */ | ||
| 502 | uint16_t EEPROM_read(uint16_t Address, uint16_t *Data) | ||
| 503 | { | ||
| 504 | uint32_t pageBase, pageEnd; | ||
| 505 | |||
| 506 | // Set default data (empty EEPROM) | ||
| 507 | *Data = EEPROM_DEFAULT_DATA; | ||
| 508 | |||
| 509 | if (Status == EEPROM_NOT_INIT) | ||
| 510 | if (EEPROM_init() != EEPROM_OK) | ||
| 511 | return Status; | ||
| 512 | |||
| 513 | // Get active Page for read operation | ||
| 514 | pageBase = EE_FindValidPage(); | ||
| 515 | if (pageBase == 0) | ||
| 516 | return EEPROM_NO_VALID_PAGE; | ||
| 517 | |||
| 518 | // Get the valid Page end Address | ||
| 519 | pageEnd = pageBase + ((uint32_t)(PageSize - 2)); | ||
| 520 | |||
| 521 | // Check each active page address starting from end | ||
| 522 | for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4) | ||
| 523 | if ((*(__IO uint16_t*)pageEnd) == Address) // Compare the read address with the virtual address | ||
| 524 | { | ||
| 525 | *Data = (*(__IO uint16_t*)(pageEnd - 2)); // Get content of Address-2 which is variable value | ||
| 526 | return EEPROM_OK; | ||
| 527 | } | ||
| 528 | |||
| 529 | // Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) | ||
| 530 | return EEPROM_BAD_ADDRESS; | ||
| 531 | } | ||
| 532 | |||
| 533 | /** | ||
| 534 | * @brief Writes/upadtes variable data in EEPROM. | ||
| 535 | * @param VirtAddress: Variable virtual address | ||
| 536 | * @param Data: 16 bit data to be written | ||
| 537 | * @retval Success or error status: | ||
| 538 | * - FLASH_COMPLETE: on success | ||
| 539 | * - EEPROM_BAD_ADDRESS: if address = 0xFFFF | ||
| 540 | * - EEPROM_PAGE_FULL: if valid page is full | ||
| 541 | * - EEPROM_NO_VALID_PAGE: if no valid page was found | ||
| 542 | * - EEPROM_OUT_SIZE: if no empty EEPROM variables | ||
| 543 | * - Flash error code: on write Flash error | ||
| 544 | */ | ||
| 545 | uint16_t EEPROM_write(uint16_t Address, uint16_t Data) | ||
| 546 | { | ||
| 547 | if (Status == EEPROM_NOT_INIT) | ||
| 548 | if (EEPROM_init() != EEPROM_OK) | ||
| 549 | return Status; | ||
| 550 | |||
| 551 | if (Address == 0xFFFF) | ||
| 552 | return EEPROM_BAD_ADDRESS; | ||
| 553 | |||
| 554 | // Write the variable virtual address and value in the EEPROM | ||
| 555 | uint16_t status = EE_VerifyPageFullWriteVariable(Address, Data); | ||
| 556 | return status; | ||
| 557 | } | ||
| 558 | |||
| 559 | /** | ||
| 560 | * @brief Writes/upadtes variable data in EEPROM. | ||
| 561 | The value is written only if differs from the one already saved at the same address. | ||
| 562 | * @param VirtAddress: Variable virtual address | ||
| 563 | * @param Data: 16 bit data to be written | ||
| 564 | * @retval Success or error status: | ||
| 565 | * - EEPROM_SAME_VALUE: If new Data matches existing EEPROM Data | ||
| 566 | * - FLASH_COMPLETE: on success | ||
| 567 | * - EEPROM_BAD_ADDRESS: if address = 0xFFFF | ||
| 568 | * - EEPROM_PAGE_FULL: if valid page is full | ||
| 569 | * - EEPROM_NO_VALID_PAGE: if no valid page was found | ||
| 570 | * - EEPROM_OUT_SIZE: if no empty EEPROM variables | ||
| 571 | * - Flash error code: on write Flash error | ||
| 572 | */ | ||
| 573 | uint16_t EEPROM_update(uint16_t Address, uint16_t Data) | ||
| 574 | { | ||
| 575 | uint16_t temp; | ||
| 576 | EEPROM_read(Address, &temp); | ||
| 577 | if (temp == Data) | ||
| 578 | return EEPROM_SAME_VALUE; | ||
| 579 | else | ||
| 580 | return EEPROM_write(Address, Data); | ||
| 581 | } | 113 | } |
| 114 | /***************************************************************************** | ||
| 115 | * Read once data byte from a specified address. | ||
| 116 | *******************************************************************************/ | ||
| 117 | uint8_t EEPROM_ReadDataByte (uint16_t Address) { | ||
| 582 | 118 | ||
| 583 | /** | 119 | uint8_t DataByte = 0xFF; |
| 584 | * @brief Return number of variable | ||
| 585 | * @retval Number of variables | ||
| 586 | */ | ||
| 587 | uint16_t EEPROM_count(uint16_t *Count) | ||
| 588 | { | ||
| 589 | if (Status == EEPROM_NOT_INIT) | ||
| 590 | if (EEPROM_init() != EEPROM_OK) | ||
| 591 | return Status; | ||
| 592 | |||
| 593 | // Get valid Page for write operation | ||
| 594 | uint32_t pageBase = EE_FindValidPage(); | ||
| 595 | if (pageBase == 0) | ||
| 596 | return EEPROM_NO_VALID_PAGE; // No valid page, return max. numbers | ||
| 597 | 120 | ||
| 598 | *Count = EE_GetVariablesCount(pageBase, 0xFFFF); | 121 | // Get Byte from specified address |
| 599 | return EEPROM_OK; | 122 | DataByte = (*(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))); |
| 600 | } | ||
| 601 | 123 | ||
| 602 | uint16_t EEPROM_maxcount(void) | 124 | return DataByte; |
| 603 | { | ||
| 604 | return ((PageSize / 4)-1); | ||
| 605 | } | 125 | } |
| 606 | 126 | ||
| 607 | 127 | /***************************************************************************** | |
| 128 | * Wrap library in AVR style functions. | ||
| 129 | *******************************************************************************/ | ||
| 608 | uint8_t eeprom_read_byte (const uint8_t *Address) | 130 | uint8_t eeprom_read_byte (const uint8_t *Address) |
| 609 | { | 131 | { |
| 610 | const uint16_t p = (const uint32_t) Address; | 132 | const uint16_t p = (const uint32_t) Address; |
| 611 | uint16_t temp; | 133 | return EEPROM_ReadDataByte(p); |
| 612 | EEPROM_read(p, &temp); | ||
| 613 | return (uint8_t) temp; | ||
| 614 | } | 134 | } |
| 615 | 135 | ||
| 616 | void eeprom_write_byte (uint8_t *Address, uint8_t Value) | 136 | void eeprom_write_byte (uint8_t *Address, uint8_t Value) |
| 617 | { | 137 | { |
| 618 | uint16_t p = (uint32_t) Address; | 138 | uint16_t p = (uint32_t) Address; |
| 619 | EEPROM_write(p, (uint16_t) Value); | 139 | EEPROM_WriteDataByte(p, Value); |
| 620 | } | 140 | } |
| 621 | 141 | ||
| 622 | void eeprom_update_byte (uint8_t *Address, uint8_t Value) | 142 | void eeprom_update_byte (uint8_t *Address, uint8_t Value) |
| 623 | { | 143 | { |
| 624 | uint16_t p = (uint32_t) Address; | 144 | uint16_t p = (uint32_t) Address; |
| 625 | EEPROM_update(p, (uint16_t) Value); | 145 | EEPROM_WriteDataByte(p, Value); |
| 626 | } | 146 | } |
| 627 | 147 | ||
| 628 | uint16_t eeprom_read_word (const uint16_t *Address) | 148 | uint16_t eeprom_read_word (const uint16_t *Address) |
| 629 | { | 149 | { |
| 630 | const uint16_t p = (const uint32_t) Address; | 150 | const uint16_t p = (const uint32_t) Address; |
| 631 | uint16_t temp; | 151 | return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8); |
| 632 | EEPROM_read(p, &temp); | ||
| 633 | return temp; | ||
| 634 | } | 152 | } |
| 635 | 153 | ||
| 636 | void eeprom_write_word (uint16_t *Address, uint16_t Value) | 154 | void eeprom_write_word (uint16_t *Address, uint16_t Value) |
| 637 | { | 155 | { |
| 638 | uint16_t p = (uint32_t) Address; | 156 | uint16_t p = (uint32_t) Address; |
| 639 | EEPROM_write(p, Value); | 157 | EEPROM_WriteDataByte(p, (uint8_t) Value); |
| 158 | EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8)); | ||
| 640 | } | 159 | } |
| 641 | 160 | ||
| 642 | void eeprom_update_word (uint16_t *Address, uint16_t Value) | 161 | void eeprom_update_word (uint16_t *Address, uint16_t Value) |
| 643 | { | 162 | { |
| 644 | uint16_t p = (uint32_t) Address; | 163 | uint16_t p = (uint32_t) Address; |
| 645 | EEPROM_update(p, Value); | 164 | EEPROM_WriteDataByte(p, (uint8_t) Value); |
| 165 | EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8)); | ||
| 646 | } | 166 | } |
| 647 | 167 | ||
| 648 | uint32_t eeprom_read_dword (const uint32_t *Address) | 168 | uint32_t eeprom_read_dword (const uint32_t *Address) |
| 649 | { | 169 | { |
| 650 | const uint16_t p = (const uint32_t) Address; | 170 | const uint16_t p = (const uint32_t) Address; |
| 651 | uint16_t temp1, temp2; | 171 | return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8) |
| 652 | EEPROM_read(p, &temp1); | 172 | | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24); |
| 653 | EEPROM_read(p + 1, &temp2); | ||
| 654 | return temp1 | (temp2 << 16); | ||
| 655 | } | 173 | } |
| 656 | 174 | ||
| 657 | void eeprom_write_dword (uint32_t *Address, uint32_t Value) | 175 | void eeprom_write_dword (uint32_t *Address, uint32_t Value) |
| 658 | { | 176 | { |
| 659 | uint16_t temp = (uint16_t) Value; | 177 | uint16_t p = (const uint32_t) Address; |
| 660 | uint16_t p = (uint32_t) Address; | 178 | EEPROM_WriteDataByte(p, (uint8_t) Value); |
| 661 | EEPROM_write(p, temp); | 179 | EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8)); |
| 662 | temp = (uint16_t) (Value >> 16); | 180 | EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16)); |
| 663 | EEPROM_write(p + 1, temp); | 181 | EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24)); |
| 664 | } | 182 | } |
| 665 | 183 | ||
| 666 | void eeprom_update_dword (uint32_t *Address, uint32_t Value) | 184 | void eeprom_update_dword (uint32_t *Address, uint32_t Value) |
| 667 | { | 185 | { |
| 668 | uint16_t temp = (uint16_t) Value; | 186 | uint16_t p = (const uint32_t) Address; |
| 669 | uint16_t p = (uint32_t) Address; | 187 | EEPROM_WriteDataByte(p, (uint8_t) Value); |
| 670 | EEPROM_update(p, temp); | 188 | EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8)); |
| 671 | temp = (uint16_t) (Value >> 16); | 189 | EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16)); |
| 672 | EEPROM_update(p + 1, temp); | 190 | EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24)); |
| 191 | } | ||
| 192 | |||
| 193 | void eeprom_read_block(void *buf, const void *addr, uint32_t len) { | ||
| 194 | const uint8_t *p = (const uint8_t *)addr; | ||
| 195 | uint8_t *dest = (uint8_t *)buf; | ||
| 196 | while (len--) { | ||
| 197 | *dest++ = eeprom_read_byte(p++); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | void eeprom_write_block(const void *buf, void *addr, uint32_t len) { | ||
| 202 | uint8_t *p = (uint8_t *)addr; | ||
| 203 | const uint8_t *src = (const uint8_t *)buf; | ||
| 204 | while (len--) { | ||
| 205 | eeprom_write_byte(p++, *src++); | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | void eeprom_update_block(const void *buf, void *addr, uint32_t len) { | ||
| 210 | uint8_t *p = (uint8_t *)addr; | ||
| 211 | const uint8_t *src = (const uint8_t *)buf; | ||
| 212 | while (len--) { | ||
| 213 | eeprom_write_byte(p++, *src++); | ||
| 214 | } | ||
| 673 | } | 215 | } |
diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/tmk_core/common/chibios/eeprom_stm32.h index 09229530c..892e417b7 100755 --- a/tmk_core/common/chibios/eeprom_stm32.h +++ b/tmk_core/common/chibios/eeprom_stm32.h | |||
| @@ -10,15 +10,17 @@ | |||
| 10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 11 | * DEALINGS IN THE SOFTWARE. | 11 | * DEALINGS IN THE SOFTWARE. |
| 12 | * | 12 | * |
| 13 | * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and | 13 | * This files are free to use from http://engsta.com/stm32-flash-memory-eeprom-emulator/ by |
| 14 | * https://github.com/leaflabs/libmaple | 14 | * Artur F. |
| 15 | * | 15 | * |
| 16 | * Modifications for QMK and STM32F303 by Yiancar | 16 | * Modifications for QMK and STM32F303 by Yiancar |
| 17 | * | ||
| 18 | * This library assumes 8-bit data locations. To add a new MCU, please provide the flash | ||
| 19 | * page size and the total flash size in Kb. The number of available pages must be a multiple | ||
| 20 | * of 2. Only half of the pages account for the total EEPROM size. | ||
| 21 | * This library also assumes that the pages are not used by the firmware. | ||
| 17 | */ | 22 | */ |
| 18 | 23 | ||
| 19 | // This file must be modified if the MCU is not defined below. | ||
| 20 | // This library also assumes that the pages are not used by the firmware. | ||
| 21 | |||
| 22 | #ifndef __EEPROM_H | 24 | #ifndef __EEPROM_H |
| 23 | #define __EEPROM_H | 25 | #define __EEPROM_H |
| 24 | 26 | ||
| @@ -38,9 +40,11 @@ | |||
| 38 | 40 | ||
| 39 | #ifndef EEPROM_PAGE_SIZE | 41 | #ifndef EEPROM_PAGE_SIZE |
| 40 | #if defined (MCU_STM32F103RB) | 42 | #if defined (MCU_STM32F103RB) |
| 41 | #define EEPROM_PAGE_SIZE (uint16_t)0x400 /* Page size = 1KByte */ | 43 | #define FEE_PAGE_SIZE (uint16_t)0x400 // Page size = 1KByte |
| 44 | #define FEE_DENSITY_PAGES 2 // How many pages are used | ||
| 42 | #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC) | 45 | #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC) |
| 43 | #define EEPROM_PAGE_SIZE (uint16_t)0x800 /* Page size = 2KByte */ | 46 | #define FEE_PAGE_SIZE (uint16_t)0x800 // Page size = 2KByte |
| 47 | #define FEE_DENSITY_PAGES 4 // How many pages are used | ||
| 44 | #else | 48 | #else |
| 45 | #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." | 49 | #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." |
| 46 | #endif | 50 | #endif |
| @@ -48,48 +52,30 @@ | |||
| 48 | 52 | ||
| 49 | #ifndef EEPROM_START_ADDRESS | 53 | #ifndef EEPROM_START_ADDRESS |
| 50 | #if defined (MCU_STM32F103RB) | 54 | #if defined (MCU_STM32F103RB) |
| 51 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 128 * 1024 - 2 * EEPROM_PAGE_SIZE)) | 55 | #define FEE_MCU_FLASH_SIZE 128 // Size in Kb |
| 52 | #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) | 56 | #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) |
| 53 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 512 * 1024 - 2 * EEPROM_PAGE_SIZE)) | 57 | #define FEE_MCU_FLASH_SIZE 512 // Size in Kb |
| 54 | #elif defined (MCU_STM32F103RD) | 58 | #elif defined (MCU_STM32F103RD) |
| 55 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 384 * 1024 - 2 * EEPROM_PAGE_SIZE)) | 59 | #define FEE_MCU_FLASH_SIZE 384 // Size in Kb |
| 56 | #elif defined (MCU_STM32F303CC) | 60 | #elif defined (MCU_STM32F303CC) |
| 57 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 256 * 1024 - 2 * EEPROM_PAGE_SIZE)) | 61 | #define FEE_MCU_FLASH_SIZE 256 // Size in Kb |
| 58 | #else | 62 | #else |
| 59 | #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." | 63 | #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." |
| 60 | #endif | 64 | #endif |
| 61 | #endif | 65 | #endif |
| 62 | 66 | ||
| 63 | /* Pages 0 and 1 base and end addresses */ | 67 | // DONT CHANGE |
| 64 | #define EEPROM_PAGE0_BASE ((uint32_t)(EEPROM_START_ADDRESS + 0x000)) | 68 | // Choose location for the first EEPROM Page address on the top of flash |
| 65 | #define EEPROM_PAGE1_BASE ((uint32_t)(EEPROM_START_ADDRESS + EEPROM_PAGE_SIZE)) | 69 | #define FEE_PAGE_BASE_ADDRESS ((uint32_t)(0x8000000 + FEE_MCU_FLASH_SIZE * 1024 - FEE_DENSITY_PAGES * FEE_PAGE_SIZE)) |
| 66 | 70 | #define FEE_DENSITY_BYTES ((FEE_PAGE_SIZE / 2) * FEE_DENSITY_PAGES - 1) | |
| 67 | /* Page status definitions */ | 71 | #define FEE_LAST_PAGE_ADDRESS (FEE_PAGE_BASE_ADDRESS + (FEE_PAGE_SIZE * FEE_DENSITY_PAGES)) |
| 68 | #define EEPROM_ERASED ((uint16_t)0xFFFF) /* PAGE is empty */ | 72 | #define FEE_EMPTY_WORD ((uint16_t)0xFFFF) |
| 69 | #define EEPROM_RECEIVE_DATA ((uint16_t)0xEEEE) /* PAGE is marked to receive data */ | 73 | #define FEE_ADDR_OFFSET(Address)(Address * 2) // 1Byte per Word will be saved to preserve Flash |
| 70 | #define EEPROM_VALID_PAGE ((uint16_t)0x0000) /* PAGE containing valid data */ | ||
| 71 | |||
| 72 | /* Page full define */ | ||
| 73 | enum uint16_t | ||
| 74 | { | ||
| 75 | EEPROM_OK = ((uint16_t)0x0000), | ||
| 76 | EEPROM_OUT_SIZE = ((uint16_t)0x0081), | ||
| 77 | EEPROM_BAD_ADDRESS = ((uint16_t)0x0082), | ||
| 78 | EEPROM_BAD_FLASH = ((uint16_t)0x0083), | ||
| 79 | EEPROM_NOT_INIT = ((uint16_t)0x0084), | ||
| 80 | EEPROM_SAME_VALUE = ((uint16_t)0x0085), | ||
| 81 | EEPROM_NO_VALID_PAGE = ((uint16_t)0x00AB) | ||
| 82 | }; | ||
| 83 | |||
| 84 | #define EEPROM_DEFAULT_DATA 0xFFFF | ||
| 85 | 74 | ||
| 86 | uint16_t EEPROM_init(void); | 75 | // Use this function to initialize the functionality |
| 87 | uint16_t EEPROM_format(void); | 76 | uint16_t EEPROM_Init(void); |
| 88 | uint16_t EEPROM_erases(uint16_t *); | 77 | void EEPROM_Erase (void); |
| 89 | uint16_t EEPROM_read (uint16_t address, uint16_t *data); | 78 | uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte); |
| 90 | uint16_t EEPROM_write(uint16_t address, uint16_t data); | 79 | uint8_t EEPROM_ReadDataByte (uint16_t Address); |
| 91 | uint16_t EEPROM_update(uint16_t address, uint16_t data); | ||
| 92 | uint16_t EEPROM_count(uint16_t *); | ||
| 93 | uint16_t EEPROM_maxcount(void); | ||
| 94 | 80 | ||
| 95 | #endif /* __EEPROM_H */ | 81 | #endif /* __EEPROM_H */ |
diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c index 273593484..164654a15 100755 --- a/tmk_core/common/chibios/flash_stm32.c +++ b/tmk_core/common/chibios/flash_stm32.c | |||
| @@ -186,3 +186,18 @@ void FLASH_Lock(void) | |||
| 186 | /* Set the Lock Bit to lock the FPEC and the FCR */ | 186 | /* Set the Lock Bit to lock the FPEC and the FCR */ |
| 187 | FLASH->CR |= FLASH_CR_LOCK; | 187 | FLASH->CR |= FLASH_CR_LOCK; |
| 188 | } | 188 | } |
| 189 | |||
| 190 | /** | ||
| 191 | * @brief Clears the FLASH's pending flags. | ||
| 192 | * @param FLASH_FLAG: specifies the FLASH flags to clear. | ||
| 193 | * This parameter can be any combination of the following values: | ||
| 194 | * @arg FLASH_FLAG_PGERR: FLASH Programming error flag flag | ||
| 195 | * @arg FLASH_FLAG_WRPERR: FLASH Write protected error flag | ||
| 196 | * @arg FLASH_FLAG_EOP: FLASH End of Programming flag | ||
| 197 | * @retval None | ||
| 198 | */ | ||
| 199 | void FLASH_ClearFlag(uint32_t FLASH_FLAG) | ||
| 200 | { | ||
| 201 | /* Clear the flags */ | ||
| 202 | FLASH->SR = FLASH_FLAG; | ||
| 203 | } | ||
diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h index cc065cbca..3c99cc566 100755 --- a/tmk_core/common/chibios/flash_stm32.h +++ b/tmk_core/common/chibios/flash_stm32.h | |||
| @@ -45,6 +45,7 @@ FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); | |||
| 45 | 45 | ||
| 46 | void FLASH_Unlock(void); | 46 | void FLASH_Unlock(void); |
| 47 | void FLASH_Lock(void); | 47 | void FLASH_Lock(void); |
| 48 | void FLASH_ClearFlag(uint32_t FLASH_FLAG); | ||
| 48 | 49 | ||
| 49 | #ifdef __cplusplus | 50 | #ifdef __cplusplus |
| 50 | } | 51 | } |
diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index d8bab7d2e..59b2bffbc 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c | |||
| @@ -33,7 +33,7 @@ void eeconfig_init_kb(void) { | |||
| 33 | */ | 33 | */ |
| 34 | void eeconfig_init_quantum(void) { | 34 | void eeconfig_init_quantum(void) { |
| 35 | #ifdef STM32_EEPROM_ENABLE | 35 | #ifdef STM32_EEPROM_ENABLE |
| 36 | EEPROM_format(); | 36 | EEPROM_Erase(); |
| 37 | #endif | 37 | #endif |
| 38 | eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); | 38 | eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); |
| 39 | eeprom_update_byte(EECONFIG_DEBUG, 0); | 39 | eeprom_update_byte(EECONFIG_DEBUG, 0); |
| @@ -74,7 +74,7 @@ void eeconfig_enable(void) | |||
| 74 | void eeconfig_disable(void) | 74 | void eeconfig_disable(void) |
| 75 | { | 75 | { |
| 76 | #ifdef STM32_EEPROM_ENABLE | 76 | #ifdef STM32_EEPROM_ENABLE |
| 77 | EEPROM_format(); | 77 | EEPROM_Erase(); |
| 78 | #endif | 78 | #endif |
| 79 | eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); | 79 | eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER_OFF); |
| 80 | } | 80 | } |
diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 8d4e1d4d0..eedd67602 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h | |||
| @@ -25,8 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 25 | #define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED | 25 | #define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED |
| 26 | #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF | 26 | #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF |
| 27 | 27 | ||
| 28 | /* eeprom parameteter address */ | 28 | /* EEPROM parameter address */ |
| 29 | #if !defined(STM32_EEPROM_ENABLE) | ||
| 30 | #define EECONFIG_MAGIC (uint16_t *)0 | 29 | #define EECONFIG_MAGIC (uint16_t *)0 |
| 31 | #define EECONFIG_DEBUG (uint8_t *)2 | 30 | #define EECONFIG_DEBUG (uint8_t *)2 |
| 32 | #define EECONFIG_DEFAULT_LAYER (uint8_t *)3 | 31 | #define EECONFIG_DEFAULT_LAYER (uint8_t *)3 |
| @@ -42,24 +41,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 42 | #define EECONFIG_KEYBOARD (uint32_t *)15 | 41 | #define EECONFIG_KEYBOARD (uint32_t *)15 |
| 43 | #define EECONFIG_USER (uint32_t *)19 | 42 | #define EECONFIG_USER (uint32_t *)19 |
| 44 | 43 | ||
| 45 | #else | ||
| 46 | /* STM32F3 uses 16byte block. Reconfigure memory map */ | ||
| 47 | #define EECONFIG_MAGIC (uint16_t *)0 | ||
| 48 | #define EECONFIG_DEBUG (uint8_t *)1 | ||
| 49 | #define EECONFIG_DEFAULT_LAYER (uint8_t *)2 | ||
| 50 | #define EECONFIG_KEYMAP (uint8_t *)3 | ||
| 51 | #define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)4 | ||
| 52 | #define EECONFIG_BACKLIGHT (uint8_t *)5 | ||
| 53 | #define EECONFIG_AUDIO (uint8_t *)6 | ||
| 54 | #define EECONFIG_RGBLIGHT (uint32_t *)7 | ||
| 55 | #define EECONFIG_UNICODEMODE (uint8_t *)9 | ||
| 56 | #define EECONFIG_STENOMODE (uint8_t *)10 | ||
| 57 | // EEHANDS for two handed boards | ||
| 58 | #define EECONFIG_HANDEDNESS (uint8_t *)11 | ||
| 59 | #define EECONFIG_KEYBOARD (uint32_t *)12 | ||
| 60 | #define EECONFIG_USER (uint32_t *)14 | ||
| 61 | #endif | ||
| 62 | |||
| 63 | /* debug bit */ | 44 | /* debug bit */ |
| 64 | #define EECONFIG_DEBUG_ENABLE (1<<0) | 45 | #define EECONFIG_DEBUG_ENABLE (1<<0) |
| 65 | #define EECONFIG_DEBUG_MATRIX (1<<1) | 46 | #define EECONFIG_DEBUG_MATRIX (1<<1) |
diff --git a/tmk_core/common/eeprom.h b/tmk_core/common/eeprom.h index 3696d0df3..5ae0f6eeb 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); | |||
| 20 | void eeprom_update_block (const void *__src, void *__dst, uint32_t __n); | 20 | void eeprom_update_block (const void *__src, void *__dst, uint32_t __n); |
| 21 | #endif | 21 | #endif |
| 22 | 22 | ||
| 23 | |||
| 24 | #endif /* TMK_CORE_COMMON_EEPROM_H_ */ | 23 | #endif /* TMK_CORE_COMMON_EEPROM_H_ */ |
diff --git a/tmk_core/common/host.h b/tmk_core/common/host.h index aeabba710..3d172eed6 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 | |||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #ifndef HOST_H | 18 | #pragma once |
| 19 | #define HOST_H | ||
| 20 | 19 | ||
| 21 | #include <stdint.h> | 20 | #include <stdint.h> |
| 22 | #include <stdbool.h> | 21 | #include <stdbool.h> |
| 23 | #include "report.h" | 22 | #include "report.h" |
| 24 | #include "host_driver.h" | 23 | #include "host_driver.h" |
| 25 | 24 | ||
| 25 | #define IS_LED_ON(leds, led_name) ( (leds) & (1 << (led_name))) | ||
| 26 | #define IS_LED_OFF(leds, led_name) (~(leds) & (1 << (led_name))) | ||
| 27 | |||
| 28 | #define IS_HOST_LED_ON(led_name) IS_LED_ON(host_keyboard_leds(), led_name) | ||
| 29 | #define IS_HOST_LED_OFF(led_name) IS_LED_OFF(host_keyboard_leds(), led_name) | ||
| 26 | 30 | ||
| 27 | #ifdef __cplusplus | 31 | #ifdef __cplusplus |
| 28 | extern "C" { | 32 | extern "C" { |
| @@ -31,7 +35,6 @@ extern "C" { | |||
| 31 | extern uint8_t keyboard_idle; | 35 | extern uint8_t keyboard_idle; |
| 32 | extern uint8_t keyboard_protocol; | 36 | extern uint8_t keyboard_protocol; |
| 33 | 37 | ||
| 34 | |||
| 35 | /* host driver */ | 38 | /* host driver */ |
| 36 | void host_set_driver(host_driver_t *driver); | 39 | void host_set_driver(host_driver_t *driver); |
| 37 | host_driver_t *host_get_driver(void); | 40 | host_driver_t *host_get_driver(void); |
| @@ -49,5 +52,3 @@ uint16_t host_last_consumer_report(void); | |||
| 49 | #ifdef __cplusplus | 52 | #ifdef __cplusplus |
| 50 | } | 53 | } |
| 51 | #endif | 54 | #endif |
| 52 | |||
| 53 | #endif | ||
diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index 71e594a89..ea2f336e9 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h | |||
| @@ -67,6 +67,8 @@ void keyboard_init(void); | |||
| 67 | void keyboard_task(void); | 67 | void keyboard_task(void); |
| 68 | /* it runs when host LED status is updated */ | 68 | /* it runs when host LED status is updated */ |
| 69 | void keyboard_set_leds(uint8_t leds); | 69 | void keyboard_set_leds(uint8_t leds); |
| 70 | /* it runs whenever code has to behave differently on a slave */ | ||
| 71 | bool is_keyboard_master(void); | ||
| 70 | 72 | ||
| 71 | #ifdef __cplusplus | 73 | #ifdef __cplusplus |
| 72 | } | 74 | } |
diff --git a/tmk_core/common/keycode.h b/tmk_core/common/keycode.h index ac3edbd21..d5904276e 100644 --- a/tmk_core/common/keycode.h +++ b/tmk_core/common/keycode.h | |||
| @@ -46,6 +46,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 46 | #define MOD_BIT(code) (1 << MOD_INDEX(code)) | 46 | #define MOD_BIT(code) (1 << MOD_INDEX(code)) |
| 47 | #define MOD_INDEX(code) ((code) & 0x07) | 47 | #define MOD_INDEX(code) ((code) & 0x07) |
| 48 | 48 | ||
| 49 | #define MOD_MASK_CTRL (MOD_BIT(KC_LCTRL) | MOD_BIT(KC_RCTRL)) | ||
| 50 | #define MOD_MASK_SHIFT (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) | ||
| 51 | #define MOD_MASK_ALT (MOD_BIT(KC_LALT) | MOD_BIT(KC_RALT)) | ||
| 52 | #define MOD_MASK_GUI (MOD_BIT(KC_LGUI) | MOD_BIT(KC_RGUI)) | ||
| 53 | #define MOD_MASK_CS (MOD_MASK_CTRL | MOD_MASK_SHIFT) | ||
| 54 | #define MOD_MASK_CA (MOD_MASK_CTRL | MOD_MASK_ALT) | ||
| 55 | #define MOD_MASK_CG (MOD_MASK_CTRL | MOD_MASK_GUI) | ||
| 56 | #define MOD_MASK_SA (MOD_MASK_SHIFT | MOD_MASK_ALT) | ||
| 57 | #define MOD_MASK_SG (MOD_MASK_SHIFT | MOD_MASK_GUI) | ||
| 58 | #define MOD_MASK_AG (MOD_MASK_ALT | MOD_MASK_GUI) | ||
| 59 | #define MOD_MASK_CSA (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT) | ||
| 60 | #define MOD_MASK_CSG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_GUI) | ||
| 61 | #define MOD_MASK_CAG (MOD_MASK_CTRL | MOD_MASK_ALT | MOD_MASK_GUI) | ||
| 62 | #define MOD_MASK_SAG (MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) | ||
| 63 | #define MOD_MASK_CSAG (MOD_MASK_CTRL | MOD_MASK_SHIFT | MOD_MASK_ALT | MOD_MASK_GUI) | ||
| 64 | |||
| 49 | #define FN_BIT(code) (1 << FN_INDEX(code)) | 65 | #define FN_BIT(code) (1 << FN_INDEX(code)) |
| 50 | #define FN_INDEX(code) ((code) - KC_FN0) | 66 | #define FN_INDEX(code) ((code) - KC_FN0) |
| 51 | #define FN_MIN KC_FN0 | 67 | #define FN_MIN KC_FN0 |
| @@ -174,6 +190,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 174 | #define KC_BRIU KC_BRIGHTNESS_UP | 190 | #define KC_BRIU KC_BRIGHTNESS_UP |
| 175 | #define KC_BRID KC_BRIGHTNESS_DOWN | 191 | #define KC_BRID KC_BRIGHTNESS_DOWN |
| 176 | 192 | ||
| 193 | /* System Specific */ | ||
| 194 | #define KC_BRMU KC_PAUSE | ||
| 195 | #define KC_BRMD KC_SCROLLLOCK | ||
| 196 | |||
| 177 | /* Mouse Keys */ | 197 | /* Mouse Keys */ |
| 178 | #define KC_MS_U KC_MS_UP | 198 | #define KC_MS_U KC_MS_UP |
| 179 | #define KC_MS_D KC_MS_DOWN | 199 | #define KC_MS_D KC_MS_DOWN |
diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h index dcc9efb3c..de9313839 100644 --- a/tmk_core/common/progmem.h +++ b/tmk_core/common/progmem.h | |||
| @@ -5,9 +5,9 @@ | |||
| 5 | # include <avr/pgmspace.h> | 5 | # include <avr/pgmspace.h> |
| 6 | #else | 6 | #else |
| 7 | # define PROGMEM | 7 | # define PROGMEM |
| 8 | # define pgm_read_byte(p) *((unsigned char*)p) | 8 | # define pgm_read_byte(p) *((unsigned char*)(p)) |
| 9 | # define pgm_read_word(p) *((uint16_t*)p) | 9 | # define pgm_read_word(p) *((uint16_t*)(p)) |
| 10 | # define pgm_read_dword(p) *((uint32_t*)p) | 10 | # define pgm_read_dword(p) *((uint32_t*)(p)) |
| 11 | #endif | 11 | #endif |
| 12 | 12 | ||
| 13 | #endif | 13 | #endif |
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h index eb9afb727..e7c31bd37 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h | |||
| @@ -48,8 +48,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 48 | #define TRANSPORT_STOP 0x00B7 | 48 | #define TRANSPORT_STOP 0x00B7 |
| 49 | #define TRANSPORT_STOP_EJECT 0x00CC | 49 | #define TRANSPORT_STOP_EJECT 0x00CC |
| 50 | #define TRANSPORT_PLAY_PAUSE 0x00CD | 50 | #define TRANSPORT_PLAY_PAUSE 0x00CD |
| 51 | #define BRIGHTNESSUP 0x006F | 51 | #define BRIGHTNESS_UP 0x006F |
| 52 | #define BRIGHTNESSDOWN 0x0070 | 52 | #define BRIGHTNESS_DOWN 0x0070 |
| 53 | /* application launch */ | 53 | /* application launch */ |
| 54 | #define AL_CC_CONFIG 0x0183 | 54 | #define AL_CC_CONFIG 0x0183 |
| 55 | #define AL_EMAIL 0x018A | 55 | #define AL_EMAIL 0x018A |
| @@ -192,8 +192,8 @@ typedef struct { | |||
| 192 | (key == KC_WWW_FORWARD ? AC_FORWARD : \ | 192 | (key == KC_WWW_FORWARD ? AC_FORWARD : \ |
| 193 | (key == KC_WWW_STOP ? AC_STOP : \ | 193 | (key == KC_WWW_STOP ? AC_STOP : \ |
| 194 | (key == KC_WWW_REFRESH ? AC_REFRESH : \ | 194 | (key == KC_WWW_REFRESH ? AC_REFRESH : \ |
| 195 | (key == KC_BRIGHTNESS_UP ? BRIGHTNESSUP : \ | 195 | (key == KC_BRIGHTNESS_UP ? BRIGHTNESS_UP : \ |
| 196 | (key == KC_BRIGHTNESS_DOWN ? BRIGHTNESSDOWN : \ | 196 | (key == KC_BRIGHTNESS_DOWN ? BRIGHTNESS_DOWN : \ |
| 197 | (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0))))))))))))))))))))))) | 197 | (key == KC_WWW_FAVORITES ? AC_BOOKMARKS : 0))))))))))))))))))))))) |
| 198 | 198 | ||
| 199 | uint8_t has_anykey(report_keyboard_t* keyboard_report); | 199 | uint8_t has_anykey(report_keyboard_t* keyboard_report); |
diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h index a7cded942..a77840bce 100644 --- a/tmk_core/common/wait.h +++ b/tmk_core/common/wait.h | |||
| @@ -15,6 +15,10 @@ extern "C" { | |||
| 15 | # include "ch.h" | 15 | # include "ch.h" |
| 16 | # define wait_ms(ms) chThdSleepMilliseconds(ms) | 16 | # define wait_ms(ms) chThdSleepMilliseconds(ms) |
| 17 | # define wait_us(us) chThdSleepMicroseconds(us) | 17 | # define wait_us(us) chThdSleepMicroseconds(us) |
| 18 | #elif defined PROTOCOL_ARM_ATSAM | ||
| 19 | # include "clks.h" | ||
| 20 | # define wait_ms(ms) CLK_delay_ms(ms) | ||
| 21 | # define wait_us(us) CLK_delay_us(us) | ||
| 18 | #elif defined(__arm__) | 22 | #elif defined(__arm__) |
| 19 | # include "wait_api.h" | 23 | # include "wait_api.h" |
| 20 | #else // Unit tests | 24 | #else // Unit tests |
diff --git a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h index 2ba099174..928af8c7e 100644 --- a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h +++ b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h | |||
| @@ -21,8 +21,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 21 | #include "samd51j18a.h" | 21 | #include "samd51j18a.h" |
| 22 | #include "md_bootloader.h" | 22 | #include "md_bootloader.h" |
| 23 | 23 | ||
| 24 | #include "timer.h" | ||
| 24 | #include "d51_util.h" | 25 | #include "d51_util.h" |
| 25 | #include "clks.h" | 26 | #include "clks.h" |
| 27 | #include "wait.h" | ||
| 26 | #include "adc.h" | 28 | #include "adc.h" |
| 27 | #include "i2c_master.h" | 29 | #include "i2c_master.h" |
| 28 | #include "spi.h" | 30 | #include "spi.h" |
diff --git a/tmk_core/protocol/arm_atsam/clks.c b/tmk_core/protocol/arm_atsam/clks.c index 8768d0a99..1ff318e59 100644 --- a/tmk_core/protocol/arm_atsam/clks.c +++ b/tmk_core/protocol/arm_atsam/clks.c | |||
| @@ -21,8 +21,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 21 | 21 | ||
| 22 | volatile clk_t system_clks; | 22 | volatile clk_t system_clks; |
| 23 | volatile uint64_t ms_clk; | 23 | volatile uint64_t ms_clk; |
| 24 | 24 | uint32_t usec_delay_mult; | |
| 25 | volatile uint8_t us_delay_done; | 25 | #define USEC_DELAY_LOOP_CYCLES 3 //Sum of instruction cycles in us delay loop |
| 26 | 26 | ||
| 27 | const uint32_t sercom_apbbase[] = {(uint32_t)SERCOM0,(uint32_t)SERCOM1,(uint32_t)SERCOM2,(uint32_t)SERCOM3,(uint32_t)SERCOM4,(uint32_t)SERCOM5}; | 27 | const uint32_t sercom_apbbase[] = {(uint32_t)SERCOM0,(uint32_t)SERCOM1,(uint32_t)SERCOM2,(uint32_t)SERCOM3,(uint32_t)SERCOM4,(uint32_t)SERCOM5}; |
| 28 | const uint8_t sercom_pchan[] = {7, 8, 23, 24, 34, 35}; | 28 | const uint8_t sercom_pchan[] = {7, 8, 23, 24, 34, 35}; |
| @@ -73,6 +73,9 @@ void CLK_oscctrl_init(void) | |||
| 73 | 73 | ||
| 74 | system_clks.freq_gclk[0] = system_clks.freq_dpll[0]; | 74 | system_clks.freq_gclk[0] = system_clks.freq_dpll[0]; |
| 75 | 75 | ||
| 76 | usec_delay_mult = system_clks.freq_gclk[0] / (USEC_DELAY_LOOP_CYCLES * 1000000); | ||
| 77 | if (usec_delay_mult < 1) usec_delay_mult = 1; //Never allow a multiplier of zero | ||
| 78 | |||
| 76 | DBGC(DC_CLK_OSC_INIT_COMPLETE); | 79 | DBGC(DC_CLK_OSC_INIT_COMPLETE); |
| 77 | } | 80 | } |
| 78 | 81 | ||
| @@ -158,23 +161,11 @@ void TC4_Handler() | |||
| 158 | } | 161 | } |
| 159 | } | 162 | } |
| 160 | 163 | ||
| 161 | void TC5_Handler() | ||
| 162 | { | ||
| 163 | if (TC5->COUNT16.INTFLAG.bit.MC0) | ||
| 164 | { | ||
| 165 | TC5->COUNT16.INTFLAG.reg = TC_INTENCLR_MC0; | ||
| 166 | us_delay_done = 1; | ||
| 167 | TC5->COUNT16.CTRLA.bit.ENABLE = 0; | ||
| 168 | while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {} | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | uint32_t CLK_enable_timebase(void) | 164 | uint32_t CLK_enable_timebase(void) |
| 173 | { | 165 | { |
| 174 | Gclk *pgclk = GCLK; | 166 | Gclk *pgclk = GCLK; |
| 175 | Mclk *pmclk = MCLK; | 167 | Mclk *pmclk = MCLK; |
| 176 | Tc *ptc4 = TC4; | 168 | Tc *ptc4 = TC4; |
| 177 | Tc *ptc5 = TC5; | ||
| 178 | Tc *ptc0 = TC0; | 169 | Tc *ptc0 = TC0; |
| 179 | Evsys *pevsys = EVSYS; | 170 | Evsys *pevsys = EVSYS; |
| 180 | 171 | ||
| @@ -189,11 +180,6 @@ uint32_t CLK_enable_timebase(void) | |||
| 189 | pgclk->PCHCTRL[TC4_GCLK_ID].bit.GEN = GEN_TC45; | 180 | pgclk->PCHCTRL[TC4_GCLK_ID].bit.GEN = GEN_TC45; |
| 190 | pgclk->PCHCTRL[TC4_GCLK_ID].bit.CHEN = 1; | 181 | pgclk->PCHCTRL[TC4_GCLK_ID].bit.CHEN = 1; |
| 191 | 182 | ||
| 192 | //unmask TC5 sourcegclk2 to TC5 | ||
| 193 | pmclk->APBCMASK.bit.TC5_ = 1; | ||
| 194 | pgclk->PCHCTRL[TC5_GCLK_ID].bit.GEN = GEN_TC45; | ||
| 195 | pgclk->PCHCTRL[TC5_GCLK_ID].bit.CHEN = 1; | ||
| 196 | |||
| 197 | //configure TC4 | 183 | //configure TC4 |
| 198 | DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN); | 184 | DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_BEGIN); |
| 199 | ptc4->COUNT16.CTRLA.bit.ENABLE = 0; | 185 | ptc4->COUNT16.CTRLA.bit.ENABLE = 0; |
| @@ -220,30 +206,6 @@ uint32_t CLK_enable_timebase(void) | |||
| 220 | 206 | ||
| 221 | DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE); | 207 | DBGC(DC_CLK_ENABLE_TIMEBASE_TC4_COMPLETE); |
| 222 | 208 | ||
| 223 | //configure TC5 | ||
| 224 | DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_BEGIN); | ||
| 225 | ptc5->COUNT16.CTRLA.bit.ENABLE = 0; | ||
| 226 | while (ptc5->COUNT16.SYNCBUSY.bit.ENABLE) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_DISABLE); } | ||
| 227 | ptc5->COUNT16.CTRLA.bit.SWRST = 1; | ||
| 228 | while (ptc5->COUNT16.SYNCBUSY.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_1); } | ||
| 229 | while (ptc5->COUNT16.CTRLA.bit.SWRST) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_SWRST_2); } | ||
| 230 | |||
| 231 | //CTRLA defaults | ||
| 232 | //CTRLB as default, counting up | ||
| 233 | ptc5->COUNT16.CTRLBCLR.reg = 5; | ||
| 234 | while (ptc5->COUNT16.SYNCBUSY.bit.CTRLB) { DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_SYNC_CLTRB); } | ||
| 235 | //ptc5->COUNT16.DBGCTRL.bit.DBGRUN = 1; | ||
| 236 | |||
| 237 | //wave mode | ||
| 238 | ptc5->COUNT16.WAVE.bit.WAVEGEN = 1; //MFRQ match frequency mode, toggle each CC match | ||
| 239 | //generate event for next stage | ||
| 240 | ptc5->COUNT16.EVCTRL.bit.MCEO0 = 1; | ||
| 241 | |||
| 242 | NVIC_EnableIRQ(TC5_IRQn); | ||
| 243 | ptc5->COUNT16.INTENSET.bit.MC0 = 1; | ||
| 244 | |||
| 245 | DBGC(DC_CLK_ENABLE_TIMEBASE_TC5_COMPLETE); | ||
| 246 | |||
| 247 | //unmask TC0,1, sourcegclk2 to TC0,1 | 209 | //unmask TC0,1, sourcegclk2 to TC0,1 |
| 248 | pmclk->APBAMASK.bit.TC0_ = 1; | 210 | pmclk->APBAMASK.bit.TC0_ = 1; |
| 249 | pgclk->PCHCTRL[TC0_GCLK_ID].bit.GEN = GEN_TC45; | 211 | pgclk->PCHCTRL[TC0_GCLK_ID].bit.GEN = GEN_TC45; |
| @@ -289,37 +251,27 @@ uint32_t CLK_enable_timebase(void) | |||
| 289 | return 0; | 251 | return 0; |
| 290 | } | 252 | } |
| 291 | 253 | ||
| 292 | uint32_t CLK_get_ms(void) | 254 | void CLK_delay_us(uint32_t usec) |
| 293 | { | 255 | { |
| 294 | return ms_clk; | 256 | asm ( |
| 295 | } | 257 | "CBZ R0, return\n\t" //If usec == 0, branch to return label |
| 296 | 258 | ); | |
| 297 | void CLK_delay_us(uint16_t usec) | 259 | asm ( |
| 298 | { | 260 | "MULS R0, %0\n\t" //Multiply R0(usec) by usec_delay_mult and store in R0 |
| 299 | us_delay_done = 0; | 261 | ".balign 16\n\t" //Ensure loop is aligned for fastest performance |
| 300 | 262 | "loop: SUBS R0, #1\n\t" //Subtract 1 from R0 and update flags (1 cycle) | |
| 301 | if (TC5->COUNT16.CTRLA.bit.ENABLE) | 263 | "BNE loop\n\t" //Branch if non-zero to loop label (2 cycles) NOTE: USEC_DELAY_LOOP_CYCLES is the sum of loop cycles |
| 302 | { | 264 | "return:\n\t" //Return label |
| 303 | TC5->COUNT16.CTRLA.bit.ENABLE = 0; | 265 | : //No output registers |
| 304 | while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {} | 266 | : "r" (usec_delay_mult) //For %0 |
| 305 | } | 267 | ); |
| 306 | 268 | //Note: BX LR generated | |
| 307 | if (usec < 10) usec = 0; | ||
| 308 | else usec -= 10; | ||
| 309 | |||
| 310 | TC5->COUNT16.CC[0].reg = usec; | ||
| 311 | while (TC5->COUNT16.SYNCBUSY.bit.CC0) {} | ||
| 312 | |||
| 313 | TC5->COUNT16.CTRLA.bit.ENABLE = 1; | ||
| 314 | while (TC5->COUNT16.SYNCBUSY.bit.ENABLE) {} | ||
| 315 | |||
| 316 | while (!us_delay_done) {} | ||
| 317 | } | 269 | } |
| 318 | 270 | ||
| 319 | void CLK_delay_ms(uint64_t msec) | 271 | void CLK_delay_ms(uint64_t msec) |
| 320 | { | 272 | { |
| 321 | msec += CLK_get_ms(); | 273 | msec += timer_read64(); |
| 322 | while (msec > CLK_get_ms()) {} | 274 | while (msec > timer_read64()) {} |
| 323 | } | 275 | } |
| 324 | 276 | ||
| 325 | void clk_enable_sercom_apbmask(int sercomn) | 277 | void clk_enable_sercom_apbmask(int sercomn) |
diff --git a/tmk_core/protocol/arm_atsam/clks.h b/tmk_core/protocol/arm_atsam/clks.h index 96819bfdd..1b01a1764 100644 --- a/tmk_core/protocol/arm_atsam/clks.h +++ b/tmk_core/protocol/arm_atsam/clks.h | |||
| @@ -77,9 +77,8 @@ void CLK_oscctrl_init(void); | |||
| 77 | void CLK_reset_time(void); | 77 | void CLK_reset_time(void); |
| 78 | uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq); | 78 | uint32_t CLK_set_gclk_freq(uint8_t gclkn, uint32_t freq); |
| 79 | uint32_t CLK_enable_timebase(void); | 79 | uint32_t CLK_enable_timebase(void); |
| 80 | uint32_t CLK_get_ms(void); | 80 | uint64_t timer_read64(void); |
| 81 | uint64_t CLK_get_us(void); | 81 | void CLK_delay_us(uint32_t usec); |
| 82 | void CLK_delay_us(uint16_t usec); | ||
| 83 | void CLK_delay_ms(uint64_t msec); | 82 | void CLK_delay_ms(uint64_t msec); |
| 84 | 83 | ||
| 85 | uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq); | 84 | uint32_t CLK_set_spi_freq(uint8_t sercomn, uint32_t freq); |
diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c index f608a79cc..d91a851f3 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.c +++ b/tmk_core/protocol/arm_atsam/i2c_master.c | |||
| @@ -265,12 +265,12 @@ uint8_t I2C3733_Init_Control(void) | |||
| 265 | //USB state machine will enable driver when communication is ready | 265 | //USB state machine will enable driver when communication is ready |
| 266 | I2C3733_Control_Set(0); | 266 | I2C3733_Control_Set(0); |
| 267 | 267 | ||
| 268 | CLK_delay_ms(1); | 268 | wait_ms(1); |
| 269 | 269 | ||
| 270 | sr_exp_data.bit.IRST = 0; | 270 | sr_exp_data.bit.IRST = 0; |
| 271 | SR_EXP_WriteData(); | 271 | SR_EXP_WriteData(); |
| 272 | 272 | ||
| 273 | CLK_delay_ms(1); | 273 | wait_ms(1); |
| 274 | 274 | ||
| 275 | DBGC(DC_I2C3733_INIT_CONTROL_COMPLETE); | 275 | DBGC(DC_I2C3733_INIT_CONTROL_COMPLETE); |
| 276 | 276 | ||
diff --git a/tmk_core/protocol/arm_atsam/led_matrix.c b/tmk_core/protocol/arm_atsam/led_matrix.c index e914fc80e..04d05af6d 100644 --- a/tmk_core/protocol/arm_atsam/led_matrix.c +++ b/tmk_core/protocol/arm_atsam/led_matrix.c | |||
| @@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 18 | #include "arm_atsam_protocol.h" | 18 | #include "arm_atsam_protocol.h" |
| 19 | #include "tmk_core/common/led.h" | 19 | #include "tmk_core/common/led.h" |
| 20 | #include <string.h> | 20 | #include <string.h> |
| 21 | #include <math.h> | ||
| 21 | 22 | ||
| 22 | void SERCOM1_0_Handler( void ) | 23 | void SERCOM1_0_Handler( void ) |
| 23 | { | 24 | { |
| @@ -217,6 +218,7 @@ void disp_calc_extents(void) | |||
| 217 | 218 | ||
| 218 | disp.width = disp.right - disp.left; | 219 | disp.width = disp.right - disp.left; |
| 219 | disp.height = disp.top - disp.bottom; | 220 | disp.height = disp.top - disp.bottom; |
| 221 | disp.max_distance = sqrtf(powf(disp.width, 2) + powf(disp.height, 2)); | ||
| 220 | } | 222 | } |
| 221 | 223 | ||
| 222 | void disp_pixel_setup(void) | 224 | void disp_pixel_setup(void) |
| @@ -249,6 +251,7 @@ uint8_t led_animation_breathing; | |||
| 249 | uint8_t led_animation_breathe_cur; | 251 | uint8_t led_animation_breathe_cur; |
| 250 | uint8_t breathe_step; | 252 | uint8_t breathe_step; |
| 251 | uint8_t breathe_dir; | 253 | uint8_t breathe_dir; |
| 254 | uint8_t led_animation_circular; | ||
| 252 | uint64_t led_next_run; | 255 | uint64_t led_next_run; |
| 253 | 256 | ||
| 254 | uint8_t led_animation_id; | 257 | uint8_t led_animation_id; |
| @@ -265,6 +268,7 @@ void led_matrix_run(void) | |||
| 265 | float go; | 268 | float go; |
| 266 | float bo; | 269 | float bo; |
| 267 | float po; | 270 | float po; |
| 271 | |||
| 268 | uint8_t led_this_run = 0; | 272 | uint8_t led_this_run = 0; |
| 269 | led_setup_t *f = (led_setup_t*)led_setups[led_animation_id]; | 273 | led_setup_t *f = (led_setup_t*)led_setups[led_animation_id]; |
| 270 | 274 | ||
| @@ -327,13 +331,18 @@ void led_matrix_run(void) | |||
| 327 | for (fcur = 0; fcur < fmax; fcur++) | 331 | for (fcur = 0; fcur < fmax; fcur++) |
| 328 | { | 332 | { |
| 329 | 333 | ||
| 330 | if (led_animation_orientation) | 334 | if (led_animation_circular) { |
| 331 | { | 335 | po = sqrtf((powf(fabsf((disp.width / 2) - (led_cur->x - disp.left)), 2) + powf(fabsf((disp.height / 2) - (led_cur->y - disp.bottom)), 2))) / disp.max_distance * 100; |
| 332 | po = led_cur->py; | ||
| 333 | } | 336 | } |
| 334 | else | 337 | else { |
| 335 | { | 338 | if (led_animation_orientation) |
| 336 | po = led_cur->px; | 339 | { |
| 340 | po = led_cur->py; | ||
| 341 | } | ||
| 342 | else | ||
| 343 | { | ||
| 344 | po = led_cur->px; | ||
| 345 | } | ||
| 337 | } | 346 | } |
| 338 | 347 | ||
| 339 | float pomod; | 348 | float pomod; |
| @@ -466,6 +475,7 @@ uint8_t led_matrix_init(void) | |||
| 466 | led_animation_breathe_cur = BREATHE_MIN_STEP; | 475 | led_animation_breathe_cur = BREATHE_MIN_STEP; |
| 467 | breathe_step = 1; | 476 | breathe_step = 1; |
| 468 | breathe_dir = 1; | 477 | breathe_dir = 1; |
| 478 | led_animation_circular = 0; | ||
| 469 | 479 | ||
| 470 | gcr_min_counter = 0; | 480 | gcr_min_counter = 0; |
| 471 | v_5v_cat_hit = 0; | 481 | v_5v_cat_hit = 0; |
| @@ -494,11 +504,11 @@ void led_matrix_task(void) | |||
| 494 | if (led_enabled) | 504 | if (led_enabled) |
| 495 | { | 505 | { |
| 496 | //If an update may run and frame processing has completed | 506 | //If an update may run and frame processing has completed |
| 497 | if (CLK_get_ms() >= led_next_run && led_cur == lede) | 507 | if (timer_read64() >= led_next_run && led_cur == lede) |
| 498 | { | 508 | { |
| 499 | uint8_t drvid; | 509 | uint8_t drvid; |
| 500 | 510 | ||
| 501 | led_next_run = CLK_get_ms() + LED_UPDATE_RATE; //Set next frame update time | 511 | led_next_run = timer_read64() + LED_UPDATE_RATE; //Set next frame update time |
| 502 | 512 | ||
| 503 | //NOTE: GCR does not need to be timed with LED processing, but there is really no harm | 513 | //NOTE: GCR does not need to be timed with LED processing, but there is really no harm |
| 504 | if (gcr_actual != gcr_actual_last) | 514 | if (gcr_actual != gcr_actual_last) |
diff --git a/tmk_core/protocol/arm_atsam/led_matrix.h b/tmk_core/protocol/arm_atsam/led_matrix.h index cedea8a85..4513234e7 100644 --- a/tmk_core/protocol/arm_atsam/led_matrix.h +++ b/tmk_core/protocol/arm_atsam/led_matrix.h | |||
| @@ -83,6 +83,7 @@ typedef struct led_disp_s { | |||
| 83 | float bottom; | 83 | float bottom; |
| 84 | float width; | 84 | float width; |
| 85 | float height; | 85 | float height; |
| 86 | float max_distance; | ||
| 86 | } led_disp_t; | 87 | } led_disp_t; |
| 87 | 88 | ||
| 88 | uint8_t led_matrix_init(void); | 89 | uint8_t led_matrix_init(void); |
| @@ -129,6 +130,7 @@ extern uint8_t led_animation_orientation; | |||
| 129 | extern uint8_t led_animation_breathing; | 130 | extern uint8_t led_animation_breathing; |
| 130 | extern uint8_t led_animation_breathe_cur; | 131 | extern uint8_t led_animation_breathe_cur; |
| 131 | extern uint8_t breathe_dir; | 132 | extern uint8_t breathe_dir; |
| 133 | extern uint8_t led_animation_circular; | ||
| 132 | extern const uint8_t led_setups_count; | 134 | extern const uint8_t led_setups_count; |
| 133 | 135 | ||
| 134 | extern void *led_setups[]; | 136 | extern void *led_setups[]; |
diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index 2bda7d7c7..eaad66e9f 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c | |||
| @@ -159,7 +159,7 @@ void send_consumer(uint16_t data) | |||
| 159 | 159 | ||
| 160 | void main_subtask_usb_state(void) | 160 | void main_subtask_usb_state(void) |
| 161 | { | 161 | { |
| 162 | static uint32_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware | 162 | static uint64_t fsmstate_on_delay = 0; //Delay timer to be sure USB is actually operating before bringing up hardware |
| 163 | uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register | 163 | uint8_t fsmstate_now = USB->DEVICE.FSMSTATUS.reg; //Current state from hardware register |
| 164 | 164 | ||
| 165 | if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED | 165 | if (fsmstate_now == USB_FSMSTATUS_FSMSTATE_SUSPEND_Val) //If USB SUSPENDED |
| @@ -188,9 +188,9 @@ void main_subtask_usb_state(void) | |||
| 188 | { | 188 | { |
| 189 | if (fsmstate_on_delay == 0) //If ON delay timer is cleared | 189 | if (fsmstate_on_delay == 0) //If ON delay timer is cleared |
| 190 | { | 190 | { |
| 191 | fsmstate_on_delay = CLK_get_ms() + 250; //Set ON delay timer | 191 | fsmstate_on_delay = timer_read64() + 250; //Set ON delay timer |
| 192 | } | 192 | } |
| 193 | else if (CLK_get_ms() > fsmstate_on_delay) //Else if ON delay timer is active and timed out | 193 | else if (timer_read64() > fsmstate_on_delay) //Else if ON delay timer is active and timed out |
| 194 | { | 194 | { |
| 195 | suspend_wakeup_init(); //Run wakeup routine | 195 | suspend_wakeup_init(); //Run wakeup routine |
| 196 | g_usb_state = fsmstate_now; //Save current USB state | 196 | g_usb_state = fsmstate_now; //Save current USB state |
| @@ -214,9 +214,9 @@ void main_subtask_power_check(void) | |||
| 214 | { | 214 | { |
| 215 | static uint64_t next_5v_checkup = 0; | 215 | static uint64_t next_5v_checkup = 0; |
| 216 | 216 | ||
| 217 | if (CLK_get_ms() > next_5v_checkup) | 217 | if (timer_read64() > next_5v_checkup) |
| 218 | { | 218 | { |
| 219 | next_5v_checkup = CLK_get_ms() + 5; | 219 | next_5v_checkup = timer_read64() + 5; |
| 220 | 220 | ||
| 221 | v_5v = adc_get(ADC_5V); | 221 | v_5v = adc_get(ADC_5V); |
| 222 | v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v; | 222 | v_5v_avg = 0.9 * v_5v_avg + 0.1 * v_5v; |
| @@ -229,9 +229,9 @@ void main_subtask_usb_extra_device(void) | |||
| 229 | { | 229 | { |
| 230 | static uint64_t next_usb_checkup = 0; | 230 | static uint64_t next_usb_checkup = 0; |
| 231 | 231 | ||
| 232 | if (CLK_get_ms() > next_usb_checkup) | 232 | if (timer_read64() > next_usb_checkup) |
| 233 | { | 233 | { |
| 234 | next_usb_checkup = CLK_get_ms() + 10; | 234 | next_usb_checkup = timer_read64() + 10; |
| 235 | 235 | ||
| 236 | USB_HandleExtraDevice(); | 236 | USB_HandleExtraDevice(); |
| 237 | } | 237 | } |
| @@ -325,9 +325,9 @@ int main(void) | |||
| 325 | keyboard_task(); | 325 | keyboard_task(); |
| 326 | 326 | ||
| 327 | #ifdef CONSOLE_ENABLE | 327 | #ifdef CONSOLE_ENABLE |
| 328 | if (CLK_get_ms() > next_print) | 328 | if (timer_read64() > next_print) |
| 329 | { | 329 | { |
| 330 | next_print = CLK_get_ms() + 250; | 330 | next_print = timer_read64() + 250; |
| 331 | //Add any debug information here that you want to see very often | 331 | //Add any debug information here that you want to see very often |
| 332 | //dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired); | 332 | //dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired); |
| 333 | } | 333 | } |
diff --git a/tmk_core/protocol/arm_atsam/usb/compiler.h b/tmk_core/protocol/arm_atsam/usb/compiler.h index 7d8350896..b2ccfd73e 100644 --- a/tmk_core/protocol/arm_atsam/usb/compiler.h +++ b/tmk_core/protocol/arm_atsam/usb/compiler.h | |||
| @@ -134,13 +134,15 @@ | |||
| 134 | * heuristics and inline the function no matter how big it thinks it | 134 | * heuristics and inline the function no matter how big it thinks it |
| 135 | * becomes. | 135 | * becomes. |
| 136 | */ | 136 | */ |
| 137 | #if !defined(__always_inline) | ||
| 137 | #if defined(__CC_ARM) | 138 | #if defined(__CC_ARM) |
| 138 | # define __always_inline __forceinline | 139 | # define __always_inline __forceinline |
| 139 | #elif (defined __GNUC__ && __GNUC__ <= 6) | 140 | #elif (defined __GNUC__) |
| 140 | # define __always_inline __attribute__((__always_inline__)) | 141 | # define __always_inline __attribute__((__always_inline__)) |
| 141 | #elif (defined __ICCARM__) | 142 | #elif (defined __ICCARM__) |
| 142 | # define __always_inline _Pragma("inline=forced") | 143 | # define __always_inline _Pragma("inline=forced") |
| 143 | #endif | 144 | #endif |
| 145 | #endif | ||
| 144 | 146 | ||
| 145 | /** | 147 | /** |
| 146 | * \def __no_inline | 148 | * \def __no_inline |
diff --git a/tmk_core/protocol/arm_atsam/usb/udi_cdc.c b/tmk_core/protocol/arm_atsam/usb/udi_cdc.c index 5f3c289e8..ffe3526db 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_cdc.c +++ b/tmk_core/protocol/arm_atsam/usb/udi_cdc.c | |||
| @@ -1227,9 +1227,9 @@ uint32_t cdc_tx_send_time_next; | |||
| 1227 | 1227 | ||
| 1228 | void CDC_send(void) | 1228 | void CDC_send(void) |
| 1229 | { | 1229 | { |
| 1230 | while (CLK_get_ms() < cdc_tx_send_time_next); | 1230 | while (timer_read64() < cdc_tx_send_time_next); |
| 1231 | udi_cdc_tx_send(0); | 1231 | udi_cdc_tx_send(0); |
| 1232 | cdc_tx_send_time_next = CLK_get_ms() + CDC_SEND_INTERVAL; | 1232 | cdc_tx_send_time_next = timer_read64() + CDC_SEND_INTERVAL; |
| 1233 | } | 1233 | } |
| 1234 | 1234 | ||
| 1235 | uint32_t CDC_print(char *printbuf) | 1235 | uint32_t CDC_print(char *printbuf) |
| @@ -1238,7 +1238,7 @@ uint32_t CDC_print(char *printbuf) | |||
| 1238 | char *buf = printbuf; | 1238 | char *buf = printbuf; |
| 1239 | char c; | 1239 | char c; |
| 1240 | 1240 | ||
| 1241 | if (CLK_get_ms() < 5000) return 0; | 1241 | if (timer_read64() < 5000) return 0; |
| 1242 | 1242 | ||
| 1243 | while ((c = *buf++) != 0 && !(count >= MAX_PRINT)) | 1243 | while ((c = *buf++) != 0 && !(count >= MAX_PRINT)) |
| 1244 | { | 1244 | { |
| @@ -1339,7 +1339,7 @@ void CDC_init(void) | |||
| 1339 | inbuf.count = 0; | 1339 | inbuf.count = 0; |
| 1340 | inbuf.lastcount = 0; | 1340 | inbuf.lastcount = 0; |
| 1341 | printbuf[0] = 0; | 1341 | printbuf[0] = 0; |
| 1342 | cdc_tx_send_time_next = CLK_get_ms() + CDC_SEND_INTERVAL; | 1342 | cdc_tx_send_time_next = timer_read64() + CDC_SEND_INTERVAL; |
| 1343 | } | 1343 | } |
| 1344 | 1344 | ||
| 1345 | #else //CDC line 62 | 1345 | #else //CDC line 62 |
diff --git a/tmk_core/protocol/arm_atsam/usb/usb2422.c b/tmk_core/protocol/arm_atsam/usb/usb2422.c index ac19bf4ea..d6e192242 100644 --- a/tmk_core/protocol/arm_atsam/usb/usb2422.c +++ b/tmk_core/protocol/arm_atsam/usb/usb2422.c | |||
| @@ -64,7 +64,7 @@ void USB_write2422_block(void) | |||
| 64 | i2c0_transmit(USB2422_ADDR, dest, 34, 50000); | 64 | i2c0_transmit(USB2422_ADDR, dest, 34, 50000); |
| 65 | SERCOM0->I2CM.CTRLB.bit.CMD = 0x03; | 65 | SERCOM0->I2CM.CTRLB.bit.CMD = 0x03; |
| 66 | while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP); } | 66 | while (SERCOM0->I2CM.SYNCBUSY.bit.SYSOP) { DBGC(DC_USB_WRITE2422_BLOCK_SYNC_SYSOP); } |
| 67 | CLK_delay_us(100); | 67 | wait_us(100); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE); | 70 | DBGC(DC_USB_WRITE2422_BLOCK_COMPLETE); |
| @@ -135,7 +135,7 @@ void USB2422_init(void) | |||
| 135 | sr_exp_data.bit.HUB_RESET_N = 1; //reset high | 135 | sr_exp_data.bit.HUB_RESET_N = 1; //reset high |
| 136 | SR_EXP_WriteData(); | 136 | SR_EXP_WriteData(); |
| 137 | 137 | ||
| 138 | CLK_delay_us(100); | 138 | wait_us(100); |
| 139 | 139 | ||
| 140 | #ifndef MD_BOOTLOADER | 140 | #ifndef MD_BOOTLOADER |
| 141 | 141 | ||
| @@ -154,10 +154,9 @@ void USB_reset(void) | |||
| 154 | //pulse reset for at least 1 usec | 154 | //pulse reset for at least 1 usec |
| 155 | sr_exp_data.bit.HUB_RESET_N = 0; //reset low | 155 | sr_exp_data.bit.HUB_RESET_N = 0; //reset low |
| 156 | SR_EXP_WriteData(); | 156 | SR_EXP_WriteData(); |
| 157 | CLK_delay_us(1); | 157 | wait_us(2); |
| 158 | sr_exp_data.bit.HUB_RESET_N = 1; //reset high to run | 158 | sr_exp_data.bit.HUB_RESET_N = 1; //reset high to run |
| 159 | SR_EXP_WriteData(); | 159 | SR_EXP_WriteData(); |
| 160 | CLK_delay_us(1); | ||
| 161 | 160 | ||
| 162 | DBGC(DC_USB_RESET_COMPLETE); | 161 | DBGC(DC_USB_RESET_COMPLETE); |
| 163 | } | 162 | } |
| @@ -247,7 +246,7 @@ void USB_set_host_by_voltage(void) | |||
| 247 | 246 | ||
| 248 | SR_EXP_WriteData(); | 247 | SR_EXP_WriteData(); |
| 249 | 248 | ||
| 250 | CLK_delay_ms(250); | 249 | wait_ms(250); |
| 251 | 250 | ||
| 252 | while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB_SET_HOST_5V_LOW_WAITING); } | 251 | while ((v_5v = adc_get(ADC_5V)) < ADC_5V_START_LEVEL) { DBGC(DC_USB_SET_HOST_5V_LOW_WAITING); } |
| 253 | 252 | ||
| @@ -313,11 +312,11 @@ uint8_t USB2422_Port_Detect_Init(void) | |||
| 313 | 312 | ||
| 314 | USB_set_host_by_voltage(); | 313 | USB_set_host_by_voltage(); |
| 315 | 314 | ||
| 316 | port_detect_retry_ms = CLK_get_ms() + PORT_DETECT_RETRY_INTERVAL; | 315 | port_detect_retry_ms = timer_read64() + PORT_DETECT_RETRY_INTERVAL; |
| 317 | 316 | ||
| 318 | while (!USB_active()) | 317 | while (!USB_active()) |
| 319 | { | 318 | { |
| 320 | tmod = CLK_get_ms() % PORT_DETECT_RETRY_INTERVAL; | 319 | tmod = timer_read64() % PORT_DETECT_RETRY_INTERVAL; |
| 321 | 320 | ||
| 322 | if (v_con_1 > v_con_2) //Values updated from USB_set_host_by_voltage(); | 321 | if (v_con_1 > v_con_2) //Values updated from USB_set_host_by_voltage(); |
| 323 | { | 322 | { |
| @@ -333,7 +332,7 @@ uint8_t USB2422_Port_Detect_Init(void) | |||
| 333 | else { DBG_LED_OFF; } | 332 | else { DBG_LED_OFF; } |
| 334 | } | 333 | } |
| 335 | 334 | ||
| 336 | if (CLK_get_ms() > port_detect_retry_ms) | 335 | if (timer_read64() > port_detect_retry_ms) |
| 337 | { | 336 | { |
| 338 | DBGC(DC_PORT_DETECT_INIT_FAILED); | 337 | DBGC(DC_PORT_DETECT_INIT_FAILED); |
| 339 | return 0; | 338 | return 0; |
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index ee9571c95..5436d4909 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c | |||
| @@ -113,7 +113,7 @@ int main(void) { | |||
| 113 | chSysInit(); | 113 | chSysInit(); |
| 114 | 114 | ||
| 115 | #ifdef STM32_EEPROM_ENABLE | 115 | #ifdef STM32_EEPROM_ENABLE |
| 116 | EEPROM_init(); | 116 | EEPROM_Init(); |
| 117 | #endif | 117 | #endif |
| 118 | 118 | ||
| 119 | // TESTING | 119 | // TESTING |
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 27cf51b16..f2ecf2465 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c | |||
| @@ -517,17 +517,16 @@ void EVENT_USB_Device_ControlRequest(void) | |||
| 517 | if (USB_DeviceState == DEVICE_STATE_Unattached) | 517 | if (USB_DeviceState == DEVICE_STATE_Unattached) |
| 518 | return; | 518 | return; |
| 519 | } | 519 | } |
| 520 | #ifdef KEYBOARD_SHARED_EP | 520 | |
| 521 | uint8_t report_id = REPORT_ID_KEYBOARD; | 521 | if (Endpoint_BytesInEndpoint() == 2) { |
| 522 | if (keyboard_protocol) { | 522 | uint8_t report_id = Endpoint_Read_8(); |
| 523 | report_id = Endpoint_Read_8(); | 523 | |
| 524 | } | 524 | if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) { |
| 525 | if (report_id == REPORT_ID_KEYBOARD || report_id == REPORT_ID_NKRO) { | ||
| 526 | keyboard_led_stats = Endpoint_Read_8(); | 525 | keyboard_led_stats = Endpoint_Read_8(); |
| 526 | } | ||
| 527 | } else { | ||
| 528 | keyboard_led_stats = Endpoint_Read_8(); | ||
| 527 | } | 529 | } |
| 528 | #else | ||
| 529 | keyboard_led_stats = Endpoint_Read_8(); | ||
| 530 | #endif | ||
| 531 | 530 | ||
| 532 | Endpoint_ClearOUT(); | 531 | Endpoint_ClearOUT(); |
| 533 | Endpoint_ClearStatusStage(); | 532 | Endpoint_ClearStatusStage(); |
