Compare commits

...

7 Commits
master ... tmp1

  1. 2
      Makefile.conf
  2. 3
      src/Makefile
  3. 344
      src/cppmain.cc
  4. 20
      src/cppmain.h
  5. 114
      src/init.c
  6. 3
      src/init.h
  7. 11
      src/types.hh
  8. 82
      src/utils.cc
  9. 41
      src/utils.h

2
Makefile.conf

@ -36,3 +36,5 @@ CXXFLAGS:=$(CFLAGS)
CFLAGS+= -std=gnu11
CXXFLAGS+= -std=c++17
LINKER_SCRIPT=STM32F407VGTX_FLASH.ld

3
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))

344
src/cppmain.cc

@ -1,47 +1,45 @@
#include "cppmain.h"
#include "init.h"
#include "usbd_cdc_if.h"
//#include "usb_device.h"
//#include "cmsis_os.h"
#include "utils.h"
#include <cmath>
#include <bitset>
#include "limits"
#include <sstream>
#define SAMPLE_FREQ 44200
#define SAMPLE_MAX 4096
#define DOUBLE_BUFFER_SIZE 16
#define BUFFER_SIZE 8
#include <iomanip>
#include <array>
const double pi{ std::acos(-1) };
static u32 double_buffer[DOUBLE_BUFFER_SIZE];
static u64 time{ 0 };
static volatile bool dma_to_dac_half_complete{ false };
static volatile bool dma_to_dac_complete{ false };
static volatile int freq = 100;
namespace Heck {
bool debug_suspend_active = false;
void debug_suspend_continue()
{
debug_suspend_active = false;
}
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;
// Serial Logging
// --------------
void log(std::string msg)
{
std::string out{ msg };
out.append("\r\n");
CDC_Transmit_FS((uint8_t *)out.data(), out.size());
}
// Buffer and block
static std::array<u32, BUFFER_SIZE> audio_buffer;
static u32 *block = &audio_buffer[0];
// DAC
// ---
static std::array<float, BLOCK_SIZE> block_float;
static volatile bool process_block{ true };
// Pots
constexpr u32 POTCOUNT = 3;
static u32 pot_nr_current = 0;
static std::array<float, POTCOUNT> pot = {};
// time
static u64 sample_clock{ 0 };
namespace ut = Heck::Utils;
namespace Heck {
// LED
// ---
void led_green_toggle()
@ -59,12 +57,10 @@ namespace Heck {
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
}
// CALLBACKS
void irq1_cb()
{
debug_suspend_continue();
freq += 10;
ut::debug_suspend_continue();
}
void timer3_cb()
@ -72,8 +68,7 @@ namespace Heck {
led_green_toggle();
}
// dont forget to start the DAC
// HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
void bytebeat()
{
long t{ 0 };
@ -86,103 +81,185 @@ namespace Heck {
}
}
u32 random(u32 max)
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 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()");
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 };
HAL_RNG_GenerateRandomNumber(&hrng, &ret);
ret %= max;
u32 samps = hz_to_samps(freq_hz);
u32 normalizing_factor = SAMPLE_MAX / samps;
ret = t % samps;
ret *= normalizing_factor;
return ret;
}
//
// void buffer_init_noise()
// {
// log("buffer_init_noise()");
// for (int i = 0; i < DOUBLE_BUFFER_SIZE; i++) {
// u32 val = random(SAMPLE_MAX);
// double_buffer[i] = val;
// log(std::to_string(val));
// }
// }
//
// void buffer_init_sin()
// {
// log("buffer_init_sin()");
// for (int i = 0; i < DOUBLE_BUFFER_SIZE; i++) {
// float p = float(i) / (float)DOUBLE_BUFFER_SIZE - 0.5;
// u32 val = sin(p) * SAMPLE_MAX;
// double_buffer[i] = val;
// log(std::to_string(val));
// }
// }
//
// void buffer_div(int div)
// {
// log("init_scale()");
// for (int i = 0; i < DOUBLE_BUFFER_SIZE; i++) {
// u32 val = double_buffer[i] / div;
// double_buffer[i] = val;
// log(std::to_string(val));
// }
// }
//
// void buffer_randomize(int max)
// {
// log("buffer_randomize()");
// u32 buf_index = random(DOUBLE_BUFFER_SIZE);
// u32 buf_val = random(max);
// double_buffer[buf_index] = buf_val;
// log("i:" + std::to_string(buf_index) + " v:" + std::to_string(buf_val));
// }
std::string reg_to_string(uint32_t val)
std::string block_to_string()
{
u32 *b = block;
std::stringstream ss{};
const std::bitset<32> x{ val };
ss << "0b" << x.to_string();
ss << " - ";
ss << std::to_string(val);
for (int i = 0; i < BLOCK_SIZE; i++) {
ss << std::setw(4) << b[i] << " ";
}
return ss.str();
}
u32 hz_to_samps(float hz)
void u12_to_float(u32 &in, float &out)
{
return (u32)floor((float)SAMPLE_FREQ / (float)hz);
out = static_cast<float>(in) / 4095.f;
}
void float_to_u12(float &in, u32 &out)
{
out = static_cast<u32>(in * 4095.f);
}
void calculate_audio(u32 *buffer)
void saw_next_samp(float *out, float freq)
{
log("calculate_audio time: ");
u64 t = time;
u32 samps = hz_to_samps(freq);
static float val{ 0 };
val += SAMPLE_MAX_FLOAT / SAMPLE_FREQ * freq;
val = std::fmod(val, 1.0);
*out = val;
}
for (int i = 0; i < BUFFER_SIZE; i++) {
buffer[i] = t % samps;
t++;
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++) {
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();
log("Starting...");
ut::log("Starting...");
HAL_TIM_Base_Start_IT(&htim_blinky_led);
HAL_DAC_Start_DMA(&hdac1, DAC_CHANNEL_1, (u32 *)double_buffer, DOUBLE_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);
log("Entering MainLoop...");
ut::log("Entering MainLoop...");
while (true) {
if (dma_to_dac_half_complete) {
calculate_audio(&double_buffer[0]);
time += BUFFER_SIZE;
dma_to_dac_half_complete = false;
}
if (dma_to_dac_complete) {
calculate_audio(&double_buffer[BUFFER_SIZE]);
time += BUFFER_SIZE;
dma_to_dac_complete = false;
if (process_block) {
process_block = false;
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();
}
}
}
@ -193,15 +270,6 @@ 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(10);
}
}
extern "C" void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0) {
@ -215,63 +283,33 @@ extern "C" void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
// Heck::log(
// "TIM2 timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
// " channel: " + std::to_string(htim->Channel));
// Heck::log(std::to_string(time));
} else if (htim->Instance == TIM3) {
Heck::log(
ut::log(
"TIM3 timer: instance: " + std::to_string(reinterpret_cast<u32>(htim->Instance)) +
" channel: " + std::to_string(htim->Channel));
Heck::timer3_cb();
} else {
Heck::log(
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");
dma_to_dac_half_complete = true;
// 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");
dma_to_dac_complete = true;
}
extern "C" void heck_log(char *msg)
{
Heck::log(std::string(msg));
// Heck::log("HAL_DAC_ConvCpltCallbackCh1");
block = &audio_buffer[BLOCK_SIZE];
process_block = true;
}
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) {}
}

