Working generator mode

This commit is contained in:
Jan Käberich 2020-09-13 18:01:32 +02:00
parent b7033a029e
commit aae01a602e
14 changed files with 172 additions and 39 deletions

Binary file not shown.

View File

@ -19,7 +19,9 @@ void Generator::updateDevice()
// can't updat if not connected // can't updat if not connected
return; return;
} }
auto status = central->getDeviceStatus();
// TODO comment in once status is filled with valid values // TODO comment in once status is filled with valid values
// window->getDevice()->SetManual(status); Protocol::PacketInfo p;
p.type = Protocol::PacketType::Generator;
p.generator = central->getDeviceStatus();
window->getDevice()->SendPacket(p);
} }

View File

@ -42,10 +42,18 @@ SignalgeneratorWidget::~SignalgeneratorWidget()
delete ui; delete ui;
} }
Protocol::ManualControl SignalgeneratorWidget::getDeviceStatus() Protocol::GeneratorSettings SignalgeneratorWidget::getDeviceStatus()
{ {
// TODO Protocol::GeneratorSettings s = {};
Protocol::ManualControl s = {}; s.frequency = ui->frequency->value();
s.cdbm_level = ui->levelSpin->value() * 100.0;
if(ui->EnablePort1->isChecked()) {
s.activePort = 1;
} else if(ui->EnablePort2->isChecked()) {
s.activePort = 2;
} else {
s.activePort = 0;
}
return s; return s;
} }

View File

@ -16,7 +16,7 @@ public:
explicit SignalgeneratorWidget(QWidget *parent = nullptr); explicit SignalgeneratorWidget(QWidget *parent = nullptr);
~SignalgeneratorWidget(); ~SignalgeneratorWidget();
Protocol::ManualControl getDeviceStatus(); Protocol::GeneratorSettings getDeviceStatus();
signals: signals:
void SettingsChanged(); void SettingsChanged();

View File

@ -126,21 +126,31 @@ VNA::VNA(AppWindow *window)
auto impedanceMatching = toolsMenu->addAction("Impedance Matching"); auto impedanceMatching = toolsMenu->addAction("Impedance Matching");
connect(impedanceMatching, &QAction::triggered, this, &VNA::StartImpedanceMatching); connect(impedanceMatching, &QAction::triggered, this, &VNA::StartImpedanceMatching);
connect(window->getUi()->actionAssignDefaultCal, &QAction::triggered, [=](){ defaultCalMenu = new QMenu("Default Calibration");
assignDefaultCal = defaultCalMenu->addAction("Assign...");
removeDefaultCal = defaultCalMenu->addAction("Remove");
removeDefaultCal->setEnabled(false);
defaultCalMenu->setEnabled(false);
actions.insert(window->getUi()->menuDevice->addSeparator());
window->getUi()->menuDevice->addMenu(defaultCalMenu);
actions.insert(defaultCalMenu->menuAction());
connect(assignDefaultCal, &QAction::triggered, [=](){
if(window->getDevice()) { if(window->getDevice()) {
auto key = "DefaultCalibration"+window->getDevice()->serial(); auto key = "DefaultCalibration"+window->getDevice()->serial();
QSettings settings; QSettings settings;
auto filename = QFileDialog::getOpenFileName(nullptr, "Load calibration data", settings.value(key).toString(), "Calibration files (*.cal)", nullptr, QFileDialog::DontUseNativeDialog); auto filename = QFileDialog::getOpenFileName(nullptr, "Load calibration data", settings.value(key).toString(), "Calibration files (*.cal)", nullptr, QFileDialog::DontUseNativeDialog);
if(!filename.isEmpty()) { if(!filename.isEmpty()) {
settings.setValue(key, filename); settings.setValue(key, filename);
window->getUi()->actionRemoveDefaultCal->setEnabled(true); removeDefaultCal->setEnabled(true);
} }
} }
}); });
connect(window->getUi()->actionRemoveDefaultCal, &QAction::triggered, [=](){ connect(removeDefaultCal, &QAction::triggered, [=](){
QSettings settings; QSettings settings;
settings.remove("DefaultCalibration"+window->getDevice()->serial()); settings.remove("DefaultCalibration"+window->getDevice()->serial());
window->getUi()->actionRemoveDefaultCal->setEnabled(false); removeDefaultCal->setEnabled(false);
}); });
@ -432,6 +442,7 @@ void VNA::deactivate()
void VNA::initializeDevice() void VNA::initializeDevice()
{ {
defaultCalMenu->setEnabled(true);
connect(window->getDevice(), &Device::DatapointReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection); connect(window->getDevice(), &Device::DatapointReceived, this, &VNA::NewDatapoint, Qt::UniqueConnection);
// Check if default calibration exists and attempt to load it // Check if default calibration exists and attempt to load it
QSettings s; QSettings s;
@ -443,15 +454,20 @@ void VNA::initializeDevice()
cal.openFromFile(filename); cal.openFromFile(filename);
ApplyCalibration(cal.getType()); ApplyCalibration(cal.getType());
} }
window->getUi()->actionRemoveDefaultCal->setEnabled(true); removeDefaultCal->setEnabled(true);
} else { } else {
qDebug() << "No default calibration file set for this device"; qDebug() << "No default calibration file set for this device";
window->getUi()->actionRemoveDefaultCal->setEnabled(false); removeDefaultCal->setEnabled(false);
} }
// Configure initial state of device // Configure initial state of device
window->getDevice()->Configure(settings); window->getDevice()->Configure(settings);
} }
void VNA::deviceDisconnected()
{
defaultCalMenu->setEnabled(false);
}
using namespace std; using namespace std;
void VNA::NewDatapoint(Protocol::Datapoint d) void VNA::NewDatapoint(Protocol::Datapoint d)

