]> code.bitgloo.com Git - clyne/stmdsp.git/commitdiff
clean up gui states
authorClyne Sullivan <clyne@bitgloo.com>
Tue, 2 Feb 2021 00:03:24 +0000 (19:03 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Tue, 2 Feb 2021 00:03:24 +0000 (19:03 -0500)
gui/stmdsp.cpp
gui/stmdsp.hpp
gui/wxmain.cpp
gui/wxmain.hpp

index 897e6434af964fa868c5173e98149a317e08bdff..1b4bba65c930a96dbf8e91aa042c291c33203e25 100644 (file)
@@ -139,13 +139,17 @@ namespace stmdsp
     }
 
     void device::siggen_start() {
-        if (connected())
+        if (connected()) {
+            m_is_siggening = true;
             m_serial.write("W");
+        }
     }
 
     void device::siggen_stop() {
-        if (connected())
+        if (connected()) {
+            m_is_siggening = false;
             m_serial.write("w");
+        }
     }
 
     void device::upload_filter(unsigned char *buffer, size_t size) {
index 9db9df6da12eb7f8a492e3f44eeba363e1eefb80..f805ab3436c6bff8b9777bf9b9ccf7c896aa5821 100644 (file)
@@ -67,6 +67,7 @@ namespace stmdsp
         void siggen_upload(dacsample_t *buffer, unsigned int size);
         void siggen_start();
         void siggen_stop();
+        bool is_siggening() const { return m_is_siggening; }
 
         // buffer is ELF binary
         void upload_filter(unsigned char *buffer, size_t size);
@@ -75,6 +76,7 @@ namespace stmdsp
     private:
         serial::Serial m_serial;
         unsigned int m_buffer_size = SAMPLES_MAX;
+        bool m_is_siggening = false;
     };
 }
 
