aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-03 20:56:38 +0200
committerBad Diode <bd@badd10de.dev>2023-04-03 20:56:38 +0200
commit0fdb142de3225dcc9f4b1eb940ec26ff869c0eb2 (patch)
tree28f87b9d0a28f6b792eb8de4067e53e08c910dff
parent6d0cec873eecc694d1ff61f398c5764a7fa55dae (diff)
downloadstepper-0fdb142de3225dcc9f4b1eb940ec26ff869c0eb2.tar.gz
stepper-0fdb142de3225dcc9f4b1eb940ec26ff869c0eb2.zip
Add pattern selection control
-rw-r--r--src/sequencer.c221
1 files changed, 154 insertions, 67 deletions
diff --git a/src/sequencer.c b/src/sequencer.c
index 3f477f3..511e5e4 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -6,7 +6,6 @@
6// - Copy paste trigs/notes/params 6// - Copy paste trigs/notes/params
7// - Different banks for storing patterns 7// - Different banks for storing patterns
8// - Buttons on the left side for selecting different patterns 8// - Buttons on the left side for selecting different patterns
9// - Pattern chaining or song mode
10// - Allow control BPM 9// - Allow control BPM
11// - Finish noise channel 10// - Finish noise channel
12 11
@@ -24,8 +23,6 @@
24// Theme colors. 23// Theme colors.
25#define COL_CURSOR COL_BLUE 24#define COL_CURSOR COL_BLUE
26#define COL_NOTE_PRESSED COL_GREY 25#define COL_NOTE_PRESSED COL_GREY
27#define COL_CURRENT_CHANNEL COL_GREY
28#define COL_CURRENT_TRIG COL_GREY
29#define COL_WAVE_A COL_RED 26#define COL_WAVE_A COL_RED
30#define COL_WAVE_B COL_CYAN 27#define COL_WAVE_B COL_CYAN
31 28
@@ -56,6 +53,12 @@
56#define R_SIDEBAR_X ((TRIG_START_X) + (TRIG_OFFSET_X) * 8 + 4) 53#define R_SIDEBAR_X ((TRIG_START_X) + (TRIG_OFFSET_X) * 8 + 4)
57#define L_SIDEBAR_X ((CHAN_START_X) - 26) 54#define L_SIDEBAR_X ((CHAN_START_X) - 26)
58 55
56#define PAT_START_X (L_SIDEBAR_X + 5)
57#define PAT_START_Y 18
58#define PAT_W 14
59#define PAT_H 12
60#define PAT_OFFSET_Y 17
61
59#define SEQ_N_CHANNELS 4 62#define SEQ_N_CHANNELS 4
60 63
61// 64//
@@ -184,12 +187,15 @@ static const u32 square_wave[16] = {
184// Globals. 187// Globals.
185// 188//
186 189
187static int bpm = 75; 190const int default_bpm = 75;
188static int step_counter = 0; 191static int step_counter = 0;
189int trig_selection_loc = 0; 192int trig_selection_loc = 0;
190int param_selection_loc = 0; 193int param_selection_loc = 0;
191int channel_selection_loc = 0; 194int channel_selection_loc = 0;
195int pattern_selection_loc = 1;
192int play_status = 0; 196int play_status = 0;
197static int current_pattern = 0;
198static int next_pattern = 0;
193 199
194typedef struct TriggerNote { 200typedef struct TriggerNote {
195 bool active; 201 bool active;
@@ -238,7 +244,7 @@ typedef struct ChannelNoise {
238 ChannelNoiseParams params[16]; 244 ChannelNoiseParams params[16];
239} ChannelNoise; 245} ChannelNoise;
240 246
241static ChannelSquare ch1 = { 247const ChannelSquare default_ch1 = {
242 .notes = { 248 .notes = {
243 {true, NOTE_C_4}, 249 {true, NOTE_C_4},
244 {true, NOTE_D_4}, 250 {true, NOTE_D_4},
@@ -278,7 +284,7 @@ static ChannelSquare ch1 = {
278 .active = false, 284 .active = false,
279}; 285};
280 286
281static ChannelSquare ch2 = { 287const ChannelSquare default_ch2 = {
282 .notes = { 288 .notes = {
283 {true, NOTE_C_4}, 289 {true, NOTE_C_4},
284 {true, NOTE_D_4}, 290 {true, NOTE_D_4},
@@ -318,7 +324,7 @@ static ChannelSquare ch2 = {
318 .active = false, 324 .active = false,
319}; 325};
320 326
321static ChannelWave ch3 = { 327const ChannelWave default_ch3 = {
322 .notes = { 328 .notes = {
323 {true, NOTE_C_4}, 329 {true, NOTE_C_4},
324 {true, NOTE_D_4}, 330 {true, NOTE_D_4},
@@ -358,8 +364,7 @@ static ChannelWave ch3 = {
358 .active = false, 364 .active = false,
359}; 365};
360 366
361// TODO: Add default noise parameters data. 367const ChannelNoise default_ch4 = {
362static ChannelNoise ch4 = {
363 .notes = { 368 .notes = {
364 {true, NOTE_C_4}, 369 {true, NOTE_C_4},
365 {false, NOTE_D_4}, 370 {false, NOTE_D_4},
@@ -399,6 +404,25 @@ static ChannelNoise ch4 = {
399 .active = true, 404 .active = true,
400}; 405};
401 406
407typedef struct Pattern {
408 int bpm;
409 ChannelSquare ch1;
410 ChannelSquare ch2;
411 ChannelWave ch3;
412 ChannelNoise ch4;
413} Pattern;
414
415static Pattern patterns[8] = {
416 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
417 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
418 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
419 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
420 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
421 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
422 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
423 {default_bpm, default_ch1, default_ch2, default_ch3, default_ch4},
424};
425
402// 426//
403// Channel render functions. 427// Channel render functions.
404// 428//
@@ -413,16 +437,16 @@ draw_channels(void) {
413 bool active = false; 437 bool active = false;
414 switch (i) { 438 switch (i) {
415 case 0: { 439 case 0: {
416 active = ch1.active; 440 active = patterns[pattern_selection_loc].ch1.active;
417 } break; 441 } break;
418 case 1: { 442 case 1: {
419 active = ch2.active; 443 active = patterns[pattern_selection_loc].ch2.active;
420 } break; 444 } break;
421 case 2: { 445 case 2: {
422 active = ch3.active; 446 active = patterns[pattern_selection_loc].ch3.active;
423 } break; 447 } break;
424 case 3: { 448 case 3: {
425 active = ch4.active; 449 active = patterns[pattern_selection_loc].ch4.active;
426 } break; 450 } break;
427 } 451 }
428 u8 clr = active ? COL_FG : COL_GREY; 452 u8 clr = active ? COL_FG : COL_GREY;
@@ -454,7 +478,7 @@ clear_trigger(size_t i) {
454 size_t x0 = TRIG_START_X + offset_x + 1; 478 size_t x0 = TRIG_START_X + offset_x + 1;
455 size_t x1 = TRIG_START_X + offset_x + TRIG_W - 1; 479 size_t x1 = TRIG_START_X + offset_x + TRIG_W - 1;
456 size_t y0 = TRIG_START_Y + offset_y + 1; 480 size_t y0 = TRIG_START_Y + offset_y + 1;
457 size_t y1 = TRIG_START_Y + offset_y + TRIG_H - 1; 481 size_t y1 = TRIG_START_Y + offset_y + TRIG_H - 4;
458 draw_filled_rect(x0, y0, x1, y1, COL_BG); 482 draw_filled_rect(x0, y0, x1, y1, COL_BG);
459} 483}
460 484
@@ -463,16 +487,16 @@ draw_trigger(size_t chan, size_t i) {
463 TriggerNote trig = {0}; 487 TriggerNote trig = {0};
464 switch (chan) { 488 switch (chan) {
465 case 0: { 489 case 0: {
466 trig = ch1.notes[i]; 490 trig = patterns[pattern_selection_loc].ch1.notes[i];
467 } break; 491 } break;
468 case 1: { 492 case 1: {
469 trig = ch2.notes[i]; 493 trig = patterns[pattern_selection_loc].ch2.notes[i];
470 } break; 494 } break;
471 case 2: { 495 case 2: {
472 trig = ch3.notes[i]; 496 trig = patterns[pattern_selection_loc].ch3.notes[i];
473 } break; 497 } break;
474 case 3: { 498 case 3: {
475 trig = ch4.notes[i]; 499 trig = patterns[pattern_selection_loc].ch4.notes[i];
476 } break; 500 } break;
477 } 501 }
478 if (trig.active) { 502 if (trig.active) {
@@ -503,8 +527,8 @@ void
503draw_current_step(u8 col) { 527draw_current_step(u8 col) {
504 size_t offset_x = TRIG_OFFSET_X * (step_counter % 8); 528 size_t offset_x = TRIG_OFFSET_X * (step_counter % 8);
505 size_t offset_y = step_counter < 8 ? 2 : 2 + TRIG_OFFSET_Y; 529 size_t offset_y = step_counter < 8 ? 2 : 2 + TRIG_OFFSET_Y;
506 size_t x0 = TRIG_START_X + 4 + offset_x; 530 size_t x0 = TRIG_START_X + 3 + offset_x;
507 size_t x1 = TRIG_START_X - 4 + TRIG_W + offset_x; 531 size_t x1 = TRIG_START_X - 3 + TRIG_W + offset_x;
508 size_t y = TRIG_START_Y - 4 + TRIG_H + offset_y; 532 size_t y = TRIG_START_Y - 4 + TRIG_H + offset_y;
509 draw_line(x0, y, x1, y, col); 533 draw_line(x0, y, x1, y, col);
510} 534}
@@ -531,28 +555,44 @@ draw_play() {
531 555
532void 556void
533draw_pattern_buttons() { 557draw_pattern_buttons() {
534 size_t x = L_SIDEBAR_X; 558 size_t x = PAT_START_X;
535 size_t y = PARAMS_START_Y + 17; 559 size_t y = PAT_START_Y;
536 txt_drawf_small("PAT", x + 5, y - 10, 4, COL_FG); 560 txt_drawf_small("PAT", x, y - 10, 4, COL_FG);
537 char pat_names[] = { 561 char pat_names[] = {
538 'A', 'B', 'C', 'D', 562 'A', 'B', 'C', 'D',
539 'E', 'F', 'G', 'H', 563 'E', 'F', 'G', 'H',
540 }; 564 };
541 for (size_t i = 0; i < 8; i++) { 565 for (int i = 0; i < 8; i++) {
542 draw_rect(x + 5, y, x + 19, y + 12, COL_GREY); 566 int color = COL_GREY;
543 txt_drawc(pat_names[i], x + 9, y + 2, 6, COL_GREY); 567 if (i == current_pattern) {
544 y += 17; 568 color = COL_FG;
569 }
570 if (i == next_pattern && current_pattern != next_pattern) {
571 color = COL_BLUE;
572 }
573 draw_filled_rect(x, y, x + PAT_W, y + PAT_H, COL_BG);
574 draw_rect(x, y, x + PAT_W, y + PAT_H, color);
575 txt_drawc(pat_names[i], x + 4, y + 2, 6, color);
576 y += PAT_OFFSET_Y;
545 } 577 }
546} 578}
547 579
548void 580void
581draw_pattern_cursor(size_t i, u8 clr) {
582 size_t offset_x = 0;
583 size_t offset_y = PAT_H + i * PAT_OFFSET_Y + 2;
584 size_t x0 = PAT_START_X + offset_x;
585 size_t x1 = PAT_START_X + offset_x + PAT_W;
586 size_t y = PAT_START_Y + offset_y;
587 draw_line(x0, y, x1, y, clr);
588}
589
590void
549draw_stop() { 591draw_stop() {
550 size_t x = R_SIDEBAR_X; 592 size_t x = R_SIDEBAR_X;
551 size_t y = TRIG_START_Y + 14; 593 size_t y = TRIG_START_Y + 14;
552 draw_rect(x, y, x + 24, y + 10, COL_RED); 594 draw_rect(x, y, x + 24, y + 10, COL_RED);
553 draw_filled_rect(x + 10, y + 3, x + 14, y + 7, COL_RED); 595 draw_filled_rect(x + 10, y + 3, x + 14, y + 7, COL_RED);
554 // DEBUG: ...
555 draw_pattern_buttons();
556} 596}
557 597
558void 598void
@@ -566,6 +606,7 @@ draw_bpm() {
566 txt_drawf_small("BPM", x + 5, y - 4, 4, COL_FG); 606 txt_drawf_small("BPM", x + 5, y - 4, 4, COL_FG);
567 607
568 // Make sure its horizontally centered if only 2 digits 608 // Make sure its horizontally centered if only 2 digits
609 int bpm = patterns[current_pattern].bpm;
569 if (bpm >= 100) { 610 if (bpm >= 100) {
570 txt_drawf("%d", x + 3, y + 7, 6, COL_FG, bpm); 611 txt_drawf("%d", x + 3, y + 7, 6, COL_FG, bpm);
571 } else { 612 } else {
@@ -907,9 +948,10 @@ IWRAM_CODE
907void 948void
908draw_parameters_wave(void) { 949draw_parameters_wave(void) {
909 // Draw current wave data. 950 // Draw current wave data.
951 Pattern *pat = &patterns[pattern_selection_loc];
910 { 952 {
911 u8 *wave_a = ch3.params[trig_selection_loc].wave_a; 953 u8 *wave_a = pat->ch3.params[trig_selection_loc].wave_a;
912 u8 *wave_b = ch3.params[trig_selection_loc].wave_b; 954 u8 *wave_b = pat->ch3.params[trig_selection_loc].wave_b;
913 955
914 size_t x = PARAMS_START_X; 956 size_t x = PARAMS_START_X;
915 size_t y = PARAMS_START_Y + 13; 957 size_t y = PARAMS_START_Y + 13;
@@ -966,7 +1008,7 @@ draw_parameters_wave(void) {
966 draw_line(x, y + 17, x + 30, y + 17, COL_FG); 1008 draw_line(x, y + 17, x + 30, y + 17, COL_FG);
967 txt_drawf_small("mode", x + 6, y, 4, COL_FG); 1009 txt_drawf_small("mode", x + 6, y, 4, COL_FG);
968 1010
969 switch (ch3.params[trig_selection_loc].wave_mode) { 1011 switch (pat->ch3.params[trig_selection_loc].wave_mode) {
970 case 0: { 1012 case 0: {
971 txt_drawf("A", x + 12, y + 7, 6, COL_FG); 1013 txt_drawf("A", x + 12, y + 7, 6, COL_FG);
972 } break; 1014 } break;
@@ -990,7 +1032,7 @@ draw_parameters_wave(void) {
990 draw_line(x, y + 20, x + 30, y + 20, COL_FG); 1032 draw_line(x, y + 20, x + 30, y + 20, COL_FG);
991 txt_drawf_small("vol", x + 8, y + 3, 4, COL_FG); 1033 txt_drawf_small("vol", x + 8, y + 3, 4, COL_FG);
992 1034
993 switch (ch3.params[trig_selection_loc].wave_volume) { 1035 switch (pat->ch3.params[trig_selection_loc].wave_volume) {
994 case 0: { 1036 case 0: {
995 txt_drawf("0", x + 12, y + 10, 6, COL_FG); 1037 txt_drawf("0", x + 12, y + 10, 6, COL_FG);
996 } break; 1038 } break;
@@ -1375,12 +1417,13 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
1375void 1417void
1376draw_parameters(void) { 1418draw_parameters(void) {
1377 clear_parameters(); 1419 clear_parameters();
1420 Pattern *pat = &patterns[pattern_selection_loc];
1378 switch (channel_selection_loc) { 1421 switch (channel_selection_loc) {
1379 case 0: { 1422 case 0: {
1380 draw_parameters_square(&ch1.params[trig_selection_loc], true); 1423 draw_parameters_square(&pat->ch1.params[trig_selection_loc], true);
1381 } break; 1424 } break;
1382 case 1: { 1425 case 1: {
1383 draw_parameters_square(&ch2.params[trig_selection_loc], false); 1426 draw_parameters_square(&pat->ch2.params[trig_selection_loc], false);
1384 } break; 1427 } break;
1385 case 2: { 1428 case 2: {
1386 draw_parameters_wave(); 1429 draw_parameters_wave();
@@ -1392,9 +1435,14 @@ draw_parameters(void) {
1392 1435
1393void 1436void
1394irq_timer(void) { 1437irq_timer(void) {
1395 if (ch1.active) { 1438 if (current_pattern != next_pattern && step_counter == 0) {
1396 TriggerNote *trig = &ch1.notes[step_counter]; 1439 current_pattern = next_pattern;
1397 ChannelSquareParams *params = &ch1.params[step_counter]; 1440 draw_pattern_buttons();
1441 }
1442 Pattern *pat = &patterns[current_pattern];
1443 if (pat->ch1.active) {
1444 TriggerNote *trig = &pat->ch1.notes[step_counter];
1445 ChannelSquareParams *params = &pat->ch1.params[step_counter];
1398 if (trig->active) { 1446 if (trig->active) {
1399 SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(params->sweep_number) 1447 SOUND_SQUARE1_SWEEP = SOUND_SWEEP_NUMBER(params->sweep_number)
1400 | SOUND_SWEEP_DIR(params->sweep_direction) 1448 | SOUND_SWEEP_DIR(params->sweep_direction)
@@ -1410,9 +1458,9 @@ irq_timer(void) {
1410 SOUND_SQUARE1_CTRL = 0; 1458 SOUND_SQUARE1_CTRL = 0;
1411 SOUND_SQUARE1_FREQ = 0; 1459 SOUND_SQUARE1_FREQ = 0;
1412 } 1460 }
1413 if (ch2.active) { 1461 if (pat->ch2.active) {
1414 TriggerNote *trig = &ch2.notes[step_counter]; 1462 TriggerNote *trig = &pat->ch2.notes[step_counter];
1415 ChannelSquareParams *params = &ch2.params[step_counter]; 1463 ChannelSquareParams *params = &pat->ch2.params[step_counter];
1416 if (trig->active) { 1464 if (trig->active) {
1417 SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume) 1465 SOUND_SQUARE2_CTRL = SOUND_SQUARE_ENV_VOL(params->env_volume)
1418 | SOUND_SQUARE_ENV_TIME(params->env_time) 1466 | SOUND_SQUARE_ENV_TIME(params->env_time)
@@ -1425,9 +1473,9 @@ irq_timer(void) {
1425 SOUND_SQUARE2_CTRL = 0; 1473 SOUND_SQUARE2_CTRL = 0;
1426 SOUND_SQUARE2_FREQ = 0; 1474 SOUND_SQUARE2_FREQ = 0;
1427 } 1475 }
1428 if (ch3.active) { 1476 if (pat->ch3.active) {
1429 TriggerNote *trig = &ch3.notes[step_counter]; 1477 TriggerNote *trig = &pat->ch3.notes[step_counter];
1430 ChannelWaveParams *params = &ch3.params[step_counter]; 1478 ChannelWaveParams *params = &pat->ch3.params[step_counter];
1431 if (trig->active) { 1479 if (trig->active) {
1432 switch (params->wave_mode) { 1480 switch (params->wave_mode) {
1433 case 0: { 1481 case 0: {
@@ -1477,9 +1525,9 @@ irq_timer(void) {
1477 SOUND_WAVE_CTRL = 0; 1525 SOUND_WAVE_CTRL = 0;
1478 SOUND_WAVE_FREQ = 0; 1526 SOUND_WAVE_FREQ = 0;
1479 } 1527 }
1480 if (ch4.active) { 1528 if (pat->ch4.active) {
1481 TriggerNote *trig = &ch4.notes[step_counter]; 1529 TriggerNote *trig = &pat->ch4.notes[step_counter];
1482 ChannelNoiseParams *params = &ch4.params[step_counter]; 1530 ChannelNoiseParams *params = &pat->ch4.params[step_counter];
1483 SOUND_NOISE_CTRL = SOUND_NOISE_ENV_VOL(params->env_volume) 1531 SOUND_NOISE_CTRL = SOUND_NOISE_ENV_VOL(params->env_volume)
1484 | SOUND_NOISE_ENV_TIME(params->env_time) 1532 | SOUND_NOISE_ENV_TIME(params->env_time)
1485 | SOUND_NOISE_ENV_DIR(params->env_direction); 1533 | SOUND_NOISE_ENV_DIR(params->env_direction);
@@ -1533,18 +1581,19 @@ set_time(int bpm) {
1533 1581
1534TriggerNote * 1582TriggerNote *
1535get_current_trig(void) { 1583get_current_trig(void) {
1584 Pattern *pat = &patterns[pattern_selection_loc];
1536 switch (channel_selection_loc) { 1585 switch (channel_selection_loc) {
1537 case 0: { 1586 case 0: {
1538 return &ch1.notes[trig_selection_loc]; 1587 return &pat->ch1.notes[trig_selection_loc];
1539 } break; 1588 } break;
1540 case 1: { 1589 case 1: {
1541 return &ch2.notes[trig_selection_loc]; 1590 return &pat->ch2.notes[trig_selection_loc];
1542 } break; 1591 } break;
1543 case 2: { 1592 case 2: {
1544 return &ch3.notes[trig_selection_loc]; 1593 return &pat->ch3.notes[trig_selection_loc];
1545 } break; 1594 } break;
1546 case 3: { 1595 case 3: {
1547 return &ch4.notes[trig_selection_loc]; 1596 return &pat->ch4.notes[trig_selection_loc];
1548 } break; 1597 } break;
1549 } 1598 }
1550 return NULL; 1599 return NULL;
@@ -1557,6 +1606,7 @@ void (*input_handler)(void);
1557 1606
1558void handle_trigger_selection(void); 1607void handle_trigger_selection(void);
1559void handle_channel_selection(void); 1608void handle_channel_selection(void);
1609void handle_pattern_selection(void);
1560void handle_param_selection_sq1(void); 1610void handle_param_selection_sq1(void);
1561void handle_param_selection_sq2(void); 1611void handle_param_selection_sq2(void);
1562void handle_param_selection_wave(void); 1612void handle_param_selection_wave(void);
@@ -1567,16 +1617,16 @@ handle_channel_selection(void) {
1567 if (key_tap(KEY_B)) { 1617 if (key_tap(KEY_B)) {
1568 switch (channel_selection_loc) { 1618 switch (channel_selection_loc) {
1569 case 0: { 1619 case 0: {
1570 ch1.active ^= 1; 1620 patterns[pattern_selection_loc].ch1.active ^= 1;
1571 } break; 1621 } break;
1572 case 1: { 1622 case 1: {
1573 ch2.active ^= 1; 1623 patterns[pattern_selection_loc].ch2.active ^= 1;
1574 } break; 1624 } break;
1575 case 2: { 1625 case 2: {
1576 ch3.active ^= 1; 1626 patterns[pattern_selection_loc].ch3.active ^= 1;
1577 } break; 1627 } break;
1578 case 3: { 1628 case 3: {
1579 ch4.active ^= 1; 1629 patterns[pattern_selection_loc].ch4.active ^= 1;
1580 } break; 1630 } break;
1581 } 1631 }
1582 draw_channels(); 1632 draw_channels();
@@ -1585,11 +1635,15 @@ handle_channel_selection(void) {
1585 trig_selection_loc = 0; 1635 trig_selection_loc = 0;
1586 param_selection_loc = 0; 1636 param_selection_loc = 0;
1587 input_handler = handle_trigger_selection; 1637 input_handler = handle_trigger_selection;
1588 draw_channel_cursor(channel_selection_loc, COL_CURRENT_CHANNEL); 1638 draw_channel_cursor(channel_selection_loc, COL_GREY);
1589 draw_trig_cursor(trig_selection_loc, COL_CURSOR); 1639 draw_trig_cursor(trig_selection_loc, COL_CURSOR);
1590 TriggerNote *trig = get_current_trig(); 1640 TriggerNote *trig = get_current_trig();
1591 draw_note(trig->note, COL_NOTE_PRESSED); 1641 draw_note(trig->note, COL_NOTE_PRESSED);
1592 draw_parameters(); 1642 draw_parameters();
1643 } else if (key_tap(KEY_LEFT)) {
1644 input_handler = handle_pattern_selection;
1645 draw_channel_cursor(channel_selection_loc, COL_GREY);
1646 draw_pattern_cursor(pattern_selection_loc, COL_CURSOR);
1593 } else if (key_tap(KEY_UP)) { 1647 } else if (key_tap(KEY_UP)) {
1594 draw_channel_cursor(channel_selection_loc, COL_BG); 1648 draw_channel_cursor(channel_selection_loc, COL_BG);
1595 if (channel_selection_loc == 0) { 1649 if (channel_selection_loc == 0) {
@@ -1612,6 +1666,33 @@ handle_channel_selection(void) {
1612} 1666}
1613 1667
1614void 1668void
1669handle_pattern_selection(void) {
1670 if (key_tap(KEY_B)) {
1671 next_pattern = pattern_selection_loc;
1672 draw_pattern_buttons();
1673 }
1674 if (key_tap(KEY_RIGHT)) {
1675 input_handler = handle_channel_selection;
1676 draw_channel_cursor(channel_selection_loc, COL_CURSOR);
1677 draw_pattern_cursor(pattern_selection_loc, COL_GREY);
1678 } else if (key_tap(KEY_UP)) {
1679 if (pattern_selection_loc > 0) {
1680 draw_pattern_cursor(pattern_selection_loc, COL_BG);
1681 pattern_selection_loc = pattern_selection_loc - 1;
1682 draw_pattern_cursor(pattern_selection_loc, COL_CURSOR);
1683 draw_triggers();
1684 }
1685 } else if (key_tap(KEY_DOWN)) {
1686 if (pattern_selection_loc < 7) {
1687 draw_pattern_cursor(pattern_selection_loc, COL_BG);
1688 pattern_selection_loc = pattern_selection_loc + 1;
1689 draw_pattern_cursor(pattern_selection_loc, COL_CURSOR);
1690 draw_triggers();
1691 }
1692 }
1693}
1694
1695void
1615handle_param_selection_sq1(void) { 1696handle_param_selection_sq1(void) {
1616 // Go back to trigger selection. 1697 // Go back to trigger selection.
1617 if (key_tap(KEY_A)) { 1698 if (key_tap(KEY_A)) {
@@ -1674,7 +1755,8 @@ handle_param_selection_sq1(void) {
1674 } else { 1755 } else {
1675 inc = 1; 1756 inc = 1;
1676 } 1757 }
1677 ChannelSquareParams *params = &ch1.params[trig_selection_loc]; 1758 Pattern *pat = &patterns[pattern_selection_loc];
1759 ChannelSquareParams *params = &pat->ch1.params[trig_selection_loc];
1678 switch (param_selection_loc) { 1760 switch (param_selection_loc) {
1679 case 0: { 1761 case 0: {
1680 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3); 1762 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3);
@@ -1734,7 +1816,8 @@ handle_param_selection_sq2(void) {
1734 } else { 1816 } else {
1735 inc = 1; 1817 inc = 1;
1736 } 1818 }
1737 ChannelSquareParams *params = &ch2.params[trig_selection_loc]; 1819 Pattern *pat = &patterns[pattern_selection_loc];
1820 ChannelSquareParams *params = &pat->ch2.params[trig_selection_loc];
1738 switch (param_selection_loc) { 1821 switch (param_selection_loc) {
1739 case 0: { 1822 case 0: {
1740 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3); 1823 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3);
@@ -1756,6 +1839,8 @@ handle_param_selection_sq2(void) {
1756 1839
1757void 1840void
1758handle_param_selection_wave(void) { 1841handle_param_selection_wave(void) {
1842 Pattern *pat = &patterns[pattern_selection_loc];
1843
1759 // Go back to trigger selection. 1844 // Go back to trigger selection.
1760 if (key_tap(KEY_A)) { 1845 if (key_tap(KEY_A)) {
1761 draw_params_cursor(param_selection_loc, COL_BG); 1846 draw_params_cursor(param_selection_loc, COL_BG);
@@ -1864,7 +1949,7 @@ handle_param_selection_wave(void) {
1864 if (param_selection_loc < 32) { 1949 if (param_selection_loc < 32) {
1865 // Draw on wave a. 1950 // Draw on wave a.
1866 u8 byte_number = param_selection_loc / 2; 1951 u8 byte_number = param_selection_loc / 2;
1867 u8 *byte = &ch3.params[trig_selection_loc].wave_a; 1952 u8 *byte = &pat->ch3.params[trig_selection_loc].wave_a;
1868 byte += byte_number; 1953 byte += byte_number;
1869 if (odd) { 1954 if (odd) {
1870 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF); 1955 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF);
@@ -1874,7 +1959,7 @@ handle_param_selection_wave(void) {
1874 } else if (param_selection_loc < 64){ 1959 } else if (param_selection_loc < 64){
1875 // Draw on wave b. 1960 // Draw on wave b.
1876 u8 byte_number = (param_selection_loc - 32) / 2; 1961 u8 byte_number = (param_selection_loc - 32) / 2;
1877 u8 *byte = &ch3.params[trig_selection_loc].wave_b; 1962 u8 *byte = &pat->ch3.params[trig_selection_loc].wave_b;
1878 byte += byte_number; 1963 byte += byte_number;
1879 if (odd) { 1964 if (odd) {
1880 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF); 1965 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF);
@@ -1883,8 +1968,8 @@ handle_param_selection_wave(void) {
1883 } 1968 }
1884 } else if (param_selection_loc < 72) { 1969 } else if (param_selection_loc < 72) {
1885 // Copy default waves. 1970 // Copy default waves.
1886 u32 *wave_a = &ch3.params[trig_selection_loc].wave_a; 1971 u32 *wave_a = &pat->ch3.params[trig_selection_loc].wave_a;
1887 u32 *wave_b = &ch3.params[trig_selection_loc].wave_b; 1972 u32 *wave_b = &pat->ch3.params[trig_selection_loc].wave_b;
1888 switch (param_selection_loc) { 1973 switch (param_selection_loc) {
1889 case 64: { 1974 case 64: {
1890 memcpy32(wave_a, sine_wave, 16); 1975 memcpy32(wave_a, sine_wave, 16);
@@ -1918,10 +2003,10 @@ handle_param_selection_wave(void) {
1918 } break; 2003 } break;
1919 } 2004 }
1920 } else if (param_selection_loc == 72) { 2005 } else if (param_selection_loc == 72) {
1921 u8 *wave_mode = &ch3.params[trig_selection_loc].wave_mode; 2006 u8 *wave_mode = &pat->ch3.params[trig_selection_loc].wave_mode;
1922 *wave_mode = CLAMP(*wave_mode + inc, 0, 2); 2007 *wave_mode = CLAMP(*wave_mode + inc, 0, 2);
1923 } else if (param_selection_loc == 73) { 2008 } else if (param_selection_loc == 73) {
1924 u8 *wave_volume = &ch3.params[trig_selection_loc].wave_volume; 2009 u8 *wave_volume = &pat->ch3.params[trig_selection_loc].wave_volume;
1925 *wave_volume = CLAMP(*wave_volume + inc, 0, 4); 2010 *wave_volume = CLAMP(*wave_volume + inc, 0, 4);
1926 } 2011 }
1927 draw_parameters(); 2012 draw_parameters();
@@ -2185,7 +2270,7 @@ handle_trigger_selection(void) {
2185 } break; 2270 } break;
2186 } 2271 }
2187 draw_params_cursor(param_selection_loc, COL_CURSOR); 2272 draw_params_cursor(param_selection_loc, COL_CURSOR);
2188 draw_trig_cursor(trig_selection_loc, COL_CURRENT_TRIG); 2273 draw_trig_cursor(trig_selection_loc, COL_GREY);
2189 } 2274 }
2190} 2275}
2191 2276
@@ -2202,7 +2287,7 @@ handle_sequencer_input(void) {
2202 } 2287 }
2203 step_counter = 0; 2288 step_counter = 0;
2204 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) { 2289 if ((TIMER_CTRL_0 & TIMER_CTRL_ENABLE) == 0) {
2205 set_time(bpm); 2290 set_time(patterns[current_pattern].bpm);
2206 } else { 2291 } else {
2207 draw_current_step(COL_RED); 2292 draw_current_step(COL_RED);
2208 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE; 2293 TIMER_CTRL_0 ^= TIMER_CTRL_ENABLE;
@@ -2249,12 +2334,14 @@ sequencer_init(void) {
2249 // Initialize input handler. 2334 // Initialize input handler.
2250 input_handler = handle_trigger_selection; 2335 input_handler = handle_trigger_selection;
2251 draw_trig_cursor(trig_selection_loc, COL_CURSOR); 2336 draw_trig_cursor(trig_selection_loc, COL_CURSOR);
2252 draw_channel_cursor(channel_selection_loc, COL_CURRENT_CHANNEL); 2337 draw_channel_cursor(channel_selection_loc, COL_GREY);
2338 draw_pattern_cursor(pattern_selection_loc, COL_GREY);
2253 draw_current_step(COL_RED); 2339 draw_current_step(COL_RED);
2254 draw_parameters(); 2340 draw_parameters();
2255 draw_bpm(); 2341 draw_bpm();
2256 draw_play(); 2342 draw_play();
2257 draw_stop(); 2343 draw_stop();
2344 draw_pattern_buttons();
2258 2345
2259 // Initialize sound system. 2346 // Initialize sound system.
2260 SOUND_STATUS = SOUND_ENABLE; 2347 SOUND_STATUS = SOUND_ENABLE;