diff options
| author | Gabriel Young <gabeplaysdrums@live.com> | 2017-02-18 03:12:13 -0800 |
|---|---|---|
| committer | Gabriel Young <gabeplaysdrums@live.com> | 2017-02-19 16:41:59 -0800 |
| commit | e405ab4bc6ff47d189d99c4d51aadf60a642d82a (patch) | |
| tree | 60d81499162c5a8a6d5e479f2acb2bba7dfe3392 | |
| parent | 5ae1411fc387a682d3e22f5cddfe1102e3312af5 (diff) | |
| download | qmk_firmware-e405ab4bc6ff47d189d99c4d51aadf60a642d82a.tar.gz qmk_firmware-e405ab4bc6ff47d189d99c4d51aadf60a642d82a.zip | |
initial implementation of polyphony using variable length array of notes on
| -rw-r--r-- | quantum/process_keycode/process_midi.c | 199 | ||||
| -rw-r--r-- | quantum/process_keycode/process_midi.h | 3 | ||||
| -rw-r--r-- | quantum/quantum_keycodes.h | 1 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 13 | ||||
| -rw-r--r-- | 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 @@ | |||
| 1 | #include "process_midi.h" | 1 | #include "process_midi.h" |
| 2 | 2 | ||
| 3 | #if 0 | ||
| 3 | bool midi_activated = false; | 4 | bool midi_activated = false; |
| 4 | uint8_t midi_starting_note = 0x0C; | 5 | uint8_t midi_starting_note = 0x0C; |
| 5 | int midi_offset = 7; | 6 | int midi_offset = 7; |
| 7 | #endif | ||
| 8 | |||
| 9 | typedef union { | ||
| 10 | uint16_t raw; | ||
| 11 | struct { | ||
| 12 | uint8_t octave :4; | ||
| 13 | uint8_t velocity :4; | ||
| 14 | uint8_t channel :4; | ||
| 15 | }; | ||
| 16 | } midi_config_t; | ||
| 17 | |||
| 18 | midi_config_t midi_config; | ||
| 19 | |||
| 20 | #define MIDI_INVALID_NOTE 0xFF | ||
| 21 | |||
| 22 | #if 0 | ||
| 23 | typedef struct { | ||
| 24 | uint64_t low; | ||
| 25 | uint64_t high; | ||
| 26 | } uint128_t; | ||
| 27 | |||
| 28 | #if 0 | ||
| 29 | static void right_shift_uint128_t(uint128_t* val, uint8_t shift) | ||
| 30 | { | ||
| 31 | uint64_t high_mask = ~0 >> (64 - shift); | ||
| 32 | uint64_t high_bits = (val->high & high_mask) << (64 - shift); | ||
| 33 | val->high = val->high >> shift; | ||
| 34 | val->low = (val->low >> shift) | high_bits; | ||
| 35 | } | ||
| 36 | #endif | ||
| 37 | |||
| 38 | static uint64_t left_shift_uint64_t(uint64_t val, uint8_t shift) | ||
| 39 | { | ||
| 40 | dprintf("left_shift_uint64_t(val, %c) ...\n", val, shift); | ||
| 41 | while (shift > 16u) { | ||
| 42 | dprintf(" left_shift_uint64_t: val=?, shift=%c\n", val, shift); | ||
| 43 | val <<= 16; | ||
| 44 | shift -= 16; | ||
| 45 | } | ||
| 46 | dprintf(" left_shift_uint64_t: val=?, shift=%c\n", val, shift); | ||
| 47 | val <<= shift; | ||
| 48 | return val; | ||
| 49 | } | ||
| 50 | |||
| 51 | static void set_bit_uint128_t(uint128_t* val, uint8_t shift) | ||
| 52 | { | ||
| 53 | uint64_t x = 1u; | ||
| 54 | |||
| 55 | if (shift < 64) | ||
| 56 | { | ||
| 57 | x = left_shift_uint64_t(x, shift); | ||
| 58 | dprintf("x: %d\n", x); | ||
| 59 | dprintf("set_bit_uint128_t (%d): 0x%016X%016X\n", shift, 0, x); | ||
| 60 | val->low = val->low | left_shift_uint64_t(1u, shift); | ||
| 61 | } | ||
| 62 | else | ||
| 63 | { | ||
| 64 | x = left_shift_uint64_t(x, shift - 64); | ||
| 65 | dprintf("set_bit_uint128_t (%d): 0x%016X%016X\n", shift, x, 0); | ||
| 66 | val->high = val->high | left_shift_uint64_t(1u, shift - 64); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | static void clear_bit_uint128_t(uint128_t* val, uint8_t shift) | ||
| 71 | { | ||
| 72 | if (shift < 64) | ||
| 73 | { | ||
| 74 | val->low = val->low & ~left_shift_uint64_t(1u, shift); | ||
| 75 | } | ||
| 76 | else | ||
| 77 | { | ||
| 78 | val->high = val->high & ~left_shift_uint64_t(1u, shift - 64); | ||
| 79 | } | ||
| 80 | } | ||
| 6 | 81 | ||
| 7 | bool process_midi(uint16_t keycode, keyrecord_t *record) { | 82 | static bool is_bit_set_uint128_t(const uint128_t* val, uint8_t shift) |
| 83 | { | ||
| 84 | if (shift < 64) | ||
| 85 | { | ||
| 86 | return !!(val->low & (1u << shift)); | ||
| 87 | } | ||
| 88 | else | ||
| 89 | { | ||
| 90 | return !!(val->high & (1u << (shift - 64))); | ||
| 91 | } | ||
| 92 | } | ||
| 93 | |||
| 94 | uint128_t note_status = { 0, 0 }; | ||
| 95 | #endif | ||
| 96 | |||
| 97 | |||
| 98 | #define MIDI_MAX_NOTES_ON 10 | ||
| 99 | |||
| 100 | typedef struct { | ||
| 101 | uint8_t note; | ||
| 102 | uint8_t tone; | ||
| 103 | } midi_notes_on_array_entry_t; | ||
| 104 | |||
| 105 | typedef struct { | ||
| 106 | uint8_t length; | ||
| 107 | midi_notes_on_array_entry_t values[MIDI_MAX_NOTES_ON]; | ||
| 108 | } midi_notes_on_array_t; | ||
| 109 | |||
| 110 | static midi_notes_on_array_t notes_on; | ||
| 111 | |||
| 112 | inline uint8_t compute_velocity(uint8_t setting) | ||
| 113 | { | ||
| 114 | return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1)); | ||
| 115 | } | ||
| 116 | |||
| 117 | void midi_init(void) | ||
| 118 | { | ||
| 119 | midi_config.octave = MI_OCT_0 - MIDI_OCTAVE_MIN; | ||
| 120 | midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN); | ||
| 121 | midi_config.channel = 0; | ||
| 122 | notes_on.length = 0; | ||
| 123 | } | ||
| 124 | |||
| 125 | bool process_midi(uint16_t keycode, keyrecord_t *record) | ||
| 126 | { | ||
| 127 | switch (keycode) { | ||
| 128 | case MIDI_TONE_MIN ... MIDI_TONE_MAX: | ||
| 129 | { | ||
| 130 | uint8_t channel = midi_config.channel; | ||
| 131 | uint8_t tone = keycode - MIDI_TONE_MIN; | ||
| 132 | uint8_t velocity = compute_velocity(midi_config.velocity); | ||
| 133 | if (record->event.pressed && notes_on.length < MIDI_MAX_NOTES_ON) { | ||
| 134 | uint8_t note = 12 * midi_config.octave + tone; | ||
| 135 | midi_send_noteon(&midi_device, channel, note, velocity); | ||
| 136 | dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity); | ||
| 137 | notes_on.values[notes_on.length].note = note; | ||
| 138 | notes_on.values[notes_on.length].tone = tone; | ||
| 139 | notes_on.length++; | ||
| 140 | } | ||
| 141 | else { | ||
| 142 | for (uint8_t i = 0; i < notes_on.length; i++) { | ||
| 143 | uint8_t note = notes_on.values[i].note; | ||
| 144 | if (tone == notes_on.values[i].tone) { | ||
| 145 | midi_send_noteoff(&midi_device, channel, note, velocity); | ||
| 146 | dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity); | ||
| 147 | |||
| 148 | for (uint8_t j=i; j < notes_on.length - 1; j++) | ||
| 149 | { | ||
| 150 | notes_on.values[j] = notes_on.values[j + 1]; | ||
| 151 | } | ||
| 152 | |||
| 153 | notes_on.length--; | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } | ||
| 158 | return false; | ||
| 159 | } | ||
| 160 | case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX: | ||
| 161 | if (record->event.pressed) | ||
| 162 | midi_config.octave = keycode - MIDI_OCTAVE_MIN; | ||
| 163 | return false; | ||
| 164 | case MI_OCTD: | ||
| 165 | if (record->event.pressed && midi_config.octave > 0) | ||
| 166 | midi_config.octave--; | ||
| 167 | return false; | ||
| 168 | case MI_OCTU: | ||
| 169 | if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) | ||
| 170 | midi_config.octave++; | ||
| 171 | return false; | ||
| 172 | case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX: | ||
| 173 | if (record->event.pressed) | ||
| 174 | midi_config.velocity = keycode - MIDI_VELOCITY_MIN; | ||
| 175 | return false; | ||
| 176 | case MI_VELD: | ||
| 177 | if (record->event.pressed && midi_config.velocity > 0) | ||
| 178 | midi_config.velocity--; | ||
| 179 | return false; | ||
| 180 | case MI_VELU: | ||
| 181 | if (record->event.pressed) | ||
| 182 | midi_config.velocity++; | ||
| 183 | return false; | ||
| 184 | case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX: | ||
| 185 | if (record->event.pressed) | ||
| 186 | midi_config.channel = keycode - MIDI_CHANNEL_MIN; | ||
| 187 | return false; | ||
| 188 | case MI_CHD: | ||
| 189 | if (record->event.pressed) | ||
| 190 | midi_config.channel--; | ||
| 191 | return false; | ||
| 192 | case MI_CHU: | ||
| 193 | if (record->event.pressed) | ||
| 194 | midi_config.channel++; | ||
| 195 | return false; | ||
| 196 | case MI_SUS: | ||
| 197 | //TODO | ||
| 198 | return false; | ||
| 199 | }; | ||
| 200 | |||
| 201 | #if 0 | ||
| 8 | if (keycode == MI_ON && record->event.pressed) { | 202 | if (keycode == MI_ON && record->event.pressed) { |
| 9 | midi_activated = true; | 203 | midi_activated = true; |
| 10 | #ifdef AUDIO_ENABLE | 204 | #ifdef AUDIO_ENABLE |
| @@ -64,5 +258,6 @@ bool process_midi(uint16_t keycode, keyrecord_t *record) { | |||
| 64 | if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through | 258 | if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through |
| 65 | return false; | 259 | return false; |
| 66 | } | 260 | } |
| 67 | return true; | 261 | #endif |
| 262 | return true; | ||
| 68 | } | 263 | } |
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 @@ | |||
| 2 | #define PROCESS_MIDI_H | 2 | #define PROCESS_MIDI_H |
| 3 | 3 | ||
| 4 | #include "quantum.h" | 4 | #include "quantum.h" |
| 5 | #include "midi.h" | ||
| 6 | |||
| 7 | void midi_init(void); | ||
| 5 | 8 | ||
| 6 | bool process_midi(uint16_t keycode, keyrecord_t *record); | 9 | bool process_midi(uint16_t keycode, keyrecord_t *record); |
| 7 | 10 | ||
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 { | |||
| 189 | MI_VEL_1 = MIDI_VELOCITY_MIN, | 189 | MI_VEL_1 = MIDI_VELOCITY_MIN, |
| 190 | MI_VEL_2, | 190 | MI_VEL_2, |
| 191 | MI_VEL_3, | 191 | MI_VEL_3, |
| 192 | MI_VEL_4, | ||
| 192 | MI_VEL_5, | 193 | MI_VEL_5, |
| 193 | MI_VEL_6, | 194 | MI_VEL_6, |
| 194 | MI_VEL_7, | 195 | 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, | |||
| 1101 | uint8_t chan, uint8_t num, uint8_t val); | 1101 | uint8_t chan, uint8_t num, uint8_t val); |
| 1102 | void sysex_callback(MidiDevice * device, | 1102 | void sysex_callback(MidiDevice * device, |
| 1103 | uint16_t start, uint8_t length, uint8_t * data); | 1103 | uint16_t start, uint8_t length, uint8_t * data); |
| 1104 | |||
| 1105 | void setup_midi(void) | ||
| 1106 | { | ||
| 1107 | midi_init(); | ||
| 1108 | midi_device_init(&midi_device); | ||
| 1109 | midi_device_set_send_func(&midi_device, usb_send_func); | ||
| 1110 | midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); | ||
| 1111 | } | ||
| 1104 | #endif | 1112 | #endif |
| 1105 | 1113 | ||
| 1106 | int main(void) __attribute__ ((weak)); | 1114 | int main(void) __attribute__ ((weak)); |
| 1107 | int main(void) | 1115 | int main(void) |
| 1108 | { | 1116 | { |
| 1109 | |||
| 1110 | #ifdef MIDI_ENABLE | 1117 | #ifdef MIDI_ENABLE |
| 1111 | midi_device_init(&midi_device); | 1118 | setup_midi(); |
| 1112 | midi_device_set_send_func(&midi_device, usb_send_func); | ||
| 1113 | midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); | ||
| 1114 | #endif | 1119 | #endif |
| 1115 | 1120 | ||
| 1116 | setup_mcu(); | 1121 | 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 @@ | |||
| 49 | #include <LUFA/Drivers/USB/USB.h> | 49 | #include <LUFA/Drivers/USB/USB.h> |
| 50 | #include "host.h" | 50 | #include "host.h" |
| 51 | #ifdef MIDI_ENABLE | 51 | #ifdef MIDI_ENABLE |
| 52 | #include "midi.h" | 52 | #include "process_midi.h" |
| 53 | #endif | 53 | #endif |
| 54 | #ifdef __cplusplus | 54 | #ifdef __cplusplus |
| 55 | extern "C" { | 55 | extern "C" { |