index 6991610c224d377d2f24fc13e40f0aba52ada615..5d14928f5f92b703b619843bfdf7fb783a79be86 100644 (file)
@@ -101,7 +101,6 @@ enum Id {
     MRunUpload,
     MRunUnload,
     MRunEditBSize,
-    MRunEditSRate,
     MRunGenUpload,
     MRunGenStart,
     MCodeCompile,
@@ -110,127 +109,156 @@ enum Id {
 
 MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50), wxSize(640, 800))
 {
-    auto splitter = new wxSplitterWindow(this, wxID_ANY);
+    // Main frame structure:
+    // Begin with a main splitter for the code and terminal panes
+    auto mainSplitter = new wxSplitterWindow(this, wxID_ANY);
+    auto panelCode    = new wxPanel(mainSplitter, wxID_ANY);
+    auto panelOutput  = new wxPanel(mainSplitter, wxID_ANY);
+    // Additional panel for the toolbar
     auto panelToolbar = new wxPanel(this, wxID_ANY);
-    auto panelCode = new wxPanel(splitter, wxID_ANY);
-    auto panelOutput = new wxPanel(splitter, wxID_ANY);
+    // Sizers for the controls
     auto sizerToolbar = new wxBoxSizer(wxHORIZONTAL);
-    auto sizerCode = new wxBoxSizer(wxVERTICAL);
-    auto sizerOutput = new wxBoxSizer(wxVERTICAL);
-    auto sizerSplitter = new wxBoxSizer(wxVERTICAL);
+    auto sizerCode    = new wxBoxSizer(wxVERTICAL);
+    auto sizerOutput  = new wxBoxSizer(wxVERTICAL);
+    auto sizerMain    = new wxBoxSizer(wxVERTICAL);
+    // Menu objects
     auto menuFile = new wxMenu;
-    auto menuRun = new wxMenu;
+    auto menuRun  = new wxMenu;
     auto menuCode = new wxMenu;
 
     // Member initialization
-    m_status_bar = new wxStatusBar(this);
-    m_text_editor = new wxStyledTextCtrl(panelCode, wxID_ANY, wxDefaultPosition, wxSize(620, 440));
-    m_compile_output = new wxTextCtrl(panelOutput, wxID_ANY, wxEmptyString, wxDefaultPosition,
-                                      wxSize(620, 250), wxTE_READONLY | wxTE_MULTILINE | wxHSCROLL);
-    m_measure_timer = new wxTimer(this, Id::MeasureTimer);
-    m_menu_bar = new wxMenuBar;
+    m_status_bar     = new wxStatusBar(this);
+    m_text_editor    = new wxStyledTextCtrl(panelCode, wxID_ANY,
+                                            wxDefaultPosition, wxSize(620, 440));
+    m_compile_output = new wxTextCtrl(panelOutput, wxID_ANY,
+                                      wxEmptyString,
+                                      wxDefaultPosition, wxSize(620, 250),
+                                      wxTE_READONLY | wxTE_MULTILINE | wxHSCROLL);
+    m_measure_timer  = new wxTimer(this, Id::MeasureTimer);
+    m_menu_bar       = new wxMenuBar;
+    m_rate_select    = new wxComboBox(panelToolbar, wxID_ANY,
+                                      wxEmptyString,
+                                      wxDefaultPosition, wxDefaultSize,
+                                      srateValues.size(), srateValues.data(),
+                                      wxCB_READONLY);
 
-    m_status_bar->SetStatusText("Ready.");
-    SetStatusBar(m_status_bar);
-
-    splitter->SetSashGravity(0.5);
-    splitter->SetMinimumPaneSize(20);
+    m_menu_bar->Append(menuFile, "&File");
+    m_menu_bar->Append(menuRun, "&Run");
+    m_menu_bar->Append(menuCode, "&Code");
+    SetMenuBar(m_menu_bar);
 
+    // Toolbar initialization
     auto comp = new wxButton(panelToolbar, Id::MCodeCompile, "Compile");
-    m_rate_select = new wxComboBox(panelToolbar, wxID_ANY,
-                                   wxEmptyString, wxDefaultPosition, wxDefaultSize,
-                                   srateValues.size(), srateValues.data(), wxCB_READONLY);
-    m_rate_select->Disable();
-
     sizerToolbar->Add(comp, 0, wxLEFT, 4);
     sizerToolbar->Add(m_rate_select, 0, wxLEFT, 12);
     panelToolbar->SetSizer(sizerToolbar);
-    Bind(wxEVT_BUTTON, &MainFrame::onRunCompile, this, Id::MCodeCompile, wxID_ANY, comp);
-    Bind(wxEVT_COMBOBOX, &MainFrame::onToolbarSampleRate, this, wxID_ANY, wxID_ANY, m_rate_select);
 
+    // Code panel init.
     prepareEditor();
     sizerCode->Add(panelToolbar, 0, wxTOP | wxBOTTOM, 4);
     sizerCode->Add(m_text_editor, 1, wxEXPAND, 0);
     panelCode->SetSizer(sizerCode);
 
+    // Output panel init.
     m_compile_output->SetBackgroundColour(wxColour(0, 0, 0));
     m_compile_output->SetDefaultStyle(wxTextAttr(*wxWHITE, *wxBLACK, wxFont("Hack")));
     sizerOutput->Add(m_compile_output, 1, wxEXPAND | wxALL, 0);
     panelOutput->SetSizer(sizerOutput);
 
-    splitter->SplitHorizontally(panelCode, panelOutput, 440);
+    // Main splitter init.
+    mainSplitter->SetSashGravity(0.5);
+    mainSplitter->SetMinimumPaneSize(20);
+    mainSplitter->SplitHorizontally(panelCode, panelOutput, 440);
+    sizerMain->Add(mainSplitter, 1, wxEXPAND, 5);
+    sizerMain->SetSizeHints(this);
+    SetSizer(sizerMain);
 
-    sizerSplitter->Add(splitter, 1, wxEXPAND, 5);
-    SetSizer(sizerSplitter);
-    sizerSplitter->SetSizeHints(this);
+    m_status_bar->SetStatusText("Ready.");
+    SetStatusBar(m_status_bar);
 
-    Bind(wxEVT_TIMER, &MainFrame::onMeasureTimer, this, Id::MeasureTimer);
+    // Binds:
 
-    Bind(wxEVT_MENU, &MainFrame::onFileNew, this, Id::MFileNew, wxID_ANY,
-         menuFile->Append(MFileNew, "&New"));
-    Bind(wxEVT_MENU, &MainFrame::onFileOpen, this, Id::MFileOpen, wxID_ANY,
-         menuFile->Append(MFileOpen, "&Open"));
+    // General
+    Bind(wxEVT_TIMER,        &MainFrame::onMeasureTimer, this, Id::MeasureTimer);
+    Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent,   this, wxID_ANY);
+
+    // Toolbar actions
+    Bind(wxEVT_BUTTON,   &MainFrame::onRunCompile,        this, Id::MCodeCompile, wxID_ANY, comp);
+    Bind(wxEVT_COMBOBOX, &MainFrame::onToolbarSampleRate, this, wxID_ANY,         wxID_ANY, m_rate_select);
 
-    menuFile->Append(MFileOpenTemplate, "Open &Template", loadTemplates());
 
