227 lines
5.3 KiB
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();
|
|
}
|
|
|
|
|