View File

@ -15,6 +15,7 @@ public:
void deactivate() override; void deactivate() override;
void initializeDevice() override; void initializeDevice() override;
void deviceDisconnected() override;
private slots: private slots:
void NewDatapoint(Protocol::Datapoint d); void NewDatapoint(Protocol::Datapoint d);
void StartImpedanceMatching(); void StartImpedanceMatching();
@ -63,6 +64,9 @@ private:
bool calWaitFirst; bool calWaitFirst;
QProgressDialog calDialog; QProgressDialog calDialog;
QMenu *defaultCalMenu;
QAction *assignDefaultCal, *removeDefaultCal;
// Status Labels // Status Labels
QLabel *lStart, *lCenter, *lStop, *lSpan, *lPoints, *lBandwidth; QLabel *lStart, *lCenter, *lStop, *lSpan, *lPoints, *lBandwidth;
QLabel *lCalibration; QLabel *lCalibration;

View File

@ -168,11 +168,19 @@ void AppWindow::ConnectToDevice(QString serial)
}); });
ui->actionDisconnect->setEnabled(true); ui->actionDisconnect->setEnabled(true);
ui->actionManual_Control->setEnabled(true); ui->actionManual_Control->setEnabled(true);
ui->menuDefault_Calibration->setEnabled(true);
ui->actionFirmware_Update->setEnabled(true); ui->actionFirmware_Update->setEnabled(true);
Mode::getActiveMode()->initializeDevice(); Mode::getActiveMode()->initializeDevice();
UpdateReference(); UpdateReference();
for(auto d : deviceActionGroup->actions()) {
if(d->text() == device->serial()) {
d->blockSignals(true);
d->setChecked(true);
d->blockSignals(false);
break;
}
}
} catch (const runtime_error e) { } catch (const runtime_error e) {
DisconnectDevice(); DisconnectDevice();
UpdateDeviceList(); UpdateDeviceList();
@ -187,13 +195,13 @@ void AppWindow::DisconnectDevice()
} }
ui->actionDisconnect->setEnabled(false); ui->actionDisconnect->setEnabled(false);
ui->actionManual_Control->setEnabled(false); ui->actionManual_Control->setEnabled(false);
ui->menuDefault_Calibration->setEnabled(false);
ui->actionFirmware_Update->setEnabled(false); ui->actionFirmware_Update->setEnabled(false);
if(deviceActionGroup->checkedAction()) { if(deviceActionGroup->checkedAction()) {
deviceActionGroup->checkedAction()->setChecked(false); deviceActionGroup->checkedAction()->setChecked(false);
} }
lConnectionStatus.setText("No device connected"); lConnectionStatus.setText("No device connected");
lDeviceInfo.setText("No device information available yet"); lDeviceInfo.setText("No device information available yet");
Mode::getActiveMode()->deviceDisconnected();
} }
void AppWindow::DeviceConnectionLost() void AppWindow::DeviceConnectionLost()

