midi.c (7949B)
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 #include "util.h" 22 23 #ifndef NULL 24 # define NULL 0 25 #endif 26 27 bool midi_is_statusbyte(uint8_t theByte) { 28 return (bool)(theByte & MIDI_STATUSMASK); 29 } 30 31 bool midi_is_realtime(uint8_t theByte) { 32 return (theByte >= MIDI_CLOCK); 33 } 34 35 midi_packet_length_t midi_packet_length(uint8_t status) { 36 switch (status & 0xF0) { 37 case MIDI_CC: 38 case MIDI_NOTEON: 39 case MIDI_NOTEOFF: 40 case MIDI_AFTERTOUCH: 41 case MIDI_PITCHBEND: 42 return THREE; 43 case MIDI_PROGCHANGE: 44 case MIDI_CHANPRESSURE: 45 case MIDI_SONGSELECT: 46 return TWO; 47 case 0xF0: 48 switch (status) { 49 case MIDI_CLOCK: 50 case MIDI_TICK: 51 case MIDI_START: 52 case MIDI_CONTINUE: 53 case MIDI_STOP: 54 case MIDI_ACTIVESENSE: 55 case MIDI_RESET: 56 case MIDI_TUNEREQUEST: 57 return ONE; 58 case MIDI_SONGPOSITION: 59 return THREE; 60 case MIDI_TC_QUARTERFRAME: 61 case MIDI_SONGSELECT: 62 return TWO; 63 case SYSEX_END: 64 case SYSEX_BEGIN: 65 default: 66 return UNDEFINED; 67 } 68 default: 69 return UNDEFINED; 70 } 71 } 72 73 void midi_send_cc(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t val) { 74 // CC Status: 0xB0 to 0xBF where the low nibble is the MIDI channel. 75 // CC Data: Controller Num, Controller Val 76 device->send_func(device, 3, MIDI_CC | (chan & MIDI_CHANMASK), num & 0x7F, val & 0x7F); 77 } 78 79 void midi_send_noteon(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t vel) { 80 // Note Data: Note Num, Note Velocity 81 device->send_func(device, 3, MIDI_NOTEON | (chan & MIDI_CHANMASK), num & 0x7F, vel & 0x7F); 82 } 83 84 void midi_send_noteoff(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t vel) { 85 // Note Data: Note Num, Note Velocity 86 device->send_func(device, 3, MIDI_NOTEOFF | (chan & MIDI_CHANMASK), num & 0x7F, vel & 0x7F); 87 } 88 89 void midi_send_aftertouch(MidiDevice* device, uint8_t chan, uint8_t note_num, uint8_t amt) { 90 device->send_func(device, 3, MIDI_AFTERTOUCH | (chan & MIDI_CHANMASK), note_num & 0x7F, amt & 0x7F); 91 } 92 93 // XXX does this work right? 94 // amt in range -0x2000, 0x1fff 95 // uAmt should be in range.. 96 // 0x0000 to 0x3FFF 97 void midi_send_pitchbend(MidiDevice* device, uint8_t chan, int16_t amt) { 98 uint16_t uAmt; 99 // check range 100 if (amt > 0x1fff) { 101 uAmt = 0x3FFF; 102 } else if (amt < -0x2000) { 103 uAmt = 0; 104 } else { 105 uAmt = amt + 0x2000; 106 } 107 device->send_func(device, 3, MIDI_PITCHBEND | (chan & MIDI_CHANMASK), uAmt & 0x7F, (uAmt >> 7) & 0x7F); 108 } 109 110 void midi_send_programchange(MidiDevice* device, uint8_t chan, uint8_t num) { 111 device->send_func(device, 2, MIDI_PROGCHANGE | (chan & MIDI_CHANMASK), num & 0x7F, 0); 112 } 113 114 void midi_send_channelpressure(MidiDevice* device, uint8_t chan, uint8_t amt) { 115 device->send_func(device, 2, MIDI_CHANPRESSURE | (chan & MIDI_CHANMASK), amt & 0x7F, 0); 116 } 117 118 void midi_send_clock(MidiDevice* device) { 119 device->send_func(device, 1, MIDI_CLOCK, 0, 0); 120 } 121 122 void midi_send_tick(MidiDevice* device) { 123 device->send_func(device, 1, MIDI_TICK, 0, 0); 124 } 125 126 void midi_send_start(MidiDevice* device) { 127 device->send_func(device, 1, MIDI_START, 0, 0); 128 } 129 130 void midi_send_continue(MidiDevice* device) { 131 device->send_func(device, 1, MIDI_CONTINUE, 0, 0); 132 } 133 134 void midi_send_stop(MidiDevice* device) { 135 device->send_func(device, 1, MIDI_STOP, 0, 0); 136 } 137 138 void midi_send_activesense(MidiDevice* device) { 139 device->send_func(device, 1, MIDI_ACTIVESENSE, 0, 0); 140 } 141 142 void midi_send_reset(MidiDevice* device) { 143 device->send_func(device, 1, MIDI_RESET, 0, 0); 144 } 145 146 void midi_send_tcquarterframe(MidiDevice* device, uint8_t time) { 147 device->send_func(device, 2, MIDI_TC_QUARTERFRAME, time & 0x7F, 0); 148 } 149 150 // XXX is this right? 151 void midi_send_songposition(MidiDevice* device, uint16_t pos) { 152 device->send_func(device, 3, MIDI_SONGPOSITION, pos & 0x7F, (pos >> 7) & 0x7F); 153 } 154 155 void midi_send_songselect(MidiDevice* device, uint8_t song) { 156 device->send_func(device, 2, MIDI_SONGSELECT, song & 0x7F, 0); 157 } 158 159 void midi_send_tunerequest(MidiDevice* device) { 160 device->send_func(device, 1, MIDI_TUNEREQUEST, 0, 0); 161 } 162 163 void midi_send_byte(MidiDevice* device, uint8_t b) { 164 device->send_func(device, 1, b, 0, 0); 165 } 166 167 void midi_send_data(MidiDevice* device, uint16_t count, uint8_t byte0, uint8_t byte1, uint8_t byte2) { 168 // ensure that the count passed along is always 3 or lower 169 if (count > 3) { 170 // TODO how to do this correctly? 171 } 172 device->send_func(device, count, byte0, byte1, byte2); 173 } 174 175 void midi_send_array(MidiDevice* device, uint16_t count, uint8_t* array) { 176 uint16_t i; 177 for (i = 0; i < count; i += 3) { 178 uint8_t b[3] = {0, 0, 0}; 179 uint16_t to_send = count - i; 180 to_send = (to_send > 3) ? 3 : to_send; 181 memcpy(b, array + i, to_send); 182 midi_send_data(device, to_send, b[0], b[1], b[2]); 183 } 184 } 185 186 void midi_register_cc_callback(MidiDevice* device, midi_three_byte_func_t func) { 187 device->input_cc_callback = func; 188 } 189 190 void midi_register_noteon_callback(MidiDevice* device, midi_three_byte_func_t func) { 191 device->input_noteon_callback = func; 192 } 193 194 void midi_register_noteoff_callback(MidiDevice* device, midi_three_byte_func_t func) { 195 device->input_noteoff_callback = func; 196 } 197 198 void midi_register_aftertouch_callback(MidiDevice* device, midi_three_byte_func_t func) { 199 device->input_aftertouch_callback = func; 200 } 201 202 void midi_register_pitchbend_callback(MidiDevice* device, midi_three_byte_func_t func) { 203 device->input_pitchbend_callback = func; 204 } 205 206 void midi_register_songposition_callback(MidiDevice* device, midi_three_byte_func_t func) { 207 device->input_songposition_callback = func; 208 } 209 210 void midi_register_progchange_callback(MidiDevice* device, midi_two_byte_func_t func) { 211 device->input_progchange_callback = func; 212 } 213 214 void midi_register_chanpressure_callback(MidiDevice* device, midi_two_byte_func_t func) { 215 device->input_chanpressure_callback = func; 216 } 217 218 void midi_register_songselect_callback(MidiDevice* device, midi_two_byte_func_t func) { 219 device->input_songselect_callback = func; 220 } 221 222 void midi_register_tc_quarterframe_callback(MidiDevice* device, midi_two_byte_func_t func) { 223 device->input_tc_quarterframe_callback = func; 224 } 225 226 void midi_register_realtime_callback(MidiDevice* device, midi_one_byte_func_t func) { 227 device->input_realtime_callback = func; 228 } 229 230 void midi_register_tunerequest_callback(MidiDevice* device, midi_one_byte_func_t func) { 231 device->input_tunerequest_callback = func; 232 } 233 234 void midi_register_sysex_callback(MidiDevice* device, midi_sysex_func_t func) { 235 device->input_sysex_callback = func; 236 } 237 238 void midi_register_fallthrough_callback(MidiDevice* device, midi_var_byte_func_t func) { 239 device->input_fallthrough_callback = func; 240 } 241 242 void midi_register_catchall_callback(MidiDevice* device, midi_var_byte_func_t func) { 243 device->input_catchall_callback = func; 244 }