summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-02-09 13:42:46 +0100
committerBad Diode <bd@badd10de.dev>2023-02-09 13:42:46 +0100
commit79b116d19fa4de2f7b5450acfe77a54524505b7d (patch)
tree6e06959a8a069a2d5da822b1c5fa3d149d26171a
parent8fc15953b2c10a8f06169b4ccbc6b16c86b205b2 (diff)
downloadlaunchpad-polymaker-79b116d19fa4de2f7b5450acfe77a54524505b7d.tar.gz
launchpad-polymaker-79b116d19fa4de2f7b5450acfe77a54524505b7d.zip
Enable bypass and bugfixes
-rw-r--r--src/app.c115
1 files changed, 83 insertions, 32 deletions
diff --git a/src/app.c b/src/app.c
index 27f88f1..7917a54 100644
--- a/src/app.c
+++ b/src/app.c
@@ -35,12 +35,16 @@
35// Housekeeping and debugging. 35// Housekeeping and debugging.
36u16 frame = 0; 36u16 frame = 0;
37u16 n_voices = 0; 37u16 n_voices = 0;
38u8 active = 1;
39u8 ch_min = 4;
40u8 ch_max = 8;
38 41
39typedef struct Voice { 42typedef struct Voice {
40 u8 active; 43 u8 active;
41 u8 channel; 44 u8 channel;
42 u8 d1; 45 u8 d1;
43 u8 d2; 46 u8 d2;
47 u8 port;
44} Voice; 48} Voice;
45 49
46Voice voices[16] = {0}; 50Voice voices[16] = {0};
@@ -134,76 +138,112 @@ u16 font_numbers[10] = {
134 0xF792, 138 0xF792,
135}; 139};
136 140
141enum Buttons {
142 POLY_PAD_ACTIVE = 11,
143};
144
137void 145void
138app_surface_event(u8 type, u8 index, u8 value) { 146app_surface_event(u8 type, u8 index, u8 value) {
139 // switch (type) { 147 switch (type) {
140 // case TYPEPAD: { 148 case TYPEPAD: {
141 // // toggle it and store it off, so we can save to flash if we want to 149 if (value && index == POLY_PAD_ACTIVE) {
142 // if (value) { 150 // Stop existing playing notes.
143 // buttons[index] = MAXLED * !buttons[index]; 151 for (u8 i = 0; i < 16; i++) {
144 // } 152 Voice *voice = &voices[i];
145 153 if (voice->active) {
146 // // example - light / extinguish pad LEDs 154 voice->active = 0;
147 // hal_plot_led(TYPEPAD, index, 0, 0, buttons[index]); 155 hal_send_midi(
148 156 voice->port,
149 // // example - send MIDI 157 NOTEOFF | voice->channel,
150 // hal_send_midi(DINMIDI, NOTEON | 0, index, value); 158 voice->d1,
151 // } break; 159 voice->d2);
152 // case TYPESETUP: { 160 }
153 // if (value) { 161 }
154 // // Pressing the setup button will save the current buttons/pad 162 n_voices = 0;
155 // // state to the flash. The flash memory is USER_AREA_SIZE bytes 163 active = !active;
156 // // long and can be organized however we need. 164 }
157 // hal_write_flash(0, buttons, BUTTON_COUNT); 165 // // toggle it and store it off, so we can save to flash if we want to
158 // } 166 // if (value) {
159 // } break; 167 // buttons[index] = MAXLED * !buttons[index];
160 // } 168 // }
169
170 // // example - light / extinguish pad LEDs
171 // hal_plot_led(TYPEPAD, index, 0, 0, buttons[index]);
172
173 // // example - send MIDI
174 // hal_send_midi(DINMIDI, NOTEON | 0, index, value);
175 } break;
176 case TYPESETUP: {
177 // if (value) {
178 // // Pressing the setup button will save the current buttons/pad
179 // // state to the flash. The flash memory is USER_AREA_SIZE bytes
180 // // long and can be organized however we need.
181 // hal_write_flash(0, buttons, BUTTON_COUNT);
182 // }
183 } break;
184 }
161} 185}
162 186
163void 187void
164app_midi_event(u8 port, u8 status, u8 d1, u8 d2) { 188app_midi_event(u8 port, u8 status, u8 d1, u8 d2) {
189 if (!active) {
190 hal_send_midi(port, status, d1, d2);
191 return;
192 }
165 u8 channel = status & 0x0F; 193 u8 channel = status & 0x0F;
166 if ((status & 0xF0) == NOTEON) { 194 if ((status & 0xF0) == NOTEON) {
195 if (n_voices == (ch_max - ch_min)) {
196 return;
197 }
198
167 // Find if the note was already pressed. 199 // Find if the note was already pressed.
168 for (u8 i = 0; i < 16; i++) { 200 for (u8 i = ch_min; i < ch_max; i++) {
169 Voice *voice = &voices[i]; 201 Voice *voice = &voices[i];
170 // Register voice. 202 // Stop voice if needed.
171 if (voice->active && voice->d1 == d1) { 203 if (voice->active && voice->d1 == d1) {
172 voice->active = 0; 204 voice->active = 0;
173 hal_send_midi(port, NOTEOFF | i, d1, d2); 205 hal_send_midi(voice->port,
206 NOTEOFF | voice->channel,
207 voice->d1,
208 voice->d2);
174 break; 209 break;
175 } 210 }
176 } 211 }
177 212
178 // Find next free voice slot. 213 // Find next free voice slot.
179 for (u8 i = 0; i < 16; i++) { 214 for (u8 i = ch_min; i < ch_max; i++) {
180 Voice *voice = &voices[i]; 215 Voice *voice = &voices[i];
181 // Register voice. 216 // Register voice.
182 if (!voice->active) { 217 if (!voice->active) {
183 voice->active = 1; 218 voice->active = 1;
219 voice->port = port;
184 voice->channel = i; 220 voice->channel = i;
185 voice->d1 = d1; 221 voice->d1 = d1;
186 voice->d2 = d2; 222 voice->d2 = d2;
187 hal_send_midi(port, NOTEON | i, d1, d2); 223 hal_send_midi(voice->port,
224 NOTEON | voice->channel,
225 voice->d1,
226 voice->d2);
188 break; 227 break;
189 } 228 }
190 } 229 }
230
191 // TODO: if there are no free slots choose the oldest active one. 231 // TODO: if there are no free slots choose the oldest active one.
192 // TODO: - Send noteoff message for the previous active channel. 232 // TODO: - Send noteoff message for the previous active channel.
193 // TODO: send noteon message. 233 // TODO: send noteon message.
234 // TODO: Round robin scheduling?
194 n_voices++; 235 n_voices++;
195 } else if ((status & 0xF0) == NOTEOFF) { 236 } else if ((status & 0xF0) == NOTEOFF) {
196 for (u8 i = 0; i < 16; i++) { 237 for (u8 i = ch_min; i < ch_max; i++) {
197 Voice *voice = &voices[i]; 238 Voice *voice = &voices[i];
198 // Register voice. 239 // Register voice.
199 if (voice->active && voice->d1 == d1) { 240 if (voice->active && voice->d1 == d1) {
200 voice->active = 0; 241 voice->active = 0;
201 hal_send_midi(port, NOTEOFF | i, d1, d2); 242 hal_send_midi(port, NOTEOFF | i, d1, d2);
243 n_voices--;
202 break; 244 break;
203 } 245 }
204 } 246 }
205 n_voices--;
206 // hal_send_midi(port, status, d1, d2);
207 } 247 }
208} 248}
209 249
@@ -263,11 +303,22 @@ clear_pads(void) {
263} 303}
264 304
265void 305void
306draw_poly_scene(void) {
307 print_number((n_voices / 10) % 10, MAXLED, MAXLED, MAXLED, 0, 0);
308 print_number( n_voices % 10, MAXLED, MAXLED, MAXLED, 4, 0);
309
310 if (active) {
311 hal_plot_led(TYPEPAD, 11, 0, MAXLED, 0);
312 } else {
313 hal_plot_led(TYPEPAD, 11, MAXLED, 0, 0);
314 }
315}
316
317void
266render(void) { 318render(void) {
267 if (frame++ == 1000 / 10) { 319 if (frame++ == 1000 / 10) {
268 clear_pads(); 320 clear_pads();
269 print_number((n_voices / 10) % 10, MAXLED, MAXLED, MAXLED, 0, 0); 321 draw_poly_scene();
270 print_number( n_voices % 10, MAXLED, MAXLED, MAXLED, 4, 0);
271 frame = 0; 322 frame = 0;
272 } 323 }
273} 324}