# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
- USE_CPPOPT = -std=c++2a -fno-rtti
+ USE_CPPOPT = -std=c++2a -fno-rtti -fno-exceptions
endif
# Enable this if you want the linker to remove unused code and data.
#define STM32_HSE_ENABLED FALSE\r
#define STM32_LSE_ENABLED FALSE\r
#define STM32_MSIPLL_ENABLED FALSE\r
-#define STM32_MSIRANGE STM32_MSIRANGE_8M\r
+#define STM32_MSIRANGE STM32_MSIRANGE_4M\r
#define STM32_MSISRANGE STM32_MSISRANGE_4M\r
#define STM32_SW STM32_SW_PLL\r
#define STM32_PLLSRC STM32_PLLSRC_MSI\r
-#define STM32_PLLM_VALUE 2\r
+#define STM32_PLLM_VALUE 1\r
#define STM32_PLLN_VALUE 72\r
#define STM32_PLLP_VALUE 7\r
#define STM32_PLLQ_VALUE 6\r
more = DAC::sigGenWantsMore();
} while (more == -1);
+ // Receive streamed samples in half-buffer chunks.
USBSerial::read(reinterpret_cast<uint8_t *>(
more == 0 ? Samples::Generator.data() : Samples::Generator.middata()),
Samples::Generator.bytesize() / 2);
#include "runstatus.hpp"
#include "samples.hpp"
-constexpr msg_t MSG_CONVFIRST = 1;
-constexpr msg_t MSG_CONVSECOND = 2;
-constexpr msg_t MSG_CONVFIRST_MEASURE = 3;
-constexpr msg_t MSG_CONVSECOND_MEASURE = 4;
+// MSG_* things below are macros rather than constexpr
+// to ensure inlining.
-constexpr auto MSG_FOR_FIRST = [](msg_t m) { return m & 1; };
-constexpr auto MSG_FOR_MEASURE = [](msg_t m) { return m > 2; };
+#define MSG_CONVFIRST (1)
+#define MSG_CONVSECOND (2)
+#define MSG_CONVFIRST_MEASURE (3)
+#define MSG_CONVSECOND_MEASURE (4)
+
+#define MSG_FOR_FIRST(msg) (msg & 1)
+#define MSG_FOR_MEASURE(msg) (msg > 2)
time_measurement_t conversion_time_measurement;
__attribute__((section(".stacks")))
std::array<char, 1024> ConversionManager::m_thread_monitor_stack = {};
__attribute__((section(".stacks")))
-std::array<char, 128> ConversionManager::m_thread_runner_entry_stack = {};
+std::array<char, THD_WORKING_AREA_SIZE(128)> ConversionManager::m_thread_runner_entry_stack = {};
__attribute__((section(".convdata")))
std::array<char, CONVERSION_THREAD_STACK_SIZE> ConversionManager::m_thread_runner_stack = {};
static thread_t *m_thread_runner;
static std::array<char, 1024> m_thread_monitor_stack;
- static std::array<char, 128> m_thread_runner_entry_stack;
+ static std::array<char, THD_WORKING_AREA_SIZE(128)> m_thread_runner_entry_stack;
static std::array<char, CONVERSION_THREAD_STACK_SIZE> m_thread_runner_stack;
static std::array<msg_t, 2> m_mailbox_buffer;
static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' };
+__attribute__((section(".convcode")))
+ELFManager::EntryFunc ELFManager::loadedElf()
+{
+ return m_entry;
+}
+
+unsigned char *ELFManager::fileBuffer()
+{
+ return m_file_buffer.data();
+}
+
+void ELFManager::unload()
+{
+ m_entry = nullptr;
+}
+
template<typename T>
constexpr static auto ptr_from_offset(void *base, uint32_t offset)
{
using EntryFunc = Sample *(*)(Sample *, size_t);
static EntryFunc loadFromInternalBuffer();
-
- static EntryFunc loadedElf() {
- return m_entry;
- }
-
- static unsigned char *fileBuffer() {
- return m_file_buffer.data();
- }
-
- static void unload() {
- m_entry = nullptr;
- }
+ static EntryFunc loadedElf();
+ static unsigned char *fileBuffer();
+ static void unload();
private:
static EntryFunc m_entry;
#include "error.hpp"
#include "runstatus.hpp"
-#include "ch.h"
#include "hal.h"
+__attribute__((section(".stacks")))
+std::array<char, THD_WORKING_AREA_SIZE(256)> Monitor::m_thread_stack = {};
+
void Monitor::begin()
{
chThdCreateStatic(m_thread_stack.data(),
}
}
-__attribute__((section(".stacks")))
-std::array<char, 256> Monitor::m_thread_stack = {};
-
#ifndef STMDSP_MONITOR_HPP
#define STMDSP_MONITOR_HPP
+#include "ch.h"
+
#include <array>
class Monitor
private:
static void threadMonitor(void *);
- static std::array<char, 256> m_thread_stack;
+ static std::array<char, THD_WORKING_AREA_SIZE(256)> m_thread_stack;
};
#endif // STMDSP_MONITOR_HPP
.end_cb = ADC::conversionCallback,
.error_cb = nullptr,
.cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */
- .cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x
+ .cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x
#if defined(TARGET_PLATFORM_H7)
.ccr = 0,
.pcsel = 0,
.end_cb = readAltCallback,
.error_cb = nullptr,
.cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */
- .cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x
+ .cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x
#if defined(TARGET_PLATFORM_H7)
.ccr = 0,
.pcsel = 0,
adcStart(m_driver, &m_config);
#elif defined(TARGET_PLATFORM_L4)
std::array<std::array<uint32_t, 3>, 6> m_rate_presets = {{
+ // PLLSAI2 sources MSI of 4MHz, divided by PLLM of /1 = 4MHz.
+ // 4MHz is then multiplied by PLLSAI2N (x8 to x86), with result
+ // between 64 and 344 MHz.
+ //
+ // SAI2N MUST BE AT LEAST 16 TO MAKE 64MHz MINIMUM.
+ //
+ // That is then divided by PLLSAI2R:
+ // R of 0 = /2; 1 = /4, 2 = /6, 3 = /8.
+ // PLLSAI2 then feeds into the ADC, which has a prescaler of /10.
+ // Finally, the ADC's SMP value produces the desired sample rate.
+ //
+ // 4MHz * N / R / 10 / SMP = sample rate.
+ //
+ // With oversampling, must create faster clock
+ // (x2 oversampling requires x2 sample rate clock).
+ //
// Rate PLLSAI2N R SMPR
- {/* 8k */ 8, 1, ADC_SMPR_SMP_12P5},
- {/* 16k */ 16, 1, ADC_SMPR_SMP_12P5},
- {/* 20k */ 20, 1, ADC_SMPR_SMP_12P5},
- {/* 32k */ 32, 1, ADC_SMPR_SMP_12P5},
- {/* 48k */ 24, 0, ADC_SMPR_SMP_12P5},
- {/* 96k */ 73, 1, ADC_SMPR_SMP_6P5} // Technically 96.05263kS/s
+ {/* 8k */ 16, 1, ADC_SMPR_SMP_12P5}, // R3=32k (min), R1=64k
+ {/* 16k */ 16, 0, ADC_SMPR_SMP_12P5},
+ {/* 20k */ 20, 0, ADC_SMPR_SMP_12P5},
+ {/* 32k */ 32, 0, ADC_SMPR_SMP_12P5},
+ {/* 48k */ 48, 0, ADC_SMPR_SMP_12P5},
+ {/* 96k */ 73, 0, ADC_SMPR_SMP_6P5} // Technically 96.05263kS/s
}};
auto& preset = m_rate_presets[static_cast<int>(rate)];
m_group_config.smpr[0] = ADC_SMPR1_SMP_AN5(smpr);
- // Set 2x oversampling
- m_group_config.cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1;
- m_group_config2.cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1;
+ // 8x oversample
+ m_group_config.cfgr2 = ADC_CFGR2_ROVSE | (2 << ADC_CFGR2_OVSR_Pos) | (3 << ADC_CFGR2_OVSS_Pos);
+ m_group_config2.cfgr2 = ADC_CFGR2_ROVSE | (2 << ADC_CFGR2_OVSR_Pos) | (3 << ADC_CFGR2_OVSS_Pos);
#endif
}
/* 48k */ 100,
/* 96k */ 50
#else
- 4500, 2250, 1800, 1125, 750, 375
+ /* 8k */ 4500,
+ /* 16k */ 2250,
+ /* 20k */ 1800,
+ /* 32k */ 1125,
+ /* 48k */ 750,
+ /* 96k */ 375
#endif
}};