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 \
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

33
drone.c
View file

@ -13,16 +13,36 @@
#include "drone.h"
#include "drums.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},
{ 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)
{
pot_set(0, 0xFF);
pot_set(1, 0x0);
pot_set(0, 0);
pot_set(1, 99);
}
void drone_beat(int pattern_pos)
@ -34,7 +54,10 @@ void drone_beat(int pattern_pos)
int lfo_rate = 7;
int lfo_step = 2;
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 (test_lfo_step == 0) {

21
drums.c
View file

@ -13,6 +13,7 @@
#include "led.h"
#include "drums.h"
#include "drone.h"
#include "settings.h"
#define TRACKS 8
@ -39,12 +40,19 @@ static void beat_cb(uint32_t b)
}
}
pattern_pos++;
if (pattern_pos >= pattern_len) {
if (pattern_pos >= Settings.pattern_len) {
pattern_pos = 0;
}
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)
{
dsample[0] = drumkit_0_au;
@ -76,16 +84,21 @@ void drums_stop(void)
void drums_set_pattern_len(int l)
{
pattern_len = l;
Settings.pattern_len = l;
timer_set_beat(1);
}
void drums_set(uint32_t track, int pos)
{
pattern[pos] |= track;
pattern[pos] |= (1 << track);
}
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
#include <stdint.h>
#define MAX_PATTERN_LEN 64
void drums_init(void);
void drums_start(void);
void drums_stop(void);
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_clear(uint32_t track, int pos);
void drums_oneshot(int track);
#define DRUMS_KICK (1 << 0)
#define DRUMS_HIHAT (1 << 1)

View file

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

View file

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

14
ui.c
View file

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

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 set_keepalive(void (*cb)(void));
void clear_keepalive(void);
int ui_get_menu_selection(void);
#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 = {
.entry_n = 1,
@ -299,6 +295,11 @@ const struct display_menu SettingsMenu = {
#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)
{
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 = {
.entry_n = 3,
.entry_n = 5,
.entry = {
/* TYPE, label, action, min, max, var, arg */
{ 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, "BPM: ", ui_bpm_action, 30, 300, 1, &Settings.bpm, NULL },
/*
{ "BPM" , ui_bpm, NULL},
{ "Pattern ", ui_submenu, &PatternMenu },
{ "Drone ", ui_submenu, &DroneMenu},
{ "Bytebeat ", ui_bytebeat },
*/
{ ENTRY_TYPE_DEC, "Pattern Len:", NULL, 8, MAX_PATTERN_LEN, 8, &Settings.pattern_len, NULL },
{ ENTRY_TYPE_TEXT, "Edit Pattern", ui_pattern_menu_action, 0, 0, 0, NULL, &PatternMenu},
{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);
}