diff options
author | clyne <clyne@bitgloo.com> | 2020-07-16 20:21:36 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-16 20:21:36 -0400 |
commit | 17cda07f3ef79069e9bed2eca6c20f2b7fcb60b9 (patch) | |
tree | 7e787e1b24100d539631a04993e1d6b53ac31f72 /gui | |
parent | 43c53c1122c64da20bbc6f54d2a087f5a457f669 (diff) | |
parent | f07e878cd23e6e35743358ea306951f2218653a4 (diff) |
Merge pull request #1 from tcsullivan/gui
Gui
Diffstat (limited to 'gui')
-rw-r--r-- | gui/Makefile | 30 | ||||
-rw-r--r-- | gui/main.cpp | 15 | ||||
m--------- | gui/serial | 0 | ||||
-rw-r--r-- | gui/stmdsp.cpp | 48 | ||||
-rw-r--r-- | gui/stmdsp.hpp | 69 | ||||
-rw-r--r-- | gui/wxapp.hpp | 20 | ||||
-rw-r--r-- | gui/wxmain.hpp | 119 |
7 files changed, 221 insertions, 80 deletions
diff --git a/gui/Makefile b/gui/Makefile index 419ed33..99a0243 100644 --- a/gui/Makefile +++ b/gui/Makefile @@ -1,15 +1,31 @@ -CXX = clang++-10 -CXXFLAGS = --std=c++20 -Wall -Wextra -pedantic +CXX = g++-10 +CXXFLAGS = --std=c++20 -ggdb -Og \ + -Wall -Wextra -pedantic \ + -Wno-deprecated-copy \ + -Iserial/include \ + $(shell wx-config --cxxflags) -CXXFILES = $(wildcard *.cpp) +CXXFILES = $(shell find serial/src -name "*.cc") $(wildcard *.cpp) +OFILES = $(patsubst %.cc, %.o, $(patsubst %.cpp, %.o, $(CXXFILES))) +LIBS = $(shell wx-config --libs) OUTELF = stmdspgui -all: $(CXXFILES) - @echo " CXX " $(CXXFILES) - @$(CXX) $(CXXFLAGS) $(CXXFILES) -o $(OUTELF) +all: $(OUTELF) + +$(OUTELF): $(OFILES) + @echo " CXX " $(OUTELF) + @$(CXX) $(CXXFLAGS) $(OFILES) $(LIBS) -o $(OUTELF) + +.cc.o: + @echo " CXX " $< + @$(CXX) $(CXXFLAGS) -c $< -o $@ + +.cpp.o: + @echo " CXX " $< + @$(CXX) $(CXXFLAGS) -c $< -o $@ clean: @echo " CLEAN" - @rm -f $(OUTELF) + @rm -f $(OUTELF) $(OFILES) diff --git a/gui/main.cpp b/gui/main.cpp index 48f2990..29f74d3 100644 --- a/gui/main.cpp +++ b/gui/main.cpp @@ -1,15 +1,6 @@ -#include "stmdsp.hpp" +#include "wxapp.hpp" -#include <iostream> +#include <wx/app.h> -int main() -{ - stmdsp::scanner scanner; - - scanner.scan(); - for (const auto& device : scanner.devices()) - std::cout << "Found stmdsp at: " << device.path() << std::endl; - - return 0; -} +wxIMPLEMENT_APP(MainApp); diff --git a/gui/serial b/gui/serial new file mode 160000 +Subproject cbcca7c83745fedd75afb7a0a27ee5c4112435c diff --git a/gui/stmdsp.cpp b/gui/stmdsp.cpp index 267bebc..837d09c 100644 --- a/gui/stmdsp.cpp +++ b/gui/stmdsp.cpp @@ -1,31 +1,37 @@ #include "stmdsp.hpp" -#include <chrono> -#include <filesystem> -#include <thread> - -using namespace std::chrono_literals; +#include <serial/serial.h> namespace stmdsp { - void scanner::scan() + std::list<std::string>& scanner::scan() { - std::string path ("/dev/ttyACM0"); + auto devices = serial::list_ports(); + for (auto& device : devices) { + if (device.hardware_id.find(STMDSP_USB_ID) != std::string::npos) + m_available_devices.emplace_front(device.port); + } + + return m_available_devices; + } + + device::device(const std::string& file) : + m_serial(file, 230400, serial::Timeout::simpleTimeout(50)) {} - for (unsigned int i = 0; i < 10; i++) { - path.back() = '0' + i; - if (std::filesystem::exists(path)) { - if (device dev (path); dev.open()) { - dev.write("i", 1); - std::this_thread::sleep_for(1s); - char buf[7]; - if (dev.read(buf, 6) == 6) { - buf[6] = '\0'; - if (std::string(buf) == "stmdsp") - m_devices.emplace(std::move(dev)); - } - } - } + std::vector<adcsample_t> device::sample(unsigned long int count) { + if (connected()) { + uint8_t request[3] = { + 'r', + static_cast<uint8_t>(count), + static_cast<uint8_t>(count >> 8) + }; + m_serial.write(request, 3); + std::vector<adcsample_t> data (count); + m_serial.read(reinterpret_cast<uint8_t *>(data.data()), + data.size() * sizeof(adcsample_t)); + return data; + } else { + return {}; } } } diff --git a/gui/stmdsp.hpp b/gui/stmdsp.hpp index 12e4578..2148fa1 100644 --- a/gui/stmdsp.hpp +++ b/gui/stmdsp.hpp @@ -1,60 +1,49 @@ -#ifndef STMDSPSCANNER_H -#define STMDSPSCANNER_H +#ifndef STMDSP_HPP_ +#define STMDSP_HPP_ -#include <fstream> -#include <set> +#include <cstdint> +#include <list> +#include <serial/serial.h> #include <string> namespace stmdsp { - class device + class scanner { - public: - device(const std::string& path) : - m_path(path) {} - - bool open() { - m_stream.open(m_path, std::ios_base::in | std::ios_base::out | std::ios_base::binary); - return m_stream.is_open(); - } - - std::size_t read(char *buffer, std::size_t count) { - return m_stream.readsome(buffer, count); - } - - std::size_t write(const char *buffer, std::size_t count) { - m_stream.write(buffer, count); - return m_stream.good() ? count : 0; - } - - const std::string& path() const { - return m_path; - } + private: + constexpr static const char *STMDSP_USB_ID = "USB VID:PID=0483:5740"; - auto operator<=>(const device& other) const { - return m_path <=> other.m_path; + public: + std::list<std::string>& scan(); + auto& devices() { + return m_available_devices; } private: - std::string m_path; - std::fstream m_stream; + std::list<std::string> m_available_devices; }; - class scanner - { - private: - constexpr static unsigned int STMDSP_VENDOR_ID = 0x0483; - constexpr static unsigned int STMDSP_DEVICE_ID = 0x5740; + using adcsample_t = uint16_t; + class device + { public: - void scan(); - const auto& devices() const { - return m_devices; + device(const std::string& file); + + ~device() { + m_serial.close(); + } + + bool connected() { + return m_serial.isOpen() && (m_serial.write("i"), m_serial.read(6) == "stmdsp"); } + std::vector<adcsample_t> sample(unsigned long int count = 1); + private: - std::set<device> m_devices; + serial::Serial m_serial; }; } -#endif // STMDSPSCANNER_H +#endif // STMDSP_HPP_ + diff --git a/gui/wxapp.hpp b/gui/wxapp.hpp new file mode 100644 index 0000000..6536554 --- /dev/null +++ b/gui/wxapp.hpp @@ -0,0 +1,20 @@ +#ifndef WXAPP_HPP_ +#define WXAPP_HPP_ + +#include "wxmain.hpp" + +#include <wx/app.h> + +class MainApp : public wxApp +{ +public: + virtual bool OnInit() final { + auto mainFrame = new MainFrame; + mainFrame->Show(true); + SetTopWindow(mainFrame); + return true; + } +}; + +#endif // WXAPP_HPP_ + diff --git a/gui/wxmain.hpp b/gui/wxmain.hpp new file mode 100644 index 0000000..97baae3 --- /dev/null +++ b/gui/wxmain.hpp @@ -0,0 +1,119 @@ +#ifndef WXMAIN_HPP_ +#define WXMAIN_HPP_ + +#include "stmdsp.hpp" + +#include <future> +#include <thread> +#include <wx/button.h> +#include <wx/combobox.h> +#include <wx/dcclient.h> +#include <wx/frame.h> +#include <wx/stattext.h> +#include <wx/timer.h> + +class MainFrame : public wxFrame +{ + enum Id { + Welcome = 1, + Single, + SelectDevice, + RenderTimer + }; + + bool m_is_rendering = false; + wxTimer *m_render_timer = nullptr; + wxComboBox *m_device_combo = nullptr; + + const wxRect m_clipping_region = {20, 100, 600, 360}; + + stmdsp::device *m_device = nullptr; + std::future<std::vector<stmdsp::adcsample_t>> m_device_samples_future; + std::vector<stmdsp::adcsample_t> m_device_samples; + +public: + MainFrame() : wxFrame(nullptr, -1, "Hello world", wxPoint(50, 50), wxSize(640, 480)) + { + new wxStaticText(this, Id::Welcome, "Welcome to the GUI.", wxPoint(20, 20)); + new wxButton(this, Id::Single, "Single", wxPoint(20, 60)); + m_device_combo = new wxComboBox(this, Id::SelectDevice, "", wxPoint(470, 20), wxSize(150, 30)); + m_device_combo->SetEditable(false); + stmdsp::scanner scanner; + for (auto& dev : scanner.scan()) + m_device_combo->Append(dev); + if (m_device_combo->GetCount() > 0) + m_device_combo->SetSelection(0); + + m_render_timer = new wxTimer(this, Id::RenderTimer); + + Bind(wxEVT_BUTTON, &MainFrame::onSinglePressed, this, Id::Single); + Bind(wxEVT_PAINT, &MainFrame::onPaint, this, wxID_ANY); + Bind(wxEVT_TIMER, &MainFrame::onRenderTimer, this, Id::RenderTimer); + } + + void onPaint([[maybe_unused]] wxPaintEvent& pe) { + auto *dc = new wxClientDC(this); + dc->SetClippingRegion(m_clipping_region); + + dc->SetBrush(*wxBLACK_BRUSH); + dc->SetPen(*wxBLACK_PEN); + dc->DrawRectangle(m_clipping_region); + + if (m_device_samples.size() > 0) { + dc->SetPen(*wxRED_PEN); + auto points = new wxPoint[m_device_samples.size()]; + const float spacing = static_cast<float>(m_clipping_region.GetWidth()) / m_device_samples.size(); + float x = 0; + for (auto ptr = points; auto sample : m_device_samples) { + *ptr++ = wxPoint { + static_cast<int>(x), + m_clipping_region.GetHeight() - sample * m_clipping_region.GetHeight() / 4096 + }; + x += spacing; + } + dc->DrawLines(m_device_samples.size(), points, m_clipping_region.GetX(), m_clipping_region.GetY()); + delete[] points; + } + } + + void doSingle() { + m_device_samples_future = std::async(std::launch::async, + [this]() { return m_device->sample(250); }); + } + + void onSinglePressed(wxCommandEvent& ce) { + auto button = dynamic_cast<wxButton *>(ce.GetEventObject()); + + if (!m_render_timer->IsRunning()) { + m_device = new stmdsp::device(m_device_combo->GetStringSelection().ToStdString()); + if (m_device->connected()) { + doSingle(); + m_render_timer->Start(100); + button->SetLabel("Stop"); + } else { + delete m_device; + m_device = nullptr; + } + } else { + m_render_timer->Stop(); + button->SetLabel("Single"); + + delete m_device; + m_device = nullptr; + } + } + + void onRenderTimer([[maybe_unused]] wxTimerEvent& te) { + updateDrawing(); + } + + void updateDrawing() { + if (m_device_samples = m_device_samples_future.get(); m_device_samples.size() > 0) + this->RefreshRect(m_clipping_region); + + doSingle(); + } +}; + +#endif // WXMAIN_HPP_ + |