diff options
| author | Jack Humbert <jack.humb@gmail.com> | 2015-08-21 23:14:48 -0400 |
|---|---|---|
| committer | Jack Humbert <jack.humb@gmail.com> | 2015-08-21 23:14:48 -0400 |
| commit | 476e29d1190ac45b810109512bbb50cc4769493b (patch) | |
| tree | 1d493bae3b0ae91a6202918aa1bf53fb0da936fa /protocol/lufa/midi/midi.c | |
| parent | 2d76b5c3d421c984f6b4b9da757383cc87e3f808 (diff) | |
| parent | b191f8c60fbbaf1fb55d67edb86a6c33489b2ce3 (diff) | |
| download | qmk_firmware-476e29d1190ac45b810109512bbb50cc4769493b.tar.gz qmk_firmware-476e29d1190ac45b810109512bbb50cc4769493b.zip | |
Merge pull request #26 from jackhumbert/midi
Midi
Diffstat (limited to 'protocol/lufa/midi/midi.c')
| -rwxr-xr-x | protocol/lufa/midi/midi.c | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/protocol/lufa/midi/midi.c b/protocol/lufa/midi/midi.c new file mode 100755 index 000000000..11a589078 --- /dev/null +++ b/protocol/lufa/midi/midi.c | |||
| @@ -0,0 +1,277 @@ | |||
| 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 | |||