View File

@ -42,22 +42,11 @@
</property> </property>
<addaction name="actionDummy"/> <addaction name="actionDummy"/>
</widget> </widget>
<widget class="QMenu" name="menuDefault_Calibration">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Default Calibration</string>
</property>
<addaction name="actionAssignDefaultCal"/>
<addaction name="actionRemoveDefaultCal"/>
</widget>
<addaction name="actionUpdate_Device_List"/> <addaction name="actionUpdate_Device_List"/>
<addaction name="menuConnect_to"/> <addaction name="menuConnect_to"/>
<addaction name="actionDisconnect"/> <addaction name="actionDisconnect"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionManual_Control"/> <addaction name="actionManual_Control"/>
<addaction name="menuDefault_Calibration"/>
<addaction name="actionFirmware_Update"/> <addaction name="actionFirmware_Update"/>
</widget> </widget>
<widget class="QMenu" name="menuWindow"> <widget class="QMenu" name="menuWindow">
@ -137,19 +126,6 @@
<string>Dummy</string> <string>Dummy</string>
</property> </property>
</action> </action>
<action name="actionAssignDefaultCal">
<property name="text">
<string>Assign...</string>
</property>
</action>
<action name="actionRemoveDefaultCal">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Remove</string>
</property>
</action>
<action name="actionFirmware_Update"> <action name="actionFirmware_Update">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>

View File

@ -19,6 +19,7 @@ public:
static Mode *getActiveMode(); static Mode *getActiveMode();
virtual void initializeDevice() = 0; virtual void initializeDevice() = 0;
virtual void deviceDisconnected(){};
protected: protected:
// call once the derived class is fully initialized // call once the derived class is fully initialized

View File

@ -166,11 +166,13 @@ void App_Start() {
VNA::ConfigureSweep(settings, VNACallback); VNA::ConfigureSweep(settings, VNACallback);
sweepActive = true; sweepActive = true;
lastNewPoint = HAL_GetTick(); lastNewPoint = HAL_GetTick();
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
break; break;
case Protocol::PacketType::ManualControl: case Protocol::PacketType::ManualControl:
sweepActive = false; sweepActive = false;
manual = packet.manual; manual = packet.manual;
VNA::ConfigureManual(manual, VNAStatusCallback); VNA::ConfigureManual(manual, VNAStatusCallback);
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
break; break;
case Protocol::PacketType::Reference: case Protocol::PacketType::Reference:
reference = packet.reference; reference = packet.reference;
@ -178,6 +180,13 @@ void App_Start() {
// can update right now // can update right now
VNA::Ref::applySettings(reference); VNA::Ref::applySettings(reference);
} }
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
break;
case Protocol::PacketType::Generator:
sweepActive = false;
LOG_INFO("Updating generator setting");
VNA::ConfigureGenerator(packet.generator);
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
break; break;
#ifdef HAS_FLASH #ifdef HAS_FLASH
case Protocol::PacketType::ClearFlash: case Protocol::PacketType::ClearFlash:

