summaryrefslogtreecommitdiffstats
path: root/src/sequencer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sequencer.c')
-rw-r--r--src/sequencer.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/sequencer.c b/src/sequencer.c
new file mode 100644
index 0000000..4231def
--- /dev/null
+++ b/src/sequencer.c
@@ -0,0 +1,218 @@
1#define SPRITE_NOTE_NAMES_W 16
2#define SPRITE_NOTE_NAMES_H 8
3
4u32 sprite_note_names[] = {
5 0x77417111, 0x77000000, 0x00000000, 0x00000000,
6 0x13157555, 0x33000000, 0x07040701, 0x07000000,
7 0x73457515, 0x73000000, 0x00000000, 0x00000000,
8 0x17117351, 0x37000000, 0x07040701, 0x07000000,
9 0x77417311, 0x77000000, 0x00000000, 0x00000000,
10 0x77417311, 0x71000000, 0x00000000, 0x00000000,
11 0x17117155, 0x37000000, 0x07040701, 0x07000000,
12 0x77417115, 0x77000000, 0x00000000, 0x00000000,
13 0x17157557, 0x35000000, 0x07040701, 0x07000000,
14 0x77457517, 0x75000000, 0x00000000, 0x00000000,
15 0x17157355, 0x37000000, 0x07040701, 0x07000000,
16 0x77457315, 0x77000000, 0x00000000, 0x00000000,
17 0x77416141, 0x77000000, 0x00000000, 0x00000000,
18 0x13157555, 0x33000000, 0x07040604, 0x07000000,
19 0x73456545, 0x73000000, 0x00000000, 0x00000000,
20 0x17117351, 0x37000000, 0x07040604, 0x07000000,
21 0x77416341, 0x77000000, 0x00000000, 0x00000000,
22 0x77416341, 0x71000000, 0x00000000, 0x00000000,
23 0x17117155, 0x37000000, 0x07040604, 0x07000000,
24 0x77416145, 0x77000000, 0x00000000, 0x00000000,
25 0x17157557, 0x35000000, 0x07040604, 0x07000000,
26 0x77456547, 0x75000000, 0x00000000, 0x00000000,
27 0x17157355, 0x37000000, 0x07040604, 0x07000000,
28 0x77456345, 0x77000000, 0x00000000, 0x00000000,
29 0x47615171, 0x47000000, 0x00000000, 0x00000000,
30 0x13157555, 0x33000000, 0x04060507, 0x04000000,
31 0x43655575, 0x43000000, 0x00000000, 0x00000000,
32 0x17117351, 0x37000000, 0x04060507, 0x04000000,
33 0x47615371, 0x47000000, 0x00000000, 0x00000000,
34 0x47615371, 0x41000000, 0x00000000, 0x00000000,
35 0x17117155, 0x37000000, 0x04060507, 0x04000000,
36 0x47615175, 0x47000000, 0x00000000, 0x00000000,
37 0x17157557, 0x35000000, 0x04060507, 0x04000000,
38 0x47655577, 0x45000000, 0x00000000, 0x00000000,
39 0x17157355, 0x37000000, 0x04060507, 0x04000000,
40 0x47655375, 0x47000000, 0x00000000, 0x00000000,
41 0x77117141, 0x77000000, 0x00000000, 0x00000000,
42 0x13157555, 0x33000000, 0x07010704, 0x07000000,
43 0x73157545, 0x73000000, 0x00000000, 0x00000000,
44 0x17117351, 0x37000000, 0x07010704, 0x07000000,
45 0x77117341, 0x77000000, 0x00000000, 0x00000000,
46 0x77117341, 0x71000000, 0x00000000, 0x00000000,
47 0x17117155, 0x37000000, 0x07010704, 0x07000000,
48 0x77117145, 0x77000000, 0x00000000, 0x00000000,
49 0x17157557, 0x35000000, 0x07010704, 0x07000000,
50 0x77157547, 0x75000000, 0x00000000, 0x00000000,
51 0x17157355, 0x37000000, 0x07010704, 0x07000000,
52 0x77157345, 0x77000000, 0x00000000, 0x00000000,
53 0x77117151, 0x77000000, 0x00000000, 0x00000000,
54 0x13157555, 0x33000000, 0x07010705, 0x07000000,
55 0x73157555, 0x73000000, 0x00000000, 0x00000000,
56 0x17117351, 0x37000000, 0x07010705, 0x07000000,
57 0x77117351, 0x77000000, 0x00000000, 0x00000000,
58 0x77117351, 0x71000000, 0x00000000, 0x00000000,
59 0x17117155, 0x37000000, 0x07010705, 0x07000000,
60 0x77117155, 0x77000000, 0x00000000, 0x00000000,
61 0x17157557, 0x35000000, 0x07010705, 0x07000000,
62 0x77157557, 0x75000000, 0x00000000, 0x00000000,
63 0x17157355, 0x37000000, 0x07010705, 0x07000000,
64 0x77157355, 0x77000000, 0x00000000, 0x00000000,
65 0x77412111, 0x17000000, 0x00000000, 0x00000000,
66 0x13157555, 0x33000000, 0x07040201, 0x01000000,
67 0x73452515, 0x13000000, 0x00000000, 0x00000000,
68 0x17117351, 0x37000000, 0x07040201, 0x01000000,
69 0x77412311, 0x17000000, 0x00000000, 0x00000000,
70 0x77412311, 0x11000000, 0x00000000, 0x00000000,
71 0x17117155, 0x37000000, 0x07040201, 0x01000000,
72 0x77412115, 0x17000000, 0x00000000, 0x00000000,
73 0x17157557, 0x35000000, 0x07040201, 0x01000000,
74 0x77452517, 0x15000000, 0x00000000, 0x00000000,
75 0x17157355, 0x37000000, 0x07040201, 0x01000000,
76 0x77452315, 0x17000000, 0x00000000, 0x00000000,
77 0x77517151, 0x77000000, 0x00000000, 0x00000000,
78};
79
80typedef struct SeqTrigger {
81 bool trigger;
82 Note note;
83 // TODO: ...
84} SeqTrigger;
85
86static SeqTrigger sequence_synth[] = {
87 {true, NOTE_D_4},
88 {true, NOTE_F_4},
89 {true, NOTE_A_4},
90 {true, NOTE_C_5},
91
92 {true, NOTE_D_4},
93 {false, NOTE_D_4},
94 {false, NOTE_D_4},
95 {false, NOTE_D_4},
96
97 {true, NOTE_D_4},
98 {true, NOTE_F_4},
99 {true, NOTE_A_4},
100 {true, NOTE_C_5},
101
102 {true, NOTE_D_4},
103 {false, NOTE_D_4},
104 {true, NOTE_A_4},
105 {false, NOTE_A_5},
106};
107
108static int step_counter = 0;
109static Note active_note;
110
111void
112irq_timer_0(void) {
113 active_note = sequence_synth[step_counter].note;
114 if (sequence_synth[step_counter].trigger) {
115 SOUND_SQUARE1_CTRL = SOUND_SQUARE_ENV_VOL(13) | SOUND_SQUARE_ENV_TIME(4) | SOUND_SQUARE_DUTY(2);
116 SOUND_SQUARE1_FREQ = SOUND_SQUARE_RESET | sound_rates[active_note];
117 }
118 step_counter = (step_counter + 1) % 16;
119}
120
121void
122set_time(int bpm) {
123 // The number of ticks of a 1024 cycle clock in a step based on the BPM can
124 // be calculated as:
125 // X bpm -> 60000 / 4 / bpm = Y ms = Ye-3 s
126 // Y ms -> Ye-3 / 59.99e-9 /1024 = Z ticks
127 // We have to operate on integer values, so the numbers have been
128 // precalculated to `n_ticks = 244181 / bmp`
129 int n_ticks = -244181 / bpm;
130
131 irs_set(IRQ_TIMER_0, irq_timer_0);
132 TIMER_DATA_0 = n_ticks;
133 TIMER_CTRL_0 = TIMER_CTRL_IRQ | TIMER_CTRL_ENABLE | TIMER_CTRL_FREQ_3;
134}
135
136static size_t note_sprites_id = 0;
137
138//
139// Sequencer sprite memory.
140//
141// Currently we load all sequencer sprite memory in the VRAM:
142//
143// - Note names: 0-73x2 tiles
144// - ...
145//
146// The order of OBJs correspond to:
147//
148// - 000-015 step note names.
149// - 015-029 step trigger steps.
150// - 030-045 step duration indicators.
151// - 046-046 current step marker.
152// - 047-047 trigger selection indicator.
153//
154
155size_t obj_counter = 0;
156
157typedef struct SeqSprite {
158 u8 id;
159 int x;
160 int y;
161 u16 obj_attr_0;
162 u16 obj_attr_1;
163 u16 obj_attr_2;
164} SeqSprite;
165
166#define SEQ_POS_X 20
167#define SEQ_POS_Y 20
168
169// SeqSprite seq_sprites[] = {
170// // 000-015: Step note names.
171// {
172// .x = SEQ_POS_X,
173// .y = SEQ_POS_Y,
174// .obj_attr_0 = OBJ_SHAPE_WIDE,
175// .obj_attr_1 = OBJ_SHAPE_SMALL,
176// .obj_attr_2 = 0,
177// },
178// };
179
180SeqSprite seq_sprites[16] = {0};
181
182void
183init_sequencer_sprites() {
184 // Load note sprites.
185 note_sprites_id = load_packed_sprite_data(&sprite_note_names, 2, 73);
186
187 for (size_t i = 0; i < 16; ++i) {
188 int x = SEQ_POS_X + i * 16;
189 int y = SEQ_POS_Y;
190 if (i >= 8) {
191 y += 32;
192 x -= 8 * 16;
193 }
194 seq_sprites[i].x = x;
195 seq_sprites[i].y = y;
196
197 seq_sprites[i].id = obj_counter++;
198 seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y);
199 // TODO: They should start hidden until the update function changes that.
200 // seq_sprites[i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_HIDDEN;
201 seq_sprites[i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x);
202 }
203}
204
205void
206render_sequencer_sprites() {
207 size_t len = sizeof(seq_sprites) / sizeof(SeqSprite);
208 for (size_t i = 0; i < len; ++i) {
209 size_t id = seq_sprites[i].id;
210 // TODO: This needs to be done in an update function, not here.
211 size_t base_tile = sequence_synth[i].note;
212 seq_sprites[i].obj_attr_2 = base_tile;
213
214 OBJ_ATTR_0(id) = seq_sprites[i].obj_attr_0;
215 OBJ_ATTR_1(id) = seq_sprites[i].obj_attr_1;
216 OBJ_ATTR_2(id) = seq_sprites[i].obj_attr_2;
217 }
218}