summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Wilkie <antigravityd@gmail.com>2023-07-18 17:00:44 -0500
committerDuncan Wilkie <antigravityd@gmail.com>2023-07-18 17:00:44 -0500
commit6380915e6e8d98e2c933ea6eb8df02fb1b123b97 (patch)
treeaf135b448ec7047fa2f33e88cc30bdae1cca4a2e
parentd5bce21d1dbdcff5746675d5f355bccb69dcb679 (diff)
Somewhat finalized base MIDI; got the minimal MIDI-CI done.
-rw-r--r--controller/inc/base_midi.h6
-rw-r--r--controller/libs/base_midi.c6
-rw-r--r--controller/libs/midi_ci.c174
-rw-r--r--controller/src/main.c2
-rw-r--r--specs/periph_driver_lib.pdfbin4830798 -> 0 bytes
5 files changed, 185 insertions, 3 deletions
diff --git a/controller/inc/base_midi.h b/controller/inc/base_midi.h
index e566a6f..8320803 100644
--- a/controller/inc/base_midi.h
+++ b/controller/inc/base_midi.h
@@ -16,6 +16,12 @@
// Otherwise sends Note On velocity 0 (so as to exploit running status).
#undef EXPORT_CONTROLLERS // If defined, export constants useful for controller messages.
+// Device info. Modify to suit your use-case.
+#define DEVICE_MANUFACTURER 0x7d
+#define DEVICE_FAMILY 0x00'00
+#define DEVICE_MODEL_NUMBER 0x00'00
+#define SOFTWARE_REVISION 0x00'00'00'00
+
// Consumers must specify
typedef struct {
void (*uart_write)(uint8_t); // Blocking, single-byte UART transmit function.
diff --git a/controller/libs/base_midi.c b/controller/libs/base_midi.c
index e146ec0..6efd2f3 100644
--- a/controller/libs/base_midi.c
+++ b/controller/libs/base_midi.c
@@ -1,10 +1,10 @@
// This file is written to be read side-along with the MIDI 1.0 spec.
// Note the tables at its very end, with /absolutely no direct allusion in the text/.
-#include "midi.h"
+#include "base_midi.h"
#include <stdlib.h>
#include <string.h>
-
+// TODO: startup function to initialize ParseMemory buffer.
#ifdef RUNNING_STATUS
uint8_t last_status = 0x00;
#endif
@@ -83,9 +83,11 @@ void sysex(uint16_t manufacturer_id, uint8_t* contents, size_t contents_len) {
pfns.uart_write(manufacturer_id >> 8);
pfns.uart_write(manufacturer_id & 0x00ff);
} else {
+#ifdef DEBUG
if (manufacturer_id > MAX_NON_UNIVERSAL_ID) {
while(true); // Used universal sysex ID.
}
+#endif
pfns.uart_write(manufacturer_id);
}
diff --git a/controller/libs/midi_ci.c b/controller/libs/midi_ci.c
new file mode 100644
index 0000000..7013d7a
--- /dev/null
+++ b/controller/libs/midi_ci.c
@@ -0,0 +1,174 @@
+// An implementation of the MIDI Capability Inquiry v1.2 Specification, over a MIDI 1.0 transport,
+// with only Property Exchange support.
+// Intended to be read alongside the corresponding specs; specifically in the order:
+// - MIDI CI Specification, minimum requirements + Property Exchange chapter,
+// - Common Rules for MIDI CI Property Exchange.
+
+#include "base_midi.h"
+
+uint32_t our_muid = rand(); // TODO: think.
+
+#define MIDI_CI_SUBID 0x0d
+#define PROFILE_CONFIGURATION_MASK 0x20
+#define PROPERTY_EXCHANGE_MASK 0x30
+#define PROCESS_INQUIRY_MASK 0x40
+#define MANAGEMENT_MASK 0x70
+#define MIDI_CI_VERSION 0x02
+#define TO_FUNCTION_BLOCK_ID 0x7f
+static void ci(uint8_t source_target, uint8_t message_type, uint32_t destination_miud,
+ uint8_t *contents, uint8_t contents_len) {
+ uint8_t *new = malloc(1 + 4 + 4 + contents_len);
+ new[0] = MIDI_CI_VERSION;
+ new[1] = our_muid & 0x00'00'00'ff;
+ new[2] = (our_muid >> 8) & 0x00'00'00'ff;
+ new[3] = (our_muid >> 16) & 0x00'00'00'ff;
+ new[4] = (our_muid >> 24) & 0x00'00'00'ff;
+ new[8] = target_muid & 0x00'00'00'ff;
+ new[7] = (target_muid >> 8) & 0x00'00'00'ff;
+ new[6] = (target_muid >> 16) & 0x00'00'00'ff;
+ new[5] = (target_muid >> 24) & 0x00'00'00'ff;
+ memcpy(new + 9, contents, contents_len);
+
+ universal_nonrealtime(source_target, (MIDI_CI_SUBID << 8) | message_type, contents, 1 + 4 + 4 + contents_len);
+
+ free(new);
+
+}
+
+#define DISCOVERY_SUBID (MANAGEMENT_MASK | 0x00)
+#define CI_CATEGORY_SUPPORTED 0b00011100
+#define MAX_SYSEX_SIZE 512
+#define BROADCAST_MUID 0x7f'7f'7f'7f
+#define SINGLE_OUTPUT_PATH 0x00
+void discovery() {
+ uint8_t *new = malloc(3 + 2 + 2 + 4 + 1 + 4 + 1);
+#if (DEVICE_MANUFACTURER <= MAX_DATA_BYTE)
+ new[0] = DEVICE_MANUFACTURER;
+ new[1] = 0;
+ new[2] = 0;
+#else
+ new[0] = 0;
+ new[1] = DEVICE_MANUFACTURER >> 8;
+ new[2] = DEVICE_MANUFACTURER & 0x00ff;
+#endif
+ new[3] = DEVICE_FAMILY & 0x00ff;
+ new[4] = DEVICE_FAMILY >> 8;
+ new[5] = DEVICE_MODEL & 0x00ff;
+ new[6] = DEVICE_MODEL >> 8;
+ new[7] = SOFTWARE_REVISION & 0x00'00'00'ff;
+ new[8] = (SOFTWARE_REVISION >> 8) & 0x00'00'00'ff;
+ new[9] = (SOFTWARE_REVISION >> 16) & 0x00'00'00'ff;
+ new[10] = (SOFTWARE_REVISION >> 24) & 0x00'00'00'ff;
+ new[11] = CI_CATEGORY_SUPPORTED;
+ new[12] = MAX_SYSEX_SIZE & 0x00'00'00'ff;
+ new[13] = (MAX_SYSEX_SIZE >> 8) & 0x00'00'00'ff;
+ new[14] = (MAX_SYSEX_SIZE >> 16) & 0x00'00'00'ff;
+ new[15] = (MAX_SYSEX_SIZE >> 24) & 0x00'00'00'ff;
+ new[16] = SINGLE_OUTPUT_PATH;
+
+ ci(TO_FUNCTION_BLOCK_ID, DISCOVERY_SUBID, BROADCAST_MUID, new, 17);
+
+ free(new);
+}
+
+#define REPLY_TO_DISCOVERY_SUBID 0x71
+#define NO_FUNCTION_BLOCK 0x7f
+void discovery_reply(uint8_t initiator_muid, uint8_t initiator_output_path_id) {
+ uint8_t *new = malloc(3 + 2 + 2 + 4 + 1 + 4 + 1 + 1);
+#if (DEVICE_MANUFACTURER <= MAX_DATA_BYTE)
+ new[0] = DEVICE_MANUFACTURER;
+ new[1] = 0;
+ new[2] = 0;
+#else
+ new[0] = 0;
+ new[1] = DEVICE_MANUFACTURER >> 8;
+ new[2] = DEVICE_MANUFACTURER & 0x00ff;
+#endif
+ new[3] = DEVICE_FAMILY & 0x00ff;
+ new[4] = DEVICE_FAMILY >> 8;
+ new[5] = DEVICE_MODEL & 0x00ff;
+ new[6] = DEVICE_MODEL >> 8;
+ new[7] = SOFTWARE_REVISION & 0x00'00'00'ff;
+ new[8] = (SOFTWARE_REVISION >> 8) & 0x00'00'00'ff;
+ new[9] = (SOFTWARE_REVISION >> 16) & 0x00'00'00'ff;
+ new[10] = (SOFTWARE_REVISION >> 24) & 0x00'00'00'ff;
+ new[11] = CI_CATEGORY_SUPPORTED;
+ new[12] = MAX_SYSEX_SIZE & 0x00'00'00'ff;
+ new[13] = (MAX_SYSEX_SIZE >> 8) & 0x00'00'00'ff;
+ new[14] = (MAX_SYSEX_SIZE >> 16) & 0x00'00'00'ff;
+ new[15] = (MAX_SYSEX_SIZE >> 24) & 0x00'00'00'ff;
+ new[16] = initiator_output_path_id;
+ new[17] = NO_FUNCTION_BLOCK;
+
+ ci(TO_FUNCTION_BLOCK_ID, REPLY_TO_DISCOVERY_SUBID, initiator_muid, new, 18);
+
+ free(new);
+
+}
+
+// TODO: Decide if Inquiry: Endpoint and Reply to Endpoint are necessary for standard conformace if we're over MIDI 1.0.
+
+// TODO: should we set a new MUID inside this function?
+#define INVALIDATE_MUID_SUBID 0x7e
+void invalidate_muid() {
+ uint8_t *new = malloc(4);
+ new[0] = our_muid & 0x00'00'00'ff;
+ new[1] = (our_muid >> 8) & 0x00'00'00'ff;
+ new[2] = (our_muid >> 16) & 0x00'00'00'ff;
+ new[3] = (our_muid >> 24) & 0x00'00'00'ff;
+
+ ci(TO_FUNCTION_BLOCK_ID, BROADCAST_MUID, new, 4);
+
+ free(new);
+
+}
+
+// TODO: consider structifying?
+#define ACK_SUBID 0x7d
+void ci_ack(uint8_t acking_device_id, uint8_t acking_muid, uint8_t original_classification, uint8_t status_code,
+ uint8_t status_data,
+ uint8_t details1, uint8_t details2, uint8_t details3, uint8_t details4, uint8_t details5,
+ uint16_t length, uint8_t *text) {
+ uint8_t *new = malloc(1 + 1 + 1 + 5 + 2 + length);
+ new[0] = original_classification;
+ new[1] = status_code;
+ new[2] = status_data;
+ new[3] = details1;
+ new[4] = details2;
+ new[5] = details3;
+ new[6] = details4;
+ new[7] = details5;
+ new[8] = length & 0x00ff;
+ new[9] = length >> 8;
+ memcpy(new + 10, text, length);
+
+ ci(acking_device_id, ACK_SUBID, acking_muid, new, 1 + 1 + 1 + 5 + 2 + length);
+
+ free(new);
+
+}
+
+
+#define NAK_SUBID 0x7f
+void ci_nack(uint8_t naking_device_id, uint8_t naking_muid, uint8_t original_classification, uint8_t status_code,
+ uint8_t status_data,
+ uint8_t details1, uint8_t details2, uint8_t details3, uint8_t details4, uint8_t details5,
+ uint16_t length, uint8_t *text) {
+ uint8_t *new = malloc(1 + 1 + 1 + 5 + 2 + length);
+ new[0] = original_classification;
+ new[1] = status_code;
+ new[2] = status_data;
+ new[3] = details1;
+ new[4] = details2;
+ new[5] = details3;
+ new[6] = details4;
+ new[7] = details5;
+ new[8] = length & 0x00ff;
+ new[9] = length >> 8;
+ memcpy(new + 10, text, length);
+
+ ci(naking_device_id, NAK_SUBID, naking_muid, new, 1 + 1 + 1 + 5 + 2 + length);
+
+ free(new);
+
+}
diff --git a/controller/src/main.c b/controller/src/main.c
index fb3f18a..1bfe8b0 100644
--- a/controller/src/main.c
+++ b/controller/src/main.c
@@ -1,4 +1,4 @@
-#include "midi.h"
+#include "base_midi.h"
#include "uart.h"
int main() {
diff --git a/specs/periph_driver_lib.pdf b/specs/periph_driver_lib.pdf
deleted file mode 100644
index 711ab77..0000000
--- a/specs/periph_driver_lib.pdf
+++ /dev/null
Binary files differ