Added drums pattern editor
This commit is contained in:
parent
d4749d2fe9
commit
3b2641fdcd
10 changed files with 190 additions and 23 deletions
2
Makefile
2
Makefile
|
@ -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
33
drone.c
|
@ -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
21
drums.c
|
@ -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)));
|
||||
}
|
||||
|
|
3
drums.h
3
drums.h
|
@ -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)
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
|
||||
struct settings Settings = {
|
||||
.bpm = 125,
|
||||
.pattern_len = 16,
|
||||
|
||||
};
|
||||
|
|
|
@ -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
14
ui.c
|
@ -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
1
ui.h
|
@ -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
|
||||
|
|
21
ui_drone.c
21
ui_drone.c
|
@ -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
113
ui_pattern.c
Normal 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);
|
||||
}
|
||||
|
Loading…
Reference in a new issue