Conquering the STM32F4 on the discovery board step-by-step. Commit history is tutorialesque, but not clean of course.
 
 
 
 
 

227 lines
5.3 KiB

#include "cppmain.h"
#include "init.h"
#include "utils.h"
#include <cmath>
#include <bitset>
#include "limits"
#include <sstream>
#include <iomanip>
#define SAMPLE_FREQ 42000
#define SAMPLE_MAX 4096
#define BUFFER_SIZE 256
#define BLOCK_SIZE 128
const double pi{ std::acos(-1) };
// Buffer and block
static u32 audio_buffer[BUFFER_SIZE];
static u32 *block = &audio_buffer[0];
static volatile bool process_block{ true };
static volatile bool process_block2{ true };
// time
static u64 inf_phasor{ 0 };
namespace ut = Heck::Utils;
namespace Heck {
// LED
// ---
void led_green_toggle()
{
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
}
void led_green_on()
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
}
void led_green_off()
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
}
// CALLBACKS
void irq1_cb()
{
ut::debug_suspend_continue();
}
void timer3_cb()
{
led_green_toggle();
}
void bytebeat()
{
long t{ 0 };
while (true) {
unsigned char res = t * ((t >> 12 | t >> 8) & 63 & t >> 4);
dac1_set((res % 256) * 100);
for (int g = 0; g < 60000; g++) {}
t++;
t %= (std::numeric_limits<long>::max() - 1);
}
}
void buffer_init_noise()
{
ut::log("buffer_init_noise()");
for (int i = 0; i < BUFFER_SIZE; i++) {
u32 val = ut::random(SAMPLE_MAX);
audio_buffer[i] = val;
}
}
void block_fill_saw()
{
u32 *b = block;
u32 step = (SAMPLE_MAX - (SAMPLE_MAX / 4)) / BLOCK_SIZE;
for (int i = 0; i < BLOCK_SIZE; i++) {
u32 val = i * step;
b[i] = val;
}
}
void buffer_init_sin()
{
ut::log("buffer_init_sin()");
for (int i = 0; i < BUFFER_SIZE; i++) {
float p = float(i) / (float)BUFFER_SIZE - 0.5;
u32 val = sin(p) * SAMPLE_MAX;
audio_buffer[i] = val;
}
}
void buffer_div(int div)
{
ut::log("init_scale()");
for (int i = 0; i < BUFFER_SIZE; i++) {
u32 val = audio_buffer[i] / div;
audio_buffer[i] = val;
}
}
void buffer_randomize(int max)
{
ut::log("buffer_randomize()");
u32 buf_index = ut::random(BUFFER_SIZE);
u32 buf_val = ut::random(max);
audio_buffer[buf_index] = buf_val;
}
u32 hz_to_samps(float hz)
{
return (u32)floor((float)SAMPLE_FREQ / (float)hz);
}
u32 saw(u64 t, float freq_hz)
{
u32 ret{ 0 };
u32 samps = hz_to_samps(freq_hz);
u32 normalizing_factor = SAMPLE_MAX / samps;
ret = t % samps;
ret *= normalizing_factor;
return ret;
}
void calculate_audio()
{
// log("calculate_audio time: ");
u32 *b = block;
u64 t = inf_phasor;
for (int i = 0; i < BLOCK_SIZE; i++) {
b[i] = saw(t, 80);
// b[i] *= saw(t, 20);
t++;
}
}
std::string block_to_string()
{
u32 *b = block;
std::stringstream ss{};
for (int i = 0; i < BLOCK_SIZE; i++) {
ss << std::setw(4) << b[i] << " ";
}
return ss.str();
}
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_TIM_Base_Start_IT(&htim_dac1);
ut::log("Entering MainLoop...");
while (true) {
if (process_block) {
process_block = false;
calculate_audio();
inf_phasor += BLOCK_SIZE;
}
}
}
} // namespace Heck
// ----------------------------------------------------------------------------------------------
// C Linkage (Bridging)
// ----------------------------------------------------------------------------------------------
extern "C" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0) {
Heck::irq1_cb();
}
}
extern "C" void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM2) {
// Heck::log(
// "TIM2 timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
// " channel: " + std::to_string(htim->Channel));
} else if (htim->Instance == TIM3) {
ut::log(
"TIM3 timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
" channel: " + std::to_string(htim->Channel));
Heck::timer3_cb();
} else {
ut::log(
"UNKNOWN timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
" channel: " + std::to_string(htim->Channel));
}
}
extern "C" void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef *hdac)
{
// Heck::log("HAL_DAC_ConvHalfCpltCallbackCh1");
block = &audio_buffer[0];
process_block = true;
}
extern "C" void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
{
// Heck::log("HAL_DAC_ConvCpltCallbackCh1");
block = &audio_buffer[BLOCK_SIZE];
process_block = true;
}
extern "C" void heck_cppmain(void)
{
Heck::main();
}