diff options
Diffstat (limited to 'source/adc.cpp')
-rw-r--r-- | source/adc.cpp | 211 |
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); } } |