summaryrefslogtreecommitdiff
path: root/quantum
diff options
context:
space:
mode:
authorIBNobody <protospherex@gmail.com>2016-04-18 15:47:10 -0500
committerIBNobody <protospherex@gmail.com>2016-04-18 15:47:10 -0500
commitcbcf0abe62b764a9f3d80848611dca8291d93eb8 (patch)
tree2014b1d839bfaa29acdbf432265d908562304834 /quantum
parentd5cc31d7d4fc1a36fc3e3e0018369cb52553f50f (diff)
parent4f4b5b8c18d4f1bf4fd4c51ad6f316501dfbd6cc (diff)
Merge remote-tracking branch 'refs/remotes/origin/personal_atomic_planck'
Diffstat (limited to 'quantum')
-rw-r--r--quantum/audio.c259
-rw-r--r--quantum/audio.h45
-rw-r--r--quantum/keymap_common.c275
-rw-r--r--quantum/keymap_common.h32
-rw-r--r--quantum/led.c1
-rw-r--r--quantum/musical_notes.h217
-rw-r--r--quantum/quantum.mk9
-rw-r--r--quantum/song_list.h101
-rw-r--r--quantum/tools/README.md6
-rw-r--r--quantum/tools/eeprom_reset.hex9
10 files changed, 752 insertions, 202 deletions
diff --git a/quantum/audio.c b/quantum/audio.c
index f29d941d7c..627e3d80a1 100644
--- a/quantum/audio.c
+++ b/quantum/audio.c
@@ -4,12 +4,16 @@
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/io.h>
-
+#include "print.h"
#include "audio.h"
#include "keymap_common.h"
+#include "eeconfig.h"
+
#define PI 3.14159265
+#define CPU_PRESCALER 8
+
// #define PWM_AUDIO
#ifdef PWM_AUDIO
@@ -30,6 +34,8 @@ int voice_place = 0;
double frequency = 0;
int volume = 0;
long position = 0;
+int duty_place = 1;
+int duty_counter = 0;
double frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
@@ -51,11 +57,36 @@ bool notes = false;
bool note = false;
float note_frequency = 0;
float note_length = 0;
+float note_tempo = TEMPO_DEFAULT;
+float note_timbre = TIMBRE_DEFAULT;
uint16_t note_position = 0;
float (* notes_pointer)[][2];
-uint8_t notes_length;
+uint8_t notes_count;
bool notes_repeat;
+float notes_rest;
+bool note_resting = false;
+
uint8_t current_note = 0;
+uint8_t rest_counter = 0;
+
+audio_config_t audio_config;
+
+
+void audio_toggle(void) {
+ audio_config.enable ^= 1;
+ eeconfig_write_audio(audio_config.raw);
+}
+
+void audio_on(void) {
+ audio_config.enable = 1;
+ eeconfig_write_audio(audio_config.raw);
+}
+
+void audio_off(void) {
+ audio_config.enable = 0;
+ eeconfig_write_audio(audio_config.raw);
+}
+
void stop_all_notes() {
voices = 0;
@@ -77,58 +108,66 @@ void stop_all_notes() {
}
void stop_note(double freq) {
- #ifdef PWM_AUDIO
- freq = freq / SAMPLE_RATE;
- #endif
- for (int i = 7; i >= 0; i--) {
- if (frequencies[i] == freq) {
- frequencies[i] = 0;
- volumes[i] = 0;
- for (int j = i; (j < 7); j++) {
- frequencies[j] = frequencies[j+1];
- frequencies[j+1] = 0;
- volumes[j] = volumes[j+1];
- volumes[j+1] = 0;
- }
- }
- }
- voices--;
- if (voices < 0)
- voices = 0;
- if (voices == 0) {
+ if (note) {
#ifdef PWM_AUDIO
- TIMSK3 &= ~_BV(OCIE3A);
- #else
- TIMSK3 &= ~_BV(OCIE3A);
- TCCR3A &= ~_BV(COM3A1);
+ freq = freq / SAMPLE_RATE;
#endif
- frequency = 0;
- volume = 0;
- note = false;
- } else {
- double freq = frequencies[voices - 1];
- int vol = volumes[voices - 1];
- double starting_f = frequency;
- if (frequency < freq) {
- sliding = true;
- for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
- frequency = f;
+ for (int i = 7; i >= 0; i--) {
+ if (frequencies[i] == freq) {
+ frequencies[i] = 0;
+ volumes[i] = 0;
+ for (int j = i; (j < 7); j++) {
+ frequencies[j] = frequencies[j+1];
+ frequencies[j+1] = 0;
+ volumes[j] = volumes[j+1];
+ volumes[j+1] = 0;
+ }
}
- sliding = false;
- } else if (frequency > freq) {
- sliding = true;
- for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) {
- frequency = f;
+ }
+ voices--;
+ if (voices < 0)
+ voices = 0;
+ if (voices == 0) {
+ #ifdef PWM_AUDIO
+ TIMSK3 &= ~_BV(OCIE3A);
+ #else
+ TIMSK3 &= ~_BV(OCIE3A);
+ TCCR3A &= ~_BV(COM3A1);
+ #endif
+ frequency = 0;
+ volume = 0;
+ note = false;
+ } else {
+ double freq = frequencies[voices - 1];
+ int vol = volumes[voices - 1];
+ double starting_f = frequency;
+ if (frequency < freq) {
+ sliding = true;
+ for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
+ frequency = f;
+ }
+ sliding = false;
+ } else if (frequency > freq) {
+ sliding = true;
+ for (double f = starting_f; f >= freq; f -= ((starting_f - freq) / 2000.0)) {
+ frequency = f;
+ }
+ sliding = false;
}
- sliding = false;
+ frequency = freq;
+ volume = vol;
}
- frequency = freq;
- volume = vol;
}
}
void init_notes() {
+ /* check signature */
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+ audio_config.raw = eeconfig_read_audio();
+
#ifdef PWM_AUDIO
PLLFRQ = _BV(PDIV2);
PLLCSR = _BV(PLLE);
@@ -144,7 +183,7 @@ void init_notes() {
DDRC |= _BV(PORTC6);
TIMSK3 &= ~_BV(OCIE3A); // Turn off 3A interputs
-
+
TCCR3A = 0x0; // Options not needed
TCCR3B = _BV(CS31) | _BV(CS30) | _BV(WGM32); // 64th prescaling and CTC
OCR3A = SAMPLE_DIVIDER - 1; // Correct count/compare, related to sample playback
@@ -160,20 +199,19 @@ void init_notes() {
ISR(TIMER3_COMPA_vect) {
-
if (note) {
#ifdef PWM_AUDIO
if (voices == 1) {
// SINE
OCR4A = pgm_read_byte(&sinewave[(uint16_t)place]) >> 2;
-
+
// SQUARE
// if (((int)place) >= 1024){
// OCR4A = 0xFF >> 2;
// } else {
// OCR4A = 0x00;
// }
-
+
// SAWTOOTH
// OCR4A = (int)place / 4;
@@ -213,13 +251,20 @@ ISR(TIMER3_COMPA_vect) {
if (frequency > 0) {
// ICR3 = (int)(((double)F_CPU) / frequency); // Set max to the period
// OCR3A = (int)(((double)F_CPU) / frequency) >> 1; // Set compare to half the period
- if (place > 10) {
+ voice_place %= voices;
+ if (place > (frequencies[voice_place] / 50)) {
voice_place = (voice_place + 1) % voices;
place = 0.0;
}
- ICR3 = (int)(((double)F_CPU) / frequencies[voice_place]); // Set max to the period
- OCR3A = (int)(((double)F_CPU) / frequencies[voice_place]) >> 1; // Set compare to half the period
+ ICR3 = (int)(((double)F_CPU) / (frequencies[voice_place] * CPU_PRESCALER)); // Set max to the period
+ OCR3A = (int)((((double)F_CPU) / (frequencies[voice_place] * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
+ //OCR3A = (int)(((double)F_CPU) / (frequencies[voice_place] * CPU_PRESCALER)) >> 1 * duty_place; // Set compare to half the period
place++;
+ // if (duty_counter > (frequencies[voice_place] / 500)) {
+ // duty_place = (duty_place % 3) + 1;
+ // duty_counter = 0;
+ // }
+ // duty_counter++;
}
#endif
}
@@ -245,8 +290,8 @@ ISR(TIMER3_COMPA_vect) {
place -= SINE_LENGTH;
#else
if (note_frequency > 0) {
- ICR3 = (int)(((double)F_CPU) / note_frequency); // Set max to the period
- OCR3A = (int)(((double)F_CPU) / note_frequency) >> 1; // Set compare to half the period
+ ICR3 = (int)(((double)F_CPU) / (note_frequency * CPU_PRESCALER)); // Set max to the period
+ OCR3A = (int)((((double)F_CPU) / (note_frequency * CPU_PRESCALER)) * note_timbre); // Set compare to half the period
} else {
ICR3 = 0;
OCR3A = 0;
@@ -255,9 +300,14 @@ ISR(TIMER3_COMPA_vect) {
note_position++;
- if (note_position >= note_length) {
+ bool end_of_note = false;
+ if (ICR3 > 0)
+ end_of_note = (note_position >= (note_length / ICR3 * 0xFFFF));
+ else
+ end_of_note = (note_position >= (note_length * 0x7FF));
+ if (end_of_note) {
current_note++;
- if (current_note >= notes_length) {
+ if (current_note >= notes_count) {
if (notes_repeat) {
current_note = 0;
} else {
@@ -271,37 +321,54 @@ ISR(TIMER3_COMPA_vect) {
return;
}
}
- #ifdef PWM_AUDIO
- note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
- note_length = (*notes_pointer)[current_note][1];
- #else
- note_frequency = (*notes_pointer)[current_note][0];
- note_length = (*notes_pointer)[current_note][1] / 4;
- #endif
+ if (!note_resting && (notes_rest > 0)) {
+ note_resting = true;
+ note_frequency = 0;
+ note_length = notes_rest;
+ current_note--;
+ } else {
+ note_resting = false;
+ #ifdef PWM_AUDIO
+ note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
+ note_length = (*notes_pointer)[current_note][1] * (note_tempo / 100);
+ #else
+ note_frequency = (*notes_pointer)[current_note][0];
+ note_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100);
+ #endif
+ }
note_position = 0;
}
}
+ if (!audio_config.enable) {
+ notes = false;
+ note = false;
+ }
}
-void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) {
+void play_notes(float (*np)[][2], uint8_t n_count, bool n_repeat, float n_rest) {
+
+if (audio_config.enable) {
+
+ // Cancel note if a note is playing
if (note)
stop_all_notes();
notes = true;
notes_pointer = np;
- notes_length = n_length;
+ notes_count = n_count;
notes_repeat = n_repeat;
+ notes_rest = n_rest;
place = 0;
current_note = 0;
#ifdef PWM_AUDIO
note_frequency = (*notes_pointer)[current_note][0] / SAMPLE_RATE;
- note_length = (*notes_pointer)[current_note][1];
+ note_length = (*notes_pointer)[current_note][1] * (note_tempo / 100);
#else
note_frequency = (*notes_pointer)[current_note][0];
- note_length = (*notes_pointer)[current_note][1] / 4;
+ note_length = ((*notes_pointer)[current_note][1] / 4) * (note_tempo / 100);
#endif
note_position = 0;
@@ -312,9 +379,15 @@ void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat) {
TIMSK3 |= _BV(OCIE3A);
TCCR3A |= _BV(COM3A1);
#endif
+
+}
+
}
void play_sample(uint8_t * s, uint16_t l, bool r) {
+
+if (audio_config.enable) {
+
stop_all_notes();
place_int = 0;
sample = s;
@@ -325,9 +398,16 @@ void play_sample(uint8_t * s, uint16_t l, bool r) {
TIMSK3 |= _BV(OCIE3A);
#else
#endif
+
+}
+
}
void play_note(double freq, int vol) {
+
+if (audio_config.enable && voices < 8) {
+
+ // Cancel notes if notes are playing
if (notes)
stop_all_notes();
note = true;
@@ -338,7 +418,7 @@ void play_note(double freq, int vol) {
if (frequency != 0) {
double starting_f = frequency;
if (frequency < freq) {
- for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
+ for (double f = starting_f; f <= freq; f += ((freq - starting_f) / 2000.0)) {
frequency = f;
}
} else if (frequency > freq) {
@@ -362,4 +442,47 @@ void play_note(double freq, int vol) {
TCCR3A |= _BV(COM3A1);
#endif
-} \ No newline at end of file
+}
+
+}
+
+void set_timbre(float timbre)
+{
+ note_timbre = timbre;
+}
+
+void set_tempo(float tempo)
+{
+ note_tempo = tempo;
+}
+
+void decrease_tempo(uint8_t tempo_change)
+{
+ note_tempo += (float) tempo_change;
+}
+
+void increase_tempo(uint8_t tempo_change)
+{
+ if (note_tempo - (float) tempo_change < 10)
+ {
+ note_tempo = 10;
+ }
+ else
+ {
+ note_tempo -= (float) tempo_change;
+ }
+}
+
+//------------------------------------------------------------------------------
+// Override these functions in your keymap file to play different tunes on
+// startup and bootloader jump
+__attribute__ ((weak))
+void play_startup_tone()
+{
+}
+
+__attribute__ ((weak))
+void play_goodbye_tone()
+{
+}
+//------------------------------------------------------------------------------
diff --git a/quantum/audio.h b/quantum/audio.h
index 99203cea7a..44cafccd68 100644
--- a/quantum/audio.h
+++ b/quantum/audio.h
@@ -2,10 +2,49 @@
#include <stdbool.h>
#include <avr/io.h>
#include <util/delay.h>
+#include "musical_notes.h"
+#include "song_list.h"
+
+#ifndef AUDIO_H
+#define AUDIO_H
+
+typedef union {
+ uint8_t raw;
+ struct {
+ bool enable :1;
+ uint8_t level :7;
+ };
+} audio_config_t;
+
+void audio_toggle(void);
+void audio_on(void);
+void audio_off(void);
void play_sample(uint8_t * s, uint16_t l, bool r);
void play_note(double freq, int vol);
void stop_note(double freq);
-void stop_all_notes();
-void init_notes();
-void play_notes(float (*np)[][2], uint8_t n_length, bool n_repeat); \ No newline at end of file
+void stop_all_notes(void);
+void init_notes(void);
+void play_notes(float (*np)[][2], uint8_t n_count, bool n_repeat, float n_rest);
+
+void set_timbre(float timbre);
+void set_tempo(float tempo);
+void increase_tempo(uint8_t tempo_change);
+void decrease_tempo(uint8_t tempo_change);
+
+#define SCALE (int []){ 0 + (12*0), 2 + (12*0), 4 + (12*0), 5 + (12*0), 7 + (12*0), 9 + (12*0), 11 + (12*0), \
+ 0 + (12*1), 2 + (12*1), 4 + (12*1), 5 + (12*1), 7 + (12*1), 9 + (12*1), 11 + (12*1), \
+ 0 + (12*2), 2 + (12*2), 4 + (12*2), 5 + (12*2), 7 + (12*2), 9 + (12*2), 11 + (12*2), \
+ 0 + (12*3), 2 + (12*3), 4 + (12*3), 5 + (12*3), 7 + (12*3), 9 + (12*3), 11 + (12*3), \
+ 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), }
+
+// These macros are used to allow play_notes to play an array of indeterminate
+// length. This works around the limitation of C's sizeof operation on pointers.
+// The global float array for the song must be used here.
+#define NOTE_ARRAY_SIZE(x) ((int)(sizeof(x) / (sizeof(x[0]))))
+#define PLAY_NOTE_ARRAY(note_array, note_repeat, note_rest_style) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), (note_repeat), (note_rest_style));
+
+void play_goodbye_tone(void);
+void play_startup_tone(void);
+
+#endif \ No newline at end of file
diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c
index ae6cddb343..4ee290ad03 100644
--- a/quantum/keymap_common.c
+++ b/quantum/keymap_common.c
@@ -26,143 +26,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "backlight.h"
#include "keymap_midi.h"
#include "bootloader.h"
+#include "eeconfig.h"
+
+extern keymap_config_t keymap_config;
#include <stdio.h>
#include <inttypes.h>
#ifdef AUDIO_ENABLE
#include "audio.h"
-
- float goodbye[][2] = {
- {440.0*pow(2.0,(67)/12.0), 400},
- {0, 50},
- {440.0*pow(2.0,(60)/12.0), 400},
- {0, 50},
- {440.0*pow(2.0,(55)/12.0), 600},
- };
-#endif
+#endif /* AUDIO_ENABLE */
static action_t keycode_to_action(uint16_t keycode);
/* converts key to action */
action_t action_for_key(uint8_t layer, keypos_t key)
{
- // 16bit keycodes - important
+ // 16bit keycodes - important
uint16_t keycode = keymap_key_to_keycode(layer, key);
- if (keycode >= 0x0100 && keycode < 0x2000) {
- // Has a modifier
- action_t action;
- // Split it up
- action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
- return action;
- } else if (keycode >= 0x2000 && keycode < 0x3000) {
- // Is a shortcut for function layer, pull last 12bits
- // This means we have 4,096 FN macros at our disposal
- return keymap_func_to_action(keycode & 0xFFF);
- } else if (keycode >= 0x3000 && keycode < 0x4000) {
- // When the code starts with 3, it's an action macro.
- action_t action;
- action.code = ACTION_MACRO(keycode & 0xFF);
- return action;
-#ifdef BACKLIGHT_ENABLE
- } else if (keycode >= BL_0 && keycode <= BL_15) {
- action_t action;
- action.code = ACTION_BACKLIGHT_LEVEL(keycode & 0x000F);
- return action;
- } else if (keycode == BL_DEC) {
- action_t action;
- action.code = ACTION_BACKLIGHT_DECREASE();
- return action;
- } else if (keycode == BL_INC) {
- action_t action;
- action.code = ACTION_BACKLIGHT_INCREASE();
- return action;
- } else if (keycode == BL_TOGG) {
- action_t action;
- action.code = ACTION_BACKLIGHT_TOGGLE();
- return action;
- } else if (keycode == BL_STEP) {
- action_t action;
- action.code = ACTION_BACKLIGHT_STEP();
- return action;
-#endif
- } else if (keycode == RESET) { // RESET is 0x5000, which is why this is here
- action_t action;
- clear_keyboard();
- #ifdef AUDIO_ENABLE
- play_notes(&goodbye, 5, false);
- #endif
- _delay_ms(250);
- #ifdef ATREUS_ASTAR
- *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
- #endif
- bootloader_jump();
- return action;
- } else if (keycode == DEBUG) { // DEBUG is 0x5001
- // TODO: Does this actually work?
- action_t action;
- print("\nDEBUG: enabled.\n");
- debug_enable = true;
- return action;
- } else if (keycode >= 0x5000 && keycode < 0x6000) {
- // Layer movement shortcuts
- // See .h to see constraints/usage
- int type = (keycode >> 0x8) & 0xF;
- if (type == 0x1) {
- // Layer set "GOTO"
- int when = (keycode >> 0x4) & 0x3;
- int layer = keycode & 0xF;
- action_t action;
- action.code = ACTION_LAYER_SET(layer, when);
- return action;
- } else if (type == 0x2) {
- // Momentary layer
- int layer = keycode & 0xFF;
- action_t action;
- action.code = ACTION_LAYER_MOMENTARY(layer);
- return action;
- } else if (type == 0x3) {
- // Set default layer
- int layer = keycode & 0xFF;
- action_t action;
- action.code = ACTION_DEFAULT_LAYER_SET(layer);
- return action;
- } else if (type == 0x4) {
- // Set default layer
- int layer = keycode & 0xFF;
- action_t action;
- action.code = ACTION_LAYER_TOGGLE(layer);
- return action;
- }
-#ifdef MIDI_ENABLE
- } else if (keycode >= 0x6000 && keycode < 0x7000) {
- action_t action;
- action.code = ACTION_FUNCTION_OPT(keycode & 0xFF, (keycode & 0x0F00) >> 8);
- return action;
-#endif
- } else if (keycode >= 0x7000 && keycode < 0x8000) {
- action_t action;
- action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
- return action;
- } else if (keycode >= 0x8000 && keycode < 0x9000) {
- action_t action;
- action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
- return action;
-#ifdef UNICODE_ENABLE
- } else if (keycode >= 0x8000000) {
- action_t action;
- uint16_t unicode = keycode & ~(0x8000);
- action.code = ACTION_FUNCTION_OPT(unicode & 0xFF, (unicode & 0xFF00) >> 8);
- return action;
-#endif
- } else {
-
- }
-
switch (keycode) {
case KC_FN0 ... KC_FN31:
return keymap_fn_to_action(keycode);
-#ifdef BOOTMAGIC_ENABLE
case KC_CAPSLOCK:
case KC_LOCKING_CAPS:
if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
@@ -226,7 +110,6 @@ action_t action_for_key(uint8_t layer, keypos_t key)
return keycode_to_action(KC_BSLASH);
}
return keycode_to_action(KC_BSPACE);
-#endif
default:
return keycode_to_action(keycode);
}
@@ -267,6 +150,142 @@ static action_t keycode_to_action(uint16_t keycode)
case KC_TRNS:
action.code = ACTION_TRANSPARENT;
break;
+ case 0x0100 ... 0x1FFF: ;
+ // Has a modifier
+ // Split it up
+ action.code = ACTION_MODS_KEY(keycode >> 8, keycode & 0xFF); // adds modifier to key
+ break;
+ case 0x2000 ... 0x2FFF:
+ // Is a shortcut for function layer, pull last 12bits
+ // This means we have 4,096 FN macros at our disposal
+ return keymap_func_to_action(keycode & 0xFFF);
+ break;
+ case 0x3000 ... 0x3FFF: ;
+ // When the code starts with 3, it's an action macro.
+ action.code = ACTION_MACRO(keycode & 0xFF);
+ break;
+ #ifdef BACKLIGHT_ENABLE
+ case BL_0 ... BL_15:
+ action.code = ACTION_BACKLIGHT_LEVEL(keycode & 0x000F);
+ break;
+ case BL_DEC:
+ action.code = ACTION_BACKLIGHT_DECREASE();
+ break;
+ case BL_INC:
+ action.code = ACTION_BACKLIGHT_INCREASE();
+ break;
+ case BL_TOGG:
+ action.code = ACTION_BACKLIGHT_TOGGLE();
+ break;
+ case BL_STEP:
+ action.code = ACTION_BACKLIGHT_STEP();
+ break;
+ #endif
+ case RESET: ; // RESET is 0x5000, which is why this is here
+ clear_keyboard();
+ #ifdef AUDIO_ENABLE
+ play_goodbye_tone();
+ #endif
+ _delay_ms(250);
+ #ifdef ATREUS_ASTAR
+ *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
+ #endif
+ bootloader_jump();
+ break;
+ case DEBUG: ; // DEBUG is 0x5001
+ print("\nDEBUG: enabled.\n");
+ debug_enable = true;
+ break;
+ case 0x5002 ... 0x50FF:
+ // MAGIC actions (BOOTMAGIC without the boot)
+ if (!eeconfig_is_enabled()) {
+ eeconfig_init();
+ }
+ /* keymap config */
+ keymap_config.raw = eeconfig_read_keymap();
+ if (keycode == MAGIC_SWAP_CONTROL_CAPSLOCK) {
+ keymap_config.swap_control_capslock = 1;
+ } else if (keycode == MAGIC_CAPSLOCK_TO_CONTROL) {
+ keymap_config.capslock_to_control = 1;
+ } else if (keycode == MAGIC_SWAP_LALT_LGUI) {
+ keymap_config.swap_lalt_lgui = 1;
+ } else if (keycode == MAGIC_SWAP_RALT_RGUI) {
+ keymap_config.swap_ralt_rgui = 1;
+ } else if (keycode == MAGIC_NO_GUI) {
+ keymap_config.no_gui = 1;
+ } else if (keycode == MAGIC_SWAP_GRAVE_ESC) {
+ keymap_config.swap_grave_esc = 1;
+ } else if (keycode == MAGIC_SWAP_BACKSLASH_BACKSPACE) {
+ keymap_config.swap_backslash_backspace = 1;
+ } else if (keycode == MAGIC_HOST_NKRO) {
+ keymap_config.nkro = 1;
+ } else if (keycode == MAGIC_SWAP_ALT_GUI) {
+ keymap_config.swap_lalt_lgui = 1;
+ keymap_config.swap_ralt_rgui = 1;
+ }
+ /* UNs */
+ else if (keycode == MAGIC_UNSWAP_CONTROL_CAPSLOCK) {
+ keymap_config.swap_control_capslock = 0;
+ } else if (keycode == MAGIC_UNCAPSLOCK_TO_CONTROL) {
+ keymap_config.capslock_to_control = 0;
+ } else if (keycode == MAGIC_UNSWAP_LALT_LGUI) {
+ keymap_config.swap_lalt_lgui = 0;
+ } else if (keycode == MAGIC_UNSWAP_RALT_RGUI) {
+ keymap_config.swap_ralt_rgui = 0;
+ } else if (keycode == MAGIC_UNNO_GUI) {
+ keymap_config.no_gui = 0;
+ } else if (keycode == MAGIC_UNSWAP_GRAVE_ESC) {
+ keymap_config.swap_grave_esc = 0;
+ } else if (keycode == MAGIC_UNSWAP_BACKSLASH_BACKSPACE) {
+ keymap_config.swap_backslash_backspace = 0;
+ } else if (keycode == MAGIC_UNHOST_NKRO) {
+ keymap_config.nkro = 0;
+ } else if (keycode == MAGIC_UNSWAP_ALT_GUI) {
+ keymap_config.swap_lalt_lgui = 0;
+ keymap_config.swap_ralt_rgui = 0;
+ }
+ eeconfig_write_keymap(keymap_config.raw);
+ break;
+ case 0x5100 ... 0x5FFF: ;
+ // Layer movement shortcuts
+ // See .h to see constraints/usage
+ int type = (keycode >> 0x8) & 0xF;
+ if (type == 0x1) {
+ // Layer set "GOTO"
+ int when = (keycode >> 0x4) & 0x3;
+ int layer = keycode & 0xF;
+ action.code = ACTION_LAYER_SET(layer, when);
+ } else if (type == 0x2) {
+ // Momentary layer
+ int layer = keycode & 0xFF;
+ action.code = ACTION_LAYER_MOMENTARY(layer);
+ } else if (type == 0x3) {
+ // Set default layer
+ int layer = keycode & 0xFF;
+ action.code = ACTION_DEFAULT_LAYER_SET(layer);
+ } else if (type == 0x4) {
+ // Set default layer
+ int layer = keycode & 0xFF;
+ action.code = ACTION_LAYER_TOGGLE(layer);
+ }
+ break;
+ #ifdef MIDI_ENABLE
+ case 0x6000 ... 0x6FFF:
+ action.code = ACTION_FUNCTION_OPT(keycode & 0xFF, (keycode & 0x0F00) >> 8);
+ break;
+ #endif
+ case 0x7000 ... 0x7FFF:
+ action.code = ACTION_MODS_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
+ break;
+ case 0x8000 ... 0x8FFF:
+ action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
+ break;
+ #ifdef UNICODE_ENABLE
+ case 0x8000000 ... 0x8FFFFFF:
+ uint16_t unicode = keycode & ~(0x8000);
+ action.code = ACTION_FUNCTION_OPT(unicode & 0xFF, (unicode & 0xFF00) >> 8);
+ break;
+ #endif
default:
action.code = ACTION_NO;
break;
@@ -278,7 +297,7 @@ static action_t keycode_to_action(uint16_t keycode)
/* translates key to keycode */
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
{
- // Read entire word (16bits)
+ // Read entire word (16bits)
return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]);
}
@@ -290,6 +309,14 @@ action_t keymap_fn_to_action(uint16_t keycode)
action_t keymap_func_to_action(uint16_t keycode)
{
- // For FUNC without 8bit limit
+ // For FUNC without 8bit limit
return (action_t){ .code = pgm_read_word(&fn_actions[(int)keycode]) };
}
+
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3) {
+ if (IS_LAYER_ON(layer1) && IS_LAYER_ON(layer2)) {
+ layer_on(layer3);
+ } else {
+ layer_off(layer3);
+ }
+}
diff --git a/quantum/keymap_common.h b/quantum/keymap_common.h
index 4a877d2a70..ce87e4770e 100644
--- a/quantum/keymap_common.h
+++ b/quantum/keymap_common.h
@@ -30,7 +30,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// #include "print.h"
#include "debug.h"
-#ifdef BOOTMAGIC_ENABLE
/* NOTE: Not portable. Bit field order depends on implementation */
typedef union {
uint16_t raw;
@@ -45,8 +44,6 @@ typedef union {
bool nkro:1;
};
} keymap_config_t;
-keymap_config_t keymap_config;
-#endif
/* translates key to keycode */
@@ -168,6 +165,30 @@ extern const uint16_t fn_actions[];
#define RESET 0x5000
#define DEBUG 0x5001
+// MAGIC keycodes
+#define MAGIC_SWAP_CONTROL_CAPSLOCK 0x5002
+#define MAGIC_UNSWAP_CONTROL_CAPSLOCK 0x5003
+#define MAGIC_CAPSLOCK_TO_CONTROL 0x5004
+#define MAGIC_UNCAPSLOCK_TO_CONTROL 0x5005
+#define MAGIC_SWAP_LALT_LGUI 0x5006
+#define MAGIC_UNSWAP_LALT_LGUI 0x5007
+#define MAGIC_SWAP_RALT_RGUI 0x5008
+#define MAGIC_UNSWAP_RALT_RGUI 0x5009
+#define MAGIC_NO_GUI 0x500a
+#define MAGIC_UNNO_GUI 0x500b
+#define MAGIC_SWAP_GRAVE_ESC 0x500c
+#define MAGIC_UNSWAP_GRAVE_ESC 0x500d
+#define MAGIC_SWAP_BACKSLASH_BACKSPACE 0x500e
+#define MAGIC_UNSWAP_BACKSLASH_BACKSPACE 0x500f
+#define MAGIC_HOST_NKRO 0x5010
+#define MAGIC_UNHOST_NKRO 0x5011
+#define MAGIC_SWAP_ALT_GUI 0x5012
+#define MAGIC_UNSWAP_ALT_GUI 0x5013
+
+#define AG_SWAP MAGIC_SWAP_ALT_GUI
+#define AG_NORM MAGIC_UNSWAP_ALT_GUI
+
+
// GOTO layer - 16 layers max
// when:
// ON_PRESS = 1
@@ -208,5 +229,10 @@ extern const uint16_t fn_actions[];
#define UNICODE(n) (n | 0x8000)
#define UC(n) UNICODE(n)
+// For tri-layer
+void update_tri_layer(uint8_t layer1, uint8_t layer2, uint8_t layer3);
+#define IS_LAYER_ON(layer) ((layer_state) & (1UL<<(layer)))
+#define IS_LAYER_OFF(layer) ((!layer_state) & (1UL<<(layer)))
+
#endif
diff --git a/quantum/led.c b/quantum/led.c
index 9cdb8a5c20..208e348f34 100644
--- a/quantum/led.c
+++ b/quantum/led.c
@@ -24,6 +24,7 @@ void led_set_kb(uint8_t usb_led) {
}
+__attribute__ ((weak))
void led_set(uint8_t usb_led)
{
diff --git a/quantum/musical_notes.h b/quantum/musical_notes.h
new file mode 100644
index 0000000000..b08d16a6fa
--- /dev/null
+++ b/quantum/musical_notes.h
@@ -0,0 +1,217 @@
+#ifndef MUSICAL_NOTES_H
+#define MUSICAL_NOTES_H
+
+// Tempo Placeholder
+#define TEMPO_DEFAULT 100
+
+
+#define SONG(notes...) { notes }
+
+
+// Note Types
+#define MUSICAL_NOTE(note, duration) {(NOTE##note), duration}
+#define WHOLE_NOTE(note) MUSICAL_NOTE(note, 64)
+#define HALF_NOTE(note) MUSICAL_NOTE(note, 32)
+#define QUARTER_NOTE(note) MUSICAL_NOTE(note, 16)
+#define EIGHTH_NOTE(note) MUSICAL_NOTE(note, 8)
+#define SIXTEENTH_NOTE(note) MUSICAL_NOTE(note, 4)
+
+#define WHOLE_DOT_NOTE(note) MUSICAL_NOTE(note, 64+32)
+#define HALF_DOT_NOTE(note) MUSICAL_NOTE(note, 32+16)
+#define QUARTER_DOT_NOTE(note) MUSICAL_NOTE(note, 16+8)
+#define EIGHTH_DOT_NOTE(note) MUSICAL_NOTE(note, 8+4)
+#define SIXTEENTH_DOT_NOTE(note) MUSICAL_NOTE(note, 4+2)
+
+// Note Type Shortcuts
+#define M__NOTE(note, duration) MUSICAL_NOTE(note, duration)
+#define W__NOTE(n) WHOLE_NOTE(n)
+#define H__NOTE(n) HALF_NOTE(n)
+#define Q__NOTE(n) QUARTER_NOTE(n)
+#define E__NOTE(n) EIGHTH_NOTE(n)
+#define S__NOTE(n) SIXTEENTH_NOTE(n)
+#define WD_NOTE(n) WHOLE_DOT_NOTE(n)
+#define HD_NOTE(n) HALF_DOT_NOTE(n)
+#define QD_NOTE(n) QUARTER_DOT_NOTE(n)
+#define ED_NOTE(n) EIGHTH_DOT_NOTE(n)
+#define SD_NOTE(n) SIXTEENTH_DOT_NOTE(n)
+
+// Note Styles
+// Staccato makes sure there is a rest between each note. Think: TA TA TA
+// Legato makes notes flow together. Think: TAAA
+#define STACCATO 0.01
+#define LEGATO 0
+
+// Note Timbre
+// Changes how the notes sound
+#define TIMBRE_12 0.125
+#define TIMBRE_25 0.250
+#define TIMBRE_50 0.500
+#define TIMBRE_75 0.750
+#define TIMBRE_DEFAULT TIMBRE_50
+
+
+// Notes - # = Octave
+
+#define NOTE_REST 0.00
+
+/* These notes are currently bugged
+#define NOTE_C0 16.35
+#define NOTE_CS0 17.32
+#define NOTE_D0 18.35
+#define NOTE_DS0 19.45
+#define NOTE_E0 20.60
+#define NOTE_F0 21.83
+#define NOTE_FS0 23.12
+#define NOTE_G0 24.50
+#define NOTE_GS0 25.96
+#define NOTE_A0 27.50
+#define NOTE_AS0 29.14
+#define NOTE_B0 30.87
+#define NOTE_C1 32.70
+#define NOTE_CS1 34.65
+#define NOTE_D1 36.71
+#define NOTE_DS1 38.89
+#define NOTE_E1 41.20
+#define NOTE_F1 43.65
+#define NOTE_FS1 46.25
+#define NOTE_G1 49.00
+#define NOTE_GS1 51.91
+#define NOTE_A1 55.00
+#define NOTE_AS1 58.27
+*/
+
+#define NOTE_B1 61.74
+#define NOTE_C2 65.41
+#define NOTE_CS2 69.30
+#define NOTE_D2 73.42
+#define NOTE_DS2 77.78
+#define NOTE_E2 82.41
+#define NOTE_F2 87.31
+#define NOTE_FS2 92.50
+#define NOTE_G2 98.00
+#define NOTE_GS2 103.83
+#define NOTE_A2 110.00
+#define NOTE_AS2 116.54
+#define NOTE_B2 123.47
+#define NOTE_C3 130.81
+#define NOTE_CS3 138.59
+#define NOTE_D3 146.83
+#define NOTE_DS3 155.56
+#define NOTE_E3 164.81
+#define NOTE_F3 174.61
+#define NOTE_FS3 185.00
+#define NOTE_G3 196.00
+#define NOTE_GS3 207.65
+#define NOTE_A3 220.00
+#define NOTE_AS3 233.08
+#define NOTE_B3 246.94
+#define NOTE_C4 261.63
+#define NOTE_CS4 277.18
+#define NOTE_D4 293.66
+#define NOTE_DS4 311.13
+#define NOTE_E4 329.63
+#define NOTE_F4 349.23
+#define NOTE_FS4 369.99
+#define NOTE_G4 392.00
+#define NOTE_GS4 415.30
+#define NOTE_A4 440.00
+#define NOTE_AS4 466.16
+#define NOTE_B4 493.88
+#define NOTE_C5 523.25
+#define NOTE_CS5 554.37
+#define NOTE_D5 587.33
+#define NOTE_DS5 622.25
+#define NOTE_E5 659.26
+#define NOTE_F5 698.46
+#define NOTE_FS5 739.99
+#define NOTE_G5 783.99
+#define NOTE_GS5 830.61
+#define NOTE_A5 880.00
+#define NOTE_AS5 932.33
+#define NOTE_B5 987.77
+#define NOTE_C6 1046.50
+#define NOTE_CS6 1108.73
+#define NOTE_D6 1174.66
+#define NOTE_DS6 1244.51
+#define NOTE_E6 1318.51
+#define NOTE_F6 1396.91
+#define NOTE_FS6 1479.98
+#define NOTE_G6 1567.98
+#define NOTE_GS6 1661.22
+#define NOTE_A6 1760.00
+#define NOTE_AS6 1864.66
+#define NOTE_B6 1975.53
+#define NOTE_C7 2093.00
+#define NOTE_CS7 2217.46
+#define NOTE_D7 2349.32
+#define NOTE_DS7 2489.02
+#define NOTE_E7 2637.02
+#define NOTE_F7 2793.83
+#define NOTE_FS7 2959.96
+#define NOTE_G7 3135.96
+#define NOTE_GS7 3322.44
+#define NOTE_A7 3520.00
+#define NOTE_AS7 3729.31
+#define NOTE_B7 3951.07
+#define NOTE_C8 4186.01
+#define NOTE_CS8 4434.92
+#define NOTE_D8 4698.64
+#define NOTE_DS8 4978.03
+#define NOTE_E8 5274.04
+#define NOTE_F8 5587.65
+#define NOTE_FS8 5919.91
+#define NOTE_G8 6271.93
+#define NOTE_GS8 6644.88
+#define NOTE_A8 7040.00
+#define NOTE_AS8 7458.62
+#define NOTE_B8 7902.13
+
+// Flat Aliases
+#define NOTE_DF0 NOTE_CS0
+#define NOTE_EF0 NOTE_DS0
+#define NOTE_GF0 NOTE_FS0
+#define NOTE_AF0 NOTE_GS0
+#define NOTE_BF0 NOTE_AS0
+#define NOTE_DF1 NOTE_CS1
+#define NOTE_EF1 NOTE_DS1
+#define NOTE_GF1 NOTE_FS1
+#define NOTE_AF1 NOTE_GS1
+#define NOTE_BF1 NOTE_AS1
+#define NOTE_DF2 NOTE_CS2
+#define NOTE_EF2 NOTE_DS2
+#define NOTE_GF2 NOTE_FS2
+#define NOTE_AF2 NOTE_GS2
+#define NOTE_BF2 NOTE_AS2
+#define NOTE_DF3 NOTE_CS3
+#define NOTE_EF3 NOTE_DS3
+#define NOTE_GF3 NOTE_FS3
+#define NOTE_AF3 NOTE_GS3
+#define NOTE_BF3 NOTE_AS3
+#define NOTE_DF4 NOTE_CS4
+#define NOTE_EF4 NOTE_DS4
+#define NOTE_GF4 NOTE_FS4
+#define NOTE_AF4 NOTE_GS4
+#define NOTE_BF4 NOTE_AS4
+#define NOTE_DF5 NOTE_CS5
+#define NOTE_EF5 NOTE_DS5
+#define NOTE_GF5 NOTE_FS5
+#define NOTE_AF5 NOTE_GS5
+#define NOTE_BF5 NOTE_AS5
+#define NOTE_DF6 NOTE_CS6
+#define NOTE_EF6 NOTE_DS6
+#define NOTE_GF6 NOTE_FS6
+#define NOTE_AF6 NOTE_GS6
+#define NOTE_BF6 NOTE_AS6
+#define NOTE_DF7 NOTE_CS7
+#define NOTE_EF7 NOTE_DS7
+#define NOTE_GF7 NOTE_FS7
+#define NOTE_AF7 NOTE_GS7
+#define NOTE_BF7 NOTE_AS7
+#define NOTE_DF8 NOTE_CS8
+#define NOTE_EF8 NOTE_DS8
+#define NOTE_GF8 NOTE_FS8
+#define NOTE_AF8 NOTE_GS8
+#define NOTE_BF8 NOTE_AS8
+
+
+#endif \ No newline at end of file
diff --git a/quantum/quantum.mk b/quantum/quantum.mk
index de93af7e8c..1fe7390eba 100644
--- a/quantum/quantum.mk
+++ b/quantum/quantum.mk
@@ -23,19 +23,19 @@ ifndef CUSTOM_MATRIX
SRC += $(QUANTUM_DIR)/matrix.c
endif
-ifdef MIDI_ENABLE
+ifeq ($(strip $(MIDI_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/keymap_midi.c
endif
-ifdef AUDIO_ENABLE
+ifeq ($(strip $(AUDIO_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/audio.c
endif
-ifdef UNICODE_ENABLE
+ifeq ($(strip $(UNICODE_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/keymap_unicode.c
endif
-ifdef RGBLIGHT_ENABLE
+ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/light_ws2812.c
SRC += $(QUANTUM_DIR)/rgblight.c
OPT_DEFS += -DRGBLIGHT_ENABLE
@@ -46,6 +46,7 @@ endif
# Search Path
VPATH += $(TOP_DIR)/$(QUANTUM_DIR)
+VPATH += $(TOP_DIR)/$(QUANTUM_DIR)/keymap_extras
include $(TMK_DIR)/protocol/lufa.mk
diff --git a/quantum/song_list.h b/quantum/song_list.h
new file mode 100644
index 0000000000..e992bd18a2
--- /dev/null
+++ b/quantum/song_list.h
@@ -0,0 +1,101 @@
+#include "musical_notes.h"
+
+#ifndef SONG_LIST_H
+#define SONG_LIST_H
+
+#define ODE_TO_JOY \
+ Q__NOTE(_E4), Q__NOTE(_E4), Q__NOTE(_F4), Q__NOTE(_G4), \
+ Q__NOTE(_G4), Q__NOTE(_F4), Q__NOTE(_E4), Q__NOTE(_D4), \
+ Q__NOTE(_C4), Q__NOTE(_C4), Q__NOTE(_D4), Q__NOTE(_E4), \
+ QD_NOTE(_E4), E__NOTE(_D4), H__NOTE(_D4),
+
+#define ROCK_A_BYE_BABY \
+ QD_NOTE(_B4), E__NOTE(_D4), Q__NOTE(_B5), \
+ H__NOTE(_A5), Q__NOTE(_G5), \
+ QD_NOTE(_B4), E__NOTE(_D5), Q__NOTE(_G5), \
+ H__NOTE(_FS5),
+
+#define CLOSE_ENCOUNTERS_5_NOTE \
+ Q__NOTE(_D5), \
+ Q__NOTE(_E5), \
+ Q__NOTE(_C5), \
+ Q__NOTE(_C4), \
+ Q__NOTE(_G4),
+
+#define DOE_A_DEER \
+ QD_NOTE(_C4), E__NOTE(_D4), \
+ QD_NOTE(_E4), E__NOTE(_C4), \
+ Q__NOTE(_E4), Q__NOTE(_C4), \
+ Q__NOTE(_E4),
+
+#define GOODBYE_SOUND \
+ E__NOTE(_E7), \
+ E__NOTE(_A6), \
+ ED_NOTE(_E6),
+
+#define STARTUP_SOUND \
+ ED_NOTE(_E7 ), \
+ E__NOTE(_CS7), \
+ E__NOTE(_E6 ), \
+ E__NOTE(_A6 ), \
+ M__NOTE(_CS7, 20),
+
+#define QWERTY_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ Q__NOTE(_E7 ),
+
+#define COLEMAK_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_E7 ), \
+ S__NOTE(_REST), \
+ ED_NOTE(_GS7 ),
+
+#define DVORAK_SOUND \
+ E__NOTE(_GS6 ), \
+ E__NOTE(_A6 ), \
+ S__NOTE(_REST), \
+ E__NOTE(_E7 ), \
+ S__NOTE(_REST), \
+ E__NOTE(_FS7 ), \
+ S__NOTE(_REST), \
+ E__NOTE(_E7 ),
+
+#define MUSIC_SCALE_SOUND \
+ E__NOTE(_A5 ), \
+ E__NOTE(_B5 ), \
+ E__NOTE(_CS6), \
+ E__NOTE(_D6 ), \
+ E__NOTE(_E6 ), \
+ E__NOTE(_FS6), \
+ E__NOTE(_GS6), \
+ E__NOTE(_A6 ),
+
+#define CAPS_LOCK_ON_SOUND \
+ E__NOTE(_A3), \
+ E__NOTE(_B3),
+
+#define CAPS_LOCK_OFF_SOUND \
+ E__NOTE(_B3), \
+ E__NOTE(_A3),
+
+#define SCROLL_LOCK_ON_SOUND \
+ E__NOTE(_D4), \
+ E__NOTE(_E4),
+
+#define SCROLL_LOCK_OFF_SOUND \
+ E__NOTE(_E4), \
+ E__NOTE(_D4),
+
+#define NUM_LOCK_ON_SOUND \
+ E__NOTE(_D5), \
+ E__NOTE(_E5),
+
+#define NUM_LOCK_OFF_SOUND \
+ E__NOTE(_E5), \
+ E__NOTE(_D5),
+
+#endif
diff --git a/quantum/tools/README.md b/quantum/tools/README.md
new file mode 100644
index 0000000000..0702144238
--- /dev/null
+++ b/quantum/tools/README.md
@@ -0,0 +1,6 @@
+`eeprom_reset.hex` is to reset the eeprom on the Atmega32u4, like this:
+
+ dfu-programmer atmega32u4 erase
+ dfu-programmer atmega32u4 flash --eeprom eeprom-reset.bin
+
+ You'll need to reflash afterwards, because DFU requires the flash to be erased before messing with the eeprom. \ No newline at end of file
diff --git a/quantum/tools/eeprom_reset.hex b/quantum/tools/eeprom_reset.hex
new file mode 100644
index 0000000000..a8a75389fe
--- /dev/null
+++ b/quantum/tools/eeprom_reset.hex
@@ -0,0 +1,9 @@
+:10000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
+:10001000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
+:10002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
+:10003000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
+:10004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
+:10005000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
+:10006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
+:10007000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
+:00000001FF