aboutsummaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/Makefile17
-rw-r--r--gui/stmdsp.cpp27
-rw-r--r--gui/stmdsp.hpp3
-rw-r--r--gui/wxmain.cpp91
-rw-r--r--gui/wxmain.hpp6
5 files changed, 128 insertions, 16 deletions
diff --git a/gui/Makefile b/gui/Makefile
index 679e1e4..20dd473 100644
--- a/gui/Makefile
+++ b/gui/Makefile
@@ -1,18 +1,21 @@
CXX = g++-10
-CXXFLAGS = --std=c++20 -ggdb -Og \
- -Wall -Wextra -pedantic \
- -Wno-deprecated-copy \
- -Iserial/include \
- $(shell wx-config --cxxflags)
+CXXFLAGS = --std=c++20 -ggdb -O0 \
+ -Wall -Wextra -pedantic \
+ -Wno-deprecated-copy \
+ -Iserial/include \
+ $(shell wx-config --cxxflags)
-CXXFILES = $(shell find serial/src -name "*.cc") $(wildcard *.cpp)
+CXXFILES = serial/src/serial.cc \
+ serial/src/impl/unix.cc \
+ serial/src/impl/list_ports/list_ports_linux.cc \
+ $(wildcard *.cpp)
OFILES = $(patsubst %.cc, %.o, $(patsubst %.cpp, %.o, $(CXXFILES)))
LIBS = $(shell wx-config --libs) -lwx_gtk3u_stc-3.1
OUTELF = stmdspgui
all: $(OUTELF)
-
+
$(OUTELF): $(OFILES)
@echo " CXX " $(OUTELF)
@$(CXX) $(CXXFLAGS) $(OFILES) $(LIBS) -o $(OUTELF)
diff --git a/gui/stmdsp.cpp b/gui/stmdsp.cpp
index 1b4bba6..5ea18af 100644
--- a/gui/stmdsp.cpp
+++ b/gui/stmdsp.cpp
@@ -120,6 +120,33 @@ namespace stmdsp
return {};
}
+ std::vector<adcsample_t> device::continuous_read_input() {
+ if (connected()) {
+ m_serial.write("t");
+ unsigned char sizebytes[2];
+ m_serial.read(sizebytes, 2);
+ unsigned int size = sizebytes[0] | (sizebytes[1] << 8);
+ if (size > 0) {
+ std::vector<adcsample_t> data (size);
+ unsigned int total = size * sizeof(adcsample_t);
+ unsigned int offset = 0;
+
+ while (total > 512) {
+ m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, 512);
+ m_serial.write("n");
+ offset += 512;
+ total -= 512;
+ }
+ m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, total);
+ m_serial.write("n");
+ return data;
+
+ }
+ }
+
+ return {};
+ }
+
void device::continuous_stop() {
if (connected())
m_serial.write("S");
diff --git a/gui/stmdsp.hpp b/gui/stmdsp.hpp
index f805ab3..a22a55d 100644
--- a/gui/stmdsp.hpp
+++ b/gui/stmdsp.hpp
@@ -19,7 +19,7 @@
namespace stmdsp
{
- constexpr unsigned int SAMPLES_MAX = 4000;
+ constexpr unsigned int SAMPLES_MAX = 4096;
class scanner
{
@@ -62,6 +62,7 @@ namespace stmdsp
void continuous_start_measure();
uint32_t continuous_start_get_measurement();
std::vector<adcsample_t> continuous_read();
+ std::vector<adcsample_t> continuous_read_input();
void continuous_stop();
void siggen_upload(dacsample_t *buffer, unsigned int size);
diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp
index c7acddf..e5f0d4d 100644
--- a/gui/wxmain.cpp
+++ b/gui/wxmain.cpp
@@ -12,6 +12,7 @@
#include "wxmain.hpp"
#include <wx/combobox.h>
+#include <wx/dcclient.h>
#include <wx/dir.h>
#include <wx/filename.h>
#include <wx/filedlg.h>
@@ -25,6 +26,7 @@
#include <wx/textdlg.h>
#include <array>
+#include <sys/mman.h>
#include <vector>
static const std::array<wxString, 6> srateValues {
@@ -133,6 +135,7 @@ enum Id {
MRunConnect,
MRunStart,
MRunMeasure,
+ MRunDrawSamples,
MRunLogResults,
MRunUpload,
MRunUnload,
@@ -177,6 +180,12 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
wxDefaultPosition, wxDefaultSize,
srateValues.size(), srateValues.data(),
wxCB_READONLY);
+ m_device_samples = reinterpret_cast<stmdsp::adcsample_t *>(::mmap(
+ nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t),
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
+ m_device_samples_input = reinterpret_cast<stmdsp::adcsample_t *>(::mmap(
+ nullptr, stmdsp::SAMPLES_MAX * sizeof(stmdsp::adcsample_t),
+ PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0));
m_menu_bar->Append(menuFile, "&File");
m_menu_bar->Append(menuRun, "&Run");
@@ -217,6 +226,7 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
// General
Bind(wxEVT_TIMER, &MainFrame::onMeasureTimer, this, Id::MeasureTimer);
Bind(wxEVT_CLOSE_WINDOW, &MainFrame::onCloseEvent, this, wxID_ANY);
+ Bind(wxEVT_PAINT, &MainFrame::onPaint, this, wxID_ANY);
// Toolbar actions
Bind(wxEVT_BUTTON, &MainFrame::onRunCompile, this, Id::MCodeCompile, wxID_ANY, comp);
@@ -237,6 +247,7 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
menuRun->AppendSeparator();
Bind(wxEVT_MENU, &MainFrame::onRunStart, this, Id::MRunStart, wxID_ANY, menuRun->Append(MRunStart, "&Start"));
m_run_measure = menuRun->AppendCheckItem(MRunMeasure, "&Measure code time");
+ m_run_draw_samples = menuRun->AppendCheckItem(MRunDrawSamples, "&Draw samples");
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"));
@@ -276,12 +287,21 @@ void MainFrame::onCloseEvent(wxCloseEvent& event)
// Only called while connected and running.
void MainFrame::onMeasureTimer(wxTimerEvent&)
{
- 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);
- m_conv_result_log->Write(str.c_str(), str.size());
+ if (m_conv_result_log || m_run_draw_samples->IsChecked()) {
+ auto samples = m_device->continuous_read();
+ if (samples.size() > 0) {
+ std::copy(samples.cbegin(), samples.cend(), m_device_samples);
+
+ if (m_conv_result_log) {
+ for (auto& s : samples) {
+ auto str = std::to_string(s);
+ m_conv_result_log->Write(str.c_str(), str.size());
+ }
+ }
+ if (m_run_draw_samples->IsChecked()) {
+ samples = m_device->continuous_read_input();
+ std::copy(samples.cbegin(), samples.cend(), m_device_samples_input);
+ this->Refresh();
}
}
}
@@ -304,6 +324,54 @@ void MainFrame::onMeasureTimer(wxTimerEvent&)
}
}
+void MainFrame::onPaint(wxPaintEvent&)
+{
+ if (!m_is_running || !m_run_draw_samples->IsChecked()) {
+ if (!m_compile_output->IsShown())
+ m_compile_output->Show();
+ return;
+ } else if (m_compile_output->IsShown()) {
+ m_compile_output->Hide();
+ }
+
+ auto py = m_compile_output->GetScreenPosition().y - this->GetScreenPosition().y - 28;
+ wxRect rect {
+ 0, py,
+ this->GetSize().GetWidth(),
+ this->GetSize().GetHeight() - py - 60
+ };
+
+ auto *dc = new wxPaintDC(this);
+ dc->SetBrush(*wxBLACK_BRUSH);
+ dc->SetPen(*wxBLACK_PEN);
+ dc->DrawRectangle(rect);
+ dc->SetBrush(*wxRED_BRUSH);
+ dc->SetPen(*wxRED_PEN);
+ auto stoy = [&](stmdsp::adcsample_t s) {
+ return static_cast<float>(py) + rect.GetHeight() -
+ (static_cast<float>(rect.GetHeight()) * s / 4095.f);
+ };
+ auto scount = m_device->get_buffer_size();
+ float dx = static_cast<float>(rect.GetWidth()) / scount;
+ float x = 0;
+ float lasty = stoy(2048);
+ for (decltype(scount) i = 0; i < scount; i++) {
+ auto y = stoy(m_device_samples[i]);
+ dc->DrawLine(x, lasty, x + dx, y);
+ x += dx, lasty = y;
+ }
+ dc->SetBrush(*wxBLUE_BRUSH);
+ dc->SetPen(*wxBLUE_PEN);
+ x = 0;
+ lasty = stoy(2048);
+ for (decltype(scount) i = 0; i < scount; i++) {
+ auto y = stoy(m_device_samples_input[i]);
+ dc->DrawLine(x, lasty, x + dx, y);
+ x += dx, lasty = y;
+ }
+ delete dc;
+}
+
void MainFrame::prepareEditor()
{
m_text_editor->SetLexer(wxSTC_LEX_CPP);
@@ -536,11 +604,14 @@ void MainFrame::onRunStart(wxCommandEvent& ce)
srateNums[m_rate_select->GetSelection()]);
} else if (m_conv_result_log) {
m_measure_timer->Start(15);
+ } else if (m_run_draw_samples->IsChecked()) {
+ m_measure_timer->Start(300);
}
m_device->continuous_start();
}
+ m_rate_select->Enable(false);
menuItem->SetItemLabel("&Stop");
m_status_bar->SetStatusText("Running.");
m_is_running = true;
@@ -548,9 +619,13 @@ void MainFrame::onRunStart(wxCommandEvent& ce)
m_device->continuous_stop();
m_measure_timer->Stop();
+ m_rate_select->Enable(true);
menuItem->SetItemLabel("&Start");
m_status_bar->SetStatusText("Ready.");
m_is_running = false;
+
+ if (m_run_draw_samples->IsChecked())
+ m_compile_output->Refresh();
}
}
@@ -581,7 +656,7 @@ void MainFrame::onRunLogResults(wxCommandEvent& ce)
void MainFrame::onRunEditBSize(wxCommandEvent&)
{
- wxTextEntryDialog dialog (this, "Enter new buffer size (100-4000)", "Set Buffer Size");
+ wxTextEntryDialog dialog (this, "Enter new buffer size (100-4096)", "Set Buffer Size");
if (dialog.ShowModal() == wxID_OK) {
if (wxString value = dialog.GetValue(); !value.IsEmpty()) {
if (unsigned long n; value.ToULong(&n)) {
@@ -667,9 +742,11 @@ void MainFrame::onRunGenStart(wxCommandEvent& ce)
if (menuItem->IsChecked()) {
m_device->siggen_start();
menuItem->SetItemLabel("Stop &generator");
+ m_status_bar->SetStatusText("Generator running.");
} else {
m_device->siggen_stop();
menuItem->SetItemLabel("Start &generator");
+ m_status_bar->SetStatusText("Ready.");
}
}
diff --git a/gui/wxmain.hpp b/gui/wxmain.hpp
index e96f51d..9b3db1e 100644
--- a/gui/wxmain.hpp
+++ b/gui/wxmain.hpp
@@ -58,7 +58,8 @@ public:
void onRunCompile(wxCommandEvent&);
void onCodeDisassemble(wxCommandEvent&);
- void onMeasureTimer(wxTimerEvent& te);
+ void onPaint(wxPaintEvent&);
+ void onMeasureTimer(wxTimerEvent&);
private:
// Set to true if connected and running
@@ -69,6 +70,7 @@ private:
wxTextCtrl *m_compile_output = nullptr;
wxControl *m_signal_area = nullptr;
wxMenuItem *m_run_measure = nullptr;
+ wxMenuItem *m_run_draw_samples = nullptr;
wxTimer *m_measure_timer = nullptr;
wxStatusBar *m_status_bar = nullptr;
wxMenuBar *m_menu_bar = nullptr;
@@ -87,6 +89,8 @@ private:
// Device interface
// Not null if connected
stmdsp::device *m_device = nullptr;
+ stmdsp::adcsample_t *m_device_samples = nullptr;
+ stmdsp::adcsample_t *m_device_samples_input = nullptr;
// WAV data for signal generator
// Not null when a WAV is loaded
wav::clip *m_wav_clip = nullptr;