From 7bccc14ea476b380ab77f05463fad1cb57149e58 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Tue, 11 May 2021 14:30:12 +0200 Subject: Add default wave patterns in channel 3 --- src/main.c | 1 + src/rng.c | 15 ++++ src/sequencer.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 212 insertions(+), 43 deletions(-) create mode 100644 src/rng.c diff --git a/src/main.c b/src/main.c index d4d49cc..636d5c4 100644 --- a/src/main.c +++ b/src/main.c @@ -18,6 +18,7 @@ int main(void) { DISP_CTRL = DISP_ENABLE_SPRITES | DISP_MODE_4 | DISP_BG_2; // DISP_CTRL = DISP_ENABLE_SPRITES | DISP_MODE_3 | DISP_BG_2; + // PAL_BUFFER_BG[0] = COLOR_BLUE; PAL_BUFFER_BG[1] = COLOR_WHITE; PAL_BUFFER_BG[2] = COLOR_RED; PAL_BUFFER_BG[3] = COLOR_CYAN; diff --git a/src/rng.c b/src/rng.c new file mode 100644 index 0000000..96760b8 --- /dev/null +++ b/src/rng.c @@ -0,0 +1,15 @@ +u16 rng_state; + +u32 hash16(u32 input, u32 key) { + u32 hash = input * key; + return ((hash >> 16) ^ hash) & 0xFFFF; +} + +u16 rng16() { + rng_state += 0xbadd; + return hash16(rng_state, 0x10de); +} + +u32 rng32() { + return (rng16() << 16) | rng16(); +} diff --git a/src/sequencer.c b/src/sequencer.c index fa44eae..867d3e4 100644 --- a/src/sequencer.c +++ b/src/sequencer.c @@ -1,26 +1,31 @@ #include "bitmap.h" +#include "rng.c" // Positioning parameters. #define SEQ_TRIG_POS_X 45 -#define SEQ_TRIG_POS_Y 50 +#define SEQ_TRIG_POS_Y 58 #define SEQ_TRIG_DIST_X 18 #define SEQ_TRIG_DIST_Y 28 #define SEQ_CHANNEL_POS_X SEQ_TRIG_POS_X - 32 #define SEQ_CHANNEL_POS_Y SEQ_TRIG_POS_Y #define SEQ_CHANNEL_DIST_Y 11 #define SEQ_ENV_POS_X 10 -#define SEQ_ENV_POS_Y 10 +#define SEQ_ENV_POS_Y 18 #define SEQ_ENV_DIST 32 #define SEQ_DUTYCYCLE_POS_X SEQ_ENV_POS_X + SEQ_ENV_DIST * 3 -#define SEQ_DUTYCYCLE_POS_Y 10 - 8 +#define SEQ_DUTYCYCLE_POS_Y SEQ_ENV_POS_Y - 8 #define SEQ_SWEEP_POS_X SEQ_DUTYCYCLE_POS_X + SEQ_ENV_DIST #define SEQ_SWEEP_POS_Y SEQ_ENV_POS_Y #define SEQ_CH3_PARAM_X SEQ_TRIG_POS_X -#define SEQ_CH3_PARAM_Y SEQ_ENV_POS_Y +#define SEQ_CH3_PARAM_Y SEQ_ENV_POS_Y - 12 #define SEQ_CH3_PARAM_SEL_X SEQ_CH3_PARAM_X - 5 #define SEQ_CH3_PARAM_SEL_Y SEQ_CH3_PARAM_Y + 22 #define SEQ_N_CHANNELS 3 +// +// Sprite data. +// + u32 sprite_note_names[] = { 0x000000e0, 0x202020e0, 0x0000000e, 0x080e020e, 0x00000098, 0xa8a8a898, 0x00000038, 0x203b0a39, @@ -108,6 +113,12 @@ u32 sprite_trigger_active_indicator[] = { 0x00000000, 0x00f80000, }; +u32 sprite_ch_3_parameter_selection[] = { + 0x00000000, 0x00f80000, + 0xfe000000, 0x00000000, + 0x7f000000, 0x00000000, +}; + u32 sprite_trigger_selection[] = { 0x0f010101, 0x00000000, 0x80000000, 0x00000000, 0x07040404, 0x00000000, 0x00000000, 0x00000000, @@ -266,6 +277,17 @@ u32 sprite_channels_selector[] = { 0x00000000, 0x00000000, 0x0008080e, 0x00000000, }; +u32 sprite_default_wave[] = { + 0xff013149, 0x850101ff, 0x3f202028, 0x2423203f, + 0xff016151, 0x49c501ff, 0x3f202c2a, 0x2928203f, + 0xff017d45, 0x45c501ff, 0x3f202828, 0x282f203f, + 0xff014911, 0x812501ff, 0x3f202128, 0x2420203f, +}; + +// +// Wave data. +// + u8 sine_wave[] = { 0x89, 0xBC, 0xDE, 0xEF, 0xFE, 0xED, 0xCB, 0x98, @@ -280,6 +302,13 @@ u8 saw_wave[16] = { 0x89, 0xab, 0xcd, 0xef, }; +u8 square_wave[16] = { + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + // TODO: Should we split this up in individual trigger structs depending on the // channel? typedef struct SeqTrigger { @@ -367,13 +396,9 @@ static SeqTrigger sequences[3][16] = { // well or the note/duration. // TODO: Allow muting and unmuting channels. Show in grey when muted. // TODO: Show channel beat indicator if a note is being played. -// TODO: Parameters should change depending on the selected channel. For -// example, we may want to hide the sweep parameters for synth 2. +// TODO: Enable control on channel 4. // TODO: Research a way of having pattern chains. -// TODO: Enable control on channels 3-4. // TODO: Study how to save patterns and chains. -// TODO: Wave channel should have a default (sine, saw, square) and/or maybe -// some buttons for set those values. static int bpm = 115; static int step_counter = 0; @@ -418,9 +443,9 @@ irq_timer_0(void) { // TODO: Should we compare if previous and current wave are the // same before updating? SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(1); - memcpy(SOUND_WAVE_RAM, trig->wave_a, 32); + memcpy(SOUND_WAVE_RAM, trig->wave_a, 16); SOUND_WAVE_MODE = SOUND_WAVE_BANK_SELECT(0); - memcpy(SOUND_WAVE_RAM, trig->wave_b, 32); + memcpy(SOUND_WAVE_RAM, trig->wave_b, 16); switch (trig->wave_mode) { case 0: { @@ -528,6 +553,7 @@ set_time(int bpm) { // - 055-055 RESERVED: FM synth?. // - 056-056 channel selector. // - 057-057 ch3 selector. +// - 058-066 ch3 default wave buttons. // @@ -550,11 +576,11 @@ typedef enum { } SeqSelect; int trig_selection_loc = 0; -int param_selection_loc = 0; +int param_selection_loc = 64; int channel_selection_loc = 2; SeqSelect current_selection = SEQ_SELECT_TRIGGER; -SeqSprite seq_sprites[58] = {0}; +SeqSprite seq_sprites[66] = {0}; void draw_wave_pattern(u8 *pattern, int x, int y, u16 clr_idx) { @@ -628,16 +654,6 @@ init_sequencer_sprites(void) { seq_sprites[32].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); seq_sprites[32].obj_attr_2 = base_tile | OBJ_PAL_BANK(1); } - { - int x = SEQ_CH3_PARAM_SEL_X; - int y = SEQ_CH3_PARAM_SEL_Y; - int base_tile = sprites[sprite_id].tile_start; - seq_sprites[57].id = obj_counter++; - seq_sprites[57].base_tile = base_tile; - seq_sprites[57].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); - seq_sprites[57].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); - seq_sprites[57].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); - } sprite_id = load_packed_sprite_data(&sprite_trigger_selection, 16, 1); { @@ -910,12 +926,46 @@ init_sequencer_sprites(void) { int base_tile = sprites[sprite_id].tile_start; seq_sprites[56].id = obj_counter++; seq_sprites[56].base_tile = base_tile; - // TODO: Start hidden. - // seq_sprites[55].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; - seq_sprites[56].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[56].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | OBJ_HIDDEN; seq_sprites[56].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); seq_sprites[56].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); } + + sprite_id = load_packed_sprite_data(&sprite_ch_3_parameter_selection, 3, 1); + { + int x = SEQ_CH3_PARAM_SEL_X; + int y = SEQ_CH3_PARAM_SEL_Y; + int base_tile = sprites[sprite_id].tile_start; + seq_sprites[57].id = obj_counter++; + seq_sprites[57].base_tile = base_tile; + seq_sprites[57].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); + seq_sprites[57].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[57].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); + } + + sprite_id = load_packed_sprite_data(&sprite_default_wave, 2, 4); + // Wave A + for (size_t i = 0; i < 4; ++i) { + int x = SEQ_CH3_PARAM_X + 17 * i; + int y = SEQ_CH3_PARAM_Y + 37; + int base_tile = sprites[sprite_id].tile_start + i * 2 % 8; + seq_sprites[58 + i].id = obj_counter++; + seq_sprites[58 + i].base_tile = base_tile; + seq_sprites[58 + i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[58 + i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[58 + i].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); + } + // Wave B + for (size_t i = 0; i < 4; ++i) { + int x = SEQ_CH3_PARAM_X + 17 * i + 76; + int y = SEQ_CH3_PARAM_Y + 37; + int base_tile = sprites[sprite_id].tile_start + i * 2 % 8; + seq_sprites[58 + 4 + i].id = obj_counter++; + seq_sprites[58 + 4 + i].base_tile = base_tile; + seq_sprites[58 + 4 + i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); + seq_sprites[58 + 4 + i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[58 + 4 + i].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); + } } bool update_params_screen = true; @@ -1040,7 +1090,7 @@ update_sequencer_sprites(void) { int x = SEQ_CHANNEL_POS_X; int y = SEQ_CHANNEL_POS_Y - 2; y += (channel_selection_loc % SEQ_N_CHANNELS * SEQ_CHANNEL_DIST_Y); - seq_sprites[56].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y); + seq_sprites[56].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y); seq_sprites[56].obj_attr_1 = OBJ_SIZE_BIG | OBJ_X_COORD(x); int base_tile = seq_sprites[56].base_tile; if (current_selection == SEQ_SELECT_CHANNEL) { @@ -1090,35 +1140,81 @@ update_sequencer_sprites(void) { // Update parameter selection. { u8 x_positions[] = { + // 32 half bytes (Wave A). 0, 4, 8, 12, 16, 20, 24, 28, 36, 40, 44, 48, 52, 56, 60, 64, 0, 4, 8, 12, 16, 20, 24, 28, 36, 40, 44, 48, 52, 56, 60, 64, + // 32 half bytes (Wave B). 76, 80, 84, 88, 92, 96, 100, 104, 112, 116, 120, 124, 128, 132, 136, 140, 76, 80, 84, 88, 92, 96, 100, 104, 112, 116, 120, 124, 128, 132, 136, 140, + // Default wave A. + 4, 21, 38, 55, + // Default wave B. + 80, 97, 114, 131, }; u8 y_positions[] = { + // 32 half bytes (Wave A) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + // 32 half bytes (Wave B) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + // Default wave A. + 23, 23, 23, 23, + // Default wave B. + 23, 23, 23, 23, }; - int x = SEQ_CH3_PARAM_SEL_X + x_positions[param_selection_loc]; - int y = SEQ_CH3_PARAM_SEL_Y + y_positions[param_selection_loc]; - int base_tile = seq_sprites[57].base_tile; - int hidden = 0; - if (current_selection != SEQ_SELECT_PARAMETER) { - hidden = OBJ_HIDDEN; + { + int x = SEQ_CH3_PARAM_SEL_X + x_positions[param_selection_loc]; + int y = SEQ_CH3_PARAM_SEL_Y + y_positions[param_selection_loc]; + int base_tile = seq_sprites[57].base_tile; + int shape = OBJ_SHAPE_SQUARE; + int hidden = 0; + if (current_selection != SEQ_SELECT_PARAMETER) { + hidden = OBJ_HIDDEN; + } + if (param_selection_loc >= 64) { + shape = OBJ_SHAPE_WIDE; + base_tile += 1; + } + seq_sprites[57].obj_attr_0 = shape | OBJ_Y_COORD(y) | hidden; + seq_sprites[57].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[57].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); + } + + // Wave A + for (size_t i = 0; i < 4; ++i) { + int x = SEQ_CH3_PARAM_X + 17 * i; + int y = SEQ_CH3_PARAM_Y + 37; + int base_tile = seq_sprites[58 + i].base_tile; + int hidden = 0; + if (current_selection == SEQ_SELECT_CHANNEL) { + hidden = OBJ_HIDDEN; + } + seq_sprites[58 + i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | hidden; + seq_sprites[58 + i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[58 + i].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); + } + // Wave B + for (size_t i = 0; i < 4; ++i) { + int x = SEQ_CH3_PARAM_X + 17 * i + 76; + int y = SEQ_CH3_PARAM_Y + 37; + int base_tile = seq_sprites[58 + 4 + i].base_tile; + int hidden = 0; + if (current_selection == SEQ_SELECT_CHANNEL) { + hidden = OBJ_HIDDEN; + } + seq_sprites[58 + 4 + i].obj_attr_0 = OBJ_SHAPE_WIDE | OBJ_Y_COORD(y) | hidden; + seq_sprites[58 + 4 + i].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); + seq_sprites[58 + 4 + i].obj_attr_2 = base_tile | OBJ_PAL_BANK(0); } - seq_sprites[57].obj_attr_0 = OBJ_SHAPE_SQUARE | OBJ_Y_COORD(y) | hidden; - seq_sprites[57].obj_attr_1 = OBJ_SIZE_SMALL | OBJ_X_COORD(x); - seq_sprites[57].obj_attr_2 = base_tile | OBJ_PAL_BANK(2); } } @@ -1159,6 +1255,9 @@ update_sequencer_sprites(void) { for (size_t i = 34; i <= 50; ++i) { seq_sprites[i].obj_attr_0 |= OBJ_HIDDEN; } + for (size_t i = 58; i <= 66; ++i) { + seq_sprites[i].obj_attr_0 |= OBJ_HIDDEN; + } flip_page(); clear_screen_m4(); } @@ -1262,33 +1361,65 @@ handle_sequencer_input(void) { int inc = 0; int loc = param_selection_loc; if (key_pressed(KEY_RIGHT)) { - if (loc == 15 || loc == 32) { + if (loc == 15 || loc == 31) { inc = 17; - } else if (loc != 47){ + } else if (loc != 47 && loc != 63){ inc = 1; } } else { if (loc == 32 || loc == 48) { inc = -17; - } else if (loc != 16){ + } else if (loc != 16 && loc != 64){ inc = -1; } } - param_selection_loc = CLAMP(loc + inc, 0, 63); + param_selection_loc = CLAMP(loc + inc, 0, 71); } if (key_pressed(KEY_UP) || key_pressed(KEY_DOWN)) { int inc = 0; int loc = param_selection_loc; if (key_pressed(KEY_UP)) { - if ((loc >= 16 && loc < 32) || (loc >= 48)) { + if ((loc >= 16 && loc < 32) || (loc >= 48 && loc < 64)) { inc = -16; + } else if (loc == 64) { + inc = -48; + } else if (loc == 65) { + inc = -45; + } else if (loc == 66) { + inc = -42; + } else if (loc == 67) { + inc = -39; + } else if (loc == 68) { + inc = -20; + } else if (loc == 69) { + inc = -17; + } else if (loc == 70) { + inc = -14; + } else if (loc == 71) { + inc = -11; } } else { if (loc < 16 || (loc >= 32 && loc < 48)) { inc = 16; + } else if (loc >= 16 && loc <= 19){ + inc = 48 - (loc - 16); + } else if (loc >= 20 && loc <= 23){ + inc = 45 - (loc - 20); + } else if (loc >= 24 && loc <= 27){ + inc = 42 - (loc - 24); + } else if (loc >= 28 && loc <= 31){ + inc = 39 - (loc - 28); + } else if (loc >= 48 && loc <= 51){ + inc = 20 - (loc - 48); + } else if (loc >= 52 && loc <= 55){ + inc = 17 - (loc - 52); + } else if (loc >= 56 && loc <= 59){ + inc = 14 - (loc - 56); + } else if (loc >= 60 && loc <= 63){ + inc = 11 - (loc - 60); } } - param_selection_loc = CLAMP(loc + inc, 0, 63); + param_selection_loc = CLAMP(loc + inc, 0, 71); } if (key_pressed(KEY_R) || key_pressed(KEY_L)) { int odd = param_selection_loc & 0x1; @@ -1311,7 +1442,7 @@ handle_sequencer_input(void) { byte = (0xF & byte) | (((byte >> 4) + inc) & 0xF) << 4; } sequences[2][trig_selection_loc].wave_a[byte_number] = byte; - } else { + } else if (param_selection_loc < 64){ u8 byte_number = (param_selection_loc - 32) >> 1; u8 byte = sequences[2][trig_selection_loc].wave_b[byte_number]; if (odd) { @@ -1320,6 +1451,28 @@ handle_sequencer_input(void) { byte = (0xF & byte) | ((byte >> 4) + inc) << 4; } sequences[2][trig_selection_loc].wave_b[byte_number] = byte; + } else if (param_selection_loc == 64){ + memcpy(&trig->wave_a, &sine_wave, 16); + } else if (param_selection_loc == 65){ + memcpy(&trig->wave_a, &saw_wave, 16); + } else if (param_selection_loc == 66){ + memcpy(&trig->wave_a, &square_wave, 16); + } else if (param_selection_loc == 67){ + u32 rand_wave[4] = { + rng32(), rng32(), rng32(), rng32(), + }; + memcpy(&trig->wave_a, &rand_wave, 16); + } else if (param_selection_loc == 68){ + memcpy(&trig->wave_b, &sine_wave, 16); + } else if (param_selection_loc == 69){ + memcpy(&trig->wave_b, &saw_wave, 16); + } else if (param_selection_loc == 70){ + memcpy(&trig->wave_b, &square_wave, 16); + } else if (param_selection_loc == 71){ + u32 rand_wave[4] = { + rng32(), rng32(), rng32(), rng32(), + }; + memcpy(&trig->wave_b, &rand_wave, 16); } } } -- cgit v1.2.1