]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/process_keycode/process_midi.c
add support for pedal cc messages
[qmk_firmware.git] / quantum / process_keycode / process_midi.c
1 #include "process_midi.h"
2
3 typedef union {
4   uint16_t raw;
5   struct {
6     uint8_t octave   :4;
7     uint8_t velocity :4;
8     uint8_t channel  :4;
9   };
10 } midi_config_t;
11
12 midi_config_t midi_config;
13
14 #define MIDI_INVALID_NOTE 0xFF
15
16 #define MIDI_TONE_COUNT (MIDI_TONE_MAX - MIDI_TONE_MIN + 1)
17 static uint8_t tone_status[MIDI_TONE_COUNT];
18
19 inline uint8_t compute_velocity(uint8_t setting)
20 {
21     return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1));
22 }
23
24 void midi_init(void)
25 {
26     midi_config.octave = MI_OCT_0 - MIDI_OCTAVE_MIN;
27     midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN);
28     midi_config.channel = 0;
29     #ifdef MIDI_USE_NOTE_ON_ARRAY
30     notes_on.length = 0;
31     #else
32     for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++)
33     {
34         tone_status[i] = MIDI_INVALID_NOTE;
35     }
36     #endif
37 }
38
39 bool process_midi(uint16_t keycode, keyrecord_t *record)
40 {
41     switch (keycode) {
42         case MIDI_TONE_MIN ... MIDI_TONE_MAX:
43         {
44             uint8_t channel = midi_config.channel;
45             uint8_t tone = keycode - MIDI_TONE_MIN;
46             uint8_t velocity = compute_velocity(midi_config.velocity);
47             if (record->event.pressed) {
48                 uint8_t note = 12 * midi_config.octave + tone;
49                 midi_send_noteon(&midi_device, channel, note, velocity);
50                 dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
51                 tone_status[tone] = note;
52             }
53             else {
54                 uint8_t note = tone_status[tone];
55                 if (note != MIDI_INVALID_NOTE)
56                 {
57                     midi_send_noteoff(&midi_device, channel, note, velocity);
58                     dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity);
59                 }
60                 tone_status[tone] = MIDI_INVALID_NOTE;
61             }
62             return false;
63         }
64         case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX:
65             if (record->event.pressed) {
66                 midi_config.octave = keycode - MIDI_OCTAVE_MIN;
67                 dprintf("midi octave %d\n", midi_config.octave);
68             }
69             return false;
70         case MI_OCTD:
71             if (record->event.pressed && midi_config.octave > 0) {
72                 midi_config.octave--;
73                 dprintf("midi octave %d\n", midi_config.octave);
74             }
75             return false;
76         case MI_OCTU:
77             if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) {
78                 midi_config.octave++;
79                 dprintf("midi octave %d\n", midi_config.octave);
80             }
81             return false;
82         case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
83             if (record->event.pressed) {
84                 midi_config.velocity = keycode - MIDI_VELOCITY_MIN;
85                 dprintf("midi velocity %d\n", midi_config.velocity);
86             }
87             return false;
88         case MI_VELD:
89             if (record->event.pressed && midi_config.velocity > 0) {
90                 midi_config.velocity--;
91                 dprintf("midi velocity %d\n", midi_config.velocity);
92             }
93             return false;
94         case MI_VELU:
95             if (record->event.pressed) {
96                 midi_config.velocity++;
97                 dprintf("midi velocity %d\n", midi_config.velocity);
98             }
99             return false;
100         case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX:
101             if (record->event.pressed) {
102                 midi_config.channel = keycode - MIDI_CHANNEL_MIN;
103                 dprintf("midi channel %d\n", midi_config.channel);
104             }
105             return false;
106         case MI_CHD:
107             if (record->event.pressed) {
108                 midi_config.channel--;
109                 dprintf("midi channel %d\n", midi_config.channel);
110             }
111             return false;
112         case MI_CHU:
113             if (record->event.pressed) {
114                 midi_config.channel++;
115                 dprintf("midi channel %d\n", midi_config.channel);
116             }
117             return false;
118         case MI_OFF:
119             if (record->event.pressed) {
120                 midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
121                 dprintf("midi off\n");
122             }
123             return false;
124         case MI_SUS:
125             midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0);
126             dprintf("midi sustain %d\n", record->event.pressed);
127             return false;
128         case MI_PORT:
129             midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0);
130             dprintf("midi portamento %d\n", record->event.pressed);
131             return false;
132         case MI_SOST:
133             midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0);
134             dprintf("midi sostenuto %d\n", record->event.pressed);
135             return false;
136         case MI_SOFT:
137             midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
138             dprintf("midi soft %d\n", record->event.pressed);
139             return false;
140         case MI_LEG:
141             midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
142             dprintf("midi legato %d\n", record->event.pressed);
143             return false;
144     };
145
146     return true;
147 }