New ui, global settings.

This commit is contained in:
Daniele Lacamera 2020-04-13 11:11:17 +02:00
parent b949063b6a
commit d4749d2fe9
15 changed files with 253 additions and 82 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
mutex.o ui_drone.o adc.o spi.o pot.o dac.o sound.o drone.o settings.o
UMX:=lib/unicore-mx/lib/libucmx_stm32f4.a

View file

@ -39,7 +39,7 @@ enum button_state {
#endif
#define BUTTON_DEBOUNCE_TIME 50
#define BUTTON_HOLD_TIME 1500
#define BUTTON_HOLD_TIME 200

View file

@ -19,6 +19,12 @@ static struct drone_slot drone_pattern[MAX_PATTERN_LEN] = {
{ 40, 10 }, { 40, 10}, {36, 10}, {32,10}
};
void drone_mute(void)
{
pot_set(0, 0xFF);
pot_set(1, 0x0);
}
void drone_beat(int pattern_pos)
{
struct drone_slot *key = &drone_pattern[pattern_pos];

View file

@ -3,6 +3,8 @@
#define DRONE_H_INCLUDED
#include <stdint.h>
void drone_mute(void);
struct __attribute__((packed)) drone_slot {
uint8_t pitch;
uint8_t env;

5
led.c
View file

@ -84,10 +84,11 @@ void led_toggle(int led)
void led_beat(int b)
{
if (b < 1 || b > 8)
if (b < 0 || b > 8)
return;
gpio_clear(GPIOB, BANK_B_LD);
gpio_clear(GPIOE, BANK_E_LD);
led_on(b);
if (b != 0)
led_on(b);
}

12
main.c
View file

@ -15,6 +15,12 @@
#include "ui.h"
#include "button.h"
#include "adc.h"
#include "pot.h"
#include "settings.h"
#include "drums.h"
#include "drone.h"
#include "uart.h"
#include "timer.h"
extern uint32_t cpu_freq;
#define BLINK_INTERVAL 500
@ -39,9 +45,6 @@ static void bootlevel_0(void)
printf("Buttons initialized.\r\n");
}
extern int timer_init(uint32_t bpm);
extern int timer_start();
extern int timer_stop();
static void bootlevel_1(void)
{
@ -66,7 +69,7 @@ static void bootlevel_1(void)
printf("Displaying splash screen...\r\n");
ui_init();
printf("UI initialized.\r\n");
timer_init(140);
timer_init();
drums_init();
drums_start();
@ -106,6 +109,7 @@ void process_button(uint8_t press, int hold)
process_input_callback(press, hold);
else
ui_button_press(press, hold);
}
extern void gettime(uint32_t *s, uint32_t *us);

40
pot.c
View file

@ -4,10 +4,11 @@
#include "system.h"
#include "led.h"
#include "pinout.h"
#include "settings.h"
#include "pot.h"
extern volatile uint32_t jiffies;
uint32_t p1_lvl, p0_lvl, master_lvl;
static int pot_cs[3] = { 8, 7, 6 }; // PC6, PC7, PC8
@ -18,13 +19,11 @@ static int pot_cs[3] = { 8, 7, 6 }; // PC6, PC7, PC8
#define POTINC GPIO14 // D14
#define POTUD GPIO15 // D15
#define NUM_POTS 3
#define POT_CS_PINS (POT0 | POT1 | POTM)
#define POT_CTRL_PINS (POTINC | POTUD)
static int HWLevel[3] = {0, 0, 0};
static uint32_t Pots[NUM_POTS] = { POT0, POT1, POTM };
static int Levels[NUM_POTS] = { 0, 0, 0 };
static void p_offset(int p, int offset)
@ -64,21 +63,21 @@ static void p_offset(int p, int offset)
;;
}
Levels[p] += offset;
if (Levels[p] > 100)
Levels[p] = 100;
if (Levels[p] < 0)
Levels[p] = 0;
HWLevel[p] += offset;
if (HWLevel[p] > 100)
HWLevel[p] = 100;
if (HWLevel[p] < 0)
HWLevel[p] = 0;
}
void pot_offset(int p, int offset)
{
if ((Levels[p] + offset) > 100) {
offset = 100 - Levels[p];
if ((HWLevel[p] + offset) > 100) {
offset = 100 - HWLevel[p];
}
if ((Levels[p] + offset) < 0) {
offset = 0 - Levels[p];
if ((HWLevel[p] + offset) < 0) {
offset = 0 - HWLevel[p];
}
if (offset == 0)
@ -108,20 +107,31 @@ void pot_init(void)
}
void pot_sync(int p)
{
pot_set(p, Settings.levels[p]);
}
int pot_get(int p)
{
return Levels[p];
return HWLevel[p];
}
void pot_set(int p, int val)
{
int old = Levels[p];
int old = HWLevel[p];
int new = val;
int off;
if (val < 0)
val = 0;
if (val > 100)
val = 100;
Settings.levels[p] = val;
off = val - old;
if (off == 0)
return;

1
pot.h
View file

@ -11,5 +11,6 @@ void pot_offset(int p, int offset);
#define pot_get_master() pot_get(2)
#define pot_set_master(x) pot_set(2,x)
#define NUM_POTS 3
#endif

6
settings.c Normal file
View file

@ -0,0 +1,6 @@
#include "settings.h"
struct settings Settings = {
.bpm = 125,
};

14
settings.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef SETTINGS_H_INCLUDED
#define SETTINGS_H_INCLUDED
#include <stdint.h>
#include "pot.h"
struct settings {
int levels[NUM_POTS];
#define master_vol levels[2]
int bpm;
int sequencer_on;
};
extern struct settings Settings;
#endif

22
timer.c
View file

@ -3,11 +3,11 @@
#include "led.h"
#include "timer.h"
#include <stdlib.h>
#include "settings.h"
#define S_PER_MINUTE (60)
extern uint32_t cpu_freq;
static uint32_t sys_bpm = 75;
void (*beat_callback)(uint32_t b) = NULL;
@ -21,19 +21,13 @@ void timer_clear_beat_callback(void)
timer_set_beat_callback(NULL);
}
uint32_t timer_get_bpm(void)
{
return sys_bpm;
}
int timer_set_bpm(uint32_t bpm)
int timer_set_bpm(void)
{
uint32_t val = 0;
uint32_t psc = 1;
uint32_t err = 0;
uint32_t reg = 0;
uint32_t clock = (cpu_freq / (4 * bpm)) * (S_PER_MINUTE);;
uint32_t clock = (cpu_freq / (4 * Settings.bpm)) * (S_PER_MINUTE);;
while (psc < 65535) {
val = clock / psc;
@ -52,7 +46,6 @@ int timer_set_bpm(uint32_t bpm)
TIM4_PSC = psc;
TIM4_ARR = val;
TIM4_CNT = val - 1;
sys_bpm = bpm;
return 0;
}
@ -64,8 +57,8 @@ int timer_start(void)
int timer_stop(void)
{
TIM4_CR1 |= TIM_CR1_CLOCK_ENABLE;
TIM4_DIER |= TIM_DIER_UIE;
TIM4_CR1 &= ~TIM_CR1_CLOCK_ENABLE;
TIM4_DIER &= ~TIM_DIER_UIE;
}
static void timer_irq_setup(void)
@ -79,12 +72,11 @@ static void timer_irq_setup(void)
}
int timer_init(uint32_t bpm)
int timer_init(void)
{
timer_stop();
timer_irq_setup();
timer_set_bpm(bpm);
timer_start();
timer_set_bpm();
return 0;
}

View file

@ -1,11 +1,10 @@
#ifndef TIMER_H_INCLUDED
#define TIMER_H_INCLUDED
uint32_t timer_get_bpm(void);
int timer_set_bpm(uint32_t bpm);
int timer_set_bpm(void);
int timer_start(void);
int timer_stop(void);
int timer_init(uint32_t bpm);
int timer_init(void);
void timer_set_beat_callback(void (*b_cb)(uint32_t));
void timer_clear_beat_callback(void);

151
ui.c
View file

@ -22,8 +22,9 @@
//#define DEVICE_INITIALIZATION
static const char welcome_message0[]= " Waveblender ";
static const char welcome_message1[]= " (c) 2020 ";
static const char welcome_message2[]= " danielinux ";
static const char welcome_message1[]= "(c) danielinux ";
static const char welcome_message2[]= " GPL v.2 ";
static const char welcome_message3[]= "src: wb.vado.li";
static uint32_t last_action = 0;
static uint32_t offset = 0;
@ -88,6 +89,7 @@ static void ui_display_menu_refresh(void)
const struct display_menu *menu = CurrentMenu;
uint8_t vline;
int i;
char txt[16];
display_scroll(NULL, display_cur_v);
display_clear(NULL);
@ -95,10 +97,74 @@ static void ui_display_menu_refresh(void)
vline = i + 4;
if (vline > 7)
vline -= 8;
switch (menu->entry[i].type) {
case ENTRY_TYPE_TEXT:
strncpy(txt, menu->entry[i].label, 15);
break;
case ENTRY_TYPE_HEX:
{
int x = *menu->entry[i].var ;
int j;
strncpy(txt, menu->entry[i].label, 11);
for (j = strlen(menu->entry[i].label); j < 12; j++)
txt[j] = ' ';
if (x > 0xFF) {
if (((x >> 8) & 0x0F) > 9)
txt[12] = (((x >> 8) & 0x0F) - 10) + 'A';
else
txt[12] = ((x >> 8) & 0x0F) + '0';
} else
txt[12] = ' ';
if (x > 0x0F) {
if (((x >> 4) & 0x0F) > 9)
txt[13] = (((x >> 4) & 0x0F) - 10) + 'A';
else
txt[13] = ((x >> 4) & 0x0F) + '0';
} else
txt[13] = ' ';
if ((x & 0x0F) > 9)
txt[14] = ((x & 0x0F) - 10) + 'A';
else
txt[14] = (x & 0x0F) + '0';
}
break;
case ENTRY_TYPE_BOOL:
{
int x = *menu->entry[i].var ;
int j;
strncpy(txt, menu->entry[i].label, 10);
for (j = strlen(menu->entry[i].label); j < 12; j++)
txt[j] = ' ';
if (x)
strcpy(txt + 10, "[ ON]");
else
strcpy(txt + 10, "[OFF]");
}
break;
case ENTRY_TYPE_DEC:
{
int x = *menu->entry[i].var ;
int j;
strncpy(txt, menu->entry[i].label, 11);
for (j = strlen(menu->entry[i].label); j < 12; j++)
txt[j] = ' ';
if (x > 99) {
txt[12] = (x / 100) + '0';
} else
txt[12] = ' ';
if (x > 9) {
txt[13] = ((x % 100)/10) + '0';
} else
txt[13] = ' ';
txt[14] = (x % 10) + '0';
}
break;
}
if (i == menu_selection)
display_text_inverse(vline, menu->entry[i].title);
display_text_inverse(vline, txt);
else
display_text(vline, menu->entry[i].title);
display_text(vline, txt);
}
WFI();
}
@ -115,32 +181,52 @@ void ui_display_menu(const struct display_menu *menu)
void ui_button_press(uint8_t b, int hold)
{
if (b == '+') {
int n = menu_selection;
menu_selection = 0;
if (CurrentMenu->entry[n].action) {
display_cur_v = 0;
display_clear(NULL);
display_scroll(NULL, display_cur_v);
CurrentMenu->entry[n].action(
CurrentMenu->entry[n].arg);
}
return;
}
if (b == 'U') {
if (menu_selection > 0) {
menu_selection--;
ui_menu_autoscroll();
ui_display_menu_refresh();
}
}
if (b == 'D') {
if (menu_selection < CurrentMenu->entry_n - 1) {
menu_selection++;
ui_menu_autoscroll();
ui_display_menu_refresh();
}
int n = menu_selection;
struct display_menu_entry e;
switch (b) {
case 'U':
if (menu_selection > 0) {
menu_selection--;
ui_menu_autoscroll();
ui_display_menu_refresh();
}
break;
case 'D':
if (menu_selection < CurrentMenu->entry_n - 1) {
menu_selection++;
ui_menu_autoscroll();
ui_display_menu_refresh();
}
break;
default:
e = CurrentMenu->entry[n];
int changed = 0;
/* Default actions for '-', '+', '*' */
if (e.var && (e.type == ENTRY_TYPE_BOOL)) {
if ((*e.var) && ((b == '-') || (b == '*'))) {
*e.var = 0;
changed = 1;
} else if ((!(*e.var)) && ((b == '+') || (b == '*'))) {
*e.var = 1;
changed = 1;
}
} else if ((e.min != e.max) && e.var && ((e.type == ENTRY_TYPE_DEC) || (e.type == ENTRY_TYPE_DEC))) {
if ((*e.var > e.min) && (b == '-')) {
*e.var -= e.step;
changed = 1;
} else if ((*e.var < e.max) && (b == '+')) {
*e.var += e.step;
changed = 1;
}
}
/* Custom actions for '-', '+', '*' (after changes are applied) */
if (b != 0 && e.action) {
e.action(&e, b);
changed = 1;
}
if (changed) {
ui_display_menu_refresh();
}
}
}
@ -152,16 +238,17 @@ void ui_init(void)
display_text(0, welcome_message0);
display_text(1, welcome_message1);
display_text(2, welcome_message2);
display_text(3, welcome_message3);
now = jiffies;
for (i = 0x3f; i >= 0x20; i--) {
display_scroll(NULL, i);
while ((jiffies - now) < 30)
while ((jiffies - now) < 20)
WFI();
now = jiffies;
}
for (i = display_getcontrast(NULL); i >= 0; i--) {
display_setcontrast(NULL, i);
while ((jiffies - now) < 10)
while ((jiffies - now) < 16)
WFI();
now = jiffies;
}

18
ui.h
View file

@ -4,14 +4,26 @@
void ui_init(void);
#define ENTRY_TYPE_TEXT 0
#define ENTRY_TYPE_BOOL 1
#define ENTRY_TYPE_DEC 2
#define ENTRY_TYPE_HEX 3
#define MAX_ENTRY 8
struct display_menu {
struct display_menu *next;
int entry_n;
struct display_menu_entry {
char title[16];
void (*action)(const void *arg);
int type;
char label[16];
void (*action)(struct display_menu_entry *item, uint8_t button);
int min, max, step;
int *var;
const void *arg;
} entry[8];
} entry[MAX_ENTRY];
};