View File

@ -204,6 +204,23 @@ static int16_t EncodeReferenceSettings(Protocol::ReferenceSettings d, uint8_t *b
return e.getSize(); return e.getSize();
} }
static Protocol::GeneratorSettings DecodeGeneratorSettings(uint8_t *buf) {
Protocol::GeneratorSettings d;
Decoder e(buf);
e.get<uint64_t>(d.frequency);
e.get<int16_t>(d.cdbm_level);
e.get<uint8_t>(d.activePort);
return d;
}
static int16_t EncodeGeneratorSettings(Protocol::GeneratorSettings d, uint8_t *buf,
uint16_t bufSize) {
Encoder e(buf, bufSize);
e.add<uint64_t>(d.frequency);
e.add<int16_t>(d.cdbm_level);
e.add<uint8_t>(d.activePort);
return e.getSize();
}
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);
@ -420,6 +437,9 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
case PacketType::FirmwarePacket: case PacketType::FirmwarePacket:
info->firmware = DecodeFirmwarePacket(&data[4]); info->firmware = DecodeFirmwarePacket(&data[4]);
break; break;
case PacketType::Generator:
info->generator = DecodeGeneratorSettings(&data[4]);
break;
case PacketType::Ack: case PacketType::Ack:
case PacketType::PerformFirmwareUpdate: case PacketType::PerformFirmwareUpdate:
case PacketType::ClearFlash: case PacketType::ClearFlash:
@ -444,7 +464,7 @@ uint16_t Protocol::EncodePacket(PacketInfo packet, uint8_t *dest, uint16_t dests
break; break;
case PacketType::Reference: case PacketType::Reference:
payload_size = EncodeReferenceSettings(packet.reference, &dest[4], destsize - 8); payload_size = EncodeReferenceSettings(packet.reference, &dest[4], destsize - 8);
break; break;
case PacketType::DeviceInfo: case PacketType::DeviceInfo:
payload_size = EncodeDeviceInfo(packet.info, &dest[4], destsize - 8); payload_size = EncodeDeviceInfo(packet.info, &dest[4], destsize - 8);
break; break;
@ -457,6 +477,9 @@ uint16_t Protocol::EncodePacket(PacketInfo packet, uint8_t *dest, uint16_t dests
case PacketType::FirmwarePacket: case PacketType::FirmwarePacket:
payload_size = EncodeFirmwarePacket(packet.firmware, &dest[4], destsize - 8); payload_size = EncodeFirmwarePacket(packet.firmware, &dest[4], destsize - 8);
break; break;
case PacketType::Generator:
payload_size = EncodeGeneratorSettings(packet.generator, &dest[4], destsize - 8);
break;
case PacketType::Ack: case PacketType::Ack:
case PacketType::PerformFirmwareUpdate: case PacketType::PerformFirmwareUpdate:
case PacketType::ClearFlash: case PacketType::ClearFlash:

View File

@ -29,6 +29,12 @@ using ReferenceSettings = struct _referenceSettings {
uint8_t UseExternalRef:1; uint8_t UseExternalRef:1;
}; };
using GeneratorSettings = struct _generatorSettings {
uint64_t frequency;
int16_t cdbm_level;
uint8_t activePort;
};
using DeviceInfo = struct _deviceInfo { using DeviceInfo = struct _deviceInfo {
uint16_t FW_major; uint16_t FW_major;
uint16_t FW_minor; uint16_t FW_minor;
@ -109,6 +115,7 @@ enum class PacketType : uint8_t {
PerformFirmwareUpdate = 9, PerformFirmwareUpdate = 9,
Nack = 10, Nack = 10,
Reference = 11, Reference = 11,
Generator = 12,
}; };
using PacketInfo = struct _packetinfo { using PacketInfo = struct _packetinfo {
@ -117,6 +124,7 @@ using PacketInfo = struct _packetinfo {
Datapoint datapoint; Datapoint datapoint;
SweepSettings settings; SweepSettings settings;
ReferenceSettings reference; ReferenceSettings reference;
GeneratorSettings generator;
DeviceInfo info; DeviceInfo info;
ManualControl manual; ManualControl manual;
ManualStatus status; ManualStatus status;

View File

@ -490,3 +490,80 @@ bool VNA::Ref::applySettings(Protocol::ReferenceSettings s) {
} }
return false; return false;
} }
bool VNA::ConfigureGenerator(Protocol::GeneratorSettings g) {
Protocol::ManualControl m;
// LOs not required
m.LO1CE = 0;
m.LO1Frequency = 1000000000;
m.LO1RFEN = 0;
m.LO1RFEN = 0;
m.LO2EN = 0;
m.LO2Frequency = 60000000;
m.Port1EN = 0;
m.Port2EN = 0;
m.RefEN = 0;
m.Samples = 131072;
// Select correct source
if(g.frequency < BandSwitchFrequency) {
m.SourceLowEN = 1;
m.SourceLowFrequency = g.frequency;
m.SourceHighCE = 0;
m.SourceHighRFEN = 0;
m.SourceHighFrequency = BandSwitchFrequency;
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947;
m.SourceHighPower = (int) MAX2871::Power::n4dbm;
m.SourceHighband = false;
} else {
m.SourceLowEN = 0;
m.SourceLowFrequency = BandSwitchFrequency;
m.SourceHighCE = 1;
m.SourceHighRFEN = 1;
m.SourceHighFrequency = g.frequency;
if(g.frequency < 900000000UL) {
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M947;
} else if(g.frequency < 1800000000UL) {
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M1880;
} else if(g.frequency < 3500000000UL) {
m.SourceHighLowpass = (int) FPGA::LowpassFilter::M3500;
} else {
m.SourceHighLowpass = (int) FPGA::LowpassFilter::None;
}
m.SourceHighband = true;
}
switch(g.activePort) {
case 0:
// no output signal, disable
m.AmplifierEN = 0;
m.SourceHighCE = 0;
m.SourceHighRFEN = 0;
m.SourceLowEN = 0;
break;
case 1:
m.AmplifierEN = 1;
m.PortSwitch = 0;
break;
case 2:
m.AmplifierEN = 1;
m.PortSwitch = 1;
break;
}
// Set level (not very accurate)
if(g.cdbm_level > -1000) {
// use higher source power (approx 0dbm with no attenuation)
m.SourceHighPower = (int) MAX2871::Power::p5dbm;
m.SourceLowPower = (int) Si5351C::DriveStrength::mA8;
} else {
// use lower source power (approx -10dbm with no attenuation)
m.SourceHighPower = (int) MAX2871::Power::n4dbm;
m.SourceLowPower = (int) Si5351C::DriveStrength::mA2;
g.cdbm_level += 1000;
}
// calculate required attenuation
uint16_t attval = -g.cdbm_level / 25;
if(attval > 127) {
attval = 127;
}
m.attenuator = attval;
return ConfigureManual(m, nullptr);
}

View File

@ -12,6 +12,7 @@ using StatusCallback = void(*)(FPGA::SamplingResult);
bool Init(); bool Init();
bool ConfigureSweep(Protocol::SweepSettings s, SweepCallback cb); bool ConfigureSweep(Protocol::SweepSettings s, SweepCallback cb);
bool ConfigureManual(Protocol::ManualControl m, StatusCallback cb); bool ConfigureManual(Protocol::ManualControl m, StatusCallback cb);
bool ConfigureGenerator(Protocol::GeneratorSettings g);
// Only call the following function when the sweep is inactive // Only call the following function when the sweep is inactive
bool GetTemps(uint8_t *source, uint8_t *lo); bool GetTemps(uint8_t *source, uint8_t *lo);