-    Bind(wxEVT_MENU, &MainFrame::onFileSave, this, Id::MFileSave, wxID_ANY,
-         menuFile->Append(MFileSave, "&Save"));
-    Bind(wxEVT_MENU, &MainFrame::onFileSaveAs, this, Id::MFileSaveAs, wxID_ANY,
-         menuFile->Append(MFileSaveAs, "Save &As"));
+    // File menu actions
+    Bind(wxEVT_MENU, &MainFrame::onFileNew,    this, Id::MFileNew,    wxID_ANY, menuFile->Append(MFileNew, "&New"));
+    Bind(wxEVT_MENU, &MainFrame::onFileOpen,   this, Id::MFileOpen,   wxID_ANY, menuFile->Append(MFileOpen, "&Open"));
+    menuFile->Append(MFileOpenTemplate, "Open &Template", loadTemplates());
+    Bind(wxEVT_MENU, &MainFrame::onFileSave,   this, Id::MFileSave,   wxID_ANY, menuFile->Append(MFileSave, "&Save"));
+    Bind(wxEVT_MENU, &MainFrame::onFileSaveAs, this, Id::MFileSaveAs, wxID_ANY, menuFile->Append(MFileSaveAs, "Save &As"));
     menuFile->AppendSeparator();
-    Bind(wxEVT_MENU, &MainFrame::onFileQuit, this, Id::MFileQuit, wxID_ANY,
-         menuFile->Append(MFileQuit, "&Quit"));
+    Bind(wxEVT_MENU, &MainFrame::onFileQuit,   this, Id::MFileQuit,   wxID_ANY, menuFile->Append(MFileQuit, "&Quit"));
 
-    Bind(wxEVT_MENU, &MainFrame::onRunConnect, this, Id::MRunConnect, wxID_ANY,
-         menuRun->Append(MRunConnect, "&Connect"));
+    // Run menu actions
+    Bind(wxEVT_MENU, &MainFrame::onRunConnect,    this, Id::MRunConnect,    wxID_ANY, menuRun->Append(MRunConnect, "&Connect"));
     menuRun->AppendSeparator();
-    Bind(wxEVT_MENU, &MainFrame::onRunStart, this, Id::MRunStart, wxID_ANY,
-         menuRun->Append(MRunStart, "&Start"));
+    Bind(wxEVT_MENU, &MainFrame::onRunStart,      this, Id::MRunStart,      wxID_ANY, menuRun->Append(MRunStart, "&Start"));
     m_run_measure = menuRun->AppendCheckItem(MRunMeasure, "&Measure code time");
-    Bind(wxEVT_MENU, &MainFrame::onRunLogResults, this, Id::MRunLogResults, wxID_ANY,
-         menuRun->AppendCheckItem(MRunLogResults, "&Log results..."));
+    Bind(wxEVT_MENU, &MainFrame::onRunLogResults, this, Id::MRunLogResults, wxID_ANY, menuRun->AppendCheckItem(MRunLogResults, "&Log results..."));
     menuRun->AppendSeparator();
-    Bind(wxEVT_MENU, &MainFrame::onRunUpload, this, Id::MRunUpload, wxID_ANY,
-         menuRun->Append(MRunUpload, "&Upload code"));
-    Bind(wxEVT_MENU, &MainFrame::onRunUnload, this, Id::MRunUnload, wxID_ANY,
-         menuRun->Append(MRunUnload, "U&nload code"));
-    Bind(wxEVT_MENU, &MainFrame::onRunEditBSize, this, Id::MRunEditBSize, wxID_ANY,
-         menuRun->Append(MRunEditBSize, "Set &buffer size..."));
-
+    Bind(wxEVT_MENU, &MainFrame::onRunUpload,     this, Id::MRunUpload,     wxID_ANY, menuRun->Append(MRunUpload, "&Upload code"));
+    Bind(wxEVT_MENU, &MainFrame::onRunUnload,     this, Id::MRunUnload,     wxID_ANY, menuRun->Append(MRunUnload, "U&nload code"));
+    Bind(wxEVT_MENU, &MainFrame::onRunEditBSize,  this, Id::MRunEditBSize,  wxID_ANY, menuRun->Append(MRunEditBSize, "Set &buffer size..."));
     menuRun->AppendSeparator();
-    Bind(wxEVT_MENU, &MainFrame::onRunGenUpload, this, Id::MRunGenUpload, wxID_ANY,
-         menuRun->Append(MRunGenUpload, "&Load signal generator..."));
-    Bind(wxEVT_MENU, &MainFrame::onRunGenStart, this, Id::MRunGenStart, wxID_ANY,
-         menuRun->AppendCheckItem(MRunGenStart, "Start &generator"));
+    Bind(wxEVT_MENU, &MainFrame::onRunGenUpload,  this, Id::MRunGenUpload,  wxID_ANY, menuRun->Append(MRunGenUpload, "&Load signal generator..."));
+    Bind(wxEVT_MENU, &MainFrame::onRunGenStart,   this, Id::MRunGenStart,   wxID_ANY, menuRun->AppendCheckItem(MRunGenStart, "Start &generator"));
 
