summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-02-08 17:49:45 +0100
committerBad Diode <bd@badd10de.dev>2023-02-08 17:49:45 +0100
commit8fc15953b2c10a8f06169b4ccbc6b16c86b205b2 (patch)
tree151c0e351ea07677e976dcae4f06ef16635662a3
parentc5095a38738d0f432245d14f91098c6309c1f6cc (diff)
downloadlaunchpad-polymaker-8fc15953b2c10a8f06169b4ccbc6b16c86b205b2.tar.gz
launchpad-polymaker-8fc15953b2c10a8f06169b4ccbc6b16c86b205b2.zip
Add initial poly midi splitter
-rw-r--r--src/app.c121
1 files changed, 81 insertions, 40 deletions
diff --git a/src/app.c b/src/app.c
index 9258965..27f88f1 100644
--- a/src/app.c
+++ b/src/app.c
@@ -34,7 +34,16 @@
34 34
35// Housekeeping and debugging. 35// Housekeeping and debugging.
36u16 frame = 0; 36u16 frame = 0;
37u16 value = 0; 37u16 n_voices = 0;
38
39typedef struct Voice {
40 u8 active;
41 u8 channel;
42 u8 d1;
43 u8 d2;
44} Voice;
45
46Voice voices[16] = {0};
38 47
39// store ADC frame pointer 48// store ADC frame pointer
40static const u16 *g_ADC = 0; 49static const u16 *g_ADC = 0;
@@ -127,42 +136,74 @@ u16 font_numbers[10] = {
127 136
128void 137void
129app_surface_event(u8 type, u8 index, u8 value) { 138app_surface_event(u8 type, u8 index, u8 value) {
130 switch (type) { 139 // switch (type) {
131 case TYPEPAD: { 140 // case TYPEPAD: {
132 // toggle it and store it off, so we can save to flash if we want to 141 // // toggle it and store it off, so we can save to flash if we want to
133 if (value) { 142 // if (value) {
134 buttons[index] = MAXLED * !buttons[index]; 143 // buttons[index] = MAXLED * !buttons[index];
135 } 144 // }
136 145
137 // example - light / extinguish pad LEDs 146 // // example - light / extinguish pad LEDs
138 // hal_plot_led(TYPEPAD, index, 0, 0, buttons[index]); 147 // hal_plot_led(TYPEPAD, index, 0, 0, buttons[index]);
139 148
140 // example - send MIDI 149 // // example - send MIDI
141 // hal_send_midi(DINMIDI, NOTEON | 0, index, value); 150 // hal_send_midi(DINMIDI, NOTEON | 0, index, value);
142 } break; 151 // } break;
143 case TYPESETUP: { 152 // case TYPESETUP: {
144 if (value) { 153 // if (value) {
145 // Pressing the setup button will save the current buttons/pad 154 // // Pressing the setup button will save the current buttons/pad
146 // state to the flash. The flash memory is USER_AREA_SIZE bytes 155 // // state to the flash. The flash memory is USER_AREA_SIZE bytes
147 // long and can be organized however we need. 156 // // long and can be organized however we need.
148 hal_write_flash(0, buttons, BUTTON_COUNT); 157 // hal_write_flash(0, buttons, BUTTON_COUNT);
149 } 158 // }
150 } break; 159 // } break;
151 } 160 // }
152} 161}
153 162
154void 163void
155app_midi_event(u8 port, u8 status, u8 d1, u8 d2) { 164app_midi_event(u8 port, u8 status, u8 d1, u8 d2) {
156 if (port == USBMIDI) { 165 u8 channel = status & 0x0F;
157 hal_send_midi(DINMIDI, status, d1, d2);
158 }
159 if (port == DINMIDI) {
160 hal_send_midi(USBMIDI, status, d1, d2);
161 }
162 if ((status & 0xF0) == NOTEON) { 166 if ((status & 0xF0) == NOTEON) {
163 value++; 167 // Find if the note was already pressed.
168 for (u8 i = 0; i < 16; i++) {
169 Voice *voice = &voices[i];
170 // Register voice.
171 if (voice->active && voice->d1 == d1) {
172 voice->active = 0;
173 hal_send_midi(port, NOTEOFF | i, d1, d2);
174 break;
175 }
176 }
177
178 // Find next free voice slot.
179 for (u8 i = 0; i < 16; i++) {
180 Voice *voice = &voices[i];
181 // Register voice.
182 if (!voice->active) {
183 voice->active = 1;
184 voice->channel = i;
185 voice->d1 = d1;
186 voice->d2 = d2;
187 hal_send_midi(port, NOTEON | i, d1, d2);
188 break;
189 }
190 }
191 // TODO: if there are no free slots choose the oldest active one.
192 // TODO: - Send noteoff message for the previous active channel.
193 // TODO: send noteon message.
194 n_voices++;
164 } else if ((status & 0xF0) == NOTEOFF) { 195 } else if ((status & 0xF0) == NOTEOFF) {
165 value--; 196 for (u8 i = 0; i < 16; i++) {
197 Voice *voice = &voices[i];
198 // Register voice.
199 if (voice->active && voice->d1 == d1) {
200 voice->active = 0;
201 hal_send_midi(port, NOTEOFF | i, d1, d2);
202 break;
203 }
204 }
205 n_voices--;
206 // hal_send_midi(port, status, d1, d2);
166 } 207 }
167} 208}
168 209
@@ -180,11 +221,11 @@ app_aftertouch_event(u8 index, u8 value) {
180void 221void
181app_cable_event(u8 type, u8 value) { 222app_cable_event(u8 type, u8 value) {
182 // example - light the Setup LED to indicate cable connections 223 // example - light the Setup LED to indicate cable connections
183 // if (type == MIDI_IN_CABLE) { 224 if (type == MIDI_IN_CABLE) {
184 // hal_plot_led(TYPESETUP, 0, 0, value, 0); // green 225 hal_plot_led(TYPESETUP, 0, 0, value, 0); // green
185 // } else if (type == MIDI_OUT_CABLE) { 226 } else if (type == MIDI_OUT_CABLE) {
186 // hal_plot_led(TYPESETUP, 0, value, 0, 0); // red 227 hal_plot_led(TYPESETUP, 0, value, 0, 0); // red
187 // } 228 }
188} 229}
189 230
190void 231void
@@ -204,14 +245,14 @@ print_number(u8 n, u16 r, u16 g, u16 b, u8 x, u8 y) {
204void 245void
205update(void) { 246update(void) {
206 // for (int i = 0; i < PAD_COUNT; ++i) { 247 // for (int i = 0; i < PAD_COUNT; ++i) {
207 // // Get the first detected button value. 248 // // Get the first detected button n_voices.
208 // u16 x = (99 * g_ADC[i]) >> 12; 249 // u16 x = (99 * g_ADC[i]) >> 12;
209 // if (x > 3) { 250 // if (x > 3) {
210 // value = x; 251 // n_voices = x;
211 // return; 252 // return;
212 // } 253 // }
213 // } 254 // }
214 // value = 0; 255 // n_voices = 0;
215} 256}
216 257
217void 258void
@@ -225,8 +266,8 @@ void
225render(void) { 266render(void) {
226 if (frame++ == 1000 / 10) { 267 if (frame++ == 1000 / 10) {
227 clear_pads(); 268 clear_pads();
228 print_number((value / 10) % 10, MAXLED, MAXLED, MAXLED, 0, 0); 269 print_number((n_voices / 10) % 10, MAXLED, MAXLED, MAXLED, 0, 0);
229 print_number( value % 10, MAXLED, MAXLED, MAXLED, 4, 0); 270 print_number( n_voices % 10, MAXLED, MAXLED, MAXLED, 4, 0);
230 frame = 0; 271 frame = 0;
231 } 272 }
232} 273}