View file

@ -7,6 +7,9 @@
#include "unicore-mx/stm32/gpio.h"
#include "unicore-mx/stm32/rcc.h"
#include "pot.h"
#include "dac.h"
#include "settings.h"
#include "timer.h"
#define CENTER_X ((int)(52))
#define CENTER_Y ((int)(50))
@ -16,7 +19,7 @@ struct display_menu *CurrentMenu = &MainMenu;
extern volatile uint32_t jiffies;
static uint32_t drone_xy_gain = 1;
#if 0
static void ui_return(uint8_t press, int hold)
{
display_clear(NULL);
@ -192,7 +195,7 @@ static void ui_bpm_input(uint8_t press, int hold)
if (press == 'U') {
if (sys_bpm < 300) {
timer_stop();
timer_set_bpm(sys_bpm + 1);
timer_set_bpm();
led_beat(1);
timer_set_beat(1);
timer_start();
@ -208,7 +211,7 @@ static void ui_bpm_input(uint8_t press, int hold)
timer_start();
}
}
if (press == '+') {
if (press == '*') {
display_clear(NULL);
clear_input_callback();
ui_display_menu(&MainMenu);
@ -294,15 +297,49 @@ const struct display_menu SettingsMenu = {
}
};
#endif
static void ui_sequencer_action(struct display_menu_entry *e, uint8_t b)
{
if (Settings.sequencer_on) {
timer_set_beat(1);
timer_start();
} else {
led_beat(0);
drone_mute();
timer_stop();
}
}
static void ui_master_action(struct display_menu_entry *e, uint8_t b)
{
pot_sync(2);
}
static void ui_bpm_action(struct display_menu_entry *e, uint8_t b)
{
timer_stop();
timer_set_bpm();
led_beat(1);
timer_set_beat(1);
timer_start();
}
const struct display_menu MainMenu = {
.entry_n = 5,
.entry_n = 3,
.entry = {
{ "Master Volume ", ui_mastervol, NULL },
/* 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 },
{ "", NULL, NULL}
*/
{0, "", NULL, 0,0,0,NULL,NULL}
}
};