From 18a2be0c24b68dbfb4667e08ab6e8912adf52e7b Mon Sep 17 00:00:00 2001 From: Duncan Wilkie Date: Tue, 18 Jul 2023 10:34:34 -0500 Subject: Refactored parsing, added header, all around based mode --- controller/inc/midi.h | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 controller/inc/midi.h (limited to 'controller/inc/midi.h') diff --git a/controller/inc/midi.h b/controller/inc/midi.h new file mode 100644 index 0000000..819db03 --- /dev/null +++ b/controller/inc/midi.h @@ -0,0 +1,207 @@ +#ifndef MIDI_H +#define MIDI_H + +#include +#include +#include + +// Configuration. + +#define DEBUG 0 // If defined, enable input safety checking (e.g. too large data bytes, bad ID numbers, etc). + // These checks have some performance downside. +#define RUNNING_STATUS 0 // If defined, the MIDI instrument stores a transmit status and uses running statuses whenever possible. +#define KEY_ON_VELOCITY 0 // If defined, the MIDI instrument sends velocities with Note On messages. +#undef RELEASE_VELOCITY // If defined, the MIDI instrument sends Note Off messages with velocities. + // Otherwise, sends Note On velocity 0 or Note Off velocity 0 according to ACTUAL_OFF_MESSAGE. +#undef ACTUAL_OFF_MESSAGE // If defined, the MIDI instrument sends true Note Off messages. + // Otherwise sends Note On velocity 0 (so as to exploit running status). +#undef EXPORT_CONTROLLERS // If defined, export constants useful for controller messages. + +// Consumers must specify +typedef struct { + void (*uart_write)(uint8_t); // Blocking, single-byte UART transmit function. + // Channel voice handlers. + void (*note_on_handler)(uint8_t, uint8_t, uint8_t); + void (*note_off_handler)(uint8_t, uint8_t, uint8_t); + void (*poly_key_handler)(uint8_t, uint8_t, uint8_t); + void (*control_change_handler)(uint8_t, uint8_t, uint8_t); + void (*program_change_handler)(uint8_t, uint8_t); + void (*aftertouch_handler)(uint8_t, uint8_t); + void (*pitch_bend_change_handler)(uint8_t, uint8_t); + // Channel mode handlers. + void (*all_sound_off_handler)(uint8_t); + void (*reset_all_controllers_handler)(uint8_t); + void (*local_control_handler)(uint8_t, uint8_t); + void (*all_notes_off_handler)(uint8_t); + void (*omni_on_handler)(uint8_t); + void (*omni_off_handler)(uint8_t); + void (*mono_on_handler)(uint8_t, uint8_t); + void (*poly_on_handler)(uint8_t); + // System common handlers. + void (*mtc_quarter_frame_handler)(uint8_t, uint8_t); + void (*song_position_pointer_handler)(uint8_t, uint8_t); + void (*song_select_handler)(uint8_t); + void (*tune_request_handler)(); + // System real time handlers. + void (*timing_clock_handler)(); + void (*start_handler)(); + void (*continue_handler)(); + void (*stop_handler)(); + void (*active_sensing_handler)(); + void (*system_reset_handler)(); + // System Exclusive handlers. + bool (*sysex_collector)(uint8_t); // Feeds most recent byte system exclusive byte (status and eox excluded, ID included) + // to client, returning false whenever the client determines sysex can be safely discarded. + // Client is expected to maintain parsing state externally, + // including resetting correctly after aborted parses. + // Client also should not abort the parse before the first post-manufacturer-ID byte. + void (*end_of_sysex_handler)(); // Sent only when client + // Universal System Exclusive handlers. + void (*bulk_tuning_dump_request_handler)(uint8_t, uint8_t); + void (*bulk_tuning_dump_handler)(uint8_t, uint8_t, char*, uint8_t*); + void (*single_note_tuning_change_handler)(uint8_t, uint8_t, uint8_t, uint8_t*); + // TODO: more. + bool (*unimplemented_universal_sysex_collector)(uint8_t); // Same as above. Parsing ends with end_of_sysex_handler. +} ConsumerBehavior; + +extern ConsumerBehavior pfns; // Initialize this globally in your main. + +// System exclusive sends. +void sysex(uint16_t manufacturer_id, bool long_id, uint8_t* contents, size_t contents_len); +void universal_nonrealtime(uint8_t device_id, uint16_t sub_id, uint8_t* contents, size_t contents_len); +void universal_realtime(uint8_t device_id, uint16_t sub_id, uint8_t* contents, size_t contents_len); + +// Channel voice sends. +#ifdef KEY_ON_VELOCITY +void note_on(uint8_t channel, uint8_t note, uint8_t velocity); +#else +void note_on(uint8_t channel, uint8_t note); +#endif +#ifdef RELEASE_VELOCITY +void note_off(uint8_t channel, uint8_t note, uint8_t velocity); +#else +void note_off(uint8_t channel, uint8_t note); +#endif +void control_change(uint8_t channel, uint8_t controller_number, uint8_t control_value); +void program_change(uint8_t channel, uint8_t program_number); +void aftertouch(uint8_t channel, uint8_t pressure_value); +void pitch_bend_change(uint8_t channel, uint16_t pressure_value); + +// Channel mode sends. +void all_sound_off(uint8_t channel); +void reset_all_controllers(uint8_t channel); +void local_control_on(uint8_t channel); +void local_control_off(uint8_t channel); +void all_notes_off(uint8_t channel); +void omni_on(uint8_t channel); +void omni_off(uint8_t channel); +void mono_on(uint8_t channel, uint8_t channel_count); +void poly_on(uint8_t channel); + + +// System Common sends. +// MTC Quarter Frame unimplemented. +void song_position_pointer(uint16_t position); +void song_select(uint8_t song); +void tune_request(); + +// System Real Time sends. +void timing_clock(); +void srt_start(); +void srt_continue(); +void srt_stop(); +void active_sensing(); +void MIDI_reset(); + +// Universal SysEx. +// Only implement MTS; consumers can do their own parsing via unimplemented_universal_sysex_collector. + +// MIDI Tuning Standard sends. +void bulk_tuning_dump_request(uint8_t device_id, uint8_t program); +void bulk_tuning_dump(uint8_t device_id, uint8_t program, char* name, uint8_t* tuning_data); +void single_note_tuning_change(uint8_t device_id, uint8_t program, uint8_t *note_tuning_data, uint8_t keys_changed); + + +// Feed bytes to this in the UART interrupt handler. +void parse_midi_stream(uint8_t byte); + + +// Public constants; magic numbers useful for consumers. +#define ALL_CALL_DEVICE_ID 0x7f +#define DEVICE_KEY_COUNT 128 +#define TUNING_LENGTH (3 * DEVICE_KEY_COUNT) +#define TUNING_NAME_LENGTH 16 +#define NOTE_TUNING_BYTES_PER_KEY 4 + + +#ifdef EXPORT_CONTROLLERS +// Controller constants. +typedef enum Controller { + BANK_SELECT = 0, + MODULATION_WHEEL = 1, + BREATH_CONTROLLER = 2, + // Undefined + FOOT_CONTROLLER = 4, + PORTAMENTO_TIME = 5, + DATA_ENTRY_MSB = 6, + CHANNEL_VOLUME = 7, + BALANCE = 8, + // Undefined + PAN = 10, + EXPRESSION = 11, + EFFECT1 = 12, + EFFECT2 = 13, + // Undefined + GP1 = 16, + GP2 = 17, + GP3 = 18, + GP4 = 19, + DAMPER_PEDAL = 64, + PORTAMENTO_TOGGLE = 65, + SOSTENUTO = 66, + SOFT_PEDAL = 67, + LEGATO_FOOTSWITCH = 68, + HOLD2 = 69, + SC1_SOUND_VARIATION = 70, + SC2_TIMBRE = 71, + SC3_RELEASE_TIME = 72, + SC4_ATTACK_TIME = 73, + SC5_BRIGHTNESS = 74, + SC6 = 75, + SC7 = 76, + SC8 = 77, + SC9 = 78, + SC10 = 79, + GP5 = 80, + GP6 = 81, + GP7 = 82, + GP8 = 83, + PORTAMENTO_CONTROL = 84, + // Undefined + EFFECTS_DEPTH1 = 91, + EFFECTS_DEPTH2 = 92, + EFFECTS_DEPTH3 = 93, + EFFECTS_DEPTH4 = 94, + EFFECTS_DEPTH5 = 95, + DATA_INCREMENT = 96, + DATA_DECREMENT = 97, + NONREGISTERED_LSB = 98, + NONREGISTERED_MSB = 99, + REGISTERED_LSB = 100, + REGISTERED_MSB = 101, + // undefined 102-119 + // reserved for channel mode 120-127 +}; + +typedef enum RegisteredParams { + PITCH_BEND_SENSITIVITY = 0, + FINE_TUNING = 1, + COARSE_TUNING = 2, + TUNING_PROGRAM_SELECT = 3, + TUNING_BANK_SELECT = 4 +}; + +#endif + + +#endif -- cgit v1.2.3