user selectable IF frequencies
This commit is contained in:
parent
d5f2f7019e
commit
5d8efd4336
@ -212,6 +212,11 @@ AppWindow::AppWindow(QWidget *parent)
|
|||||||
spectrumAnalyzer->setAveragingMode(Averaging::Mode::Mean);
|
spectrumAnalyzer->setAveragingMode(Averaging::Mode::Mean);
|
||||||
vna->setAveragingMode(Averaging::Mode::Mean);
|
vna->setAveragingMode(Averaging::Mode::Mean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// acquisition frequencies may have changed, update
|
||||||
|
UpdateAcquisitionFrequencies();
|
||||||
|
|
||||||
|
active->initializeDevice();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->actionAbout, &QAction::triggered, [=](){
|
connect(ui->actionAbout, &QAction::triggered, [=](){
|
||||||
@ -306,6 +311,7 @@ bool AppWindow::ConnectToDevice(QString serial)
|
|||||||
ui->actionReceiver_Calibration->setEnabled(true);
|
ui->actionReceiver_Calibration->setEnabled(true);
|
||||||
ui->actionFrequency_Calibration->setEnabled(true);
|
ui->actionFrequency_Calibration->setEnabled(true);
|
||||||
|
|
||||||
|
UpdateAcquisitionFrequencies();
|
||||||
Mode::getActiveMode()->initializeDevice();
|
Mode::getActiveMode()->initializeDevice();
|
||||||
UpdateReference();
|
UpdateReference();
|
||||||
|
|
||||||
@ -866,6 +872,20 @@ void AppWindow::UpdateReference()
|
|||||||
device->SendPacket(p);
|
device->SendPacket(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppWindow::UpdateAcquisitionFrequencies()
|
||||||
|
{
|
||||||
|
if(!device) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Protocol::PacketInfo p;
|
||||||
|
p.type = Protocol::PacketType::AcquisitionFrequencySettings;
|
||||||
|
auto pref = Preferences::getInstance();
|
||||||
|
p.acquisitionFrequencySettings.IF1 = pref.Acquisition.IF1;
|
||||||
|
p.acquisitionFrequencySettings.ADCprescaler = pref.Acquisition.ADCprescaler;
|
||||||
|
p.acquisitionFrequencySettings.DFTphaseInc = pref.Acquisition.DFTPhaseInc;
|
||||||
|
device->SendPacket(p);
|
||||||
|
}
|
||||||
|
|
||||||
void AppWindow::StartFirmwareUpdateDialog()
|
void AppWindow::StartFirmwareUpdateDialog()
|
||||||
{
|
{
|
||||||
if(device) {
|
if(device) {
|
||||||
|
@ -54,6 +54,7 @@ private slots:
|
|||||||
int UpdateDeviceList();
|
int UpdateDeviceList();
|
||||||
void StartManualControl();
|
void StartManualControl();
|
||||||
void UpdateReference();
|
void UpdateReference();
|
||||||
|
void UpdateAcquisitionFrequencies();
|
||||||
void StartFirmwareUpdateDialog();
|
void StartFirmwareUpdateDialog();
|
||||||
void DeviceNeedsUpdate(int reported, int expected);
|
void DeviceNeedsUpdate(int reported, int expected);
|
||||||
void SourceCalibrationDialog();
|
void SourceCalibrationDialog();
|
||||||
|
@ -73,6 +73,26 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||||||
connect(ui->AcquisitionUseDFT, &QCheckBox::toggled, [=](bool enabled) {
|
connect(ui->AcquisitionUseDFT, &QCheckBox::toggled, [=](bool enabled) {
|
||||||
ui->AcquisitionDFTlimitRBW->setEnabled(enabled);
|
ui->AcquisitionDFTlimitRBW->setEnabled(enabled);
|
||||||
});
|
});
|
||||||
|
ui->AcquisitionIF1->setUnit("Hz");
|
||||||
|
ui->AcquisitionIF1->setPrefixes(" kM");
|
||||||
|
ui->AcquisitionIF1->setPrecision(6);
|
||||||
|
ui->AcquisitionADCRate->setUnit("Hz");
|
||||||
|
ui->AcquisitionADCRate->setPrefixes(" kM");
|
||||||
|
ui->AcquisitionADCRate->setPrecision(6);
|
||||||
|
ui->AcquisitionIF2->setUnit("Hz");
|
||||||
|
ui->AcquisitionIF2->setPrefixes(" kM");
|
||||||
|
ui->AcquisitionIF2->setPrecision(6);
|
||||||
|
auto updateADCRate = [=]() {
|
||||||
|
// update ADC rate, see FPGA protocol for calculation
|
||||||
|
ui->AcquisitionADCRate->setValue(102400000.0 / ui->AcquisitionADCpresc->value());
|
||||||
|
};
|
||||||
|
auto updateIF2 = [=]() {
|
||||||
|
auto ADCrate = ui->AcquisitionADCRate->value();
|
||||||
|
ui->AcquisitionIF2->setValue(ADCrate * ui->AcquisitionADCphaseInc->value() / 4096);
|
||||||
|
};
|
||||||
|
connect(ui->AcquisitionADCpresc, qOverload<int>(&QSpinBox::valueChanged), updateADCRate);
|
||||||
|
connect(ui->AcquisitionADCpresc, qOverload<int>(&QSpinBox::valueChanged), updateIF2);
|
||||||
|
connect(ui->AcquisitionADCphaseInc, qOverload<int>(&QSpinBox::valueChanged), updateIF2);
|
||||||
|
|
||||||
// General page
|
// General page
|
||||||
if(p->TCPoverride) {
|
if(p->TCPoverride) {
|
||||||
@ -136,6 +156,9 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||||||
p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked();
|
p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked();
|
||||||
p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value();
|
p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value();
|
||||||
p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1;
|
p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1;
|
||||||
|
p->Acquisition.IF1 = ui->AcquisitionIF1->value();
|
||||||
|
p->Acquisition.ADCprescaler = ui->AcquisitionADCpresc->value();
|
||||||
|
p->Acquisition.DFTPhaseInc = ui->AcquisitionADCphaseInc->value();
|
||||||
|
|
||||||
p->Graphs.showUnits = ui->GraphsShowUnit->isChecked();
|
p->Graphs.showUnits = ui->GraphsShowUnit->isChecked();
|
||||||
p->Graphs.Color.background = ui->GraphsColorBackground->getColor();
|
p->Graphs.Color.background = ui->GraphsColorBackground->getColor();
|
||||||
@ -156,6 +179,8 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
|
|||||||
});
|
});
|
||||||
|
|
||||||
setInitialGUIState();
|
setInitialGUIState();
|
||||||
|
updateADCRate();
|
||||||
|
updateIF2();
|
||||||
|
|
||||||
connect(ui->AcquisitionUseHarmonic, &QCheckBox::toggled, [=](bool enabled) {
|
connect(ui->AcquisitionUseHarmonic, &QCheckBox::toggled, [=](bool enabled) {
|
||||||
if(enabled) {
|
if(enabled) {
|
||||||
@ -208,6 +233,9 @@ void PreferencesDialog::setInitialGUIState()
|
|||||||
ui->AcquisitionUseDFT->setChecked(p->Acquisition.useDFTinSAmode);
|
ui->AcquisitionUseDFT->setChecked(p->Acquisition.useDFTinSAmode);
|
||||||
ui->AcquisitionDFTlimitRBW->setValue(p->Acquisition.RBWLimitForDFT);
|
ui->AcquisitionDFTlimitRBW->setValue(p->Acquisition.RBWLimitForDFT);
|
||||||
ui->AcquisitionAveragingMode->setCurrentIndex(p->Acquisition.useMedianAveraging ? 1 : 0);
|
ui->AcquisitionAveragingMode->setCurrentIndex(p->Acquisition.useMedianAveraging ? 1 : 0);
|
||||||
|
ui->AcquisitionIF1->setValue(p->Acquisition.IF1);
|
||||||
|
ui->AcquisitionADCpresc->setValue(p->Acquisition.ADCprescaler);
|
||||||
|
ui->AcquisitionADCphaseInc->setValue(p->Acquisition.DFTPhaseInc);
|
||||||
|
|
||||||
ui->GraphsShowUnit->setChecked(p->Graphs.showUnits);
|
ui->GraphsShowUnit->setChecked(p->Graphs.showUnits);
|
||||||
ui->GraphsColorBackground->setColor(p->Graphs.Color.background);
|
ui->GraphsColorBackground->setColor(p->Graphs.Color.background);
|
||||||
|
@ -68,6 +68,11 @@ public:
|
|||||||
bool useDFTinSAmode;
|
bool useDFTinSAmode;
|
||||||
double RBWLimitForDFT;
|
double RBWLimitForDFT;
|
||||||
bool useMedianAveraging;
|
bool useMedianAveraging;
|
||||||
|
|
||||||
|
// advanced, hardware specific settings
|
||||||
|
double IF1;
|
||||||
|
int ADCprescaler;
|
||||||
|
int DFTPhaseInc;
|
||||||
} Acquisition;
|
} Acquisition;
|
||||||
struct {
|
struct {
|
||||||
bool showUnits;
|
bool showUnits;
|
||||||
@ -108,7 +113,7 @@ private:
|
|||||||
QString name;
|
QString name;
|
||||||
QVariant def;
|
QVariant def;
|
||||||
};
|
};
|
||||||
const std::array<SettingDescription, 42> descr = {{
|
const std::array<SettingDescription, 45> descr = {{
|
||||||
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
|
{&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true},
|
||||||
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
|
{&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false},
|
||||||
{&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"},
|
{&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"},
|
||||||
@ -138,6 +143,9 @@ private:
|
|||||||
{&Acquisition.useDFTinSAmode, "Acquisition.useDFTinSAmode", true},
|
{&Acquisition.useDFTinSAmode, "Acquisition.useDFTinSAmode", true},
|
||||||
{&Acquisition.RBWLimitForDFT, "Acquisition.RBWLimitForDFT", 3000.0},
|
{&Acquisition.RBWLimitForDFT, "Acquisition.RBWLimitForDFT", 3000.0},
|
||||||
{&Acquisition.useMedianAveraging, "Acquisition.useMedianAveraging", false},
|
{&Acquisition.useMedianAveraging, "Acquisition.useMedianAveraging", false},
|
||||||
|
{&Acquisition.IF1, "Acquisition.IF1", 62000000},
|
||||||
|
{&Acquisition.ADCprescaler, "Acquisition.ADCprescaler", 128},
|
||||||
|
{&Acquisition.DFTPhaseInc, "Acquisition.DFTPhaseInc", 1280},
|
||||||
{&Graphs.showUnits, "Graphs.showUnits", true},
|
{&Graphs.showUnits, "Graphs.showUnits", true},
|
||||||
{&Graphs.Color.background, "Graphs.Color.background", QColor(Qt::black)},
|
{&Graphs.Color.background, "Graphs.Color.background", QColor(Qt::black)},
|
||||||
{&Graphs.Color.axis, "Graphs.Color.axis", QColor(Qt::white)},
|
{&Graphs.Color.axis, "Graphs.Color.axis", QColor(Qt::white)},
|
||||||
|
@ -83,7 +83,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>3</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">
|
||||||
@ -569,7 +569,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="Acquisition">
|
<widget class="QWidget" name="Acquisition">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_6">
|
<widget class="QGroupBox" name="groupBox_6">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -647,26 +647,141 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Common</string>
|
<string>Common</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QFormLayout" name="formLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||||
<item row="0" column="0">
|
<item>
|
||||||
<widget class="QLabel" name="label_26">
|
<layout class="QFormLayout" name="formLayout_10">
|
||||||
<property name="text">
|
<item row="0" column="0">
|
||||||
<string>Averaging mode:</string>
|
<widget class="QLabel" name="label_26">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Averaging mode:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="AcquisitionAveragingMode">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mean</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Median</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item>
|
||||||
<widget class="QComboBox" name="AcquisitionAveragingMode">
|
<widget class="QGroupBox" name="groupBox_15">
|
||||||
<item>
|
<property name="title">
|
||||||
<property name="text">
|
<string>IF frequencies</string>
|
||||||
<string>Mean</string>
|
</property>
|
||||||
</property>
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
</item>
|
<item>
|
||||||
<item>
|
<widget class="QLabel" name="label_34">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Median</string>
|
<string>This section contains advanced system settings. It is recommended to leave them at default values unless you know what you are doing. Slight changes of the IF frequencies can be used to shift possible spikes to less problematic frequencies. Large changes of these frequencies may severely impact device performance.</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_29">
|
||||||
|
<property name="text">
|
||||||
|
<string>IF 1:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="AcquisitionIF1">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Frequency of the first IF</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_30">
|
||||||
|
<property name="text">
|
||||||
|
<string>ADC prescaler:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="AcquisitionADCpresc">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>ADC prescaler in FPGA. The ADC sample rate is determined by 102.4MHz/prescaler</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>112</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>255</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>128</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_31">
|
||||||
|
<property name="text">
|
||||||
|
<string>ADC sample rate:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="AcquisitionADCRate">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_32">
|
||||||
|
<property name="text">
|
||||||
|
<string>Phase increment:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QSpinBox" name="AcquisitionADCphaseInc">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Phase increment per ADC sample. Together with the ADC sample rate this determines the frequency of the second IF</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>4095</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>1280</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_33">
|
||||||
|
<property name="text">
|
||||||
|
<string>IF 2:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="SIUnitEdit" name="AcquisitionIF2">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -222,6 +222,21 @@ inline void App_Process() {
|
|||||||
Cal::setFrequencyCal(recv_packet.frequencyCorrection.ppm);
|
Cal::setFrequencyCal(recv_packet.frequencyCorrection.ppm);
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
break;
|
break;
|
||||||
|
case Protocol::PacketType::RequestAcquisitionFrequencySettings:
|
||||||
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
|
{
|
||||||
|
Protocol::PacketInfo send;
|
||||||
|
send.type = Protocol::PacketType::AcquisitionFrequencySettings;
|
||||||
|
send.acquisitionFrequencySettings.IF1 = HW::getIF1();
|
||||||
|
send.acquisitionFrequencySettings.ADCprescaler = HW::getADCPrescaler();
|
||||||
|
send.acquisitionFrequencySettings.DFTphaseInc = HW::getDFTPhaseInc();
|
||||||
|
Communication::Send(send);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::AcquisitionFrequencySettings:
|
||||||
|
HW::setAcquisitionFrequencies(recv_packet.acquisitionFrequencySettings);
|
||||||
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// this packet type is not supported
|
// this packet type is not supported
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
|
||||||
|
@ -100,6 +100,7 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
|
|||||||
case PacketType::SourceCalPoint:
|
case PacketType::SourceCalPoint:
|
||||||
case PacketType::ReceiverCalPoint: payload_size = sizeof(packet.amplitudePoint); break;
|
case PacketType::ReceiverCalPoint: payload_size = sizeof(packet.amplitudePoint); break;
|
||||||
case PacketType::FrequencyCorrection: payload_size = sizeof(packet.frequencyCorrection); break;
|
case PacketType::FrequencyCorrection: payload_size = sizeof(packet.frequencyCorrection); break;
|
||||||
|
case PacketType::AcquisitionFrequencySettings: payload_size = sizeof(packet.acquisitionFrequencySettings); break;
|
||||||
case PacketType::Ack:
|
case PacketType::Ack:
|
||||||
case PacketType::PerformFirmwareUpdate:
|
case PacketType::PerformFirmwareUpdate:
|
||||||
case PacketType::ClearFlash:
|
case PacketType::ClearFlash:
|
||||||
@ -109,6 +110,7 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
|
|||||||
case PacketType::RequestReceiverCal:
|
case PacketType::RequestReceiverCal:
|
||||||
case PacketType::SetIdle:
|
case PacketType::SetIdle:
|
||||||
case PacketType::RequestFrequencyCorrection:
|
case PacketType::RequestFrequencyCorrection:
|
||||||
|
case PacketType::RequestAcquisitionFrequencySettings:
|
||||||
// no payload
|
// no payload
|
||||||
break;
|
break;
|
||||||
case PacketType::None:
|
case PacketType::None:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
namespace Protocol {
|
namespace Protocol {
|
||||||
|
|
||||||
static constexpr uint16_t Version = 8;
|
static constexpr uint16_t Version = 9;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
@ -160,6 +160,12 @@ using FrequencyCorrection = struct _frequencycorrection {
|
|||||||
float ppm;
|
float ppm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using AcquisitionFrequencySettings = struct _acquisitionfrequencysettigns {
|
||||||
|
uint32_t IF1;
|
||||||
|
uint8_t ADCprescaler;
|
||||||
|
uint16_t DFTphaseInc;
|
||||||
|
};
|
||||||
|
|
||||||
enum class PacketType : uint8_t {
|
enum class PacketType : uint8_t {
|
||||||
None = 0,
|
None = 0,
|
||||||
Datapoint = 1,
|
Datapoint = 1,
|
||||||
@ -184,6 +190,8 @@ enum class PacketType : uint8_t {
|
|||||||
SetIdle = 20,
|
SetIdle = 20,
|
||||||
RequestFrequencyCorrection = 21,
|
RequestFrequencyCorrection = 21,
|
||||||
FrequencyCorrection = 22,
|
FrequencyCorrection = 22,
|
||||||
|
RequestAcquisitionFrequencySettings = 23,
|
||||||
|
AcquisitionFrequencySettings = 24,
|
||||||
};
|
};
|
||||||
|
|
||||||
using PacketInfo = struct _packetinfo {
|
using PacketInfo = struct _packetinfo {
|
||||||
@ -201,6 +209,7 @@ using PacketInfo = struct _packetinfo {
|
|||||||
SpectrumAnalyzerResult spectrumResult;
|
SpectrumAnalyzerResult spectrumResult;
|
||||||
AmplitudeCorrectionPoint amplitudePoint;
|
AmplitudeCorrectionPoint amplitudePoint;
|
||||||
FrequencyCorrection frequencyCorrection;
|
FrequencyCorrection frequencyCorrection;
|
||||||
|
AcquisitionFrequencySettings acquisitionFrequencySettings;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,6 +21,12 @@ static bool unlevel = false;
|
|||||||
static Protocol::ReferenceSettings ref;
|
static Protocol::ReferenceSettings ref;
|
||||||
static uint32_t lastISR;
|
static uint32_t lastISR;
|
||||||
|
|
||||||
|
static uint32_t IF1 = HW::DefaultIF1;
|
||||||
|
static uint32_t IF2 = HW::DefaultIF2;
|
||||||
|
static uint32_t ADCsamplerate = HW::DefaultADCSamplerate;
|
||||||
|
static uint8_t ADCprescaler = HW::DefaultADCprescaler;
|
||||||
|
static uint16_t DFTphaseInc = HW::DefaultDFTphaseInc;
|
||||||
|
|
||||||
using namespace HWHAL;
|
using namespace HWHAL;
|
||||||
|
|
||||||
static void HaltedCallback() {
|
static void HaltedCallback() {
|
||||||
@ -133,9 +139,9 @@ bool HW::Init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set default ADC samplerate
|
// Set default ADC samplerate
|
||||||
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, HW::ADCprescaler);
|
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, ADCprescaler);
|
||||||
// Set phase increment according to
|
// Set phase increment according to
|
||||||
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::DFTphaseInc);
|
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, DFTphaseInc);
|
||||||
|
|
||||||
Exti::SetCallback(FPGA_INTR_GPIO_Port, FPGA_INTR_Pin, Exti::EdgeType::Rising, Exti::Pull::Down, FPGA_Interrupt);
|
Exti::SetCallback(FPGA_INTR_GPIO_Port, FPGA_INTR_Pin, Exti::EdgeType::Rising, Exti::Pull::Down, FPGA_Interrupt);
|
||||||
|
|
||||||
@ -385,3 +391,33 @@ void HW::Ref::update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HW::setAcquisitionFrequencies(Protocol::AcquisitionFrequencySettings s) {
|
||||||
|
IF1 = s.IF1;
|
||||||
|
ADCprescaler = s.ADCprescaler;
|
||||||
|
DFTphaseInc = s.DFTphaseInc;
|
||||||
|
float ADCrate = (float) FPGA::Clockrate / ADCprescaler;
|
||||||
|
IF2 = ADCrate * DFTphaseInc / 4096;
|
||||||
|
ADCsamplerate = ADCrate;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HW::getIF1() {
|
||||||
|
return IF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HW::getIF2() {
|
||||||
|
return IF2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t HW::getADCRate() {
|
||||||
|
return ADCsamplerate;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t HW::getADCPrescaler() {
|
||||||
|
return ADCprescaler;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t HW::getDFTPhaseInc() {
|
||||||
|
return DFTphaseInc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -35,19 +35,19 @@ static constexpr uint32_t ExtRefOut2Frequency = 10000000;
|
|||||||
static constexpr uint32_t SI5351CPLLAlignedFrequency = 832000000;
|
static constexpr uint32_t SI5351CPLLAlignedFrequency = 832000000;
|
||||||
static constexpr uint32_t SI5351CPLLConstantFrequency = 800000000;
|
static constexpr uint32_t SI5351CPLLConstantFrequency = 800000000;
|
||||||
static constexpr uint32_t FPGAClkInFrequency = 16000000;
|
static constexpr uint32_t FPGAClkInFrequency = 16000000;
|
||||||
static constexpr uint32_t ADCSamplerate = 800000;
|
static constexpr uint32_t DefaultADCSamplerate = 800000;
|
||||||
static constexpr uint32_t IF1 = 62000000;
|
static constexpr uint32_t DefaultIF1 = 62000000;
|
||||||
static constexpr uint32_t IF2 = 250000;
|
static constexpr uint32_t DefaultIF2 = 250000;
|
||||||
static constexpr uint32_t LO1_minFreq = 25000000;
|
static constexpr uint32_t LO1_minFreq = 25000000;
|
||||||
static constexpr uint32_t MaxSamples = 130944;
|
static constexpr uint32_t MaxSamples = 130944;
|
||||||
static constexpr uint32_t MinSamples = 16;
|
static constexpr uint32_t MinSamples = 16;
|
||||||
static constexpr uint32_t PLLRef = 104000000;
|
static constexpr uint32_t PLLRef = 104000000;
|
||||||
static constexpr uint32_t BandSwitchFrequency = 25000000;
|
static constexpr uint32_t BandSwitchFrequency = 25000000;
|
||||||
|
|
||||||
static constexpr uint8_t ADCprescaler = FPGA::Clockrate / ADCSamplerate;
|
static constexpr uint8_t DefaultADCprescaler = FPGA::Clockrate / DefaultADCSamplerate;
|
||||||
static_assert(ADCprescaler * ADCSamplerate == FPGA::Clockrate, "ADCSamplerate can not be reached exactly");
|
static_assert(DefaultADCprescaler * DefaultADCSamplerate == FPGA::Clockrate, "ADCSamplerate can not be reached exactly");
|
||||||
static constexpr uint16_t DFTphaseInc = 4096 * IF2 / ADCSamplerate;
|
static constexpr uint16_t DefaultDFTphaseInc = 4096 * DefaultIF2 / DefaultADCSamplerate;
|
||||||
static_assert(DFTphaseInc * ADCSamplerate == 4096 * IF2, "DFT can not be computed for 2.IF");
|
static_assert(DefaultDFTphaseInc * DefaultADCSamplerate == 4096 * DefaultIF2, "DFT can not be computed for 2.IF");
|
||||||
|
|
||||||
static constexpr uint16_t _fpga_div = SI5351CPLLConstantFrequency / FPGAClkInFrequency;
|
static constexpr uint16_t _fpga_div = SI5351CPLLConstantFrequency / FPGAClkInFrequency;
|
||||||
static_assert(_fpga_div * FPGAClkInFrequency == SI5351CPLLConstantFrequency && _fpga_div >= 6 && _fpga_div <= 254 && (_fpga_div & 0x01) == 0, "Unable to generate FPGA clock input frequency");
|
static_assert(_fpga_div * FPGAClkInFrequency == SI5351CPLLConstantFrequency && _fpga_div >= 6 && _fpga_div <= 254 && (_fpga_div & 0x01) == 0, "Unable to generate FPGA clock input frequency");
|
||||||
@ -83,13 +83,13 @@ static constexpr Protocol::DeviceInfo Info = {
|
|||||||
.temp_MCU = 0,
|
.temp_MCU = 0,
|
||||||
.limits_minFreq = 0,
|
.limits_minFreq = 0,
|
||||||
.limits_maxFreq = 6000000000,
|
.limits_maxFreq = 6000000000,
|
||||||
.limits_minIFBW = ADCSamplerate / MaxSamples,
|
.limits_minIFBW = DefaultADCSamplerate / MaxSamples,
|
||||||
.limits_maxIFBW = ADCSamplerate / MinSamples,
|
.limits_maxIFBW = DefaultADCSamplerate / MinSamples,
|
||||||
.limits_maxPoints = FPGA::MaxPoints,
|
.limits_maxPoints = FPGA::MaxPoints,
|
||||||
.limits_cdbm_min = -4000,
|
.limits_cdbm_min = -4000,
|
||||||
.limits_cdbm_max = 0,
|
.limits_cdbm_max = 0,
|
||||||
.limits_minRBW = (uint32_t) (ADCSamplerate * 2.23f / MaxSamples),
|
.limits_minRBW = (uint32_t) (DefaultADCSamplerate * 2.23f / MaxSamples),
|
||||||
.limits_maxRBW = (uint32_t) (ADCSamplerate * 2.23f / MinSamples),
|
.limits_maxRBW = (uint32_t) (DefaultADCSamplerate * 2.23f / MinSamples),
|
||||||
.limits_maxAmplitudePoints = Cal::maxPoints,
|
.limits_maxAmplitudePoints = Cal::maxPoints,
|
||||||
.limits_maxFreqHarmonic = 18000000000,
|
.limits_maxFreqHarmonic = 18000000000,
|
||||||
};
|
};
|
||||||
@ -129,4 +129,12 @@ namespace Ref {
|
|||||||
void update();
|
void update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acquisition frequency settings
|
||||||
|
void setAcquisitionFrequencies(Protocol::AcquisitionFrequencySettings s);
|
||||||
|
uint32_t getIF1();
|
||||||
|
uint32_t getIF2();
|
||||||
|
uint32_t getADCRate();
|
||||||
|
uint8_t getADCPrescaler();
|
||||||
|
uint16_t getDFTPhaseInc();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,8 @@ static void StartNextSample() {
|
|||||||
port2Measurement[i] = std::numeric_limits<float>::max();
|
port2Measurement[i] = std::numeric_limits<float>::max();
|
||||||
}
|
}
|
||||||
// Use default LO frequencies
|
// Use default LO frequencies
|
||||||
LO1freq = freq + HW::IF1;
|
LO1freq = freq + HW::getIF1();
|
||||||
LO2freq = HW::IF1 - HW::IF2;
|
LO2freq = HW::getIF1() - HW::getIF2();
|
||||||
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, 112);
|
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, 112);
|
||||||
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, 1120);
|
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, 1120);
|
||||||
negativeDFT = true;
|
negativeDFT = true;
|
||||||
@ -88,17 +88,17 @@ static void StartNextSample() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
LO2freq = HW::IF1 - HW::IF2;
|
LO2freq = HW::getIF1() - HW::getIF2();
|
||||||
negativeDFT = false;
|
negativeDFT = false;
|
||||||
// Shift first LO to other side
|
// Shift first LO to other side
|
||||||
// depending on the measurement frequency this is not possible or additive mixing has to be used
|
// depending on the measurement frequency this is not possible or additive mixing has to be used
|
||||||
if(freq >= HW::IF1 + HW::LO1_minFreq) {
|
if(freq >= HW::getIF1() + HW::LO1_minFreq) {
|
||||||
// frequency is high enough to shift 1.LO below measurement frequency
|
// frequency is high enough to shift 1.LO below measurement frequency
|
||||||
LO1freq = freq - HW::IF1;
|
LO1freq = freq - HW::getIF1();
|
||||||
break;
|
break;
|
||||||
} else if(freq <= HW::IF1 - HW::LO1_minFreq) {
|
} else if(freq <= HW::getIF1() - HW::LO1_minFreq) {
|
||||||
// frequency is low enough to add 1.LO to measurement frequency
|
// frequency is low enough to add 1.LO to measurement frequency
|
||||||
LO1freq = HW::IF1 - freq;
|
LO1freq = HW::getIF1() - freq;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// unable to reach required frequency with 1.LO, skip this signal ID step
|
// unable to reach required frequency with 1.LO, skip this signal ID step
|
||||||
@ -106,22 +106,22 @@ static void StartNextSample() {
|
|||||||
/* no break */
|
/* no break */
|
||||||
case 2:
|
case 2:
|
||||||
// Shift second LOs to other side
|
// Shift second LOs to other side
|
||||||
LO1freq = freq + HW::IF1;
|
LO1freq = freq + HW::getIF1();
|
||||||
LO2freq = HW::IF1 + HW::IF2;
|
LO2freq = HW::getIF1() + HW::getIF2();
|
||||||
negativeDFT = false;
|
negativeDFT = false;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// Shift both LO to other side
|
// Shift both LO to other side
|
||||||
LO2freq = HW::IF1 + HW::IF2;
|
LO2freq = HW::getIF1() + HW::getIF2();
|
||||||
negativeDFT = true;
|
negativeDFT = true;
|
||||||
// depending on the measurement frequency this is not possible or additive mixing has to be used
|
// depending on the measurement frequency this is not possible or additive mixing has to be used
|
||||||
if(freq >= HW::IF1 + HW::LO1_minFreq) {
|
if(freq >= HW::getIF1() + HW::LO1_minFreq) {
|
||||||
// frequency is high enough to shift 1.LO below measurement frequency
|
// frequency is high enough to shift 1.LO below measurement frequency
|
||||||
LO1freq = freq - HW::IF1;
|
LO1freq = freq - HW::getIF1();
|
||||||
break;
|
break;
|
||||||
} else if(freq <= HW::IF1 - HW::LO1_minFreq) {
|
} else if(freq <= HW::getIF1() - HW::LO1_minFreq) {
|
||||||
// frequency is low enough to add 1.LO to measurement frequency
|
// frequency is low enough to add 1.LO to measurement frequency
|
||||||
LO1freq = HW::IF1 - freq;
|
LO1freq = HW::getIF1() - freq;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// unable to reach required frequency with 1.LO, skip this signal ID step
|
// unable to reach required frequency with 1.LO, skip this signal ID step
|
||||||
@ -130,8 +130,8 @@ static void StartNextSample() {
|
|||||||
default:
|
default:
|
||||||
// Use default frequencies with different ADC samplerate to remove images in final IF
|
// Use default frequencies with different ADC samplerate to remove images in final IF
|
||||||
negativeDFT = true;
|
negativeDFT = true;
|
||||||
LO1freq = freq + HW::IF1;
|
LO1freq = freq + HW::getIF1();
|
||||||
LO2freq = HW::IF1 - HW::IF2;
|
LO2freq = HW::getIF1() - HW::getIF2();
|
||||||
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, signalIDprescalers[signalIDstep-4]);
|
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, signalIDprescalers[signalIDstep-4]);
|
||||||
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, (uint16_t) signalIDprescalers[signalIDstep-4] * 10);
|
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, (uint16_t) signalIDprescalers[signalIDstep-4] * 10);
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ static void StartNextSample() {
|
|||||||
}
|
}
|
||||||
if (s.UseDFT) {
|
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::getIF2();
|
||||||
if(negativeDFT) {
|
if(negativeDFT) {
|
||||||
// needs to look below the start frequency, shift start
|
// needs to look below the start frequency, shift start
|
||||||
start -= spacing * (DFTpoints - 1);
|
start -= spacing * (DFTpoints - 1);
|
||||||
@ -172,13 +172,15 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
|||||||
s = settings;
|
s = settings;
|
||||||
HW::SetMode(HW::Mode::SA);
|
HW::SetMode(HW::Mode::SA);
|
||||||
FPGA::SetMode(FPGA::Mode::FPGA);
|
FPGA::SetMode(FPGA::Mode::FPGA);
|
||||||
|
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, HW::getADCPrescaler());
|
||||||
|
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::getDFTPhaseInc());
|
||||||
// in almost all cases a full sweep requires more points than the FPGA can handle at a time
|
// in almost all cases a full sweep requires more points than the FPGA can handle at a time
|
||||||
// individually start each point and do the sweep in the uC
|
// individually start each point and do the sweep in the uC
|
||||||
FPGA::SetNumberOfPoints(1);
|
FPGA::SetNumberOfPoints(1);
|
||||||
// calculate required samples per measurement for requested RBW
|
// calculate required samples per measurement for requested RBW
|
||||||
// see https://www.tek.com/blog/window-functions-spectrum-analyzers for window factors
|
// see https://www.tek.com/blog/window-functions-spectrum-analyzers for window factors
|
||||||
constexpr float window_factors[4] = {0.89f, 2.23f, 1.44f, 3.77f};
|
constexpr float window_factors[4] = {0.89f, 2.23f, 1.44f, 3.77f};
|
||||||
sampleNum = HW::ADCSamplerate * window_factors[s.WindowType] / s.RBW;
|
sampleNum = HW::getADCRate() * window_factors[s.WindowType] / s.RBW;
|
||||||
// round up to next multiple of 16
|
// round up to next multiple of 16
|
||||||
if(sampleNum%16) {
|
if(sampleNum%16) {
|
||||||
sampleNum += 16 - sampleNum%16;
|
sampleNum += 16 - sampleNum%16;
|
||||||
@ -186,7 +188,7 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
|
|||||||
if(sampleNum >= HW::MaxSamples) {
|
if(sampleNum >= HW::MaxSamples) {
|
||||||
sampleNum = HW::MaxSamples;
|
sampleNum = HW::MaxSamples;
|
||||||
}
|
}
|
||||||
actualRBW = HW::ADCSamplerate * window_factors[s.WindowType] / sampleNum;
|
actualRBW = HW::getADCRate() * window_factors[s.WindowType] / sampleNum;
|
||||||
FPGA::SetSamplesPerPoint(sampleNum);
|
FPGA::SetSamplesPerPoint(sampleNum);
|
||||||
// calculate amount of required points
|
// calculate amount of required points
|
||||||
points = 2 * (s.f_stop - s.f_start) / actualRBW;
|
points = 2 * (s.f_stop - s.f_start) / actualRBW;
|
||||||
|
@ -44,8 +44,8 @@ static uint16_t IFTableIndexCnt = 0;
|
|||||||
static constexpr float alternativeSamplerate = 914285.7143f;
|
static constexpr float alternativeSamplerate = 914285.7143f;
|
||||||
static constexpr uint8_t alternativePrescaler = 102400000UL / alternativeSamplerate;
|
static constexpr uint8_t alternativePrescaler = 102400000UL / alternativeSamplerate;
|
||||||
static_assert(alternativePrescaler * alternativeSamplerate == 102400000UL, "alternative ADCSamplerate can not be reached exactly");
|
static_assert(alternativePrescaler * alternativeSamplerate == 102400000UL, "alternative ADCSamplerate can not be reached exactly");
|
||||||
static constexpr uint16_t alternativePhaseInc = 4096 * HW::IF2 / alternativeSamplerate;
|
static constexpr uint16_t alternativePhaseInc = 4096 * HW::DefaultIF2 / alternativeSamplerate;
|
||||||
static_assert(alternativePhaseInc * alternativeSamplerate == 4096 * HW::IF2, "DFT can not be computed for 2.IF when using alternative samplerate");
|
static_assert(alternativePhaseInc * alternativeSamplerate == 4096 * HW::DefaultIF2, "DFT can not be computed for 2.IF when using alternative samplerate");
|
||||||
|
|
||||||
// Constants for USB buffer overflow prevention
|
// Constants for USB buffer overflow prevention
|
||||||
static constexpr uint16_t maxPointsBetweenHalts = 40;
|
static constexpr uint16_t maxPointsBetweenHalts = 40;
|
||||||
@ -84,6 +84,8 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
}
|
}
|
||||||
// Abort possible active sweep first
|
// Abort possible active sweep first
|
||||||
FPGA::SetMode(FPGA::Mode::FPGA);
|
FPGA::SetMode(FPGA::Mode::FPGA);
|
||||||
|
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, HW::getADCPrescaler());
|
||||||
|
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::getDFTPhaseInc());
|
||||||
if(settings.points > FPGA::MaxPoints) {
|
if(settings.points > FPGA::MaxPoints) {
|
||||||
settings.points = FPGA::MaxPoints;
|
settings.points = FPGA::MaxPoints;
|
||||||
}
|
}
|
||||||
@ -92,12 +94,12 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
logMultiplier = pow((double) settings.f_stop / settings.f_start, 1.0 / (settings.points-1));
|
logMultiplier = pow((double) settings.f_stop / settings.f_start, 1.0 / (settings.points-1));
|
||||||
// Configure sweep
|
// Configure sweep
|
||||||
FPGA::SetNumberOfPoints(settings.points);
|
FPGA::SetNumberOfPoints(settings.points);
|
||||||
uint32_t samplesPerPoint = (HW::ADCSamplerate / s.if_bandwidth);
|
uint32_t samplesPerPoint = (HW::getADCRate() / s.if_bandwidth);
|
||||||
// round up to next multiple of 16 (16 samples are spread across 5 IF2 periods)
|
// round up to next multiple of 16 (16 samples are spread across 5 IF2 periods)
|
||||||
if(samplesPerPoint%16) {
|
if(samplesPerPoint%16) {
|
||||||
samplesPerPoint += 16 - samplesPerPoint%16;
|
samplesPerPoint += 16 - samplesPerPoint%16;
|
||||||
}
|
}
|
||||||
actualBandwidth = HW::ADCSamplerate / samplesPerPoint;
|
actualBandwidth = HW::getADCRate() / samplesPerPoint;
|
||||||
// has to be one less than actual number of samples
|
// has to be one less than actual number of samples
|
||||||
FPGA::SetSamplesPerPoint(samplesPerPoint);
|
FPGA::SetSamplesPerPoint(samplesPerPoint);
|
||||||
|
|
||||||
@ -129,7 +131,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
|
|
||||||
FPGA::WriteMAX2871Default(Source.GetRegisters());
|
FPGA::WriteMAX2871Default(Source.GetRegisters());
|
||||||
|
|
||||||
uint32_t last_LO2 = HW::IF1 - HW::IF2;
|
uint32_t last_LO2 = HW::getIF1() - HW::getIF2();
|
||||||
Si5351.SetCLK(SiChannel::Port1LO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
Si5351.SetCLK(SiChannel::Port1LO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
||||||
Si5351.SetCLK(SiChannel::Port2LO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
Si5351.SetCLK(SiChannel::Port2LO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
||||||
Si5351.SetCLK(SiChannel::RefLO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
Si5351.SetCLK(SiChannel::RefLO2, last_LO2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
||||||
@ -180,7 +182,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
// additional halt before first highband point to enable highband source
|
// additional halt before first highband point to enable highband source
|
||||||
needs_halt = true;
|
needs_halt = true;
|
||||||
}
|
}
|
||||||
uint64_t LOFreq = freq + HW::IF1;
|
uint64_t LOFreq = freq + HW::getIF1();
|
||||||
if(harmonic_mixing) {
|
if(harmonic_mixing) {
|
||||||
LOFreq /= LOHarmonic;
|
LOFreq /= LOHarmonic;
|
||||||
}
|
}
|
||||||
@ -191,7 +193,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
}
|
}
|
||||||
uint32_t actualFirstIF = actualLO1 - actualSourceFreq;
|
uint32_t actualFirstIF = actualLO1 - actualSourceFreq;
|
||||||
uint32_t actualFinalIF = actualFirstIF - last_LO2;
|
uint32_t actualFinalIF = actualFirstIF - last_LO2;
|
||||||
uint32_t IFdeviation = abs(actualFinalIF - HW::IF2);
|
uint32_t IFdeviation = abs(actualFinalIF - HW::getIF2());
|
||||||
bool needs_LO2_shift = false;
|
bool needs_LO2_shift = false;
|
||||||
if(IFdeviation > actualBandwidth / 2) {
|
if(IFdeviation > actualBandwidth / 2) {
|
||||||
needs_LO2_shift = true;
|
needs_LO2_shift = true;
|
||||||
@ -204,7 +206,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
if(IFTableIndexCnt < IFTableNumEntries - 1) {
|
if(IFTableIndexCnt < IFTableNumEntries - 1) {
|
||||||
// Configure LO2 for the changed IF1. This is not necessary right now but it will generate
|
// Configure LO2 for the changed IF1. This is not necessary right now but it will generate
|
||||||
// the correct clock settings
|
// the correct clock settings
|
||||||
last_LO2 = actualFirstIF - HW::IF2;
|
last_LO2 = actualFirstIF - HW::getIF2();
|
||||||
LOG_INFO("Changing 2.LO to %lu at point %lu (%lu%06luHz) to reach correct 2.IF frequency (1.LO: %lu%06luHz, 1.IF: %lu%06luHz)",
|
LOG_INFO("Changing 2.LO to %lu at point %lu (%lu%06luHz) to reach correct 2.IF frequency (1.LO: %lu%06luHz, 1.IF: %lu%06luHz)",
|
||||||
last_LO2, i, (uint32_t ) (freq / 1000000),
|
last_LO2, i, (uint32_t ) (freq / 1000000),
|
||||||
(uint32_t ) (freq % 1000000), (uint32_t ) (actualLO1 / 1000000),
|
(uint32_t ) (freq % 1000000), (uint32_t ) (actualLO1 / 1000000),
|
||||||
@ -212,7 +214,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
(uint32_t ) (actualFirstIF % 1000000));
|
(uint32_t ) (actualFirstIF % 1000000));
|
||||||
} else {
|
} else {
|
||||||
// last entry in IF table, revert LO2 to default
|
// last entry in IF table, revert LO2 to default
|
||||||
last_LO2 = HW::IF1 - HW::IF2;
|
last_LO2 = HW::getIF1() - HW::getIF2();
|
||||||
}
|
}
|
||||||
Si5351.SetCLK(SiChannel::RefLO2, last_LO2,
|
Si5351.SetCLK(SiChannel::RefLO2, last_LO2,
|
||||||
Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
||||||
@ -259,10 +261,10 @@ bool VNA::Setup(Protocol::SweepSettings s) {
|
|||||||
last_lowband = lowband;
|
last_lowband = lowband;
|
||||||
}
|
}
|
||||||
// revert clk configuration to previous value (might have been changed in sweep calculation)
|
// revert clk configuration to previous value (might have been changed in sweep calculation)
|
||||||
Si5351.SetCLK(SiChannel::RefLO2, HW::IF1 - HW::IF2, Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
Si5351.SetCLK(SiChannel::RefLO2, HW::getIF1() - HW::getIF2(), Si5351C::PLL::B, Si5351C::DriveStrength::mA2);
|
||||||
Si5351.ResetPLL(Si5351C::PLL::B);
|
Si5351.ResetPLL(Si5351C::PLL::B);
|
||||||
// Enable mixers/amplifier/PLLs
|
// Enable mixers/amplifier/PLLs
|
||||||
FPGA::SetWindow(FPGA::Window::None);
|
FPGA::SetWindow(FPGA::Window::Kaiser);
|
||||||
FPGA::Enable(FPGA::Periphery::Port1Mixer);
|
FPGA::Enable(FPGA::Periphery::Port1Mixer);
|
||||||
FPGA::Enable(FPGA::Periphery::Port2Mixer);
|
FPGA::Enable(FPGA::Periphery::Port2Mixer);
|
||||||
FPGA::Enable(FPGA::Periphery::RefMixer);
|
FPGA::Enable(FPGA::Periphery::RefMixer);
|
||||||
@ -399,14 +401,17 @@ void VNA::SweepHalted() {
|
|||||||
Delay::us(1300);
|
Delay::us(1300);
|
||||||
}
|
}
|
||||||
|
|
||||||
// At low frequencies the 1.LO feedtrough mixes with the 2.LO in the second mixer.
|
// At low frequencies the 1.LO feedthrough mixes with the 2.LO in the second mixer.
|
||||||
// Depending on the stimulus frequency, the resulting mixing product might alias to the 2.IF
|
// Depending on the stimulus frequency, the resulting mixing product might alias to the 2.IF
|
||||||
// in the ADC which causes a spike. Check for this and shift the ADC sampling frequency if necessary
|
// in the ADC which causes a spike. Check for this and shift the ADC sampling frequency if necessary
|
||||||
uint32_t LO_mixing = (HW::IF1 + frequency) - (HW::IF1 - HW::IF2);
|
|
||||||
if(abs(Util::Alias(LO_mixing, HW::ADCSamplerate) - HW::IF2) <= actualBandwidth * 2) {
|
uint32_t LO_mixing = (HW::getIF1() + frequency) - (HW::getIF1() - HW::getIF2());
|
||||||
|
if(abs(Util::Alias(LO_mixing, HW::getADCRate()) - HW::getIF2()) <= actualBandwidth * 2) {
|
||||||
// the image is in or near the IF bandwidth and would cause a peak
|
// the image is in or near the IF bandwidth and would cause a peak
|
||||||
// Use a slightly different ADC samplerate
|
// Use a slightly different ADC sample rate if possible
|
||||||
adcShiftRequired = true;
|
if(HW::getIF2() == HW::DefaultIF2) {
|
||||||
|
adcShiftRequired = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if(!FPGA::IsEnabled(FPGA::Periphery::SourceRF)){
|
} else if(!FPGA::IsEnabled(FPGA::Periphery::SourceRF)){
|
||||||
// first sweep point in highband is also halted, disable lowband source
|
// first sweep point in highband is also halted, disable lowband source
|
||||||
@ -420,8 +425,8 @@ void VNA::SweepHalted() {
|
|||||||
adcShifted = true;
|
adcShifted = true;
|
||||||
} else if(adcShifted) {
|
} else if(adcShifted) {
|
||||||
// reset to default value
|
// reset to default value
|
||||||
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, HW::ADCprescaler);
|
FPGA::WriteRegister(FPGA::Reg::ADCPrescaler, HW::getADCPrescaler());
|
||||||
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::DFTphaseInc);
|
FPGA::WriteRegister(FPGA::Reg::PhaseIncrement, HW::getDFTPhaseInc());
|
||||||
adcShifted = false;
|
adcShifted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user