diff --git a/Documentation/DeveloperInfo/FPGA_protocol.pdf b/Documentation/DeveloperInfo/FPGA_protocol.pdf
index d2a9522..ada7569 100644
Binary files a/Documentation/DeveloperInfo/FPGA_protocol.pdf and b/Documentation/DeveloperInfo/FPGA_protocol.pdf differ
diff --git a/Documentation/DeveloperInfo/FPGA_protocol.tex b/Documentation/DeveloperInfo/FPGA_protocol.tex
index 3db4964..4d8e55d 100644
--- a/Documentation/DeveloperInfo/FPGA_protocol.tex
+++ b/Documentation/DeveloperInfo/FPGA_protocol.tex
@@ -348,9 +348,9 @@ The register contains the number of points per sweep negative one, e.g. set to 1
\rwbits{9}{2}{Window[1:0]}
\rwbits{11}{1}{SCEN}
\rwbits{12}{1}{LCEN}
-\robits{13}{2}{reserved}
+\robits{13}{1}{reserved}
%\rwbits{13}{1}{EXP2}
-%\rwbits{14}{1}{EXP1}
+\rwbits{14}{1}{SYM}
\rwbits{15}{1}{PSEN}
\end{tikzpicture}
\end{center}
@@ -378,7 +378,7 @@ Setting & Window type\\
\item \textbf{SCEN:}{Source chip enable}
\item \textbf{LCEN:}{LO chip enable}
%\item \textbf{EXP1:}{Excite Port1 during sweep}
-%\item \textbf{EXP2:}{Excite Port2 during sweep}
+\item \textbf{SYM:}{Sync master, see also section~\ref{synchronization}. If multiple devices are combined, exactly one must have this bit set.}
\item \textbf{PSEN:}{Port switch enable}
\end{itemize}
@@ -731,7 +731,7 @@ The FPGA supports synchronization of the sweep across multiple devices. This fea
The synchronization works by delaying sampling until the stimulus signal is present, even when generated by another device. For each sampling stage, performs the following steps:
\begin{itemize}
-\item When the device generates the stimulus signal in the current phase:
+\item When the device is the synchronization master (SYM bit set):
\begin{itemize}
\item Set up source and 1.LO PLLs
\item If applicable: wait for the "resume sweep" command
@@ -741,7 +741,7 @@ The synchronization works by delaying sampling until the stimulus signal is pres
\item Set the trigger output to low
\item Wait for low level on trigger input
\end{itemize}
-\item When the device does not generate the stimulus signal in the current phase:
+\item When the device is the synchronization slave (SYM bit not set):
\begin{itemize}
\item Set 1.LO PLL
\item If applicable: wait for the "resume sweep" command
diff --git a/FPGA/VNA/SPIConfig.vhd b/FPGA/VNA/SPIConfig.vhd
index 351a917..02077ce 100644
--- a/FPGA/VNA/SPIConfig.vhd
+++ b/FPGA/VNA/SPIConfig.vhd
@@ -52,6 +52,7 @@ entity SPICommands is
NSAMPLES : out STD_LOGIC_VECTOR (12 downto 0);
STAGES : out STD_LOGIC_VECTOR (2 downto 0);
SYNC_ENABLED : out STD_LOGIC;
+ SYNC_MASTER : out STD_LOGIC;
PORT1_STAGE : out STD_LOGIC_VECTOR (2 downto 0);
PORT2_STAGE : out STD_LOGIC_VECTOR (2 downto 0);
PORT1_EN : out STD_LOGIC;
@@ -250,6 +251,7 @@ begin
WINDOW_SETTING <= spi_buf_out(6 downto 5);
SOURCE_CE_EN <= spi_buf_out(4);
LO_CE_EN <= spi_buf_out(3);
+ SYNC_MASTER <= spi_buf_out(1);
when 4 => ADC_PRESCALER <= spi_buf_out(7 downto 0);
when 5 => ADC_PHASEINC <= spi_buf_out(11 downto 0);
when 6 => STAGES <= spi_buf_out(15 downto 13);
diff --git a/FPGA/VNA/Sweep.vhd b/FPGA/VNA/Sweep.vhd
index db63133..5e08670 100644
--- a/FPGA/VNA/Sweep.vhd
+++ b/FPGA/VNA/Sweep.vhd
@@ -62,9 +62,12 @@ entity Sweep is
SWEEP_RESUME : in STD_LOGIC;
SYNC_ENABLED : in STD_LOGIC;
+ SYNC_MASTER : in STD_LOGIC;
TRIGGER_IN : in STD_LOGIC;
TRIGGER_OUT : out STD_LOGIC;
+ NEW_DATA : out STD_LOGIC;
+
ATTENUATOR : out STD_LOGIC_VECTOR(6 downto 0);
SOURCE_FILTER : out STD_LOGIC_VECTOR(1 downto 0);
@@ -85,7 +88,7 @@ end Sweep;
architecture Behavioral of Sweep is
signal point_cnt : unsigned(12 downto 0);
- type Point_states is (TriggerSetup, SettingUp, Settling, WaitTriggerHigh, Exciting, WaitTriggerLow, SamplingDone, NextPoint, Done);
+ type Point_states is (WaitInitialLow, TriggerSetup, SettingUp, Settling, WaitTriggerHigh, Exciting, WaitTriggerLow, SamplingDone, NextPoint, Done);
signal state : Point_states;
signal settling_cnt : unsigned(15 downto 0);
signal settling_time : unsigned(15 downto 0);
@@ -153,7 +156,7 @@ begin
if RESET = '1' then
point_cnt <= (others => '0');
stage_cnt <= (others => '0');
- state <= WaitTriggerLow;
+ state <= WaitInitialLow;
START_SAMPLING <= '0';
RELOAD_PLL_REGS <= '0';
SWEEP_HALTED <= '0';
@@ -164,19 +167,10 @@ begin
source_active <= '0';
else
case state is
- when WaitTriggerLow =>
- if SYNC_ENABLED = '1' and (std_logic_vector(stage_cnt) = PORT1_STAGE or std_logic_vector(stage_cnt) = PORT2_STAGE) then
- TRIGGER_OUT <= '0';
- end if;
+ when WaitInitialLow =>
+ TRIGGER_OUT <= '0';
if TRIGGER_IN = '0' or SYNC_ENABLED = '0' then
- TRIGGER_OUT <= '0';
- if stage_cnt = 0 then
- -- first stage in point, need to trigger PLL setup
- state <= TriggerSetup;
- else
- -- PLLs already configured correctly
- state <= SettingUp;
- end if;
+ state <= TriggerSetup;
end if;
when TriggerSetup =>
RELOAD_PLL_REGS <= '1';
@@ -221,7 +215,7 @@ begin
else
-- need to wait for the trigger
state <= WaitTriggerHigh;
- if SYNC_ENABLED = '1' and (std_logic_vector(stage_cnt) = PORT1_STAGE or std_logic_vector(stage_cnt) = PORT2_STAGE) then
+ if SYNC_MASTER = '1' then
-- this device generates the stimulus signal, it needs start the trigger itself
TRIGGER_OUT <= '1';
end if;
@@ -238,14 +232,25 @@ begin
-- wait for sampling to finish
START_SAMPLING <= '0';
if SAMPLING_BUSY = '0' then
+ NEW_DATA <= '1';
RESULT_INDEX <= std_logic_vector(stage_cnt) & std_logic_vector(point_cnt);
+ state <= WaitTriggerLow;
+ end if;
+ when WaitTriggerLow =>
+ NEW_DATA <= '0';
+ if SYNC_MASTER = '1' then
+ TRIGGER_OUT <= '0';
+ end if;
+ if TRIGGER_IN = '0' or SYNC_ENABLED = '0' then
+ TRIGGER_OUT <= '0';
state <= SamplingDone;
end if;
when SamplingDone =>
+ NEW_DATA <= '0';
if stage_cnt < unsigned(STAGES) then
stage_cnt <= stage_cnt + 1;
-- can go directly to preperation for next stage
- state <= WaitTriggerLow;
+ state <= Settling;
else
state <= NextPoint;
end if;
@@ -254,7 +259,7 @@ begin
if point_cnt < unsigned(NPOINTS) then
point_cnt <= point_cnt + 1;
stage_cnt <= (others => '0');
- state <= WaitTriggerLow;
+ state <= TriggerSetup;
else
point_cnt <= (others => '0');
state <= Done;
diff --git a/FPGA/VNA/VNA.gise b/FPGA/VNA/VNA.gise
index 261e9bf..e406c7a 100644
--- a/FPGA/VNA/VNA.gise
+++ b/FPGA/VNA/VNA.gise
@@ -224,7 +224,7 @@
-
+
@@ -253,7 +253,7 @@
-
+
@@ -275,7 +275,7 @@
-
+
@@ -284,7 +284,7 @@
-
+
@@ -298,7 +298,7 @@
-
+
@@ -312,8 +312,9 @@
-
+
+
@@ -365,7 +366,7 @@
-
+
diff --git a/FPGA/VNA/top.bin b/FPGA/VNA/top.bin
index ff682eb..6117ec7 100644
Binary files a/FPGA/VNA/top.bin and b/FPGA/VNA/top.bin differ
diff --git a/FPGA/VNA/top.vhd b/FPGA/VNA/top.vhd
index bccf536..a719d60 100644
--- a/FPGA/VNA/top.vhd
+++ b/FPGA/VNA/top.vhd
@@ -139,8 +139,10 @@ architecture Behavioral of top is
SWEEP_HALTED : out STD_LOGIC;
SWEEP_RESUME : in STD_LOGIC;
SYNC_ENABLED : in STD_LOGIC;
+ SYNC_MASTER : in STD_LOGIC;
TRIGGER_IN : in STD_LOGIC;
TRIGGER_OUT : out STD_LOGIC;
+ NEW_DATA : out STD_LOGIC;
ATTENUATOR : OUT std_logic_vector(6 downto 0);
SOURCE_FILTER : OUT std_logic_vector(1 downto 0);
STAGES : in STD_LOGIC_VECTOR (2 downto 0);
@@ -253,6 +255,7 @@ architecture Behavioral of top is
NSAMPLES : OUT std_logic_vector(12 downto 0);
STAGES : out STD_LOGIC_VECTOR (2 downto 0);
SYNC_ENABLED : out STD_LOGIC;
+ SYNC_MASTER : out STD_LOGIC;
PORT1_STAGE : out STD_LOGIC_VECTOR (2 downto 0);
PORT2_STAGE : out STD_LOGIC_VECTOR (2 downto 0);
PORT1_EN : out STD_LOGIC;
@@ -376,6 +379,7 @@ architecture Behavioral of top is
signal sweep_points : std_logic_vector(12 downto 0);
signal sweep_stages : STD_LOGIC_VECTOR (2 downto 0);
signal sweep_sync_enabled: STD_LOGIC;
+ signal sweep_sync_master : STD_LOGIC;
signal sweep_port1_stage : STD_LOGIC_VECTOR (2 downto 0);
signal sweep_port2_stage : STD_LOGIC_VECTOR (2 downto 0);
signal sweep_config_data : std_logic_vector(95 downto 0);
@@ -395,6 +399,9 @@ architecture Behavioral of top is
signal sweep_excite_port1 : std_logic;
signal sweep_excite_port2 : std_logic;
+ signal sweep_trigger_in : std_logic;
+ signal sweep_trigger_out : std_logic;
+
-- Configuration signals
signal settling_time : std_logic_vector(15 downto 0);
signal def_reg_4 : std_logic_vector(31 downto 0);
@@ -531,7 +538,21 @@ begin
CLK => clk_pll,
SYNC_IN => MCU_NSS,
SYNC_OUT => nss_sync
- );
+ );
+ Sync_TRIGGER_IN : Synchronizer
+ GENERIC MAP(stages => 2)
+ PORT MAP(
+ CLK => clk_pll,
+ SYNC_IN => TRIGGER_IN,
+ SYNC_OUT => sweep_trigger_in
+ );
+ Sync_TRIGGER_OUT : Synchronizer
+ GENERIC MAP(stages => 2)
+ PORT MAP(
+ CLK => clk_pll,
+ SYNC_IN => sweep_trigger_out,
+ SYNC_OUT => TRIGGER_OUT
+ );
Source: MAX2871
@@ -644,7 +665,7 @@ begin
REF => ref_windowed,
ADC_START => adc_trigger_sample,
NEW_SAMPLE => windowing_ready,
- DONE => sampling_done,
+ DONE => open,
PRE_DONE => open,
START => sampling_start,
SAMPLES => sampling_samples,
@@ -689,8 +710,10 @@ begin
SWEEP_HALTED => sweep_halted,
SWEEP_RESUME => sweep_resume,
SYNC_ENABLED => sweep_sync_enabled,
- TRIGGER_IN => TRIGGER_IN,
- TRIGGER_OUT => TRIGGER_OUT,
+ SYNC_MASTER => sweep_sync_master,
+ TRIGGER_IN => sweep_trigger_in,
+ TRIGGER_OUT => sweep_trigger_out,
+ NEW_DATA => sampling_done,
ATTENUATOR => sweep_attenuator,
SOURCE_FILTER => sweep_source_filter,
STAGES => sweep_stages,
@@ -772,6 +795,7 @@ begin
SWEEP_RESUME => sweep_resume,
STAGES => sweep_stages,
SYNC_ENABLED => sweep_sync_enabled,
+ SYNC_MASTER => sweep_sync_master,
PORT1_STAGE => sweep_port1_stage,
PORT2_STAGE => sweep_port2_stage,
SPI_OVERWRITE_ENABLED => HW_overwrite_enabled,
diff --git a/Software/PC_Application/Calibration/amplitudecaldialog.cpp b/Software/PC_Application/Calibration/amplitudecaldialog.cpp
index 80912e6..503822f 100644
--- a/Software/PC_Application/Calibration/amplitudecaldialog.cpp
+++ b/Software/PC_Application/Calibration/amplitudecaldialog.cpp
@@ -423,8 +423,9 @@ void AmplitudeCalDialog::AutomaticMeasurementDialog()
}
}
-void AmplitudeCalDialog::ReceivedMeasurement(Protocol::SpectrumAnalyzerResult res)
+void AmplitudeCalDialog::ReceivedMeasurement(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
+ Q_UNUSED(dev)
MeasurementResult m = {.port1 = Util::SparamTodB(res.port1), .port2 = Util::SparamTodB(res.port2)};
sweepMeasurements.push_back(m);
if(res.pointNum == automaticSweepPoints - 1) {
@@ -529,8 +530,9 @@ void AmplitudeCalDialog::SetupNextAutomaticPoint(bool isSourceCal)
sweepMeasurements.reserve(automaticSweepPoints);
}
-void AmplitudeCalDialog::ReceivedAutomaticMeasurementResult(Protocol::SpectrumAnalyzerResult res)
+void AmplitudeCalDialog::ReceivedAutomaticMeasurementResult(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
+ Q_UNUSED(dev)
if(res.pointNum != automaticSweepPoints - 1) {
// ignore everything except end of sweep
return;
diff --git a/Software/PC_Application/Calibration/amplitudecaldialog.h b/Software/PC_Application/Calibration/amplitudecaldialog.h
index 531983d..fc1d48e 100644
--- a/Software/PC_Application/Calibration/amplitudecaldialog.h
+++ b/Software/PC_Application/Calibration/amplitudecaldialog.h
@@ -78,7 +78,7 @@ protected slots:
bool AddPoint(double frequency);
void AddPointDialog();
void AutomaticMeasurementDialog();
- void ReceivedMeasurement(Protocol::SpectrumAnalyzerResult res);
+ void ReceivedMeasurement(Device *dev, Protocol::SpectrumAnalyzerResult res);
signals:
void pointsUpdated();
void newPointCreated(CorrectionPoint& p);
@@ -108,7 +108,7 @@ protected:
CalibrationMode mode;
void SetupNextAutomaticPoint(bool isSourceCal);
- void ReceivedAutomaticMeasurementResult(Protocol::SpectrumAnalyzerResult res);
+ void ReceivedAutomaticMeasurementResult(Device *dev, Protocol::SpectrumAnalyzerResult res);
struct {
QDialog *dialog;
std::vector points;
diff --git a/Software/PC_Application/CustomWidgets/tilewidget.cpp b/Software/PC_Application/CustomWidgets/tilewidget.cpp
index 2c8e1cb..452dad1 100644
--- a/Software/PC_Application/CustomWidgets/tilewidget.cpp
+++ b/Software/PC_Application/CustomWidgets/tilewidget.cpp
@@ -122,6 +122,15 @@ bool TileWidget::allLimitsPassing()
}
}
+void TileWidget::setSplitPercentage(int percentage)
+{
+ if(!isSplit) {
+ return;
+ }
+ splitter->setStretchFactor(0, percentage);
+ splitter->setStretchFactor(1, 100 - percentage);
+}
+
void TileWidget::splitVertically(bool moveContentToSecondChild)
{
if(isSplit) {
diff --git a/Software/PC_Application/CustomWidgets/tilewidget.h b/Software/PC_Application/CustomWidgets/tilewidget.h
index 66e385b..fd43721 100644
--- a/Software/PC_Application/CustomWidgets/tilewidget.h
+++ b/Software/PC_Application/CustomWidgets/tilewidget.h
@@ -32,6 +32,8 @@ public:
// check potential trace limits on graphs, only returns true if all traces in all graphs are within limits
bool allLimitsPassing();
+ void setSplitPercentage(int percentage);
+
public slots:
void splitVertically(bool moveContentToSecondChild = false);
void splitHorizontally(bool moveContentToSecondChild = false);
diff --git a/Software/PC_Application/Device/device.cpp b/Software/PC_Application/Device/device.cpp
index 027dfe0..e355a8b 100644
--- a/Software/PC_Application/Device/device.cpp
+++ b/Software/PC_Application/Device/device.cpp
@@ -326,7 +326,6 @@ std::set Device::GetDevices()
void Device::SetTrigger(bool set)
{
- qDebug() << "Trigger" << set << "to" << this;
if(set) {
SendCommandWithoutPayload(Protocol::PacketType::SetTrigger);
} else {
@@ -479,13 +478,13 @@ void Device::ReceivedData()
dataBuffer->removeBytes(handled_len);
switch(packet.type) {
case Protocol::PacketType::VNADatapoint:
- emit DatapointReceived(packet.VNAdatapoint);
+ emit DatapointReceived(this, packet.VNAdatapoint);
break;
case Protocol::PacketType::ManualStatusV1:
emit ManualStatusReceived(packet.manualStatusV1);
break;
case Protocol::PacketType::SpectrumAnalyzerResult:
- emit SpectrumResultReceived(packet.spectrumResult);
+ emit SpectrumResultReceived(this, packet.spectrumResult);
break;
case Protocol::PacketType::SourceCalPoint:
case Protocol::PacketType::ReceiverCalPoint:
@@ -500,11 +499,11 @@ void Device::ReceivedData()
info = packet.info;
}
infoValid = true;
- emit DeviceInfoUpdated();
+ emit DeviceInfoUpdated(this);
break;
case Protocol::PacketType::DeviceStatusV1:
status.v1 = packet.statusV1;
- emit DeviceStatusUpdated();
+ emit DeviceStatusUpdated(this);
break;
case Protocol::PacketType::Ack:
emit AckReceived();
@@ -518,11 +517,9 @@ void Device::ReceivedData()
emit FrequencyCorrectionReceived(packet.frequencyCorrection.ppm);
break;
case Protocol::PacketType::SetTrigger:
- qDebug() << "Trigger" << true << "from" << this;
emit TriggerReceived(true);
break;
case Protocol::PacketType::ClearTrigger:
- qDebug() << "Trigger" << false << "from" << this;
emit TriggerReceived(false);
break;
default:
diff --git a/Software/PC_Application/Device/device.h b/Software/PC_Application/Device/device.h
index 45a94e3..5e907be 100644
--- a/Software/PC_Application/Device/device.h
+++ b/Software/PC_Application/Device/device.h
@@ -78,13 +78,13 @@ public:
// Returns serial numbers of all connected devices
static std::set GetDevices();
signals:
- void DatapointReceived(Protocol::VNADatapoint<32>*);
+ void DatapointReceived(Device*, Protocol::VNADatapoint<32>*);
void ManualStatusReceived(Protocol::ManualStatusV1);
- void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult);
+ void SpectrumResultReceived(Device*, Protocol::SpectrumAnalyzerResult);
void AmplitudeCorrectionPointReceived(Protocol::AmplitudeCorrectionPoint);
void FrequencyCorrectionReceived(float ppm);
- void DeviceInfoUpdated();
- void DeviceStatusUpdated();
+ void DeviceInfoUpdated(Device*);
+ void DeviceStatusUpdated(Device*);
void ConnectionLost();
void AckReceived();
void NackReceived();
diff --git a/Software/PC_Application/Device/virtualdevice.cpp b/Software/PC_Application/Device/virtualdevice.cpp
index 51c690a..4668172 100644
--- a/Software/PC_Application/Device/virtualdevice.cpp
+++ b/Software/PC_Application/Device/virtualdevice.cpp
@@ -147,18 +147,10 @@ VirtualDevice::VirtualDevice(QString serial)
connect(dev, &Device::LogLineReceived, [=](QString line){
emit LogLineReceived(line.prepend(dev->serial()+": "));
});
- connect(dev, &Device::DeviceInfoUpdated, [=](){
- compoundInfoUpdated(dev);
- });
- connect(dev, &Device::DeviceStatusUpdated, [=](){
- compoundStatusUpdated(dev);
- });
- connect(dev, &Device::DatapointReceived, [=](Protocol::VNADatapoint<32> *data){
- compoundDatapointReceivecd(data, dev);
- });
- connect(dev, &Device::SpectrumResultReceived, [=](Protocol::SpectrumAnalyzerResult res) {
- compoundSpectrumResultReceived(res, dev);
- });
+ connect(dev, &Device::DeviceInfoUpdated, this, &VirtualDevice::compoundInfoUpdated, Qt::QueuedConnection);
+ connect(dev, &Device::DeviceStatusUpdated, this, &VirtualDevice::compoundStatusUpdated, Qt::QueuedConnection);
+ connect(dev, &Device::DatapointReceived, this, &VirtualDevice::compoundDatapointReceivecd, Qt::QueuedConnection);
+ connect(dev, &Device::SpectrumResultReceived, this, &VirtualDevice::compoundSpectrumResultReceived, Qt::QueuedConnection);
}
if(cdev->sync == CompoundDevice::Synchronization::USB) {
// create trigger connections for USB synchronization
@@ -283,6 +275,7 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::functionConfigure(sd, [=](Device::TransmissionResult r){
if(cb) {
cb(r == Device::TransmissionResult::Ack);
@@ -306,6 +299,7 @@ bool VirtualDevice::setVNA(const VirtualDevice::VNASettings &s, std::functionConfigure(sd, [=](Device::TransmissionResult r){
if(cb) {
results[devices[i]] = r;
@@ -342,34 +336,65 @@ bool VirtualDevice::setSA(const VirtualDevice::SASettings &s, std::functionConfigure(sd, [=](Device::TransmissionResult r){
if(cb) {
cb(r == Device::TransmissionResult::Ack);
}
});
} else {
- // TODO
- return false;
+ // set the synchronization mode
+ switch(cdev->sync) {
+ case CompoundDevice::Synchronization::USB: sd.syncMode = 1; break;
+ case CompoundDevice::Synchronization::ExtRef: sd.syncMode = 2; break;
+ case CompoundDevice::Synchronization::Trigger: sd.syncMode = 3; break;
+ }
+ // Configure the devices
+ results.clear();
+ bool success = true;
+ for(unsigned int i=0;iportMapping, i, 0) == s.trackingPort) {
+ sd.trackingGenerator = 1;
+ sd.trackingGeneratorPort = 0;
+ } else if(CompoundDevice::PortMapping::findActiveStage(cdev->portMapping, i, 1) == s.trackingPort) {
+ sd.trackingGenerator = 1;
+ sd.trackingGeneratorPort = 1;
+ }
+ } else {
+ // not used
+ sd.trackingGenerator = 0;
+ sd.trackingGeneratorPort = 0;
+ }
+ sd.syncMaster = i == 0 ? 1 : 0;
+ success &= devices[i]->Configure(sd, [=](Device::TransmissionResult r){
+ if(cb) {
+ results[devices[i]] = r;
+ checkIfAllTransmissionsComplete(cb);
+ }
+ });
+ }
+ return success;
}
}
@@ -520,8 +545,9 @@ VirtualDevice *VirtualDevice::getConnected()
return connected;
}
-void VirtualDevice::singleDatapointReceived(Protocol::VNADatapoint<32> *res)
+void VirtualDevice::singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res)
{
+ Q_UNUSED(dev)
VNAMeasurement m;
m.pointNum = res->pointNum;
m.Z0 = 50.0;
@@ -548,7 +574,7 @@ void VirtualDevice::singleDatapointReceived(Protocol::VNADatapoint<32> *res)
emit VNAmeasurementReceived(m);
}
-void VirtualDevice::compoundDatapointReceivecd(Protocol::VNADatapoint<32> *data, Device *dev)
+void VirtualDevice::compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data)
{
if(!compoundVNABuffer.count(data->pointNum)) {
compoundVNABuffer[data->pointNum] = std::map*>();
@@ -600,18 +626,25 @@ void VirtualDevice::compoundDatapointReceivecd(Protocol::VNADatapoint<32> *data,
emit VNAmeasurementReceived(m);
- // Clear this and all incomplete older datapoint buffers
- for(auto p : compoundVNABuffer) {
- for(auto d : p.second) {
- delete d.second;
+ // Clear this and all (incomplete) older datapoint buffers
+ int pointNum = data->pointNum;
+ auto it = compoundVNABuffer.begin();
+ while(it != compoundVNABuffer.end()) {
+ if(it->first <= pointNum) {
+ for(auto d : it->second) {
+ delete d.second;
+ }
+ it = compoundVNABuffer.erase(it);
+ } else {
+ it++;
}
}
- compoundVNABuffer.clear();
}
}
-void VirtualDevice::singleSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res)
+void VirtualDevice::singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
+ Q_UNUSED(dev)
SAMeasurement m;
m.pointNum = res.pointNum;
if(zerospan) {
@@ -624,9 +657,47 @@ void VirtualDevice::singleSpectrumResultReceived(Protocol::SpectrumAnalyzerResul
emit SAmeasurementReceived(m);
}
-void VirtualDevice::compoundSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res, Device *dev)
+void VirtualDevice::compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res)
{
+ if(!compoundSABuffer.count(res.pointNum)) {
+ compoundSABuffer[res.pointNum] = std::map();
+ }
+ auto &buf = compoundSABuffer[res.pointNum];
+ buf[dev] = res;
+ if(buf.size() == devices.size()) {
+ // Got datapoints from all devices, can create merged VNA result
+ SAMeasurement m;
+ m.pointNum = res.pointNum;
+ if(zerospan) {
+ m.us = res.us;
+ } else {
+ m.frequency = res.frequency;
+ }
+ // assemble data
+ for(unsigned int port=0;portportMapping.size();port++) {
+ auto device = devices[cdev->portMapping[port].device];
+ auto devicePort = cdev->portMapping[port].port;
+ QString name = "PORT"+QString::number(port+1);
+ if(devicePort == 0) {
+ m.measurements[name] = buf[device].port1;
+ } else {
+ m.measurements[name] = buf[device].port2;
+ }
+ }
+
+ emit SAmeasurementReceived(m);
+
+ // Clear this and all (incomplete) older datapoint buffers
+ auto it = compoundSABuffer.begin();
+ while(it != compoundSABuffer.end()) {
+ if(it->first <= res.pointNum) {
+ it = compoundSABuffer.erase(it);
+ } else {
+ it++;
+ }
+ }
+ }
}
void VirtualDevice::compoundInfoUpdated(Device *dev)
@@ -778,7 +849,7 @@ VirtualDevice::Info::Info(Device *dev)
Limits.mindBm = (double) info.limits_cdbm_min / 100;
Limits.maxdBm = (double) info.limits_cdbm_max / 100;
Limits.minRBW = info.limits_minRBW;
- Limits.maxRBW = info.limits_minRBW;
+ Limits.maxRBW = info.limits_maxRBW;
}
void VirtualDevice::Info::subset(const VirtualDevice::Info &merge)
diff --git a/Software/PC_Application/Device/virtualdevice.h b/Software/PC_Application/Device/virtualdevice.h
index ff57d96..a922e95 100644
--- a/Software/PC_Application/Device/virtualdevice.h
+++ b/Software/PC_Application/Device/virtualdevice.h
@@ -141,7 +141,6 @@ public:
struct {
// for non-zero span
double frequency;
- double cdbm;
};
struct {
// for zero span
@@ -184,10 +183,10 @@ signals:
void NeedsFirmwareUpdate(int usedProtocol, int requiredProtocol);
private slots:
- void singleDatapointReceived(Protocol::VNADatapoint<32> *res);
- void compoundDatapointReceivecd(Protocol::VNADatapoint<32> *data, Device *dev);
- void singleSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res);
- void compoundSpectrumResultReceived(Protocol::SpectrumAnalyzerResult res, Device *dev);
+ void singleDatapointReceived(Device *dev, Protocol::VNADatapoint<32> *res);
+ void compoundDatapointReceivecd(Device *dev, Protocol::VNADatapoint<32> *data);
+ void singleSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
+ void compoundSpectrumResultReceived(Device *dev, Protocol::SpectrumAnalyzerResult res);
void compoundInfoUpdated(Device *dev);
void compoundStatusUpdated(Device *dev);
private:
diff --git a/Software/PC_Application/Generator/generator.cpp b/Software/PC_Application/Generator/generator.cpp
index a2d1127..b7d1c81 100644
--- a/Software/PC_Application/Generator/generator.cpp
+++ b/Software/PC_Application/Generator/generator.cpp
@@ -53,6 +53,11 @@ void Generator::fromJSON(nlohmann::json j)
central->fromJSON(j);
}
+void Generator::preset()
+{
+
+}
+
void Generator::updateDevice()
{
if(!window->getDevice() || isActive != true) {
diff --git a/Software/PC_Application/Generator/generator.h b/Software/PC_Application/Generator/generator.h
index 456aeee..4dc0aff 100644
--- a/Software/PC_Application/Generator/generator.h
+++ b/Software/PC_Application/Generator/generator.h
@@ -21,6 +21,8 @@ public:
void setAveragingMode(Averaging::Mode mode) override {Q_UNUSED(mode)}
+ void preset() override;
+
private slots:
void updateDevice();
diff --git a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp
index a912b71..43c1f72 100644
--- a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp
+++ b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.cpp
@@ -60,20 +60,7 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window, QString name)
traceModel.setSource(TraceModel::DataSource::SA);
// Create default traces
- auto tPort1 = new Trace("Port1", Qt::yellow);
- tPort1->fromLivedata(Trace::LivedataType::Overwrite, "PORT1");
- traceModel.addTrace(tPort1);
- auto tPort2 = new Trace("Port2", Qt::blue);
- tPort2->fromLivedata(Trace::LivedataType::Overwrite, "PORT2");
- traceModel.addTrace(tPort2);
-
- auto traceXY = new TraceXYPlot(traceModel);
- traceXY->enableTrace(tPort1, true);
- traceXY->enableTrace(tPort2, true);
- traceXY->setYAxis(0, YAxis::Type::Magnitude, false, false, -120,0,10);
- traceXY->setYAxis(1, YAxis::Type::Disabled, false, true, 0,0,1);
-
- central->setPlot(traceXY);
+ preset();
// Create menu entries and connections
// Sweep toolbar
@@ -1153,11 +1140,42 @@ void SpectrumAnalyzer::StoreSweepSettings()
s.setValue("SASignalID", static_cast(settings.signalID));
}
+void SpectrumAnalyzer::createDefaultTracesAndGraphs(int ports)
+{
+ central->clear();
+ auto traceXY = new TraceXYPlot(traceModel);
+ traceXY->setYAxis(0, YAxis::Type::Magnitude, false, false, -120,0,10);
+ traceXY->setYAxis(1, YAxis::Type::Disabled, false, true, 0,0,1);
+ traceXY->updateSpan(settings.freqStart, settings.freqStop);
+
+ central->setPlot(traceXY);
+
+ QColor defaultColors[] = {Qt::yellow, Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::cyan, Qt::magenta, Qt::white};
+
+ for(int i=0;ienableTrace(trace, true);
+ }
+}
+
void SpectrumAnalyzer::setAveragingMode(Averaging::Mode mode)
{
average.setMode(mode);
}
+void SpectrumAnalyzer::preset()
+{
+ for(auto t : traceModel.getTraces()) {
+ if(Trace::isSAParameter(t->name())) {
+ traceModel.removeTrace(t);
+ }
+ }
+ // Create default traces
+ createDefaultTracesAndGraphs(VirtualDevice::getInfo(window->getDevice()).ports);
+}
+
QString SpectrumAnalyzer::WindowToString(VirtualDevice::SASettings::Window w)
{
switch(w) {
diff --git a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h
index a1237d2..4cea860 100644
--- a/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h
+++ b/Software/PC_Application/SpectrumAnalyzer/spectrumanalyzer.h
@@ -31,6 +31,7 @@ public:
void updateGraphColors();
void setAveragingMode(Averaging::Mode mode) override;
+ void preset() override;
private:
static QString WindowToString(VirtualDevice::SASettings::Window w);
@@ -74,6 +75,8 @@ private:
void LoadSweepSettings();
void StoreSweepSettings();
+ void createDefaultTracesAndGraphs(int ports);
+
VirtualDevice::SASettings settings;
bool changingSettings;
unsigned int averages;
diff --git a/Software/PC_Application/Traces/tracemodel.cpp b/Software/PC_Application/Traces/tracemodel.cpp
index 13f87c7..dcb3ece 100644
--- a/Software/PC_Application/Traces/tracemodel.cpp
+++ b/Software/PC_Application/Traces/tracemodel.cpp
@@ -48,11 +48,29 @@ void TraceModel::removeTrace(unsigned int index)
}
}
+void TraceModel::removeTrace(Trace *t)
+{
+ auto index = findIndex(t);
+ if(index >= 0) {
+ removeTrace(index);
+ }
+}
+
Trace *TraceModel::trace(unsigned int index)
{
return traces.at(index);
}
+int TraceModel::findIndex(Trace *t)
+{
+ for(int i=0;ifromLivedata(Trace::LivedataType::Overwrite, "S11");
- traceModel.addTrace(tS11);
- auto tS12 = new Trace("S12", Qt::blue);
- tS12->fromLivedata(Trace::LivedataType::Overwrite, "S12");
- traceModel.addTrace(tS12);
- auto tS21 = new Trace("S21", Qt::green);
- tS21->fromLivedata(Trace::LivedataType::Overwrite, "S21");
- traceModel.addTrace(tS21);
- auto tS22 = new Trace("S22", Qt::red);
- tS22->fromLivedata(Trace::LivedataType::Overwrite, "S22");
- traceModel.addTrace(tS22);
-
- auto tracesmith1 = new TraceSmithChart(traceModel);
- tracesmith1->enableTrace(tS11, true);
-
- auto tracesmith2 = new TraceSmithChart(traceModel);
- tracesmith2->enableTrace(tS22, true);
-
- auto traceXY1 = new TraceXYPlot(traceModel);
- traceXY1->enableTrace(tS12, true);
- auto traceXY2 = new TraceXYPlot(traceModel);
- traceXY2->enableTrace(tS21, true);
+ createDefaultTracesAndGraphs(2);
connect(&traceModel, &TraceModel::requiredExcitation, this, &VNA::ExcitationRequired);
- central->splitVertically();
- central->Child1()->splitHorizontally();
- central->Child2()->splitHorizontally();
- central->Child1()->Child1()->setPlot(tracesmith1);
- central->Child1()->Child2()->setPlot(traceXY1);
- central->Child2()->Child1()->setPlot(traceXY2);
- central->Child2()->Child2()->setPlot(tracesmith2);
-
// Create menu entries and connections
auto calMenu = new QMenu("Calibration", window);
window->menuBar()->insertMenu(window->getUi()->menuWindow->menuAction(), calMenu);
@@ -924,7 +894,7 @@ void VNA::SettingsChanged(bool resetTraces, std::function cb)
// assemble VNA protocol settings
VirtualDevice::VNASettings s = {};
s.IFBW = settings.bandwidth;
- if(Preferences::getInstance().Acquisition.alwaysExciteBothPorts) {
+ if(Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
for(int i=0;igetDevice()).ports;i++) {
s.excitedPorts.push_back(i);
}
@@ -1183,7 +1153,7 @@ void VNA::SetAveraging(unsigned int averages)
void VNA::ExcitationRequired()
{
- if(!Preferences::getInstance().Acquisition.alwaysExciteBothPorts) {
+ if(!Preferences::getInstance().Acquisition.alwaysExciteAllPorts) {
for(int i=1;igetDevice()).ports;i++) {
auto required = traceModel.PortExcitationRequired(i);
auto set = find(settings.excitedPorts.begin(), settings.excitedPorts.end(), i) != settings.excitedPorts.end();
@@ -1624,6 +1594,92 @@ void VNA::UpdateCalWidget()
calLabel->setToolTip(getCalToolTip());
}
+void VNA::createDefaultTracesAndGraphs(int ports)
+{
+ auto getDefaultColor = [](int ports, int i, int j)->QColor {
+ // Default colors for up to four ports, ensures that e.g. S21 always has the same color
+ const array, 4> defaultColors = {{
+ {Qt::yellow},
+ {Qt::yellow, Qt::blue, Qt::green, Qt::red},
+ {Qt::yellow, Qt::blue, Qt::cyan, Qt::green, Qt::red, Qt::darkGreen, Qt::darkBlue, Qt::darkYellow, Qt::magenta},
+ {Qt::yellow, Qt::blue, Qt::cyan, Qt::darkCyan, Qt::green, Qt::red, Qt::darkGreen, Qt::gray, Qt::darkBlue, Qt::darkYellow, Qt::magenta, Qt::darkMagenta, Qt::cyan, Qt::darkGray, Qt::lightGray, Qt::darkRed},
+ }};
+
+ if(ports >= 1 && ports <= 4) {
+ return defaultColors[ports-1][i*ports+j];
+ } else {
+ // not enough predefined colors available for all ports, just cycle through list
+ const array list = {{
+ Qt::yellow, Qt::blue, Qt::green, Qt::red, Qt::cyan, Qt::magenta, Qt::yellow, Qt::darkRed, Qt::darkGreen, Qt::darkBlue, Qt::gray, Qt::darkCyan, Qt::darkMagenta, Qt::darkYellow, Qt::darkGray, Qt::lightGray
+ }};
+ auto index = (i*ports+j) % list.size();
+ return list[index];
+ }
+ };
+
+ vector> plots;
+ for(int i=0;i());
+ for(int j=0;jupdateSpan(settings.Freq.start, settings.Freq.stop);
+ plot->enableTrace(trace, true);
+ plots[i].push_back(plot);
+ }
+ }
+ // Add created graphs to tiles
+ central->clear();
+ TileWidget *tile = central;
+ for(int i=0;isplitVertically();
+ row = tile->Child1();
+ tile = tile->Child2();
+ } else {
+ row = tile;
+ }
+ for(int j=0;jsplitHorizontally();
+ graphTile = row->Child1();
+ row = row->Child2();
+ } else {
+ graphTile = row;
+ }
+ graphTile->setPlot(plots[i][j]);
+ }
+ }
+ if(ports >= 3) {
+ // default split at the middle does not result in all plots being the same size, adjust
+ tile = central;
+ for(int i=0;isetSplitPercentage(100 / (ports - i));
+ rowTile = tile->Child1();
+ } else {
+ rowTile = tile;
+ }
+ for(int j=0;jsetSplitPercentage(100 / (ports - j));
+ rowTile = rowTile->Child2();
+ }
+ tile = tile->Child2();
+ }
+ }
+}
+
void VNA::EnableDeembedding(bool enable)
{
deembedding_active = enable;
@@ -1637,6 +1693,17 @@ void VNA::setAveragingMode(Averaging::Mode mode)
average.setMode(mode);
}
+void VNA::preset()
+{
+ for(auto t : traceModel.getTraces()) {
+ if(Trace::isVNAParameter(t->name())) {
+ traceModel.removeTrace(t);
+ }
+ }
+ // Create default traces
+ createDefaultTracesAndGraphs(VirtualDevice::getInfo(window->getDevice()).ports);
+}
+
QString VNA::SweepTypeToString(VNA::SweepType sw)
{
switch(sw) {
diff --git a/Software/PC_Application/VNA/vna.h b/Software/PC_Application/VNA/vna.h
index 3067b70..250a1bc 100644
--- a/Software/PC_Application/VNA/vna.h
+++ b/Software/PC_Application/VNA/vna.h
@@ -33,6 +33,8 @@ public:
void updateGraphColors();
void setAveragingMode(Averaging::Mode mode) override;
+ void preset() override;
+
enum class SweepType {
Frequency = 0,
Power = 1,
@@ -121,6 +123,8 @@ private:
void StopSweep();
void StartCalibrationDialog(Calibration::Type type = Calibration::Type::None);
void UpdateCalWidget();
+
+ void createDefaultTracesAndGraphs(int ports);
private slots:
void EnableDeembedding(bool enable);
void UpdateStatusbar();
diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp
index 7530f3f..5f6a7cb 100644
--- a/Software/PC_Application/appwindow.cpp
+++ b/Software/PC_Application/appwindow.cpp
@@ -236,6 +236,11 @@ void AppWindow::SetupMenu()
connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
connect(ui->actionReceiver_Calibration, &QAction::triggered, this, &AppWindow::ReceiverCalibrationDialog);
connect(ui->actionFrequency_Calibration, &QAction::triggered, this, &AppWindow::FrequencyCalibrationDialog);
+
+ connect(ui->actionPreset, &QAction::triggered, [=](){
+ modeHandler->getActiveMode()->preset();
+ });
+
connect(ui->actionPreferences, &QAction::triggered, [=](){
// save previous SCPI settings in case they change
auto &p = Preferences::getInstance();
@@ -338,6 +343,7 @@ bool AppWindow::ConnectToDevice(QString serial)
ui->actionReceiver_Calibration->setEnabled(true);
ui->actionFrequency_Calibration->setEnabled(true);
}
+ ui->actionPreset->setEnabled(true);
UpdateAcquisitionFrequencies();
@@ -368,6 +374,7 @@ void AppWindow::DisconnectDevice()
ui->actionSource_Calibration->setEnabled(false);
ui->actionReceiver_Calibration->setEnabled(false);
ui->actionFrequency_Calibration->setEnabled(false);
+ ui->actionPreset->setEnabled(false);
for(auto a : deviceActionGroup->actions()) {
a->setChecked(false);
}
diff --git a/Software/PC_Application/main.ui b/Software/PC_Application/main.ui
index 5402d31..cf71388 100644
--- a/Software/PC_Application/main.ui
+++ b/Software/PC_Application/main.ui
@@ -82,8 +82,15 @@
+
+
@@ -209,6 +216,14 @@
Frequency Calibration
+
+
+ false
+
+
+ Preset
+
+
diff --git a/Software/PC_Application/mode.h b/Software/PC_Application/mode.h
index 43213c3..2d20f6d 100644
--- a/Software/PC_Application/mode.h
+++ b/Software/PC_Application/mode.h
@@ -43,6 +43,8 @@ public:
virtual void setAveragingMode(Averaging::Mode mode) = 0;
+ virtual void preset() = 0;
+
signals:
void statusbarMessage(QString msg);
protected:
diff --git a/Software/PC_Application/preferences.cpp b/Software/PC_Application/preferences.cpp
index b33ea87..20c3988 100644
--- a/Software/PC_Application/preferences.cpp
+++ b/Software/PC_Application/preferences.cpp
@@ -138,6 +138,10 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) :
auto index = ui->compoundList->currentRow();
if(index >= 0 && index < p->compoundDevices.size()) {
auto d = new CompoundDeviceEditDialog(p->compoundDevices[index]);
+ connect(d, &QDialog::accepted, [=](){
+ ui->compoundList->item(index)->setText(p->compoundDevices[index]->getDesription());
+ p->nonTrivialWriting();
+ });
d->show();
}
});
@@ -276,7 +280,7 @@ void PreferencesDialog::setInitialGUIState()
ui->StartupSAAveraging->setValue(p->Startup.SA.averaging);
ui->StartupSASignalID->setChecked(p->Startup.SA.signalID);
- ui->AcquisitionAlwaysExciteBoth->setChecked(p->Acquisition.alwaysExciteBothPorts);
+ ui->AcquisitionAlwaysExciteBoth->setChecked(p->Acquisition.alwaysExciteAllPorts);
ui->AcquisitionSuppressPeaks->setChecked(p->Acquisition.suppressPeaks);
ui->AcquisitionAdjustPowerLevel->setChecked(p->Acquisition.adjustPowerLevel);
ui->AcquisitionUseHarmonic->setChecked(p->Acquisition.harmonicMixing);
@@ -346,7 +350,7 @@ void PreferencesDialog::updateFromGUI()
p->Startup.SA.detector = ui->StartupSADetector->currentIndex();
p->Startup.SA.signalID = ui->StartupSASignalID->isChecked();
- p->Acquisition.alwaysExciteBothPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
+ p->Acquisition.alwaysExciteAllPorts = ui->AcquisitionAlwaysExciteBoth->isChecked();
p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked();
p->Acquisition.adjustPowerLevel = ui->AcquisitionAdjustPowerLevel->isChecked();
p->Acquisition.harmonicMixing = ui->AcquisitionUseHarmonic->isChecked();
@@ -379,6 +383,8 @@ void PreferencesDialog::updateFromGUI()
p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked();
p->SCPIServer.port = ui->SCPIServerPort->value();
+
+ p->nonTrivialWriting();
}
void Preferences::load()
diff --git a/Software/PC_Application/preferences.h b/Software/PC_Application/preferences.h
index b859bd2..1699e9f 100644
--- a/Software/PC_Application/preferences.h
+++ b/Software/PC_Application/preferences.h
@@ -83,7 +83,7 @@ public:
} SA;
} Startup;
struct {
- bool alwaysExciteBothPorts;
+ bool alwaysExciteAllPorts;
bool suppressPeaks;
bool adjustPowerLevel;
bool harmonicMixing;
@@ -145,7 +145,9 @@ public:
private:
Preferences() :
- TCPoverride(false) {}
+ TCPoverride(false) {
+ qDebug() << "Pref constructor: " << &compoundDeviceJSON;
+ }
static Preferences instance;
const std::vector descr = {{
@@ -174,7 +176,7 @@ private:
{&Startup.SA.detector, "Startup.SA.detector", 0},
{&Startup.SA.averaging, "Startup.SA.averaging", 1},
{&Startup.SA.signalID, "Startup.SA.signalID", true},
- {&Acquisition.alwaysExciteBothPorts, "Acquisition.alwaysExciteBothPorts", true},
+ {&Acquisition.alwaysExciteAllPorts, "Acquisition.alwaysExciteBothPorts", true},
{&Acquisition.suppressPeaks, "Acquisition.suppressPeaks", true},
{&Acquisition.adjustPowerLevel, "Acquisition.adjustPowerLevel", false},
{&Acquisition.harmonicMixing, "Acquisition.harmonicMixing", false},
diff --git a/Software/PC_Application/preferencesdialog.ui b/Software/PC_Application/preferencesdialog.ui
index f8bf760..f7fa1a9 100644
--- a/Software/PC_Application/preferencesdialog.ui
+++ b/Software/PC_Application/preferencesdialog.ui
@@ -84,7 +84,7 @@
0
0
687
- 884
+ 938
@@ -103,7 +103,7 @@
- 5
+ 1
@@ -714,7 +714,7 @@
<html><head/><body><p>If only S11/S21 or S22/S12 are enabled, faster sweeps are possible by only exciting one port. Checking this option forces the device to always excite both ports even when the measurements from one port will not be used.</p></body></html>
- Always perform full 2-port measurement
+ Always create the stimulus signal at all ports
diff --git a/Software/VNA_embedded/Application/App.cpp b/Software/VNA_embedded/Application/App.cpp
index 6c48ed2..adfd421 100644
--- a/Software/VNA_embedded/Application/App.cpp
+++ b/Software/VNA_embedded/Application/App.cpp
@@ -305,10 +305,6 @@ inline void App_Process() {
}
}
if(HW::TimedOut()) {
- vTaskDelay(1000);
- LOG_WARN("Timed out, FPGA status: 0x%04x", FPGA::GetStatus());
- vTaskDelay(1000);
- LOG_WARN("Trigger out: %d (last reported: %d), in: %d", (uint8_t) Trigger::GetOutput(), (uint8_t) lastReportedTrigger, (uint8_t) Trigger::GetInput());
HW::SetMode(HW::Mode::Idle);
// insert the last received packet (restarts the timed out operation)
Communication::BlockNextAck();
diff --git a/Software/VNA_embedded/Application/Communication/Protocol.hpp b/Software/VNA_embedded/Application/Communication/Protocol.hpp
index abb9992..803eeb3 100644
--- a/Software/VNA_embedded/Application/Communication/Protocol.hpp
+++ b/Software/VNA_embedded/Application/Communication/Protocol.hpp
@@ -130,7 +130,8 @@ using SweepSettings = struct _sweepSettings {
uint16_t points;
uint32_t if_bandwidth;
int16_t cdbm_excitation_start; // in 1/100 dbm
- uint16_t unused:2;
+ uint16_t unused:1;
+ uint16_t syncMaster:1;
uint16_t suppressPeaks:1;
uint16_t fixedPowerSetting:1; // if set the attenuator and source PLL power will not be changed across the sweep
uint16_t logSweep:1;
@@ -258,6 +259,7 @@ using SpectrumAnalyzerSettings = struct _spectrumAnalyzerSettings {
* 3: Trigger synchronization (not supported yet by hardware)
*/
uint8_t syncMode :2;
+ uint8_t syncMaster :1;
int64_t trackingGeneratorOffset;
int16_t trackingPower;
};
diff --git a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
index 3f184fe..0f95cd9 100644
--- a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
+++ b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.cpp
@@ -130,7 +130,7 @@ void FPGA::SetSamplesPerPoint(uint32_t nsamples) {
WriteRegister(Reg::SamplesPerPoint, nsamples);
}
-void FPGA::SetupSweep(uint8_t stages, uint8_t port1_stage, uint8_t port2_stage, bool synchronize) {
+void FPGA::SetupSweep(uint8_t stages, uint8_t port1_stage, uint8_t port2_stage, bool synchronize, bool syncMaster) {
uint16_t value = 0x0000;
value |= (uint16_t) (stages & 0x07) << 13;
if(synchronize) {
@@ -139,6 +139,7 @@ void FPGA::SetupSweep(uint8_t stages, uint8_t port1_stage, uint8_t port2_stage,
value |= (port1_stage & 0x07) << 3;
value |= (port2_stage & 0x07) << 0;
WriteRegister(Reg::SweepSetup, value);
+ Enable(Periphery::SyncMaster, syncMaster);
}
void FPGA::Enable(Periphery p, bool enable) {
diff --git a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
index 80487dc..f356f83 100644
--- a/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
+++ b/Software/VNA_embedded/Application/Drivers/FPGA/FPGA.hpp
@@ -61,7 +61,7 @@ enum class Periphery {
DebugLED = 0x0080,
SourceChip = 0x0010,
LO1Chip = 0x0008,
-
+ SyncMaster = 0x0002,
PortSwitch = 0x0001,
};
@@ -114,7 +114,7 @@ bool Init(HaltedCallback cb = nullptr);
void WriteRegister(FPGA::Reg reg, uint16_t value);
void SetNumberOfPoints(uint16_t npoints);
void SetSamplesPerPoint(uint32_t nsamples);
-void SetupSweep(uint8_t stages, uint8_t port1_stage, uint8_t port2_stage, bool synchronize = false);
+void SetupSweep(uint8_t stages, uint8_t port1_stage, uint8_t port2_stage, bool synchronize = false, bool syncMaster = false);
void Enable(Periphery p, bool enable = true);
void Disable(Periphery p);
bool IsEnabled(Periphery p);
diff --git a/Software/VNA_embedded/Application/Hardware.cpp b/Software/VNA_embedded/Application/Hardware.cpp
index 3b00427..9f4fa8f 100644
--- a/Software/VNA_embedded/Application/Hardware.cpp
+++ b/Software/VNA_embedded/Application/Hardware.cpp
@@ -9,6 +9,7 @@
#include "delay.hpp"
#include "SpectrumAnalyzer.hpp"
#include "Communication.h"
+#include "Trigger.hpp"
#include
#define LOG_LEVEL LOG_LEVEL_INFO
@@ -230,6 +231,7 @@ bool HW::GetTemps(uint8_t *source, uint8_t *lo) {
void HW::SetIdle() {
unlevel = false;
+ Trigger::SetInput(false);
FPGA::AbortSweep();
FPGA::SetMode(FPGA::Mode::FPGA);
FPGA::DisableHardwareOverwrite();
diff --git a/Software/VNA_embedded/Application/Led.cpp b/Software/VNA_embedded/Application/Led.cpp
index 8228482..82695d6 100644
--- a/Software/VNA_embedded/Application/Led.cpp
+++ b/Software/VNA_embedded/Application/Led.cpp
@@ -87,8 +87,8 @@ void LED::Init() {
#if HW_REVISION == 'B'
led_ncnt = 0;
mode = Mode::Off;
- HAL_TIM_Base_Start(&htim2);
- HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
+// HAL_TIM_Base_Start(&htim2);
+// HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
LedStatusHandle = xTaskCreateStatic(LedStatus, "LedStatusTask", LED_STATUS_TASK_STACK_SIZE_WORDS,
NULL, 6, LedStatusStack, &LedStatusCB);
@@ -132,3 +132,11 @@ void LED::Error(uint8_t code) {
vTaskResume(LedStatusHandle);
#endif
}
+
+void LED::On() {
+ GPIOA->BSRR = GPIO_PIN_15;
+}
+
+void LED::Toggle() {
+ GPIOA->ODR ^= GPIO_PIN_15;
+}
diff --git a/Software/VNA_embedded/Application/Led.hpp b/Software/VNA_embedded/Application/Led.hpp
index 0e0b361..774036a 100644
--- a/Software/VNA_embedded/Application/Led.hpp
+++ b/Software/VNA_embedded/Application/Led.hpp
@@ -9,4 +9,7 @@ void Pulsating();
void Off();
void Error(uint8_t code);
+void On();
+void Toggle();
+
}
diff --git a/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp b/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp
index 8bebd54..1bb2033 100644
--- a/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp
+++ b/Software/VNA_embedded/Application/SpectrumAnalyzer.cpp
@@ -225,7 +225,7 @@ void SA::Setup(Protocol::SpectrumAnalyzerSettings settings) {
FPGA::SetWindow((FPGA::Window) s.WindowType);
FPGA::Enable(FPGA::Periphery::LO1Chip);
FPGA::Enable(FPGA::Periphery::LO1RF);
- FPGA::SetupSweep(0, s.trackingGeneratorPort == 1, s.trackingGeneratorPort == 0, s.syncMode != 0);
+ FPGA::SetupSweep(0, s.trackingGeneratorPort == 1, s.trackingGeneratorPort == 0, s.syncMode != 0, s.syncMaster);
FPGA::Enable(FPGA::Periphery::PortSwitch, s.trackingGenerator);
FPGA::Enable(FPGA::Periphery::Amplifier, s.trackingGenerator);
FPGA::Enable(FPGA::Periphery::Port1Mixer);
diff --git a/Software/VNA_embedded/Application/VNA.cpp b/Software/VNA_embedded/Application/VNA.cpp
index 8c75c18..9b146ea 100644
--- a/Software/VNA_embedded/Application/VNA.cpp
+++ b/Software/VNA_embedded/Application/VNA.cpp
@@ -279,7 +279,7 @@ bool VNA::Setup(Protocol::SweepSettings s) {
FPGA::Enable(FPGA::Periphery::SourceRF);
FPGA::Enable(FPGA::Periphery::LO1Chip);
FPGA::Enable(FPGA::Periphery::LO1RF);
- FPGA::SetupSweep(s.stages, s.port1Stage, s.port2Stage, s.syncMode != 0);
+ FPGA::SetupSweep(s.stages, s.port1Stage, s.port2Stage, s.syncMode != 0, s.syncMaster);
Trigger::SetMode((Trigger::Mode) s.syncMode);
FPGA::Enable(FPGA::Periphery::PortSwitch);
pointCnt = 0;
diff --git a/Software/VNA_embedded/VNA_embedded.ioc b/Software/VNA_embedded/VNA_embedded.ioc
index 1a13187..be31ef2 100644
--- a/Software/VNA_embedded/VNA_embedded.ioc
+++ b/Software/VNA_embedded/VNA_embedded.ioc
@@ -405,7 +405,7 @@ SPI2.VirtualType=VM_MASTER
TIM1.IPParameters=Prescaler
TIM1.Prescaler=159
TIM2.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
-TIM2.IPParameters=Channel-PWM Generation1 CH1,Prescaler,PeriodNoDither,OCMode_PWM-PWM Generation1 CH1
+TIM2.IPParameters=Prescaler,PeriodNoDither,Channel-PWM Generation1 CH1,OCMode_PWM-PWM Generation1 CH1
TIM2.OCMode_PWM-PWM\ Generation1\ CH1=TIM_OCMODE_PWM2
TIM2.PeriodNoDither=99
TIM2.Prescaler=143