-    Bind(wxEVT_MENU, &MainFrame::onRunCompile, this, Id::MCodeCompile, wxID_ANY,
-         menuCode->Append(MCodeCompile, "&Compile code"));
-    Bind(wxEVT_MENU, &MainFrame::onCodeDisassemble, this, Id::MCodeDisassemble, wxID_ANY,
-         menuCode->Append(MCodeDisassemble, "Show &Disassembly"));
+    // Code menu actions
+    Bind(wxEVT_MENU, &MainFrame::onRunCompile,      this, Id::MCodeCompile,     wxID_ANY, menuCode->Append(MCodeCompile, "&Compile code"));
+    Bind(wxEVT_MENU, &MainFrame::onCodeDisassemble, this, Id::MCodeDisassemble, wxID_ANY, menuCode->Append(MCodeDisassemble, "Show &Disassembly"));
+    menuCode->AppendSeparator();
 
-    Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent, this, wxID_ANY);
-
-    m_menu_bar->Append(menuFile, "&File");
-    m_menu_bar->Append(menuRun, "&Run");
-    m_menu_bar->Append(menuCode, "&Code");
-    SetMenuBar(m_menu_bar);
+    updateMenuOptions();
 }
 
+// Closes the window
+// Needs to clean things up
 void MainFrame::onCloseEvent(wxCloseEvent& event)
 {
-    SetMenuBar(nullptr);
-    m_menu_bar->Remove(2);
-    m_menu_bar->Remove(1);
-    m_menu_bar->Remove(0);
-    delete m_menu_bar;
-    delete m_measure_timer;
+    //SetMenuBar(nullptr);
+    //delete m_menu_bar->Remove(2);
+    //delete m_menu_bar->Remove(1);
+    //delete m_menu_bar->Remove(0);
+    //delete m_menu_bar;
+    //delete m_measure_timer;
+
+    //Unbind(wxEVT_TIMER,        &MainFrame::onMeasureTimer, this, Id::MeasureTimer);
+    //Unbind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent,   this, wxID_ANY);
+    //Unbind(wxEVT_BUTTON,   &MainFrame::onRunCompile,        this, Id::MCodeCompile, wxID_ANY);
+    //Unbind(wxEVT_COMBOBOX, &MainFrame::onToolbarSampleRate, this, wxID_ANY,         wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onFileNew,    this, Id::MFileNew,    wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onFileOpen,   this, Id::MFileOpen,   wxID_ANY);
+    ////menuFile->Append(MFileOpenTemplate, "Open &Template", loadTemplates());
+    //Unbind(wxEVT_MENU, &MainFrame::onFileSave,   this, Id::MFileSave,   wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onFileSaveAs, this, Id::MFileSaveAs, wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onFileQuit,   this, Id::MFileQuit,   wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunConnect,    this, Id::MRunConnect,    wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunStart,      this, Id::MRunStart,      wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunLogResults, this, Id::MRunLogResults, wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunUpload,     this, Id::MRunUpload,     wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunUnload,     this, Id::MRunUnload,     wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunEditBSize,  this, Id::MRunEditBSize,  wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunGenUpload,  this, Id::MRunGenUpload,  wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunGenStart,   this, Id::MRunGenStart,   wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onRunCompile,      this, Id::MCodeCompile,     wxID_ANY);
+    //Unbind(wxEVT_MENU, &MainFrame::onCodeDisassemble, this, Id::MCodeDisassemble, wxID_ANY);
 
     event.Skip();
 }
 
