1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
#include <LUFA/Drivers/USB/USB.h>
#include "qmk_midi.h"
#include "sysex_tools.h"
#include "midi.h"
#include "usb_descriptor.h"
#include "process_midi.h"
/*******************************************************************************
* MIDI
******************************************************************************/
MidiDevice midi_device;
#define SYSEX_START_OR_CONT 0x40
#define SYSEX_ENDS_IN_1 0x50
#define SYSEX_ENDS_IN_2 0x60
#define SYSEX_ENDS_IN_3 0x70
#define SYS_COMMON_1 0x50
#define SYS_COMMON_2 0x20
#define SYS_COMMON_3 0x30
static void usb_send_func(MidiDevice* device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
MIDI_EventPacket_t event;
event.Data1 = byte0;
event.Data2 = byte1;
event.Data3 = byte2;
uint8_t cable = 0;
// if the length is undefined we assume it is a SYSEX message
if (midi_packet_length(byte0) == UNDEFINED) {
switch (cnt) {
case 3:
if (byte2 == SYSEX_END)
event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_3);
else
event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
break;
case 2:
if (byte1 == SYSEX_END)
event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_2);
else
event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
break;
case 1:
if (byte0 == SYSEX_END)
event.Event = MIDI_EVENT(cable, SYSEX_ENDS_IN_1);
else
event.Event = MIDI_EVENT(cable, SYSEX_START_OR_CONT);
break;
default:
return; // invalid cnt
}
} else {
// deal with 'system common' messages
// TODO are there any more?
switch (byte0 & 0xF0) {
case MIDI_SONGPOSITION:
event.Event = MIDI_EVENT(cable, SYS_COMMON_3);
break;
case MIDI_SONGSELECT:
case MIDI_TC_QUARTERFRAME:
event.Event = MIDI_EVENT(cable, SYS_COMMON_2);
break;
default:
event.Event = MIDI_EVENT(cable, byte0);
break;
}
}
send_midi_packet(&event);
}
static void usb_get_midi(MidiDevice* device) {
MIDI_EventPacket_t event;
while (recv_midi_packet(&event)) {
midi_packet_length_t length = midi_packet_length(event.Data1);
uint8_t input[3];
input[0] = event.Data1;
input[1] = event.Data2;
input[2] = event.Data3;
if (length == UNDEFINED) {
// sysex
if (event.Event == MIDI_EVENT(0, SYSEX_START_OR_CONT) || event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_3)) {
length = 3;
} else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_2)) {
length = 2;
} else if (event.Event == MIDI_EVENT(0, SYSEX_ENDS_IN_1)) {
length = 1;
} else {
// XXX what to do?
}
}
// pass the data to the device input function
if (length != UNDEFINED) midi_device_input(device, length, input);
}
}
static void fallthrough_callback(MidiDevice* device, uint16_t cnt, uint8_t byte0, uint8_t byte1, uint8_t byte2) {
#ifdef AUDIO_ENABLE
if (cnt == 3) {
switch (byte0 & 0xF0) {
case MIDI_NOTEON:
play_note(((double)261.6) * pow(2.0, -4.0) * pow(2.0, (byte1 & 0x7F) / 12.0), (byte2 & 0x7F) / 8);
break;
case MIDI_NOTEOFF:
stop_note(((double)261.6) * pow(2.0, -4.0) * pow(2.0, (byte1 & 0x7F) / 12.0));
break;
}
}
if (byte0 == MIDI_STOP) {
stop_all_notes();
}
#endif
}
static void cc_callback(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t val) {
// sending it back on the next channel
// midi_send_cc(device, (chan + 1) % 16, num, val);
}
void midi_init(void);
void setup_midi(void) {
#ifdef MIDI_ADVANCED
midi_init();
#endif
midi_device_init(&midi_device);
midi_device_set_send_func(&midi_device, usb_send_func);
midi_device_set_pre_input_process_func(&midi_device, usb_get_midi);
midi_register_fallthrough_callback(&midi_device, fallthrough_callback);
midi_register_cc_callback(&midi_device, cc_callback);
}
|