]> code.bitgloo.com Git - clyne/stmdsp.git/commitdiff
2nd pot; some doc; smooth WAV playback
authorClyne Sullivan <clyne@bitgloo.com>
Sun, 23 May 2021 17:19:09 +0000 (13:19 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Sun, 23 May 2021 17:19:09 +0000 (13:19 -0400)
15 files changed:
gui/wxmain_devdata.cpp
gui/wxmain_mrun.cpp
source/adc.cpp
source/adc.hpp
source/dac.cpp
source/dac.hpp
source/elf_load.cpp
source/elf_load.hpp
source/main.cpp
source/samplebuffer.cpp
source/samplebuffer.hpp
source/sclock.cpp
source/sclock.hpp
source/usbserial.cpp
source/usbserial.hpp

index 551f6ccde0a668db7a4148077b12b55e6c5a05b3..7f736a24c1822d27a9fa426ead42f75cc75e1882 100644 (file)
@@ -49,16 +49,16 @@ const char *makefile_text_l4 =
 #endif
     "arm-none-eabi-g++ -x c++ -Os -std=c++20 -fno-exceptions -fno-rtti "
         "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 "
-       "-nostartfiles -I$1/cmsis"
+        "-nostartfiles -I$1/cmsis "
         "-Wl,-Ttext-segment=0x10000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry "
         "$0 -o $0.o" NEWLINE
-       COPY " $0.o $0.orig.o" NEWLINE
-       "arm-none-eabi-strip -s -S --strip-unneeded $0.o" NEWLINE
-       "arm-none-eabi-objcopy --remove-section .ARM.attributes "
+    COPY " $0.o $0.orig.o" NEWLINE
+    "arm-none-eabi-strip -s -S --strip-unneeded $0.o" NEWLINE
+    "arm-none-eabi-objcopy --remove-section .ARM.attributes "
                           "--remove-section .comment "
                           "--remove-section .noinit "
                           "$0.o" NEWLINE
-       "arm-none-eabi-size $0.o" NEWLINE;
+    "arm-none-eabi-size $0.o" NEWLINE;
 
 // $0 = buffer size
 const char *file_header_h7 = R"cpp(
@@ -168,11 +168,21 @@ asm("vsqrt.f32 s0, s0; bx lr");
 return 0;
 }
 
-auto readalt() {
+auto readpot1() {
 Sample s;
-asm("push {r4-r6}; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s));
+asm("push {r4-r6}; eor r0, r0; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s));
 return s;
 }
+auto readpot2() {
+Sample s;
+asm("push {r4-r6}; mov r0, #1; svc 3; mov %0, r0; pop {r4-r6}" : "=&r"(s));
+return s;
+}
+
+void puts(const char *s) {
+// 's' will already be in r0.
+asm("push {r4-r6}; svc 4; pop {r4-r6}");
+}
 
 // End stmdspgui header code
 
index 58b1873ed4e338151ed4b386dbaac522d9f66b08..e12d068d5cb5c18a1a380a44ba8317433ca3b20b 100644 (file)
@@ -48,18 +48,16 @@ void MainFrame::onRunStart(wxCommandEvent& ce)
             m_device->continuous_start_measure();
             m_timer_performance->StartOnce(1000);
         } else {
-            if (m_device->is_siggening() && m_wav_clip) {
-                // TODO Confirm need for factor of 500
-                m_timer_wavclip->Start(m_device->get_buffer_size() * 500 /
-                                       srateNums[m_rate_select->GetSelection()]);
-            } else if (m_conv_result_log) {
-                m_timer_record->Start(m_device->get_buffer_size() /
-                      srateNums[m_rate_select->GetSelection()] *
-                      800 / 1000);
-            } else if (m_run_draw_samples->IsChecked()) {
-                m_timer_record->Start(m_device->get_buffer_size() /
-                      srateNums[m_rate_select->GetSelection()]);
-            }
+            auto reqSpeedExact =
+                m_device->get_buffer_size()
+                / static_cast<float>(srateNums[m_rate_select->GetSelection()])
+                * 1000.f * 0.5f;
+            int reqSpeed = reqSpeedExact;
+
+            if (m_device->is_siggening() && m_wav_clip)
+                m_timer_wavclip->Start(reqSpeed);
+            if (m_conv_result_log || m_run_draw_samples->IsChecked())
+                m_timer_record->Start(reqSpeed);
 
             m_device->continuous_start();
         }
index 3ab5430693994c6b9c56db5627e5a21d5bef2731..2a4fa38a6df288f79940b30996a47d42fc3b3c89 100644 (file)
@@ -2,7 +2,7 @@
  * @file adc.cpp
  * @brief Manages signal reading through the ADC.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
@@ -69,7 +69,7 @@ static void readAltCallback(ADCDriver *)
 }
 ADCConversionGroup ADC::m_group_config2 = {
     .circular = false,
-    .num_channels = 1,
+    .num_channels = 2,
     .end_cb = readAltCallback,
     .error_cb = nullptr,
     .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13),  /* TIM6_TRGO */
@@ -88,10 +88,10 @@ ADCConversionGroup ADC::m_group_config2 = {
     .awd3cr = 0,
 #endif
     .smpr = {
-        ADC_SMPR1_SMP_AN1(ADC_SMPR_SMP_12P5), 0
+        ADC_SMPR1_SMP_AN1(ADC_SMPR_SMP_12P5) | ADC_SMPR1_SMP_AN2(ADC_SMPR_SMP_12P5), 0
     },
     .sqr = {
-        ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1),
+        ADC_SQR1_SQ1_N(ADC_CHANNEL_IN1) | ADC_SQR1_SQ2_N(ADC_CHANNEL_IN2),
         0, 0, 0
     },
 };
