Conquering the STM32F4 on the discovery board step-by-step. Commit history is tutorialesque, but not clean of course.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

259 lines
6.2 KiB

#include "cppmain.h"
#include "init.h"
#include "usbd_cdc_if.h"
//#include "usb_device.h"
//#include "cmsis_os.h"
#include <cmath>
#include "limits"
const double pi{ std::acos(-1) };
#define BUFFER_SIZE 512
namespace Heck {
bool debug_suspend_active = false;
void debug_suspend_continue() {
debug_suspend_active = false;
}
// Serial Logging
// --------------
void log(std::string msg)
{
std::string out{ msg };
out.append("\r\n");
CDC_Transmit_FS((uint8_t *)out.data(), out.size());
}
// DAC
// ---
u32 audio_buffer[BUFFER_SIZE];
void dac1_set(u32 val)
{
HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, val);
}
void dac1_toggle()
{
static bool dac_state{ 0 };
dac_state = !dac_state;
if (dac_state) {
dac1_set(0b0000111111111111);
} else {
dac1_set(0b0000000000000000);
}
}
void dac_start_dma()
{
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (u32 *)audio_buffer, BUFFER_SIZE, DAC_ALIGN_12B_R);
}
void dac_stop_dma()
{
HAL_DAC_Stop_DMA(&hdac1, DAC_CHANNEL_1);
}
// 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()
{
debug_suspend_continue();
}
void timer2_cb()
{
led_green_toggle();
}
void timer7_cb() {}
// dont forget to start the DAC
// HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
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);
}
}
u32 random(u32 max)
{
u32 ret{ 0 };
HAL_RNG_GenerateRandomNumber(&hrng, &ret);
ret %= max;
return ret;
}
void buffer_init_noise()
{
log("buffer_init_noise()");
for (int i = 0; i < BUFFER_SIZE; i++) {
u32 val = random(4096);
audio_buffer[i] = val;
log(std::to_string(val));
}
}
void buffer_init_sin()
{
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) * 4096;
audio_buffer[i] = val;
log(std::to_string(val));
}
}
void buffer_div(int div)
{
log("init_scale()");
for (int i = 0; i < BUFFER_SIZE; i++) {
u32 val = audio_buffer[i] / div;
audio_buffer[i] = val;
log(std::to_string(val));
}
}
void buffer_randomize(int max)
{
log("buffer_randomize()");
u32 buf_index = random(BUFFER_SIZE);
u32 buf_val = random(max);
audio_buffer[buf_index] = buf_val;
log("i:" + std::to_string(buf_index) + " v:" + std::to_string(buf_val));
}
void main()
{
heck_debug_suspend();
log("Starting...");
dac_start_dma();
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim7);
HAL_TIM_Base_Start(&htim6);
// init_buffer_noise();
buffer_init_sin();
buffer_div(10);
log("Entering MainLoop...");
while (true) {
// buffer_randomize(400);
HAL_Delay(10);
}
}
} // namespace Heck
// ----------------------------------------------------------------------------------------------
// C Linkage (Bridging)
// ----------------------------------------------------------------------------------------------
extern "C" void heck_debug_suspend(void) {
Heck::debug_suspend_active = true;
while(Heck::debug_suspend_active == true) {
Heck::log("debug_suspend...");
HAL_Delay(1000);
}
}
extern "C" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0) {
Heck::irq1_cb();
} else {
__NOP(); // why NOP? i dont know! was from an example
}
}
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));
Heck::timer2_cb();
} else if (htim->Instance == TIM6) {
Heck::log(
"TIM6 timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
" channel: " + std::to_string(htim->Channel));
} else if (htim->Instance == TIM7) {
Heck::log(
"TIM7 timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
" channel: " + std::to_string(htim->Channel));
Heck::timer7_cb();
} else {
Heck::log(
"UNKNOWN timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
" channel: " + std::to_string(htim->Channel));
}
}
extern "C" void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
{
Heck::dac_start_dma();
}
extern "C" void heck_log(char *msg)
{
Heck::log(std::string(msg));
}
extern "C" void heck_cppmain(void)
{
Heck::main();
}
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
extern "C" void assert_failed(uint8_t *file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
int str_size = 1024;
char str[str_size];
snprintf(str, str_size, "assert failed: %s:%d",file,line);
heck_log(str);
}
extern "C" void Error_Handler(void)
{
heck_log("Error_Handler StR1keZ!");
__disable_irq();
while (1) {}
}