qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

qmk_midi.c (4457B)


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