1 /* 2 * Copyright (c) 2024 Titouan Christophe 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_INCLUDE_AUDIO_MIDI_H_ 8 #define ZEPHYR_INCLUDE_AUDIO_MIDI_H_ 9 10 #ifdef __cplusplus 11 extern "C" { 12 #endif 13 14 #include <stdint.h> 15 16 /** 17 * @brief Universal MIDI Packet definitions 18 * @defgroup midi_ump MIDI2 Universal MIDI Packet definitions 19 * @ingroup audio_interface 20 * @since 4.1 21 * @version 0.1.0 22 * @see ump112: "Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol" 23 * Document version 1.1.2 24 * @{ 25 */ 26 27 /** 28 * @brief Universal MIDI Packet container 29 */ 30 struct midi_ump { 31 uint32_t data[4]; /**< Raw content, in the CPU native endianness */ 32 }; 33 34 /** 35 * @defgroup midi_ump_mt Message types 36 * @ingroup midi_ump 37 * @see ump112: 2.1.4 Message Type (MT) Allocation 38 * @{ 39 */ 40 41 /** Utility Messages */ 42 #define UMP_MT_UTILITY 0x00 43 /** System Real Time and System Common Messages (except System Exclusive) */ 44 #define UMP_MT_SYS_RT_COMMON 0x01 45 /** MIDI 1.0 Channel Voice Messages */ 46 #define UMP_MT_MIDI1_CHANNEL_VOICE 0x02 47 /** 64 bits Data Messages (including System Exclusive) */ 48 #define UMP_MT_DATA_64 0x03 49 /** MIDI 2.0 Channel Voice Messages */ 50 #define UMP_MT_MIDI2_CHANNEL_VOICE 0x04 51 /** 128 bits Data Messages */ 52 #define UMP_MT_DATA_128 0x05 53 /** Flex Data Messages */ 54 #define UMP_MT_FLEX_DATA 0x0d 55 /** UMP Stream Message */ 56 #define UMP_MT_UMP_STREAM 0x0f 57 /** @} */ 58 59 /** 60 * @brief Message Type field of a Universal MIDI Packet 61 * @param[in] ump Universal MIDI Packet 62 */ 63 #define UMP_MT(ump) \ 64 ((ump).data[0] >> 28) 65 66 /** 67 * There are 16 UMP message types, each of which can be 1 to 4 uint32 long. 68 * Hence this packed representation of 16x2b array as an uint32 lookup table 69 */ 70 #define UMP_NUM_WORDS_LOOKUP_TABLE \ 71 ((0U << 0) | (0U << 2) | (0U << 4) | (1U << 6) | \ 72 (1U << 8) | (3U << 10) | (0U << 12) | (0U << 14) | \ 73 (1U << 16) | (1U << 18) | (1U << 20) | (2U << 22) | \ 74 (2U << 24) | (3U << 26) | (3U << 28) | (3U << 30)) 75 76 /** 77 * @brief Size of a Universal MIDI Packet, in 32bit words 78 * @param[in] ump Universal MIDI Packet 79 * @see ump112: 2.1.4 Message Type (MT) Allocation 80 */ 81 #define UMP_NUM_WORDS(ump) \ 82 (1 + ((UMP_NUM_WORDS_LOOKUP_TABLE >> (2 * UMP_MT(ump))) & 3)) 83 84 /** 85 * @brief MIDI group field of a Universal MIDI Packet 86 * @param[in] ump Universal MIDI Packet 87 */ 88 #define UMP_GROUP(ump) \ 89 (((ump).data[0] >> 24) & 0x0f) 90 91 /** 92 * @brief Status byte of a MIDI channel voice or system message 93 * @param[in] ump Universal MIDI Packet (containing a MIDI1 event) 94 */ 95 #define UMP_MIDI_STATUS(ump) \ 96 (((ump).data[0] >> 16) & 0xff) 97 /** 98 * @brief Command of a MIDI channel voice message 99 * @param[in] ump Universal MIDI Packet (containing a MIDI event) 100 * @see midi_ump_cmd 101 */ 102 #define UMP_MIDI_COMMAND(ump) \ 103 (UMP_MIDI_STATUS(ump) >> 4) 104 /** 105 * @brief Channel of a MIDI channel voice message 106 * @param[in] ump Universal MIDI Packet (containing a MIDI event) 107 */ 108 #define UMP_MIDI_CHANNEL(ump) \ 109 (UMP_MIDI_STATUS(ump) & 0x0f) 110 /** 111 * @brief First parameter of a MIDI1 channel voice or system message 112 * @param[in] ump Universal MIDI Packet (containing a MIDI1 message) 113 */ 114 #define UMP_MIDI1_P1(ump) \ 115 (((ump).data[0] >> 8) & 0x7f) 116 /** 117 * @brief Second parameter of a MIDI1 channel voice or system message 118 * @param[in] ump Universal MIDI Packet (containing a MIDI1 message) 119 */ 120 #define UMP_MIDI1_P2(ump) \ 121 ((ump).data[0] & 0x7f) 122 123 /** 124 * @brief Initialize a UMP with a MIDI1 channel voice message 125 * @remark For messages that take a single parameter, p2 is ignored by the receiver. 126 * @param group The UMP group 127 * @param command The MIDI1 command 128 * @param channel The MIDI1 channel number 129 * @param p1 The 1st MIDI1 parameter 130 * @param p2 The 2nd MIDI1 parameter 131 */ 132 #define UMP_MIDI1_CHANNEL_VOICE(group, command, channel, p1, p2) \ 133 (struct midi_ump) {.data = { \ 134 (UMP_MT_MIDI1_CHANNEL_VOICE << 28) \ 135 | (((group) & 0x0f) << 24) \ 136 | (((command) & 0x0f) << 20) \ 137 | (((channel) & 0x0f) << 16) \ 138 | (((p1) & 0x7f) << 8) \ 139 | ((p2) & 0x7f) \ 140 }} 141 142 /** 143 * @defgroup midi_ump_cmd MIDI commands 144 * @ingroup midi_ump 145 * @see ump112: 7.3 MIDI 1.0 Channel Voice Messages 146 * 147 * When UMP_MT(x)=UMP_MT_MIDI1_CHANNEL_VOICE or UMP_MT_MIDI2_CHANNEL_VOICE, then 148 * UMP_MIDI_COMMAND(x) may be one of: 149 * @{ 150 */ 151 #define UMP_MIDI_NOTE_OFF 0x8 /**< Note Off (p1=note number, p2=velocity) */ 152 #define UMP_MIDI_NOTE_ON 0x9 /**< Note On (p1=note number, p2=velocity) */ 153 #define UMP_MIDI_AFTERTOUCH 0xa /**< Polyphonic aftertouch (p1=note number, p2=data) */ 154 #define UMP_MIDI_CONTROL_CHANGE 0xb /**< Control Change (p1=index, p2=data) */ 155 #define UMP_MIDI_PROGRAM_CHANGE 0xc /**< Control Change (p1=program) */ 156 #define UMP_MIDI_CHAN_AFTERTOUCH 0xd /**< Channel aftertouch (p1=data) */ 157 #define UMP_MIDI_PITCH_BEND 0xe /**< Pitch bend (p1=lsb, p2=msb) */ 158 /** @} */ 159 160 /** 161 * @brief Initialize a UMP with a System Real Time and System Common Message 162 * @remark For messages that take only one (or no) parameter, p2 (and p1) 163 * are ignored by the receiver. 164 * @param group The UMP group 165 * @param status The status byte 166 * @param p1 The 1st parameter 167 * @param p2 The 2nd parameter 168 */ 169 #define UMP_SYS_RT_COMMON(group, status, p1, p2) \ 170 (struct midi_ump) {.data = { \ 171 (UMP_MT_SYS_RT_COMMON << 28) \ 172 | (((group) & 0x0f) << 24) \ 173 | ((status) << 16) \ 174 | (((p1) & 0x7f) << 8) \ 175 | ((p2) & 0x7f) \ 176 }} 177 178 /** 179 * @defgroup midi_ump_sys System common and System Real Time message status 180 * @ingroup midi_ump 181 * @see ump112: 7.6 System Common and System Real Time Messages 182 * 183 * When UMP_MT(x)=UMP_MT_SYS_RT_COMMON, UMP_MIDI_STATUS(x) may be one of: 184 * @{ 185 */ 186 #define UMP_SYS_MIDI_TIME_CODE 0xf1 /**< MIDI Time Code (no param) */ 187 #define UMP_SYS_SONG_POSITION 0xf2 /**< Song Position Pointer (p1=lsb, p2=msb) */ 188 #define UMP_SYS_SONG_SELECT 0xf3 /**< Song Select (p1=song number) */ 189 #define UMP_SYS_TUNE_REQUEST 0xf6 /**< Tune Request (no param) */ 190 #define UMP_SYS_TIMING_CLOCK 0xf8 /**< Timing Clock (no param) */ 191 #define UMP_SYS_START 0xfa /**< Start (no param) */ 192 #define UMP_SYS_CONTINUE 0xfb /**< Continue (no param) */ 193 #define UMP_SYS_STOP 0xfc /**< Stop (no param) */ 194 #define UMP_SYS_ACTIVE_SENSING 0xfe /**< Active sensing (no param) */ 195 #define UMP_SYS_RESET 0xff /**< Reset (no param) */ 196 /** @} */ 197 198 /** @} */ 199 200 #ifdef __cplusplus 201 } 202 #endif 203 204 #endif 205