Added drums pattern editor

This commit is contained in:
Daniele Lacamera 2020-04-23 22:19:22 +02:00
parent d4749d2fe9
commit 3b2641fdcd
10 changed files with 190 additions and 23 deletions

View file

@ -5,7 +5,7 @@ VERSION?=1
OBJS:=startup.o main.o system.o mem.o led.o \ OBJS:=startup.o main.o system.o mem.o led.o \
i2c.o display.o font_twisted.o button.o systick.o newlib.o uart.o ui.o timer.o\ i2c.o display.o font_twisted.o button.o systick.o newlib.o uart.o ui.o timer.o\
mutex.o ui_drone.o adc.o spi.o pot.o dac.o sound.o drone.o settings.o mutex.o ui_drone.o adc.o spi.o pot.o dac.o sound.o drone.o settings.o ui_pattern.o
UMX:=lib/unicore-mx/lib/libucmx_stm32f4.a UMX:=lib/unicore-mx/lib/libucmx_stm32f4.a

33
drone.c
View file

@ -13,16 +13,36 @@
#include "drone.h" #include "drone.h"
#include "drums.h" #include "drums.h"
#include "pot.h" #include "pot.h"
#include "settings.h"
static struct drone_slot drone_pattern[MAX_PATTERN_LEN] = { #define MUTE { 0 , 0 }
static struct drone_slot drone_pattern[MAX_PATTERN_LEN] = {
{ 28, 10 }, { 28, 20}, {36,20}, {40,20}, { 28, 10 }, { 28, 20}, {36,20}, {40,20},
{ 40, 10 }, { 40, 10}, {36, 10}, {32,10} { 40, 10 }, { 40, 10}, {36, 10}, {32,10},
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
MUTE, MUTE, MUTE, MUTE,
}; };
void drone_mute(void) void drone_mute(void)
{ {
pot_set(0, 0xFF); pot_set(0, 0);
pot_set(1, 0x0); pot_set(1, 99);
} }
void drone_beat(int pattern_pos) void drone_beat(int pattern_pos)
@ -34,7 +54,10 @@ void drone_beat(int pattern_pos)
int lfo_rate = 7; int lfo_rate = 7;
int lfo_step = 2; int lfo_step = 2;
int tgt_env; int tgt_env;
pot_set(0, 99); pot_set(0, 0);
pot_set(1, 99);
if ((key->pitch == 0) && (key->env == 0))
return;
if ((pattern_pos % lfo_step) == 0) { if ((pattern_pos % lfo_step) == 0) {
if (test_lfo_step == 0) { if (test_lfo_step == 0) {

21
drums.c
View file

@ -13,6 +13,7 @@
#include "led.h" #include "led.h"
#include "drums.h" #include "drums.h"
#include "drone.h" #include "drone.h"
#include "settings.h"
#define TRACKS 8 #define TRACKS 8
@ -39,12 +40,19 @@ static void beat_cb(uint32_t b)
} }
} }
pattern_pos++; pattern_pos++;
if (pattern_pos >= pattern_len) { if (pattern_pos >= Settings.pattern_len) {
pattern_pos = 0; pattern_pos = 0;
} }
led_beat((pattern_pos % 8) + 1); led_beat((pattern_pos % 8) + 1);
} }
void drums_oneshot(int track)
{
while(dac_is_busy())
dac_stop();
dac_play_direct(dsample[track], dsample_len[track]);
}
void drums_init(void) void drums_init(void)
{ {
dsample[0] = drumkit_0_au; dsample[0] = drumkit_0_au;
@ -76,16 +84,21 @@ void drums_stop(void)
void drums_set_pattern_len(int l) void drums_set_pattern_len(int l)
{ {
pattern_len = l; Settings.pattern_len = l;
timer_set_beat(1); timer_set_beat(1);
} }
void drums_set(uint32_t track, int pos) void drums_set(uint32_t track, int pos)
{ {
pattern[pos] |= track; pattern[pos] |= (1 << track);
} }
void drums_clear(uint32_t track, int pos) void drums_clear(uint32_t track, int pos)
{ {
pattern[pos] &= ~track; pattern[pos] &= ~(1 << track);
}
int drums_get(uint32_t track, int pos)
{
return (!!(pattern[pos] & (1 << track)));
} }

View file

@ -2,13 +2,14 @@
#define DRUMS_H_INCLUDED #define DRUMS_H_INCLUDED
#include <stdint.h> #include <stdint.h>
#define MAX_PATTERN_LEN 64
void drums_init(void); void drums_init(void);
void drums_start(void); void drums_start(void);
void drums_stop(void); void drums_stop(void);
void drums_set_pattern_len(int l); void drums_set_pattern_len(int l);
int drums_get(uint32_t track, int pos);
void drums_set(uint32_t track, int pos); void drums_set(uint32_t track, int pos);
void drums_clear(uint32_t track, int pos); void drums_clear(uint32_t track, int pos);
void drums_oneshot(int track);
#define DRUMS_KICK (1 << 0) #define DRUMS_KICK (1 << 0)
#define DRUMS_HIHAT (1 << 1) #define DRUMS_HIHAT (1 << 1)

View file

@ -2,5 +2,6 @@
struct settings Settings = { struct settings Settings = {
.bpm = 125, .bpm = 125,
.pattern_len = 16,
}; };

View file

@ -3,11 +3,15 @@
#include <stdint.h> #include <stdint.h>
#include "pot.h" #include "pot.h"
#define MAX_PATTERN_LEN 64
#define MAX_TRACKS 8
struct settings { struct settings {
int levels[NUM_POTS]; int levels[NUM_POTS];
#define master_vol levels[2] #define master_vol levels[2]
int bpm; int bpm;
int sequencer_on; int sequencer_on;
int pattern_len;
}; };
extern struct settings Settings; extern struct settings Settings;

14
ui.c
View file

@ -169,6 +169,11 @@ static void ui_display_menu_refresh(void)
WFI(); WFI();
} }
int ui_get_menu_selection(void)
{
return menu_selection;
}
void ui_display_menu(const struct display_menu *menu) void ui_display_menu(const struct display_menu *menu)
{ {
uint8_t i; uint8_t i;
@ -259,10 +264,17 @@ void ui_init(void)
now = jiffies; now = jiffies;
for (i = 1; i < 9; i++) { for (i = 1; i < 9; i++) {
led_beat(i); led_beat(i);
while((jiffies - now < 10)) while((jiffies - now) < 100)
WFI(); WFI();
now = jiffies; now = jiffies;
} }
for (i = 8; i > 0; i--) {
led_beat(i);
while((jiffies - now) < 100)
WFI();
now = jiffies;
}
led_beat(0);
} }
void ui_keepalive(uint32_t timeslice) void ui_keepalive(uint32_t timeslice)