-void MainFrame::onMeasureTimer([[maybe_unused]] wxTimerEvent&)
+// Measure timer tick handler
+// Only called while connected and running.
+void MainFrame::onMeasureTimer(wxTimerEvent&)
 {
-    if (m_conv_result_log != nullptr) {
+    if (m_conv_result_log) {
+        // We're meant to log
         if (auto samples = m_device->continuous_read(); samples.size() > 0) {
             for (auto& s : samples) {
                 auto str = std::to_string(s);
@@ -239,7 +267,8 @@ void MainFrame::onMeasureTimer([[maybe_unused]] wxTimerEvent&)
         }
     }
 
-    if (m_wav_clip != nullptr) {
+    if (m_wav_clip) {
+        // Stream out next WAV chunk
         auto size = m_device->get_buffer_size();
         auto chunk = new stmdsp::adcsample_t[size];
         auto src = reinterpret_cast<uint16_t *>(m_wav_clip->next(size));
@@ -249,7 +278,8 @@ void MainFrame::onMeasureTimer([[maybe_unused]] wxTimerEvent&)
         delete[] chunk;
     }
 
-    if (m_status_bar && m_run_measure && m_run_measure->IsChecked()) {
+    if (m_run_measure->IsChecked()) {
+        // Show execution time
         m_status_bar->SetStatusText(wxString::Format(wxT("Execution time: %u cycles"),
                                                      m_device->continuous_start_get_measurement()));
     }
@@ -300,8 +330,8 @@ wxString MainFrame::compileEditorCode()
 
     wxFile file (m_temp_file_name, wxFile::write);
     wxString file_text (file_header);
-    file_text.Replace("$0", std::to_string(m_device != nullptr ? m_device->get_buffer_size()
-                                                               : stmdsp::SAMPLES_MAX));
+    file_text.Replace("$0", std::to_string(m_device ? m_device->get_buffer_size()
+                                                    : stmdsp::SAMPLES_MAX));
     file.Write(wxString(file_text) + m_text_editor->GetText());
     file.Close();
 
@@ -331,7 +361,7 @@ wxString MainFrame::compileEditorCode()
     }
 }
 
-void MainFrame::onFileNew([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onFileNew(wxCommandEvent&)
 {
     m_open_file_path = "";
     m_text_editor->SetText(file_content);
@@ -339,7 +369,7 @@ void MainFrame::onFileNew([[maybe_unused]] wxCommandEvent&)
     m_status_bar->SetStatusText("Ready.");
 }
 
-void MainFrame::onFileOpen([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onFileOpen(wxCommandEvent&)
 {
     wxFileDialog openDialog(this, "Open filter file", "", "",
                             "C++ source file (*.cpp)|*.cpp",
@@ -356,9 +386,15 @@ void MainFrame::onFileOpen([[maybe_unused]] wxCommandEvent&)
                 m_text_editor->DiscardEdits();
                 m_compile_output->ChangeValue("");
                 m_status_bar->SetStatusText("Ready.");
+            } else {
+                m_status_bar->SetStatusText("Failed to read file contents.");
             }
             delete[] buffer;
+        } else {
+            m_status_bar->SetStatusText("Failed to open file.");
         }
+    } else {
+        m_status_bar->SetStatusText("Ready.");
     }
 }
 
@@ -375,8 +411,12 @@ void MainFrame::onFileOpenTemplate(wxCommandEvent& event)
             m_text_editor->SetText(buffer);
             //m_text_editor->DiscardEdits();
             m_status_bar->SetStatusText("Ready.");
+        } else {
+            m_status_bar->SetStatusText("Failed to read file contents.");
         }
         delete[] buffer;
+    } else {
+        m_status_bar->SetStatusText("Ready.");
     }
 }
 
@@ -401,7 +441,7 @@ void MainFrame::onFileSave(wxCommandEvent& ce)
     }
 }
 
