mirror of
				https://github.com/mfulz/qmk_firmware.git
				synced 2025-10-31 05:12:33 +01:00 
			
		
		
		
	initial implementation of polyphony using variable length array of notes on
This commit is contained in:
		
							parent
							
								
									5ae1411fc3
								
							
						
					
					
						commit
						e405ab4bc6
					
				| @ -1,10 +1,204 @@ | |||||||
| #include "process_midi.h" | #include "process_midi.h" | ||||||
| 
 | 
 | ||||||
|  | #if 0 | ||||||
| bool midi_activated = false; | bool midi_activated = false; | ||||||
| uint8_t midi_starting_note = 0x0C; | uint8_t midi_starting_note = 0x0C; | ||||||
| int midi_offset = 7; | 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) { |     if (keycode == MI_ON && record->event.pressed) { | ||||||
|       midi_activated = true; |       midi_activated = true; | ||||||
| #ifdef AUDIO_ENABLE | #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
 |       if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
 | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  | #endif | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,9 @@ | |||||||
| #define PROCESS_MIDI_H | #define PROCESS_MIDI_H | ||||||
| 
 | 
 | ||||||
| #include "quantum.h" | #include "quantum.h" | ||||||
|  | #include "midi.h" | ||||||
|  | 
 | ||||||
|  | void midi_init(void); | ||||||
| 
 | 
 | ||||||
| bool process_midi(uint16_t keycode, keyrecord_t *record); | bool process_midi(uint16_t keycode, keyrecord_t *record); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -189,6 +189,7 @@ enum quantum_keycodes { | |||||||
|     MI_VEL_1 = MIDI_VELOCITY_MIN, |     MI_VEL_1 = MIDI_VELOCITY_MIN, | ||||||
|     MI_VEL_2, |     MI_VEL_2, | ||||||
|     MI_VEL_3, |     MI_VEL_3, | ||||||
|  |     MI_VEL_4, | ||||||
|     MI_VEL_5, |     MI_VEL_5, | ||||||
|     MI_VEL_6, |     MI_VEL_6, | ||||||
|     MI_VEL_7, |     MI_VEL_7, | ||||||
|  | |||||||
| @ -1101,16 +1101,21 @@ void cc_callback(MidiDevice * device, | |||||||
|     uint8_t chan, uint8_t num, uint8_t val); |     uint8_t chan, uint8_t num, uint8_t val); | ||||||
| void sysex_callback(MidiDevice * device, | void sysex_callback(MidiDevice * device, | ||||||
|     uint16_t start, uint8_t length, uint8_t * data); |     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 | #endif | ||||||
| 
 | 
 | ||||||
| int main(void)  __attribute__ ((weak)); | int main(void)  __attribute__ ((weak)); | ||||||
| int main(void) | int main(void) | ||||||
| { | { | ||||||
| 
 |  | ||||||
| #ifdef MIDI_ENABLE | #ifdef MIDI_ENABLE | ||||||
|     midi_device_init(&midi_device); |     setup_midi(); | ||||||
|     midi_device_set_send_func(&midi_device, usb_send_func); |  | ||||||
|     midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     setup_mcu(); |     setup_mcu(); | ||||||
|  | |||||||
| @ -49,7 +49,7 @@ | |||||||
| #include <LUFA/Drivers/USB/USB.h> | #include <LUFA/Drivers/USB/USB.h> | ||||||
| #include "host.h" | #include "host.h" | ||||||
| #ifdef MIDI_ENABLE | #ifdef MIDI_ENABLE | ||||||
|   #include "midi.h" |   #include "process_midi.h" | ||||||
| #endif | #endif | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Gabriel Young
						Gabriel Young