1
ui.h
View file

@ -40,5 +40,6 @@ void set_input_callback(void (*cb)(uint8_t press, int hold));
void clear_input_callback(void); void clear_input_callback(void);
void set_keepalive(void (*cb)(void)); void set_keepalive(void (*cb)(void));
void clear_keepalive(void); void clear_keepalive(void);
int ui_get_menu_selection(void);
#endif #endif

View file

@ -267,10 +267,6 @@ static void ui_bytebeat(const void *arg)
} }
static void ui_submenu(const void *arg)
{
ui_display_menu(arg);
}
const struct display_menu PatternMenu = { const struct display_menu PatternMenu = {
.entry_n = 1, .entry_n = 1,
@ -299,6 +295,11 @@ const struct display_menu SettingsMenu = {
#endif #endif
static void ui_submenu_action(struct display_menu_entry *e, uint8_t b)
{
ui_display_menu(e->arg);
}
static void ui_sequencer_action(struct display_menu_entry *e, uint8_t b) static void ui_sequencer_action(struct display_menu_entry *e, uint8_t b)
{ {
if (Settings.sequencer_on) { if (Settings.sequencer_on) {
@ -326,19 +327,17 @@ static void ui_bpm_action(struct display_menu_entry *e, uint8_t b)
} }
extern void ui_pattern_menu_action(struct display_menu_entry *e, uint8_t b);
extern struct display_menu PatternMenu;
const struct display_menu MainMenu = { const struct display_menu MainMenu = {
.entry_n = 3, .entry_n = 5,
.entry = { .entry = {
/* TYPE, label, action, min, max, var, arg */ /* TYPE, label, action, min, max, var, arg */
{ ENTRY_TYPE_BOOL, "Sequencer", ui_sequencer_action, 0, 0, 0, &Settings.sequencer_on, NULL }, { ENTRY_TYPE_BOOL, "Sequencer", ui_sequencer_action, 0, 0, 0, &Settings.sequencer_on, NULL },
{ ENTRY_TYPE_DEC, "Volume: ", ui_master_action, 0, 100, 2, &Settings.levels[2], NULL }, { ENTRY_TYPE_DEC, "Volume: ", ui_master_action, 0, 100, 2, &Settings.levels[2], NULL },
{ ENTRY_TYPE_DEC, "BPM: ", ui_bpm_action, 30, 300, 1, &Settings.bpm, NULL }, { ENTRY_TYPE_DEC, "BPM: ", ui_bpm_action, 30, 300, 1, &Settings.bpm, NULL },
/* { ENTRY_TYPE_DEC, "Pattern Len:", NULL, 8, MAX_PATTERN_LEN, 8, &Settings.pattern_len, NULL },
{ "BPM" , ui_bpm, NULL}, { ENTRY_TYPE_TEXT, "Edit Pattern", ui_pattern_menu_action, 0, 0, 0, NULL, &PatternMenu},
{ "Pattern ", ui_submenu, &PatternMenu },
{ "Drone ", ui_submenu, &DroneMenu},
{ "Bytebeat ", ui_bytebeat },
*/
{0, "", NULL, 0,0,0,NULL,NULL} {0, "", NULL, 0,0,0,NULL,NULL}
} }
}; };

113
ui_pattern.c Normal file
View file

@ -0,0 +1,113 @@
#include <stddef.h>
#include "ui.h"
#include <string.h>
#include "adc.h"
#include "button.h"
#include "system.h"
#include "unicore-mx/stm32/gpio.h"
#include "unicore-mx/stm32/rcc.h"
#include "pot.h"
#include "dac.h"
#include "settings.h"
#include "timer.h"
static int sel_pos = 1;
static int sel_track = 0;
static int sel_val = 0;
extern volatile uint32_t jiffies;
void ui_pattern_refresh_action(struct display_menu_entry *e, uint8_t b)
{
int i;
int off;
sel_val = drums_get(sel_track, sel_pos - 1);
led_beat(0);
off = ((sel_pos - 1)/ 8) * 8;
for (i = 0; i < 8; i++) {
if (drums_get(sel_track, (off + i)))
led_on(i+1);
else
led_off(i+1);
}
}
void ui_pattern_update_action(struct display_menu_entry *e, uint8_t b)
{
if (sel_val) {
drums_set(sel_track, sel_pos - 1);
drums_oneshot(sel_track);
} else
drums_clear(sel_track, sel_pos - 1);
}
void ui_pattern_keepalive(void)
{
static uint32_t blink_time = 0;
if (jiffies - blink_time > 20) {
led_toggle(((sel_pos - 1) % 8) + 1);
blink_time = jiffies;
}
}
void ui_pattern_menu_return_to_main(struct display_menu_entry *e, uint8_t b)
{
display_clear(NULL);
clear_input_callback();
clear_keepalive();
led_beat(0);
ui_display_menu(&MainMenu);
}
struct display_menu PatternMenu = {
.entry_n = 4,
.entry = {
/* TYPE, label, action, min, max, var, arg */
{ ENTRY_TYPE_DEC, "Track: ", ui_pattern_refresh_action, 0, (MAX_TRACKS - 1), 1, &sel_track, NULL },
{ ENTRY_TYPE_DEC, "Pos : ", ui_pattern_refresh_action, 1, 8, 1, &sel_pos, NULL },
{ ENTRY_TYPE_BOOL, "Value : ", ui_pattern_update_action, 0, 0, 0, &sel_val, NULL },
{ ENTRY_TYPE_TEXT, "Back to main", ui_pattern_menu_return_to_main, 0, 0, 0, NULL, NULL },
{0, "", NULL, 0,0,0,NULL,NULL}
}
};
void ui_pattern_input(int press, int hold)
{
if (press == '*' && (ui_get_menu_selection() == 1)) {
sel_val = !sel_val;
ui_pattern_update_action(NULL, 0);
ui_pattern_refresh_action(NULL, 0);
press = 0;
return;
}
ui_button_press(press, hold);
if ((press == '+' || press == '-') && (ui_get_menu_selection() == 0)) {
drums_oneshot(sel_track);
}
}
const char instr_txt[MAX_TRACKS][14] = {
"Kick",
"Snare",
"HitHat",
"Tom1",
"Tom2",
"Clap",
"Cow",
"",
};
void ui_pattern_menu_action(struct display_menu_entry *e, uint8_t b)
{
PatternMenu.entry[1].max = Settings.pattern_len;
sel_val = drums_get(sel_track, sel_pos - 1);
ui_display_menu(e->arg);
set_keepalive(ui_pattern_keepalive);
set_input_callback(ui_pattern_input);
ui_pattern_refresh_action(e, b);
}