summaryrefslogtreecommitdiff
path: root/controller/inc/midi.h
diff options
context:
space:
mode:
authorDuncan Wilkie <antigravityd@gmail.com>2023-07-18 10:34:34 -0500
committerDuncan Wilkie <antigravityd@gmail.com>2023-07-18 10:34:34 -0500
commit18a2be0c24b68dbfb4667e08ab6e8912adf52e7b (patch)
tree2b600e0e45a313c6477e09400fc443ba9ea832cd /controller/inc/midi.h
parent1fd366764d17874b8211ef63d41313995833e36d (diff)
Refactored parsing, added header, all around based mode
Diffstat (limited to 'controller/inc/midi.h')
-rw-r--r--controller/inc/midi.h207
1 files changed, 207 insertions, 0 deletions
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 <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+// 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