]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/protocol/midi/midi.c
fixed two typos
[qmk_firmware.git] / tmk_core / protocol / midi / midi.c
1 //midi for embedded chips,
2 //Copyright 2010 Alex Norman
3 //
4 //This file is part of avr-midi.
5 //
6 //avr-midi is free software: you can redistribute it and/or modify
7 //it under the terms of the GNU General Public License as published by
8 //the Free Software Foundation, either version 3 of the License, or
9 //(at your option) any later version.
10 //
11 //avr-midi is distributed in the hope that it will be useful,
12 //but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //GNU General Public License for more details.
15 //
16 //You should have received a copy of the GNU General Public License
17 //along with avr-midi.  If not, see <http://www.gnu.org/licenses/>.
18
19 #include "midi.h"
20 #include <string.h> //for memcpy
21
22 #define MIN(x,y) (((x) < (y)) ? (x) : (y)) 
23
24 #ifndef NULL
25 #define NULL 0
26 #endif
27
28 bool midi_is_statusbyte(uint8_t theByte){
29    return (bool)(theByte & MIDI_STATUSMASK);
30 }
31
32 bool midi_is_realtime(uint8_t theByte){
33    return (theByte >= MIDI_CLOCK);
34 }
35
36 midi_packet_length_t midi_packet_length(uint8_t status){
37    switch(status & 0xF0){
38       case MIDI_CC:
39       case MIDI_NOTEON:
40       case MIDI_NOTEOFF:
41       case MIDI_AFTERTOUCH:
42       case MIDI_PITCHBEND:
43          return THREE;
44       case MIDI_PROGCHANGE:
45       case MIDI_CHANPRESSURE:
46       case MIDI_SONGSELECT:
47          return TWO;
48       case 0xF0:
49          switch(status) {
50             case MIDI_CLOCK:
51             case MIDI_TICK:
52             case MIDI_START:
53             case MIDI_CONTINUE:
54             case MIDI_STOP:
55             case MIDI_ACTIVESENSE:
56             case MIDI_RESET:
57             case MIDI_TUNEREQUEST:
58                return ONE;
59             case MIDI_SONGPOSITION:
60                return THREE;
61             case MIDI_TC_QUARTERFRAME:
62             case MIDI_SONGSELECT:
63                return TWO;
64             case SYSEX_END:
65             case SYSEX_BEGIN:
66             default:
67                return UNDEFINED;
68          }
69       default:
70          return UNDEFINED;
71    }
72 }
73
74 void midi_send_cc(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t val){
75    //CC Status: 0xB0 to 0xBF where the low nibble is the MIDI channel.
76    //CC Data: Controller Num, Controller Val
77    device->send_func(device, 3,
78          MIDI_CC | (chan & MIDI_CHANMASK),
79          num & 0x7F,
80          val & 0x7F);
81 }
82
83 void midi_send_noteon(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t vel){
84    //Note Data: Note Num, Note Velocity
85    device->send_func(device, 3,
86          MIDI_NOTEON | (chan & MIDI_CHANMASK),
87          num & 0x7F,
88          vel & 0x7F);
89 }
90
91 void midi_send_noteoff(MidiDevice * device, uint8_t chan, uint8_t num, uint8_t vel){
92    //Note Data: Note Num, Note Velocity
93    device->send_func(device, 3,
94          MIDI_NOTEOFF | (chan & MIDI_CHANMASK),
95          num & 0x7F,
96          vel & 0x7F);
97 }
98
99 void midi_send_aftertouch(MidiDevice * device, uint8_t chan, uint8_t note_num, uint8_t amt){
100    device->send_func(device, 3,
101          MIDI_AFTERTOUCH | (chan & MIDI_CHANMASK),
102          note_num & 0x7F,
103          amt & 0x7F);
104 }
105
106 //XXX does this work right?
107 //amt in range -0x2000, 0x1fff
108 //uAmt should be in range..
109 //0x0000 to 0x3FFF
110 void midi_send_pitchbend(MidiDevice * device, uint8_t chan, int16_t amt){
111    uint16_t uAmt;
112    //check range
113    if(amt > 0x1fff){
114       uAmt = 0x3FFF;
115    } else if(amt < -0x2000){
116       uAmt = 0;
117    } else {
118       uAmt = amt + 0x2000;
119    }
120    device->send_func(device, 3,
121          MIDI_PITCHBEND | (chan & MIDI_CHANMASK),
122          uAmt & 0x7F,
123          (uAmt >> 7) & 0x7F);
124 }
125
126 void midi_send_programchange(MidiDevice * device, uint8_t chan, uint8_t num){
127    device->send_func(device, 2,
128          MIDI_PROGCHANGE | (chan & MIDI_CHANMASK),
129          num & 0x7F,
130          0);
131 }
132
133 void midi_send_channelpressure(MidiDevice * device, uint8_t chan, uint8_t amt){
134    device->send_func(device, 2,
135          MIDI_CHANPRESSURE | (chan & MIDI_CHANMASK),
136          amt & 0x7F,
137          0);
138 }
139
140 void midi_send_clock(MidiDevice * device){
141    device->send_func(device, 1, MIDI_CLOCK, 0, 0);
142 }
143
144 void midi_send_tick(MidiDevice * device){
145    device->send_func(device, 1, MIDI_TICK, 0, 0);
146 }
147
148 void midi_send_start(MidiDevice * device){
149    device->send_func(device, 1, MIDI_START, 0, 0);
150 }
151
152 void midi_send_continue(MidiDevice * device){
153    device->send_func(device, 1, MIDI_CONTINUE, 0, 0);
154 }
155
156 void midi_send_stop(MidiDevice * device){
157    device->send_func(device, 1, MIDI_STOP, 0, 0);
158 }
159
160 void midi_send_activesense(MidiDevice * device){
161    device->send_func(device, 1, MIDI_ACTIVESENSE, 0, 0);
162 }
163
164 void midi_send_reset(MidiDevice * device){
165    device->send_func(device, 1, MIDI_RESET, 0, 0);
166 }
167
168 void midi_send_tcquarterframe(MidiDevice * device, uint8_t time){
169    device->send_func(device, 2,
170          MIDI_TC_QUARTERFRAME,
171          time & 0x7F,
172          0);
173 }
174
175 //XXX is this right?
176 void midi_send_songposition(MidiDevice * device, uint16_t pos){
177    device->send_func(device, 3,
178          MIDI_SONGPOSITION,
179          pos & 0x7F,
180          (pos >> 7) & 0x7F);
181 }
182
183 void midi_send_songselect(MidiDevice * device, uint8_t song){
184    device->send_func(device, 2,
185          MIDI_SONGSELECT,
186          song & 0x7F,
187          0);
188 }
189
190 void midi_send_tunerequest(MidiDevice * device){
191    device->send_func(device, 1, MIDI_TUNEREQUEST, 0, 0);
192 }
193
194 void midi_send_byte(MidiDevice * device, uint8_t b){
195    device->send_func(device, 1, b, 0, 0);
196 }
197
198 void midi_send_data(MidiDevice * device, uint16_t count, uint8_t byte0, uint8_t byte1, uint8_t byte2){
199    //ensure that the count passed along is always 3 or lower
200    if (count > 3) {
201       //TODO how to do this correctly?
202    }
203    device->send_func(device, count, byte0, byte1, byte2);
204 }
205
206 void midi_send_array(MidiDevice * device, uint16_t count, uint8_t * array) {
207   uint16_t i;
208   for (i = 0; i < count; i += 3) {
209     uint8_t b[3] = { 0, 0, 0 };
210     uint16_t to_send = count - i;
211     to_send = (to_send > 3) ? 3 : to_send;
212     memcpy(b, array + i, to_send);
213     midi_send_data(device, to_send, b[0], b[1], b[2]);
214   }
215 }
216
217
218 void midi_register_cc_callback(MidiDevice * device, midi_three_byte_func_t func){
219    device->input_cc_callback = func;
220 }
221
222 void midi_register_noteon_callback(MidiDevice * device, midi_three_byte_func_t func){
223    device->input_noteon_callback = func;
224 }
225
226 void midi_register_noteoff_callback(MidiDevice * device, midi_three_byte_func_t func){
227    device->input_noteoff_callback = func;
228 }
229
230 void midi_register_aftertouch_callback(MidiDevice * device, midi_three_byte_func_t func){
231    device->input_aftertouch_callback = func;
232 }
233
234 void midi_register_pitchbend_callback(MidiDevice * device, midi_three_byte_func_t func){
235    device->input_pitchbend_callback = func;
236 }
237
238 void midi_register_songposition_callback(MidiDevice * device, midi_three_byte_func_t func){
239    device->input_songposition_callback = func;
240 }
241
242 void midi_register_progchange_callback(MidiDevice * device, midi_two_byte_func_t func) {
243    device->input_progchange_callback = func;
244 }
245
246 void midi_register_chanpressure_callback(MidiDevice * device, midi_two_byte_func_t func) {
247    device->input_chanpressure_callback = func;
248 }
249
250 void midi_register_songselect_callback(MidiDevice * device, midi_two_byte_func_t func) {
251    device->input_songselect_callback = func;
252 }
253
254 void midi_register_tc_quarterframe_callback(MidiDevice * device, midi_two_byte_func_t func) {
255    device->input_tc_quarterframe_callback = func;
256 }
257
258 void midi_register_realtime_callback(MidiDevice * device, midi_one_byte_func_t func){
259    device->input_realtime_callback = func;
260 }
261
262 void midi_register_tunerequest_callback(MidiDevice * device, midi_one_byte_func_t func){
263    device->input_tunerequest_callback = func;
264 }
265
266 void midi_register_sysex_callback(MidiDevice * device, midi_sysex_func_t func) {
267    device->input_sysex_callback = func;
268 }
269
270 void midi_register_fallthrough_callback(MidiDevice * device, midi_var_byte_func_t func){
271    device->input_fallthrough_callback = func;
272 }
273
274 void midi_register_catchall_callback(MidiDevice * device, midi_var_byte_func_t func){
275    device->input_catchall_callback = func;
276 }
277