@@ -107,6 +107,7 @@ void ADC::begin()
 #else
     palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG); // Algorithm in
     palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG); // Potentiometer 1
+    palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG); // Potentiometer 2
 #endif
 
     adcStart(m_driver, &m_config);
@@ -135,15 +136,15 @@ void ADC::stop()
 
 adcsample_t ADC::readAlt(unsigned int id)
 {
-    if (id != 0)
+    if (id > 1)
         return 0;
-    static adcsample_t result[32] = {};
+    static adcsample_t result[16] = {};
     readAltDone = false;
-    adcStartConversion(m_driver2, &m_group_config2, result, 32);
+    adcStartConversion(m_driver2, &m_group_config2, result, 8);
     while (!readAltDone)
-        ;
+        __WFI();
     adcStopConversion(m_driver2);
-    return result[0];
+    return result[id];
 }
 
 void ADC::setRate(SClock::Rate rate)
index 24a7fff2b82471d3745c3fcb35832c3bbb377b87..5f7fa08ff4ba8ab5444930f8fd5feddbc0e07508 100644 (file)
@@ -2,7 +2,7 @@
  * @file adc.hpp
  * @brief Manages signal reading through the ADC.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
index ce9c465dc165f9a6c7d88f4aca197c3a32bfa5fd..2772928f48dd0d71eced9d6fe1163d73ca9040fd 100644 (file)
@@ -2,7 +2,7 @@
  * @file dac.cpp
  * @brief Manages signal creation using the DAC.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
@@ -22,9 +22,16 @@ const DACConfig DAC::m_config = {
     .cr = 0
 };
 
