diff options
author | Bad Diode <bd@badd10de.dev> | 2023-04-03 12:29:48 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2023-04-03 12:29:48 +0200 |
commit | d96f6da677bc319f7868e832f09948c94ee6a148 (patch) | |
tree | d22dc99df5a1fb4f4b9c24b9d43aeb85fef4a283 | |
parent | 4a4e0f5d55caa5c56929f8505a6722eb1423e73f (diff) | |
download | stepper-d96f6da677bc319f7868e832f09948c94ee6a148.tar.gz stepper-d96f6da677bc319f7868e832f09948c94ee6a148.zip |
Add noise channel with note support
-rw-r--r-- | src/gba/gba.h | 14 | ||||
-rw-r--r-- | src/sequencer.c | 395 |
2 files changed, 395 insertions, 14 deletions
diff --git a/src/gba/gba.h b/src/gba/gba.h index cdb3b31..b02d745 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h | |||
@@ -558,7 +558,7 @@ sound_volume(SoundChannel channels, u8 volume) { | |||
558 | #define SOUND_SWEEP_DIR(N) ((N) << 0x3) | 558 | #define SOUND_SWEEP_DIR(N) ((N) << 0x3) |
559 | #define SOUND_SWEEP_TIME(N) ((N) << 0x4) | 559 | #define SOUND_SWEEP_TIME(N) ((N) << 0x4) |
560 | 560 | ||
561 | // DMG frequency bits (Square/Wave). | 561 | // DMG frequency bits (Square/Wave/NOISE). |
562 | #define SOUND_FREQ_TIMED (1 << 0xE) | 562 | #define SOUND_FREQ_TIMED (1 << 0xE) |
563 | #define SOUND_FREQ_RESET (1 << 0xF) | 563 | #define SOUND_FREQ_RESET (1 << 0xF) |
564 | 564 | ||
@@ -585,6 +585,18 @@ typedef u8 WaveBank[32]; | |||
585 | 585 | ||
586 | #define SOUND_WAVE_RAM ((WaveBank*)(MEM_IO + 0x90)) | 586 | #define SOUND_WAVE_RAM ((WaveBank*)(MEM_IO + 0x90)) |
587 | 587 | ||
588 | // DMG noise control bits. | ||
589 | #define SOUND_NOISE_LENGTH(N) (((N) & 0x3F) << 0) | ||
590 | #define SOUND_NOISE_ENV_TIME(N) (((N) & 0x07) << 0x8) | ||
591 | #define SOUND_NOISE_ENV_DIR(N) (((N) & 0x01) << 0xB) | ||
592 | #define SOUND_NOISE_ENV_VOL(N) (((N) & 0x0F) << 0xC) | ||
593 | |||
594 | // DMG noise freq bits. | ||
595 | #define SOUND_NOISE_DIV_FREQ(N) (((N) & 0x07) << 0) | ||
596 | #define SOUND_NOISE_COUNTER_STAGE(N) (((N) & 0x01) << 0x3) | ||
597 | #define SOUND_NOISE_PRESTEP_FREQ(N) (((N) & 0x0F) << 0x4) | ||
598 | #define SOUND_NOISE_TIMED_MODE(N) (((N) & 0x01) << 0xe) | ||
599 | |||
588 | typedef enum { | 600 | typedef enum { |
589 | NOTE_C_2 , NOTE_C_SHARP_2 , NOTE_D_2 , NOTE_D_SHARP_2 , | 601 | NOTE_C_2 , NOTE_C_SHARP_2 , NOTE_D_2 , NOTE_D_SHARP_2 , |
590 | NOTE_E_2 , NOTE_F_2 , NOTE_F_SHARP_2 , NOTE_G_2 , | 602 | NOTE_E_2 , NOTE_F_2 , NOTE_F_SHARP_2 , NOTE_G_2 , |
diff --git a/src/sequencer.c b/src/sequencer.c index 856d579..8c3f89a 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -1,6 +1,15 @@ | |||
1 | #include "rng.c" | 1 | #include "rng.c" |
2 | #include "text.h" | 2 | #include "text.h" |
3 | 3 | ||
4 | // TODO | ||
5 | // - Preview sound keys | ||
6 | // - Copy paste trigs/notes/params | ||
7 | // - Different banks for storing patterns | ||
8 | // - Buttons on the left side for selecting different patterns | ||
9 | // - Pattern chaining or song mode | ||
10 | // - Allow control BPM | ||
11 | // - Finish noise channel | ||
12 | |||
4 | // | 13 | // |
5 | // Color indexes. | 14 | // Color indexes. |
6 | // | 15 | // |
@@ -150,7 +159,7 @@ static int bpm = 115; | |||
150 | static int step_counter = 0; | 159 | static int step_counter = 0; |
151 | int trig_selection_loc = 0; | 160 | int trig_selection_loc = 0; |
152 | int param_selection_loc = 0; | 161 | int param_selection_loc = 0; |
153 | int channel_selection_loc = 0; | 162 | int channel_selection_loc = 3; |
154 | 163 | ||
155 | typedef struct TriggerNote { | 164 | typedef struct TriggerNote { |
156 | bool active; | 165 | bool active; |
@@ -186,6 +195,11 @@ typedef struct ChannelWave { | |||
186 | ChannelWaveParams params[16]; | 195 | ChannelWaveParams params[16]; |
187 | } ChannelWave; | 196 | } ChannelWave; |
188 | 197 | ||
198 | typedef struct ChannelNoise { | ||
199 | bool active; | ||
200 | TriggerNote notes[16]; | ||
201 | } ChannelNoise; | ||
202 | |||
189 | static ChannelSquare ch1 = { | 203 | static ChannelSquare ch1 = { |
190 | .notes = { | 204 | .notes = { |
191 | {true, NOTE_C_4}, | 205 | {true, NOTE_C_4}, |
@@ -223,7 +237,7 @@ static ChannelSquare ch1 = { | |||
223 | {8, 4, 0, 2, 0, 0, 0}, | 237 | {8, 4, 0, 2, 0, 0, 0}, |
224 | {8, 4, 0, 2, 0, 0, 0}, | 238 | {8, 4, 0, 2, 0, 0, 0}, |
225 | }, | 239 | }, |
226 | .active = true, | 240 | .active = false, |
227 | }; | 241 | }; |
228 | 242 | ||
229 | static ChannelSquare ch2 = { | 243 | static ChannelSquare ch2 = { |
@@ -263,7 +277,7 @@ static ChannelSquare ch2 = { | |||
263 | {8, 4, 0, 2, 0, 0, 0}, | 277 | {8, 4, 0, 2, 0, 0, 0}, |
264 | {8, 4, 0, 2, 0, 0, 0}, | 278 | {8, 4, 0, 2, 0, 0, 0}, |
265 | }, | 279 | }, |
266 | .active = true, | 280 | .active = false, |
267 | }; | 281 | }; |
268 | 282 | ||
269 | static ChannelWave ch3 = { | 283 | static ChannelWave ch3 = { |
@@ -303,6 +317,29 @@ static ChannelWave ch3 = { | |||
303 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | 317 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, |
304 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, | 318 | {3, 0, {0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000},{0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000}}, |
305 | }, | 319 | }, |
320 | .active = false, | ||
321 | }; | ||
322 | |||
323 | // TODO: Add default noise parameters data. | ||
324 | static ChannelNoise ch4 = { | ||
325 | .notes = { | ||
326 | {true, 0}, | ||
327 | {false, NOTE_D_4}, | ||
328 | {false, NOTE_E_4}, | ||
329 | {false, NOTE_F_4}, | ||
330 | {false, NOTE_G_4}, | ||
331 | {false, NOTE_A_4}, | ||
332 | {false, NOTE_B_4}, | ||
333 | {false, NOTE_C_5}, | ||
334 | {false, NOTE_C_4}, | ||
335 | {false, NOTE_C_4}, | ||
336 | {false, NOTE_C_4}, | ||
337 | {false, NOTE_C_4}, | ||
338 | {false, NOTE_C_4}, | ||
339 | {false, NOTE_C_4}, | ||
340 | {false, NOTE_C_4}, | ||
341 | {false, NOTE_C_4}, | ||
342 | }, | ||
306 | .active = true, | 343 | .active = true, |
307 | }; | 344 | }; |
308 | 345 | ||
@@ -313,7 +350,7 @@ static ChannelWave ch3 = { | |||
313 | #define TRIG_W 15 | 350 | #define TRIG_W 15 |
314 | #define TRIG_H 24 | 351 | #define TRIG_H 24 |
315 | #define TRIG_START_X 64 | 352 | #define TRIG_START_X 64 |
316 | #define TRIG_START_Y 97 | 353 | #define TRIG_START_Y 92 |
317 | #define TRIG_OFFSET_X (TRIG_W + 3) | 354 | #define TRIG_OFFSET_X (TRIG_W + 3) |
318 | #define TRIG_OFFSET_Y (TRIG_H + 7) | 355 | #define TRIG_OFFSET_Y (TRIG_H + 7) |
319 | 356 | ||
@@ -341,6 +378,9 @@ draw_trigger(size_t chan, size_t i) { | |||
341 | case 2: { | 378 | case 2: { |
342 | trig = ch3.notes[i]; | 379 | trig = ch3.notes[i]; |
343 | } break; | 380 | } break; |
381 | case 3: { | ||
382 | trig = ch4.notes[i]; | ||
383 | } break; | ||
344 | } | 384 | } |
345 | if (trig.active) { | 385 | if (trig.active) { |
346 | size_t offset_x = TRIG_OFFSET_X * (i % 8); | 386 | size_t offset_x = TRIG_OFFSET_X * (i % 8); |
@@ -388,7 +428,7 @@ draw_triggers(void) { | |||
388 | #define CHAN_W 19 | 428 | #define CHAN_W 19 |
389 | #define CHAN_H 8 | 429 | #define CHAN_H 8 |
390 | #define CHAN_START_X 35 | 430 | #define CHAN_START_X 35 |
391 | #define CHAN_START_Y 97 | 431 | #define CHAN_START_Y 92 |
392 | #define CHAN_OFFSET_Y 12 | 432 | #define CHAN_OFFSET_Y 12 |
393 | 433 | ||
394 | void | 434 | void |
@@ -409,6 +449,9 @@ draw_channels(void) { | |||
409 | case 2: { | 449 | case 2: { |
410 | active = ch3.active; | 450 | active = ch3.active; |
411 | } break; | 451 | } break; |
452 | case 3: { | ||
453 | active = ch4.active; | ||
454 | } break; | ||
412 | } | 455 | } |
413 | u8 clr = active ? COL_FG : COL_GREY; | 456 | u8 clr = active ? COL_FG : COL_GREY; |
414 | size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; | 457 | size_t y = CHAN_START_Y + i * CHAN_OFFSET_Y; |
@@ -431,7 +474,7 @@ draw_channel_cursor(size_t i, u8 clr) { | |||
431 | #define PIANO_W 170 | 474 | #define PIANO_W 170 |
432 | #define PIANO_H 20 | 475 | #define PIANO_H 20 |
433 | #define PIANO_START_X 35 | 476 | #define PIANO_START_X 35 |
434 | #define PIANO_START_Y 72 | 477 | #define PIANO_START_Y 65 |
435 | #define PIANO_NOTE_W 2 | 478 | #define PIANO_NOTE_W 2 |
436 | 479 | ||
437 | void | 480 | void |
@@ -571,7 +614,7 @@ draw_piano(void) { | |||
571 | #define PARAMS_W 170 | 614 | #define PARAMS_W 170 |
572 | #define PARAMS_H 64 | 615 | #define PARAMS_H 64 |
573 | #define PARAMS_START_X 35 | 616 | #define PARAMS_START_X 35 |
574 | #define PARAMS_START_Y 8 | 617 | #define PARAMS_START_Y 1 |
575 | 618 | ||
576 | void | 619 | void |
577 | draw_params_cursor_wave(size_t i, u8 clr) { | 620 | draw_params_cursor_wave(size_t i, u8 clr) { |
@@ -629,6 +672,61 @@ draw_params_cursor_wave(size_t i, u8 clr) { | |||
629 | } | 672 | } |
630 | 673 | ||
631 | void | 674 | void |
675 | draw_params_cursor_noise(size_t i, u8 clr) { | ||
676 | // u8 x_positions[] = { | ||
677 | // // 32 half bytes (Wave A). | ||
678 | // 0, 4, 8, 12, 16, 20, 24, 28, | ||
679 | // 34, 38, 42, 46, 50, 54, 58, 62, | ||
680 | // 0, 4, 8, 12, 16, 20, 24, 28, | ||
681 | // 34, 38, 42, 46, 50, 54, 58, 62, | ||
682 | // // 32 half bytes (Wave B). | ||
683 | // 70, 74, 78, 82, 86, 90, 94, 98, | ||
684 | // 104, 108, 112, 116, 120, 124, 128, 132, | ||
685 | // 70, 74, 78, 82, 86, 90, 94, 98, | ||
686 | // 104, 108, 112, 116, 120, 124, 128, 132, | ||
687 | // // Default wave A. | ||
688 | // 1, 18, 35, 52, | ||
689 | // // Default wave B. | ||
690 | // 71, 88, 105, 122, | ||
691 | // // Mode selection. | ||
692 | // 141, | ||
693 | // // Volume selection. | ||
694 | // 141, | ||
695 | // }; | ||
696 | // u8 y_positions[] = { | ||
697 | // // 32 half bytes (Wave A) | ||
698 | // 0, 0, 0, 0, 0, 0, 0, 0, | ||
699 | // 0, 0, 0, 0, 0, 0, 0, 0, | ||
700 | // 8, 8, 8, 8, 8, 8, 8, 8, | ||
701 | // 8, 8, 8, 8, 8, 8, 8, 8, | ||
702 | // // 32 half bytes (Wave B) | ||
703 | // 0, 0, 0, 0, 0, 0, 0, 0, | ||
704 | // 0, 0, 0, 0, 0, 0, 0, 0, | ||
705 | // 8, 8, 8, 8, 8, 8, 8, 8, | ||
706 | // 8, 8, 8, 8, 8, 8, 8, 8, | ||
707 | // // Default wave A. | ||
708 | // 20, 20, 20, 20, | ||
709 | // // Default wave B. | ||
710 | // 20, 20, 20, 20, | ||
711 | // // Mode selection. | ||
712 | // 20, | ||
713 | // // Volume selection. | ||
714 | // 0, | ||
715 | // }; | ||
716 | // size_t cursor_length = 0; | ||
717 | // if (i < 64) { | ||
718 | // cursor_length = 4; | ||
719 | // } else if (i < 72) { | ||
720 | // cursor_length = 13; | ||
721 | // } else { | ||
722 | // cursor_length = 30; | ||
723 | // } | ||
724 | // size_t x = PARAMS_START_X + x_positions[i] - 1; | ||
725 | // size_t y = PARAMS_START_Y + PARAMS_H - 23 + y_positions[i]; | ||
726 | // draw_line(x, y, x + cursor_length, y, clr); | ||
727 | } | ||
728 | |||
729 | void | ||
632 | draw_params_cursor_square(size_t i, u8 clr, bool sweep) { | 730 | draw_params_cursor_square(size_t i, u8 clr, bool sweep) { |
633 | size_t x_offset = sweep ? 0 : 30; | 731 | size_t x_offset = sweep ? 0 : 30; |
634 | u8 x_positions[] = { | 732 | u8 x_positions[] = { |
@@ -668,6 +766,7 @@ draw_params_cursor(size_t i, u8 clr) { | |||
668 | draw_params_cursor_wave(i, clr); | 766 | draw_params_cursor_wave(i, clr); |
669 | } break; | 767 | } break; |
670 | case 3: { | 768 | case 3: { |
769 | draw_params_cursor_noise(i, clr); | ||
671 | } break; | 770 | } break; |
672 | } | 771 | } |
673 | } | 772 | } |
@@ -814,7 +913,7 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) { | |||
814 | // Shape drawing. | 913 | // Shape drawing. |
815 | { | 914 | { |
816 | size_t x = PARAMS_START_X + x_offset; | 915 | size_t x = PARAMS_START_X + x_offset; |
817 | size_t y = PARAMS_START_Y + PARAMS_H - 43; | 916 | size_t y = PARAMS_START_Y + PARAMS_H - 44; |
818 | 917 | ||
819 | size_t x0 = x + 2; | 918 | size_t x0 = x + 2; |
820 | size_t x1 = x0; | 919 | size_t x1 = x0; |
@@ -904,14 +1003,14 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) { | |||
904 | // Bounding box. | 1003 | // Bounding box. |
905 | { | 1004 | { |
906 | size_t x0 = PARAMS_START_X + 31 + x_offset; | 1005 | size_t x0 = PARAMS_START_X + 31 + x_offset; |
907 | size_t y0 = PARAMS_START_Y + PARAMS_H - 46; | 1006 | size_t y0 = PARAMS_START_Y + PARAMS_H - 47; |
908 | size_t x1 = x0 + 79; | 1007 | size_t x1 = x0 + 79; |
909 | size_t y1 = y0 + 21; | 1008 | size_t y1 = y0 + 21; |
910 | draw_rect(x0, y0, x1, y1, COL_CYAN); | 1009 | draw_rect(x0, y0, x1, y1, COL_CYAN); |
911 | } | 1010 | } |
912 | 1011 | ||
913 | size_t x = PARAMS_START_X + 42 + x_offset; | 1012 | size_t x = PARAMS_START_X + 42 + x_offset; |
914 | size_t y = PARAMS_START_Y + PARAMS_H - 43; | 1013 | size_t y = PARAMS_START_Y + PARAMS_H - 44; |
915 | size_t x0 = x; | 1014 | size_t x0 = x; |
916 | size_t y0 = y + 15 - params->env_volume; | 1015 | size_t y0 = y + 15 - params->env_volume; |
917 | size_t x1 = x + 8 * params->env_time; | 1016 | size_t x1 = x + 8 * params->env_time; |
@@ -1158,7 +1257,7 @@ draw_parameters_square(ChannelSquareParams *params, bool sweep) { | |||
1158 | // Labels. | 1257 | // Labels. |
1159 | { | 1258 | { |
1160 | size_t x = PARAMS_START_X + x_offset; | 1259 | size_t x = PARAMS_START_X + x_offset; |
1161 | size_t y = PARAMS_START_Y + PARAMS_H - 43; | 1260 | size_t y = PARAMS_START_Y + PARAMS_H - 45; |
1162 | txt_drawf_small("shape", x + 1, y - 12, 4, COL_FG); | 1261 | txt_drawf_small("shape", x + 1, y - 12, 4, COL_FG); |
1163 | txt_drawf_small("envelope", x + 54, y - 12, 4, COL_FG); | 1262 | txt_drawf_small("envelope", x + 54, y - 12, 4, COL_FG); |
1164 | if (sweep) { | 1263 | if (sweep) { |
@@ -1272,6 +1371,83 @@ irq_timer(void) { | |||
1272 | SOUND_WAVE_CTRL = 0; | 1371 | SOUND_WAVE_CTRL = 0; |
1273 | SOUND_WAVE_FREQ = 0; | 1372 | SOUND_WAVE_FREQ = 0; |
1274 | } | 1373 | } |
1374 | if (ch4.active) { | ||
1375 | TriggerNote *trig = &ch4.notes[step_counter]; | ||
1376 | // ChannelNoiseParams *params = &ch4.params[step_counter]; | ||
1377 | if (trig->active) { | ||
1378 | // switch (params->wave_mode) { | ||
1379 | // case 0: { | ||
1380 | // SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); | ||
1381 | // memcpy32(SOUND_WAVE_RAM, params->wave_a, 16); | ||
1382 | // SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | ||
1383 | // | SOUND_WAVE_BANK_SELECT(0); | ||
1384 | // } break; | ||
1385 | // case 1: { | ||
1386 | // SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | ||
1387 | // memcpy32(SOUND_WAVE_RAM, params->wave_b, 16); | ||
1388 | // SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(0) | ||
1389 | // | SOUND_WAVE_BANK_SELECT(1); | ||
1390 | // } break; | ||
1391 | // case 2: { | ||
1392 | // SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); | ||
1393 | // memcpy32(SOUND_WAVE_RAM, params->wave_b, 16); | ||
1394 | // SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); | ||
1395 | // memcpy32(SOUND_WAVE_RAM, params->wave_a, 16); | ||
1396 | // SOUND_WAVE_MODE = SOUND_WAVE_BANK_MODE(1) | ||
1397 | // | SOUND_WAVE_BANK_SELECT(0); | ||
1398 | // } break; | ||
1399 | // } | ||
1400 | // SOUND_WAVE_MODE |= SOUND_WAVE_ENABLE; | ||
1401 | |||
1402 | // switch (params->wave_volume) { | ||
1403 | // case 0: { | ||
1404 | // SOUND_WAVE_CTRL = SOUND_WAVE_MUTE; | ||
1405 | // } break; | ||
1406 | // case 1: { | ||
1407 | // SOUND_WAVE_CTRL = SOUND_WAVE_VOL_25; | ||
1408 | // } break; | ||
1409 | // case 2: { | ||
1410 | // SOUND_WAVE_CTRL = SOUND_WAVE_VOL_50; | ||
1411 | // } break; | ||
1412 | // case 3: { | ||
1413 | // SOUND_WAVE_CTRL = SOUND_WAVE_VOL_75; | ||
1414 | // } break; | ||
1415 | // case 4: { | ||
1416 | // SOUND_WAVE_CTRL = SOUND_WAVE_VOL_100; | ||
1417 | // } break; | ||
1418 | // } | ||
1419 | static const u8 div_freq[] = { | ||
1420 | 7, 6, 5, 4, 7, 6, 5, 4, 7, 6, 5, 4, | ||
1421 | 7, 6, 5, 4, 7, 6, 5, 4, 7, 6, 5, 4, | ||
1422 | 7, 6, 5, 4, 7, 6, 5, 4, 7, 6, 5, 4, | ||
1423 | 7, 6, 5, 4, 7, 6, 5, 4, 7, 6, 5, 4, | ||
1424 | 7, 6, 5, 4, 7, 6, 5, 4, 3, 2, 1, 0, | ||
1425 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
1426 | }; | ||
1427 | static const u8 pre_freq[] = { | ||
1428 | 13, 13, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, | ||
1429 | 10, 10, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, | ||
1430 | 7, 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, | ||
1431 | 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 2, | ||
1432 | 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, | ||
1433 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
1434 | }; | ||
1435 | SOUND_NOISE_CTRL = SOUND_NOISE_ENV_VOL(0xF) | ||
1436 | | SOUND_NOISE_ENV_TIME(0x2) | ||
1437 | | SOUND_NOISE_ENV_DIR(0) | ||
1438 | | SOUND_NOISE_LENGTH(50); | ||
1439 | SOUND_NOISE_FREQ = SOUND_FREQ_RESET | ||
1440 | | SOUND_NOISE_PRESTEP_FREQ(pre_freq[trig->note]) | ||
1441 | | SOUND_NOISE_DIV_FREQ(div_freq[trig->note]) | ||
1442 | | SOUND_NOISE_COUNTER_STAGE(0) | ||
1443 | | SOUND_NOISE_TIMED_MODE(0); | ||
1444 | } else { | ||
1445 | SOUND_NOISE_FREQ = 0; | ||
1446 | } | ||
1447 | } else { | ||
1448 | SOUND_NOISE_CTRL = 0; | ||
1449 | SOUND_NOISE_FREQ = 0; | ||
1450 | } | ||
1275 | step_counter = (step_counter + 1) % 16; | 1451 | step_counter = (step_counter + 1) % 16; |
1276 | } | 1452 | } |
1277 | 1453 | ||
@@ -1301,6 +1477,9 @@ get_current_trig(void) { | |||
1301 | case 2: { | 1477 | case 2: { |
1302 | return &ch3.notes[trig_selection_loc]; | 1478 | return &ch3.notes[trig_selection_loc]; |
1303 | } break; | 1479 | } break; |
1480 | case 3: { | ||
1481 | return &ch4.notes[trig_selection_loc]; | ||
1482 | } break; | ||
1304 | } | 1483 | } |
1305 | return NULL; | 1484 | return NULL; |
1306 | } | 1485 | } |
@@ -1310,13 +1489,14 @@ get_current_trig(void) { | |||
1310 | // selection. | 1489 | // selection. |
1311 | void (*input_handler)(void); | 1490 | void (*input_handler)(void); |
1312 | 1491 | ||
1313 | #define SEQ_N_CHANNELS 3 | 1492 | #define SEQ_N_CHANNELS 4 |
1314 | 1493 | ||
1315 | void handle_trigger_selection(void); | 1494 | void handle_trigger_selection(void); |
1316 | void handle_channel_selection(void); | 1495 | void handle_channel_selection(void); |
1317 | void handle_param_selection_sq1(void); | 1496 | void handle_param_selection_sq1(void); |
1318 | void handle_param_selection_sq2(void); | 1497 | void handle_param_selection_sq2(void); |
1319 | void handle_param_selection_wave(void); | 1498 | void handle_param_selection_wave(void); |
1499 | void handle_param_selection_noise(void); | ||
1320 | 1500 | ||
1321 | void | 1501 | void |
1322 | handle_channel_selection(void) { | 1502 | handle_channel_selection(void) { |
@@ -1331,6 +1511,9 @@ handle_channel_selection(void) { | |||
1331 | case 2: { | 1511 | case 2: { |
1332 | ch3.active ^= 1; | 1512 | ch3.active ^= 1; |
1333 | } break; | 1513 | } break; |
1514 | case 3: { | ||
1515 | ch4.active ^= 1; | ||
1516 | } break; | ||
1334 | } | 1517 | } |
1335 | draw_channels(); | 1518 | draw_channels(); |
1336 | } | 1519 | } |
@@ -1683,6 +1866,181 @@ handle_param_selection_wave(void) { | |||
1683 | } | 1866 | } |
1684 | 1867 | ||
1685 | void | 1868 | void |
1869 | handle_param_selection_noise(void) { | ||
1870 | // Go back to trigger selection. | ||
1871 | // if (key_tap(KEY_A)) { | ||
1872 | // draw_params_cursor(param_selection_loc, COL_BG); | ||
1873 | // input_handler = handle_trigger_selection; | ||
1874 | // draw_trig_cursor(trig_selection_loc, COL_CURSOR); | ||
1875 | // } | ||
1876 | |||
1877 | // // Cursor movement. | ||
1878 | // if (key_tap(KEY_LEFT) || key_tap(KEY_RIGHT)) { | ||
1879 | // int inc = 0; | ||
1880 | // int loc = param_selection_loc; | ||
1881 | // if (key_tap(KEY_RIGHT)) { | ||
1882 | // if (loc == 15 || loc == 31) { | ||
1883 | // inc = 17; | ||
1884 | // } else if (loc == 47) { | ||
1885 | // inc = 26; | ||
1886 | // } else if (loc == 63) { | ||
1887 | // inc = 9; | ||
1888 | // } else if (loc != 47 && loc != 63 && loc < 72) { | ||
1889 | // inc = 1; | ||
1890 | // } | ||
1891 | // } else { | ||
1892 | // if (loc == 32 || loc == 48) { | ||
1893 | // inc = -17; | ||
1894 | // } else if (loc == 73) { | ||
1895 | // inc = -26; | ||
1896 | // } else if (loc != 16 && loc != 64) { | ||
1897 | // inc = -1; | ||
1898 | // } | ||
1899 | // } | ||
1900 | // draw_params_cursor(param_selection_loc, COL_BG); | ||
1901 | // param_selection_loc = CLAMP(loc + inc, 0, 73); | ||
1902 | // draw_params_cursor(param_selection_loc, COL_CURSOR); | ||
1903 | // } | ||
1904 | // if (key_tap(KEY_UP) || key_tap(KEY_DOWN)) { | ||
1905 | // int inc = 0; | ||
1906 | // int loc = param_selection_loc; | ||
1907 | // if (key_tap(KEY_UP)) { | ||
1908 | // if ((loc >= 16 && loc < 32) || (loc >= 48 && loc < 64)) { | ||
1909 | // inc = -16; | ||
1910 | // } else if (loc == 64) { | ||
1911 | // inc = -48; | ||
1912 | // } else if (loc == 65) { | ||
1913 | // inc = -45; | ||
1914 | // } else if (loc == 66) { | ||
1915 | // inc = -42; | ||
1916 | // } else if (loc == 67) { | ||
1917 | // inc = -39; | ||
1918 | // } else if (loc == 68) { | ||
1919 | // inc = -20; | ||
1920 | // } else if (loc == 69) { | ||
1921 | // inc = -17; | ||
1922 | // } else if (loc == 70) { | ||
1923 | // inc = -14; | ||
1924 | // } else if (loc == 71) { | ||
1925 | // inc = -11; | ||
1926 | // } else if (loc == 72) { | ||
1927 | // inc = 1; | ||
1928 | // } else if (loc == 73) { | ||
1929 | // inc = -1; | ||
1930 | // } | ||
1931 | // } else { | ||
1932 | // if (loc < 16 || (loc >= 32 && loc < 48)) { | ||
1933 | // inc = 16; | ||
1934 | // } else if (loc >= 16 && loc <= 19) { | ||
1935 | // inc = 48 - (loc - 16); | ||
1936 | // } else if (loc >= 20 && loc <= 23) { | ||
1937 | // inc = 45 - (loc - 20); | ||
1938 | // } else if (loc >= 24 && loc <= 27) { | ||
1939 | // inc = 42 - (loc - 24); | ||
1940 | // } else if (loc >= 28 && loc <= 31) { | ||
1941 | // inc = 39 - (loc - 28); | ||
1942 | // } else if (loc >= 48 && loc <= 51) { | ||
1943 | // inc = 20 - (loc - 48); | ||
1944 | // } else if (loc >= 52 && loc <= 55) { | ||
1945 | // inc = 17 - (loc - 52); | ||
1946 | // } else if (loc >= 56 && loc <= 59) { | ||
1947 | // inc = 14 - (loc - 56); | ||
1948 | // } else if (loc >= 60 && loc <= 63) { | ||
1949 | // inc = 11 - (loc - 60); | ||
1950 | // } else if (loc == 72) { | ||
1951 | // inc = 1; | ||
1952 | // } else if (loc == 73) { | ||
1953 | // inc = -1; | ||
1954 | // } | ||
1955 | // } | ||
1956 | // draw_params_cursor(param_selection_loc, COL_BG); | ||
1957 | // param_selection_loc = CLAMP(loc + inc, 0, 73); | ||
1958 | // draw_params_cursor(param_selection_loc, COL_CURSOR); | ||
1959 | // } | ||
1960 | |||
1961 | // // Adjust parameter. | ||
1962 | // if (key_tap(KEY_R) || key_tap(KEY_L)) { | ||
1963 | // int odd = param_selection_loc & 0x1; | ||
1964 | // int inc; | ||
1965 | // if (key_tap(KEY_R)) { | ||
1966 | // inc = 1; | ||
1967 | // } else { | ||
1968 | // inc = -1; | ||
1969 | // } | ||
1970 | |||
1971 | // // Wave: AA BB CC DD ... | ||
1972 | // // ^^ | ||
1973 | // // |`- odd | ||
1974 | // // `-- even | ||
1975 | // if (param_selection_loc < 32) { | ||
1976 | // // Draw on wave a. | ||
1977 | // u8 byte_number = param_selection_loc / 2; | ||
1978 | // u8 *byte = &ch3.params[trig_selection_loc].wave_a; | ||
1979 | // byte += byte_number; | ||
1980 | // if (odd) { | ||
1981 | // *byte = (~0xF & *byte) | ((*byte + inc) & 0xF); | ||
1982 | // } else { | ||
1983 | // *byte = (0xF & *byte) | (((*byte >> 4) + inc) & 0xF) << 4; | ||
1984 | // } | ||
1985 | // } else if (param_selection_loc < 64){ | ||
1986 | // // Draw on wave b. | ||
1987 | // u8 byte_number = (param_selection_loc - 32) / 2; | ||
1988 | // u8 *byte = &ch3.params[trig_selection_loc].wave_b; | ||
1989 | // byte += byte_number; | ||
1990 | // if (odd) { | ||
1991 | // *byte = (~0xF & *byte) | ((*byte + inc) & 0xF); | ||
1992 | // } else { | ||
1993 | // *byte = (0xF & *byte) | (((*byte >> 4) + inc) & 0xF) << 4; | ||
1994 | // } | ||
1995 | // } else if (param_selection_loc < 72) { | ||
1996 | // // Copy default waves. | ||
1997 | // u32 *wave_a = &ch3.params[trig_selection_loc].wave_a; | ||
1998 | // u32 *wave_b = &ch3.params[trig_selection_loc].wave_b; | ||
1999 | // switch (param_selection_loc) { | ||
2000 | // case 64: { | ||
2001 | // memcpy32(wave_a, sine_wave, 16); | ||
2002 | // } break; | ||
2003 | // case 65: { | ||
2004 | // memcpy32(wave_a, saw_wave, 16); | ||
2005 | // } break; | ||
2006 | // case 66: { | ||
2007 | // memcpy32(wave_a, square_wave, 16); | ||
2008 | // } break; | ||
2009 | // case 67: { | ||
2010 | // u32 rand_wave[4] = { | ||
2011 | // rng32(), rng32(), rng32(), rng32(), | ||
2012 | // }; | ||
2013 | // memcpy32(wave_a, rand_wave, 16); | ||
2014 | // } break; | ||
2015 | // case 68: { | ||
2016 | // memcpy32(wave_b, sine_wave, 16); | ||
2017 | // } break; | ||
2018 | // case 69: { | ||
2019 | // memcpy32(wave_b, saw_wave, 16); | ||
2020 | // } break; | ||
2021 | // case 70: { | ||
2022 | // memcpy32(wave_b, square_wave, 16); | ||
2023 | // } break; | ||
2024 | // case 71: { | ||
2025 | // u32 rand_wave[4] = { | ||
2026 | // rng32(), rng32(), rng32(), rng32(), | ||
2027 | // }; | ||
2028 | // memcpy32(wave_b, rand_wave, 16); | ||
2029 | // } break; | ||
2030 | // } | ||
2031 | // } else if (param_selection_loc == 72) { | ||
2032 | // u8 *wave_mode = &ch3.params[trig_selection_loc].wave_mode; | ||
2033 | // *wave_mode = CLAMP(*wave_mode + inc, 0, 2); | ||
2034 | // } else if (param_selection_loc == 73) { | ||
2035 | // u8 *wave_volume = &ch3.params[trig_selection_loc].wave_volume; | ||
2036 | // *wave_volume = CLAMP(*wave_volume + inc, 0, 4); | ||
2037 | // } | ||
2038 | // draw_parameters(); | ||
2039 | // draw_params_cursor(param_selection_loc, COL_CURSOR); | ||
2040 | // } | ||
2041 | } | ||
2042 | |||
2043 | void | ||
1686 | handle_trigger_selection(void) { | 2044 | handle_trigger_selection(void) { |
1687 | TriggerNote *trig = get_current_trig(); | 2045 | TriggerNote *trig = get_current_trig(); |
1688 | 2046 | ||
@@ -1758,6 +2116,9 @@ handle_trigger_selection(void) { | |||
1758 | case 2: { | 2116 | case 2: { |
1759 | input_handler = handle_param_selection_wave; | 2117 | input_handler = handle_param_selection_wave; |
1760 | } break; | 2118 | } break; |
2119 | case 3: { | ||
2120 | input_handler = handle_param_selection_noise; | ||
2121 | } break; | ||
1761 | } | 2122 | } |
1762 | draw_params_cursor(param_selection_loc, COL_CURSOR); | 2123 | draw_params_cursor(param_selection_loc, COL_CURSOR); |
1763 | draw_trig_cursor(trig_selection_loc, COL_CURRENT_TRIG); | 2124 | draw_trig_cursor(trig_selection_loc, COL_CURRENT_TRIG); |
@@ -1779,6 +2140,7 @@ handle_sequencer_input(void) { | |||
1779 | SOUND_SQUARE1_CTRL = 0; | 2140 | SOUND_SQUARE1_CTRL = 0; |
1780 | SOUND_SQUARE2_CTRL = 0; | 2141 | SOUND_SQUARE2_CTRL = 0; |
1781 | SOUND_WAVE_CTRL = 0; | 2142 | SOUND_WAVE_CTRL = 0; |
2143 | SOUND_NOISE_CTRL = 0; | ||
1782 | } | 2144 | } |
1783 | } else if (key_tap(KEY_SELECT)) { | 2145 | } else if (key_tap(KEY_SELECT)) { |
1784 | // Play/pause. | 2146 | // Play/pause. |
@@ -1786,6 +2148,7 @@ handle_sequencer_input(void) { | |||
1786 | SOUND_SQUARE1_CTRL = 0; | 2148 | SOUND_SQUARE1_CTRL = 0; |
1787 | SOUND_SQUARE2_CTRL = 0; | 2149 | SOUND_SQUARE2_CTRL = 0; |
1788 | SOUND_WAVE_CTRL = 0; | 2150 | SOUND_WAVE_CTRL = 0; |
2151 | SOUND_NOISE_CTRL = 0; | ||
1789 | } | 2152 | } |
1790 | } | 2153 | } |
1791 | 2154 | ||
@@ -1808,6 +2171,9 @@ sequencer_init(void) { | |||
1808 | TriggerNote *trig = get_current_trig(); | 2171 | TriggerNote *trig = get_current_trig(); |
1809 | draw_note(trig->note, COL_NOTE_PRESSED); | 2172 | draw_note(trig->note, COL_NOTE_PRESSED); |
1810 | 2173 | ||
2174 | // Draw screen border frame. | ||
2175 | draw_rect(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 1); | ||
2176 | |||
1811 | // Initialize input handler. | 2177 | // Initialize input handler. |
1812 | input_handler = handle_trigger_selection; | 2178 | input_handler = handle_trigger_selection; |
1813 | draw_trig_cursor(trig_selection_loc, COL_CURSOR); | 2179 | draw_trig_cursor(trig_selection_loc, COL_CURSOR); |
@@ -1818,6 +2184,9 @@ sequencer_init(void) { | |||
1818 | SOUND_STATUS = SOUND_ENABLE; | 2184 | SOUND_STATUS = SOUND_ENABLE; |
1819 | SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 | 2185 | SOUND_DMG_MASTER = sound_volume(SOUND_SQUARE1 |
1820 | | SOUND_SQUARE2 | 2186 | | SOUND_SQUARE2 |
1821 | | SOUND_WAVE, 3); | 2187 | | SOUND_WAVE |
2188 | | SOUND_NOISE, 3); | ||
1822 | SOUND_DSOUND_MASTER = SOUND_DMG25; | 2189 | SOUND_DSOUND_MASTER = SOUND_DMG25; |
2190 | // SOUND_NOISE_CTRL = SOUND_NOISE_ENV_VOL(0x8) | SOUND_NOISE_ENV_TIME(0) | SOUND_NOISE_ENV_DIR(1) | 0x4; | ||
2191 | // SOUND_NOISE_FREQ = SOUND_FREQ_RESET | SOUND_NOISE_PRESTEP_FREQ(0x7) | SOUND_NOISE_DIV_FREQ(2) | SOUND_NOISE_COUNTER_STAGE(1); | ||
1823 | } | 2192 | } |