aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2020-10-18 21:20:00 -0400
committerClyne Sullivan <clyne@bitgloo.com>2020-10-18 21:20:00 -0400
commit241a089c39c77345e8e0a0c8a04301ba2271e432 (patch)
treeebce9026eed4bd0561f4422fcdc35149ba338487
parent9c98bfb62c3d981eb95957186b3c85e735e0b2f5 (diff)
document/standardize; add compile log to gui
-rw-r--r--gui/stmdsp.cpp12
-rw-r--r--gui/stmdsp.hpp2
-rw-r--r--gui/wxmain.cpp18
-rw-r--r--gui/wxmain.hpp3
-rw-r--r--source/adc.cpp2
-rw-r--r--source/elf_format.hpp7
-rw-r--r--source/elf_load.cpp32
-rw-r--r--source/elf_load.hpp11
-rw-r--r--source/main.cpp237
9 files changed, 200 insertions, 124 deletions
diff --git a/gui/stmdsp.cpp b/gui/stmdsp.cpp
index bbfc716..8f19065 100644
--- a/gui/stmdsp.cpp
+++ b/gui/stmdsp.cpp
@@ -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");
}
}
diff --git a/gui/stmdsp.hpp b/gui/stmdsp.hpp
index 06d36ba..2d336c5 100644
--- a/gui/stmdsp.hpp
+++ b/gui/stmdsp.hpp
@@ -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();
diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp
index d4f4878..874f26e 100644
--- a/gui/wxmain.cpp
+++ b/gui/wxmain.cpp
@@ -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 {
diff --git a/gui/wxmain.hpp b/gui/wxmain.hpp
index b8ff11d..268a08d 100644
--- a/gui/wxmain.hpp
+++ b/gui/wxmain.hpp
@@ -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;
diff --git a/source/adc.cpp b/source/adc.cpp
index 744dbc0..6c1af7b 100644
--- a/source/adc.cpp
+++ b/source/adc.cpp
@@ -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
diff --git a/source/elf_format.hpp b/source/elf_format.hpp
index ed74c7b..d4feb99 100644
--- a/source/elf_format.hpp
+++ b/source/elf_format.hpp
@@ -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_
diff --git a/source/elf_load.cpp b/source/elf_load.cpp
index 3fd8a0f..79cd4fe 100644
--- a/source/elf_load.cpp
+++ b/source/elf_load.cpp
@@ -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;
-//}
-
diff --git a/source/elf_load.hpp b/source/elf_load.hpp
index 4fda526..faa74d2 100644
--- a/source/elf_load.hpp
+++ b/source/elf_load.hpp
@@ -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_
diff --git a/source/main.cpp b/source/main.cpp
index 1e3c5fb..c46685f 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -19,23 +19,47 @@
#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]);
}
}
}