]> code.bitgloo.com Git - clyne/stmdsp.git/commitdiff
reorganized code; added dac support
authorClyne Sullivan <clyne@bitgloo.com>
Wed, 5 Aug 2020 00:09:48 +0000 (20:09 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Wed, 5 Aug 2020 00:09:48 +0000 (20:09 -0400)
.gitignore
cfg/mcuconf.h
source/adc.cpp
source/adc.hpp
source/dac.cpp
source/dac.hpp
source/main.cpp
source/usbserial.cpp
source/usbserial.hpp

index a9adb0f1cd0802d2f4f4ac34a9b433c4fdacc28d..c24aa5fd649d4cae617b04ea932eb3f641193d98 100644 (file)
@@ -2,6 +2,6 @@ build
 ChibiOS_*
 **/.*
 gui/stmdspgui
-*.o
+**/*.o
 perf*
 
index 03b961ce13c3bc2893e8b0fd85be018c7f00423d..e1e50c3b2bbf126852cdb84f6c647754135783c0 100644 (file)
 #define STM32_GPT_USE_TIM2                  FALSE\r
 #define STM32_GPT_USE_TIM3                  FALSE\r
 #define STM32_GPT_USE_TIM4                  TRUE\r
-#define STM32_GPT_USE_TIM5                  FALSE\r
+#define STM32_GPT_USE_TIM5                  TRUE\r
 #define STM32_GPT_USE_TIM6                  FALSE\r
 #define STM32_GPT_USE_TIM7                  FALSE\r
 #define STM32_GPT_USE_TIM8                  FALSE\r
index 4e68a6e742050e1c29c84dbe4b296bdcb77dfc53..851b46139a38c687791a45159b2544801da7499e 100644 (file)
@@ -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
  *
 
 #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<const ADCdConfig *>(adcd->config)->adcdinst;
-    gptStopTimer(_this->m_gptd);
-    _this->m_is_adc_finished = true;
+    adc_group_config.smpr[0] = val;
 }
 
index 99898838bd27a94735ec0be2e67606e881f1d27a..4c3836ebeee60b330ff40761190d48e1088cba26 100644 (file)
@@ -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
  *
 
 #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<unsigned int>(1.f / (sps / static_cast<float>(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_
 
index 8981fc321e985abc1b2dcb3bbb0dd789c547aab4..d2bcf37235d790fcb4beaa4006ed9c59b4f4ec54 100644 (file)
@@ -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
  *
 
 #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);
 }
 
index dc6cc3aa953b1742fbae37e5cfbb466022be2f48..ce67f409e8101db2dc968a1745646978852ddb15 100644 (file)
@@ -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
  *
 
 #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_
 
index 95211b4e0145331eddf2f39cad187ec6b02795bb..cfd20a91aec311c7b42a3f6da5452e3067deb045 100644 (file)
@@ -24,6 +24,7 @@ static_assert(sizeof(adcsample_t) == sizeof(uint16_t));
 CC_ALIGN(CACHE_LINE_SIZE)
 #endif
 static std::array<adcsample_t, CACHE_SIZE_ALIGN(adcsample_t, 2048)> adc_samples;
+static std::array<dacsample_t, CACHE_SIZE_ALIGN(dacsample_t, 2048)> 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<unsigned int>(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<unsigned int>(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;
index 105e9bf57e4d285128dfc882f6e46f80cecd49c1..5d605e62657404eb47caca5cd381a837b706ef19 100644 (file)
 
 #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<BaseSequentialStream *>(m_driver);
+    auto bss = reinterpret_cast<BaseSequentialStream *>(sdud);
     return streamRead(bss, static_cast<uint8_t *>(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<BaseSequentialStream *>(m_driver);
+    auto bss = reinterpret_cast<BaseSequentialStream *>(sdud);
     return streamWrite(bss, static_cast<const uint8_t *>(buffer), count);
 }
 
-void USBSeriald::initPins()
-{
-    palSetPadMode(GPIOA, 11, PAL_MODE_ALTERNATE(10));
-    palSetPadMode(GPIOA, 12, PAL_MODE_ALTERNATE(10));
-}
-
index 377f73cd5a6318a1f16e7b6403c9fa5e8c77c757..4b0eab209fb880c73fd9d186ea1ff846cb8cb968 100644 (file)
 #ifndef STMDSP_USBSERIAL_HPP_
 #define STMDSP_USBSERIAL_HPP_
 
-#include "usbcfg.h"
+#include "hal.h"
 
-#include <cstddef>
-
-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_