-void MainFrame::onFileSaveAs([[maybe_unused]] wxCommandEvent& ce)
+void MainFrame::onFileSaveAs(wxCommandEvent&)
 {
     if (m_text_editor->IsModified()) {
         wxFileDialog saveDialog(this, "Save filter file", "", "",
@@ -424,7 +464,7 @@ void MainFrame::onFileSaveAs([[maybe_unused]] wxCommandEvent& ce)
     }
 }
 
-void MainFrame::onFileQuit([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onFileQuit(wxCommandEvent&)
 {
     Close(true);
 }
@@ -433,15 +473,15 @@ void MainFrame::onRunConnect(wxCommandEvent& ce)
 {
     auto menuItem = dynamic_cast<wxMenuItem *>(ce.GetEventUserData());
 
-    if (m_device == nullptr) {
+    if (!m_device) {
         stmdsp::scanner scanner;
         if (auto devices = scanner.scan(); devices.size() > 0) {
             m_device = new stmdsp::device(devices.front());
             if (m_device->connected()) {
                 auto rate = m_device->get_sample_rate();
                 m_rate_select->SetSelection(rate);
-                m_rate_select->Enable();
 
+                updateMenuOptions();
                 menuItem->SetItemLabel("&Disconnect");
                 m_status_bar->SetStatusText("Connected.");
             } else {
@@ -457,7 +497,7 @@ void MainFrame::onRunConnect(wxCommandEvent& ce)
     } else {
         delete m_device;
         m_device = nullptr;
-        m_rate_select->Disable();
+        updateMenuOptions();
         menuItem->SetItemLabel("&Connect");
         m_status_bar->SetStatusText("Disconnected.");
     }
@@ -468,26 +508,23 @@ void MainFrame::onRunStart(wxCommandEvent& ce)
     auto menuItem = dynamic_cast<wxMenuItem *>(ce.GetEventUserData());
 
     if (!m_is_running) {
-        if (m_device != nullptr && m_device->connected()) {
-            if (m_run_measure && m_run_measure->IsChecked()) {
-                m_device->continuous_start_measure();
-                m_measure_timer->StartOnce(1000);
-            } else if (m_wav_clip != nullptr) {
-                m_device->continuous_start();
+        if (m_run_measure->IsChecked()) {
+            m_device->continuous_start_measure();
+            m_measure_timer->StartOnce(1000);
+        } else {
+            if (m_device->is_siggening() && m_wav_clip) {
                 m_measure_timer->Start(m_device->get_buffer_size() * 500 / 
                                        srateNums[m_rate_select->GetSelection()]);
-            } else {
-                m_device->continuous_start();
+            } else if (m_conv_result_log) {
                 m_measure_timer->Start(15);
             }
 
-            menuItem->SetItemLabel("&Stop");
-            m_status_bar->SetStatusText("Running.");
-            m_is_running = true;
-        } else {
-            wxMessageBox("No device connected!", "Run", wxICON_WARNING);
-            m_status_bar->SetStatusText("Please connect.");
+            m_device->continuous_start();
         }
+
+        menuItem->SetItemLabel("&Stop");
+        m_status_bar->SetStatusText("Running.");
+        m_is_running = true;
     } else {
         m_device->continuous_stop();
         m_measure_timer->Stop();
@@ -506,7 +543,7 @@ void MainFrame::onRunLogResults(wxCommandEvent& ce)
                             wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
 
         if (dialog.ShowModal() != wxID_CANCEL) {
-            if (m_conv_result_log != nullptr) {
+            if (m_conv_result_log) {
                 m_conv_result_log->Close();
                 delete m_conv_result_log;
                 m_conv_result_log = nullptr;
@@ -516,174 +553,151 @@ void MainFrame::onRunLogResults(wxCommandEvent& ce)
         }
 
         m_status_bar->SetStatusText("Ready.");
-    } else if (m_conv_result_log != nullptr) {
+    } else if (m_conv_result_log) {
         m_conv_result_log->Close();
         delete m_conv_result_log;
         m_conv_result_log = nullptr;
     }
 }
 
-void MainFrame::onRunEditBSize([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onRunEditBSize(wxCommandEvent&)
 {
-    if (m_device != nullptr && m_device->connected()) {
-        wxTextEntryDialog dialog (this, "Enter new buffer size (100-3000)", "Set Buffer Size");
-        if (dialog.ShowModal() == wxID_OK) {
-            if (wxString value = dialog.GetValue(); !value.IsEmpty()) {
-                if (unsigned long n; value.ToULong(&n)) {
-                    if (n >= 100 && n <= stmdsp::SAMPLES_MAX) {
-                        m_device->continuous_set_buffer_size(n);
-                    } else {
-                        m_status_bar->SetStatusText("Error: Invalid buffer size.");
-                    }
+    wxTextEntryDialog dialog (this, "Enter new buffer size (100-3000)", "Set Buffer Size");
+    if (dialog.ShowModal() == wxID_OK) {
+        if (wxString value = dialog.GetValue(); !value.IsEmpty()) {
+            if (unsigned long n; value.ToULong(&n)) {
+                if (n >= 100 && n <= stmdsp::SAMPLES_MAX) {
+                    m_device->continuous_set_buffer_size(n);
                 } else {
                     m_status_bar->SetStatusText("Error: Invalid buffer size.");
                 }
             } else {
-                m_status_bar->SetStatusText("Ready.");
+                m_status_bar->SetStatusText("Error: Invalid buffer size.");
             }
         } else {
             m_status_bar->SetStatusText("Ready.");
         }
     } else {
-        wxMessageBox("No device connected!", "Run", wxICON_WARNING);
-        m_status_bar->SetStatusText("Please connect.");
+        m_status_bar->SetStatusText("Ready.");
     }
 }
 
 void MainFrame::onToolbarSampleRate(wxCommandEvent& ce)
 {
-    if (m_device != nullptr && m_device->connected()) {
-        auto combo = dynamic_cast<wxComboBox *>(ce.GetEventUserData());
-        m_device->set_sample_rate(combo->GetCurrentSelection());
-        m_status_bar->SetStatusText("Ready.");
-    } else {
-        wxMessageBox("No device connected!", "Run", wxICON_WARNING);
-        m_status_bar->SetStatusText("Please connect.");
-    }
+    auto combo = dynamic_cast<wxComboBox *>(ce.GetEventUserData());
+    m_device->set_sample_rate(combo->GetCurrentSelection());
+    m_status_bar->SetStatusText("Ready.");
 }
 
-void MainFrame::onRunGenUpload([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onRunGenUpload(wxCommandEvent&)
 {
-    if (m_device != nullptr && m_device->connected()) {
-        wxTextEntryDialog dialog (this, "Enter generator values below. Values must be whole numbers "
-                                        "between zero and 4095.", "Enter Generator Values");
-        if (dialog.ShowModal() == wxID_OK) {
-            if (wxString values = dialog.GetValue(); !values.IsEmpty()) {
-                if (values[0] == '/') {
-                    m_wav_clip = new wav::clip(values.Mid(1));
-                    if (m_wav_clip->valid()) {
-                        m_status_bar->SetStatusText("Generator ready.");
-                    } else {
-                        delete m_wav_clip;
-                        m_wav_clip = nullptr;
-                        m_status_bar->SetStatusText("Error: Bad WAV file.");
-                    }
+    wxTextEntryDialog dialog (this, "Enter generator values below. Values must be whole numbers "
+                                    "between zero and 4095.", "Enter Generator Values");
+    if (dialog.ShowModal() == wxID_OK) {
+        if (wxString values = dialog.GetValue(); !values.IsEmpty()) {
+            if (values[0] == '/') {
+                m_wav_clip = new wav::clip(values.Mid(1));
+                if (m_wav_clip->valid()) {
+                    m_status_bar->SetStatusText("Generator ready.");
                 } else {
-                    std::vector<stmdsp::dacsample_t> samples;
-                    while (!values.IsEmpty()) {
-                        if (auto number_end = values.find_first_not_of("0123456789");
-                            number_end != wxString::npos && number_end > 0)
+                    delete m_wav_clip;
+                    m_wav_clip = nullptr;
+                    m_status_bar->SetStatusText("Error: Bad WAV file.");
+                }
+            } else {
+                std::vector<stmdsp::dacsample_t> samples;
+                while (!values.IsEmpty()) {
+                    if (auto number_end = values.find_first_not_of("0123456789");
+                        number_end != wxString::npos && number_end > 0)
+                    {
+                        auto number = values.Left(number_end);
+                        if (unsigned long n; number.ToULong(&n))
+                            samples.push_back(n & 4095);
+
+                        if (auto next = values.find_first_of("0123456789", number_end + 1);
+                            next != wxString::npos)
                         {
-                            auto number = values.Left(number_end);
-                            if (unsigned long n; number.ToULong(&n))
-                                samples.push_back(n & 4095);
-
-                            if (auto next = values.find_first_of("0123456789", number_end + 1);
-                                next != wxString::npos)
-                            {
-                                values = values.Mid(next);
-                            } else {
-                                break;
-                            }
+                            values = values.Mid(next);
                         } else {
                             break;
                         }
-                    }
-
-                    if (samples.size() <= stmdsp::SAMPLES_MAX) {
-                        m_device->siggen_upload(&samples[0], samples.size());
-                        m_status_bar->SetStatusText("Generator ready.");
                     } else {
-                        m_status_bar->SetStatusText("Error: Too many samples.");
+                        break;
                     }
                 }
-            } else {
-                m_status_bar->SetStatusText("Error: No samples given.");
+
+                if (samples.size() <= stmdsp::SAMPLES_MAX) {
+                    m_device->siggen_upload(&samples[0], samples.size());
+                    m_status_bar->SetStatusText("Generator ready.");
+                } else {
+                    m_status_bar->SetStatusText("Error: Too many samples.");
+                }
             }
         } else {
-            m_status_bar->SetStatusText("Ready.");
+            m_status_bar->SetStatusText("Error: No samples given.");
         }
     } else {
-        wxMessageBox("No device connected!", "Run", wxICON_WARNING);
-        m_status_bar->SetStatusText("Please connect.");
+        m_status_bar->SetStatusText("Ready.");
     }
 }
 
 void MainFrame::onRunGenStart(wxCommandEvent& ce)
 {
     auto menuItem = dynamic_cast<wxMenuItem *>(ce.GetEventUserData());
-    if (m_device != nullptr && m_device->connected()) {
-        if (menuItem->IsChecked()) {
-            m_device->siggen_start();
-            menuItem->SetItemLabel("Stop &generator");
-        } else {
-            m_device->siggen_stop();
-            menuItem->SetItemLabel("Start &generator");
-        }
+    if (menuItem->IsChecked()) {
+        m_device->siggen_start();
+        menuItem->SetItemLabel("Stop &generator");
     } else {
-        wxMessageBox("No device connected!", "Run", wxICON_WARNING);
-        m_status_bar->SetStatusText("Please connect.");
+        m_device->siggen_stop();
+        menuItem->SetItemLabel("Start &generator");
     }
 }
 
-void MainFrame::onRunUpload([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onRunUpload(wxCommandEvent&)
 {
     if (auto file = compileEditorCode(); !file.IsEmpty()) {
         if (wxFileInputStream file_stream (file); file_stream.IsOk()) {
             auto size = file_stream.GetSize();
             auto buffer = new unsigned char[size];
-            if (m_device != nullptr && m_device->connected()) {
-                file_stream.ReadAll(buffer, size);
-                m_device->upload_filter(buffer, size);
-                m_status_bar->SetStatusText("Code uploaded.");
-            } else {
-                wxMessageBox("No device connected!", "Run", wxICON_WARNING);
-                m_status_bar->SetStatusText("Please connect.");
-            }
+            file_stream.ReadAll(buffer, size);
+            m_device->upload_filter(buffer, size);
+            m_status_bar->SetStatusText("Code uploaded.");
         } else {
              m_status_bar->SetStatusText("Couldn't load compiled code.");
         }
     }
 }
 
-void MainFrame::onRunUnload([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onRunUnload(wxCommandEvent&)
 {
-    if (m_device != nullptr && m_device->connected()) {
-        m_device->unload_filter();
-        m_status_bar->SetStatusText("Unloaded code.");
-    } else {
-        m_status_bar->SetStatusText("No device connected.");
-    }
+    m_device->unload_filter();
+    m_status_bar->SetStatusText("Unloaded code.");
 }
 
-void MainFrame::onRunCompile([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onRunCompile(wxCommandEvent&)
 {
     compileEditorCode();
 }
 
-void MainFrame::onCodeDisassemble([[maybe_unused]] wxCommandEvent&)
+void MainFrame::onCodeDisassemble(wxCommandEvent&)
 {
-    auto output = m_temp_file_name + ".asm.log";
-    wxString command = wxString("arm-none-eabi-objdump -d --no-show-raw-insn ") + m_temp_file_name + ".orig.o"
-                                " > " + output + " 2>&1";
-
-    if (system(command.ToAscii()) == 0) {
-        m_compile_output->LoadFile(output);
-        m_status_bar->SetStatusText(wxString::Format(wxT("Done. Line count: %u."),
-                                                         m_compile_output->GetNumberOfLines()));
+    if (!m_temp_file_name.IsEmpty()) {
+        auto output = m_temp_file_name + ".asm.log";
+        wxString command = wxString("arm-none-eabi-objdump -d --no-show-raw-insn ") +
+                                    m_temp_file_name + ".orig.o" // +
+                                    " > " + output + " 2>&1";
+    
+        if (system(command.ToAscii()) == 0) {
+            m_compile_output->LoadFile(output);
+            m_status_bar->SetStatusText(wxString::Format(wxT("Done. Line count: %u."),
+                                                             m_compile_output->GetNumberOfLines()));
+        } else {
+            m_compile_output->ChangeValue("");
+            m_status_bar->SetStatusText("Failed to load disassembly.");
+        }
     } else {
         m_compile_output->ChangeValue("");
-        m_status_bar->SetStatusText("Failed to load disassembly (code compiled?).");
+        m_status_bar->SetStatusText("Need to compile code before analyzing.");
     }
 }
 
@@ -705,3 +719,15 @@ wxMenu *MainFrame::loadTemplates()
     return menu;
 }
 
+void MainFrame::updateMenuOptions()
+{
+    bool connected = m_device != nullptr;
+    m_menu_bar->Enable(MRunStart, connected);
+    m_menu_bar->Enable(MRunUpload, connected);
+    m_menu_bar->Enable(MRunUnload, connected);
+    m_menu_bar->Enable(MRunEditBSize, connected);
+    m_menu_bar->Enable(MRunGenUpload, connected);
+    m_menu_bar->Enable(MRunGenStart, connected);
+    m_rate_select->Enable(connected);
+}
+
index 8068784ac12bd5053c313fac9caf1b68e09526dd..e96f51d3b5cb8319cb3d644eadbc128bd72b0e6b 100644 (file)
@@ -61,7 +61,9 @@ public:
     void onMeasureTimer(wxTimerEvent& te);
 
 private:
+    // Set to true if connected and running
     bool m_is_running = false;
+
     wxComboBox *m_device_combo = nullptr;
     wxStyledTextCtrl *m_text_editor = nullptr;
     wxTextCtrl *m_compile_output = nullptr;
@@ -71,17 +73,30 @@ private:
     wxStatusBar *m_status_bar = nullptr;
     wxMenuBar *m_menu_bar = nullptr;
     wxComboBox *m_rate_select = nullptr;
+
+    // File handle for logging output samples
+    // Not null when logging is enabled
     wxFileOutputStream *m_conv_result_log = nullptr;
+    // File path of currently opened file
+    // Empty if new file
     wxString m_open_file_path;
+    // File path for temporary files (e.g. compiled ELF)
+    // Set by compile action
     wxString m_temp_file_name;
 
+    // Device interface
+    // Not null if connected
     stmdsp::device *m_device = nullptr;
+    // WAV data for signal generator
+    // Not null when a WAV is loaded
     wav::clip *m_wav_clip = nullptr;
 
     bool tryDevice();
     void prepareEditor();
     wxString compileEditorCode();
     wxMenu *loadTemplates();
+    // Updates control availabilities based on device connection
+    void updateMenuOptions();
 };
 
 #endif // WXMAIN_HPP_