diff options
author | Bad Diode <bd@badd10de.dev> | 2023-02-08 17:49:45 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-02-08 17:49:45 +0100 |
commit | 8fc15953b2c10a8f06169b4ccbc6b16c86b205b2 (patch) | |
tree | 151c0e351ea07677e976dcae4f06ef16635662a3 /src | |
parent | c5095a38738d0f432245d14f91098c6309c1f6cc (diff) | |
download | launchpad-polymaker-8fc15953b2c10a8f06169b4ccbc6b16c86b205b2.tar.gz launchpad-polymaker-8fc15953b2c10a8f06169b4ccbc6b16c86b205b2.zip |
Add initial poly midi splitter
Diffstat (limited to 'src')
-rw-r--r-- | src/app.c | 121 |
1 files changed, 81 insertions, 40 deletions
@@ -34,7 +34,16 @@ | |||
34 | 34 | ||
35 | // Housekeeping and debugging. | 35 | // Housekeeping and debugging. |
36 | u16 frame = 0; | 36 | u16 frame = 0; |
37 | u16 value = 0; | 37 | u16 n_voices = 0; |
38 | |||
39 | typedef struct Voice { | ||
40 | u8 active; | ||
41 | u8 channel; | ||
42 | u8 d1; | ||
43 | u8 d2; | ||
44 | } Voice; | ||
45 | |||
46 | Voice voices[16] = {0}; | ||
38 | 47 | ||
39 | // store ADC frame pointer | 48 | // store ADC frame pointer |
40 | static const u16 *g_ADC = 0; | 49 | static const u16 *g_ADC = 0; |
@@ -127,42 +136,74 @@ u16 font_numbers[10] = { | |||
127 | 136 | ||
128 | void | 137 | void |
129 | app_surface_event(u8 type, u8 index, u8 value) { | 138 | app_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 | ||
154 | void | 163 | void |
155 | app_midi_event(u8 port, u8 status, u8 d1, u8 d2) { | 164 | app_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) { | |||
180 | void | 221 | void |
181 | app_cable_event(u8 type, u8 value) { | 222 | app_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 | ||
190 | void | 231 | void |
@@ -204,14 +245,14 @@ print_number(u8 n, u16 r, u16 g, u16 b, u8 x, u8 y) { | |||
204 | void | 245 | void |
205 | update(void) { | 246 | update(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 | ||
217 | void | 258 | void |
@@ -225,8 +266,8 @@ void | |||
225 | render(void) { | 266 | render(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 | } |