diff --git a/Makefile.conf b/Makefile.conf index afc7de7..ee9f307 100644 --- a/Makefile.conf +++ b/Makefile.conf @@ -36,3 +36,5 @@ CXXFLAGS:=$(CFLAGS) CFLAGS+= -std=gnu11 CXXFLAGS+= -std=c++17 + +LINKER_SCRIPT=STM32F407VGTX_FLASH.ld \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index 2dac74d..23b08f9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,8 +21,7 @@ LIB_OBJ+=$(wildcard ../libs/STM32F4xx_HAL_Driver/Src/*.o) LIB_OBJ+=$(wildcard ../libs/st_usb/*.o) LDFLAGS+= -Wl,-gc-sections,--print-memory-usage,-Map=$(TARGET_MAP) -LDFLAGS+= -T STM32F407VGTX_FLASH.ld - +LDFLAGS+= -T $(LINKER_SCRIPT) C_SRC=$(wildcard *.c) C_OBJ=$(subst .c,.o,$(C_SRC)) diff --git a/src/cppmain.cc b/src/cppmain.cc index 7be5184..36ee8c7 100644 --- a/src/cppmain.cc +++ b/src/cppmain.cc @@ -7,23 +7,34 @@ #include "limits" #include #include - -#define SAMPLE_FREQ 42000 -#define SAMPLE_MAX 4096 -#define BUFFER_SIZE 256 -#define BLOCK_SIZE 128 +#include const double pi{ std::acos(-1) }; + +constexpr u32 SAMPLE_FREQ = 42000U; +constexpr u32 SAMPLE_MIN = 0U; +constexpr u32 SAMPLE_MAX = 4095U; +constexpr float SAMPLE_MIN_FLOAT = -1.0f; +constexpr float SAMPLE_MAX_FLOAT = 1.0f; +constexpr u32 BUFFER_SIZE = 128; +constexpr u32 BLOCK_SIZE = BUFFER_SIZE / 2; + + // Buffer and block -static u32 audio_buffer[BUFFER_SIZE]; +static std::array audio_buffer; static u32 *block = &audio_buffer[0]; + +static std::array block_float; static volatile bool process_block{ true }; -static volatile bool process_block2{ true }; -static volatile u32 pot1{ 0 }; +// Pots +constexpr u32 POTCOUNT = 3; +static u32 pot_nr_current = 0; +static std::array pot = {}; + // time -static u64 inf_phasor{ 0 }; +static u64 sample_clock{ 0 }; namespace ut = Heck::Utils; @@ -57,6 +68,7 @@ namespace Heck { led_green_toggle(); } + void bytebeat() { long t{ 0 }; @@ -88,6 +100,15 @@ namespace Heck { } } + void block_float_saw_unipolar() + { + float step = SAMPLE_MAX_FLOAT / BLOCK_SIZE; + for (int i = 0; i < BLOCK_SIZE; i++) { + float val = (float)i * step; + block_float[i] = val; + } + } + void buffer_init_sin() { ut::log("buffer_init_sin()"); @@ -144,40 +165,101 @@ namespace Heck { return ss.str(); } - void calculate_audio() + + void u12_to_float(u32 &in, float &out) { - // log("calculate_audio time: "); - u32 *b = block; - u64 t = inf_phasor; + out = static_cast(in) / 4095.f; + } + + void float_to_u12(float &in, u32 &out) + { + out = static_cast(in * 4095.f); + } + + void saw_next_samp(float *out, float freq) + { + static float val{ 0 }; + val += SAMPLE_MAX_FLOAT / SAMPLE_FREQ * freq; + val = std::fmod(val, 1.0); + *out = val; + } + + void sine_from_saw(float *sig) + { + *sig = sin(*sig * 2.f * pi) / 2.f + 0.5f; + } + + void waveshape(float *sig, float amt) + { + *sig = std::tanh(*sig * amt); + } + void calculate_block_float() + { + float *sig = &block_float[0]; for (int i = 0; i < BLOCK_SIZE; i++) { - b[i] = saw(t, pot1); - // b[i] *= saw(t, 20); - t++; + sig = &block_float[i]; + saw_next_samp(sig, pot[0] * 1000.f); + sine_from_saw(sig); + waveshape(sig, pot[1] * 2.f); + } + } + + + void pot_select_current(u32 pot_nr) + { + if (pot_nr != pot_nr_current) { + adc2_select_channel(pot_nr); + pot_nr_current = pot_nr; } } + void pot_read() + { + HAL_ADC_Start(&hadc1); + // HAL_ADC_PollForConversion(&hadc1, 1); + u32 pot1_tmp = HAL_ADC_GetValue(&hadc1); + // Fixme: add stabilization + u12_to_float(pot1_tmp, pot[pot_nr_current]); + +// HAL_ADC_Stop(&hadc1); + // ut::log("pot[" + std::to_string(pot_nr_current) + "]: " + std::to_string(pot[pot_nr_current])); + } + + void read_next_pot() + { + pot_select_current(pot_nr_current); + pot_read(); + pot_nr_current++; + pot_nr_current %= POTCOUNT; + } + void main() { heck_debug_suspend(); ut::log("Starting..."); HAL_TIM_Base_Start_IT(&htim_blinky_led); - HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, audio_buffer, BUFFER_SIZE, DAC_ALIGN_12B_R); + HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, audio_buffer.data(), BUFFER_SIZE, DAC_ALIGN_12B_R); HAL_TIM_Base_Start_IT(&htim_dac1); ut::log("Entering MainLoop..."); while (true) { if (process_block) { process_block = false; - calculate_audio(); - inf_phasor += BLOCK_SIZE; - } - HAL_ADC_Start(&hadc1); - HAL_ADC_PollForConversion(&hadc1, 1); - u32 pot1_tmp = HAL_ADC_GetValue(&hadc1); - if (std::abs(int(pot1 - pot1_tmp)) > 20) { - pot1 = pot1_tmp; - ut::log("pot1:" + std::to_string(pot1)); + + calculate_block_float(); + + u32 *b = block; + for (int i = 0; i < BLOCK_SIZE; i++) { + float_to_u12(block_float[i], b[i]); + } + + sample_clock += BLOCK_SIZE; + if (process_block == true) { + ut::log("UNDERRUN!"); + } + } else { + read_next_pot(); } } } diff --git a/src/cppmain.h b/src/cppmain.h index c51ce7f..071078e 100644 --- a/src/cppmain.h +++ b/src/cppmain.h @@ -43,6 +43,12 @@ namespace Heck { void bytebeat(); // MAIN + u32 saw(u64 t, float freq_hz); + u32 hz_to_samps(float hz); + std::string block_to_string(); + void u12_to_float(const u32 &in, float &out); + + void calculate_block_float(); void main(); } // namespace Heck #endif diff --git a/src/init.c b/src/init.c index 3245675..edf8b5d 100644 --- a/src/init.c +++ b/src/init.c @@ -224,13 +224,29 @@ void dac_init(void) // hdma_dac1.Parent = &hdac1; // hdac1.DMA_Handle1 = &hdma_dac1; // But this seems to be enough: - // hdac1.DMA_Handle1 = &hdma_dac1; + hdac1.DMA_Handle1 = &hdma_dac1; HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); } +// --- +// ADC +// --- + +ADC_ChannelConfTypeDef adc_channel_conf = {}; + +static uint32_t adc_channel_map[6] = { ADC_CHANNEL_1, ADC_CHANNEL_2, ADC_CHANNEL_3, + ADC_CHANNEL_4, ADC_CHANNEL_5, ADC_CHANNEL_6 }; + + +void adc2_select_channel(int channel_nr) +{ + adc_channel_conf.Channel = adc_channel_map[channel_nr]; + HAL_ADC_ConfigChannel(&hadc1,&adc_channel_conf); +} + void adc_init(void) { { @@ -280,30 +296,11 @@ void adc_init(void) Error_Handler(); } - ADC_ChannelConfTypeDef sConfig = {}; - sConfig.Channel = ADC_CHANNEL_1; - sConfig.Rank = 1; - sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES; - if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { - Error_Handler(); - } + adc_channel_conf.Rank = 1; + adc_channel_conf.Channel = adc_channel_map[0]; + adc_channel_conf.SamplingTime = ADC_SAMPLETIME_3CYCLES; - // // adc1->CR2 - // while (1) { - // // SET_BIT(adc1->CR2, ADC_CR2_ADON); - // // SET_BIT(adc1->CR2, ADC_CR2_SWSTART); - // HAL_ADC_Start(&hadc1); - // - // // heck_log("ADC123_COMMON->CCR:" + reg_to_string(adc_common->CCR)); - // // heck_log("ADC1->CR1:" + reg_to_string(adc1->CR1)); - // // heck_log("ADC1->CR2:" + reg_to_string(adc1->CR2)); - // // heck_log("ADC1->SQR1:" + reg_to_string(adc1->SQR1)); - // // heck_log("ADC1->SQR2:" + reg_to_string(adc1->SQR2)); - // // heck_log("ADC1->SQR3:" + reg_to_string(adc1->SQR3)); - // // heck_log("ADC1->DR:" + reg_to_string(adc1->DR)); - // heck_log("\n"); - // HAL_Delay(100); - // } + HAL_ADC_ConfigChannel(&hadc1,&adc_channel_conf); } void rng_init(void) diff --git a/src/init.h b/src/init.h index b0e51a1..e2835fa 100644 --- a/src/init.h +++ b/src/init.h @@ -16,6 +16,7 @@ extern "C" { extern RNG_HandleTypeDef hrng; void heck_init(); + void adc2_select_channel(int channel_nr); #ifdef __cplusplus } #endif