From 5ae1411fc387a682d3e22f5cddfe1102e3312af5 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Thu, 16 Feb 2017 20:49:02 -0800 Subject: [PATCH 01/20] Expand MIDI key codes --- quantum/quantum_keycodes.h | 114 ++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 63b626926..3728fa366 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -107,10 +107,122 @@ enum quantum_keycodes { MUV_IN, MUV_DE, - // Midi mode on/off +#ifdef MIDI_ENABLE + // Midi MIDI_ON, MIDI_OFF, + MIDI_TONE_MIN, + + MI_C = MIDI_TONE_MIN, + MI_Cs, + MI_Db = MI_Cs, + MI_D, + MI_Ds, + MI_Eb = MI_Ds, + MI_E, + MI_F, + MI_Fs, + MI_Gb = MI_Fs, + MI_G, + MI_Gs, + MI_Ab = MI_Gs, + MI_A, + MI_As, + MI_Bb = MI_As, + MI_B, + + MI_C_1, + MI_Cs_1, + MI_Db_1 = MI_Cs_1, + MI_D_1, + MI_Ds_1, + MI_Eb_1 = MI_Ds_1, + MI_E_1, + MI_F_1, + MI_Fs_1, + MI_Gb_1 = MI_Fs_1, + MI_G_1, + MI_Gs_1, + MI_Ab_1 = MI_Gs_1, + MI_A_1, + MI_As_1, + MI_Bb_1 = MI_As_1, + MI_B_1, + + MI_C_2, + MI_Cs_2, + MI_Db_2 = MI_Cs_2, + MI_D_2, + MI_Ds_2, + MI_Eb_2 = MI_Ds_2, + MI_E_2, + MI_F_2, + MI_Fs_2, + MI_Gb_2 = MI_Fs_2, + MI_G_2, + MI_Gs_2, + MI_Ab_2 = MI_Gs_2, + MI_A_2, + MI_As_2, + MI_Bb_2 = MI_As_2, + MI_B_2, + + MIDI_TONE_MAX = MI_B_2, + + MIDI_OCTAVE_MIN, + MI_OCT_N2 = MIDI_OCTAVE_MIN, + MI_OCT_N1, + MI_OCT_0, + MI_OCT_1, + MI_OCT_2, + MI_OCT_3, + MI_OCT_4, + MI_OCT_5, + MI_OCT_6, + MI_OCT_7, + MIDI_OCTAVE_MAX = MI_OCT_7, + MI_OCTD, // octave down + MI_OCTU, // octave up + + MIDI_VELOCITY_MIN, + MI_VEL_1 = MIDI_VELOCITY_MIN, + MI_VEL_2, + MI_VEL_3, + MI_VEL_5, + MI_VEL_6, + MI_VEL_7, + MI_VEL_8, + MI_VEL_9, + MI_VEL_10, + MIDI_VELOCITY_MAX = MI_VEL_10, + MI_VELD, // velocity down + MI_VELU, // velocity up + + MIDI_CHANNEL_MIN, + MI_CH1 = MIDI_CHANNEL_MIN, + MI_CH2, + MI_CH3, + MI_CH4, + MI_CH5, + MI_CH6, + MI_CH7, + MI_CH8, + MI_CH9, + MI_CH10, + MI_CH11, + MI_CH12, + MI_CH13, + MI_CH14, + MI_CH15, + MI_CH16, + MIDI_CHANNEL_MAX = MI_CH16, + MI_CHD, // previous channel + MI_CHU, // next channel + + MI_SUS, // sustain +#endif + // Backlight functionality BL_0, BL_1, From e405ab4bc6ff47d189d99c4d51aadf60a642d82a Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 03:12:13 -0800 Subject: [PATCH 02/20] initial implementation of polyphony using variable length array of notes on --- quantum/process_keycode/process_midi.c | 199 ++++++++++++++++++++++++- quantum/process_keycode/process_midi.h | 3 + quantum/quantum_keycodes.h | 1 + tmk_core/protocol/lufa/lufa.c | 13 +- tmk_core/protocol/lufa/lufa.h | 2 +- 5 files changed, 211 insertions(+), 7 deletions(-) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 577dad43a..bc48b3905 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -1,10 +1,204 @@ #include "process_midi.h" +#if 0 bool midi_activated = false; uint8_t midi_starting_note = 0x0C; int midi_offset = 7; +#endif -bool process_midi(uint16_t keycode, keyrecord_t *record) { +typedef union { + uint16_t raw; + struct { + uint8_t octave :4; + uint8_t velocity :4; + uint8_t channel :4; + }; +} midi_config_t; + +midi_config_t midi_config; + +#define MIDI_INVALID_NOTE 0xFF + +#if 0 +typedef struct { + uint64_t low; + uint64_t high; +} uint128_t; + +#if 0 +static void right_shift_uint128_t(uint128_t* val, uint8_t shift) +{ + uint64_t high_mask = ~0 >> (64 - shift); + uint64_t high_bits = (val->high & high_mask) << (64 - shift); + val->high = val->high >> shift; + val->low = (val->low >> shift) | high_bits; +} +#endif + +static uint64_t left_shift_uint64_t(uint64_t val, uint8_t shift) +{ + dprintf("left_shift_uint64_t(val, %c) ...\n", val, shift); + while (shift > 16u) { + dprintf(" left_shift_uint64_t: val=?, shift=%c\n", val, shift); + val <<= 16; + shift -= 16; + } + dprintf(" left_shift_uint64_t: val=?, shift=%c\n", val, shift); + val <<= shift; + return val; +} + +static void set_bit_uint128_t(uint128_t* val, uint8_t shift) +{ + uint64_t x = 1u; + + if (shift < 64) + { + x = left_shift_uint64_t(x, shift); + dprintf("x: %d\n", x); + dprintf("set_bit_uint128_t (%d): 0x%016X%016X\n", shift, 0, x); + val->low = val->low | left_shift_uint64_t(1u, shift); + } + else + { + x = left_shift_uint64_t(x, shift - 64); + dprintf("set_bit_uint128_t (%d): 0x%016X%016X\n", shift, x, 0); + val->high = val->high | left_shift_uint64_t(1u, shift - 64); + } +} + +static void clear_bit_uint128_t(uint128_t* val, uint8_t shift) +{ + if (shift < 64) + { + val->low = val->low & ~left_shift_uint64_t(1u, shift); + } + else + { + val->high = val->high & ~left_shift_uint64_t(1u, shift - 64); + } +} + +static bool is_bit_set_uint128_t(const uint128_t* val, uint8_t shift) +{ + if (shift < 64) + { + return !!(val->low & (1u << shift)); + } + else + { + return !!(val->high & (1u << (shift - 64))); + } +} + +uint128_t note_status = { 0, 0 }; +#endif + + +#define MIDI_MAX_NOTES_ON 10 + +typedef struct { + uint8_t note; + uint8_t tone; +} midi_notes_on_array_entry_t; + +typedef struct { + uint8_t length; + midi_notes_on_array_entry_t values[MIDI_MAX_NOTES_ON]; +} midi_notes_on_array_t; + +static midi_notes_on_array_t notes_on; + +inline uint8_t compute_velocity(uint8_t setting) +{ + return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); +} + +void midi_init(void) +{ + midi_config.octave = MI_OCT_0 - MIDI_OCTAVE_MIN; + midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); + midi_config.channel = 0; + notes_on.length = 0; +} + +bool process_midi(uint16_t keycode, keyrecord_t *record) +{ + switch (keycode) { + case MIDI_TONE_MIN ... MIDI_TONE_MAX: + { + uint8_t channel = midi_config.channel; + uint8_t tone = keycode - MIDI_TONE_MIN; + uint8_t velocity = compute_velocity(midi_config.velocity); + if (record->event.pressed && notes_on.length < MIDI_MAX_NOTES_ON) { + uint8_t note = 12 * midi_config.octave + tone; + midi_send_noteon(&midi_device, channel, note, velocity); + dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); + notes_on.values[notes_on.length].note = note; + notes_on.values[notes_on.length].tone = tone; + notes_on.length++; + } + else { + for (uint8_t i = 0; i < notes_on.length; i++) { + uint8_t note = notes_on.values[i].note; + if (tone == notes_on.values[i].tone) { + midi_send_noteoff(&midi_device, channel, note, velocity); + dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity); + + for (uint8_t j=i; j < notes_on.length - 1; j++) + { + notes_on.values[j] = notes_on.values[j + 1]; + } + + notes_on.length--; + break; + } + } + } + return false; + } + case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX: + if (record->event.pressed) + midi_config.octave = keycode - MIDI_OCTAVE_MIN; + return false; + case MI_OCTD: + if (record->event.pressed && midi_config.octave > 0) + midi_config.octave--; + return false; + case MI_OCTU: + if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) + midi_config.octave++; + return false; + case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX: + if (record->event.pressed) + midi_config.velocity = keycode - MIDI_VELOCITY_MIN; + return false; + case MI_VELD: + if (record->event.pressed && midi_config.velocity > 0) + midi_config.velocity--; + return false; + case MI_VELU: + if (record->event.pressed) + midi_config.velocity++; + return false; + case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX: + if (record->event.pressed) + midi_config.channel = keycode - MIDI_CHANNEL_MIN; + return false; + case MI_CHD: + if (record->event.pressed) + midi_config.channel--; + return false; + case MI_CHU: + if (record->event.pressed) + midi_config.channel++; + return false; + case MI_SUS: + //TODO + return false; + }; + +#if 0 if (keycode == MI_ON && record->event.pressed) { midi_activated = true; #ifdef AUDIO_ENABLE @@ -64,5 +258,6 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) { if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through return false; } - return true; +#endif + return true; } diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index acd4fc1b1..b0e0aeb83 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -2,6 +2,9 @@ #define PROCESS_MIDI_H #include "quantum.h" +#include "midi.h" + +void midi_init(void); bool process_midi(uint16_t keycode, keyrecord_t *record); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 3728fa366..a024a9639 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -189,6 +189,7 @@ enum quantum_keycodes { MI_VEL_1 = MIDI_VELOCITY_MIN, MI_VEL_2, MI_VEL_3, + MI_VEL_4, MI_VEL_5, MI_VEL_6, MI_VEL_7, diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index ba49284c9..fb60658df 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1101,16 +1101,21 @@ void cc_callback(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t val); void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data); + +void setup_midi(void) +{ + midi_init(); + midi_device_init(&midi_device); + midi_device_set_send_func(&midi_device, usb_send_func); + midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); +} #endif int main(void) __attribute__ ((weak)); int main(void) { - #ifdef MIDI_ENABLE - midi_device_init(&midi_device); - midi_device_set_send_func(&midi_device, usb_send_func); - midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); + setup_midi(); #endif setup_mcu(); diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h index a049fd43c..a51573786 100644 --- a/tmk_core/protocol/lufa/lufa.h +++ b/tmk_core/protocol/lufa/lufa.h @@ -49,7 +49,7 @@ #include #include "host.h" #ifdef MIDI_ENABLE - #include "midi.h" + #include "process_midi.h" #endif #ifdef __cplusplus extern "C" { From f2b2e05f126403c8a6f0fc3d542beddac7974e9b Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 03:13:43 -0800 Subject: [PATCH 03/20] clean up commented code --- quantum/process_keycode/process_midi.c | 137 ------------------------- 1 file changed, 137 deletions(-) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index bc48b3905..acaae7c30 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -19,82 +19,6 @@ midi_config_t midi_config; #define MIDI_INVALID_NOTE 0xFF -#if 0 -typedef struct { - uint64_t low; - uint64_t high; -} uint128_t; - -#if 0 -static void right_shift_uint128_t(uint128_t* val, uint8_t shift) -{ - uint64_t high_mask = ~0 >> (64 - shift); - uint64_t high_bits = (val->high & high_mask) << (64 - shift); - val->high = val->high >> shift; - val->low = (val->low >> shift) | high_bits; -} -#endif - -static uint64_t left_shift_uint64_t(uint64_t val, uint8_t shift) -{ - dprintf("left_shift_uint64_t(val, %c) ...\n", val, shift); - while (shift > 16u) { - dprintf(" left_shift_uint64_t: val=?, shift=%c\n", val, shift); - val <<= 16; - shift -= 16; - } - dprintf(" left_shift_uint64_t: val=?, shift=%c\n", val, shift); - val <<= shift; - return val; -} - -static void set_bit_uint128_t(uint128_t* val, uint8_t shift) -{ - uint64_t x = 1u; - - if (shift < 64) - { - x = left_shift_uint64_t(x, shift); - dprintf("x: %d\n", x); - dprintf("set_bit_uint128_t (%d): 0x%016X%016X\n", shift, 0, x); - val->low = val->low | left_shift_uint64_t(1u, shift); - } - else - { - x = left_shift_uint64_t(x, shift - 64); - dprintf("set_bit_uint128_t (%d): 0x%016X%016X\n", shift, x, 0); - val->high = val->high | left_shift_uint64_t(1u, shift - 64); - } -} - -static void clear_bit_uint128_t(uint128_t* val, uint8_t shift) -{ - if (shift < 64) - { - val->low = val->low & ~left_shift_uint64_t(1u, shift); - } - else - { - val->high = val->high & ~left_shift_uint64_t(1u, shift - 64); - } -} - -static bool is_bit_set_uint128_t(const uint128_t* val, uint8_t shift) -{ - if (shift < 64) - { - return !!(val->low & (1u << shift)); - } - else - { - return !!(val->high & (1u << (shift - 64))); - } -} - -uint128_t note_status = { 0, 0 }; -#endif - - #define MIDI_MAX_NOTES_ON 10 typedef struct { @@ -198,66 +122,5 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) return false; }; -#if 0 - if (keycode == MI_ON && record->event.pressed) { - midi_activated = true; -#ifdef AUDIO_ENABLE - music_scale_user(); -#endif - return false; - } - - if (keycode == MI_OFF && record->event.pressed) { - midi_activated = false; - midi_send_cc(&midi_device, 0, 0x7B, 0); - return false; - } - - if (midi_activated) { - if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) { - if (record->event.pressed) { - midi_starting_note++; // Change key - midi_send_cc(&midi_device, 0, 0x7B, 0); - } - return false; - } - if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) { - if (record->event.pressed) { - midi_starting_note--; // Change key - midi_send_cc(&midi_device, 0, 0x7B, 0); - } - return false; - } - if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { - midi_offset++; // Change scale - midi_send_cc(&midi_device, 0, 0x7B, 0); - return false; - } - if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { - midi_offset--; // Change scale - midi_send_cc(&midi_device, 0, 0x7B, 0); - return false; - } - // basic - // uint8_t note = (midi_starting_note + SCALE[record->event.key.col + midi_offset])+12*(MATRIX_ROWS - record->event.key.row); - // advanced - // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+12*(MATRIX_ROWS - record->event.key.row); - // guitar - uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+5*(MATRIX_ROWS - record->event.key.row); - // violin - // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+7*(MATRIX_ROWS - record->event.key.row); - - if (record->event.pressed) { - // midi_send_noteon(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127); - midi_send_noteon(&midi_device, 0, note, 127); - } else { - // midi_send_noteoff(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127); - midi_send_noteoff(&midi_device, 0, note, 127); - } - - if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through - return false; - } -#endif return true; } From a4163466cb09144a96e2ea7bc697af1af8a5e770 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 03:40:49 -0800 Subject: [PATCH 04/20] Alternative version with a tone array tone array: text data bss dec hex filename 0 25698 0 25698 6462 satan_newsboytko.hex 0x6480 bytes written into 0x7000 bytes memory (89.73%). note on array: text data bss dec hex filename 0 25802 0 25802 64ca satan_newsboytko.hex 0x6500 bytes written into 0x7000 bytes memory (90.18%). --- quantum/process_keycode/process_midi.c | 109 +++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index acaae7c30..4fbb28816 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -19,6 +19,10 @@ midi_config_t midi_config; #define MIDI_INVALID_NOTE 0xFF +#define MIDI_USE_NOTE_ON_ARRAY + +#ifdef MIDI_USE_NOTE_ON_ARRAY + #define MIDI_MAX_NOTES_ON 10 typedef struct { @@ -33,6 +37,15 @@ typedef struct { static midi_notes_on_array_t notes_on; +#else + +#define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1) +static uint8_t tone_status[MIDI_TONE_COUNT]; + +#endif + + + inline uint8_t compute_velocity(uint8_t setting) { return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); @@ -43,7 +56,14 @@ void midi_init(void) midi_config.octave = MI_OCT_0 - MIDI_OCTAVE_MIN; midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); midi_config.channel = 0; + #ifdef MIDI_USE_NOTE_ON_ARRAY notes_on.length = 0; + #else + for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++) + { + tone_status[i] = MIDI_INVALID_NOTE; + } + #endif } bool process_midi(uint16_t keycode, keyrecord_t *record) @@ -54,15 +74,31 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) uint8_t channel = midi_config.channel; uint8_t tone = keycode - MIDI_TONE_MIN; uint8_t velocity = compute_velocity(midi_config.velocity); + #ifdef MIDI_USE_NOTE_ON_ARRAY if (record->event.pressed && notes_on.length < MIDI_MAX_NOTES_ON) { + #else + if (record->event.pressed) { + #endif uint8_t note = 12 * midi_config.octave + tone; midi_send_noteon(&midi_device, channel, note, velocity); dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); + + #ifdef MIDI_USE_NOTE_ON_ARRAY + notes_on.values[notes_on.length].note = note; notes_on.values[notes_on.length].tone = tone; notes_on.length++; + + #else + + tone_status[tone] = note; + + #endif } else { + + #ifdef MIDI_USE_NOTE_ON_ARRAY + for (uint8_t i = 0; i < notes_on.length; i++) { uint8_t note = notes_on.values[i].note; if (tone == notes_on.values[i].tone) { @@ -78,6 +114,18 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) break; } } + + #else + + uint8_t note = tone_status[tone]; + if (note != MIDI_INVALID_NOTE) + { + midi_send_noteoff(&midi_device, channel, note, velocity); + dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity); + } + tone_status[tone] = MIDI_INVALID_NOTE; + + #endif } return false; } @@ -122,5 +170,66 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) return false; }; +#if 0 + if (keycode == MI_ON && record->event.pressed) { + midi_activated = true; +#ifdef AUDIO_ENABLE + music_scale_user(); +#endif + return false; + } + + if (keycode == MI_OFF && record->event.pressed) { + midi_activated = false; + midi_send_cc(&midi_device, 0, 0x7B, 0); + return false; + } + + if (midi_activated) { + if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) { + if (record->event.pressed) { + midi_starting_note++; // Change key + midi_send_cc(&midi_device, 0, 0x7B, 0); + } + return false; + } + if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) { + if (record->event.pressed) { + midi_starting_note--; // Change key + midi_send_cc(&midi_device, 0, 0x7B, 0); + } + return false; + } + if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { + midi_offset++; // Change scale + midi_send_cc(&midi_device, 0, 0x7B, 0); + return false; + } + if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { + midi_offset--; // Change scale + midi_send_cc(&midi_device, 0, 0x7B, 0); + return false; + } + // basic + // uint8_t note = (midi_starting_note + SCALE[record->event.key.col + midi_offset])+12*(MATRIX_ROWS - record->event.key.row); + // advanced + // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+12*(MATRIX_ROWS - record->event.key.row); + // guitar + uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+5*(MATRIX_ROWS - record->event.key.row); + // violin + // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+7*(MATRIX_ROWS - record->event.key.row); + + if (record->event.pressed) { + // midi_send_noteon(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127); + midi_send_noteon(&midi_device, 0, note, 127); + } else { + // midi_send_noteoff(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127); + midi_send_noteoff(&midi_device, 0, note, 127); + } + + if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through + return false; + } +#endif return true; } From f67aefc522dd8b72711e7fc5280e1cae1470d1c5 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 03:43:30 -0800 Subject: [PATCH 05/20] remove disabled code --- quantum/process_keycode/process_midi.c | 129 ------------------------- 1 file changed, 129 deletions(-) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 4fbb28816..2ce7418ea 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -1,11 +1,5 @@ #include "process_midi.h" -#if 0 -bool midi_activated = false; -uint8_t midi_starting_note = 0x0C; -int midi_offset = 7; -#endif - typedef union { uint16_t raw; struct { @@ -19,33 +13,9 @@ midi_config_t midi_config; #define MIDI_INVALID_NOTE 0xFF -#define MIDI_USE_NOTE_ON_ARRAY - -#ifdef MIDI_USE_NOTE_ON_ARRAY - -#define MIDI_MAX_NOTES_ON 10 - -typedef struct { - uint8_t note; - uint8_t tone; -} midi_notes_on_array_entry_t; - -typedef struct { - uint8_t length; - midi_notes_on_array_entry_t values[MIDI_MAX_NOTES_ON]; -} midi_notes_on_array_t; - -static midi_notes_on_array_t notes_on; - -#else - #define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1) static uint8_t tone_status[MIDI_TONE_COUNT]; -#endif - - - inline uint8_t compute_velocity(uint8_t setting) { return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); @@ -74,49 +44,13 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) uint8_t channel = midi_config.channel; uint8_t tone = keycode - MIDI_TONE_MIN; uint8_t velocity = compute_velocity(midi_config.velocity); - #ifdef MIDI_USE_NOTE_ON_ARRAY - if (record->event.pressed && notes_on.length < MIDI_MAX_NOTES_ON) { - #else if (record->event.pressed) { - #endif uint8_t note = 12 * midi_config.octave + tone; midi_send_noteon(&midi_device, channel, note, velocity); dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); - - #ifdef MIDI_USE_NOTE_ON_ARRAY - - notes_on.values[notes_on.length].note = note; - notes_on.values[notes_on.length].tone = tone; - notes_on.length++; - - #else - tone_status[tone] = note; - - #endif } else { - - #ifdef MIDI_USE_NOTE_ON_ARRAY - - for (uint8_t i = 0; i < notes_on.length; i++) { - uint8_t note = notes_on.values[i].note; - if (tone == notes_on.values[i].tone) { - midi_send_noteoff(&midi_device, channel, note, velocity); - dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity); - - for (uint8_t j=i; j < notes_on.length - 1; j++) - { - notes_on.values[j] = notes_on.values[j + 1]; - } - - notes_on.length--; - break; - } - } - - #else - uint8_t note = tone_status[tone]; if (note != MIDI_INVALID_NOTE) { @@ -124,8 +58,6 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity); } tone_status[tone] = MIDI_INVALID_NOTE; - - #endif } return false; } @@ -170,66 +102,5 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) return false; }; -#if 0 - if (keycode == MI_ON && record->event.pressed) { - midi_activated = true; -#ifdef AUDIO_ENABLE - music_scale_user(); -#endif - return false; - } - - if (keycode == MI_OFF && record->event.pressed) { - midi_activated = false; - midi_send_cc(&midi_device, 0, 0x7B, 0); - return false; - } - - if (midi_activated) { - if (record->event.key.col == (MATRIX_COLS - 1) && record->event.key.row == (MATRIX_ROWS - 1)) { - if (record->event.pressed) { - midi_starting_note++; // Change key - midi_send_cc(&midi_device, 0, 0x7B, 0); - } - return false; - } - if (record->event.key.col == (MATRIX_COLS - 2) && record->event.key.row == (MATRIX_ROWS - 1)) { - if (record->event.pressed) { - midi_starting_note--; // Change key - midi_send_cc(&midi_device, 0, 0x7B, 0); - } - return false; - } - if (record->event.key.col == (MATRIX_COLS - 3) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { - midi_offset++; // Change scale - midi_send_cc(&midi_device, 0, 0x7B, 0); - return false; - } - if (record->event.key.col == (MATRIX_COLS - 4) && record->event.key.row == (MATRIX_ROWS - 1) && record->event.pressed) { - midi_offset--; // Change scale - midi_send_cc(&midi_device, 0, 0x7B, 0); - return false; - } - // basic - // uint8_t note = (midi_starting_note + SCALE[record->event.key.col + midi_offset])+12*(MATRIX_ROWS - record->event.key.row); - // advanced - // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+12*(MATRIX_ROWS - record->event.key.row); - // guitar - uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+5*(MATRIX_ROWS - record->event.key.row); - // violin - // uint8_t note = (midi_starting_note + record->event.key.col + midi_offset)+7*(MATRIX_ROWS - record->event.key.row); - - if (record->event.pressed) { - // midi_send_noteon(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127); - midi_send_noteon(&midi_device, 0, note, 127); - } else { - // midi_send_noteoff(&midi_device, record->event.key.row, midi_starting_note + SCALE[record->event.key.col], 127); - midi_send_noteoff(&midi_device, 0, note, 127); - } - - if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through - return false; - } -#endif return true; } From 7c5e510fe2e57d1b3c0f98612f1f89d413c07525 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 04:25:17 -0800 Subject: [PATCH 06/20] add support for pedal cc messages --- quantum/process_keycode/process_midi.c | 61 +++++++++++++++++++++----- quantum/quantum_keycodes.h | 11 ++--- 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 2ce7418ea..f7a8b6650 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -62,43 +62,84 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) return false; } case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX: - if (record->event.pressed) + if (record->event.pressed) { midi_config.octave = keycode - MIDI_OCTAVE_MIN; + dprintf("midi octave %d\n", midi_config.octave); + } return false; case MI_OCTD: - if (record->event.pressed && midi_config.octave > 0) + if (record->event.pressed && midi_config.octave > 0) { midi_config.octave--; + dprintf("midi octave %d\n", midi_config.octave); + } return false; case MI_OCTU: - if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) + if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) { midi_config.octave++; + dprintf("midi octave %d\n", midi_config.octave); + } return false; case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX: - if (record->event.pressed) + if (record->event.pressed) { midi_config.velocity = keycode - MIDI_VELOCITY_MIN; + dprintf("midi velocity %d\n", midi_config.velocity); + } return false; case MI_VELD: - if (record->event.pressed && midi_config.velocity > 0) + if (record->event.pressed && midi_config.velocity > 0) { midi_config.velocity--; + dprintf("midi velocity %d\n", midi_config.velocity); + } return false; case MI_VELU: - if (record->event.pressed) + if (record->event.pressed) { midi_config.velocity++; + dprintf("midi velocity %d\n", midi_config.velocity); + } return false; case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX: - if (record->event.pressed) + if (record->event.pressed) { midi_config.channel = keycode - MIDI_CHANNEL_MIN; + dprintf("midi channel %d\n", midi_config.channel); + } return false; case MI_CHD: - if (record->event.pressed) + if (record->event.pressed) { midi_config.channel--; + dprintf("midi channel %d\n", midi_config.channel); + } return false; case MI_CHU: - if (record->event.pressed) + if (record->event.pressed) { midi_config.channel++; + dprintf("midi channel %d\n", midi_config.channel); + } + return false; + case MI_OFF: + if (record->event.pressed) { + midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0); + dprintf("midi off\n"); + } return false; case MI_SUS: - //TODO + midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0); + dprintf("midi sustain %d\n", record->event.pressed); + return false; + case MI_PORT: + midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0); + dprintf("midi portamento %d\n", record->event.pressed); + return false; + case MI_SOST: + midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0); + dprintf("midi sostenuto %d\n", record->event.pressed); + return false; + case MI_SOFT: + midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0); + dprintf("midi soft %d\n", record->event.pressed); + return false; + case MI_LEG: + midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0); + dprintf("midi legato %d\n", record->event.pressed); return false; }; diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index a024a9639..f2b9509b5 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -109,8 +109,6 @@ enum quantum_keycodes { #ifdef MIDI_ENABLE // Midi - MIDI_ON, - MIDI_OFF, MIDI_TONE_MIN, @@ -221,7 +219,13 @@ enum quantum_keycodes { MI_CHD, // previous channel MI_CHU, // next channel + MI_OFF, // all notes off + MI_SUS, // sustain + MI_PORT, // portamento + MI_SOST, // sostenuto + MI_SOFT, // soft + MI_LEG, // legato #endif // Backlight functionality @@ -394,9 +398,6 @@ enum quantum_keycodes { #define BL_ON BL_9 #define BL_OFF BL_0 -#define MI_ON MIDI_ON -#define MI_OFF MIDI_OFF - // GOTO layer - 16 layers max // when: // ON_PRESS = 1 From dd8f8e6baeb1549735403edf2a2f04f07edb4bf2 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 05:32:55 -0800 Subject: [PATCH 07/20] implement modulation --- quantum/process_keycode/process_midi.c | 58 ++++++- quantum/process_keycode/process_midi.h | 201 +------------------------ quantum/quantum_keycodes.h | 6 +- tmk_core/protocol/lufa/lufa.c | 2 +- 4 files changed, 61 insertions(+), 206 deletions(-) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index f7a8b6650..d09aa0b38 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -1,4 +1,5 @@ #include "process_midi.h" +#include "timer.h" typedef union { uint16_t raw; @@ -6,6 +7,7 @@ typedef union { uint8_t octave :4; uint8_t velocity :4; uint8_t channel :4; + uint8_t modulation_interval :4; }; } midi_config_t; @@ -16,6 +18,10 @@ midi_config_t midi_config; #define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1) static uint8_t tone_status[MIDI_TONE_COUNT]; +static uint8_t midi_modulation; +static int8_t midi_modulation_step; +static uint16_t midi_modulation_timer; + inline uint8_t compute_velocity(uint8_t setting) { return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); @@ -26,14 +32,40 @@ void midi_init(void) midi_config.octave = MI_OCT_0 - MIDI_OCTAVE_MIN; midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); midi_config.channel = 0; - #ifdef MIDI_USE_NOTE_ON_ARRAY - notes_on.length = 0; - #else + midi_config.modulation_interval = 8; + for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++) { tone_status[i] = MIDI_INVALID_NOTE; } - #endif + + midi_modulation = 0; + midi_modulation_step = 0; + midi_modulation_timer = 0; +} + +void midi_task(void) +{ + if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval) + return; + midi_modulation_timer = timer_read(); + + if (midi_modulation_step != 0) + { + dprintf("midi modulation %d\n", midi_modulation); + midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation); + + if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) { + midi_modulation = 0; + midi_modulation_step = 0; + return; + } + + midi_modulation += midi_modulation_step; + + if (midi_modulation > 127) + midi_modulation = 127; + } } bool process_midi(uint16_t keycode, keyrecord_t *record) @@ -141,6 +173,24 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0); dprintf("midi legato %d\n", record->event.pressed); return false; + case MI_MOD: + midi_modulation_step = record->event.pressed ? 1 : -1; + return false; + case MI_MODSD: + if (record->event.pressed) { + midi_config.modulation_interval++; + // prevent overflow + if (midi_config.modulation_interval == 0) + midi_config.modulation_interval--; + dprintf("midi modulation interval %d\n", midi_config.modulation_interval); + } + return false; + case MI_MODSU: + if (record->event.pressed && midi_config.modulation_interval > 0) { + midi_config.modulation_interval--; + dprintf("midi modulation interval %d\n", midi_config.modulation_interval); + } + return false; }; return true; diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index b0e0aeb83..66ce60b0e 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -5,206 +5,7 @@ #include "midi.h" void midi_init(void); - +void midi_task(void); bool process_midi(uint16_t keycode, keyrecord_t *record); -#define MIDI(n) ((n) | 0x6000) -#define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000 - -#define CHNL(note, channel) (note + (channel << 8)) - -#define SCALE (int8_t []){ 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), } - -#define N_CN1 (0x600C + (12 * -1) + 0 ) -#define N_CN1S (0x600C + (12 * -1) + 1 ) -#define N_DN1F (0x600C + (12 * -1) + 1 ) -#define N_DN1 (0x600C + (12 * -1) + 2 ) -#define N_DN1S (0x600C + (12 * -1) + 3 ) -#define N_EN1F (0x600C + (12 * -1) + 3 ) -#define N_EN1 (0x600C + (12 * -1) + 4 ) -#define N_FN1 (0x600C + (12 * -1) + 5 ) -#define N_FN1S (0x600C + (12 * -1) + 6 ) -#define N_GN1F (0x600C + (12 * -1) + 6 ) -#define N_GN1 (0x600C + (12 * -1) + 7 ) -#define N_GN1S (0x600C + (12 * -1) + 8 ) -#define N_AN1F (0x600C + (12 * -1) + 8 ) -#define N_AN1 (0x600C + (12 * -1) + 9 ) -#define N_AN1S (0x600C + (12 * -1) + 10) -#define N_BN1F (0x600C + (12 * -1) + 10) -#define N_BN1 (0x600C + (12 * -1) + 11) -#define N_C0 (0x600C + (12 * 0) + 0 ) -#define N_C0S (0x600C + (12 * 0) + 1 ) -#define N_D0F (0x600C + (12 * 0) + 1 ) -#define N_D0 (0x600C + (12 * 0) + 2 ) -#define N_D0S (0x600C + (12 * 0) + 3 ) -#define N_E0F (0x600C + (12 * 0) + 3 ) -#define N_E0 (0x600C + (12 * 0) + 4 ) -#define N_F0 (0x600C + (12 * 0) + 5 ) -#define N_F0S (0x600C + (12 * 0) + 6 ) -#define N_G0F (0x600C + (12 * 0) + 6 ) -#define N_G0 (0x600C + (12 * 0) + 7 ) -#define N_G0S (0x600C + (12 * 0) + 8 ) -#define N_A0F (0x600C + (12 * 0) + 8 ) -#define N_A0 (0x600C + (12 * 0) + 9 ) -#define N_A0S (0x600C + (12 * 0) + 10) -#define N_B0F (0x600C + (12 * 0) + 10) -#define N_B0 (0x600C + (12 * 0) + 11) -#define N_C1 (0x600C + (12 * 1) + 0 ) -#define N_C1S (0x600C + (12 * 1) + 1 ) -#define N_D1F (0x600C + (12 * 1) + 1 ) -#define N_D1 (0x600C + (12 * 1) + 2 ) -#define N_D1S (0x600C + (12 * 1) + 3 ) -#define N_E1F (0x600C + (12 * 1) + 3 ) -#define N_E1 (0x600C + (12 * 1) + 4 ) -#define N_F1 (0x600C + (12 * 1) + 5 ) -#define N_F1S (0x600C + (12 * 1) + 6 ) -#define N_G1F (0x600C + (12 * 1) + 6 ) -#define N_G1 (0x600C + (12 * 1) + 7 ) -#define N_G1S (0x600C + (12 * 1) + 8 ) -#define N_A1F (0x600C + (12 * 1) + 8 ) -#define N_A1 (0x600C + (12 * 1) + 9 ) -#define N_A1S (0x600C + (12 * 1) + 10) -#define N_B1F (0x600C + (12 * 1) + 10) -#define N_B1 (0x600C + (12 * 1) + 11) -#define N_C2 (0x600C + (12 * 2) + 0 ) -#define N_C2S (0x600C + (12 * 2) + 1 ) -#define N_D2F (0x600C + (12 * 2) + 1 ) -#define N_D2 (0x600C + (12 * 2) + 2 ) -#define N_D2S (0x600C + (12 * 2) + 3 ) -#define N_E2F (0x600C + (12 * 2) + 3 ) -#define N_E2 (0x600C + (12 * 2) + 4 ) -#define N_F2 (0x600C + (12 * 2) + 5 ) -#define N_F2S (0x600C + (12 * 2) + 6 ) -#define N_G2F (0x600C + (12 * 2) + 6 ) -#define N_G2 (0x600C + (12 * 2) + 7 ) -#define N_G2S (0x600C + (12 * 2) + 8 ) -#define N_A2F (0x600C + (12 * 2) + 8 ) -#define N_A2 (0x600C + (12 * 2) + 9 ) -#define N_A2S (0x600C + (12 * 2) + 10) -#define N_B2F (0x600C + (12 * 2) + 10) -#define N_B2 (0x600C + (12 * 2) + 11) -#define N_C3 (0x600C + (12 * 3) + 0 ) -#define N_C3S (0x600C + (12 * 3) + 1 ) -#define N_D3F (0x600C + (12 * 3) + 1 ) -#define N_D3 (0x600C + (12 * 3) + 2 ) -#define N_D3S (0x600C + (12 * 3) + 3 ) -#define N_E3F (0x600C + (12 * 3) + 3 ) -#define N_E3 (0x600C + (12 * 3) + 4 ) -#define N_F3 (0x600C + (12 * 3) + 5 ) -#define N_F3S (0x600C + (12 * 3) + 6 ) -#define N_G3F (0x600C + (12 * 3) + 6 ) -#define N_G3 (0x600C + (12 * 3) + 7 ) -#define N_G3S (0x600C + (12 * 3) + 8 ) -#define N_A3F (0x600C + (12 * 3) + 8 ) -#define N_A3 (0x600C + (12 * 3) + 9 ) -#define N_A3S (0x600C + (12 * 3) + 10) -#define N_B3F (0x600C + (12 * 3) + 10) -#define N_B3 (0x600C + (12 * 3) + 11) -#define N_C4 (0x600C + (12 * 4) + 0 ) -#define N_C4S (0x600C + (12 * 4) + 1 ) -#define N_D4F (0x600C + (12 * 4) + 1 ) -#define N_D4 (0x600C + (12 * 4) + 2 ) -#define N_D4S (0x600C + (12 * 4) + 3 ) -#define N_E4F (0x600C + (12 * 4) + 3 ) -#define N_E4 (0x600C + (12 * 4) + 4 ) -#define N_F4 (0x600C + (12 * 4) + 5 ) -#define N_F4S (0x600C + (12 * 4) + 6 ) -#define N_G4F (0x600C + (12 * 4) + 6 ) -#define N_G4 (0x600C + (12 * 4) + 7 ) -#define N_G4S (0x600C + (12 * 4) + 8 ) -#define N_A4F (0x600C + (12 * 4) + 8 ) -#define N_A4 (0x600C + (12 * 4) + 9 ) -#define N_A4S (0x600C + (12 * 4) + 10) -#define N_B4F (0x600C + (12 * 4) + 10) -#define N_B4 (0x600C + (12 * 4) + 11) -#define N_C5 (0x600C + (12 * 5) + 0 ) -#define N_C5S (0x600C + (12 * 5) + 1 ) -#define N_D5F (0x600C + (12 * 5) + 1 ) -#define N_D5 (0x600C + (12 * 5) + 2 ) -#define N_D5S (0x600C + (12 * 5) + 3 ) -#define N_E5F (0x600C + (12 * 5) + 3 ) -#define N_E5 (0x600C + (12 * 5) + 4 ) -#define N_F5 (0x600C + (12 * 5) + 5 ) -#define N_F5S (0x600C + (12 * 5) + 6 ) -#define N_G5F (0x600C + (12 * 5) + 6 ) -#define N_G5 (0x600C + (12 * 5) + 7 ) -#define N_G5S (0x600C + (12 * 5) + 8 ) -#define N_A5F (0x600C + (12 * 5) + 8 ) -#define N_A5 (0x600C + (12 * 5) + 9 ) -#define N_A5S (0x600C + (12 * 5) + 10) -#define N_B5F (0x600C + (12 * 5) + 10) -#define N_B5 (0x600C + (12 * 5) + 11) -#define N_C6 (0x600C + (12 * 6) + 0 ) -#define N_C6S (0x600C + (12 * 6) + 1 ) -#define N_D6F (0x600C + (12 * 6) + 1 ) -#define N_D6 (0x600C + (12 * 6) + 2 ) -#define N_D6S (0x600C + (12 * 6) + 3 ) -#define N_E6F (0x600C + (12 * 6) + 3 ) -#define N_E6 (0x600C + (12 * 6) + 4 ) -#define N_F6 (0x600C + (12 * 6) + 5 ) -#define N_F6S (0x600C + (12 * 6) + 6 ) -#define N_G6F (0x600C + (12 * 6) + 6 ) -#define N_G6 (0x600C + (12 * 6) + 7 ) -#define N_G6S (0x600C + (12 * 6) + 8 ) -#define N_A6F (0x600C + (12 * 6) + 8 ) -#define N_A6 (0x600C + (12 * 6) + 9 ) -#define N_A6S (0x600C + (12 * 6) + 10) -#define N_B6F (0x600C + (12 * 6) + 10) -#define N_B6 (0x600C + (12 * 6) + 11) -#define N_C7 (0x600C + (12 * 7) + 0 ) -#define N_C7S (0x600C + (12 * 7) + 1 ) -#define N_D7F (0x600C + (12 * 7) + 1 ) -#define N_D7 (0x600C + (12 * 7) + 2 ) -#define N_D7S (0x600C + (12 * 7) + 3 ) -#define N_E7F (0x600C + (12 * 7) + 3 ) -#define N_E7 (0x600C + (12 * 7) + 4 ) -#define N_F7 (0x600C + (12 * 7) + 5 ) -#define N_F7S (0x600C + (12 * 7) + 6 ) -#define N_G7F (0x600C + (12 * 7) + 6 ) -#define N_G7 (0x600C + (12 * 7) + 7 ) -#define N_G7S (0x600C + (12 * 7) + 8 ) -#define N_A7F (0x600C + (12 * 7) + 8 ) -#define N_A7 (0x600C + (12 * 7) + 9 ) -#define N_A7S (0x600C + (12 * 7) + 10) -#define N_B7F (0x600C + (12 * 7) + 10) -#define N_B7 (0x600C + (12 * 7) + 11) -#define N_C8 (0x600C + (12 * 8) + 0 ) -#define N_C8S (0x600C + (12 * 8) + 1 ) -#define N_D8F (0x600C + (12 * 8) + 1 ) -#define N_D8 (0x600C + (12 * 8) + 2 ) -#define N_D8S (0x600C + (12 * 8) + 3 ) -#define N_E8F (0x600C + (12 * 8) + 3 ) -#define N_E8 (0x600C + (12 * 8) + 4 ) -#define N_F8 (0x600C + (12 * 8) + 5 ) -#define N_F8S (0x600C + (12 * 8) + 6 ) -#define N_G8F (0x600C + (12 * 8) + 6 ) -#define N_G8 (0x600C + (12 * 8) + 7 ) -#define N_G8S (0x600C + (12 * 8) + 8 ) -#define N_A8F (0x600C + (12 * 8) + 8 ) -#define N_A8 (0x600C + (12 * 8) + 9 ) -#define N_A8S (0x600C + (12 * 8) + 10) -#define N_B8F (0x600C + (12 * 8) + 10) -#define N_B8 (0x600C + (12 * 8) + 11) -#define N_C8 (0x600C + (12 * 8) + 0 ) -#define N_C8S (0x600C + (12 * 8) + 1 ) -#define N_D8F (0x600C + (12 * 8) + 1 ) -#define N_D8 (0x600C + (12 * 8) + 2 ) -#define N_D8S (0x600C + (12 * 8) + 3 ) -#define N_E8F (0x600C + (12 * 8) + 3 ) -#define N_E8 (0x600C + (12 * 8) + 4 ) -#define N_F8 (0x600C + (12 * 8) + 5 ) -#define N_F8S (0x600C + (12 * 8) + 6 ) -#define N_G8F (0x600C + (12 * 8) + 6 ) -#define N_G8 (0x600C + (12 * 8) + 7 ) -#define N_G8S (0x600C + (12 * 8) + 8 ) -#define N_A8F (0x600C + (12 * 8) + 8 ) -#define N_A8 (0x600C + (12 * 8) + 9 ) -#define N_A8S (0x600C + (12 * 8) + 10) -#define N_B8F (0x600C + (12 * 8) + 10) -#define N_B8 (0x600C + (12 * 8) + 11) - #endif \ No newline at end of file diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index f2b9509b5..4423d25ef 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -224,8 +224,12 @@ enum quantum_keycodes { MI_SUS, // sustain MI_PORT, // portamento MI_SOST, // sostenuto - MI_SOFT, // soft + MI_SOFT, // soft pedal MI_LEG, // legato + + MI_MOD, // modulation + MI_MODSD, // decrease modulation speed + MI_MODSU, // increase modulation speed #endif // Backlight functionality diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index fb60658df..bd2498057 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1180,7 +1180,7 @@ int main(void) #ifdef MIDI_ENABLE midi_device_process(&midi_device); - // MIDI_Task(); + midi_task(); #endif #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE) From 5e6097f0154403dccb9b5658390c84441aa509bc Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 06:19:48 -0800 Subject: [PATCH 08/20] add keycodes for transpose range --- quantum/process_keycode/process_midi.c | 37 +++++++++++++++++++++----- quantum/quantum_keycodes.h | 18 +++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index d09aa0b38..4d60aefb1 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -2,12 +2,13 @@ #include "timer.h" typedef union { - uint16_t raw; + uint32_t raw; struct { - uint8_t octave :4; - uint8_t velocity :4; - uint8_t channel :4; - uint8_t modulation_interval :4; + uint8_t octave :4; + int8_t transpose :4; + uint8_t velocity :4; + uint8_t channel :4; + uint8_t modulation_interval :4; }; } midi_config_t; @@ -29,7 +30,8 @@ inline uint8_t compute_velocity(uint8_t setting) void midi_init(void) { - midi_config.octave = MI_OCT_0 - MIDI_OCTAVE_MIN; + midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN; + midi_config.transpose = 0; midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); midi_config.channel = 0; midi_config.modulation_interval = 8; @@ -77,7 +79,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) uint8_t tone = keycode - MIDI_TONE_MIN; uint8_t velocity = compute_velocity(midi_config.velocity); if (record->event.pressed) { - uint8_t note = 12 * midi_config.octave + tone; + uint8_t note = 12 * midi_config.octave + tone + midi_config.transpose; midi_send_noteon(&midi_device, channel, note, velocity); dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); tone_status[tone] = note; @@ -111,6 +113,27 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) dprintf("midi octave %d\n", midi_config.octave); } return false; + case MIDI_TRANSPOSE_MIN ... MIDI_TRANSPOSE_MAX: + if (record->event.pressed) { + midi_config.transpose = keycode - MI_TRNS_0; + dprintf("midi transpose %d\n", midi_config.transpose); + } + return false; + case MI_TRNSD: + if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - MI_TRNS_0)) { + midi_config.transpose--; + dprintf("midi transpose %d\n", midi_config.transpose); + } + return false; + case MI_TRNSU: + if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) { + const bool positive = midi_config.transpose > 0; + midi_config.transpose++; + if (positive && midi_config.transpose < 0) + midi_config.transpose--; + dprintf("midi transpose %d\n", midi_config.transpose); + } + return false; case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX: if (record->event.pressed) { midi_config.velocity = keycode - MIDI_VELOCITY_MIN; diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 4423d25ef..30cc9abdb 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -183,6 +183,24 @@ enum quantum_keycodes { MI_OCTD, // octave down MI_OCTU, // octave up + MIDI_TRANSPOSE_MIN, + MI_TRNS_N6 = MIDI_TRANSPOSE_MIN, + MI_TRNS_N5, + MI_TRNS_N4, + MI_TRNS_N3, + MI_TRNS_N2, + MI_TRNS_N1, + MI_TRNS_0, + MI_TRNS_1, + MI_TRNS_2, + MI_TRNS_3, + MI_TRNS_4, + MI_TRNS_5, + MI_TRNS_6, + MIDI_TRANSPOSE_MAX = MI_TRNS_6, + MI_TRNSD, // transpose down + MI_TRNSU, // transpose up + MIDI_VELOCITY_MIN, MI_VEL_1 = MIDI_VELOCITY_MIN, MI_VEL_2, From ae0752dff552a07fb52e08c7057979959959d247 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 18 Feb 2017 21:07:07 -0800 Subject: [PATCH 09/20] expose midi_config --- quantum/process_keycode/process_midi.c | 23 ++++++----------------- quantum/process_keycode/process_midi.h | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 4d60aefb1..9190fa047 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -1,22 +1,6 @@ #include "process_midi.h" #include "timer.h" -typedef union { - uint32_t raw; - struct { - uint8_t octave :4; - int8_t transpose :4; - uint8_t velocity :4; - uint8_t channel :4; - uint8_t modulation_interval :4; - }; -} midi_config_t; - -midi_config_t midi_config; - -#define MIDI_INVALID_NOTE 0xFF - -#define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1) static uint8_t tone_status[MIDI_TONE_COUNT]; static uint8_t midi_modulation; @@ -70,6 +54,11 @@ void midi_task(void) } } +uint8_t midi_compute_note(uint16_t keycode) +{ + return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose; +} + bool process_midi(uint16_t keycode, keyrecord_t *record) { switch (keycode) { @@ -79,7 +68,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) uint8_t tone = keycode - MIDI_TONE_MIN; uint8_t velocity = compute_velocity(midi_config.velocity); if (record->event.pressed) { - uint8_t note = 12 * midi_config.octave + tone + midi_config.transpose; + uint8_t note = midi_compute_note(keycode); midi_send_noteon(&midi_device, channel, note, velocity); dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); tone_status[tone] = note; diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index 66ce60b0e..ffd41579f 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -4,8 +4,26 @@ #include "quantum.h" #include "midi.h" +typedef union { + uint32_t raw; + struct { + uint8_t octave :4; + int8_t transpose :4; + uint8_t velocity :4; + uint8_t channel :4; + uint8_t modulation_interval :4; + }; +} midi_config_t; + +midi_config_t midi_config; + void midi_init(void); void midi_task(void); bool process_midi(uint16_t keycode, keyrecord_t *record); +#define MIDI_INVALID_NOTE 0xFF +#define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1) + +uint8_t midi_compute_note(uint16_t keycode); + #endif \ No newline at end of file From d1fe24ad9f85768774ae50465c71f3757a33cc00 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sun, 19 Feb 2017 17:18:05 -0800 Subject: [PATCH 10/20] Allow customization of the number of tone keycodes and add example keymap --- keyboards/satan/keymaps/midi/Makefile | 21 +++++++ keyboards/satan/keymaps/midi/config.h | 11 ++++ keyboards/satan/keymaps/midi/keymap.c | 60 ++++++++++++++++++ keyboards/satan/keymaps/midi/readme.md | 1 + quantum/quantum_keycodes.h | 84 ++++++++++++++++++++++++++ quantum/template/config.h | 3 + 6 files changed, 180 insertions(+) create mode 100644 keyboards/satan/keymaps/midi/Makefile create mode 100644 keyboards/satan/keymaps/midi/config.h create mode 100644 keyboards/satan/keymaps/midi/keymap.c create mode 100644 keyboards/satan/keymaps/midi/readme.md diff --git a/keyboards/satan/keymaps/midi/Makefile b/keyboards/satan/keymaps/midi/Makefile new file mode 100644 index 000000000..5cbda96ce --- /dev/null +++ b/keyboards/satan/keymaps/midi/Makefile @@ -0,0 +1,21 @@ +# Build Options +# change to "no" to disable the options, or define them in the Makefile in +# the appropriate keymap folder that will get included automatically +# +BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration(+1000) +MOUSEKEY_ENABLE = yes # Mouse keys(+4700) +EXTRAKEY_ENABLE = yes # Audio control and System control(+450) +CONSOLE_ENABLE = no # Console for debug(+400) +COMMAND_ENABLE = yes # Commands for debug and configuration +NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work +BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality +MIDI_ENABLE = yes # MIDI controls +AUDIO_ENABLE = no # Audio output on port C6 +UNICODE_ENABLE = no # Unicode +BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID +RGBLIGHT_ENABLE = no # Enable WS2812 RGB underlight. Do not enable this with audio at the same time. +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend + +ifndef QUANTUM_DIR + include ../../../../Makefile +endif diff --git a/keyboards/satan/keymaps/midi/config.h b/keyboards/satan/keymaps/midi/config.h new file mode 100644 index 000000000..e345d40c9 --- /dev/null +++ b/keyboards/satan/keymaps/midi/config.h @@ -0,0 +1,11 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +// place overrides here + +/* override number of MIDI tone keycodes (each octave adds 12 bytes) */ +#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/satan/keymaps/midi/keymap.c b/keyboards/satan/keymaps/midi/keymap.c new file mode 100644 index 000000000..ac9725933 --- /dev/null +++ b/keyboards/satan/keymaps/midi/keymap.c @@ -0,0 +1,60 @@ +#include "satan.h" + +// Each layer gets a name for readability, which is then used in the keymap matrix below. +// The underscores don't mean anything - you can have a layer called STUFF or any other name. +// Layer names don't all need to be of the same length, obviously, and you can also skip them +// entirely and just use numbers. +#define _BL 0 +#define _ML 1 + +// readability +#define _______ KC_TRNS +#define XXXXXXX KC_NO + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Keymap _BL: (Base Layer) Default Layer + * ,-----------------------------------------------------------. + * |Esc | 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ | + * |-----------------------------------------------------------| + * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift | + * |-----------------------------------------------------------| + * |Ctrl|Gui |Alt | Space |Alt |Gui |FN |Ctrl | + * `-----------------------------------------------------------' + */ +[_BL] = KEYMAP_ANSI( + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC,KC_BSLS, \ + KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT, KC_ENT, \ + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT, \ + KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,KC_RGUI, TG(_ML), KC_RCTL), + +/* Keymap _ML: MIDI Layer + * ,------------------------------------------------------------------------. + * | Exit | | | | | | | | | | | | | | + * |------------------------------------------------------------------------| + * | Ch+ | | C# | D# | | F# | G# | A# | | C# | D# | | | | + * |------------------------------------------------------------------------| + * | Mod | C | D | E | F | G | A | B | C | D | E | F |>>OnStage| + * |------------------------------------------------------------------------| + * | Sustain |Oct-|Oct+|Mod-|Mod+| | | |Tns-|Tns+|Tns0| Sustain | + * |------------------------------------------------------------------------| + * | | | | All notes off | | | | | + * `------------------------------------------------------------------------' + * + * Foot switches: + * ,--------. ,--------. + * | | | | + * | | | | + * `--------' `--------' + */ +[_ML] = KEYMAP_ANSI( + TG(_ML), MI_VEL_1, MI_VEL_2, MI_VEL_3, MI_VEL_4, MI_VEL_5, MI_VEL_6, MI_VEL_7, MI_VEL_8, MI_VEL_9, MI_VEL_10, XXXXXXX, XXXXXXX, XXXXXXX, \ + MI_CHU, XXXXXXX, MI_Cs, MI_Ds, XXXXXXX, MI_Fs, MI_Gs, MI_As, XXXXXXX, MI_Cs_1, MI_Ds_1, XXXXXXX, XXXXXXX, XXXXXXX, \ + MI_MOD, MI_C, MI_D, MI_E, MI_F, MI_G, MI_A, MI_B, MI_C_1, MI_D_1, MI_E_1, MI_F_1, _______, \ + MI_SUS, MI_OCTD, MI_OCTU, MI_MODSD, MI_MODSU, XXXXXXX, XXXXXXX, XXXXXXX, MI_TRNSD, MI_TRNSU, MI_TRNS_0, MI_SUS, \ + _______, _______, _______, MI_OFF, _______, _______, _______, _______), +}; \ No newline at end of file diff --git a/keyboards/satan/keymaps/midi/readme.md b/keyboards/satan/keymaps/midi/readme.md new file mode 100644 index 000000000..87844a854 --- /dev/null +++ b/keyboards/satan/keymaps/midi/readme.md @@ -0,0 +1 @@ +# Satan GH60 layout demonstrating MIDI key mapping diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 30cc9abdb..6d1438051 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -2,6 +2,12 @@ #ifndef QUANTUM_KEYCODES_H #define QUANTUM_KEYCODES_H +#ifdef MIDI_ENABLE +#ifndef MIDI_TONE_KEYCODE_OCTAVES +#define MIDI_TONE_KEYCODE_OCTAVES 3 +#endif +#endif + enum quantum_keycodes { // Ranges used in shortucuts - not to be used directly QK_TMK = 0x0000, @@ -112,6 +118,7 @@ enum quantum_keycodes { MIDI_TONE_MIN, +#if MIDI_TONE_KEYCODE_OCTAVES > 0 MI_C = MIDI_TONE_MIN, MI_Cs, MI_Db = MI_Cs, @@ -129,7 +136,9 @@ enum quantum_keycodes { MI_As, MI_Bb = MI_As, MI_B, +#endif +#if MIDI_TONE_KEYCODE_OCTAVES > 1 MI_C_1, MI_Cs_1, MI_Db_1 = MI_Cs_1, @@ -147,7 +156,9 @@ enum quantum_keycodes { MI_As_1, MI_Bb_1 = MI_As_1, MI_B_1, +#endif +#if MIDI_TONE_KEYCODE_OCTAVES > 2 MI_C_2, MI_Cs_2, MI_Db_2 = MI_Cs_2, @@ -165,8 +176,81 @@ enum quantum_keycodes { MI_As_2, MI_Bb_2 = MI_As_2, MI_B_2, +#endif +#if MIDI_TONE_KEYCODE_OCTAVES > 3 + MI_C_3, + MI_Cs_3, + MI_Db_3 = MI_Cs_3, + MI_D_3, + MI_Ds_3, + MI_Eb_3 = MI_Ds_3, + MI_E_3, + MI_F_3, + MI_Fs_3, + MI_Gb_3 = MI_Fs_3, + MI_G_3, + MI_Gs_3, + MI_Ab_3 = MI_Gs_3, + MI_A_3, + MI_As_3, + MI_Bb_3 = MI_As_3, + MI_B_3, +#endif + +#if MIDI_TONE_KEYCODE_OCTAVES > 4 + MI_C_4, + MI_Cs_4, + MI_Db_4 = MI_Cs_4, + MI_D_4, + MI_Ds_4, + MI_Eb_4 = MI_Ds_4, + MI_E_4, + MI_F_4, + MI_Fs_4, + MI_Gb_4 = MI_Fs_4, + MI_G_4, + MI_Gs_4, + MI_Ab_4 = MI_Gs_4, + MI_A_4, + MI_As_4, + MI_Bb_4 = MI_As_4, + MI_B_4, +#endif + +#if MIDI_TONE_KEYCODE_OCTAVES > 5 + MI_C_5, + MI_Cs_5, + MI_Db_5 = MI_Cs_5, + MI_D_5, + MI_Ds_5, + MI_Eb_5 = MI_Ds_5, + MI_E_5, + MI_F_5, + MI_Fs_5, + MI_Gb_5 = MI_Fs_5, + MI_G_5, + MI_Gs_5, + MI_Ab_5 = MI_Gs_5, + MI_A_5, + MI_As_5, + MI_Bb_5 = MI_As_5, + MI_B_5, +#endif + +#if MIDI_TONE_KEYCODE_OCTAVES > 5 + MIDI_TONE_MAX = MI_B_5, +#elif MIDI_TONE_KEYCODE_OCTAVES > 4 + MIDI_TONE_MAX = MI_B_4, +#elif MIDI_TONE_KEYCODE_OCTAVES > 3 + MIDI_TONE_MAX = MI_B_3, +#elif MIDI_TONE_KEYCODE_OCTAVES > 2 MIDI_TONE_MAX = MI_B_2, +#elif MIDI_TONE_KEYCODE_OCTAVES > 1 + MIDI_TONE_MAX = MI_B_1, +#elif MIDI_TONE_KEYCODE_OCTAVES > 0 + MIDI_TONE_MAX = MI_B, +#endif MIDI_OCTAVE_MIN, MI_OCT_N2 = MIDI_OCTAVE_MIN, diff --git a/quantum/template/config.h b/quantum/template/config.h index c61c4a618..d0bee0d89 100644 --- a/quantum/template/config.h +++ b/quantum/template/config.h @@ -159,4 +159,7 @@ along with this program. If not, see . //#define NO_ACTION_MACRO //#define NO_ACTION_FUNCTION +/* override number of MIDI tone keycodes (each octave adds 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 1 + #endif From ed15973a3ffff6e18e62f81654632b97961f18d2 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sun, 19 Feb 2017 17:45:08 -0800 Subject: [PATCH 11/20] Document size added by MIDI_ENABLE (~3800 bytes according to my experiments) satan/keymaps/midi MIDI_ENABLE = no text data bss dec hex filename 0 17080 0 17080 42b8 satan_midi.hex MIDI_ENABLE = yes #define MIDI_TONE_KEYCODE_OCTAVES 3 // default text data bss dec hex filename 0 20846 0 20846 516e satan_midi.hex MIDI_ENABLE = yes #define MIDI_TONE_KEYCODE_OCTAVES 2 // fewer octaves text data bss dec hex filename 0 20846 0 20846 516e satan_midi.hex --- keyboards/satan/keymaps/midi/Makefile | 2 +- keyboards/satan/keymaps/midi/config.h | 2 +- keyboards/satan/keymaps/midi/keymap.c | 2 ++ quantum/process_keycode/process_midi.c | 2 ++ quantum/template/config.h | 2 +- quantum/template/keymaps/default/Makefile | 2 +- 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/keyboards/satan/keymaps/midi/Makefile b/keyboards/satan/keymaps/midi/Makefile index 5cbda96ce..4e2d9d2f7 100644 --- a/keyboards/satan/keymaps/midi/Makefile +++ b/keyboards/satan/keymaps/midi/Makefile @@ -9,7 +9,7 @@ CONSOLE_ENABLE = no # Console for debug(+400) COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality -MIDI_ENABLE = yes # MIDI controls +MIDI_ENABLE = yes # MIDI support (+3800) AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID diff --git a/keyboards/satan/keymaps/midi/config.h b/keyboards/satan/keymaps/midi/config.h index e345d40c9..0dbdb5cbc 100644 --- a/keyboards/satan/keymaps/midi/config.h +++ b/keyboards/satan/keymaps/midi/config.h @@ -5,7 +5,7 @@ // place overrides here -/* override number of MIDI tone keycodes (each octave adds 12 bytes) */ +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ #define MIDI_TONE_KEYCODE_OCTAVES 2 #endif \ No newline at end of file diff --git a/keyboards/satan/keymaps/midi/keymap.c b/keyboards/satan/keymaps/midi/keymap.c index ac9725933..004690f41 100644 --- a/keyboards/satan/keymaps/midi/keymap.c +++ b/keyboards/satan/keymaps/midi/keymap.c @@ -32,6 +32,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT, \ KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,KC_RGUI, TG(_ML), KC_RCTL), +#ifdef MIDI_ENABLE /* Keymap _ML: MIDI Layer * ,------------------------------------------------------------------------. * | Exit | | | | | | | | | | | | | | @@ -57,4 +58,5 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { MI_MOD, MI_C, MI_D, MI_E, MI_F, MI_G, MI_A, MI_B, MI_C_1, MI_D_1, MI_E_1, MI_F_1, _______, \ MI_SUS, MI_OCTD, MI_OCTU, MI_MODSD, MI_MODSU, XXXXXXX, XXXXXXX, XXXXXXX, MI_TRNSD, MI_TRNSU, MI_TRNS_0, MI_SUS, \ _______, _______, _______, MI_OFF, _______, _______, _______, _______), +#endif }; \ No newline at end of file diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 9190fa047..5530ea97c 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -1,3 +1,5 @@ +#define MIDI_TONE_KEYCODE_OCTAVES 2 + #include "process_midi.h" #include "timer.h" diff --git a/quantum/template/config.h b/quantum/template/config.h index d0bee0d89..cd6dfa2c6 100644 --- a/quantum/template/config.h +++ b/quantum/template/config.h @@ -159,7 +159,7 @@ along with this program. If not, see . //#define NO_ACTION_MACRO //#define NO_ACTION_FUNCTION -/* override number of MIDI tone keycodes (each octave adds 12 bytes) */ +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ //#define MIDI_TONE_KEYCODE_OCTAVES 1 #endif diff --git a/quantum/template/keymaps/default/Makefile b/quantum/template/keymaps/default/Makefile index f4671a9d1..24442db37 100644 --- a/quantum/template/keymaps/default/Makefile +++ b/quantum/template/keymaps/default/Makefile @@ -9,7 +9,7 @@ CONSOLE_ENABLE = no # Console for debug(+400) COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality -MIDI_ENABLE = no # MIDI controls +MIDI_ENABLE = no # MIDI support (+3800) AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID From 64eecfc5303788bd82bf2fb466ec4a6f1bd0c028 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sun, 19 Feb 2017 22:23:06 -0800 Subject: [PATCH 12/20] fix typos in keymap --- keyboards/satan/keymaps/midi/keymap.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/keyboards/satan/keymaps/midi/keymap.c b/keyboards/satan/keymaps/midi/keymap.c index 004690f41..397fe097b 100644 --- a/keyboards/satan/keymaps/midi/keymap.c +++ b/keyboards/satan/keymaps/midi/keymap.c @@ -22,7 +22,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |-----------------------------------------------------------| * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift | * |-----------------------------------------------------------| - * |Ctrl|Gui |Alt | Space |Alt |Gui |FN |Ctrl | + * |Ctrl|Gui |Alt | Space |Alt |Gui |Midi|Ctrl | * `-----------------------------------------------------------' */ [_BL] = KEYMAP_ANSI( @@ -39,18 +39,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * |------------------------------------------------------------------------| * | Ch+ | | C# | D# | | F# | G# | A# | | C# | D# | | | | * |------------------------------------------------------------------------| - * | Mod | C | D | E | F | G | A | B | C | D | E | F |>>OnStage| + * | Mod | C | D | E | F | G | A | B | C | D | E | F | | * |------------------------------------------------------------------------| * | Sustain |Oct-|Oct+|Mod-|Mod+| | | |Tns-|Tns+|Tns0| Sustain | * |------------------------------------------------------------------------| * | | | | All notes off | | | | | * `------------------------------------------------------------------------' - * - * Foot switches: - * ,--------. ,--------. - * | | | | - * | | | | - * `--------' `--------' */ [_ML] = KEYMAP_ANSI( TG(_ML), MI_VEL_1, MI_VEL_2, MI_VEL_3, MI_VEL_4, MI_VEL_5, MI_VEL_6, MI_VEL_7, MI_VEL_8, MI_VEL_9, MI_VEL_10, XXXXXXX, XXXXXXX, XXXXXXX, \ From 525be99ee938aa6e48448d7dd6ea6e6fe50bb36d Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 25 Feb 2017 15:02:43 -0800 Subject: [PATCH 13/20] Split MIDI functionality into MIDI_BASIC and MIDI_ADVANCED MIDI_ENABLE = no text data bss dec hex filename 0 17080 0 17080 42b8 satan_midi.hex MIDI_ENABLE = yes MIDI_BASIC undefined MIDI_ADVANCED undefined text data bss dec hex filename 0 19494 0 19494 4c26 satan_midi.hex MIDI_ENABLE = yes #define MIDI_BASIC MIDI_ADVANCED undefined text data bss dec hex filename 0 19788 0 19788 4d4c satan_midi.hex MIDI_ENABLE = yes MIDI_BASIC undefined #define MIDI_ADVANCED text data bss dec hex filename 0 20846 0 20846 516e satan_midi.hex MIDI_ENABLE = yes #define MIDI_BASIC #define MIDI_ADVANCED text data bss dec hex filename 0 21140 0 21140 5294 satan_midi.hex --- build_keyboard.mk | 1 + keyboards/satan/keymaps/midi/config.h | 17 ++++++++++++++++- keyboards/satan/keymaps/midi/keymap.c | 4 ++-- quantum/process_keycode/process_midi.c | 9 ++++++--- quantum/process_keycode/process_music.c | 22 ++++++++++++++++++++++ quantum/quantum.c | 4 ++-- quantum/quantum_keycodes.h | 13 ++++++++++--- quantum/template/config.h | 17 +++++++++++++++++ tmk_core/protocol/lufa/lufa.c | 4 ++++ 9 files changed, 80 insertions(+), 11 deletions(-) diff --git a/build_keyboard.mk b/build_keyboard.mk index 4a6fc0980..eea8d5919 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -141,6 +141,7 @@ endif ifeq ($(strip $(MIDI_ENABLE)), yes) OPT_DEFS += -DMIDI_ENABLE + SRC += $(QUANTUM_DIR)/process_keycode/process_music.c SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c endif diff --git a/keyboards/satan/keymaps/midi/config.h b/keyboards/satan/keymaps/midi/config.h index 0dbdb5cbc..59250b49e 100644 --- a/keyboards/satan/keymaps/midi/config.h +++ b/keyboards/satan/keymaps/midi/config.h @@ -3,7 +3,22 @@ #include "../../config.h" -// place overrides here +/* + * MIDI options + */ + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +#define MIDI_ADVANCED /* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ #define MIDI_TONE_KEYCODE_OCTAVES 2 diff --git a/keyboards/satan/keymaps/midi/keymap.c b/keyboards/satan/keymaps/midi/keymap.c index 397fe097b..349391c3b 100644 --- a/keyboards/satan/keymaps/midi/keymap.c +++ b/keyboards/satan/keymaps/midi/keymap.c @@ -32,7 +32,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT, \ KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,KC_RGUI, TG(_ML), KC_RCTL), -#ifdef MIDI_ENABLE +#if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) /* Keymap _ML: MIDI Layer * ,------------------------------------------------------------------------. * | Exit | | | | | | | | | | | | | | @@ -51,6 +51,6 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { MI_CHU, XXXXXXX, MI_Cs, MI_Ds, XXXXXXX, MI_Fs, MI_Gs, MI_As, XXXXXXX, MI_Cs_1, MI_Ds_1, XXXXXXX, XXXXXXX, XXXXXXX, \ MI_MOD, MI_C, MI_D, MI_E, MI_F, MI_G, MI_A, MI_B, MI_C_1, MI_D_1, MI_E_1, MI_F_1, _______, \ MI_SUS, MI_OCTD, MI_OCTU, MI_MODSD, MI_MODSU, XXXXXXX, XXXXXXX, XXXXXXX, MI_TRNSD, MI_TRNSU, MI_TRNS_0, MI_SUS, \ - _______, _______, _______, MI_OFF, _______, _______, _______, _______), + _______, _______, _______, MI_ALLOFF, _______, _______, _______, _______), #endif }; \ No newline at end of file diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 5530ea97c..161f04a24 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -1,6 +1,7 @@ -#define MIDI_TONE_KEYCODE_OCTAVES 2 - #include "process_midi.h" + +#if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) + #include "timer.h" static uint8_t tone_status[MIDI_TONE_COUNT]; @@ -161,7 +162,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) dprintf("midi channel %d\n", midi_config.channel); } return false; - case MI_OFF: + case MI_ALLOFF: if (record->event.pressed) { midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0); dprintf("midi off\n"); @@ -209,3 +210,5 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) return true; } + +#endif // MIDI_ADVANCED diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 1e2648bff..ac906b628 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -17,6 +17,7 @@ static uint16_t music_sequence_interval = 100; bool process_music(uint16_t keycode, keyrecord_t *record) { + #ifdef AUDIO_ENABLE if (keycode == AU_ON && record->event.pressed) { audio_on(); return false; @@ -38,6 +39,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } return false; } + #endif // AUDIO_ENABLE if (keycode == MU_ON && record->event.pressed) { music_on(); @@ -61,6 +63,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { return false; } + #ifdef AUDIO_ENABLE if (keycode == MUV_IN && record->event.pressed) { voice_iterate(); music_scale_user(); @@ -72,11 +75,14 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { music_scale_user(); return false; } + #endif // AUDIO_ENABLE if (music_activated) { if (keycode == KC_LCTL && record->event.pressed) { // Start recording + #ifdef AUDIO_ENABLE stop_all_notes(); + #endif music_sequence_recording = true; music_sequence_recorded = false; music_sequence_playing = false; @@ -85,7 +91,9 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing + #ifdef AUDIO_ENABLE stop_all_notes(); + #endif if (music_sequence_recording) { // was recording music_sequence_recorded = true; } @@ -95,7 +103,9 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing + #ifdef AUDIO_ENABLE stop_all_notes(); + #endif music_sequence_recording = false; music_sequence_playing = true; music_sequence_position = 0; @@ -116,6 +126,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } #define MUSIC_MODE_GUITAR + #ifdef AUDIO_ENABLE #ifdef MUSIC_MODE_CHROMATIC float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(MATRIX_ROWS - record->event.key.row)); #elif defined(MUSIC_MODE_GUITAR) @@ -125,15 +136,20 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { #else float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + SCALE[record->event.key.col + music_offset])/12.0+(MATRIX_ROWS - record->event.key.row)); #endif + #endif // AUDIO_ENABLE if (record->event.pressed) { + #ifdef AUDIO_ENABLE play_note(freq, 0xF); if (music_sequence_recording) { music_sequence[music_sequence_count] = freq; music_sequence_count++; } + #endif } else { + #ifdef AUDIO_ENABLE stop_note(freq); + #endif } if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through @@ -161,15 +177,19 @@ void music_on(void) { void music_off(void) { music_activated = 0; + #ifdef AUDIO_ENABLE stop_all_notes(); + #endif } __attribute__ ((weak)) void music_on_user() {} +#ifdef AUDIO_ENABLE __attribute__ ((weak)) void audio_on_user() {} +#endif __attribute__ ((weak)) void music_scale_user() {} @@ -178,8 +198,10 @@ void matrix_scan_music(void) { if (music_sequence_playing) { if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) { music_sequence_timer = timer_read(); + #ifdef AUDIO_ENABLE stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]); play_note(music_sequence[music_sequence_position], 0xF); + #endif music_sequence_position = (music_sequence_position + 1) % music_sequence_count; } } diff --git a/quantum/quantum.c b/quantum/quantum.c index 4a6d0355f..83fa87708 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -150,10 +150,10 @@ bool process_record_quantum(keyrecord_t *record) { if (!( process_record_kb(keycode, record) && - #ifdef MIDI_ENABLE + #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) process_midi(keycode, record) && #endif - #ifdef AUDIO_ENABLE + #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) process_music(keycode, record) && #endif #ifdef TAP_DANCE_ENABLE diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 6d1438051..3b82b7208 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -2,7 +2,7 @@ #ifndef QUANTUM_KEYCODES_H #define QUANTUM_KEYCODES_H -#ifdef MIDI_ENABLE +#if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) #ifndef MIDI_TONE_KEYCODE_OCTAVES #define MIDI_TONE_KEYCODE_OCTAVES 3 #endif @@ -116,6 +116,12 @@ enum quantum_keycodes { #ifdef MIDI_ENABLE // Midi +#ifdef MIDI_BASIC + MI_ON, // send midi notes when music mode is enabled + MI_OFF, // don't send midi notes when music mode is enabled +#endif + +#ifdef MIDI_ADVANCED MIDI_TONE_MIN, #if MIDI_TONE_KEYCODE_OCTAVES > 0 @@ -321,7 +327,7 @@ enum quantum_keycodes { MI_CHD, // previous channel MI_CHU, // next channel - MI_OFF, // all notes off + MI_ALLOFF, // all notes off MI_SUS, // sustain MI_PORT, // portamento @@ -332,7 +338,8 @@ enum quantum_keycodes { MI_MOD, // modulation MI_MODSD, // decrease modulation speed MI_MODSU, // increase modulation speed -#endif +#endif // MIDI_ADVANCED +#endif // MIDI_ENABLE // Backlight functionality BL_0, diff --git a/quantum/template/config.h b/quantum/template/config.h index cd6dfa2c6..54db4f242 100644 --- a/quantum/template/config.h +++ b/quantum/template/config.h @@ -159,6 +159,23 @@ along with this program. If not, see . //#define NO_ACTION_MACRO //#define NO_ACTION_FUNCTION +/* + * MIDI options + */ + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +//#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + /* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ //#define MIDI_TONE_KEYCODE_OCTAVES 1 diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index bd2498057..651a0f347 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -1104,7 +1104,9 @@ void sysex_callback(MidiDevice * device, void setup_midi(void) { +#ifdef MIDI_ADVANCED midi_init(); +#endif midi_device_init(&midi_device); midi_device_set_send_func(&midi_device, usb_send_func); midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); @@ -1180,8 +1182,10 @@ int main(void) #ifdef MIDI_ENABLE midi_device_process(&midi_device); +#ifdef MIDI_ADVANCED midi_task(); #endif +#endif #if defined(RGBLIGHT_ANIMATIONS) & defined(RGBLIGHT_ENABLE) rgblight_task(); From 1000799d1ef594bf9f48076986ec300ef9e536db Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 25 Feb 2017 19:25:33 -0800 Subject: [PATCH 14/20] Factor basic note processing into respective processors --- build_keyboard.mk | 1 + quantum/process_keycode/process_audio.c | 62 +++++++++++ quantum/process_keycode/process_audio.h | 11 ++ quantum/process_keycode/process_midi.c | 28 ++++- quantum/process_keycode/process_midi.h | 13 ++- quantum/process_keycode/process_music.c | 141 ++++++++++-------------- quantum/process_keycode/process_music.h | 5 +- quantum/quantum.c | 3 + quantum/quantum.h | 7 +- 9 files changed, 186 insertions(+), 85 deletions(-) create mode 100644 quantum/process_keycode/process_audio.c create mode 100644 quantum/process_keycode/process_audio.h diff --git a/build_keyboard.mk b/build_keyboard.mk index eea8d5919..07dfe85b4 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -157,6 +157,7 @@ endif ifeq ($(strip $(AUDIO_ENABLE)), yes) OPT_DEFS += -DAUDIO_ENABLE SRC += $(QUANTUM_DIR)/process_keycode/process_music.c + SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c SRC += $(QUANTUM_DIR)/audio/audio.c SRC += $(QUANTUM_DIR)/audio/voices.c SRC += $(QUANTUM_DIR)/audio/luts.c diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c new file mode 100644 index 000000000..5b5da546e --- /dev/null +++ b/quantum/process_keycode/process_audio.c @@ -0,0 +1,62 @@ +#include "process_audio.h" +#include "audio.h" + +static float compute_freq_for_midi_note(uint8_t note) +{ + // https://en.wikipedia.org/wiki/MIDI_tuning_standard + return pow(2.0, (note - 69) / 12.0) * 440.0f; +} + +bool process_audio(uint16_t keycode, keyrecord_t *record) { + + if (keycode == AU_ON && record->event.pressed) { + audio_on(); + return false; + } + + if (keycode == AU_OFF && record->event.pressed) { + audio_off(); + return false; + } + + if (keycode == AU_TOG && record->event.pressed) { + if (is_audio_on()) + { + audio_off(); + } + else + { + audio_on(); + } + return false; + } + + if (keycode == MUV_IN && record->event.pressed) { + voice_iterate(); + music_scale_user(); + return false; + } + + if (keycode == MUV_DE && record->event.pressed) { + voice_deiterate(); + music_scale_user(); + return false; + } + + return true +} + +void process_audio_noteon(uint8_t note) { + play_note(compute_freq_for_midi_note(note), 0xF); +} + +void process_audio_noteoff(uint8_t note) { + stop_note(compute_freq_for_midi_note(note)); +} + +void process_audio_stop_all_notes(void) { + stop_all_notes(); +} + +__attribute__ ((weak)) +void audio_on_user() {} \ No newline at end of file diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h new file mode 100644 index 000000000..59a17725a --- /dev/null +++ b/quantum/process_keycode/process_audio.h @@ -0,0 +1,11 @@ +#ifndef PROCESS_AUDIO_H +#define PROCESS_AUDIO_H + +bool process_audio(uint16_t keycode, keyrecord_t *record); +void process_audio_noteon(uint8_t note); +void process_audio_noteoff(uint8_t note); +void process_audio_stop_all_notes(void); + +void audio_on_user(void); + +#endif \ No newline at end of file diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 161f04a24..214bba902 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -1,6 +1,28 @@ #include "process_midi.h" -#if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) +#ifdef MIDI_ENABLE +#include "midi.h" + +#ifdef MIDI_BASIC + +void process_midi_basic_noteon(uint8_t note) +{ + midi_send_noteon(&midi_device, 0, note, 128); +} + +void process_midi_basic_noteoff(uint8_t note) +{ + midi_send_noteoff(&midi_device, 0, note, 0); +} + +void process_midi_basic_stop_all_notes(void) +{ + midi_send_cc(&midi_device, 0, 0x7B, 0); +} + +#endif // MIDI_BASIC + +#ifdef MIDI_ADVANCED #include "timer.h" @@ -165,7 +187,7 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) case MI_ALLOFF: if (record->event.pressed) { midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0); - dprintf("midi off\n"); + dprintf("midi all notes off\n"); } return false; case MI_SUS: @@ -212,3 +234,5 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) } #endif // MIDI_ADVANCED + +#endif // MIDI_ENABLE diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index ffd41579f..0f559ec23 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -2,8 +2,16 @@ #define PROCESS_MIDI_H #include "quantum.h" -#include "midi.h" +#ifdef MIDI_ENABLE + +#ifdef MIDI_BASIC +void process_midi_basic_noteon(uint8_t note); +void process_midi_basic_noteoff(uint8_t note); +void process_midi_basic_stop_all_notes(void); +#endif + +#ifdef MIDI_ADVANCED typedef union { uint32_t raw; struct { @@ -25,5 +33,8 @@ bool process_midi(uint16_t keycode, keyrecord_t *record); #define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1) uint8_t midi_compute_note(uint16_t keycode); +#endif // MIDI_ADVANCED + +#endif // MIDI_ENABLE #endif \ No newline at end of file diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index ac906b628..a1e270df1 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -1,5 +1,14 @@ #include "process_music.h" +#ifdef AUDIO_ENABLE +#include "process_audio.h" +#endif +#if defined(MIDI_ENABLE) && defined(MIDI_BASIC) +#include "process_midi.h" +#endif + +#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) + bool music_activated = false; uint8_t music_starting_note = 0x0C; int music_offset = 7; @@ -8,39 +17,42 @@ int music_offset = 7; static bool music_sequence_recording = false; static bool music_sequence_recorded = false; static bool music_sequence_playing = false; -static float music_sequence[16] = {0}; +static uint8_t music_sequence[16] = {0}; static uint8_t music_sequence_count = 0; static uint8_t music_sequence_position = 0; static uint16_t music_sequence_timer = 0; static uint16_t music_sequence_interval = 100; +static void music_noteon(uint8_t note) { + #ifdef AUDIO_ENABLE + process_audio_noteon(note); + #endif + #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) + process_midi_basic_noteon(note); + #endif +} + +static void music_noteoff(uint8_t note) { + #ifdef AUDIO_ENABLE + process_audio_noteoff(note); + #endif + #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) + process_midi_basic_noteoff(note); + #endif +} + +static void music_all_notes_off(void) { + #ifdef AUDIO_ENABLE + process_audio_stop_all_notes(); + #endif + #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) + process_midi_basic_stop_all_notes(); + #endif +} + bool process_music(uint16_t keycode, keyrecord_t *record) { - #ifdef AUDIO_ENABLE - if (keycode == AU_ON && record->event.pressed) { - audio_on(); - return false; - } - - if (keycode == AU_OFF && record->event.pressed) { - audio_off(); - return false; - } - - if (keycode == AU_TOG && record->event.pressed) { - if (is_audio_on()) - { - audio_off(); - } - else - { - audio_on(); - } - return false; - } - #endif // AUDIO_ENABLE - if (keycode == MU_ON && record->event.pressed) { music_on(); return false; @@ -63,26 +75,10 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { return false; } - #ifdef AUDIO_ENABLE - if (keycode == MUV_IN && record->event.pressed) { - voice_iterate(); - music_scale_user(); - return false; - } - - if (keycode == MUV_DE && record->event.pressed) { - voice_deiterate(); - music_scale_user(); - return false; - } - #endif // AUDIO_ENABLE - if (music_activated) { if (keycode == KC_LCTL && record->event.pressed) { // Start recording - #ifdef AUDIO_ENABLE - stop_all_notes(); - #endif + music_all_notes_off(); music_sequence_recording = true; music_sequence_recorded = false; music_sequence_playing = false; @@ -91,9 +87,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing - #ifdef AUDIO_ENABLE - stop_all_notes(); - #endif + music_all_notes_off(); if (music_sequence_recording) { // was recording music_sequence_recorded = true; } @@ -103,9 +97,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing - #ifdef AUDIO_ENABLE - stop_all_notes(); - #endif + music_all_notes_off(); music_sequence_recording = false; music_sequence_playing = true; music_sequence_position = 0; @@ -124,32 +116,27 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { music_sequence_interval+=10; return false; } + #define MUSIC_MODE_GUITAR - #ifdef AUDIO_ENABLE #ifdef MUSIC_MODE_CHROMATIC - float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(MATRIX_ROWS - record->event.key.row)); + uint8_t note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); #elif defined(MUSIC_MODE_GUITAR) - float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(float)(MATRIX_ROWS - record->event.key.row + 7)*5.0/12); + uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); #elif defined(MUSIC_MODE_VIOLIN) - float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + record->event.key.col + music_offset)/12.0+(float)(MATRIX_ROWS - record->event.key.row + 5)*7.0/12); + uint8_t note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); #else - float freq = ((float)220.0)*pow(2.0, -5.0)*pow(2.0,(music_starting_note + SCALE[record->event.key.col + music_offset])/12.0+(MATRIX_ROWS - record->event.key.row)); + uint8_t note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); #endif - #endif // AUDIO_ENABLE if (record->event.pressed) { - #ifdef AUDIO_ENABLE - play_note(freq, 0xF); + music_noteon(note); if (music_sequence_recording) { - music_sequence[music_sequence_count] = freq; + music_sequence[music_sequence_count] = note; music_sequence_count++; } - #endif } else { - #ifdef AUDIO_ENABLE - stop_note(freq); - #endif + music_noteoff(note); } if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through @@ -177,32 +164,26 @@ void music_on(void) { void music_off(void) { music_activated = 0; - #ifdef AUDIO_ENABLE - stop_all_notes(); - #endif + music_all_notes_off(); } - -__attribute__ ((weak)) -void music_on_user() {} - -#ifdef AUDIO_ENABLE -__attribute__ ((weak)) -void audio_on_user() {} -#endif - -__attribute__ ((weak)) -void music_scale_user() {} - void matrix_scan_music(void) { if (music_sequence_playing) { if ((music_sequence_timer == 0) || (timer_elapsed(music_sequence_timer) > music_sequence_interval)) { music_sequence_timer = timer_read(); - #ifdef AUDIO_ENABLE - stop_note(music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]); - play_note(music_sequence[music_sequence_position], 0xF); - #endif + uint8_t prev_note = music_sequence[(music_sequence_position - 1 < 0)?(music_sequence_position - 1 + music_sequence_count):(music_sequence_position - 1)]; + uint8_t next_note = music_sequence[music_sequence_position]; + music_noteoff(prev_note); + music_noteon(next_note); music_sequence_position = (music_sequence_position + 1) % music_sequence_count; } } } + +__attribute__ ((weak)) +void music_on_user() {} + +__attribute__ ((weak)) +void music_scale_user() {} + +#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) \ No newline at end of file diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h index 318b3e387..69913b276 100644 --- a/quantum/process_keycode/process_music.h +++ b/quantum/process_keycode/process_music.h @@ -3,6 +3,8 @@ #include "quantum.h" +#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) + bool process_music(uint16_t keycode, keyrecord_t *record); bool is_music_on(void); @@ -10,7 +12,6 @@ void music_toggle(void); void music_on(void); void music_off(void); -void audio_on_user(void); void music_on_user(void); void music_scale_user(void); @@ -24,4 +25,6 @@ void matrix_scan_music(void); 0 + (12*4), 2 + (12*4), 4 + (12*4), 5 + (12*4), 7 + (12*4), 9 + (12*4), 11 + (12*4), } #endif +#endif // defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) + #endif \ No newline at end of file diff --git a/quantum/quantum.c b/quantum/quantum.c index 83fa87708..7a27a568a 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -153,6 +153,9 @@ bool process_record_quantum(keyrecord_t *record) { #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) process_midi(keycode, record) && #endif + #ifdef AUDIO_ENABLE + process_audio(keycode, record) && + #endif #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) process_music(keycode, record) && #endif diff --git a/quantum/quantum.h b/quantum/quantum.h index 580d51202..77732d43f 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -35,11 +35,16 @@ extern uint32_t default_layer_state; #ifdef MIDI_ENABLE #include +#ifdef MIDI_ADVANCED #include "process_midi.h" #endif +#endif // MIDI_ENABLE #ifdef AUDIO_ENABLE - #include "audio.h" + #include "process_audio.h" +#endif + +#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) #include "process_music.h" #endif From ea14ed122fb5c1b3be5f5d6edda9b39b151692e5 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 25 Feb 2017 19:37:33 -0800 Subject: [PATCH 15/20] Add basic layer to sample MIDI keycap --- keyboards/satan/keymaps/midi/keymap.c | 23 ++++++++++++++++++++++- quantum/process_keycode/process_audio.c | 2 +- quantum/process_keycode/process_music.c | 3 ++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/keyboards/satan/keymaps/midi/keymap.c b/keyboards/satan/keymaps/midi/keymap.c index 349391c3b..8378b4e4b 100644 --- a/keyboards/satan/keymaps/midi/keymap.c +++ b/keyboards/satan/keymaps/midi/keymap.c @@ -33,7 +33,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_LCTL, KC_LGUI,KC_LALT, KC_SPC, KC_RALT,KC_RGUI, TG(_ML), KC_RCTL), #if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) -/* Keymap _ML: MIDI Layer +/* Keymap _ML: MIDI Layer (Advanced) * ,------------------------------------------------------------------------. * | Exit | | | | | | | | | | | | | | * |------------------------------------------------------------------------| @@ -52,5 +52,26 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { MI_MOD, MI_C, MI_D, MI_E, MI_F, MI_G, MI_A, MI_B, MI_C_1, MI_D_1, MI_E_1, MI_F_1, _______, \ MI_SUS, MI_OCTD, MI_OCTU, MI_MODSD, MI_MODSU, XXXXXXX, XXXXXXX, XXXXXXX, MI_TRNSD, MI_TRNSU, MI_TRNS_0, MI_SUS, \ _______, _______, _______, MI_ALLOFF, _______, _______, _______, _______), +#elif defined(MIDI_ENABLE) && defined(MIDI_BASIC) +/* Keymap _ML: MIDI Layer (Advanced) + * ,------------------------------------------------------------------------. + * | Exit | | | | | | | | | | | | | | + * |------------------------------------------------------------------------| + * | | | | | | | | | | | | | | | + * |------------------------------------------------------------------------| + * | | | | | | | | | | | | | | + * |------------------------------------------------------------------------| + * | |MuOn|MuOf|MiOn|MiOf| | | | | | | | + * |------------------------------------------------------------------------| + * | | | | | | | | | + * `------------------------------------------------------------------------' + */ + +[_ML] = KEYMAP_ANSI( + TG(_ML), _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ + _______, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, _______, _______, _______, \ + _______, _______, _______, _______, _______, _______, _______, _______), #endif }; \ No newline at end of file diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index 5b5da546e..d45242c9e 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -28,7 +28,7 @@ bool process_audio(uint16_t keycode, keyrecord_t *record) { { audio_on(); } - return false; + return false; } if (keycode == MUV_IN && record->event.pressed) { diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index a1e270df1..43bcf973e 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -142,7 +142,8 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through return false; } - return true; + + return true; } bool is_music_on(void) { From a64ae1066250d3aafb6e9670bf617237ec4338e7 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 25 Feb 2017 20:41:13 -0800 Subject: [PATCH 16/20] Update existing keymaps Update existing keymaps to enable MIDI_BASIC functionality. Also added an option MIDI_ENABLE_STRICT to be strict about keycode use (which also reduces memory footprint at runtime) --- keyboards/planck/keymaps/dbroqua/config.h | 29 +++++++++++++++++++ keyboards/planck/keymaps/default/config.h | 29 +++++++++++++++++++ .../planck/keymaps/experimental/config.h | 23 +++++++++++++++ keyboards/planck/keymaps/impossible/config.h | 29 +++++++++++++++++++ keyboards/planck/keymaps/jeebak/config.h | 29 +++++++++++++++++++ keyboards/planck/keymaps/jhenahan/config.h | 23 +++++++++++++++ keyboards/planck/keymaps/premek/config.h | 29 +++++++++++++++++++ keyboards/planck/keymaps/sgoodwin/config.h | 29 +++++++++++++++++++ keyboards/planck/keymaps/smt/config.h | 29 +++++++++++++++++++ .../planck/keymaps/thermal_printer/config.h | 23 +++++++++++++++ keyboards/planck/keymaps/unicode/config.h | 29 +++++++++++++++++++ keyboards/planck/keymaps/xyverz/config.h | 29 +++++++++++++++++++ .../preonic/keymaps/CMD-Preonic/config.h | 29 +++++++++++++++++++ keyboards/preonic/keymaps/default/config.h | 29 +++++++++++++++++++ keyboards/preonic/keymaps/smt/config.h | 29 +++++++++++++++++++ keyboards/satan/keymaps/midi/config.h | 3 ++ keyboards/subatomic/keymaps/default/config.h | 29 +++++++++++++++++++ quantum/process_keycode/process_audio.c | 4 +-- quantum/process_keycode/process_music.c | 2 +- quantum/process_keycode/process_music.h | 1 + quantum/quantum.c | 4 +-- quantum/quantum_keycodes.h | 28 +++++++++--------- quantum/template/config.h | 3 ++ 23 files changed, 472 insertions(+), 19 deletions(-) create mode 100644 keyboards/planck/keymaps/dbroqua/config.h create mode 100644 keyboards/planck/keymaps/default/config.h create mode 100644 keyboards/planck/keymaps/impossible/config.h create mode 100644 keyboards/planck/keymaps/jeebak/config.h create mode 100644 keyboards/planck/keymaps/premek/config.h create mode 100644 keyboards/planck/keymaps/sgoodwin/config.h create mode 100644 keyboards/planck/keymaps/smt/config.h create mode 100644 keyboards/planck/keymaps/unicode/config.h create mode 100644 keyboards/planck/keymaps/xyverz/config.h create mode 100644 keyboards/preonic/keymaps/CMD-Preonic/config.h create mode 100644 keyboards/preonic/keymaps/default/config.h create mode 100644 keyboards/preonic/keymaps/smt/config.h create mode 100644 keyboards/subatomic/keymaps/default/config.h diff --git a/keyboards/planck/keymaps/dbroqua/config.h b/keyboards/planck/keymaps/dbroqua/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/dbroqua/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/default/config.h b/keyboards/planck/keymaps/default/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/default/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/experimental/config.h b/keyboards/planck/keymaps/experimental/config.h index cc093bee4..492490ca1 100644 --- a/keyboards/planck/keymaps/experimental/config.h +++ b/keyboards/planck/keymaps/experimental/config.h @@ -14,4 +14,27 @@ #define RGBLIGHT_HUE_STEP 10 #define RGBLIGHT_SAT_STEP 17 +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + #endif diff --git a/keyboards/planck/keymaps/impossible/config.h b/keyboards/planck/keymaps/impossible/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/impossible/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/jeebak/config.h b/keyboards/planck/keymaps/jeebak/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/jeebak/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/jhenahan/config.h b/keyboards/planck/keymaps/jhenahan/config.h index cd3adc41c..1e42b92b9 100644 --- a/keyboards/planck/keymaps/jhenahan/config.h +++ b/keyboards/planck/keymaps/jhenahan/config.h @@ -6,4 +6,27 @@ #define FORCE_NKRO #define WORKMAN_SOUND COLEMAK_SOUND +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + #endif diff --git a/keyboards/planck/keymaps/premek/config.h b/keyboards/planck/keymaps/premek/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/premek/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/sgoodwin/config.h b/keyboards/planck/keymaps/sgoodwin/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/sgoodwin/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/smt/config.h b/keyboards/planck/keymaps/smt/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/smt/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/thermal_printer/config.h b/keyboards/planck/keymaps/thermal_printer/config.h index 430b6493c..bcd098930 100644 --- a/keyboards/planck/keymaps/thermal_printer/config.h +++ b/keyboards/planck/keymaps/thermal_printer/config.h @@ -20,4 +20,27 @@ sei(); \ } while(0) +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + #endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/unicode/config.h b/keyboards/planck/keymaps/unicode/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/unicode/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/planck/keymaps/xyverz/config.h b/keyboards/planck/keymaps/xyverz/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/planck/keymaps/xyverz/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/preonic/keymaps/CMD-Preonic/config.h b/keyboards/preonic/keymaps/CMD-Preonic/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/preonic/keymaps/CMD-Preonic/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/preonic/keymaps/default/config.h b/keyboards/preonic/keymaps/default/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/preonic/keymaps/default/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/preonic/keymaps/smt/config.h b/keyboards/preonic/keymaps/smt/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/preonic/keymaps/smt/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/keyboards/satan/keymaps/midi/config.h b/keyboards/satan/keymaps/midi/config.h index 59250b49e..8e10b04ec 100644 --- a/keyboards/satan/keymaps/midi/config.h +++ b/keyboards/satan/keymaps/midi/config.h @@ -7,6 +7,9 @@ * MIDI options */ +/* Prevent use of disabled MIDI features in the keymap */ +#define MIDI_ENABLE_STRICT 1 + /* enable basic MIDI features: - MIDI notes can be sent when in Music mode is on */ diff --git a/keyboards/subatomic/keymaps/default/config.h b/keyboards/subatomic/keymaps/default/config.h new file mode 100644 index 000000000..4c6158199 --- /dev/null +++ b/keyboards/subatomic/keymaps/default/config.h @@ -0,0 +1,29 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "../../config.h" + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +#endif \ No newline at end of file diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index d45242c9e..71c0297ee 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -1,5 +1,5 @@ -#include "process_audio.h" #include "audio.h" +#include "process_audio.h" static float compute_freq_for_midi_note(uint8_t note) { @@ -43,7 +43,7 @@ bool process_audio(uint16_t keycode, keyrecord_t *record) { return false; } - return true + return true; } void process_audio_noteon(uint8_t note) { diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 43bcf973e..4b86b91f0 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -42,7 +42,7 @@ static void music_noteoff(uint8_t note) { #endif } -static void music_all_notes_off(void) { +void music_all_notes_off(void) { #ifdef AUDIO_ENABLE process_audio_stop_all_notes(); #endif diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h index 69913b276..a36514a44 100644 --- a/quantum/process_keycode/process_music.h +++ b/quantum/process_keycode/process_music.h @@ -14,6 +14,7 @@ void music_off(void); void music_on_user(void); void music_scale_user(void); +void music_all_notes_off(void); void matrix_scan_music(void); diff --git a/quantum/quantum.c b/quantum/quantum.c index 7a27a568a..a4a12061b 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -95,8 +95,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { void reset_keyboard(void) { clear_keyboard(); -#ifdef AUDIO_ENABLE - stop_all_notes(); +#if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_ENABLE_BASIC)) + music_all_notes_off(); shutdown_user(); #endif wait_ms(250); diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h index 3b82b7208..56228f276 100644 --- a/quantum/quantum_keycodes.h +++ b/quantum/quantum_keycodes.h @@ -1,8 +1,11 @@ - #ifndef QUANTUM_KEYCODES_H #define QUANTUM_KEYCODES_H -#if defined(MIDI_ENABLE) && defined(MIDI_ADVANCED) +#ifndef MIDI_ENABLE_STRICT +#define MIDI_ENABLE_STRICT 0 +#endif + +#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)) #ifndef MIDI_TONE_KEYCODE_OCTAVES #define MIDI_TONE_KEYCODE_OCTAVES 3 #endif @@ -113,18 +116,16 @@ enum quantum_keycodes { MUV_IN, MUV_DE, -#ifdef MIDI_ENABLE // Midi - -#ifdef MIDI_BASIC +#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_BASIC)) MI_ON, // send midi notes when music mode is enabled MI_OFF, // don't send midi notes when music mode is enabled #endif -#ifdef MIDI_ADVANCED +#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED)) MIDI_TONE_MIN, -#if MIDI_TONE_KEYCODE_OCTAVES > 0 +#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 0 MI_C = MIDI_TONE_MIN, MI_Cs, MI_Db = MI_Cs, @@ -144,7 +145,7 @@ enum quantum_keycodes { MI_B, #endif -#if MIDI_TONE_KEYCODE_OCTAVES > 1 +#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 1 MI_C_1, MI_Cs_1, MI_Db_1 = MI_Cs_1, @@ -164,7 +165,7 @@ enum quantum_keycodes { MI_B_1, #endif -#if MIDI_TONE_KEYCODE_OCTAVES > 2 +#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 2 MI_C_2, MI_Cs_2, MI_Db_2 = MI_Cs_2, @@ -184,7 +185,7 @@ enum quantum_keycodes { MI_B_2, #endif -#if MIDI_TONE_KEYCODE_OCTAVES > 3 +#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 3 MI_C_3, MI_Cs_3, MI_Db_3 = MI_Cs_3, @@ -204,7 +205,7 @@ enum quantum_keycodes { MI_B_3, #endif -#if MIDI_TONE_KEYCODE_OCTAVES > 4 +#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 4 MI_C_4, MI_Cs_4, MI_Db_4 = MI_Cs_4, @@ -224,7 +225,7 @@ enum quantum_keycodes { MI_B_4, #endif -#if MIDI_TONE_KEYCODE_OCTAVES > 5 +#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 MI_C_5, MI_Cs_5, MI_Db_5 = MI_Cs_5, @@ -244,7 +245,7 @@ enum quantum_keycodes { MI_B_5, #endif -#if MIDI_TONE_KEYCODE_OCTAVES > 5 +#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 5 MIDI_TONE_MAX = MI_B_5, #elif MIDI_TONE_KEYCODE_OCTAVES > 4 MIDI_TONE_MAX = MI_B_4, @@ -339,7 +340,6 @@ enum quantum_keycodes { MI_MODSD, // decrease modulation speed MI_MODSU, // increase modulation speed #endif // MIDI_ADVANCED -#endif // MIDI_ENABLE // Backlight functionality BL_0, diff --git a/quantum/template/config.h b/quantum/template/config.h index 54db4f242..7393097e1 100644 --- a/quantum/template/config.h +++ b/quantum/template/config.h @@ -163,6 +163,9 @@ along with this program. If not, see . * MIDI options */ +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + /* enable basic MIDI features: - MIDI notes can be sent when in Music mode is on */ From b911e1966f6e9077df01c01d77b4e2018b582eb0 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 25 Feb 2017 21:13:47 -0800 Subject: [PATCH 17/20] Fix redundant process_music.c in sources --- build_keyboard.mk | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/build_keyboard.mk b/build_keyboard.mk index 07dfe85b4..82464d583 100644 --- a/build_keyboard.mk +++ b/build_keyboard.mk @@ -23,9 +23,9 @@ ifdef master MASTER = $(master) endif -ifeq ($(MASTER),right) +ifeq ($(MASTER),right) OPT_DEFS += -DMASTER_IS_ON_RIGHT -else +else ifneq ($(MASTER),left) $(error MASTER does not have a valid value(left/right)) endif @@ -38,7 +38,7 @@ KEYBOARD_C := $(KEYBOARD_PATH)/$(KEYBOARD).c ifneq ("$(wildcard $(KEYBOARD_C))","") include $(KEYBOARD_PATH)/rules.mk -else +else $(error "$(KEYBOARD_C)" does not exist) endif @@ -49,7 +49,7 @@ ifneq ($(SUBPROJECT),) ifneq ("$(wildcard $(SUBPROJECT_C))","") OPT_DEFS += -DSUBPROJECT_$(SUBPROJECT) include $(SUBPROJECT_PATH)/rules.mk - else + else $(error "$(SUBPROJECT_PATH)/$(SUBPROJECT).c" does not exist) endif endif @@ -83,7 +83,7 @@ ifneq ($(SUBPROJECT),) endif endif -# Save the defines and includes here, so we don't include any keymap specific ones +# Save the defines and includes here, so we don't include any keymap specific ones PROJECT_DEFS := $(OPT_DEFS) PROJECT_INC := $(VPATH) $(EXTRAINCDIRS) $(SUBPROJECT_PATH) $(KEYBOARD_PATH) PROJECT_CONFIG := $(CONFIG_H) @@ -139,12 +139,27 @@ ifeq ($(strip $(API_SYSEX_ENABLE)), yes) MIDI_ENABLE=yes endif +MUSIC_ENABLE := 0 + +ifeq ($(strip $(AUDIO_ENABLE)), yes) + OPT_DEFS += -DAUDIO_ENABLE + MUSIC_ENABLE := 1 + SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c + SRC += $(QUANTUM_DIR)/audio/audio.c + SRC += $(QUANTUM_DIR)/audio/voices.c + SRC += $(QUANTUM_DIR)/audio/luts.c +endif + ifeq ($(strip $(MIDI_ENABLE)), yes) OPT_DEFS += -DMIDI_ENABLE - SRC += $(QUANTUM_DIR)/process_keycode/process_music.c + MUSIC_ENABLE := 1 SRC += $(QUANTUM_DIR)/process_keycode/process_midi.c endif +ifeq ($(MUSIC_ENABLE), 1) + SRC += $(QUANTUM_DIR)/process_keycode/process_music.c +endif + ifeq ($(strip $(COMBO_ENABLE)), yes) OPT_DEFS += -DCOMBO_ENABLE SRC += $(QUANTUM_DIR)/process_keycode/process_combo.c @@ -154,15 +169,6 @@ ifeq ($(strip $(VIRTSER_ENABLE)), yes) OPT_DEFS += -DVIRTSER_ENABLE endif -ifeq ($(strip $(AUDIO_ENABLE)), yes) - OPT_DEFS += -DAUDIO_ENABLE - SRC += $(QUANTUM_DIR)/process_keycode/process_music.c - SRC += $(QUANTUM_DIR)/process_keycode/process_audio.c - SRC += $(QUANTUM_DIR)/audio/audio.c - SRC += $(QUANTUM_DIR)/audio/voices.c - SRC += $(QUANTUM_DIR)/audio/luts.c -endif - ifeq ($(strip $(FAUXCLICKY_ENABLE)), yes) OPT_DEFS += -DFAUXCLICKY_ENABLE SRC += $(QUANTUM_DIR)/fauxclicky.c @@ -252,7 +258,7 @@ endif OUTPUTS := $(KEYMAP_OUTPUT) $(KEYBOARD_OUTPUT) $(KEYMAP_OUTPUT)_SRC := $(SRC) -$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) -DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYMAP=\"$(KEYMAP)\" +$(KEYMAP_OUTPUT)_DEFS := $(OPT_DEFS) -DQMK_KEYBOARD=\"$(KEYBOARD)\" -DQMK_KEYMAP=\"$(KEYMAP)\" $(KEYMAP_OUTPUT)_INC := $(VPATH) $(EXTRAINCDIRS) $(KEYMAP_OUTPUT)_CONFIG := $(CONFIG_H) $(KEYBOARD_OUTPUT)_SRC := $(CHIBISRC) From 976c856966841cd0be6e514c6365c73164f5b96d Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Sat, 25 Feb 2017 21:38:35 -0800 Subject: [PATCH 18/20] Update size estimates in the Makefile MIDI_ENABLE = no text data bss dec hex filename 0 17080 0 17080 42b8 satan_midi.hex MIDI_ENABLE = yes MIDI_BASIC undefined MIDI_ADVANCED undefined text data bss dec hex filename 0 19494 0 19494 4c26 satan_midi.hex +2414 bytes (vs. MIDI_ENABLE = no) MIDI_ENABLE = yes 0 20846 0 20846 516e satan_midi.hex +1352 bytes (vs. MIDI_ENABLE = yes, MIDI_BASIC off, MIDI_ADVANCED off) MIDI_ENABLE = yes #define MIDI_BASIC #define MIDI_ADVANCED text data bss dec hex filename 0 21292 0 21292 532c satan_midi.hex +1798 bytes (vs. MIDI_ENABLE = yes, MIDI_BASIC off, MIDI_ADVANCED off) Conclusion: +2400 to 4200, depending on config --- keyboards/satan/keymaps/midi/Makefile | 2 +- quantum/template/rules.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/keyboards/satan/keymaps/midi/Makefile b/keyboards/satan/keymaps/midi/Makefile index 4e2d9d2f7..89c34b394 100644 --- a/keyboards/satan/keymaps/midi/Makefile +++ b/keyboards/satan/keymaps/midi/Makefile @@ -9,7 +9,7 @@ CONSOLE_ENABLE = no # Console for debug(+400) COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work BACKLIGHT_ENABLE = yes # Enable keyboard backlight functionality -MIDI_ENABLE = yes # MIDI support (+3800) +MIDI_ENABLE = yes # MIDI support (+2400 to 4200, depending on config) AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID diff --git a/quantum/template/rules.mk b/quantum/template/rules.mk index bad3387bf..a1f9377d8 100644 --- a/quantum/template/rules.mk +++ b/quantum/template/rules.mk @@ -61,7 +61,7 @@ SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend # if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work NKRO_ENABLE ?= no # USB Nkey Rollover BACKLIGHT_ENABLE ?= no # Enable keyboard backlight functionality on B7 by default -MIDI_ENABLE ?= no # MIDI controls +MIDI_ENABLE ?= no # MIDI support (+2400 to 4200, depending on config) UNICODE_ENABLE ?= no # Unicode BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID AUDIO_ENABLE ?= no # Audio output on port C6 From d11962aeb27c73b87f8154d7f2cee747c8858d09 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Thu, 2 Mar 2017 11:40:06 -0800 Subject: [PATCH 19/20] fix 'stop_all_notes' naming to be more consistent --- quantum/process_keycode/process_audio.c | 2 +- quantum/process_keycode/process_audio.h | 2 +- quantum/process_keycode/process_midi.c | 2 +- quantum/process_keycode/process_midi.h | 2 +- quantum/process_keycode/process_music.c | 4 ++-- quantum/template/keymaps/default/Makefile | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index 71c0297ee..0b6380ed3 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -54,7 +54,7 @@ void process_audio_noteoff(uint8_t note) { stop_note(compute_freq_for_midi_note(note)); } -void process_audio_stop_all_notes(void) { +void process_audio_all_notes_off(void) { stop_all_notes(); } diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h index 59a17725a..7ac15b733 100644 --- a/quantum/process_keycode/process_audio.h +++ b/quantum/process_keycode/process_audio.h @@ -4,7 +4,7 @@ bool process_audio(uint16_t keycode, keyrecord_t *record); void process_audio_noteon(uint8_t note); void process_audio_noteoff(uint8_t note); -void process_audio_stop_all_notes(void); +void process_audio_all_notes_off(void); void audio_on_user(void); diff --git a/quantum/process_keycode/process_midi.c b/quantum/process_keycode/process_midi.c index 214bba902..700c6ce8e 100644 --- a/quantum/process_keycode/process_midi.c +++ b/quantum/process_keycode/process_midi.c @@ -15,7 +15,7 @@ void process_midi_basic_noteoff(uint8_t note) midi_send_noteoff(&midi_device, 0, note, 0); } -void process_midi_basic_stop_all_notes(void) +void process_midi_all_notes_off(void) { midi_send_cc(&midi_device, 0, 0x7B, 0); } diff --git a/quantum/process_keycode/process_midi.h b/quantum/process_keycode/process_midi.h index 0f559ec23..58b7650c6 100644 --- a/quantum/process_keycode/process_midi.h +++ b/quantum/process_keycode/process_midi.h @@ -8,7 +8,7 @@ #ifdef MIDI_BASIC void process_midi_basic_noteon(uint8_t note); void process_midi_basic_noteoff(uint8_t note); -void process_midi_basic_stop_all_notes(void); +void process_midi_all_notes_off(void); #endif #ifdef MIDI_ADVANCED diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 4b86b91f0..f89a04ee3 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -44,10 +44,10 @@ static void music_noteoff(uint8_t note) { void music_all_notes_off(void) { #ifdef AUDIO_ENABLE - process_audio_stop_all_notes(); + process_audio_all_notes_off(); #endif #if defined(MIDI_ENABLE) && defined(MIDI_BASIC) - process_midi_basic_stop_all_notes(); + process_midi_all_notes_off(); #endif } diff --git a/quantum/template/keymaps/default/Makefile b/quantum/template/keymaps/default/Makefile index 24442db37..29f11bbc7 100644 --- a/quantum/template/keymaps/default/Makefile +++ b/quantum/template/keymaps/default/Makefile @@ -9,7 +9,7 @@ CONSOLE_ENABLE = no # Console for debug(+400) COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # Nkey Rollover - if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work BACKLIGHT_ENABLE = no # Enable keyboard backlight functionality -MIDI_ENABLE = no # MIDI support (+3800) +MIDI_ENABLE = no # MIDI support (+2400 to 4200, depending on config) AUDIO_ENABLE = no # Audio output on port C6 UNICODE_ENABLE = no # Unicode BLUETOOTH_ENABLE = no # Enable Bluetooth with the Adafruit EZ-Key HID From 0734f569409974624b40735fcd498dac9adba2d2 Mon Sep 17 00:00:00 2001 From: Gabriel Young Date: Thu, 2 Mar 2017 12:28:12 -0800 Subject: [PATCH 20/20] add debug messages to audio --- quantum/audio/audio.c | 294 +++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 144 deletions(-) diff --git a/quantum/audio/audio.c b/quantum/audio/audio.c index 2a315fd16..e1e81fd2b 100644 --- a/quantum/audio/audio.c +++ b/quantum/audio/audio.c @@ -89,15 +89,15 @@ void audio_init() } audio_config.raw = eeconfig_read_audio(); - // Set port PC6 (OC3A and /OC4A) as output + // Set port PC6 (OC3A and /OC4A) as output DDRC |= _BV(PORTC6); DISABLE_AUDIO_COUNTER_3_ISR; - // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers - // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 - // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) - // Clock Select (CS3n) = 0b010 = Clock / 8 + // TCCR3A / TCCR3B: Timer/Counter #3 Control Registers + // Compare Output Mode (COM3An) = 0b00 = Normal port operation, OC3A disconnected from PC6 + // Waveform Generation Mode (WGM3n) = 0b1110 = Fast PWM Mode 14 (Period = ICR3, Duty Cycle = OCR3A) + // Clock Select (CS3n) = 0b010 = Clock / 8 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30); TCCR3B = (1 << WGM33) | (1 << WGM32) | (0 << CS32) | (1 << CS31) | (0 << CS30); @@ -106,6 +106,8 @@ void audio_init() void stop_all_notes() { + dprintf("audio stop all notes"); + if (!audio_initialized) { audio_init(); } @@ -128,6 +130,8 @@ void stop_all_notes() void stop_note(float freq) { + dprintf("audio stop note freq=%d", (int)freq); + if (playing_note) { if (!audio_initialized) { audio_init(); @@ -183,159 +187,161 @@ float vibrato(float average_freq) { ISR(TIMER3_COMPA_vect) { - float freq; + float freq; - if (playing_note) { - if (voices > 0) { - if (polyphony_rate > 0) { - if (voices > 1) { - voice_place %= voices; - if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) { - voice_place = (voice_place + 1) % voices; - place = 0.0; - } - } + if (playing_note) { + if (voices > 0) { + if (polyphony_rate > 0) { + if (voices > 1) { + voice_place %= voices; + if (place++ > (frequencies[voice_place] / polyphony_rate / CPU_PRESCALER)) { + voice_place = (voice_place + 1) % voices; + place = 0.0; + } + } - #ifdef VIBRATO_ENABLE - if (vibrato_strength > 0) { - freq = vibrato(frequencies[voice_place]); - } else { - freq = frequencies[voice_place]; - } - #else - freq = frequencies[voice_place]; - #endif - } else { - if (glissando) { - if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { - frequency = frequency * pow(2, 440/frequency/12/2); - } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { - frequency = frequency * pow(2, -440/frequency/12/2); - } else { - frequency = frequencies[voices - 1]; - } - } else { - frequency = frequencies[voices - 1]; - } + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequencies[voice_place]); + } else { + freq = frequencies[voice_place]; + } + #else + freq = frequencies[voice_place]; + #endif + } else { + if (glissando) { + if (frequency != 0 && frequency < frequencies[voices - 1] && frequency < frequencies[voices - 1] * pow(2, -440/frequencies[voices - 1]/12/2)) { + frequency = frequency * pow(2, 440/frequency/12/2); + } else if (frequency != 0 && frequency > frequencies[voices - 1] && frequency > frequencies[voices - 1] * pow(2, 440/frequencies[voices - 1]/12/2)) { + frequency = frequency * pow(2, -440/frequency/12/2); + } else { + frequency = frequencies[voices - 1]; + } + } else { + frequency = frequencies[voices - 1]; + } - #ifdef VIBRATO_ENABLE - if (vibrato_strength > 0) { - freq = vibrato(frequency); - } else { - freq = frequency; - } - #else - freq = frequency; - #endif - } + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(frequency); + } else { + freq = frequency; + } + #else + freq = frequency; + #endif + } - if (envelope_index < 65535) { - envelope_index++; - } + if (envelope_index < 65535) { + envelope_index++; + } - freq = voice_envelope(freq); + freq = voice_envelope(freq); - if (freq < 30.517578125) { - freq = 30.52; - } + if (freq < 30.517578125) { + freq = 30.52; + } - TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); - TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); - } - } + TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); + TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); + } + } - if (playing_notes) { - if (note_frequency > 0) { - #ifdef VIBRATO_ENABLE - if (vibrato_strength > 0) { - freq = vibrato(note_frequency); - } else { - freq = note_frequency; - } - #else - freq = note_frequency; - #endif + if (playing_notes) { + if (note_frequency > 0) { + #ifdef VIBRATO_ENABLE + if (vibrato_strength > 0) { + freq = vibrato(note_frequency); + } else { + freq = note_frequency; + } + #else + freq = note_frequency; + #endif - if (envelope_index < 65535) { - envelope_index++; - } - freq = voice_envelope(freq); + if (envelope_index < 65535) { + envelope_index++; + } + freq = voice_envelope(freq); - TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); - TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); - } else { - TIMER_3_PERIOD = 0; - TIMER_3_DUTY_CYCLE = 0; - } + TIMER_3_PERIOD = (uint16_t)(((float)F_CPU) / (freq * CPU_PRESCALER)); + TIMER_3_DUTY_CYCLE = (uint16_t)((((float)F_CPU) / (freq * CPU_PRESCALER)) * note_timbre); + } else { + TIMER_3_PERIOD = 0; + TIMER_3_DUTY_CYCLE = 0; + } - note_position++; - bool end_of_note = false; - if (TIMER_3_PERIOD > 0) { - end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF)); - } else { - end_of_note = (note_position >= (note_length * 0x7FF)); - } + note_position++; + bool end_of_note = false; + if (TIMER_3_PERIOD > 0) { + end_of_note = (note_position >= (note_length / TIMER_3_PERIOD * 0xFFFF)); + } else { + end_of_note = (note_position >= (note_length * 0x7FF)); + } - if (end_of_note) { - current_note++; - if (current_note >= notes_count) { - if (notes_repeat) { - current_note = 0; - } else { - DISABLE_AUDIO_COUNTER_3_ISR; - DISABLE_AUDIO_COUNTER_3_OUTPUT; - playing_notes = false; - return; - } - } - if (!note_resting && (notes_rest > 0)) { - note_resting = true; - note_frequency = 0; - note_length = notes_rest; - current_note--; - } else { - note_resting = false; - envelope_index = 0; - note_frequency = (*notes_pointer)[current_note][0]; - note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); - } + if (end_of_note) { + current_note++; + if (current_note >= notes_count) { + if (notes_repeat) { + current_note = 0; + } else { + DISABLE_AUDIO_COUNTER_3_ISR; + DISABLE_AUDIO_COUNTER_3_OUTPUT; + playing_notes = false; + return; + } + } + if (!note_resting && (notes_rest > 0)) { + note_resting = true; + note_frequency = 0; + note_length = notes_rest; + current_note--; + } else { + note_resting = false; + envelope_index = 0; + note_frequency = (*notes_pointer)[current_note][0]; + note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); + } - note_position = 0; - } - } + note_position = 0; + } + } - if (!audio_config.enable) { - playing_notes = false; - playing_note = false; - } + if (!audio_config.enable) { + playing_notes = false; + playing_note = false; + } } void play_note(float freq, int vol) { + dprintf("audio play note freq=%d vol=%d", (int)freq, vol); + if (!audio_initialized) { audio_init(); } - if (audio_config.enable && voices < 8) { - DISABLE_AUDIO_COUNTER_3_ISR; + if (audio_config.enable && voices < 8) { + DISABLE_AUDIO_COUNTER_3_ISR; - // Cancel notes if notes are playing - if (playing_notes) - stop_all_notes(); + // Cancel notes if notes are playing + if (playing_notes) + stop_all_notes(); - playing_note = true; + playing_note = true; - envelope_index = 0; + envelope_index = 0; - if (freq > 0) { - frequencies[voices] = freq; - volumes[voices] = vol; - voices++; - } + if (freq > 0) { + frequencies[voices] = freq; + volumes[voices] = vol; + voices++; + } ENABLE_AUDIO_COUNTER_3_ISR; ENABLE_AUDIO_COUNTER_3_OUTPUT; - } + } } @@ -346,37 +352,37 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat, float n_rest) audio_init(); } - if (audio_config.enable) { + if (audio_config.enable) { - DISABLE_AUDIO_COUNTER_3_ISR; + DISABLE_AUDIO_COUNTER_3_ISR; - // Cancel note if a note is playing - if (playing_note) - stop_all_notes(); + // Cancel note if a note is playing + if (playing_note) + stop_all_notes(); - playing_notes = true; + playing_notes = true; - notes_pointer = np; - notes_count = n_count; - notes_repeat = n_repeat; - notes_rest = n_rest; + notes_pointer = np; + notes_count = n_count; + notes_repeat = n_repeat; + notes_rest = n_rest; - place = 0; - current_note = 0; + place = 0; + current_note = 0; note_frequency = (*notes_pointer)[current_note][0]; note_length = ((*notes_pointer)[current_note][1] / 4) * (((float)note_tempo) / 100); - note_position = 0; + note_position = 0; ENABLE_AUDIO_COUNTER_3_ISR; ENABLE_AUDIO_COUNTER_3_OUTPUT; - } + } } bool is_playing_notes(void) { - return playing_notes; + return playing_notes; } bool is_audio_on(void) {