aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-04-24 14:49:38 +0200
committerBad Diode <bd@badd10de.dev>2023-04-24 14:49:38 +0200
commit7399fd06ad3e9682a619550c6de50a565ccc3a25 (patch)
tree23a36f4c00e4ac0a3b5154ad62067912d79309d3
parentb83958d07ec0e4dcc185f40928a84d1bcdd48675 (diff)
downloadstepper-7399fd06ad3e9682a619550c6de50a565ccc3a25.tar.gz
stepper-7399fd06ad3e9682a619550c6de50a565ccc3a25.zip
Prepare for per-channel param adjustment
-rw-r--r--Makefile2
-rw-r--r--src/drawing.c454
-rw-r--r--src/globals.c8
-rw-r--r--src/patterns.c6
-rw-r--r--src/sequencer.c104
5 files changed, 215 insertions, 359 deletions
diff --git a/Makefile b/Makefile
index cb49812..02ee360 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ INC_FLAGS := $(addprefix -I,$(INC_DIRS))
27INC_FLAGS += -I$(LIBGBA_SRC) 27INC_FLAGS += -I$(LIBGBA_SRC)
28 28
29# Output library names and executables. 29# Output library names and executables.
30TARGET := STEPPER-v1.2 30TARGET := STEPPER-v1.3-dev
31ELF := $(BUILD_DIR)/$(TARGET).elf 31ELF := $(BUILD_DIR)/$(TARGET).elf
32BIN := $(BUILD_DIR)/$(TARGET).gba 32BIN := $(BUILD_DIR)/$(TARGET).gba
33 33
diff --git a/src/drawing.c b/src/drawing.c
index 964c4ce..0ee1243 100644
--- a/src/drawing.c
+++ b/src/drawing.c
@@ -14,18 +14,10 @@ draw_channels(void) {
14 for (size_t i = 0; i < 4; i++) { 14 for (size_t i = 0; i < 4; i++) {
15 bool active = false; 15 bool active = false;
16 switch (i) { 16 switch (i) {
17 case 0: { 17 case 0: { active = patterns[pattern_selection_loc].ch1.active; } break;
18 active = patterns[pattern_selection_loc].ch1.active; 18 case 1: { active = patterns[pattern_selection_loc].ch2.active; } break;
19 } break; 19 case 2: { active = patterns[pattern_selection_loc].ch3.active; } break;
20 case 1: { 20 case 3: { active = patterns[pattern_selection_loc].ch4.active; } break;
21 active = patterns[pattern_selection_loc].ch2.active;
22 } break;
23 case 2: {
24 active = patterns[pattern_selection_loc].ch3.active;
25 } break;
26 case 3: {
27 active = patterns[pattern_selection_loc].ch4.active;
28 } break;
29 } 21 }
30 u8 clr = active ? COL_FG : COL_GREY; 22 u8 clr = active ? COL_FG : COL_GREY;
31 size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; 23 size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y;
@@ -62,18 +54,10 @@ void
62draw_trigger(size_t chan, size_t i) { 54draw_trigger(size_t chan, size_t i) {
63 TriggerNote trig = {0}; 55 TriggerNote trig = {0};
64 switch (chan) { 56 switch (chan) {
65 case 0: { 57 case 0: { trig = patterns[pattern_selection_loc].ch1.notes[i]; } break;
66 trig = patterns[pattern_selection_loc].ch1.notes[i]; 58 case 1: { trig = patterns[pattern_selection_loc].ch2.notes[i]; } break;
67 } break; 59 case 2: { trig = patterns[pattern_selection_loc].ch3.notes[i]; } break;
68 case 1: { 60 case 3: { trig = patterns[pattern_selection_loc].ch4.notes[i]; } break;
69 trig = patterns[pattern_selection_loc].ch2.notes[i];
70 } break;
71 case 2: {
72 trig = patterns[pattern_selection_loc].ch3.notes[i];
73 } break;
74 case 3: {
75 trig = patterns[pattern_selection_loc].ch4.notes[i];
76 } break;
77 } 61 }
78 if (trig.active) { 62 if (trig.active) {
79 size_t offset_x = TRIG_OFFSET_X * (i % 8); 63 size_t offset_x = TRIG_OFFSET_X * (i % 8);
@@ -373,21 +357,11 @@ draw_note(u8 note, u8 clr) {
373 y0 = PIANO_START_Y + 2; 357 y0 = PIANO_START_Y + 2;
374 y1 = PIANO_START_Y - 2 + 11; 358 y1 = PIANO_START_Y - 2 + 11;
375 switch (value) { 359 switch (value) {
376 case 1: { 360 case 1: { x0 = PIANO_START_X + 2 + octave * 28 + 3; } break;
377 x0 = PIANO_START_X + 2 + octave * 28 + 3; 361 case 3: { x0 = PIANO_START_X + 2 + octave * 28 + 7; } break;
378 } break; 362 case 6: { x0 = PIANO_START_X + 2 + octave * 28 + 15; } break;
379 case 3: { 363 case 8: { x0 = PIANO_START_X + 2 + octave * 28 + 19; } break;
380 x0 = PIANO_START_X + 2 + octave * 28 + 7; 364 case 10: { x0 = PIANO_START_X + 2 + octave * 28 + 23; } break;
381 } break;
382 case 6: {
383 x0 = PIANO_START_X + 2 + octave * 28 + 15;
384 } break;
385 case 8: {
386 x0 = PIANO_START_X + 2 + octave * 28 + 19;
387 } break;
388 case 10: {
389 x0 = PIANO_START_X + 2 + octave * 28 + 23;
390 } break;
391 } 365 }
392 x1 = x0; 366 x1 = x0;
393 draw_line(x0, y0, x1, y1, clr); 367 draw_line(x0, y0, x1, y1, clr);
@@ -512,18 +486,10 @@ draw_params_cursor_square(size_t i, u8 clr, bool sweep) {
512void 486void
513draw_params_cursor(size_t i, u8 clr) { 487draw_params_cursor(size_t i, u8 clr) {
514 switch (channel_selection_loc) { 488 switch (channel_selection_loc) {
515 case 0: { 489 case 0: { draw_params_cursor_square(i, clr, true); } break;
516 draw_params_cursor_square(i, clr, true); 490 case 1: { draw_params_cursor_square(i, clr, false); } break;
517 } break; 491 case 2: { draw_params_cursor_wave(i, clr); } break;
518 case 1: { 492 case 3: { draw_params_cursor_noise(i, clr); } break;
519 draw_params_cursor_square(i, clr, false);
520 } break;
521 case 2: {
522 draw_params_cursor_wave(i, clr);
523 } break;
524 case 3: {
525 draw_params_cursor_noise(i, clr);
526 } break;
527 } 493 }
528} 494}
529 495
@@ -555,12 +521,11 @@ clear_parameters(void) {
555 521
556IWRAM_CODE 522IWRAM_CODE
557void 523void
558draw_parameters_wave(void) { 524draw_parameters_wave(ChannelWaveParams *params) {
559 // Draw current wave data. 525 // Draw current wave data.
560 Pattern *pat = &patterns[pattern_selection_loc];
561 { 526 {
562 u8 *wave_a = pat->ch3.params[trig_selection_loc].wave_a; 527 u8 *wave_a = params->wave_a;
563 u8 *wave_b = pat->ch3.params[trig_selection_loc].wave_b; 528 u8 *wave_b = params->wave_b;
564 529
565 size_t x = PARAMS_START_X; 530 size_t x = PARAMS_START_X;
566 size_t y = PARAMS_START_Y + 13; 531 size_t y = PARAMS_START_Y + 13;
@@ -617,16 +582,10 @@ draw_parameters_wave(void) {
617 draw_line(x, y + 17, x + 30, y + 17, COL_FG); 582 draw_line(x, y + 17, x + 30, y + 17, COL_FG);
618 txt_drawf_small("mode", x + 6, y, COL_FG); 583 txt_drawf_small("mode", x + 6, y, COL_FG);
619 584
620 switch (pat->ch3.params[trig_selection_loc].wave_mode) { 585 switch (params->wave_mode) {
621 case 0: { 586 case 0: { txt_drawf("A", x + 12, y + 7, COL_FG); } break;
622 txt_drawf("A", x + 12, y + 7, COL_FG); 587 case 1: { txt_drawf("B", x + 12, y + 7, COL_FG); } break;
623 } break; 588 case 2: { txt_drawf("A+B", x + 6, y + 7, COL_FG); } break;
624 case 1: {
625 txt_drawf("B", x + 12, y + 7, COL_FG);
626 } break;
627 case 2: {
628 txt_drawf("A+B", x + 6, y + 7, COL_FG);
629 } break;
630 } 589 }
631 } 590 }
632 591
@@ -641,22 +600,12 @@ draw_parameters_wave(void) {
641 draw_line(x, y + 20, x + 30, y + 20, COL_FG); 600 draw_line(x, y + 20, x + 30, y + 20, COL_FG);
642 txt_drawf_small("vol", x + 8, y + 3, COL_FG); 601 txt_drawf_small("vol", x + 8, y + 3, COL_FG);
643 602
644 switch (pat->ch3.params[trig_selection_loc].wave_volume) { 603 switch (params->wave_volume) {
645 case 0: { 604 case 0: { txt_drawf("0", x + 12, y + 10, COL_FG); } break;
646 txt_drawf("0", x + 12, y + 10, COL_FG); 605 case 1: { txt_drawf("25", x + 9, y + 10, COL_FG); } break;
647 } break; 606 case 2: { txt_drawf("50", x + 9, y + 10, COL_FG); } break;
648 case 1: { 607 case 3: { txt_drawf("75", x + 9, y + 10, COL_FG); } break;
649 txt_drawf("25", x + 9, y + 10, COL_FG); 608 case 4: { txt_drawf("100", x + 6, y + 10, COL_FG); } break;
650 } break;
651 case 2: {
652 txt_drawf("50", x + 9, y + 10, COL_FG);
653 } break;
654 case 3: {
655 txt_drawf("75", x + 9, y + 10, COL_FG);
656 } break;
657 case 4: {
658 txt_drawf("100", x + 6, y + 10, COL_FG);
659 } break;
660 } 609 }
661 } 610 }
662} 611}
@@ -737,18 +686,10 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
737 txt_drawf_small("duty", x + 3, y + 3, COL_FG); 686 txt_drawf_small("duty", x + 3, y + 3, COL_FG);
738 687
739 switch (params->duty_cycle) { 688 switch (params->duty_cycle) {
740 case 0: { 689 case 0: { txt_drawf("12", x + 6, y + 10, COL_FG); } break;
741 txt_drawf("12", x + 6, y + 10, COL_FG); 690 case 1: { txt_drawf("25", x + 6, y + 10, COL_FG); } break;
742 } break; 691 case 2: { txt_drawf("50", x + 6, y + 10, COL_FG); } break;
743 case 1: { 692 case 3: { txt_drawf("75", x + 6, y + 10, COL_FG); } break;
744 txt_drawf("25", x + 6, y + 10, COL_FG);
745 } break;
746 case 2: {
747 txt_drawf("50", x + 6, y + 10, COL_FG);
748 } break;
749 case 3: {
750 txt_drawf("75", x + 6, y + 10, COL_FG);
751 } break;
752 } 693 }
753 } 694 }
754 } 695 }
@@ -796,54 +737,22 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
796 txt_drawf_small("vol", x + 5, y + 3, COL_FG); 737 txt_drawf_small("vol", x + 5, y + 3, COL_FG);
797 738
798 switch (params->env_volume) { 739 switch (params->env_volume) {
799 case 0: { 740 case 0: { txt_drawf("0", x + 9, y + 10, COL_FG); } break;
800 txt_drawf("0", x + 9, y + 10, COL_FG); 741 case 1: { txt_drawf("6", x + 9, y + 10, COL_FG); } break;
801 } break; 742 case 2: { txt_drawf("13", x + 6, y + 10, COL_FG); } break;
802 case 1: { 743 case 3: { txt_drawf("20", x + 6, y + 10, COL_FG); } break;
803 txt_drawf("6", x + 9, y + 10, COL_FG); 744 case 4: { txt_drawf("26", x + 6, y + 10, COL_FG); } break;
804 } break; 745 case 5: { txt_drawf("33", x + 6, y + 10, COL_FG); } break;
805 case 2: { 746 case 6: { txt_drawf("40", x + 6, y + 10, COL_FG); } break;
806 txt_drawf("13", x + 6, y + 10, COL_FG); 747 case 7: { txt_drawf("46", x + 6, y + 10, COL_FG); } break;
807 } break; 748 case 8: { txt_drawf("53", x + 6, y + 10, COL_FG); } break;
808 case 3: { 749 case 9: { txt_drawf("60", x + 6, y + 10, COL_FG); } break;
809 txt_drawf("20", x + 6, y + 10, COL_FG); 750 case 10: { txt_drawf("66", x + 6, y + 10, COL_FG); } break;
810 } break; 751 case 11: { txt_drawf("73", x + 6, y + 10, COL_FG); } break;
811 case 4: { 752 case 12: { txt_drawf("80", x + 6, y + 10, COL_FG); } break;
812 txt_drawf("26", x + 6, y + 10, COL_FG); 753 case 13: { txt_drawf("86", x + 6, y + 10, COL_FG); } break;
813 } break; 754 case 14: { txt_drawf("93", x + 6, y + 10, COL_FG); } break;
814 case 5: { 755 case 15: { txt_drawf("100", x + 3, y + 10, COL_FG); } break;
815 txt_drawf("33", x + 6, y + 10, COL_FG);
816 } break;
817 case 6: {
818 txt_drawf("40", x + 6, y + 10, COL_FG);
819 } break;
820 case 7: {
821 txt_drawf("46", x + 6, y + 10, COL_FG);
822 } break;
823 case 8: {
824 txt_drawf("53", x + 6, y + 10, COL_FG);
825 } break;
826 case 9: {
827 txt_drawf("60", x + 6, y + 10, COL_FG);
828 } break;
829 case 10: {
830 txt_drawf("66", x + 6, y + 10, COL_FG);
831 } break;
832 case 11: {
833 txt_drawf("73", x + 6, y + 10, COL_FG);
834 } break;
835 case 12: {
836 txt_drawf("80", x + 6, y + 10, COL_FG);
837 } break;
838 case 13: {
839 txt_drawf("86", x + 6, y + 10, COL_FG);
840 } break;
841 case 14: {
842 txt_drawf("93", x + 6, y + 10, COL_FG);
843 } break;
844 case 15: {
845 txt_drawf("100", x + 3, y + 10, COL_FG);
846 } break;
847 } 756 }
848 } 757 }
849 758
@@ -861,12 +770,8 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
861 char arr_up[2] = { 0x19, 0 }; 770 char arr_up[2] = { 0x19, 0 };
862 char arr_down[2] = { 0x18, 0 }; 771 char arr_down[2] = { 0x18, 0 };
863 switch (params->env_direction) { 772 switch (params->env_direction) {
864 case 0: { 773 case 0: { txt_drawf(arr_up, x + 9, y + 11, COL_FG); } break;
865 txt_drawf(arr_up, x + 9, y + 11, COL_FG); 774 case 1: { txt_drawf(arr_down, x + 9, y + 11, COL_FG); } break;
866 } break;
867 case 1: {
868 txt_drawf(arr_down, x + 9, y + 11, COL_FG);
869 } break;
870 } 775 }
871 } 776 }
872 777
@@ -882,30 +787,14 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
882 txt_drawf_small("time", x + 3, y + 3, COL_FG); 787 txt_drawf_small("time", x + 3, y + 3, COL_FG);
883 788
884 switch (params->env_time) { 789 switch (params->env_time) {
885 case 0: { 790 case 0: { txt_drawf("0", x + 9, y + 10, COL_FG); } break;
886 txt_drawf("0", x + 9, y + 10, COL_FG); 791 case 1: { txt_drawf("14", x + 6, y + 10, COL_FG); } break;
887 } break; 792 case 2: { txt_drawf("28", x + 6, y + 10, COL_FG); } break;
888 case 1: { 793 case 3: { txt_drawf("42", x + 6, y + 10, COL_FG); } break;
889 txt_drawf("14", x + 6, y + 10, COL_FG); 794 case 4: { txt_drawf("57", x + 6, y + 10, COL_FG); } break;
890 } break; 795 case 5: { txt_drawf("71", x + 6, y + 10, COL_FG); } break;
891 case 2: { 796 case 6: { txt_drawf("85", x + 6, y + 10, COL_FG); } break;
892 txt_drawf("28", x + 6, y + 10, COL_FG); 797 case 7: { txt_drawf("100", x + 3, y + 10, COL_FG); } break;
893 } break;
894 case 3: {
895 txt_drawf("42", x + 6, y + 10, COL_FG);
896 } break;
897 case 4: {
898 txt_drawf("57", x + 6, y + 10, COL_FG);
899 } break;
900 case 5: {
901 txt_drawf("71", x + 6, y + 10, COL_FG);
902 } break;
903 case 6: {
904 txt_drawf("85", x + 6, y + 10, COL_FG);
905 } break;
906 case 7: {
907 txt_drawf("100", x + 3, y + 10, COL_FG);
908 } break;
909 } 798 }
910 } 799 }
911 } 800 }
@@ -922,30 +811,14 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
922 txt_drawf_small("num", x + 5, y + 3, COL_FG); 811 txt_drawf_small("num", x + 5, y + 3, COL_FG);
923 812
924 switch (params->sweep_number) { 813 switch (params->sweep_number) {
925 case 0: { 814 case 0: { txt_drawf("0", x + 9, y + 10, COL_FG); } break;
926 txt_drawf("0", x + 9, y + 10, COL_FG); 815 case 1: { txt_drawf("1", x + 9, y + 10, COL_FG); } break;
927 } break; 816 case 2: { txt_drawf("2", x + 9, y + 10, COL_FG); } break;
928 case 1: { 817 case 3: { txt_drawf("3", x + 9, y + 10, COL_FG); } break;
929 txt_drawf("1", x + 9, y + 10, COL_FG); 818 case 4: { txt_drawf("4", x + 9, y + 10, COL_FG); } break;
930 } break; 819 case 5: { txt_drawf("5", x + 9, y + 10, COL_FG); } break;
931 case 2: { 820 case 6: { txt_drawf("6", x + 9, y + 10, COL_FG); } break;
932 txt_drawf("2", x + 9, y + 10, COL_FG); 821 case 7: { txt_drawf("7", x + 9, y + 10, COL_FG); } break;
933 } break;
934 case 3: {
935 txt_drawf("3", x + 9, y + 10, COL_FG);
936 } break;
937 case 4: {
938 txt_drawf("4", x + 9, y + 10, COL_FG);
939 } break;
940 case 5: {
941 txt_drawf("5", x + 9, y + 10, COL_FG);
942 } break;
943 case 6: {
944 txt_drawf("6", x + 9, y + 10, COL_FG);
945 } break;
946 case 7: {
947 txt_drawf("7", x + 9, y + 10, COL_FG);
948 } break;
949 } 822 }
950 } 823 }
951 824
@@ -961,30 +834,14 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
961 txt_drawf_small("time", x + 3, y + 3, COL_FG); 834 txt_drawf_small("time", x + 3, y + 3, COL_FG);
962 835
963 switch (params->sweep_time) { 836 switch (params->sweep_time) {
964 case 0: { 837 case 0: { txt_drawf("0", x + 9, y + 10, COL_FG); } break;
965 txt_drawf("0", x + 9, y + 10, COL_FG); 838 case 1: { txt_drawf("1", x + 9, y + 10, COL_FG); } break;
966 } break; 839 case 2: { txt_drawf("2", x + 9, y + 10, COL_FG); } break;
967 case 1: { 840 case 3: { txt_drawf("3", x + 9, y + 10, COL_FG); } break;
968 txt_drawf("1", x + 9, y + 10, COL_FG); 841 case 4: { txt_drawf("4", x + 9, y + 10, COL_FG); } break;
969 } break; 842 case 5: { txt_drawf("5", x + 9, y + 10, COL_FG); } break;
970 case 2: { 843 case 6: { txt_drawf("6", x + 9, y + 10, COL_FG); } break;
971 txt_drawf("2", x + 9, y + 10, COL_FG); 844 case 7: { txt_drawf("7", x + 9, y + 10, COL_FG); } break;
972 } break;
973 case 3: {
974 txt_drawf("3", x + 9, y + 10, COL_FG);
975 } break;
976 case 4: {
977 txt_drawf("4", x + 9, y + 10, COL_FG);
978 } break;
979 case 5: {
980 txt_drawf("5", x + 9, y + 10, COL_FG);
981 } break;
982 case 6: {
983 txt_drawf("6", x + 9, y + 10, COL_FG);
984 } break;
985 case 7: {
986 txt_drawf("7", x + 9, y + 10, COL_FG);
987 } break;
988 } 845 }
989 } 846 }
990 847
@@ -1002,12 +859,8 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
1002 char arr_up[2] = { 0x19, 0 }; 859 char arr_up[2] = { 0x19, 0 };
1003 char arr_down[2] = { 0x18, 0 }; 860 char arr_down[2] = { 0x18, 0 };
1004 switch (params->sweep_direction) { 861 switch (params->sweep_direction) {
1005 case 0: { 862 case 0: { txt_drawf(arr_up, x + 9, y + 11, COL_FG); } break;
1006 txt_drawf(arr_up, x + 9, y + 11, COL_FG); 863 case 1: { txt_drawf(arr_down, x + 9, y + 11, COL_FG); } break;
1007 } break;
1008 case 1: {
1009 txt_drawf(arr_down, x + 9, y + 11, COL_FG);
1010 } break;
1011 } 864 }
1012 } 865 }
1013 866
@@ -1024,10 +877,8 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) {
1024} 877}
1025 878
1026void 879void
1027draw_parameters_noise(void) { 880draw_parameters_noise(ChannelNoiseParams* params) {
1028 size_t x_offset = 30; 881 size_t x_offset = 30;
1029 Pattern *pat = &patterns[pattern_selection_loc];
1030 ChannelNoiseParams *params = &pat->ch4.params[trig_selection_loc];
1031 882
1032 // Bit mode. 883 // Bit mode.
1033 { 884 {
@@ -1043,12 +894,8 @@ draw_parameters_noise(void) {
1043 txt_drawf_small("mode", x + 3, y + 3, COL_FG); 894 txt_drawf_small("mode", x + 3, y + 3, COL_FG);
1044 895
1045 switch (params->bit_mode) { 896 switch (params->bit_mode) {
1046 case 0: { 897 case 0: { txt_drawf("A", x + 9, y + 10, COL_FG); } break;
1047 txt_drawf("A", x + 9, y + 10, COL_FG); 898 case 1: { txt_drawf("B", x + 9, y + 10, COL_FG); } break;
1048 } break;
1049 case 1: {
1050 txt_drawf("B", x + 9, y + 10, COL_FG);
1051 } break;
1052 } 899 }
1053 } 900 }
1054 } 901 }
@@ -1096,54 +943,22 @@ draw_parameters_noise(void) {
1096 txt_drawf_small("vol", x + 5, y + 3, COL_FG); 943 txt_drawf_small("vol", x + 5, y + 3, COL_FG);
1097 944
1098 switch (params->env_volume) { 945 switch (params->env_volume) {
1099 case 0: { 946 case 0: { txt_drawf("0", x + 9, y + 10, COL_FG); } break;
1100 txt_drawf("0", x + 9, y + 10, COL_FG); 947 case 1: { txt_drawf("6", x + 9, y + 10, COL_FG); } break;
1101 } break; 948 case 2: { txt_drawf("13", x + 6, y + 10, COL_FG); } break;
1102 case 1: { 949 case 3: { txt_drawf("20", x + 6, y + 10, COL_FG); } break;
1103 txt_drawf("6", x + 9, y + 10, COL_FG); 950 case 4: { txt_drawf("26", x + 6, y + 10, COL_FG); } break;
1104 } break; 951 case 5: { txt_drawf("33", x + 6, y + 10, COL_FG); } break;
1105 case 2: { 952 case 6: { txt_drawf("40", x + 6, y + 10, COL_FG); } break;
1106 txt_drawf("13", x + 6, y + 10, COL_FG); 953 case 7: { txt_drawf("46", x + 6, y + 10, COL_FG); } break;
1107 } break; 954 case 8: { txt_drawf("53", x + 6, y + 10, COL_FG); } break;
1108 case 3: { 955 case 9: { txt_drawf("60", x + 6, y + 10, COL_FG); } break;
1109 txt_drawf("20", x + 6, y + 10, COL_FG); 956 case 10: { txt_drawf("66", x + 6, y + 10, COL_FG); } break;
1110 } break; 957 case 11: { txt_drawf("73", x + 6, y + 10, COL_FG); } break;
1111 case 4: { 958 case 12: { txt_drawf("80", x + 6, y + 10, COL_FG); } break;
1112 txt_drawf("26", x + 6, y + 10, COL_FG); 959 case 13: { txt_drawf("86", x + 6, y + 10, COL_FG); } break;
1113 } break; 960 case 14: { txt_drawf("93", x + 6, y + 10, COL_FG); } break;
1114 case 5: { 961 case 15: { txt_drawf("100", x + 3, y + 10, COL_FG); } break;
1115 txt_drawf("33", x + 6, y + 10, COL_FG);
1116 } break;
1117 case 6: {
1118 txt_drawf("40", x + 6, y + 10, COL_FG);
1119 } break;
1120 case 7: {
1121 txt_drawf("46", x + 6, y + 10, COL_FG);
1122 } break;
1123 case 8: {
1124 txt_drawf("53", x + 6, y + 10, COL_FG);
1125 } break;
1126 case 9: {
1127 txt_drawf("60", x + 6, y + 10, COL_FG);
1128 } break;
1129 case 10: {
1130 txt_drawf("66", x + 6, y + 10, COL_FG);
1131 } break;
1132 case 11: {
1133 txt_drawf("73", x + 6, y + 10, COL_FG);
1134 } break;
1135 case 12: {
1136 txt_drawf("80", x + 6, y + 10, COL_FG);
1137 } break;
1138 case 13: {
1139 txt_drawf("86", x + 6, y + 10, COL_FG);
1140 } break;
1141 case 14: {
1142 txt_drawf("93", x + 6, y + 10, COL_FG);
1143 } break;
1144 case 15: {
1145 txt_drawf("100", x + 3, y + 10, COL_FG);
1146 } break;
1147 } 962 }
1148 } 963 }
1149 964
@@ -1182,30 +997,14 @@ draw_parameters_noise(void) {
1182 txt_drawf_small("time", x + 3, y + 3, COL_FG); 997 txt_drawf_small("time", x + 3, y + 3, COL_FG);
1183 998
1184 switch (params->env_time) { 999 switch (params->env_time) {
1185 case 0: { 1000 case 0: { txt_drawf("0", x + 9, y + 10, COL_FG); } break;
1186 txt_drawf("0", x + 9, y + 10, COL_FG); 1001 case 1: { txt_drawf("14", x + 6, y + 10, COL_FG); } break;
1187 } break; 1002 case 2: { txt_drawf("28", x + 6, y + 10, COL_FG); } break;
1188 case 1: { 1003 case 3: { txt_drawf("42", x + 6, y + 10, COL_FG); } break;
1189 txt_drawf("14", x + 6, y + 10, COL_FG); 1004 case 4: { txt_drawf("57", x + 6, y + 10, COL_FG); } break;
1190 } break; 1005 case 5: { txt_drawf("71", x + 6, y + 10, COL_FG); } break;
1191 case 2: { 1006 case 6: { txt_drawf("85", x + 6, y + 10, COL_FG); } break;
1192 txt_drawf("28", x + 6, y + 10, COL_FG); 1007 case 7: { txt_drawf("100", x + 3, y + 10, COL_FG); } break;
1193 } break;
1194 case 3: {
1195 txt_drawf("42", x + 6, y + 10, COL_FG);
1196 } break;
1197 case 4: {
1198 txt_drawf("57", x + 6, y + 10, COL_FG);
1199 } break;
1200 case 5: {
1201 txt_drawf("71", x + 6, y + 10, COL_FG);
1202 } break;
1203 case 6: {
1204 txt_drawf("85", x + 6, y + 10, COL_FG);
1205 } break;
1206 case 7: {
1207 txt_drawf("100", x + 3, y + 10, COL_FG);
1208 } break;
1209 } 1008 }
1210 } 1009 }
1211 } 1010 }
@@ -1221,27 +1020,32 @@ draw_parameters_noise(void) {
1221void 1020void
1222draw_parameters(void) { 1021draw_parameters(void) {
1223 clear_parameters(); 1022 clear_parameters();
1224 if (input_handler != handle_trigger_selection && 1023 Pattern *pat = &patterns[pattern_selection_loc];
1225 input_handler != handle_param_selection_sq1 && 1024 if (input_handler == handle_trigger_selection ||
1226 input_handler != handle_param_selection_sq2 && 1025 input_handler == handle_param_selection_sq1 ||
1227 input_handler != handle_param_selection_wave && 1026 input_handler == handle_param_selection_sq2 ||
1228 input_handler != handle_param_selection_noise) { 1027 input_handler == handle_param_selection_wave ||
1028 input_handler == handle_param_selection_noise) {
1029 switch (channel_selection_loc) {
1030 case 0: { draw_parameters_square(&pat->ch1.params[trig_selection_loc], true); } break;
1031 case 1: { draw_parameters_square(&pat->ch2.params[trig_selection_loc], false); } break;
1032 case 2: { draw_parameters_wave(&pat->ch3.params[trig_selection_loc]); } break;
1033 case 3: { draw_parameters_noise(&pat->ch4.params[trig_selection_loc]); } break;
1034 }
1229 return; 1035 return;
1230 } 1036 }
1231 Pattern *pat = &patterns[pattern_selection_loc]; 1037 if (input_handler == handle_channel_selection ||
1232 switch (channel_selection_loc) { 1038 input_handler == handle_param_selection_ch1 ||
1233 case 0: { 1039 input_handler == handle_param_selection_ch2 ||
1234 draw_parameters_square(&pat->ch1.params[trig_selection_loc], true); 1040 input_handler == handle_param_selection_ch3 ||
1235 } break; 1041 input_handler == handle_param_selection_ch4) {
1236 case 1: { 1042 switch (channel_selection_loc) {
1237 draw_parameters_square(&pat->ch2.params[trig_selection_loc], false); 1043 case 0: { draw_parameters_square(&pat->ch1.params[16], true); } break;
1238 } break; 1044 case 1: { draw_parameters_square(&pat->ch2.params[16], false); } break;
1239 case 2: { 1045 case 2: { draw_parameters_wave(&pat->ch3.params[16]); } break;
1240 draw_parameters_wave(); 1046 case 3: { draw_parameters_noise(&pat->ch4.params[16]); } break;
1241 } break; 1047 }
1242 case 3: { 1048 return;
1243 draw_parameters_noise();
1244 } break;
1245 } 1049 }
1246} 1050}
1247 1051
diff --git a/src/globals.c b/src/globals.c
index 34e9bb5..8ce79d5 100644
--- a/src/globals.c
+++ b/src/globals.c
@@ -97,7 +97,9 @@ enum RIGHT_COL_LOC {
97// Input handling works using a FSM. The input handler is switched to whichever 97// Input handling works using a FSM. The input handler is switched to whichever
98// function controls each section. For example, channel selection or trigger 98// function controls each section. For example, channel selection or trigger
99// selection. 99// selection.
100void (*input_handler)(void); 100typedef void (*InputHandler)(void);
101
102InputHandler input_handler;
101 103
102void handle_trigger_selection(void); 104void handle_trigger_selection(void);
103void handle_channel_selection(void); 105void handle_channel_selection(void);
@@ -107,3 +109,7 @@ void handle_param_selection_sq2(void);
107void handle_param_selection_wave(void); 109void handle_param_selection_wave(void);
108void handle_param_selection_noise(void); 110void handle_param_selection_noise(void);
109void handle_right_col_selection(void); 111void handle_right_col_selection(void);
112void handle_param_selection_ch1(void);
113void handle_param_selection_ch2(void);
114void handle_param_selection_ch3(void);
115void handle_param_selection_ch4(void);
diff --git a/src/patterns.c b/src/patterns.c
index 09f7bae..dbd9c9f 100644
--- a/src/patterns.c
+++ b/src/patterns.c
@@ -34,19 +34,19 @@ typedef struct ChannelNoiseParams {
34typedef struct ChannelSquare { 34typedef struct ChannelSquare {
35 bool active; 35 bool active;
36 TriggerNote notes[16]; 36 TriggerNote notes[16];
37 ChannelSquareParams params[16]; 37 ChannelSquareParams params[17];
38} ChannelSquare; 38} ChannelSquare;
39 39
40typedef struct ChannelWave { 40typedef struct ChannelWave {
41 bool active; 41 bool active;
42 TriggerNote notes[16]; 42 TriggerNote notes[16];
43 ChannelWaveParams params[16]; 43 ChannelWaveParams params[17];
44} ChannelWave; 44} ChannelWave;
45 45
46typedef struct ChannelNoise { 46typedef struct ChannelNoise {
47 bool active; 47 bool active;
48 TriggerNote notes[16]; 48 TriggerNote notes[16];
49 ChannelNoiseParams params[16]; 49 ChannelNoiseParams params[17];
50} ChannelNoise; 50} ChannelNoise;
51 51
52typedef struct Pattern { 52typedef struct Pattern {
diff --git a/src/sequencer.c b/src/sequencer.c
index 8f2b183..1280f5f 100644
--- a/src/sequencer.c
+++ b/src/sequencer.c
@@ -209,6 +209,14 @@ handle_channel_selection(void) {
209 } else if (key_tap(KEY_A)) { 209 } else if (key_tap(KEY_A)) {
210 if (key_hold(KEY_SELECT)) { 210 if (key_hold(KEY_SELECT)) {
211 clipboard_paste(); 211 clipboard_paste();
212 } else {
213 switch (channel_selection_loc) {
214 case 0: { input_handler = handle_param_selection_ch1; } break;
215 case 1: { input_handler = handle_param_selection_ch2; } break;
216 case 2: { input_handler = handle_param_selection_ch3; } break;
217 case 3: { input_handler = handle_param_selection_ch4; } break;
218 }
219 redraw_params = true;
212 } 220 }
213 } else if (key_tap(KEY_L)) { 221 } else if (key_tap(KEY_L)) {
214 s32 inc = -1; 222 s32 inc = -1;
@@ -222,6 +230,7 @@ handle_channel_selection(void) {
222 case 1: { trig = &pat->ch2.notes[i]; } break; 230 case 1: { trig = &pat->ch2.notes[i]; } break;
223 case 2: { trig = &pat->ch3.notes[i]; } break; 231 case 2: { trig = &pat->ch3.notes[i]; } break;
224 case 3: { trig = &pat->ch4.notes[i]; } break; 232 case 3: { trig = &pat->ch4.notes[i]; } break;
233 default: {trig = &pat->ch1.notes[i]; } break;
225 } 234 }
226 trig->note = MAX((s32)trig->note + inc, (s32)NOTE_C_2); 235 trig->note = MAX((s32)trig->note + inc, (s32)NOTE_C_2);
227 } 236 }
@@ -238,6 +247,7 @@ handle_channel_selection(void) {
238 case 1: { trig = &pat->ch2.notes[i]; } break; 247 case 1: { trig = &pat->ch2.notes[i]; } break;
239 case 2: { trig = &pat->ch3.notes[i]; } break; 248 case 2: { trig = &pat->ch3.notes[i]; } break;
240 case 3: { trig = &pat->ch4.notes[i]; } break; 249 case 3: { trig = &pat->ch4.notes[i]; } break;
250 default: {trig = &pat->ch1.notes[i]; } break;
241 } 251 }
242 trig->note = MIN((s32)trig->note + inc, (s32)NOTE_C_8 - 1); 252 trig->note = MIN((s32)trig->note + inc, (s32)NOTE_C_8 - 1);
243 } 253 }
@@ -258,6 +268,7 @@ handle_channel_selection(void) {
258 channel_selection_loc = MAX(channel_selection_loc - 1, 0); 268 channel_selection_loc = MAX(channel_selection_loc - 1, 0);
259 } 269 }
260 redraw_trigs = true; 270 redraw_trigs = true;
271 redraw_params = true;
261 } else if (key_tap(KEY_DOWN)) { 272 } else if (key_tap(KEY_DOWN)) {
262 if (channel_selection_loc == SEQ_N_CHANNELS - 1) { 273 if (channel_selection_loc == SEQ_N_CHANNELS - 1) {
263 channel_selection_loc = 0; 274 channel_selection_loc = 0;
@@ -265,6 +276,7 @@ handle_channel_selection(void) {
265 channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS); 276 channel_selection_loc = MIN(channel_selection_loc + 1, SEQ_N_CHANNELS);
266 } 277 }
267 redraw_trigs = true; 278 redraw_trigs = true;
279 redraw_params = true;
268 } 280 }
269} 281}
270 282
@@ -457,10 +469,10 @@ handle_pattern_selection(void) {
457} 469}
458 470
459void 471void
460handle_param_selection_sq1(void) { 472set_param_selection_sq1(size_t i, InputHandler return_handler) {
461 // Go back to trigger selection. 473 // Go back to trigger selection.
462 if (key_released(KEY_A)) { 474 if (key_released(KEY_A)) {
463 input_handler = handle_trigger_selection; 475 input_handler = return_handler;
464 redraw_params = true; 476 redraw_params = true;
465 return; 477 return;
466 } 478 }
@@ -518,7 +530,7 @@ handle_param_selection_sq1(void) {
518 inc = 1; 530 inc = 1;
519 } 531 }
520 Pattern *pat = &patterns[pattern_selection_loc]; 532 Pattern *pat = &patterns[pattern_selection_loc];
521 ChannelSquareParams *params = &pat->ch1.params[trig_selection_loc]; 533 ChannelSquareParams *params = &pat->ch1.params[i];
522 switch (param_selection_loc) { 534 switch (param_selection_loc) {
523 case 0: { 535 case 0: {
524 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3); 536 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3);
@@ -547,10 +559,10 @@ handle_param_selection_sq1(void) {
547} 559}
548 560
549void 561void
550handle_param_selection_sq2(void) { 562set_param_selection_sq2(size_t i, InputHandler return_handler) {
551 // Go back to trigger selection. 563 // Go back to trigger selection.
552 if (key_released(KEY_A)) { 564 if (key_released(KEY_A)) {
553 input_handler = handle_trigger_selection; 565 input_handler = return_handler;
554 redraw_params = true; 566 redraw_params = true;
555 return; 567 return;
556 } 568 }
@@ -577,7 +589,7 @@ handle_param_selection_sq2(void) {
577 inc = 1; 589 inc = 1;
578 } 590 }
579 Pattern *pat = &patterns[pattern_selection_loc]; 591 Pattern *pat = &patterns[pattern_selection_loc];
580 ChannelSquareParams *params = &pat->ch2.params[trig_selection_loc]; 592 ChannelSquareParams *params = &pat->ch2.params[i];
581 switch (param_selection_loc) { 593 switch (param_selection_loc) {
582 case 0: { 594 case 0: {
583 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3); 595 params->duty_cycle = CLAMP(params->duty_cycle + inc, 0, 3);
@@ -597,12 +609,12 @@ handle_param_selection_sq2(void) {
597} 609}
598 610
599void 611void
600handle_param_selection_wave(void) { 612set_param_selection_wave(size_t i, InputHandler return_handler) {
601 Pattern *pat = &patterns[pattern_selection_loc]; 613 Pattern *pat = &patterns[pattern_selection_loc];
602 614
603 // Go back to trigger selection. 615 // Go back to trigger selection.
604 if (key_released(KEY_A)) { 616 if (key_released(KEY_A)) {
605 input_handler = handle_trigger_selection; 617 input_handler = return_handler;
606 redraw_params = true; 618 redraw_params = true;
607 return; 619 return;
608 } 620 }
@@ -706,7 +718,7 @@ handle_param_selection_wave(void) {
706 if (param_selection_loc < 32) { 718 if (param_selection_loc < 32) {
707 // Draw on wave a. 719 // Draw on wave a.
708 u8 byte_number = param_selection_loc / 2; 720 u8 byte_number = param_selection_loc / 2;
709 u8 *byte = &pat->ch3.params[trig_selection_loc].wave_a; 721 u8 *byte = &pat->ch3.params[i].wave_a;
710 byte += byte_number; 722 byte += byte_number;
711 if (odd) { 723 if (odd) {
712 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF); 724 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF);
@@ -716,7 +728,7 @@ handle_param_selection_wave(void) {
716 } else if (param_selection_loc < 64){ 728 } else if (param_selection_loc < 64){
717 // Draw on wave b. 729 // Draw on wave b.
718 u8 byte_number = (param_selection_loc - 32) / 2; 730 u8 byte_number = (param_selection_loc - 32) / 2;
719 u8 *byte = &pat->ch3.params[trig_selection_loc].wave_b; 731 u8 *byte = &pat->ch3.params[i].wave_b;
720 byte += byte_number; 732 byte += byte_number;
721 if (odd) { 733 if (odd) {
722 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF); 734 *byte = (~0xF & *byte) | ((*byte + inc) & 0xF);
@@ -725,8 +737,8 @@ handle_param_selection_wave(void) {
725 } 737 }
726 } else if (param_selection_loc < 72) { 738 } else if (param_selection_loc < 72) {
727 // Copy default waves. 739 // Copy default waves.
728 u32 *wave_a = &pat->ch3.params[trig_selection_loc].wave_a; 740 u32 *wave_a = &pat->ch3.params[i].wave_a;
729 u32 *wave_b = &pat->ch3.params[trig_selection_loc].wave_b; 741 u32 *wave_b = &pat->ch3.params[i].wave_b;
730 switch (param_selection_loc) { 742 switch (param_selection_loc) {
731 case 64: { 743 case 64: {
732 memcpy32(wave_a, sine_wave, 16); 744 memcpy32(wave_a, sine_wave, 16);
@@ -760,10 +772,10 @@ handle_param_selection_wave(void) {
760 } break; 772 } break;
761 } 773 }
762 } else if (param_selection_loc == 72) { 774 } else if (param_selection_loc == 72) {
763 u8 *wave_mode = &pat->ch3.params[trig_selection_loc].wave_mode; 775 u8 *wave_mode = &pat->ch3.params[i].wave_mode;
764 *wave_mode = CLAMP(*wave_mode + inc, 0, 2); 776 *wave_mode = CLAMP(*wave_mode + inc, 0, 2);
765 } else if (param_selection_loc == 73) { 777 } else if (param_selection_loc == 73) {
766 u8 *wave_volume = &pat->ch3.params[trig_selection_loc].wave_volume; 778 u8 *wave_volume = &pat->ch3.params[i].wave_volume;
767 *wave_volume = CLAMP(*wave_volume + inc, 0, 4); 779 *wave_volume = CLAMP(*wave_volume + inc, 0, 4);
768 } 780 }
769 redraw_params = true; 781 redraw_params = true;
@@ -771,10 +783,11 @@ handle_param_selection_wave(void) {
771} 783}
772 784
773void 785void
774handle_param_selection_noise(void) { 786set_param_selection_noise(size_t i, InputHandler return_handler) {
775 // Go back to trigger selection. 787 // Go back to trigger selection.
776 if (key_released(KEY_A)) { 788 if (key_released(KEY_A)) {
777 input_handler = handle_trigger_selection; 789 input_handler = return_handler;
790 redraw_params = true;
778 return; 791 return;
779 } 792 }
780 793
@@ -788,6 +801,7 @@ handle_param_selection_noise(void) {
788 inc = -1; 801 inc = -1;
789 } 802 }
790 param_selection_loc = CLAMP(loc + inc, 0, 3); 803 param_selection_loc = CLAMP(loc + inc, 0, 3);
804 redraw_params = true;
791 } 805 }
792 806
793 // Adjust parameter. 807 // Adjust parameter.
@@ -799,7 +813,7 @@ handle_param_selection_noise(void) {
799 inc = 1; 813 inc = 1;
800 } 814 }
801 Pattern *pat = &patterns[pattern_selection_loc]; 815 Pattern *pat = &patterns[pattern_selection_loc];
802 ChannelNoiseParams *params = &pat->ch4.params[trig_selection_loc]; 816 ChannelNoiseParams *params = &pat->ch4.params[i];
803 switch (param_selection_loc) { 817 switch (param_selection_loc) {
804 case 0: { 818 case 0: {
805 params->bit_mode = CLAMP(params->bit_mode + inc, 0, 1); 819 params->bit_mode = CLAMP(params->bit_mode + inc, 0, 1);
@@ -819,6 +833,46 @@ handle_param_selection_noise(void) {
819} 833}
820 834
821void 835void
836handle_param_selection_ch1() {
837 set_param_selection_sq1(16, handle_channel_selection);
838}
839
840void
841handle_param_selection_ch2() {
842 set_param_selection_sq2(16, handle_channel_selection);
843}
844
845void
846handle_param_selection_ch3() {
847 set_param_selection_wave(16, handle_channel_selection);
848}
849
850void
851handle_param_selection_ch4() {
852 set_param_selection_noise(16, handle_channel_selection);
853}
854
855void
856handle_param_selection_sq1() {
857 set_param_selection_sq1(trig_selection_loc, handle_trigger_selection);
858}
859
860void
861handle_param_selection_sq2() {
862 set_param_selection_sq2(trig_selection_loc, handle_trigger_selection);
863}
864
865void
866handle_param_selection_wave() {
867 set_param_selection_wave(trig_selection_loc, handle_trigger_selection);
868}
869
870void
871handle_param_selection_noise() {
872 set_param_selection_noise(trig_selection_loc, handle_trigger_selection);
873}
874
875void
822handle_trigger_selection(void) { 876handle_trigger_selection(void) {
823 TriggerNote *trig = get_current_trig(); 877 TriggerNote *trig = get_current_trig();
824 878
@@ -886,18 +940,10 @@ handle_trigger_selection(void) {
886 } else { 940 } else {
887 // Switch to parameter selection. 941 // Switch to parameter selection.
888 switch (channel_selection_loc) { 942 switch (channel_selection_loc) {
889 case 0: { 943 case 0: { input_handler = handle_param_selection_sq1; } break;
890 input_handler = handle_param_selection_sq1; 944 case 1: { input_handler = handle_param_selection_sq2; } break;
891 } break; 945 case 2: { input_handler = handle_param_selection_wave; } break;
892 case 1: { 946 case 3: { input_handler = handle_param_selection_noise; } break;
893 input_handler = handle_param_selection_sq2;
894 } break;
895 case 2: {
896 input_handler = handle_param_selection_wave;
897 } break;
898 case 3: {
899 input_handler = handle_param_selection_noise;
900 } break;
901 } 947 }
902 redraw_params = true; 948 redraw_params = true;
903 redraw_piano_note = true; 949 redraw_piano_note = true;