Protocol adjustment + exposing settings for DFT

This commit is contained in:
Jan Käberich 2020-11-07 13:22:10 +01:00
parent ce475fa042
commit a2389fca13
19 changed files with 314 additions and 205 deletions

View File

@ -111,22 +111,40 @@ uint8_t *USBInBuffer::getBuffer() const
return buffer; return buffer;
} }
static Protocol::DeviceLimits limits = { static constexpr Protocol::DeviceInfo defaultInfo = {
.minFreq = 0, .ProtocolVersion = Protocol::Version,
.maxFreq = 6000000000, .FW_major = 0,
.minIFBW = 10, .FW_minor = 0,
.maxIFBW = 50000, .FW_patch = 0,
.maxPoints = 4501, .HW_Revision = '0',
.cdbm_min = -4000, .extRefAvailable = 0,
.cdbm_max = 0, .extRefInUse = 0,
.minRBW = 10, .FPGA_configured = 0,
.maxRBW = 100000, .source_locked = 0,
.LO1_locked = 0,
.ADC_overload = 0,
.temp_source = 0,
.temp_LO1 = 0,
.temp_MCU = 0,
.limits_minFreq = 0,
.limits_maxFreq = 6000000000,
.limits_minIFBW = 10,
.limits_maxIFBW = 50000,
.limits_maxPoints = 4501,
.limits_cdbm_min = -4000,
.limits_cdbm_max = 0,
.limits_minRBW = 15,
.limits_maxRBW = 100000,
}; };
Protocol::DeviceInfo Device::lastInfo = defaultInfo;
Device::Device(QString serial) Device::Device(QString serial)
{ {
qDebug() << "Starting device connection..."; qDebug() << "Starting device connection...";
lastInfo = defaultInfo;
m_handle = nullptr; m_handle = nullptr;
lastInfoValid = false; lastInfoValid = false;
libusb_init(&m_context); libusb_init(&m_context);
@ -182,8 +200,8 @@ Device::Device(QString serial)
connect(this, &Device::receivedAnswer, this, &Device::transmissionFinished, Qt::QueuedConnection); connect(this, &Device::receivedAnswer, this, &Device::transmissionFinished, Qt::QueuedConnection);
transmissionTimer.setSingleShot(true); transmissionTimer.setSingleShot(true);
transmissionActive = false; transmissionActive = false;
// got a new connection, request limits // got a new connection, request info
SendCommandWithoutPayload(Protocol::PacketType::RequestDeviceLimits); SendCommandWithoutPayload(Protocol::PacketType::RequestDeviceInfo);
} }
Device::~Device() Device::~Device()
@ -282,11 +300,6 @@ std::set<QString> Device::GetDevices()
return serials; return serials;
} }
Protocol::DeviceLimits Device::Limits()
{
return limits;
}
void Device::USBHandleThread() void Device::USBHandleThread()
{ {
qInfo() << "Receive thread started" << flush; qInfo() << "Receive thread started" << flush;
@ -366,7 +379,7 @@ void Device::SearchDevices(std::function<bool (libusb_device_handle *, QString)>
libusb_free_device_list(devList, 1); libusb_free_device_list(devList, 1);
} }
Protocol::DeviceInfo Device::getLastInfo() const const Protocol::DeviceInfo &Device::Info()
{ {
return lastInfo; return lastInfo;
} }
@ -379,8 +392,8 @@ QString Device::getLastDeviceInfoString()
} else { } else {
ret.append("HW Rev."); ret.append("HW Rev.");
ret.append(lastInfo.HW_Revision); ret.append(lastInfo.HW_Revision);
ret.append(" FW "+QString::number(lastInfo.FW_major)+"."+QString::number(lastInfo.FW_minor).rightJustified(2, '0')); ret.append(" FW "+QString::number(lastInfo.FW_major)+"."+QString::number(lastInfo.FW_minor)+"."+QString::number(lastInfo.FW_patch));
ret.append(" Temps: "+QString::number(lastInfo.temperatures.source)+"°C/"+QString::number(lastInfo.temperatures.LO1)+"°C/"+QString::number(lastInfo.temperatures.MCU)+"°C"); ret.append(" Temps: "+QString::number(lastInfo.temp_source)+"°C/"+QString::number(lastInfo.temp_LO1)+"°C/"+QString::number(lastInfo.temp_MCU)+"°C");
ret.append(" Reference:"); ret.append(" Reference:");
if(lastInfo.extRefInUse) { if(lastInfo.extRefInUse) {
ret.append("External"); ret.append("External");
@ -412,7 +425,13 @@ void Device::ReceivedData()
emit SpectrumResultReceived(packet.spectrumResult); emit SpectrumResultReceived(packet.spectrumResult);
break; break;
case Protocol::PacketType::DeviceInfo: case Protocol::PacketType::DeviceInfo:
if(packet.info.ProtocolVersion != Protocol::Version) {
if(!lastInfoValid) {
emit NeedsFirmwareUpdate(packet.info.ProtocolVersion, Protocol::Version);
}
} else {
lastInfo = packet.info; lastInfo = packet.info;
}
lastInfoValid = true; lastInfoValid = true;
emit DeviceInfoUpdated(); emit DeviceInfoUpdated();
break; break;
@ -424,9 +443,6 @@ void Device::ReceivedData()
emit NackReceived(); emit NackReceived();
emit receivedAnswer(TransmissionResult::Nack); emit receivedAnswer(TransmissionResult::Nack);
break; break;
case Protocol::PacketType::DeviceLimits:
limits = packet.limits;
break;
default: default:
break; break;
} }

View File

@ -65,12 +65,11 @@ public:
bool SendFirmwareChunk(Protocol::FirmwarePacket &fw); bool SendFirmwareChunk(Protocol::FirmwarePacket &fw);
bool SendCommandWithoutPayload(Protocol::PacketType type); bool SendCommandWithoutPayload(Protocol::PacketType type);
QString serial() const; QString serial() const;
Protocol::DeviceInfo getLastInfo() const; static const Protocol::DeviceInfo& Info();
QString getLastDeviceInfoString(); QString getLastDeviceInfoString();
// Returns serial numbers of all connected devices // Returns serial numbers of all connected devices
static std::set<QString> GetDevices(); static std::set<QString> GetDevices();
static Protocol::DeviceLimits Limits();
signals: signals:
void DatapointReceived(Protocol::Datapoint); void DatapointReceived(Protocol::Datapoint);
void ManualStatusReceived(Protocol::ManualStatus); void ManualStatusReceived(Protocol::ManualStatus);
@ -80,6 +79,7 @@ signals:
void AckReceived(); void AckReceived();
void NackReceived(); void NackReceived();
void LogLineReceived(QString line); void LogLineReceived(QString line);
void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol);
private slots: private slots:
void ReceivedData(); void ReceivedData();
void ReceivedLog(); void ReceivedLog();
@ -119,7 +119,7 @@ private:
QString m_serial; QString m_serial;
bool m_connected; bool m_connected;
std::thread *m_receiveThread; std::thread *m_receiveThread;
Protocol::DeviceInfo lastInfo; static Protocol::DeviceInfo lastInfo;
bool lastInfoValid; bool lastInfoValid;
}; };

