]> code.bitgloo.com Git - clyne/stmdsp.git/commitdiff
document/standardize; add compile log to gui
authorClyne Sullivan <clyne@bitgloo.com>
Mon, 19 Oct 2020 01:20:00 +0000 (21:20 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Mon, 19 Oct 2020 01:20:00 +0000 (21:20 -0400)
gui/stmdsp.cpp
gui/stmdsp.hpp
gui/wxmain.cpp
gui/wxmain.hpp
source/adc.cpp
source/elf_format.hpp
source/elf_load.cpp
source/elf_load.hpp
source/main.cpp

index bbfc716e5d15af08b9ddbd65a2ad5c389c8daf0b..8f190651c0c11f7671b4b2ace1dbf195d10991de 100644 (file)
@@ -25,10 +25,10 @@ namespace stmdsp
         }
     }
 
-    std::vector<adcsample_t> device::sample(unsigned long int count) {
+    /*std::vector<adcsample_t> device::sample(unsigned long int count) {
         if (connected()) {
             uint8_t request[3] = {
-                'r',
+                'd',
                 static_cast<uint8_t>(count),
                 static_cast<uint8_t>(count >> 8)
             };
@@ -39,7 +39,7 @@ namespace stmdsp
         } else {
             return {};
         }
-    }
+    }*/
 
     void device::continuous_start() {
         if (connected())
@@ -63,7 +63,7 @@ namespace stmdsp
 
     std::vector<adcsample_t> device::continuous_read() {
         if (connected()) {
-            m_serial.write("s");
+            m_serial.write("a");
             std::vector<adcsample_t> data (2048);
             m_serial.read(reinterpret_cast<uint8_t *>(data.data()), 2048 * sizeof(adcsample_t));
             return data;
@@ -80,7 +80,7 @@ namespace stmdsp
     void device::upload_filter(unsigned char *buffer, size_t size) {
         if (connected()) {
             uint8_t request[3] = {
-                'e',
+                'E',
                 static_cast<uint8_t>(size),
                 static_cast<uint8_t>(size >> 8)
             };
@@ -92,6 +92,6 @@ namespace stmdsp
 
     void device::unload_filter() {
         if (connected())
-            m_serial.write("E");
+            m_serial.write("e");
     }
 }
index 06d36ba0324ef1fb968db286b861a8bbd54bb5ae..2d336c534614ddeb91a0533b63d6ca1c21706448 100644 (file)
@@ -38,7 +38,7 @@ namespace stmdsp
             return m_serial.isOpen();
         }
 
-        std::vector<adcsample_t> sample(unsigned long int count = 1);
+        //std::vector<adcsample_t> sample(unsigned long int count = 1);
 
         void continuous_start();
         void continuous_start_measure();
index d4f48787a2881217f344970b9c714aad87379551..874f26ec4940a9962252df6b59fddf7be8f1900e 100644 (file)
@@ -63,9 +63,13 @@ MainFrame::MainFrame() : wxFrame(nullptr, -1, "stmdspgui", wxPoint(50, 50), wxSi
 
     auto window = new wxBoxSizer(wxVERTICAL);
 
-    m_text_editor = new wxStyledTextCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(620, 700));
+    m_text_editor = new wxStyledTextCtrl(this, wxID_ANY, wxDefaultPosition, wxSize(620, 500));
     prepareEditor();
-    window->Add(m_text_editor, 1, wxEXPAND | wxALL, 10);
+    window->Add(m_text_editor, 2, wxEXPAND | wxALL, 10);
+
+    m_compile_output = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
+                                      wxTE_READONLY | wxTE_MULTILINE | wxHSCROLL);
+    window->Add(m_compile_output, 1, wxEXPAND | wxALL, 10);
 
     SetSizerAndFit(window);
 
@@ -168,9 +172,15 @@ wxString MainFrame::compileEditorCode()
     makefile.Write(make_text);
     makefile.Close();
 
+    wxString make_output = temp_file_name + "make.log";
     wxString make_command = wxString("make -C ") + temp_file_name.BeforeLast('/') +
-                            " -f " + temp_file_name + "make";
-    if (system(make_command.ToAscii()) == 0) {
+                            " -f " + temp_file_name + "make" +
+                            " > " + make_output + " 2>&1";
+
+    int result = system(make_command.ToAscii());
+    m_compile_output->LoadFile(make_output);
+
+    if (result == 0) {
         m_status_bar->SetStatusText("Compilation succeeded.");
         return temp_file_name + ".o";
     } else {
index b8ff11d2ae664de7be08f4e8d2b5bacf2f34d5d4..268a08d668efdfe397fe79edba8a153b5430c19b 100644 (file)
@@ -3,7 +3,9 @@
 
 #include "stmdsp.hpp"
 
+#include <fstream>
 #include <future>
+#include <iostream>
 #include <thread>
 #include <wx/button.h>
 #include <wx/combobox.h>
@@ -39,6 +41,7 @@ private:
     bool m_is_running = false;
     wxComboBox *m_device_combo = nullptr;
     wxStyledTextCtrl *m_text_editor = nullptr;
+    wxTextCtrl *m_compile_output = nullptr;
     wxControl *m_signal_area = nullptr;
     wxMenuItem *m_run_measure = nullptr;
     wxTimer *m_measure_timer = nullptr;
index 744dbc077676472644a6fe331c534c07d075e678..6c1af7b2ccc01b90c26c7cfe78dcc3c63a6c429e 100644 (file)
@@ -26,7 +26,7 @@ static ADCConversionGroup adc_group_config = {
     .end_cb = adc_read_callback,
     .error_cb = nullptr,
     .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(12),  /* TIM4_TRGO */
-    .cfgr2 = 0,
+    .cfgr2 = 0,//ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1, // Oversampling 2x
     .tr1 = ADC_TR(0, 4095),
     .smpr = {
         ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_12P5), 0
index ed74c7bfe4fb2cfa045a5ee6877d389d31fb1600..d4feb9902d9ceb442385e9d0ac90d9b362869ae2 100644 (file)
@@ -1,3 +1,10 @@
+/**
+ * @file elf_format.cpp
+ * @brief Defines ELF binary format info.
+ *
+ * Free to use, written by Clyne Sullivan.
+ */
+
 #ifndef STMDSP_ELF_FORMAT_HPP_
 #define STMDSP_ELF_FORMAT_HPP_
 
index 3fd8a0ffb9ed399e1c4072893b7051dc2a1e3ac0..79cd4feccf680cbe28f270037865dbfac6aff7a6 100644 (file)
@@ -1,11 +1,20 @@
+/**
+ * @file elf_load.cpp
+ * @brief Loads ELF binary data into memory for execution.
+ *
+ * Copyright (C) 2020 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 "elf_load.hpp"
 #include "elf_format.hpp"
 
 #include <algorithm>
 #include <cstring>
 
-//constexpr unsigned int ELF_LOAD_ADDR = 0x10000000;
-
 static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' };
 
 template<typename T>
@@ -14,8 +23,6 @@ constexpr static auto ptr_from_offset(void *base, uint32_t offset)
     return reinterpret_cast<T>(reinterpret_cast<uint8_t *>(base) + offset);
 }
 
-//static Elf32_Shdr *find_section(Elf32_Ehdr *ehdr, const char *name);
-
 namespace elf {
 
 entry_t load(void *elf_data)
@@ -52,20 +59,3 @@ entry_t load(void *elf_data)
 
 } // namespace elf
 
-//Elf32_Shdr *find_section(Elf32_Ehdr *ehdr, const char *name)
-//{
-//    auto shdr = ptr_from_offset<Elf32_Shdr *>(ehdr, ehdr->e_shoff);
-//    auto shdr_str = ptr_from_offset<Elf32_Shdr *>(ehdr,
-//        ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
-//
-//    for (Elf32_Half i = 0; i < ehdr->e_shnum; i++) {
-//        char *section = ptr_from_offset<char *>(ehdr, shdr_str->sh_offset) + shdr->sh_name;
-//        if (!strcmp(section, name))
-//            return shdr;
-//
-//        shdr = ptr_from_offset<Elf32_Shdr *>(shdr, ehdr->e_shentsize);
-//    }
-//
-//    return 0;
-//}
-
index 4fda5262273938cfaf52b42b8e9817eed1319132..faa74d236d545ba47fccfdefafb0120726bef6a6 100644 (file)
@@ -1,3 +1,14 @@
+/**
+ * @file elf_load.hpp
+ * @brief Loads ELF binary data into memory for execution.
+ *
+ * Copyright (C) 2020 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 ELF_LOAD_HPP_
 #define ELF_LOAD_HPP_
 
index 1e3c5fb1c0e530593e76bb1d852a34b0689d732f..c46685f136805f291f41a81a48a6383e35164754 100644 (file)
 
 #include <array>
 
+constexpr unsigned int MAX_ELF_FILE_SIZE = 12 * 1024;
+constexpr unsigned int MAX_ERROR_QUEUE_SIZE = 8;
 constexpr unsigned int MAX_SAMPLE_BUFFER_SIZE = 8000;
 
 enum class RunStatus : char
 {
     Idle = '1',
-    Converting,
-    Recovered
+    Running
 };
+enum class Error : char
+{
+    None = 0,
+    BadParam,
+    BadParamSize,
+    BadUserCodeLoad,
+    BadUserCodeSize,
+    NotIdle,
+    ConversionAborted
+};
+
 static RunStatus run_status = RunStatus::Idle;
+static Error error_queue[MAX_ERROR_QUEUE_SIZE];
+static unsigned int error_queue_index = 0;
+
+static void error_queue_add(Error error)
+{
+    if (error_queue_index < MAX_ERROR_QUEUE_SIZE)
+        error_queue[error_queue_index++] = error;
+}
+static Error error_queue_pop()
+{
+    return error_queue_index == 0 ? Error::None : error_queue[--error_queue_index];
+}
 
 #define MSG_CONVFIRST          (1)
 #define MSG_CONVSECOND         (2)
 #define MSG_CONVFIRST_MEASURE  (3)
 #define MSG_CONVSECOND_MEASURE (4)
 
-static msg_t conversionMBBuffer[8];
-static MAILBOX_DECL(conversionMB, conversionMBBuffer, 8);
+static msg_t conversionMBBuffer[4];
+static MAILBOX_DECL(conversionMB, conversionMBBuffer, 4);
 
 static THD_WORKING_AREA(conversionThreadWA, 1024);
 static THD_FUNCTION(conversionThread, arg);
@@ -54,7 +78,7 @@ CC_ALIGN(CACHE_LINE_SIZE)
 #endif
 static std::array<dacsample_t, CACHE_SIZE_ALIGN(dacsample_t, MAX_SAMPLE_BUFFER_SIZE)> dac_samples;
 
-static uint8_t elf_file_store[12288];
+static uint8_t elf_file_store[MAX_ELF_FILE_SIZE];
 static elf::entry_t elf_entry = nullptr;
 
 static void signal_operate(adcsample_t *buffer, size_t count);
@@ -87,9 +111,13 @@ int main()
     main_loop();
 }
 
+static unsigned int dac_sample_count = MAX_SAMPLE_BUFFER_SIZE;
+static unsigned int adc_sample_count = MAX_SAMPLE_BUFFER_SIZE;
+static bool adc_preloaded = false;
+static bool dac_preloaded = false;
+
 void main_loop()
 {
-    static unsigned int dac_sample_count = MAX_SAMPLE_BUFFER_SIZE;
 
        while (1) {
         if (usbserial::is_active()) {
@@ -98,111 +126,136 @@ void main_loop()
                 // Packet received, first byte represents the desired command/action
                 switch (cmd[0]) {
 
-                // 'r' - Conduct a single sample of the ADC, and send the results back over USB.
-                case 'r':
-                    // Get the next two bytes of the packet to determine the desired sample size
-                    if (run_status != RunStatus::Idle || usbserial::read(&cmd[1], 2) < 2)
-                        break;
-                    if (unsigned int desiredSize = cmd[1] | (cmd[2] << 8); desiredSize <= adc_samples.size()) {
-                        adc::read(&adc_samples[0], desiredSize);
-                        usbserial::write(adc_samples.data(), desiredSize * sizeof(adcsample_t));
-                    }
+                case 'a':
+                    usbserial::write(adc_samples.data(), adc_sample_count * sizeof(adcsample_t));
+                    break;
+                case 'A':
+                    usbserial::read(&adc_samples[0], adc_sample_count * sizeof(adcsample_t));
                     break;
 
-                // 'R' - Begin continuous sampling/conversion of the ADC. Samples will go through
-                //       the conversion code, and will be sent out over the DAC.
-                case 'R':
-                    //if (run_status != RunStatus::Idle)
-                    //    break;
-
-                    run_status = RunStatus::Converting;
-                    dac_samples.fill(0);
-                    adc::read_start(signal_operate, &adc_samples[0], adc_samples.size());
-                    dac::write_start(&dac_samples[0], dac_samples.size());
+                case 'B':
+                    if (run_status == RunStatus::Idle) {
+                        if (usbserial::read(&cmd[1], 2) == 2) {
+                            unsigned int count = cmd[1] | (cmd[2] << 8);
+                            if (count <= MAX_SAMPLE_BUFFER_SIZE / 2) {
+                                adc_sample_count = count * 2;
+                                dac_sample_count = count * 2;
+                            } else {
+                                error_queue_add(Error::BadParam);
+                            }
+                        } else {
+                            error_queue_add(Error::BadParamSize);
+                        }
+                    } else {
+                        error_queue_add(Error::NotIdle);
+                    }
                     break;
 
-                // 'M' - Begins continuous sampling, but measures the execution time of the first
-                //       sample processing. This duration can be later read through 'm'.
-                case 'M':
-                    run_status = RunStatus::Converting;
-                    dac_samples.fill(0);
-                    adc::read_start(signal_operate_measure, &adc_samples[0], adc_samples.size());
-                    dac::write_start(&dac_samples[0], dac_samples.size());
+                case 'd':
+                    usbserial::write(dac_samples.data(), dac_sample_count * sizeof(dacsample_t));
+                    break;
+                case 'D':
+                    usbserial::read(&dac_samples[0], dac_sample_count * sizeof(dacsample_t));
                     break;
 
-                // 'm' - Returns the last measured sample processing time, presumably in processor
-                //       ticks.
-                case 'm':
-                    usbserial::write(&conversion_time_measurement.last, sizeof(rtcnt_t));
+                // 'E' - Reads in and loads the compiled conversion code binary from USB.
+                case 'E':
+                    if (run_status == RunStatus::Idle) {
+                        if (usbserial::read(&cmd[1], 2) == 2) {
+                            // Only load the binary if it can fit in the memory reserved for it.
+                            unsigned int size = cmd[1] | (cmd[2] << 8);
+                            if (size < sizeof(elf_file_store)) {
+                                usbserial::read(elf_file_store, size);
+                                elf_entry = elf::load(elf_file_store);
+
+                                if (elf_entry == nullptr)
+                                    error_queue_add(Error::BadUserCodeLoad);
+                            } else {
+                                error_queue_add(Error::BadUserCodeSize);
+                            }
+                        } else {
+                            error_queue_add(Error::BadParamSize);
+                        }
+                    } else {
+                        error_queue_add(Error::NotIdle);
+                    }
                     break;
 
-                // 's' - Sends the current contents of the DAC buffer back over USB.
-                case 's':
-                    usbserial::write(dac_samples.data(), 1/*dac_samples.size()*/ * sizeof(dacsample_t));
+                // 'e' - Unloads the currently loaded conversion code
+                case 'e':
+                    elf_entry = nullptr;
                     break;
 
-                // 'S' - Stops the continuous sampling/conversion.
-                case 'S':
-                    //if (run_status != RunStatus::Converting)
-                    //    break;
+                // 'i' - Sends an identifying string to confirm that this is the stmdsp device.
+                case 'i':
+                    usbserial::write("stmdsp", 6);
+                    break;
 
-                    dac::write_stop();
-                    adc::read_stop();
-                    run_status = RunStatus::Idle;
+                // 'I' - Sends the current run status.
+                case 'I':
+                    {
+                        char buf[2] = {
+                            static_cast<char>(run_status),
+                            static_cast<char>(error_queue_pop())
+                        };
+                        usbserial::write(buf, sizeof(buf));
+                    }
                     break;
 
-                // 'e' - Reads in and loads the compiled conversion code binary from USB.
-                case 'e':
-                    // Get the binary's size
-                    if (usbserial::read(&cmd[1], 2) < 2)
-                        break;
-
-                    // Only load the binary if it can fit in the memory reserved for it.
-                    if (unsigned int binarySize = cmd[1] | (cmd[2] << 8); binarySize < sizeof(elf_file_store)) {
-                        usbserial::read(elf_file_store, binarySize);
-                        elf_entry = elf::load(elf_file_store);
+                // 'M' - Begins continuous sampling, but measures the execution time of the first
+                //       sample processing. This duration can be later read through 'm'.
+                case 'M':
+                    if (run_status == RunStatus::Idle) {
+                        run_status = RunStatus::Running;
+                        dac_samples.fill(0);
+                        if (!adc_preloaded)
+                            adc::read_start(signal_operate_measure, &adc_samples[0], adc_sample_count);
+                        if (!dac_preloaded)
+                            dac::write_start(&dac_samples[0], dac_sample_count);
                     } else {
-                        elf_entry = nullptr;
+                        error_queue_add(Error::NotIdle);
                     }
                     break;
 
-                // 'E' - Unloads the currently loaded conversion code
-                case 'E':
-                    elf_entry = nullptr;
+                // 'm' - Returns the last measured sample processing time, presumably in processor
+                //       ticks.
+                case 'm':
+                    usbserial::write(&conversion_time_measurement.last, sizeof(rtcnt_t));
                     break;
 
-                // 'W' - Sets the number of samples for DAC writing with command 'w'.
-                //       If the provided count is zero, DAC writing is stopped.
-                case 'W':
-                    if (usbserial::read(&cmd[1], 2) < 2)
-                        break;
-                    if (unsigned int sampleCount = cmd[1] | (cmd[2] << 8); sampleCount <= dac_samples.size()) {
-                        if (sampleCount > 0)
-                            dac_sample_count = sampleCount;
-                        else
-                            dac::write_stop();
+                // 'R' - Begin continuous sampling/conversion of the ADC. Samples will go through
+                //       the conversion code, and will be sent out over the DAC.
+                case 'R':
+                    if (run_status == RunStatus::Idle) {
+                        run_status = RunStatus::Running;
+                        dac_samples.fill(0);
+                        if (!adc_preloaded)
+                            adc::read_start(signal_operate, &adc_samples[0], adc_sample_count);
+                        if (!dac_preloaded)
+                            dac::write_start(&dac_samples[0], dac_sample_count);
+                    } else {
+                        error_queue_add(Error::NotIdle);
                     }
                     break;
 
-                // 'w' - Starts the DAC, looping over the given data (data size set by command 'W').
-                case 'w':
-                    if (usbserial::read(&dac_samples[0], dac_sample_count * sizeof(dacsample_t) !=
-                        dac_sample_count * sizeof(dacsample_t)))
-                    {
-                        break;
+                case 'r':
+                    if (usbserial::read(&cmd[1], 1) == 1) {
+                        adc_preloaded = cmd[1] & (1 << 0);
+                        dac_preloaded = cmd[1] & (1 << 1);
                     } else {
-                        dac::write_start(&dac_samples[0], dac_sample_count);
+                        error_queue_add(Error::BadParamSize);
                     }
                     break;
 
-                // 'i' - Sends an identifying string to confirm that this is the stmdsp device.
-                case 'i':
-                    usbserial::write("stmdsp", 6);
-                    break;
-
-                // 'I' - Sends the current run status.
-                case 'I':
-                    usbserial::write(&run_status, sizeof(run_status));
+                // 'S' - Stops the continuous sampling/conversion.
+                case 'S':
+                    if (run_status == RunStatus::Running) {
+                        if (!dac_preloaded)
+                            dac::write_stop();
+                        if (!adc_preloaded)
+                            adc::read_stop();
+                        run_status = RunStatus::Idle;
+                    }
                     break;
 
                 default:
@@ -218,9 +271,11 @@ void main_loop()
 void conversion_abort()
 {
     elf_entry = nullptr;
-    dac::write_stop();
-    adc::read_stop();
-    run_status = RunStatus::Recovered;
+    if (!dac_preloaded)
+        dac::write_stop();
+    if (!adc_preloaded)
+        adc::read_stop();
+    error_queue_add(Error::ConversionAborted);
 }
 
 THD_FUNCTION(conversionThread, arg)
@@ -231,7 +286,7 @@ THD_FUNCTION(conversionThread, arg)
         msg_t message;
         if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK) {
             adcsample_t *samples = nullptr;
-            auto halfsize = adc_samples.size() / 2;
+            auto halfsize = adc_sample_count / 2;
             if (message == MSG_CONVFIRST) {
                 if (elf_entry)
                     samples = elf_entry(&adc_samples[0], halfsize);
@@ -243,7 +298,7 @@ THD_FUNCTION(conversionThread, arg)
                     samples = elf_entry(&adc_samples[halfsize], halfsize);
                 if (!samples)
                     samples = &adc_samples[halfsize];
-                std::copy(samples, samples + halfsize, &dac_samples[dac_samples.size() / 2]);
+                std::copy(samples, samples + halfsize, &dac_samples[dac_sample_count / 2]);
             } else if (message == MSG_CONVFIRST_MEASURE) {
                 chTMStartMeasurementX(&conversion_time_measurement);
                 if (elf_entry)
@@ -259,7 +314,7 @@ THD_FUNCTION(conversionThread, arg)
                 chTMStopMeasurementX(&conversion_time_measurement);
                 if (!samples)
                     samples = &adc_samples[halfsize];
-                std::copy(samples, samples + halfsize, &dac_samples[dac_samples.size() / 2]);
+                std::copy(samples, samples + halfsize, &dac_samples[dac_sample_count / 2]);
             }
         }
     }