Merge pull request #1112 from newsboytko/newsboytko/midi-keycodes
Flesh out MIDI support
This commit is contained in:
		
						commit
						7e37daa2ce
					
				
					 36 changed files with 1435 additions and 496 deletions
				
			
		| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										62
									
								
								quantum/process_keycode/process_audio.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								quantum/process_keycode/process_audio.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
#include "audio.h"
 | 
			
		||||
#include "process_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_all_notes_off(void) {
 | 
			
		||||
    stop_all_notes();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
void audio_on_user() {}
 | 
			
		||||
							
								
								
									
										11
									
								
								quantum/process_keycode/process_audio.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								quantum/process_keycode/process_audio.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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_all_notes_off(void);
 | 
			
		||||
 | 
			
		||||
void audio_on_user(void);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -1,68 +1,238 @@
 | 
			
		|||
#include "process_midi.h"
 | 
			
		||||
 | 
			
		||||
bool midi_activated = false;
 | 
			
		||||
uint8_t midi_starting_note = 0x0C;
 | 
			
		||||
int midi_offset = 7;
 | 
			
		||||
#ifdef MIDI_ENABLE
 | 
			
		||||
#include "midi.h"
 | 
			
		||||
 | 
			
		||||
bool process_midi(uint16_t keycode, keyrecord_t *record) {
 | 
			
		||||
    if (keycode == MI_ON && record->event.pressed) {
 | 
			
		||||
      midi_activated = true;
 | 
			
		||||
#ifdef AUDIO_ENABLE
 | 
			
		||||
      music_scale_user();
 | 
			
		||||
#endif
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
#ifdef MIDI_BASIC
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
  return true;
 | 
			
		||||
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_all_notes_off(void)
 | 
			
		||||
{
 | 
			
		||||
    midi_send_cc(&midi_device, 0, 0x7B, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // MIDI_BASIC
 | 
			
		||||
 | 
			
		||||
#ifdef MIDI_ADVANCED
 | 
			
		||||
 | 
			
		||||
#include "timer.h"
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void midi_init(void)
 | 
			
		||||
{
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
    for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++)
 | 
			
		||||
    {
 | 
			
		||||
        tone_status[i] = MIDI_INVALID_NOTE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
        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) {
 | 
			
		||||
                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;
 | 
			
		||||
            }
 | 
			
		||||
            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;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX:
 | 
			
		||||
            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) {
 | 
			
		||||
                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)) {
 | 
			
		||||
                midi_config.octave++;
 | 
			
		||||
                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;
 | 
			
		||||
                dprintf("midi velocity %d\n", midi_config.velocity);
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        case MI_VELD:
 | 
			
		||||
            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) {
 | 
			
		||||
                midi_config.velocity++;
 | 
			
		||||
                dprintf("midi velocity %d\n", midi_config.velocity);
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX:
 | 
			
		||||
            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) {
 | 
			
		||||
                midi_config.channel--;
 | 
			
		||||
                dprintf("midi channel %d\n", midi_config.channel);
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        case MI_CHU:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                midi_config.channel++;
 | 
			
		||||
                dprintf("midi channel %d\n", midi_config.channel);
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        case MI_ALLOFF:
 | 
			
		||||
            if (record->event.pressed) {
 | 
			
		||||
                midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
 | 
			
		||||
                dprintf("midi all notes off\n");
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        case MI_SUS:
 | 
			
		||||
            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;
 | 
			
		||||
        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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // MIDI_ADVANCED
 | 
			
		||||
 | 
			
		||||
#endif // MIDI_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,205 +3,38 @@
 | 
			
		|||
 | 
			
		||||
#include "quantum.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_all_notes_off(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef MIDI_ADVANCED
 | 
			
		||||
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(n) ((n) | 0x6000)
 | 
			
		||||
#define MIDI12 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000
 | 
			
		||||
#define MIDI_INVALID_NOTE 0xFF
 | 
			
		||||
#define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1)
 | 
			
		||||
 | 
			
		||||
#define CHNL(note, channel) (note + (channel << 8))
 | 
			
		||||
uint8_t midi_compute_note(uint16_t keycode);
 | 
			
		||||
#endif // MIDI_ADVANCED
 | 
			
		||||
 | 
			
		||||
#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 // MIDI_ENABLE
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -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,37 +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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void music_all_notes_off(void) {
 | 
			
		||||
    #ifdef AUDIO_ENABLE
 | 
			
		||||
    process_audio_all_notes_off();
 | 
			
		||||
    #endif
 | 
			
		||||
    #if defined(MIDI_ENABLE) && defined(MIDI_BASIC)
 | 
			
		||||
    process_midi_all_notes_off();
 | 
			
		||||
    #endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool process_music(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 == MU_ON && record->event.pressed) {
 | 
			
		||||
        music_on();
 | 
			
		||||
        return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -61,22 +75,10 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
 | 
			
		|||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (music_activated) {
 | 
			
		||||
 | 
			
		||||
      if (keycode == KC_LCTL && record->event.pressed) { // Start recording
 | 
			
		||||
        stop_all_notes();
 | 
			
		||||
        music_all_notes_off();
 | 
			
		||||
        music_sequence_recording = true;
 | 
			
		||||
        music_sequence_recorded = false;
 | 
			
		||||
        music_sequence_playing = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +87,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      if (keycode == KC_LALT && record->event.pressed) { // Stop recording/playing
 | 
			
		||||
        stop_all_notes();
 | 
			
		||||
        music_all_notes_off();
 | 
			
		||||
        if (music_sequence_recording) { // was recording
 | 
			
		||||
          music_sequence_recorded = true;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +97,7 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      if (keycode == KC_LGUI && record->event.pressed && music_sequence_recorded) { // Start playing
 | 
			
		||||
        stop_all_notes();
 | 
			
		||||
        music_all_notes_off();
 | 
			
		||||
        music_sequence_recording = false;
 | 
			
		||||
        music_sequence_playing = true;
 | 
			
		||||
        music_sequence_position = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -114,32 +116,34 @@ bool process_music(uint16_t keycode, keyrecord_t *record) {
 | 
			
		|||
            music_sequence_interval+=10;
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      #define MUSIC_MODE_GUITAR
 | 
			
		||||
 | 
			
		||||
      #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
 | 
			
		||||
 | 
			
		||||
      if (record->event.pressed) {
 | 
			
		||||
        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++;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        stop_note(freq);
 | 
			
		||||
        music_noteoff(note);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
  return true;
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool is_music_on(void) {
 | 
			
		||||
| 
						 | 
				
			
			@ -161,26 +165,26 @@ void music_on(void) {
 | 
			
		|||
 | 
			
		||||
void music_off(void) {
 | 
			
		||||
    music_activated = 0;
 | 
			
		||||
    stop_all_notes();
 | 
			
		||||
    music_all_notes_off();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
void music_on_user() {}
 | 
			
		||||
 | 
			
		||||
__attribute__ ((weak))
 | 
			
		||||
void audio_on_user() {}
 | 
			
		||||
 | 
			
		||||
__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();
 | 
			
		||||
      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);
 | 
			
		||||
      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))
 | 
			
		||||
| 
						 | 
				
			
			@ -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,9 +12,9 @@ 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);
 | 
			
		||||
void music_all_notes_off(void);
 | 
			
		||||
 | 
			
		||||
void matrix_scan_music(void);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -24,4 +26,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
 | 
			
		||||
| 
						 | 
				
			
			@ -98,8 +98,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -153,10 +153,13 @@ 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
 | 
			
		||||
    process_audio(keycode, record) &&
 | 
			
		||||
  #endif
 | 
			
		||||
  #if defined(AUDIO_ENABLE) || (defined(MIDI_ENABLE) && defined(MIDI_BASIC))
 | 
			
		||||
    process_music(keycode, record) &&
 | 
			
		||||
  #endif
 | 
			
		||||
  #ifdef TAP_DANCE_ENABLE
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,11 +35,16 @@ extern uint32_t default_layer_state;
 | 
			
		|||
 | 
			
		||||
#ifdef MIDI_ENABLE
 | 
			
		||||
	#include <lufa.h>
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,16 @@
 | 
			
		|||
 | 
			
		||||
#ifndef QUANTUM_KEYCODES_H
 | 
			
		||||
#define QUANTUM_KEYCODES_H
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
enum quantum_keycodes {
 | 
			
		||||
    // Ranges used in shortucuts - not to be used directly
 | 
			
		||||
    QK_TMK                = 0x0000,
 | 
			
		||||
| 
						 | 
				
			
			@ -107,9 +116,230 @@ enum quantum_keycodes {
 | 
			
		|||
    MUV_IN,
 | 
			
		||||
    MUV_DE,
 | 
			
		||||
 | 
			
		||||
    // Midi mode on/off
 | 
			
		||||
    MIDI_ON,
 | 
			
		||||
    MIDI_OFF,
 | 
			
		||||
    // Midi
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
#if !MIDI_ENABLE_STRICT || (defined(MIDI_ENABLE) && defined(MIDI_ADVANCED))
 | 
			
		||||
    MIDI_TONE_MIN,
 | 
			
		||||
 | 
			
		||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 0
 | 
			
		||||
    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,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 1
 | 
			
		||||
    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,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !MIDI_ENABLE_STRICT || MIDI_TONE_KEYCODE_OCTAVES > 2
 | 
			
		||||
    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,
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !MIDI_ENABLE_STRICT || 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_ENABLE_STRICT || 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_ENABLE_STRICT || 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_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,
 | 
			
		||||
#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,
 | 
			
		||||
    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_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,
 | 
			
		||||
    MI_VEL_3,
 | 
			
		||||
    MI_VEL_4,
 | 
			
		||||
    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_ALLOFF, // all notes off
 | 
			
		||||
 | 
			
		||||
    MI_SUS, // sustain
 | 
			
		||||
    MI_PORT, // portamento
 | 
			
		||||
    MI_SOST, // sostenuto
 | 
			
		||||
    MI_SOFT, // soft pedal
 | 
			
		||||
    MI_LEG,  // legato
 | 
			
		||||
 | 
			
		||||
    MI_MOD, // modulation
 | 
			
		||||
    MI_MODSD, // decrease modulation speed
 | 
			
		||||
    MI_MODSU, // increase modulation speed
 | 
			
		||||
#endif // MIDI_ADVANCED
 | 
			
		||||
 | 
			
		||||
    // Backlight functionality
 | 
			
		||||
    BL_0,
 | 
			
		||||
| 
						 | 
				
			
			@ -279,9 +509,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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -159,4 +159,27 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		|||
//#define NO_ACTION_MACRO
 | 
			
		||||
//#define NO_ACTION_FUNCTION
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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 1
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 (+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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue