From 7f59ca704b6f3c0ad254d391a123961aa0a86284 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Tue, 4 Aug 2020 20:09:48 -0400 Subject: [PATCH] reorganized code; added dac support --- .gitignore | 2 +- cfg/mcuconf.h | 2 +- source/adc.cpp | 101 +++++++++++++++++++++++++------------------ source/adc.hpp | 92 +++------------------------------------ source/dac.cpp | 51 +++++++++++++++------- source/dac.hpp | 21 ++------- source/main.cpp | 43 ++++++++++-------- source/usbserial.cpp | 31 ++++++------- source/usbserial.hpp | 26 +++-------- 9 files changed, 149 insertions(+), 220 deletions(-) diff --git a/.gitignore b/.gitignore index a9adb0f..c24aa5f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,6 @@ build ChibiOS_* **/.* gui/stmdspgui -*.o +**/*.o perf* diff --git a/cfg/mcuconf.h b/cfg/mcuconf.h index 03b961c..e1e50c3 100644 --- a/cfg/mcuconf.h +++ b/cfg/mcuconf.h @@ -177,7 +177,7 @@ #define STM32_GPT_USE_TIM2 FALSE #define STM32_GPT_USE_TIM3 FALSE #define STM32_GPT_USE_TIM4 TRUE -#define STM32_GPT_USE_TIM5 FALSE +#define STM32_GPT_USE_TIM5 TRUE #define STM32_GPT_USE_TIM6 FALSE #define STM32_GPT_USE_TIM7 FALSE #define STM32_GPT_USE_TIM8 FALSE diff --git a/source/adc.cpp b/source/adc.cpp index 4e68a6e..851b461 100644 --- a/source/adc.cpp +++ b/source/adc.cpp @@ -1,6 +1,6 @@ /** * @file adc.cpp - * @brief Wrapper for ChibiOS's ADCDriver. + * @brief Manages signal reading through the ADC. * * Copyright (C) 2020 Clyne Sullivan * @@ -11,77 +11,96 @@ #include "adc.hpp" -const GPTConfig ADCd::m_gpt_config = { - .frequency = 1000000, - .callback = NULL, - .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ - .dier = 0 +constexpr static const auto adcd = &ADCD1; +constexpr static const auto gptd = &GPTD4; + +constexpr static const ADCConfig adc_config = { + .difsel = 0 }; -void ADCd::start() -{ - initPins(); - gptStart(m_gptd, &m_gpt_config); +void adc_read_callback(ADCDriver *); + +/*constexpr*/ static ADCConversionGroup adc_group_config = { + .circular = false, + .num_channels = 1, + .end_cb = adc_read_callback, + .error_cb = nullptr, + .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(12), /* TIM4_TRGO */ + .cfgr2 = 0, + .tr1 = ADC_TR(0, 4095), + .smpr = { + ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_247P5), 0 + }, + .sqr = { + ADC_SQR1_SQ1_N(ADC_CHANNEL_IN5), + 0, 0, 0 + } +}; - m_adc_config.difsel = 0; - m_adc_config.adcdinst = this; +constexpr static const GPTConfig gpt_config = { + .frequency = 1000000, + .callback = nullptr, + .cr2 = TIM_CR2_MMS_1, /* TRGO */ + .dier = 0 +}; + +static bool adc_is_read_finished = false; + +void adc_init() +{ + palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG); - adcStart(m_adcd, &m_adc_config); - adcSTM32EnableVREF(m_adcd); + gptStart(gptd, &gpt_config); + adcStart(adcd, &adc_config); + adcSTM32EnableVREF(adcd); } -adcsample_t *ADCd::getSamples(adcsample_t *buffer, size_t count) +adcsample_t *adc_read(adcsample_t *buffer, size_t count) { - m_is_adc_finished = false; - adcStartConversion(m_adcd, &m_adc_group_config, buffer, count); - gptStartContinuous(m_gptd, 100); // 10kHz - while (!m_is_adc_finished); + adc_is_read_finished = false; + adcStartConversion(adcd, &adc_group_config, buffer, count); + gptStartContinuous(gptd, 100); // 10kHz + while (!adc_is_read_finished); return buffer; } -void ADCd::setSampleRate(ADCdRate rate) +void adc_read_callback([[maybe_unused]] ADCDriver *driver) +{ + gptStopTimer(gptd); + adc_is_read_finished = true; +} + +void adc_set_rate(ADCRate rate) { uint32_t val = 0; switch (rate) { - case ADCdRate::R2P5: + case ADCRate::R2P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_2P5); break; - case ADCdRate::R6P5: + case ADCRate::R6P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_6P5); break; - case ADCdRate::R12P5: + case ADCRate::R12P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_12P5); break; - case ADCdRate::R24P5: + case ADCRate::R24P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_24P5); break; - case ADCdRate::R47P5: + case ADCRate::R47P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_47P5); break; - case ADCdRate::R92P5: + case ADCRate::R92P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_92P5); break; - case ADCdRate::R247P5: + case ADCRate::R247P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_247P5); break; - case ADCdRate::R640P5: + case ADCRate::R640P5: val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_640P5); break; } - m_adc_group_config.smpr[0] = val; -} - -void ADCd::initPins() -{ - palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG); -} - -void ADCd::adcEndCallback(ADCDriver *adcd) -{ - auto *_this = reinterpret_cast(adcd->config)->adcdinst; - gptStopTimer(_this->m_gptd); - _this->m_is_adc_finished = true; + adc_group_config.smpr[0] = val; } diff --git a/source/adc.hpp b/source/adc.hpp index 9989883..4c3836e 100644 --- a/source/adc.hpp +++ b/source/adc.hpp @@ -1,6 +1,6 @@ /** * @file adc.hpp - * @brief Wrapper for ChibiOS's ADCDriver. + * @brief Manages signal reading through the ADC. * * Copyright (C) 2020 Clyne Sullivan * @@ -14,14 +14,7 @@ #include "hal.h" -class ADCd; - -struct ADCdConfig : public ADCConfig -{ - ADCd *adcdinst; -}; - -enum class ADCdRate : unsigned int { +enum class ADCRate { R2P5, R6P5, R12P5, @@ -32,84 +25,9 @@ enum class ADCdRate : unsigned int { R640P5 }; -class ADCd -{ -public: - constexpr static const unsigned int CLOCK_RATE = 40000000; - constexpr static unsigned int SAMPLES_PER_SECOND(ADCdRate rate) { - unsigned int sps = 0; - switch (rate) { - case ADCdRate::R2P5: - sps = 15; - break; - case ADCdRate::R6P5: - sps = 19; - break; - case ADCdRate::R12P5: - sps = 25; - break; - case ADCdRate::R24P5: - sps = 37; - break; - case ADCdRate::R47P5: - sps = 60; - break; - case ADCdRate::R92P5: - sps = 105; - break; - case ADCdRate::R247P5: - sps = 260; - break; - case ADCdRate::R640P5: - sps = 653; - break; - } - - return static_cast(1.f / (sps / static_cast(CLOCK_RATE))); - } - - constexpr explicit ADCd(ADCDriver& adcd, GPTDriver& gptd) : - m_adcd(&adcd), m_gptd(&gptd), m_adc_config{}, - m_adc_group_config(ADC_GROUP_CONFIG), - m_is_adc_finished(false) {} - - void start(); - adcsample_t *getSamples(adcsample_t *buffer, size_t count); - void setSampleRate(ADCdRate rate); - -private: - static const GPTConfig m_gpt_config; - - ADCDriver *m_adcd; - GPTDriver *m_gptd; - ADCdConfig m_adc_config; - ADCConversionGroup m_adc_group_config; - - bool m_is_adc_finished; - - void initPins(); - //void selectPins(bool a0, bool a1); - - static void adcEndCallback(ADCDriver *adcd); - - constexpr static const ADCConversionGroup ADC_GROUP_CONFIG = { - .circular = false, - .num_channels = 1, - .end_cb = ADCd::adcEndCallback, - .error_cb = nullptr, - .cfgr = ADC_CFGR_EXTEN_RISING | - ADC_CFGR_EXTSEL_SRC(12), /* TIM4_TRGO */ - .cfgr2 = 0, - .tr1 = ADC_TR(0, 4095), - .smpr = { - ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_247P5), 0 - }, - .sqr = { - ADC_SQR1_SQ1_N(ADC_CHANNEL_IN5), - 0, 0, 0 - } - }; -}; +void adc_init(); +adcsample_t *adc_read(adcsample_t *buffer, size_t count); +void adc_set_rate(ADCRate rate); #endif // STMDSP_ADC_HPP_ diff --git a/source/dac.cpp b/source/dac.cpp index 8981fc3..d2bcf37 100644 --- a/source/dac.cpp +++ b/source/dac.cpp @@ -1,6 +1,6 @@ /** * @file dac.cpp - * @brief Wrapper for ChibiOS's DACDriver. + * @brief Manages signal creation using the DAC. * * Copyright (C) 2020 Clyne Sullivan * @@ -11,28 +11,47 @@ #include "dac.hpp" -//static const DACConversionGroup dacGroupConfig = { -// .num_channels = 1, -// .end_cb = NULL, -// .error_cb = NULL, -// .trigger = DAC_TRG(0) -//}; +constexpr static const auto dacd = &DACD1; +constexpr static const auto gptd = &GPTD5; -void DACd::init() +constexpr static const DACConfig dac_config = { + .init = 0, + .datamode = DAC_DHRM_12BIT_RIGHT, + .cr = 0 +}; + +constexpr static const DACConversionGroup dac_group_config = { + .num_channels = 1, + .end_cb = nullptr, + .error_cb = nullptr, + .trigger = DAC_TRG(3) +}; + +constexpr static const GPTConfig gpt_config = { + .frequency = 500000, + .callback = nullptr, + .cr2 = TIM_CR2_MMS_1, /* TRGO */ + .dier = 0 +}; + +void dac_init() { - initPins(); - dacStart(m_driver, &m_config); + palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); + //palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); + + dacStart(dacd, &dac_config); + gptStart(gptd, &gpt_config); } -void DACd::write(unsigned int channel, uint16_t value) +void dac_write_start(dacsample_t *buffer, size_t count) { - if (channel < 2) - dacPutChannelX(m_driver, channel, value); + dacStartConversion(dacd, &dac_group_config, buffer, count); + gptStartContinuous(gptd, 1); } -void DACd::initPins() +void dac_write_stop() { - palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); // DAC out1, out2 - palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); + gptStopTimer(gptd); + dacStopConversion(dacd); } diff --git a/source/dac.hpp b/source/dac.hpp index dc6cc3a..ce67f40 100644 --- a/source/dac.hpp +++ b/source/dac.hpp @@ -1,6 +1,6 @@ /** * @file dac.hpp - * @brief Wrapper for ChibiOS's DACDriver. + * @brief Manages signal creation using the DAC. * * Copyright (C) 2020 Clyne Sullivan * @@ -14,22 +14,9 @@ #include "hal.h" -class DACd -{ -public: - constexpr explicit DACd(DACDriver& driver, const DACConfig& config) : - m_driver(&driver), m_config(config) {} - - void init(); - - void write(unsigned int channel, uint16_t value); - -private: - DACDriver *m_driver; - DACConfig m_config; - - void initPins(); -}; +void dac_init(); +void dac_write_start(dacsample_t *buffer, size_t count); +void dac_write_stop(); #endif // STMDSP_DAC_HPP_ diff --git a/source/main.cpp b/source/main.cpp index 95211b4..cfd20a9 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -24,6 +24,7 @@ static_assert(sizeof(adcsample_t) == sizeof(uint16_t)); CC_ALIGN(CACHE_LINE_SIZE) #endif static std::array adc_samples; +static std::array dac_samples; int main() { @@ -32,35 +33,39 @@ int main() palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); // LED - ADCd adc (ADCD1, GPTD4); - adc.start(); - - //DACd dac (DACD1, { - // .init = 0, - // .datamode = DAC_DHRM_12BIT_RIGHT, - // .cr = 0 - //}); - //dac.start(); - //dac.write(0, 1024); - - USBSeriald usbd (SDU1); - usbd.start(); + adc_init(); + dac_init(); + usbserial_init(); + static unsigned int dac_sample_count = 2048; while (true) { - if (usbd.active()) { + if (usbserial_is_active()) { // Expect to receive a byte command 'packet'. - if (char cmd[3]; usbd.read(&cmd, 1) > 0) { + if (char cmd[3]; usbserial_read(&cmd, 1) > 0) { switch (cmd[0]) { case 'r': // Read in analog signal - if (usbd.read(&cmd[1], 2) < 2) + if (usbserial_read(&cmd[1], 2) < 2) break; if (auto count = std::min(static_cast(cmd[1] | (cmd[2] << 8)), adc_samples.size()); count > 0) { - adc.getSamples(&adc_samples[0], count); - usbd.write(adc_samples.data(), count * sizeof(adcsample_t)); + adc_read(&adc_samples[0], count); + usbserial_write(adc_samples.data(), count * sizeof(adcsample_t)); } break; + case 'W': + if (usbserial_read(&cmd[1], 2) < 2) + break; + if (auto count = std::min(static_cast(cmd[1] | (cmd[2] << 8)), dac_samples.size()); count > 0) + dac_sample_count = count; + else + dac_write_stop(); + break; + case 'w': + if (usbserial_read(&dac_samples[0], 2 * dac_sample_count) != 2 * dac_sample_count) + break; + dac_write_start(&dac_samples[0], dac_sample_count); + break; case 'i': // Identify ourself as an stmdsp device - usbd.write("stmdsp", 6); + usbserial_write("stmdsp", 6); break; default: break; diff --git a/source/usbserial.cpp b/source/usbserial.cpp index 105e9bf..5d605e6 100644 --- a/source/usbserial.cpp +++ b/source/usbserial.cpp @@ -11,14 +11,17 @@ #include "usbserial.hpp" -#include "hal.h" +#include "usbcfg.h" -void USBSeriald::start() +constexpr static const auto sdud = &SDU1; + +void usbserial_init() { - initPins(); + palSetPadMode(GPIOA, 11, PAL_MODE_ALTERNATE(10)); + palSetPadMode(GPIOA, 12, PAL_MODE_ALTERNATE(10)); - sduObjectInit(m_driver); - sduStart(m_driver, &serusbcfg); + sduObjectInit(sdud); + sduStart(sdud, &serusbcfg); // Reconnect bus so device can re-enumerate on reset usbDisconnectBus(serusbcfg.usbp); @@ -27,26 +30,20 @@ void USBSeriald::start() usbConnectBus(serusbcfg.usbp); } -bool USBSeriald::active() const +bool usbserial_is_active() { - return m_driver->config->usbp->state == USB_ACTIVE; + return sdud->config->usbp->state == USB_ACTIVE; } -std::size_t USBSeriald::read(void *buffer, std::size_t count) +size_t usbserial_read(void *buffer, size_t count) { - auto *bss = reinterpret_cast(m_driver); + auto bss = reinterpret_cast(sdud); return streamRead(bss, static_cast(buffer), count); } -std::size_t USBSeriald::write(const void *buffer, std::size_t count) +size_t usbserial_write(const void *buffer, size_t count) { - auto *bss = reinterpret_cast(m_driver); + auto bss = reinterpret_cast(sdud); return streamWrite(bss, static_cast(buffer), count); } -void USBSeriald::initPins() -{ - palSetPadMode(GPIOA, 11, PAL_MODE_ALTERNATE(10)); - palSetPadMode(GPIOA, 12, PAL_MODE_ALTERNATE(10)); -} - diff --git a/source/usbserial.hpp b/source/usbserial.hpp index 377f73c..4b0eab2 100644 --- a/source/usbserial.hpp +++ b/source/usbserial.hpp @@ -12,28 +12,12 @@ #ifndef STMDSP_USBSERIAL_HPP_ #define STMDSP_USBSERIAL_HPP_ -#include "usbcfg.h" +#include "hal.h" -#include - -class USBSeriald -{ -public: - constexpr explicit USBSeriald(SerialUSBDriver& driver) : - m_driver(&driver) {} - - void start(); - - bool active() const; - - std::size_t read(void *buffer, std::size_t count = 1); - std::size_t write(const void *buffer, std::size_t count = 1); - -private: - SerialUSBDriver *m_driver; - - void initPins(); -}; +void usbserial_init(); +bool usbserial_is_active(); +size_t usbserial_read(void *buffer, size_t count); +size_t usbserial_write(const void *buffer, size_t count); #endif // STMDSP_USBSERIAL_HPP_