Line data Source code
1 0 : /*
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 : * @{
23 : */
24 :
25 : /**
26 : * @defgroup ump112 Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol
27 : * @ingroup midi_ump
28 : * @{
29 : * @details Definitions based on the following document
30 : * <a href="https://midi.org/universal-midi-packet-ump-and-midi-2-0-protocol-specification">
31 : * Universal MIDI Packet (UMP) Format and MIDI 2.0 Protocol
32 : * With MIDI 1.0 Protocol in UMP Format - Document version 1.1.2
33 : * (MIDI Association Document: M2-104-UM)
34 : * </a>
35 : * @}
36 : */
37 :
38 : /**
39 : * @brief Universal MIDI Packet container
40 : */
41 1 : struct midi_ump {
42 1 : uint32_t data[4]; /**< Raw content, in the CPU native endianness */
43 : };
44 :
45 : /**
46 : * @defgroup midi_ump_mt Message types
47 : * @ingroup midi_ump
48 : * @see ump112: 2.1.4 Message Type (MT) Allocation
49 : * @{
50 : */
51 :
52 : /** Utility Messages */
53 1 : #define UMP_MT_UTILITY 0x00
54 : /** System Real Time and System Common Messages (except System Exclusive) */
55 1 : #define UMP_MT_SYS_RT_COMMON 0x01
56 : /** MIDI 1.0 Channel Voice Messages */
57 1 : #define UMP_MT_MIDI1_CHANNEL_VOICE 0x02
58 : /** 64 bits Data Messages (including System Exclusive) */
59 1 : #define UMP_MT_DATA_64 0x03
60 : /** MIDI 2.0 Channel Voice Messages */
61 1 : #define UMP_MT_MIDI2_CHANNEL_VOICE 0x04
62 : /** 128 bits Data Messages */
63 1 : #define UMP_MT_DATA_128 0x05
64 : /** Flex Data Messages */
65 1 : #define UMP_MT_FLEX_DATA 0x0d
66 : /**
67 : * UMP Stream Message
68 : * @see midi_ump_stream
69 : */
70 1 : #define UMP_MT_UMP_STREAM 0x0f
71 : /** @} */
72 :
73 : /**
74 : * @brief Message Type field of a Universal MIDI Packet
75 : * @param[in] ump Universal MIDI Packet
76 : * @see midi_ump_mt
77 : */
78 1 : #define UMP_MT(ump) \
79 : ((ump).data[0] >> 28)
80 :
81 : /**
82 : * There are 16 UMP message types, each of which can be 1 to 4 uint32 long.
83 : * Hence this packed representation of 16x2b array as an uint32 lookup table
84 : */
85 1 : #define UMP_NUM_WORDS_LOOKUP_TABLE \
86 : ((0U << 0) | (0U << 2) | (0U << 4) | (1U << 6) | \
87 : (1U << 8) | (3U << 10) | (0U << 12) | (0U << 14) | \
88 : (1U << 16) | (1U << 18) | (1U << 20) | (2U << 22) | \
89 : (2U << 24) | (3U << 26) | (3U << 28) | (3U << 30))
90 :
91 : /**
92 : * @brief Size of a Universal MIDI Packet, in 32bit words
93 : * @param[in] ump Universal MIDI Packet
94 : * @see ump112: 2.1.4 Message Type (MT) Allocation
95 : */
96 1 : #define UMP_NUM_WORDS(ump) \
97 : (1 + ((UMP_NUM_WORDS_LOOKUP_TABLE >> (2 * UMP_MT(ump))) & 3))
98 :
99 : /**
100 : * @brief MIDI group field of a Universal MIDI Packet
101 : * @param[in] ump Universal MIDI Packet
102 : */
103 1 : #define UMP_GROUP(ump) \
104 : (((ump).data[0] >> 24) & 0xF)
105 :
106 : /**
107 : * @brief Status byte of a MIDI channel voice or system message
108 : * @param[in] ump Universal MIDI Packet (containing a MIDI1 event)
109 : * @see midi_ump_sys
110 : */
111 1 : #define UMP_MIDI_STATUS(ump) \
112 : (((ump).data[0] >> 16) & 0xFF)
113 : /**
114 : * @brief Command of a MIDI channel voice message
115 : * @param[in] ump Universal MIDI Packet (containing a MIDI event)
116 : * @see midi_ump_cmd
117 : */
118 1 : #define UMP_MIDI_COMMAND(ump) \
119 : (UMP_MIDI_STATUS(ump) >> 4)
120 : /**
121 : * @brief Channel of a MIDI channel voice message
122 : * @param[in] ump Universal MIDI Packet (containing a MIDI event)
123 : */
124 1 : #define UMP_MIDI_CHANNEL(ump) \
125 : (UMP_MIDI_STATUS(ump) & 0xF)
126 : /**
127 : * @brief First parameter of a MIDI1 channel voice or system message
128 : * @param[in] ump Universal MIDI Packet (containing a MIDI1 message)
129 : */
130 1 : #define UMP_MIDI1_P1(ump) \
131 : (((ump).data[0] >> 8) & 0x7F)
132 : /**
133 : * @brief Second parameter of a MIDI1 channel voice or system message
134 : * @param[in] ump Universal MIDI Packet (containing a MIDI1 message)
135 : */
136 1 : #define UMP_MIDI1_P2(ump) \
137 : ((ump).data[0] & 0x7F)
138 :
139 : /**
140 : * @brief Initialize a UMP with a MIDI1 channel voice message
141 : * @remark For messages that take a single parameter, p2 is ignored by the receiver.
142 : * @param group The UMP group
143 : * @param command The MIDI1 command
144 : * @param channel The MIDI1 channel number
145 : * @param p1 The 1st MIDI1 parameter
146 : * @param p2 The 2nd MIDI1 parameter
147 : */
148 1 : #define UMP_MIDI1_CHANNEL_VOICE(group, command, channel, p1, p2) \
149 : (struct midi_ump) {.data = { \
150 : (UMP_MT_MIDI1_CHANNEL_VOICE << 28) \
151 : | (((group) & 0x0f) << 24) \
152 : | (((command) & 0x0f) << 20) \
153 : | (((channel) & 0x0f) << 16) \
154 : | (((p1) & 0x7f) << 8) \
155 : | ((p2) & 0x7f) \
156 : }}
157 :
158 : /**
159 : * @defgroup midi_ump_cmd MIDI commands
160 : * @ingroup midi_ump
161 : * @see ump112: 7.3 MIDI 1.0 Channel Voice Messages
162 : * @remark When UMP_MT(x)=UMP_MT_MIDI1_CHANNEL_VOICE or UMP_MT_MIDI2_CHANNEL_VOICE,
163 : * then UMP_MIDI_COMMAND(x) may be one of:
164 : * @{
165 : */
166 1 : #define UMP_MIDI_NOTE_OFF 0x8 /**< Note Off (p1=note number, p2=velocity) */
167 1 : #define UMP_MIDI_NOTE_ON 0x9 /**< Note On (p1=note number, p2=velocity) */
168 1 : #define UMP_MIDI_AFTERTOUCH 0xa /**< Polyphonic aftertouch (p1=note number, p2=data) */
169 1 : #define UMP_MIDI_CONTROL_CHANGE 0xb /**< Control Change (p1=index, p2=data) */
170 1 : #define UMP_MIDI_PROGRAM_CHANGE 0xc /**< Control Change (p1=program) */
171 1 : #define UMP_MIDI_CHAN_AFTERTOUCH 0xd /**< Channel aftertouch (p1=data) */
172 1 : #define UMP_MIDI_PITCH_BEND 0xe /**< Pitch bend (p1=lsb, p2=msb) */
173 : /** @} */
174 :
175 : /**
176 : * @brief Initialize a UMP with a System Real Time and System Common Message
177 : * @remark For messages that take only one (or no) parameter, p2 (and p1)
178 : * are ignored by the receiver.
179 : * @param group The UMP group
180 : * @param status The status byte
181 : * @param p1 The 1st parameter
182 : * @param p2 The 2nd parameter
183 : */
184 1 : #define UMP_SYS_RT_COMMON(group, status, p1, p2) \
185 : (struct midi_ump) {.data = { \
186 : (UMP_MT_SYS_RT_COMMON << 28) \
187 : | (((group) & 0x0f) << 24) \
188 : | ((status) << 16) \
189 : | (((p1) & 0x7f) << 8) \
190 : | ((p2) & 0x7f) \
191 : }}
192 :
193 : /**
194 : * @defgroup midi_ump_sys System common and System Real Time message status
195 : * @ingroup midi_ump
196 : * @see ump112: 7.6 System Common and System Real Time Messages
197 : *
198 : * @remark When UMP_MT(x)=UMP_MT_SYS_RT_COMMON,
199 : * then UMP_MIDI_STATUS(x) may be one of:
200 : * @{
201 : */
202 1 : #define UMP_SYS_MIDI_TIME_CODE 0xf1 /**< MIDI Time Code (no param) */
203 1 : #define UMP_SYS_SONG_POSITION 0xf2 /**< Song Position Pointer (p1=lsb, p2=msb) */
204 1 : #define UMP_SYS_SONG_SELECT 0xf3 /**< Song Select (p1=song number) */
205 1 : #define UMP_SYS_TUNE_REQUEST 0xf6 /**< Tune Request (no param) */
206 1 : #define UMP_SYS_TIMING_CLOCK 0xf8 /**< Timing Clock (no param) */
207 1 : #define UMP_SYS_START 0xfa /**< Start (no param) */
208 1 : #define UMP_SYS_CONTINUE 0xfb /**< Continue (no param) */
209 1 : #define UMP_SYS_STOP 0xfc /**< Stop (no param) */
210 1 : #define UMP_SYS_ACTIVE_SENSING 0xfe /**< Active sensing (no param) */
211 1 : #define UMP_SYS_RESET 0xff /**< Reset (no param) */
212 : /** @} */
213 :
214 :
215 : /**
216 : * @defgroup midi_ump_stream UMP Stream specific fields
217 : * @ingroup midi_ump
218 : * @see ump112: 7.1 UMP Stream Messages
219 : *
220 : * @{
221 : */
222 :
223 : /**
224 : * @brief Format of a UMP Stream message
225 : * @param[in] ump Universal MIDI Packet (containing a UMP Stream message)
226 : * @see midi_ump_stream_format
227 : */
228 1 : #define UMP_STREAM_FORMAT(ump) \
229 : (((ump).data[0] >> 26) & 0x03)
230 :
231 : /**
232 : * @defgroup midi_ump_stream_format UMP Stream format
233 : * @ingroup midi_ump_stream
234 : * @see ump112: 7.1 UMP Stream Messages: Format
235 : * @remark When UMP_MT(x)=UMP_MT_UMP_STREAM,
236 : * then UMP_STREAM_FORMAT(x) may be one of:
237 : * @{
238 : */
239 :
240 : /** Complete message in one UMP */
241 1 : #define UMP_STREAM_FORMAT_COMPLETE 0x00
242 : /** Start of a message which spans two or more UMPs */
243 1 : #define UMP_STREAM_FORMAT_START 0x01
244 : /** Continuing a message which spans three or more UMPs.
245 : * There might be multiple Continue UMPs in a single message
246 : */
247 1 : #define UMP_STREAM_FORMAT_CONTINUE 0x02
248 : /** End of message which spans two or more UMPs */
249 1 : #define UMP_STREAM_FORMAT_END 0x03
250 :
251 : /** @} */
252 :
253 : /**
254 : * @brief Status field of a UMP Stream message
255 : * @param[in] ump Universal MIDI Packet (containing a UMP Stream message)
256 : * @see midi_ump_stream_status
257 : */
258 1 : #define UMP_STREAM_STATUS(ump) \
259 : (((ump).data[0] >> 16) & 0x3FF)
260 :
261 : /**
262 : * @defgroup midi_ump_stream_status UMP Stream status
263 : * @ingroup midi_ump_stream
264 : * @see ump112: 7.1 UMP Stream Messages
265 : * @remark When UMP_MT(x)=UMP_MT_UMP_STREAM,
266 : * then UMP_STREAM_STATUS(x) may be one of:
267 : * @{
268 : */
269 :
270 : /** Endpoint Discovery Message */
271 1 : #define UMP_STREAM_STATUS_EP_DISCOVERY 0x00
272 : /** Endpoint Info Notification Message */
273 1 : #define UMP_STREAM_STATUS_EP_INFO 0x01
274 : /** Device Identity Notification Message */
275 1 : #define UMP_STREAM_STATUS_DEVICE_IDENT 0x02
276 : /** Endpoint Name Notification */
277 1 : #define UMP_STREAM_STATUS_EP_NAME 0x03
278 : /** Product Instance Id Notification Message */
279 1 : #define UMP_STREAM_STATUS_PROD_ID 0x04
280 : /** Stream Configuration Request Message */
281 1 : #define UMP_STREAM_STATUS_CONF_REQ 0x05
282 : /** Stream Configuration Notification Message */
283 1 : #define UMP_STREAM_STATUS_CONF_NOTIF 0x06
284 : /** Function Block Discovery Message */
285 1 : #define UMP_STREAM_STATUS_FB_DISCOVERY 0x10
286 : /** Function Block Info Notification */
287 1 : #define UMP_STREAM_STATUS_FB_INFO 0x11
288 : /** Function Block Name Notification */
289 1 : #define UMP_STREAM_STATUS_FB_NAME 0x12
290 : /** @} */
291 :
292 : /**
293 : * @brief Filter bitmap of an Endpoint Discovery message
294 : * @param[in] ump Universal MIDI Packet (containing an Endpoint Discovery message)
295 : * @see ump112: 7.1.1 Endpoint Discovery Message
296 : * @see midi_ump_ep_disc
297 : */
298 1 : #define UMP_STREAM_EP_DISCOVERY_FILTER(ump) \
299 : ((ump).data[1] & 0xFF)
300 :
301 : /**
302 : * @defgroup midi_ump_ep_disc UMP Stream endpoint discovery message filter bits
303 : * @ingroup midi_ump_stream
304 : * @see ump112: 7.1.1 Fig. 12: Endpoint Discovery Message Filter Bitmap Field
305 : * @remark When UMP_MT(x)=UMP_MT_UMP_STREAM and
306 : * UMP_STREAM_STATUS(x)=UMP_STREAM_STATUS_EP_DISCOVERY,
307 : * then UMP_STREAM_EP_DISCOVERY_FILTER(x) may be an ORed combination of:
308 : * @{
309 : */
310 :
311 : /** Requesting an Endpoint Info Notification */
312 1 : #define UMP_EP_DISC_FILTER_EP_INFO BIT(0)
313 : /** Requesting a Device Identity Notification */
314 1 : #define UMP_EP_DISC_FILTER_DEVICE_ID BIT(1)
315 : /** Requesting an Endpoint Name Notification */
316 1 : #define UMP_EP_DISC_FILTER_EP_NAME BIT(2)
317 : /** Requesting a Product Instance Id Notification */
318 1 : #define UMP_EP_DISC_FILTER_PRODUCT_ID BIT(3)
319 : /** Requesting a Stream Configuration Notification */
320 1 : #define UMP_EP_DISC_FILTER_STREAM_CFG BIT(4)
321 : /** @} */
322 :
323 : /**
324 : * @brief Filter bitmap of a Function Block Discovery message
325 : * @param[in] ump Universal MIDI Packet (containing a Function Block Discovery message)
326 : * @see ump112: 7.1.7 Function Block Discovery Message
327 : * @see midi_ump_fb_disc
328 : */
329 1 : #define UMP_STREAM_FB_DISCOVERY_FILTER(ump) \
330 : ((ump).data[0] & 0xFF)
331 :
332 : /**
333 : * @brief Block number requested in a Function Block Discovery message
334 : * @param[in] ump Universal MIDI Packet (containing a Function Block Discovery message)
335 : * @see ump112: 7.1.7 Function Block Discovery Message
336 : */
337 1 : #define UMP_STREAM_FB_DISCOVERY_NUM(ump) \
338 : (((ump).data[0] >> 8) & 0xFF)
339 :
340 : /**
341 : * @defgroup midi_ump_fb_disc UMP Stream Function Block discovery message filter bits
342 : * @ingroup midi_ump_stream
343 : * @see ump112: 7.1.7 Fig. 21: Function Block Discovery Filter Bitmap Field Format
344 : * @remark When UMP_MT(x)=UMP_MT_UMP_STREAM and
345 : * UMP_STREAM_STATUS(x)=UMP_STREAM_STATUS_FB_DISCOVERY,
346 : * then UMP_STREAM_FB_DISCOVERY_FILTER(x) may be an ORed combination of:
347 : * @{
348 : */
349 : /** Requesting a Function Block Info Notification */
350 1 : #define UMP_FB_DISC_FILTER_INFO BIT(0)
351 : /** Requesting a Function Block Name Notification */
352 1 : #define UMP_FB_DISC_FILTER_NAME BIT(1)
353 : /** @} */
354 :
355 : /** @} */
356 :
357 : /** @} */
358 :
359 : #ifdef __cplusplus
360 : }
361 : #endif
362 :
363 : #endif
|