logo

qmk_firmware

custom branch of QMK firmware git clone https://anongit.hacktivis.me/git/qmk_firmware.git

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