fixed sample rate setting

pull/3/head
Clyne 4 years ago
parent f3e4d176d5
commit e12639c46f

@ -544,7 +544,7 @@
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_CHECKS) #if !defined(CH_DBG_ENABLE_CHECKS)
#define CH_DBG_ENABLE_CHECKS FALSE #define CH_DBG_ENABLE_CHECKS TRUE
#endif #endif
/** /**
@ -556,7 +556,7 @@
* @note The default is @p FALSE. * @note The default is @p FALSE.
*/ */
#if !defined(CH_DBG_ENABLE_ASSERTS) #if !defined(CH_DBG_ENABLE_ASSERTS)
#define CH_DBG_ENABLE_ASSERTS FALSE #define CH_DBG_ENABLE_ASSERTS TRUE
#endif #endif
/** /**

@ -69,7 +69,7 @@
#define STM32_PLLSAI1R_VALUE 4 #define STM32_PLLSAI1R_VALUE 4
#define STM32_PLLSAI2N_VALUE 24 #define STM32_PLLSAI2N_VALUE 24
#define STM32_PLLSAI2P_VALUE 7 #define STM32_PLLSAI2P_VALUE 7
#define STM32_PLLSAI2R_VALUE 2 #define STM32_PLLSAI2R_VALUE 8
/* /*
* Peripherals clock sources. * Peripherals clock sources.
@ -88,7 +88,7 @@
#define STM32_SAI1SEL STM32_SAI1SEL_OFF #define STM32_SAI1SEL STM32_SAI1SEL_OFF
#define STM32_SAI2SEL STM32_SAI2SEL_OFF #define STM32_SAI2SEL STM32_SAI2SEL_OFF
#define STM32_CLK48SEL STM32_CLK48SEL_PLLSAI1 #define STM32_CLK48SEL STM32_CLK48SEL_PLLSAI1
#define STM32_ADCSEL STM32_ADCSEL_PLLSAI1 #define STM32_ADCSEL STM32_ADCSEL_PLLSAI2
#define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1 #define STM32_SWPMI1SEL STM32_SWPMI1SEL_PCLK1
#define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2 #define STM32_DFSDMSEL STM32_DFSDMSEL_PCLK2
#define STM32_RTCSEL STM32_RTCSEL_LSI #define STM32_RTCSEL STM32_RTCSEL_LSI

@ -62,6 +62,20 @@ namespace stmdsp
} }
} }
unsigned int device::get_sample_rate() {
unsigned char result = 0xFF;
if (connected()) {
uint8_t request[2] = {
'r', 0xFF
};
m_serial.write(request, 2);
m_serial.read(&result, 1);
}
return result;
}
void device::continuous_start() { void device::continuous_start() {
if (connected()) if (connected())
m_serial.write("R"); m_serial.write("R");

@ -45,6 +45,7 @@ namespace stmdsp
void continuous_set_buffer_size(unsigned int size); void continuous_set_buffer_size(unsigned int size);
void set_sample_rate(unsigned int id); void set_sample_rate(unsigned int id);
unsigned int get_sample_rate();
void continuous_start(); void continuous_start();
void continuous_start_measure(); void continuous_start_measure();
uint32_t continuous_start_get_measurement(); uint32_t continuous_start_get_measurement();

@ -1,5 +1,6 @@
#include "wxmain.hpp" #include "wxmain.hpp"
#include <wx/combobox.h>
#include <wx/dir.h> #include <wx/dir.h>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/filedlg.h> #include <wx/filedlg.h>
@ -40,8 +41,10 @@ enum Id {
MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50), wxSize(640, 800)) MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50), wxSize(640, 800))
{ {
auto splitter = new wxSplitterWindow(this, wxID_ANY); auto splitter = new wxSplitterWindow(this, wxID_ANY);
auto panelToolbar = new wxPanel(this, wxID_ANY);
auto panelCode = new wxPanel(splitter, wxID_ANY); auto panelCode = new wxPanel(splitter, wxID_ANY);
auto panelOutput = new wxPanel(splitter, wxID_ANY); auto panelOutput = new wxPanel(splitter, wxID_ANY);
auto sizerToolbar = new wxBoxSizer(wxHORIZONTAL);
auto sizerCode = new wxBoxSizer(wxVERTICAL); auto sizerCode = new wxBoxSizer(wxVERTICAL);
auto sizerOutput = new wxBoxSizer(wxVERTICAL); auto sizerOutput = new wxBoxSizer(wxVERTICAL);
auto sizerSplitter = new wxBoxSizer(wxVERTICAL); auto sizerSplitter = new wxBoxSizer(wxVERTICAL);
@ -51,7 +54,7 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
// Member initialization // Member initialization
m_status_bar = new wxStatusBar(this); m_status_bar = new wxStatusBar(this);
m_text_editor = new wxStyledTextCtrl(panelCode, wxID_ANY, wxDefaultPosition, wxSize(620, 500)); m_text_editor = new wxStyledTextCtrl(panelCode, wxID_ANY, wxDefaultPosition, wxSize(620, 440));
m_compile_output = new wxTextCtrl(panelOutput, wxID_ANY, wxEmptyString, wxDefaultPosition, m_compile_output = new wxTextCtrl(panelOutput, wxID_ANY, wxEmptyString, wxDefaultPosition,
wxSize(620, 250), wxTE_READONLY | wxTE_MULTILINE | wxHSCROLL); wxSize(620, 250), wxTE_READONLY | wxTE_MULTILINE | wxHSCROLL);
m_measure_timer = new wxTimer(this, Id::MeasureTimer); m_measure_timer = new wxTimer(this, Id::MeasureTimer);
@ -63,8 +66,30 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
splitter->SetSashGravity(0.5); splitter->SetSashGravity(0.5);
splitter->SetMinimumPaneSize(20); splitter->SetMinimumPaneSize(20);
auto comp = new wxButton(panelToolbar, Id::MCodeCompile, "Compile");
static const wxString srateValues[] = {
"16 kS/s",
"48 kS/s",
"96 kS/s",
"100 kS/s",
"200 kS/s",
"1 MS/s",
"2 MS/s"
};
m_rate_select = new wxComboBox(panelToolbar, wxID_ANY,
wxEmptyString, wxDefaultPosition, wxDefaultSize,
7, srateValues, 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);
prepareEditor(); prepareEditor();
sizerCode->Add(m_text_editor, 1, wxEXPAND | wxALL, 0); sizerCode->Add(panelToolbar, 0, wxTOP | wxBOTTOM, 4);
sizerCode->Add(m_text_editor, 1, wxEXPAND, 0);
panelCode->SetSizer(sizerCode); panelCode->SetSizer(sizerCode);
m_compile_output->SetBackgroundColour(wxColour(0, 0, 0)); m_compile_output->SetBackgroundColour(wxColour(0, 0, 0));
@ -72,7 +97,7 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
sizerOutput->Add(m_compile_output, 1, wxEXPAND | wxALL, 0); sizerOutput->Add(m_compile_output, 1, wxEXPAND | wxALL, 0);
panelOutput->SetSizer(sizerOutput); panelOutput->SetSizer(sizerOutput);
splitter->SplitHorizontally(panelCode, panelOutput, 500); splitter->SplitHorizontally(panelCode, panelOutput, 440);
sizerSplitter->Add(splitter, 1, wxEXPAND, 5); sizerSplitter->Add(splitter, 1, wxEXPAND, 5);
SetSizer(sizerSplitter); SetSizer(sizerSplitter);
@ -110,8 +135,6 @@ MainFrame::MainFrame() : wxFrame(nullptr, wxID_ANY, "stmdspgui", wxPoint(50, 50)
menuRun->Append(MRunUnload, "U&nload code")); menuRun->Append(MRunUnload, "U&nload code"));
Bind(wxEVT_MENU, &MainFrame::onRunEditBSize, this, Id::MRunEditBSize, wxID_ANY, Bind(wxEVT_MENU, &MainFrame::onRunEditBSize, this, Id::MRunEditBSize, wxID_ANY,
menuRun->Append(MRunEditBSize, "Set &buffer size...")); menuRun->Append(MRunEditBSize, "Set &buffer size..."));
Bind(wxEVT_MENU, &MainFrame::onRunEditSRate, this, Id::MRunEditSRate, wxID_ANY,
menuRun->Append(MRunEditSRate, "Set sample &rate..."));
menuRun->AppendSeparator(); menuRun->AppendSeparator();
Bind(wxEVT_MENU, &MainFrame::onRunGenUpload, this, Id::MRunGenUpload, wxID_ANY, Bind(wxEVT_MENU, &MainFrame::onRunGenUpload, this, Id::MRunGenUpload, wxID_ANY,
@ -210,6 +233,7 @@ all:
--remove-section .comment \ --remove-section .comment \
--remove-section .noinit \ --remove-section .noinit \
$0.o $0.o
arm-none-eabi-size $0.o
)make"; )make";
static wxString file_header (R"cpp( static wxString file_header (R"cpp(
@ -257,11 +281,9 @@ wxString MainFrame::compileEditorCode()
if (result == 0) { if (result == 0) {
m_status_bar->SetStatusText("Compilation succeeded."); m_status_bar->SetStatusText("Compilation succeeded.");
m_compile_output->ChangeValue("");
return m_temp_file_name + ".o"; return m_temp_file_name + ".o";
} else { } else {
m_status_bar->SetStatusText("Compilation failed."); m_status_bar->SetStatusText("Compilation failed.");
m_compile_output->LoadFile(make_output);
return ""; return "";
} }
} }
@ -294,6 +316,7 @@ void MainFrame::onFileOpen([[maybe_unused]] wxCommandEvent&)
m_open_file_path = openDialog.GetPath(); m_open_file_path = openDialog.GetPath();
m_text_editor->SetText(buffer); m_text_editor->SetText(buffer);
m_text_editor->DiscardEdits(); m_text_editor->DiscardEdits();
m_compile_output->ChangeValue("");
m_status_bar->SetStatusText("Ready."); m_status_bar->SetStatusText("Ready.");
} }
delete[] buffer; delete[] buffer;
@ -377,11 +400,17 @@ void MainFrame::onRunConnect(wxCommandEvent& ce)
if (auto devices = scanner.scan(); devices.size() > 0) { if (auto devices = scanner.scan(); devices.size() > 0) {
m_device = new stmdsp::device(devices.front()); m_device = new stmdsp::device(devices.front());
if (m_device->connected()) { if (m_device->connected()) {
auto rate = m_device->get_sample_rate();
m_rate_select->SetSelection(rate);
m_rate_select->Enable();
menuItem->SetItemLabel("&Disconnect"); menuItem->SetItemLabel("&Disconnect");
m_status_bar->SetStatusText("Connected."); m_status_bar->SetStatusText("Connected.");
} else { } else {
delete m_device; delete m_device;
m_device = nullptr; m_device = nullptr;
m_rate_select->Disable();
menuItem->SetItemLabel("&Connect"); menuItem->SetItemLabel("&Connect");
m_status_bar->SetStatusText("Failed to connect."); m_status_bar->SetStatusText("Failed to connect.");
} }
@ -478,27 +507,12 @@ void MainFrame::onRunEditBSize([[maybe_unused]] wxCommandEvent&)
} }
} }
void MainFrame::onRunEditSRate([[maybe_unused]] wxCommandEvent&) void MainFrame::onToolbarSampleRate(wxCommandEvent& ce)
{ {
if (m_device != nullptr && m_device->connected()) { if (m_device != nullptr && m_device->connected()) {
wxTextEntryDialog dialog (this, "Enter new sample rate id:", "Set Sample Rate"); auto combo = dynamic_cast<wxComboBox *>(ce.GetEventUserData());
if (dialog.ShowModal() == wxID_OK) { m_device->set_sample_rate(combo->GetCurrentSelection());
if (wxString value = dialog.GetValue(); !value.IsEmpty()) { m_status_bar->SetStatusText("Ready.");
if (unsigned long n; value.ToULong(&n)) {
if (n < 20) {
m_device->set_sample_rate(n);
} else {
m_status_bar->SetStatusText("Error: Invalid sample rate.");
}
} else {
m_status_bar->SetStatusText("Error: Invalid sample rate.");
}
} else {
m_status_bar->SetStatusText("Ready.");
}
} else {
m_status_bar->SetStatusText("Ready.");
}
} else { } else {
wxMessageBox("No device connected!", "Run", wxICON_WARNING); wxMessageBox("No device connected!", "Run", wxICON_WARNING);
m_status_bar->SetStatusText("Please connect."); m_status_bar->SetStatusText("Please connect.");

@ -38,10 +38,11 @@ public:
void onRunUpload(wxCommandEvent&); void onRunUpload(wxCommandEvent&);
void onRunUnload(wxCommandEvent&); void onRunUnload(wxCommandEvent&);
void onRunEditBSize(wxCommandEvent&); void onRunEditBSize(wxCommandEvent&);
void onRunEditSRate(wxCommandEvent&);
void onRunGenUpload(wxCommandEvent&); void onRunGenUpload(wxCommandEvent&);
void onRunGenStart(wxCommandEvent&); void onRunGenStart(wxCommandEvent&);
void onToolbarSampleRate(wxCommandEvent&);
void onRunCompile(wxCommandEvent&); void onRunCompile(wxCommandEvent&);
void onCodeDisassemble(wxCommandEvent&); void onCodeDisassemble(wxCommandEvent&);
@ -57,6 +58,7 @@ private:
wxTimer *m_measure_timer = nullptr; wxTimer *m_measure_timer = nullptr;
wxStatusBar *m_status_bar = nullptr; wxStatusBar *m_status_bar = nullptr;
wxMenuBar *m_menu_bar = nullptr; wxMenuBar *m_menu_bar = nullptr;
wxComboBox *m_rate_select = nullptr;
wxFileOutputStream *m_conv_result_log = nullptr; wxFileOutputStream *m_conv_result_log = nullptr;
wxString m_open_file_path; wxString m_open_file_path;
wxString m_temp_file_name; wxString m_temp_file_name;

@ -38,36 +38,23 @@ static ADCConversionGroup adc_group_config = {
}; };
constexpr static const GPTConfig gpt_config = { constexpr static const GPTConfig gpt_config = {
.frequency = 14400000, .frequency = 36000000,
.callback = nullptr, .callback = nullptr,
.cr2 = TIM_CR2_MMS_1, /* TRGO */ .cr2 = TIM_CR2_MMS_1, /* TRGO */
.dier = 0 .dier = 0
}; };
#define ADC_CCR_PRESC_DIV1 (0)
#define ADC_SAMPLE_RATE_SETTINGS_COUNT (7)
static uint32_t adc_sample_rate_settings[] = { static uint32_t adc_sample_rate_settings[] = {
10, ADC_SMPR_SMP_47P5, 4608, // 3125 // Rate PLLSAI2N ADC_PRESC ADC_SMPR GPT_DIV
11, ADC_SMPR_SMP_12P5, 3840, // 3750 /* 16k */ 8, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 2250,
9, ADC_SMPR_SMP_47P5, 2304, // 6250 /* 48k */ 24, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 750,
10, ADC_SMPR_SMP_12P5, 1920, // 7500 /* 96k */ 48, ADC_CCR_PRESC_DIV10, ADC_SMPR_SMP_12P5, 375,
8, ADC_SMPR_SMP_47P5, 1152, // 12K5 /* 100k */ 40, ADC_CCR_PRESC_DIV8, ADC_SMPR_SMP_12P5, 360,
9, ADC_SMPR_SMP_12P5, 960, // 15K /* 400k */ 40, ADC_CCR_PRESC_DIV2, ADC_SMPR_SMP_12P5, 90,
7, ADC_SMPR_SMP_47P5, 576, // 25K /* 1M */ 38, ADC_CCR_PRESC_DIV1, ADC_SMPR_SMP_6P5, 36,
8, ADC_SMPR_SMP_12P5, 480, // 30K /* 2M */ 76, ADC_CCR_PRESC_DIV1, ADC_SMPR_SMP_6P5, 18
5, ADC_SMPR_SMP_47P5, 360, // 40K
4, ADC_SMPR_SMP_47P5, 288, // 50K
7, ADC_SMPR_SMP_12P5, 240, // 60K
6, ADC_SMPR_SMP_12P5, 180, // 80K
5, ADC_SMPR_SMP_12P5, 150, // 96K
2, ADC_SMPR_SMP_47P5, 144, // 100K
4, ADC_SMPR_SMP_12P5, 120, // 120K
3, ADC_SMPR_SMP_12P5, 90, // 160K
1, ADC_SMPR_SMP_47P5, 72, // 200K
2, ADC_SMPR_SMP_12P5, 60, // 240K
0, ADC_SMPR_SMP_47P5, 36, // 400K
1, ADC_SMPR_SMP_12P5, 30, // 480K
1, ADC_SMPR_SMP_2P5, 18, // 800K
0, ADC_SMPR_SMP_12P5, 15, // 960K
0, ADC_SMPR_SMP_2P5, 9 // 1M6
}; };
static bool adc_is_read_finished = false; static bool adc_is_read_finished = false;
@ -92,18 +79,36 @@ namespace adc
void set_rate(rate new_rate) void set_rate(rate new_rate)
{ {
auto index = static_cast<unsigned int>(new_rate); auto index = static_cast<unsigned int>(new_rate);
auto presc = adc_sample_rate_settings[index * 3] << 18; auto plln = adc_sample_rate_settings[index * 4] << RCC_PLLSAI2CFGR_PLLSAI2N_Pos;
auto smp = adc_sample_rate_settings[index * 3 + 1]; auto presc = adc_sample_rate_settings[index * 4 + 1] << ADC_CCR_PRESC_Pos;
adc_gpt_divisor = adc_sample_rate_settings[index * 3 + 2]; auto smp = adc_sample_rate_settings[index * 4 + 2];
adc_gpt_divisor = adc_sample_rate_settings[index * 4 + 3];
adcStop(adcd); adcStop(adcd);
// Adjust PLLSAI2
RCC->CR &= ~(RCC_CR_PLLSAI2ON);
while ((RCC->CR & RCC_CR_PLLSAI2RDY) == RCC_CR_PLLSAI2RDY);
RCC->PLLSAI2CFGR = (RCC->PLLSAI2CFGR & ~(RCC_PLLSAI2CFGR_PLLSAI2N_Msk)) | plln;
RCC->CR |= RCC_CR_PLLSAI2ON;
// Set ADC prescaler // Set ADC prescaler
adcd->adcc->CCR = (adcd->adcc->CCR & ~(0xF << 18)) | presc; adcd->adcc->CCR = (adcd->adcc->CCR & ~(ADC_CCR_PRESC_Msk)) | presc;
// Set sampling time // Set sampling time
adc_group_config.smpr[0] = ADC_SMPR1_SMP_AN5(smp); adc_group_config.smpr[0] = ADC_SMPR1_SMP_AN5(smp);
adcStart(adcd, &adc_config); adcStart(adcd, &adc_config);
} }
unsigned int get_rate()
{
for (unsigned int i = 0; i < ADC_SAMPLE_RATE_SETTINGS_COUNT; i++) {
if (adc_gpt_divisor == adc_sample_rate_settings[i * 3 + 3])
return i;
}
return 0xFF;
}
unsigned int get_gpt_divisor() unsigned int get_gpt_divisor()
{ {
return adc_gpt_divisor; return adc_gpt_divisor;

@ -19,33 +19,18 @@ namespace adc
using operation_t = void (*)(adcsample_t *buffer, size_t count); using operation_t = void (*)(adcsample_t *buffer, size_t count);
enum class rate : unsigned int { enum class rate : unsigned int {
R3125 = 0, R16K = 0,
R3750, R48K,
R6250,
R7500,
R12K5,
R15K,
R25K,
R30K,
R40K,
R50K,
R60K,
R80K,
R96K, R96K,
R100K, R100K,
R120K,
R160K,
R200K,
R240K,
R400K, R400K,
R480K, R1M,
R800K, R2M
R960K,
R1M6
}; };
void init(); void init();
void set_rate(rate new_rate); void set_rate(rate new_rate);
unsigned int get_rate();
unsigned int get_gpt_divisor(); unsigned int get_gpt_divisor();
adcsample_t *read(adcsample_t *buffer, size_t count); adcsample_t *read(adcsample_t *buffer, size_t count);
void read_start(operation_t operation_func, adcsample_t *buffer, size_t count); void read_start(operation_t operation_func, adcsample_t *buffer, size_t count);

@ -30,7 +30,7 @@ constexpr static const DACConversionGroup dac_group_config = {
}; };
constexpr static const GPTConfig gpt_config = { constexpr static const GPTConfig gpt_config = {
.frequency = 14400000, .frequency = 36000000,
.callback = nullptr, .callback = nullptr,
.cr2 = TIM_CR2_MMS_1, /* TRGO */ .cr2 = TIM_CR2_MMS_1, /* TRGO */
.dier = 0 .dier = 0

@ -250,10 +250,16 @@ void main_loop()
break; break;
case 'r': case 'r':
if (usbserial::read(&cmd[1], 1) == 1) if (usbserial::read(&cmd[1], 1) == 1) {
adc::set_rate(static_cast<adc::rate>(cmd[1])); if (cmd[1] == 0xFF) {
else unsigned char r = static_cast<unsigned char>(adc::get_rate());
usbserial::write(&r, 1);
} else {
adc::set_rate(static_cast<adc::rate>(cmd[1]));
}
} else {
error_queue_add(Error::BadParamSize); error_queue_add(Error::BadParamSize);
}
break; break;
// 'S' - Stops the continuous sampling/conversion. // 'S' - Stops the continuous sampling/conversion.
@ -267,6 +273,10 @@ void main_loop()
case 's': case 's':
if (dac_samples_new != nullptr) { if (dac_samples_new != nullptr) {
auto samps = reinterpret_cast<const uint8_t *>(
const_cast<const dacsample_t *>(dac_samples_new));
dac_samples_new = nullptr;
unsigned char buf[2] = { unsigned char buf[2] = {
static_cast<unsigned char>(dac_sample_count / 2 & 0xFF), static_cast<unsigned char>(dac_sample_count / 2 & 0xFF),
static_cast<unsigned char>(((dac_sample_count / 2) >> 8) & 0xFF) static_cast<unsigned char>(((dac_sample_count / 2) >> 8) & 0xFF)
@ -275,8 +285,6 @@ void main_loop()
unsigned int total = dac_sample_count / 2 * sizeof(dacsample_t); unsigned int total = dac_sample_count / 2 * sizeof(dacsample_t);
unsigned int offset = 0; unsigned int offset = 0;
unsigned char unused; unsigned char unused;
auto samps = reinterpret_cast<const uint8_t *>(
const_cast<const dacsample_t *>(dac_samples_new));
while (total > 512) { while (total > 512) {
usbserial::write(samps + offset, 512); usbserial::write(samps + offset, 512);
while (usbserial::read(&unused, 1) == 0); while (usbserial::read(&unused, 1) == 0);
@ -285,7 +293,6 @@ void main_loop()
} }
usbserial::write(samps + offset, total); usbserial::write(samps + offset, total);
while (usbserial::read(&unused, 1) == 0); while (usbserial::read(&unused, 1) == 0);
dac_samples_new = nullptr;
} else { } else {
usbserial::write("\0\0", 2); usbserial::write("\0\0", 2);
} }

Loading…
Cancel
Save