+static int dacIsDone = -1;
+static void dacEndCallback(DACDriver *dacd)
+{
+    if (dacd == &DACD2)
+        dacIsDone = dacIsBufferComplete(dacd) ? 1 : 0;
+}
+
 const DACConversionGroup DAC::m_group_config = {
     .num_channels = 1,
-    .end_cb = nullptr,
+    .end_cb = dacEndCallback,
     .error_cb = nullptr,
 #if defined(TARGET_PLATFORM_H7)
     .trigger = 5 // TIM6_TRGO
@@ -45,11 +52,18 @@ void DAC::begin()
 void DAC::start(int channel, dacsample_t *buffer, size_t count)
 {
     if (channel >= 0 && channel < 2) {
+        if (channel == 1)
+            dacIsDone = -1;
         dacStartConversion(m_driver[channel], &m_group_config, buffer, count);
         SClock::start();
     }
 }
 
+int DAC::sigGenWantsMore()
+{
+    return dacIsDone;
+}
+
 void DAC::stop(int channel)
 {
     if (channel >= 0 && channel < 2) {
index e305c4be9fcc017e2c4956b17957a496e6f40546..4360c26596cea3954182d60a83d3493d5d075faa 100644 (file)
@@ -2,7 +2,7 @@
  * @file dac.hpp
  * @brief Manages signal creation using the DAC.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
@@ -23,6 +23,8 @@ public:
     static void start(int channel, dacsample_t *buffer, size_t count);
     static void stop(int channel);
 
+    static int sigGenWantsMore();
+
 private:
     static DACDriver *m_driver[2];
 
index 0e41d6aedf9a95d258605146cbe43e0c0f7705c6..e1612069361a761428178bcb6d4969526495710e 100644 (file)
@@ -2,7 +2,7 @@
  * @file elf_load.cpp
  * @brief Loads ELF binary data into memory for execution.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
index 619dada288dc3cb3a460730ebfca2709e8be836b..ae7265bda7d55c7c35c984f102e06878a4e544a3 100644 (file)
@@ -2,7 +2,7 @@
  * @file elf_load.hpp
  * @brief Loads ELF binary data into memory for execution.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
index aaf268ab54df5d57b489ff13349748602f355e15..e9c33efba168f4b6fe52a0f07594f269b50580bc 100644 (file)
@@ -2,7 +2,7 @@
  * @file main.cpp
  * @brief Program entry point.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
@@ -26,8 +26,16 @@ static_assert(sizeof(dacsample_t) == sizeof(uint16_t));
 
 #include <array>
 
-constexpr unsigned int MAX_ELF_FILE_SIZE = 16 * 1024;
+// Pin definitions
+//
+#if defined(TARGET_PLATFORM_L4)
+constexpr auto LINE_LED_GREEN = PAL_LINE(GPIOC_BASE, 10U);
+constexpr auto LINE_LED_YELLOW = PAL_LINE(GPIOC_BASE, 11U);
+constexpr auto LINE_LED_RED = PAL_LINE(GPIOC_BASE, 12U);
+#endif
 
+// Run status
+//
 enum class RunStatus : char
 {
     Idle = '1',
@@ -36,6 +44,8 @@ enum class RunStatus : char
 };
 static RunStatus run_status = RunStatus::Idle;
 
+// Conversion threads messaging
+//
 #define MSG_CONVFIRST          (1)
 #define MSG_CONVSECOND         (2)
 #define MSG_CONVFIRST_MEASURE  (3)
@@ -44,43 +54,11 @@ static RunStatus run_status = RunStatus::Idle;
 #define MSG_FOR_FIRST(m)   (m & 1)
 #define MSG_FOR_MEASURE(m) (m > 2)
 
-static ErrorManager EM;
-
 static msg_t conversionMBBuffer[2];
 static MAILBOX_DECL(conversionMB, conversionMBBuffer, 2);
 
-// Thread for LED status and wakeup hold
-__attribute__((section(".stacks")))
-static THD_WORKING_AREA(monitorThreadWA, 256);
-static THD_FUNCTION(monitorThread, arg);
-
-// Thread for managing the conversion task
-__attribute__((section(".stacks")))
-static THD_WORKING_AREA(conversionThreadMonitorWA, 1024);
-static THD_FUNCTION(conversionThreadMonitor, arg);
-static thread_t *conversionThreadHandle = nullptr;
-
-// Thread for unprivileged algorithm execution
-__attribute__((section(".stacks")))
-static THD_WORKING_AREA(conversionThreadWA, 128); // All we do is enter unprivileged mode.
-static THD_FUNCTION(conversionThread, arg);
-constexpr unsigned int conversionThreadUPWASize = 
-#if defined(TARGET_PLATFORM_H7)
-                                                  62 * 1024;
-#else
-                                                  15 * 1024;
-#endif
-__attribute__((section(".convdata")))
-static THD_WORKING_AREA(conversionThreadUPWA, conversionThreadUPWASize);
-__attribute__((section(".convdata")))
-static thread_t *conversionThreadMonitorHandle = nullptr;
-
-// Thread for USB monitoring
-__attribute__((section(".stacks")))
-static THD_WORKING_AREA(communicationThreadWA, 4096);
-static THD_FUNCTION(communicationThread, arg);
-
-static time_measurement_t conversion_time_measurement;
+// Sample input and output buffers
+//
 #if defined(TARGET_PLATFORM_H7)
 __attribute__((section(".convdata")))
 static SampleBuffer samplesIn  (reinterpret_cast<Sample *>(0x38000000)); // 16k
@@ -95,35 +73,38 @@ static SampleBuffer samplesOut (reinterpret_cast<Sample *>(0x2000C000)); // 16k
 static SampleBuffer samplesSigGen (reinterpret_cast<Sample *>(0x20010000)); // 16k
 #endif
 
+// Algorithm binary storage
+//
+constexpr unsigned int MAX_ELF_FILE_SIZE = 16 * 1024;
 static unsigned char elf_file_store[MAX_ELF_FILE_SIZE];
 __attribute__((section(".convdata")))
 static ELF::Entry elf_entry = nullptr;
 
+// Other variables
+//
+static ErrorManager EM;
+static time_measurement_t conversion_time_measurement;
 static char userMessageBuffer[128];
 static unsigned char userMessageSize = 0;
 
+// Functions
+//
 __attribute__((section(".convcode")))
 static void conversion_unprivileged_main();
-
-static void mpu_setup();
+static void startThreads();
+static void mpuSetup();
 static void abortAlgorithmFromISR();
-static void signal_operate(adcsample_t *buffer, size_t count);
-static void signal_operate_measure(adcsample_t *buffer, size_t count);
-
-#if defined(TARGET_PLATFORM_L4)
-constexpr auto LINE_LED_GREEN = PAL_LINE(GPIOC_BASE, 10U);
-constexpr auto LINE_LED_YELLOW = PAL_LINE(GPIOC_BASE, 11U);
-constexpr auto LINE_LED_RED = PAL_LINE(GPIOC_BASE, 12U);
-#endif
+static void signalOperate(adcsample_t *buffer, size_t count);
+static void signalOperateMeasure(adcsample_t *buffer, size_t count);
 
 int main()
 {
-    // Initialize the RTOS
+    // Initialize ChibiOS
     halInit();
     chSysInit();
 
     SCB->CPACR |= 0xF << 20; // Enable FPU
-    mpu_setup();
+    mpuSetup();
 
 #if defined(TARGET_PLATFORM_L4)
     palSetLineMode(LINE_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL);
@@ -140,7 +121,42 @@ int main()
     SClock::setRate(SClock::Rate::R32K);
     ADC::setRate(SClock::Rate::R32K);
 
-    chTMObjectInit(&conversion_time_measurement);
+    startThreads();
+    chThdExit(0);
+    return 0;
+}
+
+static THD_FUNCTION(monitorThread, arg);           // Runs status LEDs and allows debug halt.
+static THD_FUNCTION(conversionThreadMonitor, arg); // Monitors and manages algo. thread.
+static THD_FUNCTION(conversionThread, arg);        // Algorithm thread (unprivileged).
+static THD_FUNCTION(communicationThread, arg);     // Manages USB communications.
+
+// Need to hold some thread handles for mailbox usage.
+static thread_t *conversionThreadHandle = nullptr;
+__attribute__((section(".convdata")))
+static thread_t *conversionThreadMonitorHandle = nullptr;
+
+// The more stack for the algorithm, the merrier.
+constexpr unsigned int conversionThreadUPWASize =
+#if defined(TARGET_PLATFORM_H7)
+                                                  62 * 1024;
+#else
+                                                  15 * 1024;
+#endif
+
+__attribute__((section(".stacks")))
+static THD_WORKING_AREA(monitorThreadWA, 256);
+__attribute__((section(".stacks")))
+static THD_WORKING_AREA(conversionThreadMonitorWA, 1024);
+__attribute__((section(".stacks")))
+static THD_WORKING_AREA(conversionThreadWA, 128); // For entering unprivileged mode.
+__attribute__((section(".convdata")))
+static THD_WORKING_AREA(conversionThreadUPWA, conversionThreadUPWASize);
+__attribute__((section(".stacks")))
+static THD_WORKING_AREA(communicationThreadWA, 4096);
+
+void startThreads()
+{
     chThdCreateStatic(
         monitorThreadWA, sizeof(monitorThreadWA),
         LOWPRIO,
@@ -149,19 +165,17 @@ int main()
         conversionThreadMonitorWA, sizeof(conversionThreadMonitorWA),
         NORMALPRIO + 1,
         conversionThreadMonitor, nullptr);
+    auto conversionThreadUPWAEnd =
+        reinterpret_cast<uint32_t>(conversionThreadUPWA) + conversionThreadUPWASize;
     conversionThreadHandle = chThdCreateStatic(
         conversionThreadWA, sizeof(conversionThreadWA),
         HIGHPRIO,
         conversionThread,
-        reinterpret_cast<void *>(reinterpret_cast<uint32_t>(conversionThreadUPWA) +
-                                 conversionThreadUPWASize));
+        reinterpret_cast<void *>(conversionThreadUPWAEnd));
     chThdCreateStatic(
         communicationThreadWA, sizeof(communicationThreadWA),
         NORMALPRIO,
         communicationThread, nullptr);
-
-    chThdExit(0);
-    return 0;
 }
 
 THD_FUNCTION(communicationThread, arg)
@@ -190,7 +204,7 @@ THD_FUNCTION(communicationThread, arg)
                 // 'S' - Stop conversion.
                 // 's' - Get latest block of conversion results.
                 // 't' - Get latest block of conversion input.
-               // 'u' - Get user message.
+                // 'u' - Get user message.
                 // 'W' - Start signal generator (siggen).
                 // 'w' - Stop siggen.
 
@@ -222,8 +236,22 @@ THD_FUNCTION(communicationThread, arg)
                     if (EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) {
                         unsigned int count = cmd[1] | (cmd[2] << 8);
                         if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) {
-                            samplesSigGen.setSize(count);
-                            USBSerial::read(samplesSigGen.bytedata(), samplesSigGen.bytesize());
+                            if (run_status == RunStatus::Idle) {
+                                samplesSigGen.setSize(count * 2);
+                                USBSerial::read(
+                                    reinterpret_cast<uint8_t *>(samplesSigGen.middata()),
+                                    samplesSigGen.bytesize() / 2);
+                            } else if (run_status == RunStatus::Running) {
+                                int more;
+                                do {
+                                    chThdSleepMicroseconds(10);
+                                    more = DAC::sigGenWantsMore();
+                                } while (more == -1);
+
+                                USBSerial::read(reinterpret_cast<uint8_t *>(
+                                    more == 0 ? samplesSigGen.data() : samplesSigGen.middata()),
+                                    samplesSigGen.bytesize() / 2);
+                            }
                         }
                     }
                     break;
@@ -275,7 +303,7 @@ THD_FUNCTION(communicationThread, arg)
                     if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) {
                         run_status = RunStatus::Running;
                         samplesOut.clear();
-                        ADC::start(samplesIn.data(), samplesIn.size(), signal_operate_measure);
+                        ADC::start(samplesIn.data(), samplesIn.size(), signalOperateMeasure);
                         DAC::start(0, samplesOut.data(), samplesOut.size());
                     }
                     break;
