aboutsummaryrefslogtreecommitdiffstats
path: root/source/adc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/adc.cpp')
-rw-r--r--source/adc.cpp211
1 files changed, 94 insertions, 117 deletions
diff --git a/source/adc.cpp b/source/adc.cpp
index c8da25f..c8d97af 100644
--- a/source/adc.cpp
+++ b/source/adc.cpp
@@ -11,19 +11,17 @@
#include "adc.hpp"
-constexpr static const auto adcd = &ADCD1;
-constexpr static const auto gptd = &GPTD6;
+ADCDriver *ADC::m_driver = &ADCD1;
+GPTDriver *ADC::m_timer = &GPTD6;
-constexpr static const ADCConfig adc_config = {
+const ADCConfig ADC::m_config = {
.difsel = 0
};
-static void adc_read_callback(ADCDriver *);
-
-static ADCConversionGroup adc_group_config = {
- .circular = false,
+ADCConversionGroup ADC::m_group_config = {
+ .circular = true,
.num_channels = 1,
- .end_cb = adc_read_callback,
+ .end_cb = ADC::conversionCallback,
.error_cb = nullptr,
.cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM4_TRGO */
.cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1, // Oversampling 2x
@@ -37,132 +35,111 @@ static ADCConversionGroup adc_group_config = {
}
};
-constexpr static const GPTConfig gpt_config = {
+const GPTConfig ADC::m_timer_config = {
.frequency = 36000000,
.callback = nullptr,
.cr2 = TIM_CR2_MMS_1, /* TRGO */
.dier = 0
};
-#define ADC_CCR_PRESC_DIV1 (0)
-#define ADC_SAMPLE_RATE_SETTINGS_COUNT (7)
-static uint32_t adc_sample_rate_settings[] = {
- // Rate PLLSAI2N ADC_PRESC ADC_SMPR GPT_DIV
- /* 16k */ 8, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 2250,
- /* 48k */ 24, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 750,
- /* 96k */ 48, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 375,
- /* 100k */ 40, ADC_CCR_PRESC_DIV8, ADC_SMPR_SMP_12P5, 360,
- /* 400k */ 40, ADC_CCR_PRESC_DIV2, ADC_SMPR_SMP_12P5, 90,
- /* 1M */ 38, ADC_CCR_PRESC_DIV1, ADC_SMPR_SMP_6P5, 36,
- /* 2M */ 76, ADC_CCR_PRESC_DIV1, ADC_SMPR_SMP_6P5, 18
-};
+std::array<std::array<uint32_t, 4>, 6> ADC::m_rate_presets = {{
+ // Rate PLLSAI2N ADC_PRESC ADC_SMPR GPT_DIV
+ {/* 16k */ 8, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 2250},
+ {/* 20k */ 10, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 1800},
+ {/* 32k */ 16, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 1125},
+ {/* 48k */ 24, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 750},
+ {/* 60k */ 30, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 600},
+ {/* 96k */ 48, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 375}
+}};
-static bool adc_is_read_finished = false;
-static adcsample_t *adc_current_buffer = nullptr;
-static size_t adc_current_buffer_size = 0;
-static adc::operation_t adc_operation_func = nullptr;
-static unsigned int adc_gpt_divisor = 1;
+adcsample_t *ADC::m_current_buffer = nullptr;
+size_t ADC::m_current_buffer_size = 0;
+ADC::Operation ADC::m_operation = nullptr;
-namespace adc
+unsigned int ADC::m_timer_divisor = 2;
+
+void ADC::begin()
{
- void init()
- {
- palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG);
-
- gptStart(gptd, &gpt_config);
- adcStart(adcd, &adc_config);
- adcSTM32EnableVREF(adcd);
-
- set_rate(rate::R96K);
- }
+ palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG);
- void set_rate(rate new_rate)
- {
- auto index = static_cast<unsigned int>(new_rate);
- auto plln = adc_sample_rate_settings[index * 4] << RCC_PLLSAI2CFGR_PLLSAI2N_Pos;
- auto presc = adc_sample_rate_settings[index * 4 + 1] << ADC_CCR_PRESC_Pos;
- auto smp = adc_sample_rate_settings[index * 4 + 2];
- adc_gpt_divisor = adc_sample_rate_settings[index * 4 + 3];
-
- adcStop(adcd);
-
- // Adjust PLLSAI2
- RCC->CR &= ~(RCC_CR_PLLSAI2ON);
- while ((RCC->CR & RCC_CR_PLLSAI2RDY) == RCC_CR_PLLSAI2RDY);
- RCC->PLLSAI2CFGR = (RCC->PLLSAI2CFGR & ~(RCC_PLLSAI2CFGR_PLLSAI2N_Msk)) | plln;
- RCC->CR |= RCC_CR_PLLSAI2ON;
-
- // Set ADC prescaler
- adcd->adcc->CCR = (adcd->adcc->CCR & ~(ADC_CCR_PRESC_Msk)) | presc;
- // Set sampling time
- adc_group_config.smpr[0] = ADC_SMPR1_SMP_AN5(smp);
- adcStart(adcd, &adc_config);
- }
-
- unsigned int get_rate()
- {
- for (unsigned int i = 0; i < ADC_SAMPLE_RATE_SETTINGS_COUNT; i++) {
- if (adc_gpt_divisor == adc_sample_rate_settings[i * 3 + 3])
- return i;
- }
-
- return 0xFF;
- }
+ adcStart(m_driver, &m_config);
+ adcSTM32EnableVREF(m_driver);
+ gptStart(m_timer, &m_timer_config);
- unsigned int get_gpt_divisor()
- {
- return adc_gpt_divisor;
- }
-
- adcsample_t *read(adcsample_t *buffer, size_t count)
- {
- adc_is_read_finished = false;
- adc_group_config.circular = false;
- adcStartConversion(adcd, &adc_group_config, buffer, count);
- gptStartContinuous(gptd, adc_gpt_divisor);
- while (!adc_is_read_finished);
- return buffer;
- }
+ setRate(Rate::R96K);
+}
- void read_start(operation_t operation_func, adcsample_t *buffer, size_t count)
- {
- adc_current_buffer = buffer;
- adc_current_buffer_size = count;
- adc_operation_func = operation_func;
- adc_group_config.circular = true;
- adcStartConversion(adcd, &adc_group_config, buffer, count);
- gptStartContinuous(gptd, adc_gpt_divisor);
- }
+void ADC::start(adcsample_t *buffer, size_t count, Operation operation)
+{
+ m_current_buffer = buffer;
+ m_current_buffer_size = count;
+ m_operation = operation;
- void read_set_operation_func(operation_t operation_func)
- {
- adc_operation_func = operation_func;
- }
-
- void read_stop()
- {
- gptStopTimer(gptd);
- adcStopConversion(adcd);
- adc_group_config.circular = false;
- adc_current_buffer = nullptr;
- adc_current_buffer_size = 0;
- adc_operation_func = nullptr;
+ adcStartConversion(m_driver, &m_group_config, buffer, count);
+ gptStartContinuous(m_timer, m_timer_divisor);
+}
+
+void ADC::stop()
+{
+ gptStopTimer(m_timer);
+ adcStopConversion(m_driver);
+
+ m_current_buffer = nullptr;
+ m_current_buffer_size = 0;
+ m_operation = nullptr;
+}
+
+void ADC::setRate(ADC::Rate rate)
+{
+ auto& preset = m_rate_presets[static_cast<int>(rate)];
+ auto plln = preset[0] << RCC_PLLSAI2CFGR_PLLSAI2N_Pos;
+ auto presc = preset[1] << ADC_CCR_PRESC_Pos;
+ auto smp = preset[2];
+ m_timer_divisor = preset[3];
+
+ adcStop(m_driver);
+
+ // Adjust PLLSAI2
+ RCC->CR &= ~(RCC_CR_PLLSAI2ON);
+ while ((RCC->CR & RCC_CR_PLLSAI2RDY) == RCC_CR_PLLSAI2RDY);
+ RCC->PLLSAI2CFGR = (RCC->PLLSAI2CFGR & ~(RCC_PLLSAI2CFGR_PLLSAI2N_Msk)) | plln;
+ RCC->CR |= RCC_CR_PLLSAI2ON;
+ // Set ADC prescaler
+ m_driver->adcc->CCR = (m_driver->adcc->CCR & ~(ADC_CCR_PRESC_Msk)) | presc;
+ // Set sampling time
+ m_group_config.smpr[0] = ADC_SMPR1_SMP_AN5(smp);
+
+ adcStart(m_driver, &m_config);
+}
+
+void ADC::setOperation(ADC::Operation operation)
+{
+ m_operation = operation;
+}
+
+int ADC::getRate()
+{
+ for (unsigned int i = 0; i < m_rate_presets.size(); i++) {
+ if (m_timer_divisor == m_rate_presets[i][3])
+ return i;
}
+
+ return -1;
+}
+
+unsigned int ADC::getTimerDivisor()
+{
+ return m_timer_divisor;
}
-void adc_read_callback(ADCDriver *driver)
+void ADC::conversionCallback(ADCDriver *driver)
{
- if (adc_group_config.circular) {
- if (adc_operation_func != nullptr) {
- auto half_size = adc_current_buffer_size / 2;
- if (adcIsBufferComplete(driver))
- adc_operation_func(adc_current_buffer + half_size, half_size);
- else
- adc_operation_func(adc_current_buffer, half_size);
- }
- } else {
- gptStopTimer(gptd);
- adc_is_read_finished = true;
+ if (m_operation != nullptr) {
+ auto half_size = m_current_buffer_size / 2;
+ if (adcIsBufferComplete(driver))
+ m_operation(m_current_buffer + half_size, half_size);
+ else
+ m_operation(m_current_buffer, half_size);
}
}