// // Globals. // static int step_counter = 0; int trig_selection_loc = 0; int param_selection_loc = 0; int channel_selection_loc = 0; int pattern_selection_loc = 0; int right_col_selection_loc = 0; int play_status = 0; int current_pattern = 0; int next_pattern = 0; int current_bank = 0; int next_bank = 0; u32 last_trig_loc = 0; u32 last_channel_loc = 0; u32 last_pattern_loc = 0; u32 last_right_col_loc = 0; u32 last_step_counter = 0; bool clear_screen = true; // // Color indexes. // #define COL_BG 0 #define COL_FG 1 #define COL_ACC_0 2 #define COL_ACC_1 3 #define COL_ACC_2 4 #define COL_OFF 5 #define CHAN_W 18 #define CHAN_H 8 #define CHAN_START_X 28 #define CHAN_START_Y 100 #define CHAN_OFFSET_Y 15 #define TRIG_W 15 #define TRIG_H 22 #define TRIG_START_X 55 #define TRIG_START_Y 100 #define TRIG_OFFSET_X (TRIG_W + 3) #define TRIG_OFFSET_Y (TRIG_H + 8) #define PIANO_W 170 #define PIANO_H 12 #define PIANO_BLACK_H 10 #define PIANO_START_X 27 #define PIANO_START_Y 80 #define PIANO_NOTE_W 2 #define NOTIF_W 170 #define NOTIF_H 10 #define NOTIF_START_X 27 #define NOTIF_START_Y 12 #define PARAMS_W 166 #define PARAMS_H 56 #define PARAMS_START_X 29 #define PARAMS_START_Y 20 #define PARAMS_BOX_W 30 #define PARAMS_BOX_H 24 #define PARAMS_BOX_OFFSET_X (PARAMS_BOX_W + 4) #define PARAMS_BOX_OFFSET_Y (PARAMS_BOX_H + 4) #define R_SIDEBAR_X ((TRIG_START_X) + (TRIG_OFFSET_X) * 8 + 8) #define PAT_START_X 5 #define PAT_START_Y 16 #define PAT_W 14 #define PAT_H 10 #define PAT_OFFSET_Y 18 #define R_COL_W 30 #define BPM_START_X (R_SIDEBAR_X - 2) #define BPM_START_Y (TRIG_START_Y + 8) #define BPM_H 15 #define SCALE_START_X (R_SIDEBAR_X - 2) #define SCALE_START_Y (PIANO_START_Y) #define SCALE_H 15 #define SETTINGS_START_X (R_SIDEBAR_X - 4) #define SETTINGS_START_Y (TRIG_START_Y + 30) #define PLAY_START_X (R_SIDEBAR_X - 2) #define PLAY_START_Y (TRIG_START_Y + 44) #define STOP_START_X (R_SIDEBAR_X + 14) #define STOP_START_Y (TRIG_START_Y + 44) #define PLAY_STOP_W (12) #define PLAY_STOP_H (8) #define BANK_START_X (R_SIDEBAR_X + 5) #define BANK_START_Y (PAT_START_Y) #define BANK_W 12 #define BANK_H 10 #define PAT_TRIG_W 14 #define PAT_TRIG_H 14 #define PAT_TRIG_START_X 32 #define PAT_TRIG_START_Y 37 #define PAT_TRIG_OFFSET_X (PAT_TRIG_W + 7) #define PAT_TRIG_OFFSET_Y (PAT_TRIG_H + 8) #define SEQ_N_CHANNELS 4 enum RIGHT_COL_LOC { R_COL_BANK_A = 0, R_COL_BANK_B = 1, R_COL_BANK_C = 2, R_COL_BANK_D = 3, R_COL_BANK_E = 4, R_COL_BANK_F = 5, R_COL_SCALE = 6, R_COL_BPM = 7, R_COL_SETTINGS = 8, R_COL_PLAY = 9, R_COL_STOP = 10, R_COL_END, }; // Input handling works using a FSM. The input handler is switched to whichever // function controls each section. For example, channel selection or trigger // selection. typedef void (*InputHandler)(void); InputHandler input_handler; void handle_trigger_selection(void); void handle_channel_selection(void); void handle_pattern_selection(void); void handle_param_selection_sq1(void); void handle_param_selection_sq2(void); void handle_param_selection_wave(void); void handle_param_selection_noise(void); void handle_right_col_selection(void); void handle_param_selection_ch1(void); void handle_param_selection_ch2(void); void handle_param_selection_ch3(void); void handle_param_selection_ch4(void); void handle_pattern_chain(void); typedef enum Scene { SCENE_SEQUENCER = 0, SCENE_SETTINGS, } Scene; static Scene scene = SCENE_SEQUENCER; static Scene next_scene = SCENE_SEQUENCER; typedef struct Notification { // We can only fit 31 characters on the notification bar at the moment. // Leaving an extra character for \0. char msg[32]; s16 time; } Notification; static Notification notif = {0}; #define NOTIF_TIME (80 + 32) #define MAX_CHAIN 16 typedef struct Chain { u8 chain[MAX_CHAIN]; u8 active[MAX_CHAIN]; u8 len; u8 current; u8 playing; u8 enabled; } Chain; typedef enum ChainButtons { CHAIN_BTN_ENABLE = 16, CHAIN_BTN_CLEAR = 17, CHAIN_BTN_RANDOM = 18, } ChainButtons; static Chain chain = {0}; typedef enum Prob { PROB_FOUR_FOUR, PROB_THREE_FOUR, PROB_TWO_FOUR, PROB_ONE_FOUR, PROB_THREE_THREE, PROB_TWO_THREE, PROB_ONE_THREE, PROB_TWO_TWO, PROB_ONE_TWO, PROB_NOT_FIRST, PROB_FIRST, PROB_100, PROB_80, PROB_60, PROB_40, PROB_20, PROB_NUM, } Prob; bool redraw_pattern_buttons = true; bool redraw_play_pause = true; bool redraw_trigs = true; bool redraw_channels = true; bool redraw_bank_buttons = true; bool redraw_params = true; bool redraw_bpm = true; bool redraw_scale = true; bool update_bpm = false; u8 bar_counter = 0; typedef enum WaveEnv { WAV_ENV_START, WAV_ENV_ATTACK, WAV_ENV_DECAY, WAV_ENV_END, WAV_ENV_OFF, } WaveEnv; enum WAVES { WAVE_SIN, WAVE_SAW, WAVE_SQUARE, WAVE_MAX, }; #define WAVE_SIZE 4 #define WAVE_VARS 4 typedef u32 Wave[WAVE_SIZE]; static WaveEnv wave_env = WAV_ENV_OFF; static const Wave *wave_target; static u32 wave_freq; static int wave_env_ticks = 0; static int wave_env_attack = 8; static int wave_env_decay = 8; static int wave_env_prog = 0; static Wave current_wave[8] = {0};