@@ -293,7 +321,7 @@ THD_FUNCTION(communicationThread, arg)
                     if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) {
                         run_status = RunStatus::Running;
                         samplesOut.clear();
-                        ADC::start(samplesIn.data(), samplesIn.size(), signal_operate);
+                        ADC::start(samplesIn.data(), samplesIn.size(), signalOperate);
                         DAC::start(0, samplesOut.data(), samplesOut.size());
                     }
                     break;
@@ -488,7 +516,7 @@ void conversion_unprivileged_main()
     }
 }
 
-void mpu_setup()
+void mpuSetup()
 {
     // Set up MPU for user algorithm
 #if defined(TARGET_PLATFORM_H7)
@@ -561,7 +589,7 @@ void abortAlgorithmFromISR()
     }
 }
 
-void signal_operate(adcsample_t *buffer, size_t)
+void signalOperate(adcsample_t *buffer, size_t)
 {
     chSysLockFromISR();
 
@@ -582,7 +610,7 @@ void signal_operate(adcsample_t *buffer, size_t)
     }
 }
 
-void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count)
+void signalOperateMeasure(adcsample_t *buffer, [[maybe_unused]] size_t count)
 {
     chSysLockFromISR();
     if (buffer == samplesIn.data()) {
@@ -594,7 +622,7 @@ void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count)
     }
     chSysUnlockFromISR();
 