20
src/cppmain.h

@ -9,13 +9,7 @@
extern "C" {
#endif
#include "stdint.h"
void heck_cppmain(void);
void heck_log(char* msg);
void heck_debug_suspend(void);
void assert_failed(uint8_t* file, uint32_t line);
void Error_Handler(void);
#ifdef __cplusplus
};
#endif
@ -26,18 +20,13 @@ extern "C" {
#ifdef __cplusplus
#include "types.hh"
#include <iostream>
#include <cstdint>
#include <string>
using u32 = uint32_t;
using u64 = uint64_t;
namespace Heck {
void debug_suspend_continue();
// Serial Logging
void log(std::string msg);
// DAC1
void dac1_set(uint32_t val);
@ -52,9 +41,14 @@ namespace Heck {
// misc
void bytebeat();
u32 random(u32 max);
// 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

114
src/init.c

@ -1,5 +1,6 @@
#include "cppmain.h"
#include "usb_device.h"
#include "utils.h"
DAC_HandleTypeDef hdac1;
TIM_HandleTypeDef htim_dac1;
@ -171,7 +172,7 @@ void dac_init(void)
htim_dac1.Instance = TIM2;
htim_dac1.Init.Prescaler = 0;
htim_dac1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim_dac1.Init.Period = 2000;// * 10000;
htim_dac1.Init.Period = 2000; // *100;
htim_dac1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim_dac1) != HAL_OK) {
Error_Handler();
@ -223,51 +224,63 @@ 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)
{
// GPIO
GPIO_InitTypeDef conf = {
.Pin = GPIO_PIN_4,
.Mode = GPIO_MODE_ANALOG,
.Pull = GPIO_NOPULL,
.Speed = GPIO_SPEED_FREQ_MEDIUM,
};
{
// GPIO
GPIO_InitTypeDef conf = {
.Pin = GPIO_PIN_1,
.Mode = GPIO_MODE_ANALOG,
.Pull = GPIO_NOPULL,
.Speed = GPIO_SPEED_FREQ_LOW,
};
HAL_GPIO_Init(GPIOA, &conf);
}
{
// GPIO
GPIO_InitTypeDef conf = {
.Pin = GPIO_PIN_2,
.Mode = GPIO_MODE_ANALOG,
.Pull = GPIO_NOPULL,
.Speed = GPIO_SPEED_FREQ_LOW,
};
HAL_GPIO_Init(GPIOA, &conf);
}
{
// GPIO
GPIO_InitTypeDef conf = {
.Pin = GPIO_PIN_3,
.Mode = GPIO_MODE_ANALOG,
.Pull = GPIO_NOPULL,
.Speed = GPIO_SPEED_FREQ_LOW,
};
HAL_GPIO_Init(GPIOA, &conf);
}
HAL_GPIO_Init(GPIOC, &conf);
ADC_Common_TypeDef *adc_common = ADC123_COMMON;
ADC_TypeDef *adc1 = ADC1;
// SET_BIT(adc_common->CCR, ADC_CCR_ADCPRE_0);
// CLEAR_BIT(adc_common->CCR, ADC_CCR_ADCPRE_1);
//
// CLEAR_BIT(adc1->CR1, ~ADC_CR1_RES_0);
// CLEAR_BIT(adc1->CR1, ADC_CR1_RES_1);
// SET_BIT(adc1->CR2, ADC_CR2_CONT);
// CLEAR_BIT(adc1->CR2, ADC_CR2_ALIGN);
// SET_BIT(adc1->CR2, ADC_CR2_ADON);
// SET_BIT(adc1->CR2, ADC_CR2_SWSTART);
//
//
// SET_BIT(adc1->SQR1,ADC_SQR1_L_0);
//// CLEAR_BIT(adc1->SQR1,ADC_SQR1_L_1);
//// CLEAR_BIT(adc1->SQR1,ADC_SQR1_L_2);
//// CLEAR_BIT(adc1->SQR1,ADC_SQR1_L_3);
////
//// ADC_SQR3_RK(1,1);
// SET_BIT(adc1->SQR3,ADC_SQR3_SQ1_0);
//// CLEAR_BIT(adc1->SQR3,ADC_SQR3_SQ1_1);
//// CLEAR_BIT(adc1->SQR3,ADC_SQR3_SQ1_2);
//// CLEAR_BIT(adc1->SQR3,ADC_SQR3_SQ1_3);
//// CLEAR_BIT(adc1->SQR3,ADC_SQR3_SQ1_4);
hadc1.Instance = ADC1;
hadc1.Instance = ADC2;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
@ -283,30 +296,11 @@ void adc_init(void)
Error_Handler();
}
ADC_ChannelConfTypeDef sConfig = {};
sConfig.Channel = ADC_CHANNEL_14;
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)

