Fixed zerocopy dac module for drum sequencer
This commit is contained in:
parent
9dab007462
commit
9a6c8e5caa
14 changed files with 459 additions and 92 deletions
2
Makefile
2
Makefile
|
@ -13,6 +13,8 @@ UMXFLAGS:=-Ilib/unicore-mx/include/ -DSTM32F4
|
|||
LIBS+=$(UMX)
|
||||
|
||||
|
||||
OBJS+=drumkit_0.o drumkit_1.o drumkit_2.o drumkit_3.o drumkit_4.o drumkit_5.o drumkit_6.o drums.o
|
||||
|
||||
LSCRIPT:=target.ld
|
||||
|
||||
OBJCOPY:=$(CROSS_COMPILE)objcopy
|
||||
|
|
5
README.md
Normal file
5
README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Waveblender
|
||||
|
||||
waveblender is a DIY synth drone.
|
||||
|
||||
Schematics+instructions coming soon.
|
163
dac.c
163
dac.c
|
@ -11,80 +11,130 @@
|
|||
#include <unicore-mx/stm32/gpio.h>
|
||||
#include <unicore-mx/stm32/rcc.h>
|
||||
#include <unicore-mx/stm32/timer.h>
|
||||
#include <stdlib.h>
|
||||
#include "pot.h"
|
||||
#include "timer.h"
|
||||
#include "system.h"
|
||||
|
||||
#define DAC_BUFSIZ 512
|
||||
#define DAC_BUFSIZ (512)
|
||||
#define DAC_MEMSIZ (4 * DAC_BUFSIZ)
|
||||
extern const unsigned char raw_au[];
|
||||
extern volatile uint32_t jiffies;
|
||||
const unsigned int raw_au_len;
|
||||
|
||||
static volatile int dac_written;
|
||||
static int dac_transfer_size;
|
||||
static int dac_chunk_size;
|
||||
static uint8_t dac_outb[DAC_BUFSIZ];
|
||||
|
||||
static uint8_t dac_memory[DAC_MEMSIZ];
|
||||
static volatile uint32_t dac_written;
|
||||
|
||||
|
||||
static volatile int direct = 0;
|
||||
static volatile int dac_busy = 0;
|
||||
|
||||
int dac_is_busy(void)
|
||||
{
|
||||
return dac_busy;
|
||||
}
|
||||
|
||||
static void dac_xmit(void)
|
||||
{
|
||||
uint32_t size = DAC_BUFSIZ;
|
||||
if ((dac_transfer_size == 0) || (dac_written >= dac_transfer_size)) {
|
||||
dac_written = 0;
|
||||
dac_transfer_size = 0;
|
||||
memset(dac_memory, 0, DAC_MEMSIZ);
|
||||
} else {
|
||||
if ((dac_transfer_size - dac_written) < size)
|
||||
size = dac_transfer_size - dac_written;
|
||||
dac_chunk_size = size;
|
||||
if (size == 0) {
|
||||
dac_transfer_size = 0;
|
||||
dac_written = 0;
|
||||
memset(dac_memory, 0, DAC_MEMSIZ);
|
||||
}
|
||||
}
|
||||
if (dac_transfer_size == 0) {
|
||||
dma_disable_stream(DMA1, DMA_STREAM5);
|
||||
dac_trigger_disable(CHANNEL_1);
|
||||
dac_dma_disable(CHANNEL_1);
|
||||
return;
|
||||
}
|
||||
|
||||
dma_set_number_of_data(DMA1, DMA_STREAM5, size);
|
||||
dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t)(dac_memory + dac_written));
|
||||
direct = 0;
|
||||
|
||||
/* Start DMA transfer of waveform */
|
||||
dac_trigger_enable(CHANNEL_1);
|
||||
dac_set_trigger_source(DAC_CR_TSEL1_T2);
|
||||
dac_dma_enable(CHANNEL_1);
|
||||
dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t) (dac_outb + dac_written));
|
||||
dma_set_number_of_data(DMA1, DMA_STREAM5, size);
|
||||
dma_enable_transfer_complete_interrupt(DMA1, DMA_STREAM5);
|
||||
dma_channel_select(DMA1, DMA_STREAM5, DMA_SxCR_CHSEL_7);
|
||||
dma_enable_stream(DMA1, DMA_STREAM5);
|
||||
}
|
||||
|
||||
int dac_write(const void *buf, unsigned int len)
|
||||
{
|
||||
if (dac_written < dac_transfer_size) {
|
||||
if ((len + dac_transfer_size) > DAC_BUFSIZ)
|
||||
return 0;
|
||||
}
|
||||
if (dac_written >= dac_transfer_size) {
|
||||
dac_written = 0;
|
||||
dac_transfer_size = 0;
|
||||
}
|
||||
memcpy(dac_outb + dac_transfer_size, buf, len);
|
||||
dac_transfer_size += len;
|
||||
dac_xmit();
|
||||
return dac_written;
|
||||
}
|
||||
|
||||
|
||||
int dac_space(void)
|
||||
{
|
||||
if (dac_written >= dac_transfer_size) {
|
||||
dac_written = 0;
|
||||
dac_transfer_size = 0;
|
||||
}
|
||||
return DAC_BUFSIZ - dac_transfer_size;
|
||||
return DAC_MEMSIZ - dac_transfer_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* IRQ Handler */
|
||||
void dma1_stream5_isr(void)
|
||||
{
|
||||
if (dma_get_interrupt_flag(DMA1, DMA_STREAM5, DMA_TCIF)) {
|
||||
if (dac_written < dac_transfer_size)
|
||||
dac_written += dac_chunk_size;
|
||||
|
||||
dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF);
|
||||
dma_disable_stream(DMA1, DMA_STREAM5);
|
||||
dac_trigger_disable(CHANNEL_1);
|
||||
dac_dma_disable(CHANNEL_1);
|
||||
if (dac_written >= dac_transfer_size) {
|
||||
return;
|
||||
dac_busy = 0;
|
||||
if (!direct) {
|
||||
if (dac_written < dac_transfer_size) {
|
||||
dac_written += DAC_BUFSIZ;
|
||||
} else {
|
||||
dac_written = 0;
|
||||
dac_transfer_size = 0;
|
||||
return;
|
||||
}
|
||||
dac_xmit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dac_stop(void)
|
||||
{
|
||||
dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF);
|
||||
dma_disable_stream(DMA1, DMA_STREAM5);
|
||||
dac_trigger_disable(CHANNEL_1);
|
||||
dac_dma_disable(CHANNEL_1);
|
||||
dac_busy = 0;
|
||||
}
|
||||
|
||||
|
||||
void dac_play_direct(uint8_t *mem, uint32_t size)
|
||||
{
|
||||
dma_clear_interrupt_flags(DMA1, DMA_STREAM5, DMA_TCIF);
|
||||
dma_disable_stream(DMA1, DMA_STREAM5);
|
||||
dac_trigger_disable(CHANNEL_1);
|
||||
dac_dma_disable(CHANNEL_1);
|
||||
dma_set_number_of_data(DMA1, DMA_STREAM5, size);
|
||||
dma_set_memory_address(DMA1, DMA_STREAM5, (uint32_t)mem);
|
||||
|
||||
direct = 1;
|
||||
dac_busy = 1;
|
||||
|
||||
/* Start DMA transfer of waveform */
|
||||
dac_trigger_enable(CHANNEL_1);
|
||||
dac_set_trigger_source(DAC_CR_TSEL1_T2);
|
||||
dac_dma_enable(CHANNEL_1);
|
||||
dma_enable_transfer_complete_interrupt(DMA1, DMA_STREAM5);
|
||||
dma_channel_select(DMA1, DMA_STREAM5, DMA_SxCR_CHSEL_7);
|
||||
dma_enable_stream(DMA1, DMA_STREAM5);
|
||||
}
|
||||
|
||||
|
||||
/* Initialization functions */
|
||||
|
||||
|
@ -147,28 +197,57 @@ static void dac_hw_init(data_channel c)
|
|||
dac_enable(c);
|
||||
}
|
||||
|
||||
void dac_reset(void)
|
||||
{
|
||||
dac_written = 0;
|
||||
dac_transfer_size = 0;
|
||||
}
|
||||
|
||||
void dac_play(const uint8_t *buf, int len)
|
||||
{
|
||||
int i = 0;
|
||||
int space;
|
||||
while(i < len) {
|
||||
space = dac_space();
|
||||
if (space > 0) {
|
||||
if (space > (len - i))
|
||||
space = len - i;
|
||||
dac_write(buf + i, space);
|
||||
i += space;
|
||||
int w = 0;
|
||||
dac_written = 0;
|
||||
dac_transfer_size = 0;
|
||||
while (len > 0) {
|
||||
space = DAC_MEMSIZ;
|
||||
if (space > len) {
|
||||
space = len;
|
||||
}
|
||||
if (dac_space() == 0) {
|
||||
WFI();
|
||||
continue;
|
||||
}
|
||||
memcpy(dac_memory, buf + w, space);
|
||||
dac_transfer_size = space;
|
||||
dac_xmit();
|
||||
len -= space;
|
||||
w += space;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
extern unsigned char drumkit_0_au[];
|
||||
extern unsigned char drumkit_1_au[];
|
||||
extern unsigned char drumkit_2_au[];
|
||||
extern unsigned int drumkit_0_au_len;
|
||||
extern unsigned int drumkit_1_au_len;
|
||||
extern unsigned int drumkit_2_au_len;
|
||||
|
||||
|
||||
int dac_init(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t now;
|
||||
dac_hw_init(CHANNEL_1);
|
||||
dac_dma_setup();
|
||||
pot_set_master(200);
|
||||
dac_play(raw_au, raw_au_len);
|
||||
pot_set_master(100);
|
||||
|
||||
// dac_play(drumkit_0_au, drumkit_0_au_len);
|
||||
// dac_play(raw_au, raw_au_len);
|
||||
dac_play_direct(drumkit_2_au, drumkit_2_au_len);
|
||||
while(dac_is_busy())
|
||||
WFI();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
1
dac.h
1
dac.h
|
@ -8,6 +8,7 @@
|
|||
void dac_init(void);
|
||||
int dac_write(const void *buf, unsigned int len);
|
||||
int dac_play(const void *buf, unsigned int len);
|
||||
void dac_play_direct(uint8_t *mem, uint32_t size);
|
||||
|
||||
#define pot_get_master() pot_get(2)
|
||||
#define pot_set_master(x) pot_set(2,x)
|
||||
|
|
102
drums.c
Normal file
102
drums.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
|
||||
|
||||
#include <stdint.h>
|
||||
#include "system.h"
|
||||
#include "display.h"
|
||||
#include "systick.h"
|
||||
#include "button.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "ui.h"
|
||||
#include "timer.h"
|
||||
#include "led.h"
|
||||
|
||||
|
||||
#define MAX_PATTERN_LEN 64
|
||||
|
||||
#define DRUMS_KICK (1 << 0)
|
||||
#define DRUMS_HIHAT (1 << 1)
|
||||
#define DRUMS_SNARE (1 << 2)
|
||||
#define DRUMS_TOM1 (1 << 3)
|
||||
#define DRUMS_TOM2 (1 << 4)
|
||||
#define DRUMS_CYM (1 << 6)
|
||||
#define DRUMS_CLAP (1 << 7)
|
||||
|
||||
|
||||
#define TRACKS 8
|
||||
|
||||
static uint32_t pattern[MAX_PATTERN_LEN] = { DRUMS_KICK, DRUMS_HIHAT, DRUMS_SNARE, DRUMS_HIHAT, DRUMS_KICK, DRUMS_KICK, DRUMS_SNARE, DRUMS_HIHAT };
|
||||
//static uint32_t pattern[MAX_PATTERN_LEN] = { DRUMS_KICK, DRUMS_KICK, DRUMS_KICK, DRUMS_KICK, DRUMS_KICK, DRUMS_KICK, DRUMS_SNARE, DRUMS_HIHAT };
|
||||
static uint32_t pattern_len = 8;
|
||||
static uint32_t pattern_pos = 0;
|
||||
static unsigned char *dsample[TRACKS] = {};
|
||||
static unsigned int dsample_len[TRACKS] = {};
|
||||
|
||||
|
||||
|
||||
void beat_cb(uint32_t b)
|
||||
{
|
||||
uint32_t key = pattern[pattern_pos];
|
||||
int i;
|
||||
for (i = 0; i < TRACKS; i++) {
|
||||
if ((key & (1 << i)) == (1 << i)) {
|
||||
if (dsample[i]) {
|
||||
while(dac_is_busy())
|
||||
dac_stop();
|
||||
dac_play_direct(dsample[i], dsample_len[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pattern_pos++;
|
||||
if (pattern_pos >= pattern_len) {
|
||||
pattern_pos = 0;
|
||||
}
|
||||
led_beat((pattern_pos % 8) + 1);
|
||||
}
|
||||
|
||||
void drums_init(void)
|
||||
{
|
||||
dsample[0] = drumkit_0_au;
|
||||
dsample[1] = drumkit_1_au;
|
||||
dsample[2] = drumkit_2_au;
|
||||
dsample[3] = drumkit_3_au;
|
||||
dsample[4] = drumkit_4_au;
|
||||
dsample[5] = drumkit_5_au;
|
||||
dsample[6] = drumkit_6_au;
|
||||
|
||||
dsample_len[0] = drumkit_0_au_len;
|
||||
dsample_len[1] = drumkit_1_au_len;
|
||||
dsample_len[2] = drumkit_2_au_len;
|
||||
dsample_len[3] = drumkit_3_au_len;
|
||||
dsample_len[4] = drumkit_4_au_len;
|
||||
dsample_len[5] = drumkit_5_au_len;
|
||||
dsample_len[6] = drumkit_6_au_len;
|
||||
}
|
||||
|
||||
void drums_start(void)
|
||||
{
|
||||
timer_set_beat_callback(beat_cb);
|
||||
}
|
||||
|
||||
void drums_stop(void)
|
||||
{
|
||||
timer_clear_beat_callback();
|
||||
}
|
||||
|
||||
void drums_set_pattern_len(int l)
|
||||
{
|
||||
pattern_len = l;
|
||||
timer_set_beat(1);
|
||||
}
|
||||
|
||||
void drums_set(uint32_t track, int pos)
|
||||
{
|
||||
pattern[pos] |= track;
|
||||
}
|
||||
|
||||
void drums_clear(uint32_t track, int pos)
|
||||
{
|
||||
pattern[pos] &= ~track;
|
||||
}
|
17
led.c
17
led.c
|
@ -43,14 +43,15 @@
|
|||
|
||||
|
||||
struct pin Leds[9] = {
|
||||
{ GPIOE, 1 << 0 },
|
||||
{ GPIOE, 1 << 10 },
|
||||
{ GPIOB, 1 << 2 },
|
||||
{ GPIOE, 1 << 8 },
|
||||
{ GPIOE, 1 << 9 },
|
||||
{ GPIOE, 1 << 1 },
|
||||
{ GPIOB, 1 << 8 },
|
||||
{ GPIOB, 1 << 9 },
|
||||
{ GPIOE, LD0 },
|
||||
{ GPIOE, LD1 },
|
||||
{ GPIOB, LD2 },
|
||||
{ GPIOE, LD3 },
|
||||
{ GPIOE, LD4 },
|
||||
{ GPIOE, LD5 },
|
||||
{ GPIOE, LD6 },
|
||||
{ GPIOB, LD7 },
|
||||
{ GPIOB, LD8 },
|
||||
};
|
||||
|
||||
void led_setup(void)
|
||||
|
|
11
main.c
11
main.c
|
@ -39,7 +39,9 @@ static void bootlevel_0(void)
|
|||
printf("Buttons initialized.\r\n");
|
||||
}
|
||||
|
||||
extern void timer_init(void);
|
||||
extern int timer_init(uint32_t bpm);
|
||||
extern int timer_start();
|
||||
extern int timer_stop();
|
||||
|
||||
static void bootlevel_1(void)
|
||||
{
|
||||
|
@ -64,8 +66,9 @@ static void bootlevel_1(void)
|
|||
printf("Displaying splash screen...\r\n");
|
||||
ui_init();
|
||||
printf("UI initialized.\r\n");
|
||||
//djhero_init();
|
||||
timer_init();
|
||||
timer_init(60);
|
||||
drums_init();
|
||||
drums_start();
|
||||
|
||||
printf("System up and running.\r\n\n\n");
|
||||
}
|
||||
|
@ -126,6 +129,8 @@ int main(void) {
|
|||
led_on(LED);
|
||||
poll_time = jiffies;
|
||||
|
||||
timer_poll();
|
||||
|
||||
if (!keepalive_callback)
|
||||
ui_keepalive(hb_len);
|
||||
else
|
||||
|
|
21
make_drumkit.sh
Executable file
21
make_drumkit.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
## Usage example:
|
||||
## ./make_drumkit.sh kick1.wav hihat1.wav snare3.wav tom1.wav tom2.wav cowbell.wav clap.wav
|
||||
|
||||
IDX=0
|
||||
|
||||
for i in $@; do
|
||||
echo $i
|
||||
sox $i -r 22050 -t u8 drumkit_$IDX.au || exit 1
|
||||
#sox $i -t u8 drumkit_$IDX.au
|
||||
|
||||
xxd -i drumkit_$IDX.au drumkit_$IDX.c
|
||||
# xxd -i drumkit_$IDX.au drumkit_tmp_$IDX.c
|
||||
# cat drumkit_tmp_$IDX.c | sed -e "s/unsigned /const unsigned /g" >drumkit_$IDX.c
|
||||
# rm drumkit_$IDX.au
|
||||
IDX=`expr $IDX + 1`
|
||||
done
|
||||
|
||||
#rm -f drumkit_tmp_* drumkit_*.au
|
2
sound.c
2
sound.c
|
@ -1,4 +1,4 @@
|
|||
const unsigned char raw_au[] = {
|
||||
unsigned char raw_au[] = {
|
||||
0x57, 0x5a, 0x58, 0x59, 0x58, 0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x56,
|
||||
0x55, 0x55, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x54, 0x53, 0x54,
|
||||
0x54, 0x53, 0x53, 0x54, 0x53, 0x53, 0x53, 0x53, 0x52, 0x53, 0x53, 0x52,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 256K - 0x100
|
||||
RAM (rw) : ORIGIN = 0x20001000, LENGTH = 60K
|
||||
RAM (rw) : ORIGIN = 0x20001000, LENGTH = 252K
|
||||
RAM_S (rw) : ORIGIN = 0x20000000, LENGTH = 4K
|
||||
}
|
||||
|
||||
|
|
113
timer.c
113
timer.c
|
@ -1,37 +1,95 @@
|
|||
#include <stdint.h>
|
||||
#include "system.h"
|
||||
#include "led.h"
|
||||
#include "timer.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static uint32_t master_clock = 0;
|
||||
#define S_PER_MINUTE (60)
|
||||
|
||||
/* Timer 4: Use val 60000 with PSC 1400 for 1s tick (84 Mhz) */
|
||||
/* Timer 4: Use val 52500 with PSC 200 for 1/8 s tick (84 Mhz) */
|
||||
extern uint32_t cpu_freq;
|
||||
static uint32_t sys_bpm = 75;
|
||||
|
||||
#define TMR4_INIT_VAL 52500
|
||||
#define TMR4_INIT_PSC 200
|
||||
void (*beat_callback)(uint32_t b) = NULL;
|
||||
|
||||
void timer_init(void)
|
||||
void timer_set_beat_callback(void (*b_cb)(uint32_t))
|
||||
{
|
||||
beat_callback = b_cb;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);;
|
||||
|
||||
while (psc < 65535) {
|
||||
val = clock / psc;
|
||||
err = clock % psc;
|
||||
if ((val < 65535) && (err < (psc / 2))) {
|
||||
val--;
|
||||
break;
|
||||
}
|
||||
val = 0;
|
||||
psc++;
|
||||
}
|
||||
if (val == 0)
|
||||
return -1;
|
||||
TIM4_CR1 = 0;
|
||||
__asm__ volatile ("dmb");
|
||||
TIM4_PSC = psc;
|
||||
TIM4_ARR = val;
|
||||
TIM4_CNT = val - 1;
|
||||
sys_bpm = bpm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timer_start(void)
|
||||
{
|
||||
TIM4_CR1 |= TIM_CR1_CLOCK_ENABLE;
|
||||
TIM4_DIER |= TIM_DIER_UIE;
|
||||
}
|
||||
|
||||
int timer_stop(void)
|
||||
{
|
||||
TIM4_CR1 |= TIM_CR1_CLOCK_ENABLE;
|
||||
TIM4_DIER |= TIM_DIER_UIE;
|
||||
}
|
||||
|
||||
static void timer_irq_setup(void)
|
||||
{
|
||||
nvic_irq_enable(NVIC_TIM4_IRQN);
|
||||
nvic_irq_setprio(NVIC_TIM4_IRQN, 0);
|
||||
APB1_CLOCK_RST |= TIM4_APB1_CLOCK_ER_VAL;
|
||||
__asm__ volatile ("dmb");
|
||||
APB1_CLOCK_RST &= ~TIM4_APB1_CLOCK_ER_VAL;
|
||||
APB1_CLOCK_ER |= TIM4_APB1_CLOCK_ER_VAL;
|
||||
}
|
||||
|
||||
TIM4_CR1 = 0;
|
||||
__asm__ volatile ("dmb");
|
||||
TIM4_PSC = TMR4_INIT_PSC;
|
||||
TIM4_ARR = TMR4_INIT_VAL;
|
||||
TIM4_CR1 |= TIM_CR1_CLOCK_ENABLE;
|
||||
TIM4_DIER |= TIM_DIER_UIE;
|
||||
__asm__ volatile ("dmb");
|
||||
|
||||
int timer_init(uint32_t bpm)
|
||||
{
|
||||
timer_stop();
|
||||
timer_irq_setup();
|
||||
timer_set_bpm(bpm);
|
||||
timer_start();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static volatile uint32_t tim4_ticks = 0;
|
||||
static volatile int pending_cb = 0;
|
||||
void isr_tim1(void)
|
||||
{
|
||||
TIM1_SR &= ~TIM_SR_UIF;
|
||||
|
@ -42,16 +100,35 @@ void isr_tim3(void)
|
|||
TIM3_SR &= ~TIM_SR_UIF;
|
||||
}
|
||||
|
||||
static int beat = 1;
|
||||
int timer_get_beat(void)
|
||||
{
|
||||
return beat;
|
||||
}
|
||||
|
||||
void timer_set_beat(int b)
|
||||
{
|
||||
beat = b;
|
||||
}
|
||||
|
||||
void timer_poll(void)
|
||||
{
|
||||
if (beat_callback && (pending_cb > 0)) {
|
||||
pending_cb--;
|
||||
beat_callback(beat);
|
||||
beat++;
|
||||
}
|
||||
}
|
||||
|
||||
void isr_tim4(void)
|
||||
{
|
||||
TIM4_SR &= ~TIM_SR_UIF;
|
||||
tim4_ticks++;
|
||||
if (beat_callback) {
|
||||
pending_cb++;
|
||||
} else {
|
||||
led_beat((beat % 8) + 1);
|
||||
}
|
||||
|
||||
void gettime(uint32_t *seconds, uint32_t *microseconds)
|
||||
{
|
||||
*microseconds = ((TIM4_CNT * TMR4_INIT_PSC) / 84) + (tim4_ticks & 0x07) * 125000;
|
||||
*seconds = (tim4_ticks >> 3);
|
||||
}
|
||||
|
||||
|
||||
|
|
28
timer.h
Normal file
28
timer.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef TIMER_H_INCLUDED
|
||||
#define TIMER_H_INCLUDED
|
||||
|
||||
uint32_t timer_get_bpm(void);
|
||||
int timer_set_bpm(uint32_t bpm);
|
||||
int timer_start(void);
|
||||
int timer_stop(void);
|
||||
int timer_init(uint32_t bpm);
|
||||
void timer_set_beat_callback(void (*b_cb)(uint32_t));
|
||||
void timer_clear_beat_callback(void);
|
||||
|
||||
extern unsigned char drumkit_0_au[],
|
||||
drumkit_1_au[],
|
||||
drumkit_2_au[],
|
||||
drumkit_3_au[],
|
||||
drumkit_4_au[],
|
||||
drumkit_5_au[],
|
||||
drumkit_6_au[];
|
||||
|
||||
extern unsigned int drumkit_0_au_len,
|
||||
drumkit_1_au_len,
|
||||
drumkit_2_au_len,
|
||||
drumkit_3_au_len,
|
||||
drumkit_4_au_len,
|
||||
drumkit_5_au_len,
|
||||
drumkit_6_au_len;
|
||||
|
||||
#endif
|
4
ui.c
4
ui.c
|
@ -14,6 +14,8 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "ui.h"
|
||||
#include "timer.h"
|
||||
#include "led.h"
|
||||
|
||||
|
||||
/* Uncomment for device initialization */
|
||||
|
@ -170,7 +172,7 @@ void ui_init(void)
|
|||
now = jiffies;
|
||||
for (i = 1; i < 9; i++) {
|
||||
led_beat(i);
|
||||
while((jiffies - now < 100))
|
||||
while((jiffies - now < 10))
|
||||
WFI();
|
||||
now = jiffies;
|
||||
}
|
||||
|
|
66
ui_drone.c
66
ui_drone.c
|
@ -49,16 +49,20 @@ static void display_drone(int line, uint16_t val)
|
|||
display_text(line, txt);
|
||||
}
|
||||
|
||||
static void display_volume(void)
|
||||
static void display_thousand(uint32_t val)
|
||||
{
|
||||
char txt[4] = "000";
|
||||
int master_vol = pot_get_master();
|
||||
txt[0] = '0' + master_vol / 100;
|
||||
txt[1] = '0' + (master_vol % 100) / 10;
|
||||
txt[2] = '0' + (master_vol % 10);
|
||||
txt[0] = '0' + val / 100;
|
||||
txt[1] = '0' + (val % 100) / 10;
|
||||
txt[2] = '0' + (val % 10);
|
||||
display_text(6, txt);
|
||||
}
|
||||
|
||||
static void display_volume(void)
|
||||
{
|
||||
display_thousand(pot_get_master());
|
||||
}
|
||||
|
||||
void ui_drone_xy_poll(void)
|
||||
{
|
||||
uint16_t x = 0, y = 0;
|
||||
|
@ -157,7 +161,7 @@ static void ui_mastervol_input(uint8_t press, int hold)
|
|||
{
|
||||
int master_vol = pot_get_master();
|
||||
if (press == 'U')
|
||||
if (master_vol < 1000)
|
||||
if (master_vol < 100)
|
||||
pot_set_master(master_vol + 5);
|
||||
|
||||
if (press == 'D') {
|
||||
|
@ -182,6 +186,45 @@ static void ui_mastervol(const void *arg)
|
|||
display_volume();
|
||||
}
|
||||
|
||||
static void ui_bpm_input(uint8_t press, int hold)
|
||||
{
|
||||
uint32_t sys_bpm = timer_get_bpm();
|
||||
if (press == 'U') {
|
||||
if (sys_bpm < 300) {
|
||||
timer_stop();
|
||||
timer_set_bpm(sys_bpm + 1);
|
||||
led_beat(1);
|
||||
timer_set_beat(1);
|
||||
timer_start();
|
||||
}
|
||||
}
|
||||
|
||||
if (press == 'D') {
|
||||
if (sys_bpm > 60) {
|
||||
timer_stop();
|
||||
timer_set_bpm(sys_bpm - 1);
|
||||
led_beat(1);
|
||||
timer_set_beat(1);
|
||||
timer_start();
|
||||
}
|
||||
}
|
||||
if (press == '+') {
|
||||
display_clear(NULL);
|
||||
clear_input_callback();
|
||||
ui_display_menu(&MainMenu);
|
||||
return;
|
||||
}
|
||||
display_text(5, " BPM ");
|
||||
display_thousand(timer_get_bpm());
|
||||
}
|
||||
|
||||
static void ui_bpm(const void *arg)
|
||||
{
|
||||
set_input_callback(ui_bpm_input);
|
||||
display_clear(NULL);
|
||||
display_text(5, " BPM ");
|
||||
display_thousand(timer_get_bpm());
|
||||
}
|
||||
|
||||
static void ui_bytebeat_input(uint8_t press, int hold) {
|
||||
if (press == '+') {
|
||||
|
@ -194,22 +237,23 @@ static void ui_bytebeat_input(uint8_t press, int hold) {
|
|||
|
||||
#define PLAY_SIZE 512
|
||||
|
||||
|
||||
static uint8_t bb_buffer[PLAY_SIZE];
|
||||
|
||||
void ui_bytebeat_keepalive(void)
|
||||
{
|
||||
static uint32_t t = 0;
|
||||
int r = 0;
|
||||
if (dac_space() >= PLAY_SIZE) {
|
||||
for(;;t++) {
|
||||
for(r = 0;;t++) {
|
||||
while (dac_is_busy())
|
||||
WFI();
|
||||
bb_buffer[r++] = (t<<1)|(t>>4)*(((t>>12)|(t>>13)|(t>>6) | ((t>>2)|(t>>4))|(t<<1)|(t<<12)|((t<<5)&~(t>>22))));
|
||||
if (r >= PLAY_SIZE) {
|
||||
dac_write(bb_buffer, r);
|
||||
dac_play_direct(bb_buffer, r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_bytebeat(const void *arg)
|
||||
{
|
||||
|
@ -254,7 +298,7 @@ const struct display_menu MainMenu = {
|
|||
.entry_n = 5,
|
||||
.entry = {
|
||||
{ "Master Volume ", ui_mastervol, NULL },
|
||||
{ "Settings ", ui_submenu, &SettingsMenu },
|
||||
{ "BPM" , ui_bpm, NULL},
|
||||
{ "Pattern ", ui_submenu, &PatternMenu },
|
||||
{ "Drone ", ui_submenu, &DroneMenu},
|
||||
{ "Bytebeat ", ui_bytebeat },
|
||||
|
|
Loading…
Reference in a new issue