-    ADC::setOperation(signal_operate);
+    ADC::setOperation(signalOperate);
 }
 
 extern "C" {
@@ -654,7 +682,7 @@ void port_syscall(struct port_extctx *ctxp, uint32_t n)
         }
         break;
     case 3:
-        ctxp->r0 = ADC::readAlt(0);
+        ctxp->r0 = ADC::readAlt(ctxp->r0);
         break;
     case 4:
         {
index 24cc42423fe3f975a8ead1bd11367a8bf68b5e79..1acf2f46eacb15cda2c6a098af32585241ef074c 100644 (file)
@@ -1,3 +1,14 @@
+/**
+ * @file samplebuffer.cpp
+ * @brief Manages ADC/DAC buffer data.
+ *
+ * Copyright (C) 2021 Clyne Sullivan
+ *
+ * Distributed under the GNU GPL v3 or later. You should have received a copy of
+ * the GNU General Public License along with this program.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
 #include "samplebuffer.hpp"
 
 SampleBuffer::SampleBuffer(Sample *buffer) :
index 6d17d2acecdfbd201e20dd9ab4817e5f513857c7..d13023aebed1d3e9f0a8f6a1b4acfc4793533544 100644 (file)
@@ -1,3 +1,14 @@
+/**
+ * @file samplebuffer.hpp
+ * @brief Manages ADC/DAC buffer data.
+ *
+ * Copyright (C) 2021 Clyne Sullivan
+ *
+ * Distributed under the GNU GPL v3 or later. You should have received a copy of
+ * the GNU General Public License along with this program.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
 #ifndef SAMPLEBUFFER_HPP_
 #define SAMPLEBUFFER_HPP_
 
index 198c6841f40204e9b13df119a7b793efacdfb9c5..317b9952937fcbac959b975690c07dd388fedb06 100644 (file)
@@ -1,3 +1,14 @@
+/**
+ * @file sclock.cpp
+ * @brief Manages sampling rate clock speeds.
+ *
+ * Copyright (C) 2021 Clyne Sullivan
+ *
+ * Distributed under the GNU GPL v3 or later. You should have received a copy of
+ * the GNU General Public License along with this program.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
 #include "sclock.hpp"
 
 GPTDriver *SClock::m_timer = &GPTD6;
index 960d9e34137eadc1ffb4727d11fa742343b792a1..d5b93df095b35e794af7ded107aaf18aa28d5212 100644 (file)
@@ -1,3 +1,14 @@
+/**
+ * @file sclock.hpp
+ * @brief Manages sampling rate clock speeds.
+ *
+ * Copyright (C) 2021 Clyne Sullivan
+ *
+ * Distributed under the GNU GPL v3 or later. You should have received a copy of
+ * the GNU General Public License along with this program.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
 #ifndef SCLOCK_HPP_
 #define SCLOCK_HPP_
 
index c24be2f15ae43d31137347861027731d7057e782..775a9117c24acc2679402e14f057902313e765c1 100644 (file)
@@ -2,7 +2,7 @@
  * @file usbserial.cpp
  * @brief Wrapper for ChibiOS's SerialUSBDriver.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.
@@ -32,7 +32,7 @@ bool USBSerial::isActive()
 {
     if (auto config = m_driver->config; config != nullptr) {
         if (auto usbp = config->usbp; usbp != nullptr)
-            return usbp->state == USB_ACTIVE;
+            return usbp->state == USB_ACTIVE && !ibqIsEmptyI(&m_driver->ibqueue);
     }
 
     return false;
index 828fc56ac7d52a333d15a875c1e5c77f02ca7065..58113c95dd85e456633fa2372d2b9056e6034466 100644 (file)
@@ -2,7 +2,7 @@
  * @file usbserial.hpp
  * @brief Wrapper for ChibiOS's SerialUSBDriver.
  *
- * Copyright (C) 2020 Clyne Sullivan
+ * Copyright (C) 2021 Clyne Sullivan
  *
  * Distributed under the GNU GPL v3 or later. You should have received a copy of
  * the GNU General Public License along with this program.