3
src/init.h

@ -1,8 +1,8 @@
#ifndef __INIT_H
#define __INIT_H
#include "stm32f4xx_hal.h"
#include "stm32f4xx.h"
#include "stm32f4xx_hal.h"
#ifdef __cplusplus
extern "C" {
@ -16,6 +16,7 @@ extern "C" {
extern RNG_HandleTypeDef hrng;
void heck_init();
void adc2_select_channel(int channel_nr);
#ifdef __cplusplus
}
#endif

11
src/types.hh

@ -0,0 +1,11 @@
#ifndef INC_TYPES_H
#define INC_TYPES_H
#include <cstdint>
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
#endif

82
src/utils.cc

@ -0,0 +1,82 @@
#include "utils.h"
#include "init.h"
#include "usbd_cdc_if.h"
#include <sstream>
#include <bitset>
namespace Heck::Utils {
bool debug_suspend_active = false;
void debug_suspend_continue()
{
debug_suspend_active = false;
}
void log(std::string msg)
{
std::string out{ msg };
out.append("\r\n");
u8 status = CDC_Transmit_FS((uint8_t *)out.data(), out.size());
if (status == USBD_BUSY) {
// usb buffer overflow
}
}
std::string reg_to_string(uint32_t val)
{
std::stringstream ss{};
const std::bitset<32> x{ val };
ss << "0b" << x.to_string();
ss << " - ";
ss << std::to_string(val);
return ss.str();
}
u32 random(u32 max)
{
u32 ret{ 0 };
HAL_RNG_GenerateRandomNumber(&hrng, &ret);
ret %= max;
return ret;
}
} // namespace Heck::Utils
extern "C" void heck_debug_suspend(void)
{
Heck::Utils::debug_suspend_active = true;
while (Heck::Utils::debug_suspend_active == true) {
Heck::Utils::log("debug_suspend...");
HAL_Delay(10);
}
}
extern "C" void heck_log(char *msg)
{
Heck::Utils::log(std::string(msg));
}
/**
* @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) {}
}

41
src/utils.h

@ -0,0 +1,41 @@
#ifndef INC_UTILS_H
#define INC_UTILS_H
// ----------------------------------------------------------------------------------------------
// C Interface
// ----------------------------------------------------------------------------------------------
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
void heck_debug_suspend(void);
void heck_log(char* msg);
void assert_failed(uint8_t* file, uint32_t line);
void Error_Handler(void);
#ifdef __cplusplus
};
#endif
// ----------------------------------------------------------------------------------------------
// C++ Interface
// ----------------------------------------------------------------------------------------------
#ifdef __cplusplus
#include "types.hh"
#include <iostream>
#include <cstdint>
#include <string>
namespace Heck::Utils {
void debug_suspend_continue();
void log(std::string msg);
std::string reg_to_string(uint32_t val);
u32 random(u32 max);
} // namespace Heck::Utils
#endif
#endif /* INC_CPPMAIN_H */
Loading…
Cancel
Save