View File

@ -10,10 +10,10 @@ SignalgeneratorWidget::SignalgeneratorWidget(QWidget *parent) :
ui->frequency->setPrefixes(" kMG"); ui->frequency->setPrefixes(" kMG");
connect(ui->frequency, &SIUnitEdit::valueChanged, [=](double newval) { connect(ui->frequency, &SIUnitEdit::valueChanged, [=](double newval) {
if(newval < Device::Limits().minFreq) { if(newval < Device::Info().limits_minFreq) {
newval = Device::Limits().minFreq; newval = Device::Info().limits_minFreq;
} else if (newval > Device::Limits().maxFreq) { } else if (newval > Device::Info().limits_maxFreq) {
newval = Device::Limits().maxFreq; newval = Device::Info().limits_maxFreq;
} }
ui->frequency->setValueQuiet(newval); ui->frequency->setValueQuiet(newval);
emit SettingsChanged(); emit SettingsChanged();

View File

@ -251,6 +251,13 @@ void SpectrumAnalyzer::SettingsChanged()
settings.pointNum = settings.f_stop - settings.f_start + 1; settings.pointNum = settings.f_stop - settings.f_start + 1;
} }
auto pref = Preferences::getInstance();
if(pref.Acquisition.useDFTinSAmode && settings.RBW <= pref.Acquisition.RBWLimitForDFT) {
settings.UseDFT = 1;
} else {
settings.UseDFT = 0;
}
if(window->getDevice()) { if(window->getDevice()) {
window->getDevice()->Configure(settings); window->getDevice()->Configure(settings);
} }
@ -311,8 +318,8 @@ void SpectrumAnalyzer::SetSpan(double span)
void SpectrumAnalyzer::SetFullSpan() void SpectrumAnalyzer::SetFullSpan()
{ {
settings.f_start = Device::Limits().minFreq; settings.f_start = Device::Info().limits_minFreq;
settings.f_stop = Device::Limits().maxFreq; settings.f_stop = Device::Info().limits_maxFreq;
ConstrainAndUpdateFrequencies(); ConstrainAndUpdateFrequencies();
} }
@ -340,10 +347,10 @@ void SpectrumAnalyzer::SpanZoomOut()
void SpectrumAnalyzer::SetRBW(double bandwidth) void SpectrumAnalyzer::SetRBW(double bandwidth)
{ {
if(bandwidth > Device::Limits().maxRBW) { if(bandwidth > Device::Info().limits_maxRBW) {
bandwidth = Device::Limits().maxRBW; bandwidth = Device::Info().limits_maxRBW;
} else if(bandwidth < Device::Limits().minRBW) { } else if(bandwidth < Device::Info().limits_minRBW) {
bandwidth = Device::Limits().minRBW; bandwidth = Device::Info().limits_minRBW;
} }
settings.RBW = bandwidth; settings.RBW = bandwidth;
emit RBWChanged(settings.RBW); emit RBWChanged(settings.RBW);
@ -365,14 +372,14 @@ void SpectrumAnalyzer::UpdateAverageCount()
void SpectrumAnalyzer::ConstrainAndUpdateFrequencies() void SpectrumAnalyzer::ConstrainAndUpdateFrequencies()
{ {
if(settings.f_stop > Device::Limits().maxFreq) { if(settings.f_stop > Device::Info().limits_maxFreq) {
settings.f_stop = Device::Limits().maxFreq; settings.f_stop = Device::Info().limits_maxFreq;
} }
if(settings.f_start > settings.f_stop) { if(settings.f_start > settings.f_stop) {
settings.f_start = settings.f_stop; settings.f_start = settings.f_stop;
} }
if(settings.f_start < Device::Limits().minFreq) { if(settings.f_start < Device::Info().limits_minFreq) {
settings.f_start = Device::Limits().minFreq; settings.f_start = Device::Info().limits_minFreq;
} }
emit startFreqChanged(settings.f_start); emit startFreqChanged(settings.f_start);
emit stopFreqChanged(settings.f_stop); emit stopFreqChanged(settings.f_stop);

View File

@ -217,7 +217,11 @@ VNA::VNA(AppWindow *window)
points->setSingleStep(100); points->setSingleStep(100);
points->setToolTip("Points/sweep"); points->setToolTip("Points/sweep");
connect(points, qOverload<int>(&QSpinBox::valueChanged), this, &VNA::SetPoints); connect(points, qOverload<int>(&QSpinBox::valueChanged), this, &VNA::SetPoints);
connect(this, &VNA::pointsChanged, points, &QSpinBox::setValue); connect(this, &VNA::pointsChanged, [=](int p) {
points->blockSignals(true);
points->setValue(p);
points->blockSignals(false);
});
tb_acq->addWidget(new QLabel("Points:")); tb_acq->addWidget(new QLabel("Points:"));
tb_acq->addWidget(points); tb_acq->addWidget(points);
@ -499,8 +503,8 @@ void VNA::SetSpan(double span)
void VNA::SetFullSpan() void VNA::SetFullSpan()
{ {
settings.f_start = Device::Limits().minFreq; settings.f_start = Device::Info().limits_minFreq;
settings.f_stop = Device::Limits().maxFreq; settings.f_stop = Device::Info().limits_maxFreq;
ConstrainAndUpdateFrequencies(); ConstrainAndUpdateFrequencies();
} }
@ -528,10 +532,10 @@ void VNA::SpanZoomOut()
void VNA::SetSourceLevel(double level) void VNA::SetSourceLevel(double level)
{ {
if(level > Device::Limits().cdbm_max / 100.0) { if(level > Device::Info().limits_cdbm_max / 100.0) {
level = Device::Limits().cdbm_max / 100.0; level = Device::Info().limits_cdbm_max / 100.0;
} else if(level < Device::Limits().cdbm_min / 100.0) { } else if(level < Device::Info().limits_cdbm_min / 100.0) {
level = Device::Limits().cdbm_min / 100.0; level = Device::Info().limits_cdbm_min / 100.0;
} }
emit sourceLevelChanged(level); emit sourceLevelChanged(level);
settings.cdbm_excitation = level * 100; settings.cdbm_excitation = level * 100;
@ -540,10 +544,10 @@ void VNA::SetSourceLevel(double level)
void VNA::SetPoints(unsigned int points) void VNA::SetPoints(unsigned int points)
{ {
if (points < 2) { if(points > Device::Info().limits_maxPoints) {
points = Device::Info().limits_maxPoints;
} else if (points < 2) {
points = 2; points = 2;
} else if(points > Device::Limits().maxPoints) {
points = Device::Limits().maxPoints;
} }
emit pointsChanged(points); emit pointsChanged(points);
settings.points = points; settings.points = points;
@ -552,10 +556,10 @@ void VNA::SetPoints(unsigned int points)
void VNA::SetIFBandwidth(double bandwidth) void VNA::SetIFBandwidth(double bandwidth)
{ {
if(bandwidth > Device::Limits().maxIFBW) { if(bandwidth > Device::Info().limits_maxIFBW) {
bandwidth = Device::Limits().maxIFBW; bandwidth = Device::Info().limits_maxIFBW;
} else if(bandwidth < Device::Limits().minIFBW) { } else if(bandwidth < Device::Info().limits_minIFBW) {
bandwidth = Device::Limits().minIFBW; bandwidth = Device::Info().limits_minIFBW;
} }
settings.if_bandwidth = bandwidth; settings.if_bandwidth = bandwidth;
emit IFBandwidthChanged(bandwidth); emit IFBandwidthChanged(bandwidth);
@ -651,14 +655,14 @@ void VNA::StartCalibrationMeasurement(Calibration::Measurement m)
void VNA::ConstrainAndUpdateFrequencies() void VNA::ConstrainAndUpdateFrequencies()
{ {
if(settings.f_stop > Device::Limits().maxFreq) { if(settings.f_stop > Device::Info().limits_maxFreq) {
settings.f_stop = Device::Limits().maxFreq; settings.f_stop = Device::Info().limits_maxFreq;
} }
if(settings.f_start > settings.f_stop) { if(settings.f_start > settings.f_stop) {
settings.f_start = settings.f_stop; settings.f_start = settings.f_stop;
} }
if(settings.f_start < Device::Limits().minFreq) { if(settings.f_start < Device::Info().limits_minFreq) {
settings.f_start = Device::Limits().minFreq; settings.f_start = Device::Info().limits_minFreq;
} }
emit startFreqChanged(settings.f_start); emit startFreqChanged(settings.f_start);
emit stopFreqChanged(settings.f_stop); emit stopFreqChanged(settings.f_stop);

View File

@ -95,14 +95,7 @@ AppWindow::AppWindow(QWidget *parent)
connect(ui->actionDisconnect, &QAction::triggered, this, &AppWindow::DisconnectDevice); connect(ui->actionDisconnect, &QAction::triggered, this, &AppWindow::DisconnectDevice);
connect(ui->actionQuit, &QAction::triggered, this, &AppWindow::close); connect(ui->actionQuit, &QAction::triggered, this, &AppWindow::close);
connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl); connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
connect(ui->actionFirmware_Update, &QAction::triggered, [=](){ connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
if(device) {
auto fw_update = new FirmwareUpdateDialog(device);
connect(fw_update, &FirmwareUpdateDialog::DeviceRebooting, this, &AppWindow::DisconnectDevice);
connect(fw_update, &FirmwareUpdateDialog::DeviceRebooted, this, &AppWindow::ConnectToDevice);
fw_update->exec();
}
});
connect(ui->actionPreferences, &QAction::triggered, [=](){ connect(ui->actionPreferences, &QAction::triggered, [=](){
Preferences::getInstance().edit(); Preferences::getInstance().edit();
// settings might have changed, update necessary stuff // settings might have changed, update necessary stuff
@ -172,6 +165,7 @@ void AppWindow::ConnectToDevice(QString serial)
connect(device, &Device::DeviceInfoUpdated, [this]() { connect(device, &Device::DeviceInfoUpdated, [this]() {
lDeviceInfo.setText(device->getLastDeviceInfoString()); lDeviceInfo.setText(device->getLastDeviceInfoString());
}); });
connect(device, &Device::NeedsFirmwareUpdate, this, &AppWindow::DeviceNeedsUpdate);
ui->actionDisconnect->setEnabled(true); ui->actionDisconnect->setEnabled(true);
ui->actionManual_Control->setEnabled(true); ui->actionManual_Control->setEnabled(true);
ui->actionFirmware_Update->setEnabled(true); ui->actionFirmware_Update->setEnabled(true);
@ -316,6 +310,28 @@ void AppWindow::UpdateReference()
device->SendPacket(p); device->SendPacket(p);
} }
void AppWindow::StartFirmwareUpdateDialog()
{
if(device) {
auto fw_update = new FirmwareUpdateDialog(device);
connect(fw_update, &FirmwareUpdateDialog::DeviceRebooting, this, &AppWindow::DisconnectDevice);
connect(fw_update, &FirmwareUpdateDialog::DeviceRebooted, this, &AppWindow::ConnectToDevice);
fw_update->exec();
}
}
void AppWindow::DeviceNeedsUpdate(int reported, int expected)
{
auto ret = QMessageBox::warning(this, "Warning",
"The device reports are different protocol"
"version (" + QString::number(reported) + ") than expected (" + QString::number(expected) + ").\n"
"A firmware update is strongly suggested. Do you want to update now?",
QMessageBox::Yes | QMessageBox::No);
if (ret == QMessageBox::Yes) {
StartFirmwareUpdateDialog();
}
}
Device *AppWindow::getDevice() const Device *AppWindow::getDevice() const
{ {
return device; return device;

View File

@ -42,7 +42,8 @@ private slots:
int UpdateDeviceList(); int UpdateDeviceList();
void StartManualControl(); void StartManualControl();
void UpdateReference(); void UpdateReference();
void StartFirmwareUpdateDialog();
void DeviceNeedsUpdate(int reported, int expected);
private: private:
void DeviceConnectionLost(); void DeviceConnectionLost();
void CreateToolbars(); void CreateToolbars();

View File

@ -67,6 +67,13 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
ui->StartupSARBW->setUnit("Hz"); ui->StartupSARBW->setUnit("Hz");
ui->StartupSARBW->setPrefixes(" k"); ui->StartupSARBW->setPrefixes(" k");
// Acquisition page
ui->AcquisitionDFTlimitRBW->setUnit("Hz");
ui->AcquisitionDFTlimitRBW->setPrefixes(" k");
connect(ui->AcquisitionUseDFT, &QCheckBox::toggled, [=](bool enabled) {
ui->AcquisitionDFTlimitRBW->setEnabled(enabled);
});
// Page selection // Page selection
connect(ui->treeWidget, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *current, QTreeWidgetItem *) { connect(ui->treeWidget, &QTreeWidget::currentItemChanged, [=](QTreeWidgetItem *current, QTreeWidgetItem *) {
auto name = current->text(0); auto name = current->text(0);
@ -107,6 +114,8 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
p->Startup.SA.signalID = ui->StartupSASignalID->isChecked(); p->Startup.SA.signalID = ui->StartupSASignalID->isChecked();
p->Acquisition.alwaysExciteBothPorts = ui->AcquisitionAlwaysExciteBoth->isChecked(); p->Acquisition.alwaysExciteBothPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked(); p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked();
p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked();
p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value();
p->General.graphColors.background = ui->GeneralGraphBackground->getColor(); p->General.graphColors.background = ui->GeneralGraphBackground->getColor();
p->General.graphColors.axis = ui->GeneralGraphAxis->getColor(); p->General.graphColors.axis = ui->GeneralGraphAxis->getColor();
p->General.graphColors.divisions = ui->GeneralGraphDivisions->getColor(); p->General.graphColors.divisions = ui->GeneralGraphDivisions->getColor();
@ -147,6 +156,8 @@ void PreferencesDialog::setInitialGUIState()
ui->AcquisitionAlwaysExciteBoth->setChecked(p->Acquisition.alwaysExciteBothPorts); ui->AcquisitionAlwaysExciteBoth->setChecked(p->Acquisition.alwaysExciteBothPorts);
ui->AcquisitionSuppressPeaks->setChecked(p->Acquisition.suppressPeaks); ui->AcquisitionSuppressPeaks->setChecked(p->Acquisition.suppressPeaks);
ui->AcquisitionUseDFT->setChecked(p->Acquisition.useDFTinSAmode);
ui->AcquisitionDFTlimitRBW->setValue(p->Acquisition.RBWLimitForDFT);
ui->GeneralGraphBackground->setColor(p->General.graphColors.background); ui->GeneralGraphBackground->setColor(p->General.graphColors.background);
ui->GeneralGraphAxis->setColor(p->General.graphColors.axis); ui->GeneralGraphAxis->setColor(p->General.graphColors.axis);

View File

@ -44,6 +44,8 @@ public:
struct { struct {
bool alwaysExciteBothPorts; bool alwaysExciteBothPorts;
bool suppressPeaks; bool suppressPeaks;
bool useDFTinSAmode;
double RBWLimitForDFT;
} Acquisition; } Acquisition;
struct { struct {
struct { struct {
@ -60,7 +62,7 @@ private:
QString name; QString name;
QVariant def; QVariant def;
}; };
const std::array<SettingDescription, 22> descr = {{ const std::array<SettingDescription, 24> descr = {{
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true}, {&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false}, {&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
{&Startup.DefaultSweep.start, "Startup.DefaultSweep.start", 1000000.0}, {&Startup.DefaultSweep.start, "Startup.DefaultSweep.start", 1000000.0},
@ -80,6 +82,8 @@ private:
{&Startup.SA.signalID, "Startup.SA.signalID", true}, {&Startup.SA.signalID, "Startup.SA.signalID", true},
{&Acquisition.alwaysExciteBothPorts, "Acquisition.alwaysExciteBothPorts", true}, {&Acquisition.alwaysExciteBothPorts, "Acquisition.alwaysExciteBothPorts", true},
{&Acquisition.suppressPeaks, "Acquisition.suppressPeaks", true}, {&Acquisition.suppressPeaks, "Acquisition.suppressPeaks", true},
{&Acquisition.useDFTinSAmode, "Acquisition.useDFTinSAmode", true},
{&Acquisition.RBWLimitForDFT, "Acquisition.RBWLimitForDFT", 3000.0},
{&General.graphColors.background, "General.graphColors.background", QColor(Qt::black)}, {&General.graphColors.background, "General.graphColors.background", QColor(Qt::black)},
{&General.graphColors.axis, "General.graphColors.axis", QColor(Qt::white)}, {&General.graphColors.axis, "General.graphColors.axis", QColor(Qt::white)},
{&General.graphColors.divisions, "General.graphColors.divisions", QColor(Qt::gray)}, {&General.graphColors.divisions, "General.graphColors.divisions", QColor(Qt::gray)},

View File

@ -73,7 +73,7 @@
</size> </size>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="Startup"> <widget class="QWidget" name="Startup">
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
@ -453,6 +453,12 @@
</widget> </widget>
<widget class="QWidget" name="Acquisition"> <widget class="QWidget" name="Acquisition">
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Vector Network Analyzer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item> <item>
<widget class="QCheckBox" name="AcquisitionAlwaysExciteBoth"> <widget class="QCheckBox" name="AcquisitionAlwaysExciteBoth">
<property name="toolTip"> <property name="toolTip">
@ -473,6 +479,35 @@
</property> </property>
</widget> </widget>
</item> </item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Spectrum Analyzer</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QFormLayout" name="formLayout_5">
<item row="0" column="0">
<widget class="QCheckBox" name="AcquisitionUseDFT">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Normally, the spectrum analyzer mode tunes the LO for each point and measures the final IF only at one frequency. When this option is enabled, a DFT of the final IF is calculated instead which covers multiple frequencies with one measurement.&lt;/p&gt;&lt;p&gt;This can speed up the measurement at low RBWs significantly.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Use DFT when RBW is below</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="SIUnitEdit" name="AcquisitionDFTlimitRBW"/>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">

View File

@ -189,6 +189,8 @@
<listOptionValue builtIn="false" value="FW_MAJOR=0"/> <listOptionValue builtIn="false" value="FW_MAJOR=0"/>
<listOptionValue builtIn="false" value="FW_PATCH=0"/>
<listOptionValue builtIn="false" value="FW_MINOR=1"/> <listOptionValue builtIn="false" value="FW_MINOR=1"/>
<listOptionValue builtIn="false" value="USE_FULL_LL_DRIVER"/> <listOptionValue builtIn="false" value="USE_FULL_LL_DRIVER"/>

View File

@ -155,10 +155,10 @@ void App_Start() {
SA::Setup(recv_packet.spectrumSettings); SA::Setup(recv_packet.spectrumSettings);
Communication::SendWithoutPayload(Protocol::PacketType::Ack); Communication::SendWithoutPayload(Protocol::PacketType::Ack);
break; break;
case Protocol::PacketType::RequestDeviceLimits: case Protocol::PacketType::RequestDeviceInfo:
Protocol::PacketInfo p; Protocol::PacketInfo p;
p.type = Protocol::PacketType::DeviceLimits; p.type = Protocol::PacketType::DeviceInfo;
p.limits = HW::Limits; HW::fillDeviceInfo(&p.info);
Communication::Send(p); Communication::Send(p);
break; break;
#ifdef HAS_FLASH #ifdef HAS_FLASH

View File

@ -238,35 +238,58 @@ static int16_t EncodeGeneratorSettings(Protocol::GeneratorSettings d, uint8_t *b
static Protocol::DeviceInfo DecodeDeviceInfo(uint8_t *buf) { static Protocol::DeviceInfo DecodeDeviceInfo(uint8_t *buf) {
Protocol::DeviceInfo d; Protocol::DeviceInfo d;
Decoder e(buf); Decoder e(buf);
e.get<uint16_t>(d.FW_major); e.get(d.ProtocolVersion);
e.get<uint16_t>(d.FW_minor); e.get(d.FW_major);
e.get<char>(d.HW_Revision); e.get(d.FW_minor);
e.get(d.FW_patch);
e.get(d.HW_Revision);
d.extRefAvailable = e.getBits(1); d.extRefAvailable = e.getBits(1);
d.extRefInUse = e.getBits(1); d.extRefInUse = e.getBits(1);
d.FPGA_configured = e.getBits(1); d.FPGA_configured = e.getBits(1);
d.source_locked = e.getBits(1); d.source_locked = e.getBits(1);
d.LO1_locked = e.getBits(1); d.LO1_locked = e.getBits(1);
d.ADC_overload = e.getBits(1); d.ADC_overload = e.getBits(1);
e.get<uint8_t>(d.temperatures.source); e.get(d.temp_source);
e.get<uint8_t>(d.temperatures.LO1); e.get(d.temp_LO1);
e.get<uint8_t>(d.temperatures.MCU); e.get(d.temp_MCU);
e.get(d.limits_minFreq);
e.get(d.limits_maxFreq);
e.get(d.limits_minIFBW);
e.get(d.limits_maxIFBW);
e.get(d.limits_maxPoints);
e.get(d.limits_cdbm_min);
e.get(d.limits_cdbm_max);
e.get(d.limits_minRBW);
e.get(d.limits_maxRBW);
return d; return d;
} }
static int16_t EncodeDeviceInfo(Protocol::DeviceInfo d, uint8_t *buf, static int16_t EncodeDeviceInfo(Protocol::DeviceInfo d, uint8_t *buf,
uint16_t bufSize) { uint16_t bufSize) {
d.ProtocolVersion = Protocol::Version;
Encoder e(buf, bufSize); Encoder e(buf, bufSize);
e.add<uint16_t>(d.FW_major); e.add(d.ProtocolVersion);
e.add<uint16_t>(d.FW_minor); e.add(d.FW_major);
e.add<char>(d.HW_Revision); e.add(d.FW_minor);
e.add(d.FW_patch);
e.add(d.HW_Revision);
e.addBits(d.extRefAvailable, 1); e.addBits(d.extRefAvailable, 1);
e.addBits(d.extRefInUse, 1); e.addBits(d.extRefInUse, 1);
e.addBits(d.FPGA_configured, 1); e.addBits(d.FPGA_configured, 1);
e.addBits(d.source_locked, 1); e.addBits(d.source_locked, 1);
e.addBits(d.LO1_locked, 1); e.addBits(d.LO1_locked, 1);
e.addBits(d.ADC_overload, 1); e.addBits(d.ADC_overload, 1);
e.add<uint8_t>(d.temperatures.source); e.add(d.temp_source);
e.add<uint8_t>(d.temperatures.LO1); e.add(d.temp_LO1);
e.add<uint8_t>(d.temperatures.MCU); e.add(d.temp_MCU);
e.add(d.limits_minFreq);
e.add(d.limits_maxFreq);
e.add(d.limits_minIFBW);
e.add(d.limits_maxIFBW);
e.add(d.limits_maxPoints);
e.add(d.limits_cdbm_min);
e.add(d.limits_cdbm_max);
e.add(d.limits_minRBW);
e.add(d.limits_maxRBW);
return e.getSize(); return e.getSize();
} }
@ -378,6 +401,7 @@ static Protocol::SpectrumAnalyzerSettings DecodeSpectrumAnalyzerSettings(uint8_t
d.WindowType = e.getBits(2); d.WindowType = e.getBits(2);
d.SignalID = e.getBits(1); d.SignalID = e.getBits(1);
d.Detector = e.getBits(3); d.Detector = e.getBits(3);
d.UseDFT = e.getBits(1);
return d; return d;
} }
static int16_t EncodeSpectrumAnalyzerSettings(Protocol::SpectrumAnalyzerSettings d, uint8_t *buf, static int16_t EncodeSpectrumAnalyzerSettings(Protocol::SpectrumAnalyzerSettings d, uint8_t *buf,
@ -390,6 +414,7 @@ static int16_t EncodeSpectrumAnalyzerSettings(Protocol::SpectrumAnalyzerSettings
e.addBits(d.WindowType, 2); e.addBits(d.WindowType, 2);
e.addBits(d.SignalID, 1); e.addBits(d.SignalID, 1);
e.addBits(d.Detector, 3); e.addBits(d.Detector, 3);
e.addBits(d.UseDFT, 1);
return e.getSize(); return e.getSize();
} }
@ -412,35 +437,6 @@ static int16_t EncodeSpectrumAnalyzerResult(Protocol::SpectrumAnalyzerResult d,
return e.getSize(); return e.getSize();
} }
static Protocol::DeviceLimits DecodeDeviceLimits(uint8_t *buf) {
Protocol::DeviceLimits d;
Decoder e(buf);
e.get(d.minFreq);
e.get(d.maxFreq);
e.get(d.minIFBW);
e.get(d.maxIFBW);
e.get(d.maxPoints);
e.get(d.cdbm_min);
e.get(d.cdbm_max);
e.get(d.minRBW);
e.get(d.maxRBW);
return d;
}
static int16_t EncodeDeviceLimits(Protocol::DeviceLimits d, uint8_t *buf,
uint16_t bufSize) {
Encoder e(buf, bufSize);
e.add(d.minFreq);
e.add(d.maxFreq);
e.add(d.minIFBW);
e.add(d.maxIFBW);
e.add(d.maxPoints);
e.add(d.cdbm_min);
e.add(d.cdbm_max);
e.add(d.minRBW);
e.add(d.maxRBW);
return e.getSize();
}
static Protocol::FirmwarePacket DecodeFirmwarePacket(uint8_t *buf) { static Protocol::FirmwarePacket DecodeFirmwarePacket(uint8_t *buf) {
Protocol::FirmwarePacket d; Protocol::FirmwarePacket d;
// simple packet format, memcpy is faster than using the decoder // simple packet format, memcpy is faster than using the decoder
@ -545,14 +541,11 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
case PacketType::SpectrumAnalyzerResult: case PacketType::SpectrumAnalyzerResult:
info->spectrumResult = DecodeSpectrumAnalyzerResult(&data[4]); info->spectrumResult = DecodeSpectrumAnalyzerResult(&data[4]);
break; break;
case PacketType::DeviceLimits:
info->limits = DecodeDeviceLimits(&data[4]);
break;
case PacketType::Ack: case PacketType::Ack:
case PacketType::PerformFirmwareUpdate: case PacketType::PerformFirmwareUpdate:
case PacketType::ClearFlash: case PacketType::ClearFlash:
case PacketType::Nack: case PacketType::Nack:
case PacketType::RequestDeviceLimits: case PacketType::RequestDeviceInfo:
// no payload, nothing to do // no payload, nothing to do
break; break;
case PacketType::None: case PacketType::None:
@ -595,14 +588,11 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
case PacketType::SpectrumAnalyzerResult: case PacketType::SpectrumAnalyzerResult:
payload_size = EncodeSpectrumAnalyzerResult(packet.spectrumResult, &dest[4], destsize - 8); payload_size = EncodeSpectrumAnalyzerResult(packet.spectrumResult, &dest[4], destsize - 8);
break; break;
case PacketType::DeviceLimits:
payload_size = EncodeDeviceLimits(packet.limits, &dest[4], destsize - 8);
break;
case PacketType::Ack: case PacketType::Ack:
case PacketType::PerformFirmwareUpdate: case PacketType::PerformFirmwareUpdate:
case PacketType::ClearFlash: case PacketType::ClearFlash:
case PacketType::Nack: case PacketType::Nack:
case PacketType::RequestDeviceLimits: case PacketType::RequestDeviceInfo:
// no payload, nothing to do // no payload, nothing to do
break; break;
case PacketType::None: case PacketType::None:

View File

@ -4,6 +4,8 @@
namespace Protocol { namespace Protocol {
static constexpr uint16_t Version = 1;
// When changing/adding/removing variables from these structs also adjust the decode/encode functions in Protocol.cpp // When changing/adding/removing variables from these structs also adjust the decode/encode functions in Protocol.cpp
using Datapoint = struct _datapoint { using Datapoint = struct _datapoint {
@ -39,8 +41,10 @@ using GeneratorSettings = struct _generatorSettings {
}; };
using DeviceInfo = struct _deviceInfo { using DeviceInfo = struct _deviceInfo {
uint16_t FW_major; uint16_t ProtocolVersion;
uint16_t FW_minor; uint8_t FW_major;
uint8_t FW_minor;
uint8_t FW_patch;
char HW_Revision; char HW_Revision;
uint8_t extRefAvailable:1; uint8_t extRefAvailable:1;
uint8_t extRefInUse:1; uint8_t extRefInUse:1;
@ -48,11 +52,18 @@ using DeviceInfo = struct _deviceInfo {
uint8_t source_locked:1; uint8_t source_locked:1;
uint8_t LO1_locked:1; uint8_t LO1_locked:1;
uint8_t ADC_overload:1; uint8_t ADC_overload:1;
struct { uint8_t temp_source;
uint8_t source; uint8_t temp_LO1;
uint8_t LO1; uint8_t temp_MCU;
uint8_t MCU; uint64_t limits_minFreq;
} temperatures; uint64_t limits_maxFreq;
uint32_t limits_minIFBW;
uint32_t limits_maxIFBW;
uint16_t limits_maxPoints;
int16_t limits_cdbm_min;
int16_t limits_cdbm_max;
uint32_t limits_minRBW;
uint32_t limits_maxRBW;
}; };
using ManualStatus = struct _manualstatus { using ManualStatus = struct _manualstatus {
@ -107,6 +118,7 @@ using SpectrumAnalyzerSettings = struct _spectrumAnalyzerSettings {
uint8_t WindowType :2; uint8_t WindowType :2;
uint8_t SignalID :1; uint8_t SignalID :1;
uint8_t Detector :3; uint8_t Detector :3;
uint8_t UseDFT :1;
}; };
using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult { using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
@ -116,18 +128,6 @@ using SpectrumAnalyzerResult = struct _spectrumAnalyzerResult {
uint16_t pointNum; uint16_t pointNum;
}; };
using DeviceLimits = struct _deviceLimits {
uint64_t minFreq;
uint64_t maxFreq;
uint32_t minIFBW;
uint32_t maxIFBW;
uint16_t maxPoints;
int16_t cdbm_min;
int16_t cdbm_max;
uint32_t minRBW;
uint32_t maxRBW;
};
static constexpr uint16_t FirmwareChunkSize = 256; static constexpr uint16_t FirmwareChunkSize = 256;
using FirmwarePacket = struct _firmwarePacket { using FirmwarePacket = struct _firmwarePacket {
uint32_t address; uint32_t address;
@ -150,8 +150,7 @@ enum class PacketType : uint8_t {
Generator = 12, Generator = 12,
SpectrumAnalyzerSettings = 13, SpectrumAnalyzerSettings = 13,
SpectrumAnalyzerResult = 14, SpectrumAnalyzerResult = 14,
RequestDeviceLimits = 15, RequestDeviceInfo = 15,
DeviceLimits = 16,
}; };
using PacketInfo = struct _packetinfo { using PacketInfo = struct _packetinfo {
@ -167,7 +166,6 @@ using PacketInfo = struct _packetinfo {
ManualStatus status; ManualStatus status;
SpectrumAnalyzerSettings spectrumSettings; SpectrumAnalyzerSettings spectrumSettings;
SpectrumAnalyzerResult spectrumResult; SpectrumAnalyzerResult spectrumResult;
DeviceLimits limits;
}; };
}; };

View File

@ -7,6 +7,7 @@
#include "VNA.hpp" #include "VNA.hpp"
#include "Manual.hpp" #include "Manual.hpp"
#include "SpectrumAnalyzer.hpp" #include "SpectrumAnalyzer.hpp"
#include <cstring>
#define LOG_LEVEL LOG_LEVEL_INFO #define LOG_LEVEL LOG_LEVEL_INFO
#define LOG_MODULE "HW" #define LOG_MODULE "HW"
@ -222,7 +223,12 @@ void HW::SetIdle() {
FPGA::Enable(FPGA::Periphery::PortSwitch, false); FPGA::Enable(FPGA::Periphery::PortSwitch, false);
} }
void HW::fillDeviceInfo(Protocol::DeviceInfo *info) { void HW::fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy) {
// copy constant default values
memcpy(info, &HW::Info, sizeof(HW::Info));
if(activeMode == Mode::Idle || updateEvenWhenBusy) {
// updating values from FPGA allowed
// read PLL temperatures // read PLL temperatures
uint8_t tempSource, tempLO; uint8_t tempSource, tempLO;
GetTemps(&tempSource, &tempLO); GetTemps(&tempSource, &tempLO);
@ -245,11 +251,12 @@ void HW::fillDeviceInfo(Protocol::DeviceInfo *info) {
info->source_locked = (status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1; info->source_locked = (status & (int) FPGA::Interrupt::SourceUnlock) ? 0 : 1;
info->extRefAvailable = Ref::available(); info->extRefAvailable = Ref::available();
info->extRefInUse = extRefInUse; info->extRefInUse = extRefInUse;
info->temperatures.LO1 = tempLO; info->temp_LO1 = tempLO;
info->temperatures.source = tempSource; info->temp_source = tempSource;
info->temperatures.MCU = STM::getTemperature();
FPGA::ResetADCLimits(); FPGA::ResetADCLimits();
} }
info->temp_MCU = STM::getTemperature();
}
bool HW::Ref::available() { bool HW::Ref::available() {
return Si5351.ExtCLKAvailable(); return Si5351.ExtCLKAvailable();

View File

@ -38,16 +38,30 @@ static_assert(ADCprescaler * ADCSamplerate == FPGA::Clockrate, "ADCSamplerate ca
static constexpr uint16_t DFTphaseInc = 4096 * IF2 / ADCSamplerate; static constexpr uint16_t DFTphaseInc = 4096 * IF2 / ADCSamplerate;
static_assert(DFTphaseInc * ADCSamplerate == 4096 * IF2, "DFT can not be computed for 2.IF"); static_assert(DFTphaseInc * ADCSamplerate == 4096 * IF2, "DFT can not be computed for 2.IF");
static constexpr Protocol::DeviceLimits Limits = { static constexpr Protocol::DeviceInfo Info = {
.minFreq = 0, .ProtocolVersion = Protocol::Version,
.maxFreq = 6000000000, .FW_major = FW_MAJOR,
.minIFBW = ADCSamplerate / MaxSamples, .FW_minor = FW_MINOR,
.maxIFBW = ADCSamplerate / MinSamples, .FW_patch = FW_PATCH,
.maxPoints = FPGA::MaxPoints, .HW_Revision = HW_REVISION,
.cdbm_min = -4000, .extRefAvailable = 0,
.cdbm_max = 0, .extRefInUse = 0,
.minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples), .FPGA_configured = 0,
.maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples), .source_locked = 0,
.LO1_locked = 0,
.ADC_overload = 0,
.temp_source = 0,
.temp_LO1 = 0,
.temp_MCU = 0,
.limits_minFreq = 0,
.limits_maxFreq = 6000000000,
.limits_minIFBW = ADCSamplerate / MaxSamples,
.limits_maxIFBW = ADCSamplerate / MinSamples,
.limits_maxPoints = FPGA::MaxPoints,
.limits_cdbm_min = -4000,
.limits_cdbm_max = 0,
.limits_minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples),
.limits_maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples),
}; };
enum class Mode { enum class Mode {
@ -63,7 +77,7 @@ void SetIdle();
void Work(); void Work();
bool GetTemps(uint8_t *source, uint8_t *lo); bool GetTemps(uint8_t *source, uint8_t *lo);
void fillDeviceInfo(Protocol::DeviceInfo *info); void fillDeviceInfo(Protocol::DeviceInfo *info, bool updateEvenWhenBusy = false);
namespace Ref { namespace Ref {
bool available(); bool available();
// reference won't change until update is called // reference won't change until update is called

View File

@ -23,7 +23,6 @@ static Protocol::PacketInfo p;
static bool active = false; static bool active = false;
static uint32_t lastLO2; static uint32_t lastLO2;
static uint32_t actualRBW; static uint32_t actualRBW;
static bool usingDFT;
static uint16_t DFTpoints; static uint16_t DFTpoints;
static bool negativeDFT; // if true, a positive frequency shift at input results in a negative shift at the 2.IF. Handle DFT accordingly static bool negativeDFT; // if true, a positive frequency shift at input results in a negative shift at the 2.IF. Handle DFT accordingly
@ -106,7 +105,7 @@ static void StartNextSample() {
Si5351.SetCLK(SiChannel::Port2LO2, LO2freq, Si5351C::PLL::B, Si5351C::DriveStrength::mA2); Si5351.SetCLK(SiChannel::Port2LO2, LO2freq, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
lastLO2 = LO2freq; lastLO2 = LO2freq;
} }
if (usingDFT) { if (s.UseDFT) {
uint32_t spacing = (s.f_stop - s.f_start) / (points - 1); uint32_t spacing = (s.f_stop - s.f_start) / (points - 1);
uint32_t start = HW::IF2; uint32_t start = HW::IF2;
if(negativeDFT) { if(negativeDFT) {
@ -166,11 +165,16 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
FPGA::Enable(FPGA::Periphery::Port1Mixer); FPGA::Enable(FPGA::Periphery::Port1Mixer);
FPGA::Enable(FPGA::Periphery::Port2Mixer); FPGA::Enable(FPGA::Periphery::Port2Mixer);
// automatically select DFT mode for lower RBWs if (s.UseDFT) {
usingDFT = actualRBW <= 1000; uint32_t spacing = (s.f_stop - s.f_start) / (points - 1);
// The DFT can only look at a small bandwidth otherwise the passband of the final ADC filter is visible in the data
if (usingDFT) { // Limit to about 30kHz
DFTpoints = FPGA::DFTbins; // use full DFT in FPGA uint32_t maxDFTpoints = 30000 / spacing;
// Limit to actual supported number of bins
if(maxDFTpoints > FPGA::DFTbins) {
maxDFTpoints = FPGA::DFTbins;
}
DFTpoints = maxDFTpoints;
FPGA::DisableInterrupt(FPGA::Interrupt::NewData); FPGA::DisableInterrupt(FPGA::Interrupt::NewData);
} else { } else {
DFTpoints = 1; // can only measure one point at a time DFTpoints = 1; // can only measure one point at a time
@ -191,7 +195,7 @@ bool SA::MeasurementDone(const FPGA::SamplingResult &result) {
for(uint16_t i=0;i<DFTpoints;i++) { for(uint16_t i=0;i<DFTpoints;i++) {
float port1, port2; float port1, port2;
if (usingDFT) { if (s.UseDFT) {
// use DFT result // use DFT result
auto dft = FPGA::ReadDFTResult(); auto dft = FPGA::ReadDFTResult();
port1 = dft.P1; port1 = dft.P1;
@ -217,7 +221,7 @@ bool SA::MeasurementDone(const FPGA::SamplingResult &result) {
} }
} }
if (usingDFT) { if (s.UseDFT) {
FPGA::StopDFT(); FPGA::StopDFT();
// will be started again in StartNextSample // will be started again in StartNextSample
} }

View File

@ -264,9 +264,8 @@ void VNA::Work() {
packet.info.FW_major = FW_MAJOR; packet.info.FW_major = FW_MAJOR;
packet.info.FW_minor = FW_MINOR; packet.info.FW_minor = FW_MINOR;
packet.info.HW_Revision = HW_REVISION; packet.info.HW_Revision = HW_REVISION;
HW::fillDeviceInfo(&packet.info); HW::fillDeviceInfo(&packet.info, true);
Communication::Send(packet); Communication::Send(packet);
FPGA::ResetADCLimits();
// Start next sweep // Start next sweep
FPGA::StartSweep(); FPGA::StartSweep();
} }

View File

@ -101,6 +101,7 @@ MCU = $(CPU) -mthumb $(FLOAT-ABI) $(FPU)
C_DEFS = \ C_DEFS = \
-DFW_MAJOR=0 \ -DFW_MAJOR=0 \
-DFW_MINOR=1 \ -DFW_MINOR=1 \
-DFW_PATCH=0 \
-DUSE_FULL_LL_DRIVER \ -DUSE_FULL_LL_DRIVER \
-DHW_REVISION="'B'" \ -DHW_REVISION="'B'" \
-D__weak="__attribute__((weak))" \ -D__weak="__attribute__((weak))" \