diff options
Diffstat (limited to 'src/sequencer.c')
-rw-r--r-- | src/sequencer.c | 214 |
1 files changed, 108 insertions, 106 deletions
diff --git a/src/sequencer.c b/src/sequencer.c index 46e57ef..dc3249c 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -2,6 +2,16 @@ | |||
2 | #include "text.h" | 2 | #include "text.h" |
3 | 3 | ||
4 | // | 4 | // |
5 | // Color indexes. | ||
6 | // | ||
7 | #define COL_BG 0 | ||
8 | #define COL_FG 1 | ||
9 | #define COL_RED 2 | ||
10 | #define COL_BLUE 3 | ||
11 | #define COL_CYAN 4 | ||
12 | #define COL_GREY 5 | ||
13 | |||
14 | // | ||
5 | // Assets. | 15 | // Assets. |
6 | // | 16 | // |
7 | 17 | ||
@@ -97,17 +107,11 @@ static const u32 channel_buttons[] = { | |||
97 | // | 107 | // |
98 | // Globals. | 108 | // Globals. |
99 | // | 109 | // |
100 | typedef enum { | ||
101 | SEQ_SELECT_TRIGGER, | ||
102 | SEQ_SELECT_CHANNEL, | ||
103 | SEQ_SELECT_PARAMETER, | ||
104 | } SeqSelect; | ||
105 | static int bpm = 115; | 110 | static int bpm = 115; |
106 | static int step_counter = 0; | 111 | static int step_counter = 0; |
107 | int trig_selection_loc = 0; | 112 | int trig_selection_loc = 0; |
108 | int param_selection_loc = 64; | 113 | int param_selection_loc = 64; |
109 | int channel_selection_loc = 0; | 114 | int channel_selection_loc = 0; |
110 | SeqSelect current_selection = SEQ_SELECT_TRIGGER; | ||
111 | 115 | ||
112 | // | 116 | // |
113 | // Wave data. | 117 | // Wave data. |
@@ -228,7 +232,7 @@ clear_trigger(size_t i) { | |||
228 | size_t x1 = TRIG_START_X + offset_x + TRIG_W - 1; | 232 | size_t x1 = TRIG_START_X + offset_x + TRIG_W - 1; |
229 | size_t y0 = TRIG_START_Y + offset_y + 1; | 233 | size_t y0 = TRIG_START_Y + offset_y + 1; |
230 | size_t y1 = TRIG_START_Y + offset_y + TRIG_H - 1; | 234 | size_t y1 = TRIG_START_Y + offset_y + TRIG_H - 1; |
231 | draw_filled_rect(x0, y0, x1, y1, 0); | 235 | draw_filled_rect(x0, y0, x1, y1, COL_BG); |
232 | } | 236 | } |
233 | 237 | ||
234 | void | 238 | void |
@@ -240,8 +244,8 @@ draw_trigger(size_t chan, size_t i) { | |||
240 | size_t y = TRIG_START_Y + offset_y; | 244 | size_t y = TRIG_START_Y + offset_y; |
241 | Tile *tiles = ASSETS_DATA; | 245 | Tile *tiles = ASSETS_DATA; |
242 | tiles += 2 * sequences[chan][i].note; | 246 | tiles += 2 * sequences[chan][i].note; |
243 | draw_tile(x, y, tiles, true); | 247 | draw_tile(x, y, tiles, COL_FG, true); |
244 | draw_tile(x + 8, y, tiles + 1, true); | 248 | draw_tile(x + 8, y, tiles + 1, COL_FG, true); |
245 | } else { | 249 | } else { |
246 | clear_trigger(i); | 250 | clear_trigger(i); |
247 | } | 251 | } |
@@ -266,11 +270,14 @@ draw_triggers(void) { | |||
266 | size_t x1 = TRIG_START_X + offset_x + TRIG_W; | 270 | size_t x1 = TRIG_START_X + offset_x + TRIG_W; |
267 | size_t y0 = TRIG_START_Y + offset_y; | 271 | size_t y0 = TRIG_START_Y + offset_y; |
268 | size_t y1 = TRIG_START_Y + offset_y + TRIG_H; | 272 | size_t y1 = TRIG_START_Y + offset_y + TRIG_H; |
269 | draw_rect(x0, y0, x1, y1, 1); | 273 | draw_rect(x0, y0, x1, y1, COL_FG); |
274 | clear_trigger(i); | ||
270 | draw_trigger(channel_selection_loc, i); | 275 | draw_trigger(channel_selection_loc, i); |
271 | } | 276 | } |
272 | } | 277 | } |
273 | 278 | ||
279 | #define CHAN_W 19 | ||
280 | #define CHAN_H 8 | ||
274 | #define CHAN_START_X 35 | 281 | #define CHAN_START_X 35 |
275 | #define CHAN_START_Y 90 | 282 | #define CHAN_START_Y 90 |
276 | #define CHAN_OFFSET_Y 12 | 283 | #define CHAN_OFFSET_Y 12 |
@@ -284,13 +291,23 @@ draw_channels(void) { | |||
284 | size_t k = 0; | 291 | size_t k = 0; |
285 | for (size_t i = 0; i < 4; i++) { | 292 | for (size_t i = 0; i < 4; i++) { |
286 | size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; | 293 | size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; |
287 | draw_tile(CHAN_START_X, y, channel_tiles + k++, false); | 294 | draw_tile(CHAN_START_X, y, channel_tiles + k++, COL_FG, false); |
288 | draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, false); | 295 | draw_tile(CHAN_START_X + 8, y, channel_tiles + k++, COL_FG, false); |
289 | draw_tile(CHAN_START_X + 16, y, channel_tiles + k++, false); | 296 | draw_tile(CHAN_START_X + 16, y, channel_tiles + k++, COL_FG, false); |
290 | } | 297 | } |
291 | } | 298 | } |
292 | 299 | ||
293 | void | 300 | void |
301 | draw_channel_cursor(size_t i, u8 clr) { | ||
302 | size_t offset_x = 0; | ||
303 | size_t offset_y = CHAN_H + i * CHAN_OFFSET_Y; | ||
304 | size_t x0 = CHAN_START_X + offset_x; | ||
305 | size_t x1 = CHAN_START_X + offset_x + CHAN_W; | ||
306 | size_t y = CHAN_START_Y + offset_y; | ||
307 | draw_line(x0, y, x1, y, clr); | ||
308 | } | ||
309 | |||
310 | void | ||
294 | irq_timer_0(void) { | 311 | irq_timer_0(void) { |
295 | Note active_note; | 312 | Note active_note; |
296 | { | 313 | { |
@@ -392,79 +409,102 @@ set_time(int bpm) { | |||
392 | TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; | 409 | TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3; |
393 | } | 410 | } |
394 | 411 | ||
412 | |||
413 | void (*input_handler)(void); | ||
414 | |||
395 | #define SEQ_N_CHANNELS 3 | 415 | #define SEQ_N_CHANNELS 3 |
396 | 416 | ||
417 | void handle_trigger_cursor(void); | ||
418 | void handle_channel_cursor(void); | ||
419 | |||
397 | void | 420 | void |
398 | trigger_cursor(void) { | 421 | handle_channel_cursor(void) { |
399 | SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; | 422 | if (key_tap(KEY_RIGHT)) { |
400 | if (key_tap(KEY_LEFT)) { | 423 | trig_selection_loc = 0; |
401 | if (trig_selection_loc == 0 || trig_selection_loc == 8) { | 424 | param_selection_loc = 0; |
402 | // current_selection = SEQ_SELECT_CHANNEL; | 425 | input_handler = handle_trigger_cursor; |
426 | draw_channel_cursor(channel_selection_loc, COL_GREY); | ||
427 | draw_trig_cursor(trig_selection_loc, COL_BLUE); | ||
428 | } | ||
429 | if (key_tap(KEY_UP)) { | ||
430 | draw_channel_cursor(channel_selection_loc, COL_BG); | ||
431 | if (channel_selection_loc == 0) { | ||
432 | channel_selection_loc = SEQ_N_CHANNELS - 1; | ||
403 | } else { | 433 | } else { |
404 | draw_trig_cursor(trig_selection_loc, 0); | 434 | channel_selection_loc = MAX(channel_selection_loc - 1, 0); |
405 | trig_selection_loc = MAX(trig_selection_loc - 1, 0); | ||
406 | draw_trig_cursor(trig_selection_loc, 3); | ||
407 | } | 435 | } |
408 | } else if (key_tap(KEY_RIGHT)) { | 436 | draw_channel_cursor(channel_selection_loc, COL_BLUE); |
409 | if (trig_selection_loc != 7) { | 437 | draw_triggers(); |
410 | draw_trig_cursor(trig_selection_loc, 0); | 438 | } |
411 | trig_selection_loc = MIN(trig_selection_loc + 1, 15); | 439 | if (key_tap(KEY_DOWN)) { |
412 | draw_trig_cursor(trig_selection_loc, 3); | 440 | draw_channel_cursor(channel_selection_loc, COL_BG); |
441 | if (channel_selection_loc == SEQ_N_CHANNELS - 1) { | ||
442 | channel_selection_loc = 0; | ||
443 | } else { | ||
444 | channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS); | ||
413 | } | 445 | } |
414 | } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { | 446 | draw_channel_cursor(channel_selection_loc, COL_BLUE); |
415 | draw_trig_cursor(trig_selection_loc, 0); | 447 | draw_triggers(); |
416 | trig_selection_loc = (trig_selection_loc + 8) % 16; | 448 | } |
417 | draw_trig_cursor(trig_selection_loc, 3); | 449 | } |
418 | } else if (key_tap(KEY_B)) { | 450 | |
451 | void | ||
452 | handle_trigger_cursor(void) { | ||
453 | SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; | ||
454 | |||
455 | if (key_tap(KEY_B)) { | ||
456 | // Toggle trigger. | ||
419 | trig->trigger ^= 1; | 457 | trig->trigger ^= 1; |
458 | draw_trigger(channel_selection_loc, trig_selection_loc); | ||
459 | } else if (key_tap(KEY_A)) { | ||
460 | // Switch to parameter selection. | ||
461 | // current_selection = SEQ_SELECT_PARAMETER; | ||
420 | } else if (key_tap(KEY_L)) { | 462 | } else if (key_tap(KEY_L)) { |
463 | // Decrease note. | ||
421 | if (trig->trigger) { | 464 | if (trig->trigger) { |
422 | trig->note = MAX(trig->note - 1, NOTE_C_2); | 465 | trig->note = MAX(trig->note - 1, NOTE_C_2); |
466 | clear_trigger(trig_selection_loc); | ||
467 | draw_trigger(channel_selection_loc, trig_selection_loc); | ||
423 | } | 468 | } |
424 | } else if (key_tap(KEY_R)) { | 469 | } else if (key_tap(KEY_R)) { |
470 | // Increase note. | ||
425 | if (trig->trigger) { | 471 | if (trig->trigger) { |
426 | trig->note = MIN( trig->note + 1, NOTE_C_8); | 472 | trig->note = MIN( trig->note + 1, NOTE_C_8); |
473 | clear_trigger(trig_selection_loc); | ||
474 | draw_trigger(channel_selection_loc, trig_selection_loc); | ||
427 | } | 475 | } |
428 | } else if (key_tap(KEY_A)) { | ||
429 | // Switch to parameter selection. | ||
430 | // current_selection = SEQ_SELECT_PARAMETER; | ||
431 | } | 476 | } |
432 | } | ||
433 | 477 | ||
434 | void (*input_handler)(void); | 478 | // Move trigger cursor. |
479 | if (key_tap(KEY_LEFT)) { | ||
480 | if (trig_selection_loc == 0 || trig_selection_loc == 8) { | ||
481 | // We are at the boundary, switch to channel selection. | ||
482 | draw_trig_cursor(trig_selection_loc, COL_BG); | ||
483 | input_handler = handle_channel_cursor; | ||
484 | draw_channel_cursor(channel_selection_loc, COL_BLUE); | ||
485 | } else { | ||
486 | draw_trig_cursor(trig_selection_loc, COL_BG); | ||
487 | trig_selection_loc = MAX(trig_selection_loc - 1, 0); | ||
488 | draw_trig_cursor(trig_selection_loc, COL_BLUE); | ||
489 | } | ||
490 | } else if (key_tap(KEY_RIGHT)) { | ||
491 | if (trig_selection_loc != 7) { | ||
492 | draw_trig_cursor(trig_selection_loc, COL_BG); | ||
493 | trig_selection_loc = MIN(trig_selection_loc + 1, 15); | ||
494 | draw_trig_cursor(trig_selection_loc, COL_BLUE); | ||
495 | } | ||
496 | } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { | ||
497 | draw_trig_cursor(trig_selection_loc, COL_BG); | ||
498 | trig_selection_loc = (trig_selection_loc + 8) % 16; | ||
499 | draw_trig_cursor(trig_selection_loc, COL_BLUE); | ||
500 | } | ||
501 | } | ||
435 | 502 | ||
436 | void | 503 | void |
437 | handle_sequencer_input(void) { | 504 | handle_sequencer_input(void) { |
438 | poll_keys(); | 505 | poll_keys(); |
439 | input_handler(); | 506 | input_handler(); |
440 | // SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; | 507 | // SeqTrigger *trig = &sequences[channel_selection_loc][trig_selection_loc]; |
441 | // if (current_selection == SEQ_SELECT_TRIGGER) { | ||
442 | // if (key_tap(KEY_LEFT)) { | ||
443 | // if (trig_selection_loc == 0 || trig_selection_loc == 8) { | ||
444 | // current_selection = SEQ_SELECT_CHANNEL; | ||
445 | // } else { | ||
446 | // trig_selection_loc = MAX(trig_selection_loc - 1, 0); | ||
447 | // } | ||
448 | // } else if (key_tap(KEY_RIGHT)) { | ||
449 | // if (trig_selection_loc != 7) { | ||
450 | // trig_selection_loc = MIN(trig_selection_loc + 1, 15); | ||
451 | // } | ||
452 | // } else if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { | ||
453 | // trig_selection_loc = (trig_selection_loc + 8) % 16; | ||
454 | // } else if (key_tap(KEY_B)) { | ||
455 | // trig->trigger ^= 1; | ||
456 | // } else if (key_tap(KEY_L)) { | ||
457 | // if (trig->trigger) { | ||
458 | // trig->note = MAX(trig->note - 1, NOTE_C_2); | ||
459 | // } | ||
460 | // } else if (key_tap(KEY_R)) { | ||
461 | // if (trig->trigger) { | ||
462 | // trig->note = MIN( trig->note + 1, NOTE_C_8); | ||
463 | // } | ||
464 | // } else if (key_tap(KEY_A)) { | ||
465 | // // Switch to parameter selection. | ||
466 | // current_selection = SEQ_SELECT_PARAMETER; | ||
467 | // } | ||
468 | // } else if (current_selection == SEQ_SELECT_PARAMETER) { | 508 | // } else if (current_selection == SEQ_SELECT_PARAMETER) { |
469 | // if (channel_selection_loc < 2) { | 509 | // if (channel_selection_loc < 2) { |
470 | // // Move through the selected synth parameters. | 510 | // // Move through the selected synth parameters. |
@@ -648,38 +688,8 @@ handle_sequencer_input(void) { | |||
648 | // } | 688 | // } |
649 | // } | 689 | // } |
650 | 690 | ||
651 | // // Go back to trigger selection. | ||
652 | // if (key_tap(KEY_A)) { | ||
653 | // current_selection = SEQ_SELECT_TRIGGER; | ||
654 | // } | ||
655 | |||
656 | // // Enable disable trigger. | ||
657 | // if (key_tap(KEY_B)) { | ||
658 | // trig->trigger ^= 1; | ||
659 | // } | ||
660 | // } else if (current_selection == SEQ_SELECT_CHANNEL) { | ||
661 | // if (key_tap(KEY_RIGHT)) { | ||
662 | // current_selection = SEQ_SELECT_TRIGGER; | ||
663 | // trig_selection_loc = 0; | ||
664 | // param_selection_loc = 0; | ||
665 | // } | ||
666 | // if (key_tap(KEY_UP)) { | ||
667 | // if (channel_selection_loc == 0) { | ||
668 | // channel_selection_loc = SEQ_N_CHANNELS - 1; | ||
669 | // } else { | ||
670 | // channel_selection_loc = MAX(channel_selection_loc - 1, 0); | ||
671 | // } | ||
672 | // } | ||
673 | // if (key_tap(KEY_DOWN)) { | ||
674 | // if (channel_selection_loc == SEQ_N_CHANNELS - 1) { | ||
675 | // channel_selection_loc = 0; | ||
676 | // } else { | ||
677 | // channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS); | ||
678 | // } | ||
679 | // } | ||
680 | // } | ||
681 | |||
682 | if (key_tap(KEY_START)) { | 691 | if (key_tap(KEY_START)) { |
692 | // Stop the sequencer or start playing from the beginning. | ||
683 | step_counter = 0; | 693 | step_counter = 0; |
684 | if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { | 694 | if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { |
685 | set_time(bpm); | 695 | set_time(bpm); |
@@ -689,22 +699,13 @@ handle_sequencer_input(void) { | |||
689 | SOUND_SQUARE2_CTRL = 0; | 699 | SOUND_SQUARE2_CTRL = 0; |
690 | SOUND_WAVE_CTRL = 0; | 700 | SOUND_WAVE_CTRL = 0; |
691 | } | 701 | } |
692 | } | 702 | } else if (key_tap(KEY_SELECT)) { |
693 | if (key_tap(KEY_SELECT)) { | 703 | // Play/pause. |
694 | TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; | 704 | TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; |
695 | SOUND_SQUARE1_CTRL = 0; | 705 | SOUND_SQUARE1_CTRL = 0; |
696 | SOUND_SQUARE2_CTRL = 0; | 706 | SOUND_SQUARE2_CTRL = 0; |
697 | SOUND_WAVE_CTRL = 0; | 707 | SOUND_WAVE_CTRL = 0; |
698 | } | 708 | } |
699 | |||
700 | // if (key_tap(KEY_LEFT) | ||
701 | // || key_tap(KEY_RIGHT) | ||
702 | // || key_tap(KEY_UP) | ||
703 | // || key_tap(KEY_DOWN) | ||
704 | // || key_tap(KEY_L) | ||
705 | // || key_tap(KEY_R) | ||
706 | // ) { | ||
707 | // } | ||
708 | } | 709 | } |
709 | 710 | ||
710 | void | 711 | void |
@@ -722,8 +723,9 @@ sequencer_init(void) { | |||
722 | draw_channels(); | 723 | draw_channels(); |
723 | 724 | ||
724 | // Initialize input handler. | 725 | // Initialize input handler. |
725 | input_handler = trigger_cursor; | 726 | input_handler = handle_trigger_cursor; |
726 | draw_trig_cursor(trig_selection_loc, 3); | 727 | draw_trig_cursor(trig_selection_loc, 3); |
728 | draw_channel_cursor(channel_selection_loc, 5); | ||
727 | 729 | ||
728 | // Initialize sound system. | 730 | // Initialize sound system. |
729 | SOUND_STATUS = SOUND_ENABLE; | 731 | SOUND_STATUS = SOUND_ENABLE; |