status monitoring; improve connection safety

pull/1/head
Clyne 3 years ago
parent 12440b673f
commit 79032a73d5

@ -24,7 +24,7 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
extern stmdsp::device *m_device; extern std::shared_ptr<stmdsp::device> m_device;
extern void log(const std::string& str); extern void log(const std::string& str);
@ -75,7 +75,7 @@ void compileEditorCode()
} }
stmdsp::platform platform; stmdsp::platform platform;
if (m_device != nullptr) { if (m_device) {
platform = m_device->get_platform(); platform = m_device->get_platform();
} else { } else {
// Assume a default. // Assume a default.

@ -26,15 +26,17 @@
#include <deque> #include <deque>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <memory>
#include <mutex> #include <mutex>
#include <thread> #include <thread>
extern std::string tempFileName; extern std::string tempFileName;
extern stmdsp::device *m_device;
extern void log(const std::string& str); extern void log(const std::string& str);
extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string_view); extern std::vector<stmdsp::dacsample_t> deviceGenLoadFormulaEval(const std::string_view);
std::shared_ptr<stmdsp::device> m_device;
static const std::array<const char *, 6> sampleRateList {{ static const std::array<const char *, 6> sampleRateList {{
"8 kHz", "8 kHz",
"16 kHz", "16 kHz",
@ -75,18 +77,18 @@ static std::deque<stmdsp::dacsample_t> drawSamplesInputQueue;
static double drawSamplesTimeframe = 1.0; // seconds static double drawSamplesTimeframe = 1.0; // seconds
static unsigned int drawSamplesBufferSize = 1; static unsigned int drawSamplesBufferSize = 1;
static void measureCodeTask(stmdsp::device *device) static void measureCodeTask(std::shared_ptr<stmdsp::device> device)
{ {
if (device == nullptr) if (!device)
return; return;
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
auto cycles = device->continuous_start_get_measurement(); auto cycles = device->continuous_start_get_measurement();
log(std::string("Execution time: ") + std::to_string(cycles) + " cycles."); log(std::string("Execution time: ") + std::to_string(cycles) + " cycles.");
} }
static void drawSamplesTask(stmdsp::device *device) static void drawSamplesTask(std::shared_ptr<stmdsp::device> device)
{ {
if (device == nullptr) if (!device)
return; return;
const bool doLogger = logResults && logSamplesFile.good(); const bool doLogger = logResults && logSamplesFile.good();
@ -159,9 +161,9 @@ static void drawSamplesTask(stmdsp::device *device)
} }
} }
static void feedSigGenTask(stmdsp::device *device) static void feedSigGenTask(std::shared_ptr<stmdsp::device> device)
{ {
if (device == nullptr) if (!device)
return; return;
const auto bufferSize = m_device->get_buffer_size(); const auto bufferSize = m_device->get_buffer_size();
@ -197,6 +199,31 @@ static void feedSigGenTask(stmdsp::device *device)
} }
} }
static void statusTask(std::shared_ptr<stmdsp::device> device)
{
if (!device)
return;
while (device->connected()) {
std::unique_lock<std::timed_mutex> lockDevice (mutexDeviceLoad, std::defer_lock);
lockDevice.lock();
auto [status, error] = device->get_status();
lockDevice.unlock();
if (error != stmdsp::Error::None) {
if (error == stmdsp::Error::NotIdle) {
log("Error: Device already running...");
} else if (error == stmdsp::Error::ConversionAborted) {
log("Error: Algorithm unloaded, a fault occurred!");
} else {
log("Error: Device had an issue...");
}
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
static void deviceConnect(); static void deviceConnect();
static void deviceStart(); static void deviceStart();
static void deviceAlgorithmUpload(); static void deviceAlgorithmUpload();
@ -286,7 +313,7 @@ void deviceRenderWidgets()
ImGui::InputText("", bufferSizeStr, sizeof(bufferSizeStr), ImGuiInputTextFlags_CharsDecimal); ImGui::InputText("", bufferSizeStr, sizeof(bufferSizeStr), ImGuiInputTextFlags_CharsDecimal);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
if (ImGui::Button("Save")) { if (ImGui::Button("Save")) {
if (m_device != nullptr) { if (m_device) {
int n = std::clamp(std::stoi(bufferSizeStr), 100, 4096); int n = std::clamp(std::stoi(bufferSizeStr), 100, 4096);
m_device->continuous_set_buffer_size(n); m_device->continuous_set_buffer_size(n);
} }
@ -437,13 +464,14 @@ void deviceRenderDraw()
void deviceRenderMenu() void deviceRenderMenu()
{ {
if (ImGui::BeginMenu("Run")) { if (ImGui::BeginMenu("Run")) {
bool isConnected = m_device != nullptr; bool isConnected = m_device ? true : false;
bool isRunning = isConnected && m_device->is_running(); bool isRunning = isConnected && m_device->is_running();
static const char *connectLabel = "Connect"; static const char *connectLabel = "Connect";
if (ImGui::MenuItem(connectLabel)) { if (ImGui::MenuItem(connectLabel, nullptr, false, !isConnected || (isConnected && !isRunning))) {
deviceConnect(); deviceConnect();
connectLabel = m_device == nullptr ? "Connect" : "Disconnect"; isConnected = m_device ? true : false;
connectLabel = isConnected ? "Disconnect" : "Connect";
} }
ImGui::Separator(); ImGui::Separator();
@ -453,9 +481,9 @@ void deviceRenderMenu()
deviceStart(); deviceStart();
} }
if (ImGui::MenuItem("Upload algorithm", nullptr, false, isConnected)) if (ImGui::MenuItem("Upload algorithm", nullptr, false, isConnected && !isRunning))
deviceAlgorithmUpload(); deviceAlgorithmUpload();
if (ImGui::MenuItem("Unload algorithm", nullptr, false, isConnected)) if (ImGui::MenuItem("Unload algorithm", nullptr, false, isConnected && !isRunning))
deviceAlgorithmUnload(); deviceAlgorithmUnload();
ImGui::Separator(); ImGui::Separator();
if (ImGui::Checkbox("Measure Code Time", &measureCodeTime)) { if (ImGui::Checkbox("Measure Code Time", &measureCodeTime)) {
@ -480,16 +508,16 @@ void deviceRenderMenu()
logResults = false; logResults = false;
} }
} }
if (ImGui::MenuItem("Set buffer size...", nullptr, false, isConnected)) { if (ImGui::MenuItem("Set buffer size...", nullptr, false, isConnected && !isRunning)) {
popupRequestBuffer = true; popupRequestBuffer = true;
} }
ImGui::Separator(); ImGui::Separator();
if (ImGui::MenuItem("Load signal generator", nullptr, false, isConnected)) { if (ImGui::MenuItem("Load signal generator", nullptr, false, isConnected && !isRunning)) {
popupRequestSiggen = true; popupRequestSiggen = true;
} }
static const char *startSiggenLabel = "Start signal generator"; static const char *startSiggenLabel = "Start signal generator";
if (ImGui::MenuItem(startSiggenLabel, nullptr, false, isConnected)) { if (ImGui::MenuItem(startSiggenLabel, nullptr, false, isConnected)) {
if (m_device != nullptr) { if (m_device) {
if (!genRunning) { if (!genRunning) {
genRunning = true; genRunning = true;
if (wavOutput.valid()) if (wavOutput.valid())
@ -522,7 +550,7 @@ void deviceRenderToolbar()
for (unsigned int i = 0; i < sampleRateList.size(); ++i) { for (unsigned int i = 0; i < sampleRateList.size(); ++i) {
if (ImGui::Selectable(sampleRateList[i])) { if (ImGui::Selectable(sampleRateList[i])) {
sampleRatePreview = sampleRateList[i]; sampleRatePreview = sampleRateList[i];
if (m_device != nullptr && !m_device->is_running()) { if (m_device && !m_device->is_running()) {
do { do {
m_device->set_sample_rate(i); m_device->set_sample_rate(i);
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
@ -538,24 +566,28 @@ void deviceRenderToolbar()
void deviceConnect() void deviceConnect()
{ {
if (m_device == nullptr) { static std::thread statusThread;
if (!m_device) {
stmdsp::scanner scanner; stmdsp::scanner scanner;
if (auto devices = scanner.scan(); devices.size() > 0) { if (auto devices = scanner.scan(); devices.size() > 0) {
try { try {
m_device = new stmdsp::device(devices.front()); m_device.reset(new stmdsp::device(devices.front()));
} catch (...) { } catch (...) {
log("Failed to connect (check permissions?)."); log("Failed to connect (check permissions?).");
m_device = nullptr; m_device.reset();
} }
if (m_device != nullptr) {
if (m_device) {
if (m_device->connected()) { if (m_device->connected()) {
auto sri = m_device->get_sample_rate(); auto sri = m_device->get_sample_rate();
sampleRatePreview = sampleRateList[sri]; sampleRatePreview = sampleRateList[sri];
drawSamplesBufferSize = std::round(sampleRateInts[sri] * drawSamplesTimeframe); drawSamplesBufferSize = std::round(sampleRateInts[sri] * drawSamplesTimeframe);
log("Connected!"); log("Connected!");
statusThread = std::thread(statusTask, m_device);
statusThread.detach();
} else { } else {
delete m_device; m_device.reset();
m_device = nullptr;
log("Failed to connect."); log("Failed to connect.");
} }
} }
@ -563,15 +595,17 @@ void deviceConnect()
log("No devices found."); log("No devices found.");
} }
} else { } else {
delete m_device; m_device->disconnect();
m_device = nullptr; if (statusThread.joinable())
statusThread.join();
m_device.reset();
log("Disconnected."); log("Disconnected.");
} }
} }
void deviceStart() void deviceStart()
{ {
if (m_device == nullptr) { if (!m_device) {
log("No device connected."); log("No device connected.");
return; return;
} }
@ -579,6 +613,7 @@ void deviceStart()
if (m_device->is_running()) { if (m_device->is_running()) {
{ {
std::scoped_lock lock (mutexDrawSamples); std::scoped_lock lock (mutexDrawSamples);
std::scoped_lock lock2 (mutexDeviceLoad);
std::this_thread::sleep_for(std::chrono::microseconds(150)); std::this_thread::sleep_for(std::chrono::microseconds(150));
m_device->continuous_stop(); m_device->continuous_stop();
} }
@ -603,7 +638,7 @@ void deviceStart()
void deviceAlgorithmUpload() void deviceAlgorithmUpload()
{ {
if (m_device == nullptr) { if (!m_device) {
log("No device connected."); log("No device connected.");
return; return;
} }
@ -625,7 +660,7 @@ void deviceAlgorithmUpload()
void deviceAlgorithmUnload() void deviceAlgorithmUnload()
{ {
if (m_device == nullptr) { if (!m_device) {
log("No device connected."); log("No device connected.");
return; return;
} }
@ -660,7 +695,7 @@ void deviceGenLoadList(std::string_view listStr)
if ((samples.size() & 1) == 1) if ((samples.size() & 1) == 1)
samples.push_back(samples.back()); samples.push_back(samples.back());
if (m_device != nullptr) if (m_device)
m_device->siggen_upload(&samples[0], samples.size()); m_device->siggen_upload(&samples[0], samples.size());
log("Generator ready."); log("Generator ready.");
} else { } else {
@ -673,7 +708,7 @@ void deviceGenLoadFormula(std::string_view formula)
auto samples = deviceGenLoadFormulaEval(formula); auto samples = deviceGenLoadFormulaEval(formula);
if (samples.size() > 0) { if (samples.size() > 0) {
if (m_device != nullptr) if (m_device)
m_device->siggen_upload(&samples[0], samples.size()); m_device->siggen_upload(&samples[0], samples.size());
log("Generator ready."); log("Generator ready.");

@ -47,7 +47,6 @@ extern void deviceRenderWidgets();
// Globals that live here // Globals that live here
bool done = false; bool done = false;
stmdsp::device *m_device = nullptr;
static LogView logView; static LogView logView;

@ -13,6 +13,8 @@
#include <serial/serial.h> #include <serial/serial.h>
extern void log(const std::string& str);
namespace stmdsp namespace stmdsp
{ {
std::list<std::string>& scanner::scan() std::list<std::string>& scanner::scan()
@ -26,23 +28,42 @@ namespace stmdsp
return m_available_devices; return m_available_devices;
} }
device::device(const std::string& file) : device::device(const std::string& file)
m_serial(file, 8'000'000, serial::Timeout::simpleTimeout(50))
{ {
if (m_serial.isOpen()) { // This could throw!
m_serial.flush(); m_serial.reset(new serial::Serial(file, 8'000'000, serial::Timeout::simpleTimeout(50)));
m_serial.write("i");
if (auto id = m_serial.read(7); id.starts_with("stmdsp")) { m_serial->flush();
m_serial->write("i");
auto id = m_serial->read(7);
if (id.starts_with("stmdsp")) {
if (id.back() == 'h') if (id.back() == 'h')
m_platform = platform::H7; m_platform = platform::H7;
else if (id.back() == 'l') else if (id.back() == 'l')
m_platform = platform::L4; m_platform = platform::L4;
else else
m_serial.close(); m_serial.release();
} else { } else {
m_serial.close(); m_serial.release();
}
}
device::~device()
{
disconnect();
} }
bool device::connected() {
if (m_serial && !m_serial->isOpen())
m_serial.release();
return m_serial ? true : false;
} }
void device::disconnect() {
if (m_serial)
m_serial.release();
} }
void device::continuous_set_buffer_size(unsigned int size) { void device::continuous_set_buffer_size(unsigned int size) {
@ -54,7 +75,13 @@ namespace stmdsp
static_cast<uint8_t>(size), static_cast<uint8_t>(size),
static_cast<uint8_t>(size >> 8) static_cast<uint8_t>(size >> 8)
}; };
m_serial.write(request, 3);
try {
m_serial->write(request, 3);
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
@ -64,7 +91,13 @@ namespace stmdsp
'r', 'r',
static_cast<uint8_t>(id) static_cast<uint8_t>(id)
}; };
m_serial.write(request, 2);
try {
m_serial->write(request, 2);
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
@ -73,10 +106,16 @@ namespace stmdsp
uint8_t request[2] = { uint8_t request[2] = {
'r', 0xFF 'r', 0xFF
}; };
m_serial.write(request, 2);
unsigned char result = 0xFF; unsigned char result = 0xFF;
m_serial.read(&result, 1); try {
m_serial->write(request, 2);
m_serial->read(&result, 1);
} catch (...) {
m_serial.release();
log("Lost connection!");
}
m_sample_rate = result; m_sample_rate = result;
} }
@ -85,23 +124,38 @@ namespace stmdsp
void device::continuous_start() { void device::continuous_start() {
if (connected()) { if (connected()) {
m_serial.write("R"); try {
m_serial->write("R");
m_is_running = true; m_is_running = true;
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
void device::continuous_start_measure() { void device::continuous_start_measure() {
if (connected()) { if (connected()) {
m_serial.write("M"); try {
m_serial->write("M");
m_is_running = true; m_is_running = true;
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
uint32_t device::continuous_start_get_measurement() { uint32_t device::continuous_start_get_measurement() {
uint32_t count = 0; uint32_t count = 0;
if (connected()) { if (connected()) {
m_serial.write("m"); try {
m_serial.read(reinterpret_cast<uint8_t *>(&count), sizeof(uint32_t)); m_serial->write("m");
m_serial->read(reinterpret_cast<uint8_t *>(&count), sizeof(uint32_t));
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
return count / 2; return count / 2;
@ -109,9 +163,10 @@ namespace stmdsp
std::vector<adcsample_t> device::continuous_read() { std::vector<adcsample_t> device::continuous_read() {
if (connected()) { if (connected()) {
m_serial.write("s"); try {
m_serial->write("s");
unsigned char sizebytes[2]; unsigned char sizebytes[2];
m_serial.read(sizebytes, 2); m_serial->read(sizebytes, 2);
unsigned int size = sizebytes[0] | (sizebytes[1] << 8); unsigned int size = sizebytes[0] | (sizebytes[1] << 8);
if (size > 0) { if (size > 0) {
std::vector<adcsample_t> data (size); std::vector<adcsample_t> data (size);
@ -119,16 +174,20 @@ namespace stmdsp
unsigned int offset = 0; unsigned int offset = 0;
while (total > 512) { while (total > 512) {
m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, 512); m_serial->read(reinterpret_cast<uint8_t *>(&data[0]) + offset, 512);
m_serial.write("n"); m_serial->write("n");
offset += 512; offset += 512;
total -= 512; total -= 512;
} }
m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, total); m_serial->read(reinterpret_cast<uint8_t *>(&data[0]) + offset, total);
m_serial.write("n"); m_serial->write("n");
return data; return data;
} }
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
return {}; return {};
@ -136,9 +195,10 @@ namespace stmdsp
std::vector<adcsample_t> device::continuous_read_input() { std::vector<adcsample_t> device::continuous_read_input() {
if (connected()) { if (connected()) {
m_serial.write("t"); try {
m_serial->write("t");
unsigned char sizebytes[2]; unsigned char sizebytes[2];
m_serial.read(sizebytes, 2); m_serial->read(sizebytes, 2);
unsigned int size = sizebytes[0] | (sizebytes[1] << 8); unsigned int size = sizebytes[0] | (sizebytes[1] << 8);
if (size > 0) { if (size > 0) {
std::vector<adcsample_t> data (size); std::vector<adcsample_t> data (size);
@ -146,16 +206,20 @@ namespace stmdsp
unsigned int offset = 0; unsigned int offset = 0;
while (total > 512) { while (total > 512) {
m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, 512); m_serial->read(reinterpret_cast<uint8_t *>(&data[0]) + offset, 512);
m_serial.write("n"); m_serial->write("n");
offset += 512; offset += 512;
total -= 512; total -= 512;
} }
m_serial.read(reinterpret_cast<uint8_t *>(&data[0]) + offset, total); m_serial->read(reinterpret_cast<uint8_t *>(&data[0]) + offset, total);
m_serial.write("n"); m_serial->write("n");
return data; return data;
} }
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
return {}; return {};
@ -163,8 +227,13 @@ namespace stmdsp
void device::continuous_stop() { void device::continuous_stop() {
if (connected()) { if (connected()) {
m_serial.write("S"); try {
m_serial->write("S");
m_is_running = false; m_is_running = false;
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
@ -175,26 +244,39 @@ namespace stmdsp
static_cast<uint8_t>(size), static_cast<uint8_t>(size),
static_cast<uint8_t>(size >> 8) static_cast<uint8_t>(size >> 8)
}; };
m_serial.write(request, 3);
m_serial.write((uint8_t *)buffer, size * sizeof(dacsample_t)); try {
// TODO m_serial->write(request, 3);
if (!m_is_running) // TODO different write size if feeding audio?
m_serial.write((uint8_t *)buffer, size * sizeof(dacsample_t)); m_serial->write((uint8_t *)buffer, size * sizeof(dacsample_t));
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
void device::siggen_start() { void device::siggen_start() {
if (connected()) { if (connected()) {
try {
m_serial->write("W");
m_is_siggening = true; m_is_siggening = true;
m_serial.write("W"); } catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
void device::siggen_stop() { void device::siggen_stop() {
if (connected()) { if (connected()) {
try {
m_serial->write("w");
m_is_siggening = false; m_is_siggening = false;
m_serial.write("w"); } catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
@ -205,14 +287,48 @@ namespace stmdsp
static_cast<uint8_t>(size), static_cast<uint8_t>(size),
static_cast<uint8_t>(size >> 8) static_cast<uint8_t>(size >> 8)
}; };
m_serial.write(request, 3);
m_serial.write(buffer, size); try {
m_serial->write(request, 3);
m_serial->write(buffer, size);
} catch (...) {
m_serial.release();
log("Lost connection!");
}
} }
} }
void device::unload_filter() { void device::unload_filter() {
if (connected()) if (connected()) {
m_serial.write("e"); try {
m_serial->write("e");
} catch (...) {
m_serial.release();
log("Lost connection!");
}
}
}
std::pair<RunStatus, Error> device::get_status() {
std::pair<RunStatus, Error> ret;
if (connected()) {
try {
m_serial->write("I");
auto result = m_serial->read(2);
ret = {static_cast<RunStatus>(result[0]),
static_cast<Error>(result[1])};
bool running = ret.first == RunStatus::Running;
if (m_is_running != running)
m_is_running = running;
} catch (...) {
m_serial.release();
log("Lost connection!");
}
}
return ret;
} }
} }

@ -12,15 +12,34 @@
#ifndef STMDSP_HPP_ #ifndef STMDSP_HPP_
#define STMDSP_HPP_ #define STMDSP_HPP_
#include <serial/serial.h>
#include <cstdint> #include <cstdint>
#include <list> #include <list>
#include <serial/serial.h> #include <memory>
#include <string> #include <string>
#include <tuple>
namespace stmdsp namespace stmdsp
{ {
constexpr unsigned int SAMPLES_MAX = 4096; constexpr unsigned int SAMPLES_MAX = 4096;
enum class RunStatus : char {
Idle = '1',
Running,
Recovering
};
enum class Error : char {
None = 0,
BadParam,
BadParamSize,
BadUserCodeLoad,
BadUserCodeSize,
NotIdle,
ConversionAborted
};
class scanner class scanner
{ {
private: private:
@ -46,39 +65,41 @@ namespace stmdsp
enum class platform { enum class platform {
Unknown, Unknown,
H7, H7, /* Behind in feature support */
L4, L4, /* Complete feature support */
G4 G4 /* Currently unsupported */
}; };
class device class device
{ {
public: public:
device(const std::string& file); device(const std::string& file);
~device();
~device() { bool connected();
m_serial.close(); void disconnect();
}
bool connected() {
return m_serial.isOpen();
}
auto get_platform() const { return m_platform; } auto get_platform() const { return m_platform; }
void continuous_set_buffer_size(unsigned int size); void continuous_set_buffer_size(unsigned int size);
unsigned int get_buffer_size() const { return m_buffer_size; } unsigned int get_buffer_size() const { return m_buffer_size; }
void set_sample_rate(unsigned int id); void set_sample_rate(unsigned int id);
unsigned int get_sample_rate(); unsigned int get_sample_rate();
void continuous_start(); void continuous_start();
void continuous_stop();
void continuous_start_measure(); void continuous_start_measure();
uint32_t continuous_start_get_measurement(); uint32_t continuous_start_get_measurement();
std::vector<adcsample_t> continuous_read(); std::vector<adcsample_t> continuous_read();
std::vector<adcsample_t> continuous_read_input(); std::vector<adcsample_t> continuous_read_input();
void continuous_stop();
void siggen_upload(dacsample_t *buffer, unsigned int size); void siggen_upload(dacsample_t *buffer, unsigned int size);
void siggen_start(); void siggen_start();
void siggen_stop(); void siggen_stop();
bool is_siggening() const { return m_is_siggening; } bool is_siggening() const { return m_is_siggening; }
bool is_running() const { return m_is_running; } bool is_running() const { return m_is_running; }
@ -86,8 +107,10 @@ namespace stmdsp
void upload_filter(unsigned char *buffer, size_t size); void upload_filter(unsigned char *buffer, size_t size);
void unload_filter(); void unload_filter();
std::pair<RunStatus, Error> get_status();
private: private:
serial::Serial m_serial; std::unique_ptr<serial::Serial> m_serial;
platform m_platform = platform::Unknown; platform m_platform = platform::Unknown;
unsigned int m_buffer_size = SAMPLES_MAX; unsigned int m_buffer_size = SAMPLES_MAX;
unsigned int m_sample_rate = 0; unsigned int m_sample_rate = 0;

Loading…
Cancel
Save