|
|
@ -7,23 +7,34 @@ |
|
|
|
#include "limits" |
|
|
|
#include <sstream> |
|
|
|
#include <iomanip> |
|
|
|
|
|
|
|
#define SAMPLE_FREQ 42000 |
|
|
|
#define SAMPLE_MAX 4096 |
|
|
|
#define BUFFER_SIZE 256 |
|
|
|
#define BLOCK_SIZE 128 |
|
|
|
#include <array> |
|
|
|
|
|
|
|
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<u32, BUFFER_SIZE> audio_buffer; |
|
|
|
static u32 *block = &audio_buffer[0]; |
|
|
|
|
|
|
|
static std::array<float, BLOCK_SIZE> 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<float, POTCOUNT> 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<float>(in) / 4095.f; |
|
|
|
} |
|
|
|
|
|
|
|
void float_to_u12(float &in, u32 &out) |
|
|
|
{ |
|
|
|
out = static_cast<u32>(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(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|