253 lines
6.6 KiB
C
253 lines
6.6 KiB
C
/*
|
|
* (c) danielinux 2020
|
|
* GPLv.2
|
|
*
|
|
* See LICENSE for details
|
|
*/
|
|
|
|
#include <unicore-mx/cm3/nvic.h>
|
|
#include <unicore-mx/stm32/dma.h>
|
|
#include <unicore-mx/stm32/dac.h>
|
|
#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_MEMSIZ (4 * DAC_BUFSIZ)
|
|
extern const unsigned char raw_au[];
|
|
extern volatile uint32_t jiffies;
|
|
const unsigned int raw_au_len;
|
|
|
|
static int dac_transfer_size;
|
|
|
|
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;
|
|
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_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_space(void)
|
|
{
|
|
return DAC_MEMSIZ - dac_transfer_size;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* IRQ Handler */
|
|
void dma1_stream5_isr(void)
|
|
{
|
|
if (dma_get_interrupt_flag(DMA1, DMA_STREAM5, DMA_TCIF)) {
|
|
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;
|
|
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 */
|
|
|
|
//#define PERIOD (5200)
|
|
#define PERIOD 8800
|
|
static void timer_setup(void)
|
|
{
|
|
/* Enable TIM2 clock. */
|
|
rcc_periph_clock_enable(RCC_TIM2);
|
|
timer_reset(TIM2);
|
|
/* Timer global mode: - No divider, Alignment edge, Direction up */
|
|
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT,
|
|
TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
|
|
timer_continuous_mode(TIM2);
|
|
timer_set_period(TIM2, PERIOD);
|
|
timer_disable_oc_output(TIM2, TIM_OC2 | TIM_OC3 | TIM_OC4);
|
|
timer_enable_oc_output(TIM2, TIM_OC1);
|
|
timer_disable_oc_clear(TIM2, TIM_OC1);
|
|
timer_disable_oc_preload(TIM2, TIM_OC1);
|
|
timer_set_oc_slow_mode(TIM2, TIM_OC1);
|
|
timer_set_oc_mode(TIM2, TIM_OC1, TIM_OCM_TOGGLE);
|
|
timer_set_oc_value(TIM2, TIM_OC1, 500);
|
|
timer_disable_preload(TIM2);
|
|
/* Set the timer trigger output (for the DAC) to the channel 1 output
|
|
* compare */
|
|
timer_set_master_mode(TIM2, TIM_CR2_MMS_COMPARE_OC1REF);
|
|
timer_enable_counter(TIM2);
|
|
}
|
|
|
|
|
|
static void dac_dma_setup(void)
|
|
{
|
|
/* DAC channel 1 uses DMA controller 1 Stream 5 Channel 7. */
|
|
/* Enable DMA1 clock and IRQ */
|
|
rcc_periph_clock_enable(RCC_DMA1);
|
|
nvic_set_priority(NVIC_DMA1_STREAM5_IRQ, 1);
|
|
nvic_enable_irq(NVIC_DMA1_STREAM5_IRQ);
|
|
dma_stream_reset(DMA1, DMA_STREAM5);
|
|
dma_set_priority(DMA1, DMA_STREAM5, DMA_SxCR_PL_LOW);
|
|
dma_set_memory_size(DMA1, DMA_STREAM5, DMA_SxCR_MSIZE_8BIT);
|
|
dma_set_peripheral_size(DMA1, DMA_STREAM5, DMA_SxCR_PSIZE_8BIT);
|
|
dma_enable_memory_increment_mode(DMA1, DMA_STREAM5);
|
|
dma_enable_circular_mode(DMA1, DMA_STREAM5);
|
|
dma_set_transfer_mode(DMA1, DMA_STREAM5,
|
|
DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
|
|
/* The register to target is the DAC1 8-bit right justified data
|
|
register */
|
|
dma_set_peripheral_address(DMA1, DMA_STREAM5, (uint32_t) &DAC_DHR8R1);
|
|
}
|
|
|
|
static void dac_hw_init(data_channel c)
|
|
{
|
|
/* Set DAC GPIO pin to analog mode */
|
|
rcc_periph_clock_enable(RCC_GPIOC);
|
|
gpio_mode_setup(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4);
|
|
timer_setup();
|
|
|
|
/* Set up DAC */
|
|
rcc_periph_clock_enable(RCC_DAC);
|
|
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;
|
|
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(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;
|
|
}
|