Partial source calibration dialog
This commit is contained in:
parent
6f717de0f1
commit
875f3b0170
@ -1,11 +1,13 @@
|
|||||||
HEADERS += \
|
HEADERS += \
|
||||||
../VNA_embedded/Application/Communication/Protocol.hpp \
|
../VNA_embedded/Application/Communication/Protocol.hpp \
|
||||||
|
Calibration/amplitudecaldialog.h \
|
||||||
Calibration/calibration.h \
|
Calibration/calibration.h \
|
||||||
Calibration/calibrationtracedialog.h \
|
Calibration/calibrationtracedialog.h \
|
||||||
Calibration/calkit.h \
|
Calibration/calkit.h \
|
||||||
Calibration/calkitdialog.h \
|
Calibration/calkitdialog.h \
|
||||||
Calibration/json.hpp \
|
Calibration/json.hpp \
|
||||||
Calibration/measurementmodel.h \
|
Calibration/measurementmodel.h \
|
||||||
|
Calibration/sourcecaldialog.h \
|
||||||
CustomWidgets/colorpickerbutton.h \
|
CustomWidgets/colorpickerbutton.h \
|
||||||
CustomWidgets/informationbox.h \
|
CustomWidgets/informationbox.h \
|
||||||
CustomWidgets/siunitedit.h \
|
CustomWidgets/siunitedit.h \
|
||||||
@ -48,11 +50,13 @@ HEADERS += \
|
|||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
../VNA_embedded/Application/Communication/Protocol.cpp \
|
../VNA_embedded/Application/Communication/Protocol.cpp \
|
||||||
|
Calibration/amplitudecaldialog.cpp \
|
||||||
Calibration/calibration.cpp \
|
Calibration/calibration.cpp \
|
||||||
Calibration/calibrationtracedialog.cpp \
|
Calibration/calibrationtracedialog.cpp \
|
||||||
Calibration/calkit.cpp \
|
Calibration/calkit.cpp \
|
||||||
Calibration/calkitdialog.cpp \
|
Calibration/calkitdialog.cpp \
|
||||||
Calibration/measurementmodel.cpp \
|
Calibration/measurementmodel.cpp \
|
||||||
|
Calibration/sourcecaldialog.cpp \
|
||||||
CustomWidgets/colorpickerbutton.cpp \
|
CustomWidgets/colorpickerbutton.cpp \
|
||||||
CustomWidgets/informationbox.cpp \
|
CustomWidgets/informationbox.cpp \
|
||||||
CustomWidgets/qwtplotpiecewisecurve.cpp \
|
CustomWidgets/qwtplotpiecewisecurve.cpp \
|
||||||
@ -102,6 +106,7 @@ win32:LIBS += -LC:\Qwt-6.1.4\lib -lqwt
|
|||||||
QT += widgets
|
QT += widgets
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
|
Calibration/amplitudecaldialog.ui \
|
||||||
Calibration/calibrationtracedialog.ui \
|
Calibration/calibrationtracedialog.ui \
|
||||||
Calibration/calkitdialog.ui \
|
Calibration/calkitdialog.ui \
|
||||||
CustomWidgets/tilewidget.ui \
|
CustomWidgets/tilewidget.ui \
|
||||||
|
187
Software/PC_Application/Calibration/amplitudecaldialog.cpp
Normal file
187
Software/PC_Application/Calibration/amplitudecaldialog.cpp
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
#include "amplitudecaldialog.h"
|
||||||
|
#include "ui_amplitudecaldialog.h"
|
||||||
|
#include "mode.h"
|
||||||
|
#include "unit.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
AmplitudeCalDialog::AmplitudeCalDialog(Device *dev, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::AmplitudeCalDialog),
|
||||||
|
dev(dev),
|
||||||
|
model(this)
|
||||||
|
{
|
||||||
|
activeMode = Mode::getActiveMode();
|
||||||
|
activeMode->deactivate();
|
||||||
|
dev->SetIdle();
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->view->setModel(&model);
|
||||||
|
ui->view->setColumnWidth(AmplitudeModel::ColIndexFreq, 100);
|
||||||
|
ui->view->setColumnWidth(AmplitudeModel::ColIndexCorrectionFactors, 150);
|
||||||
|
ui->view->setColumnWidth(AmplitudeModel::ColIndexPort1, 150);
|
||||||
|
ui->view->setColumnWidth(AmplitudeModel::ColIndexPort2, 150);
|
||||||
|
connect(dev, &Device::AmplitudeCorrectionPointReceived, this, &AmplitudeCalDialog::ReceivedPoint);
|
||||||
|
connect(ui->load, &QPushButton::clicked, this, &AmplitudeCalDialog::LoadFromDevice);
|
||||||
|
connect(ui->add, &QPushButton::clicked, this, &AmplitudeCalDialog::AddPoint);
|
||||||
|
connect(ui->remove, &QPushButton::clicked, this, &AmplitudeCalDialog::RemovePoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
AmplitudeCalDialog::~AmplitudeCalDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
activeMode->activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCalDialog::reject()
|
||||||
|
{
|
||||||
|
// TODO check for unsaved data
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AmplitudeCalDialog::CorrectionPoint> AmplitudeCalDialog::getPoints() const
|
||||||
|
{
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCalDialog::setAmplitude(double amplitude, unsigned int point, bool port2)
|
||||||
|
{
|
||||||
|
if(point >= points.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(port2) {
|
||||||
|
points[point].amplitudePort2 = amplitude;
|
||||||
|
} else {
|
||||||
|
points[point].amplitudePort1 = amplitude;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCalDialog::ReceivedPoint(Protocol::AmplitudeCorrectionPoint p)
|
||||||
|
{
|
||||||
|
qDebug() << "Received a point";
|
||||||
|
CorrectionPoint c;
|
||||||
|
c.frequency = p.freq * 10.0;
|
||||||
|
c.correctionPort1 = p.port1;
|
||||||
|
c.correctionPort2 = p.port2;
|
||||||
|
model.beginInsertRows(QModelIndex(), points.size(), points.size());
|
||||||
|
points.push_back(c);
|
||||||
|
model.endInsertRows();
|
||||||
|
emit pointsUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCalDialog::LoadFromDevice()
|
||||||
|
{
|
||||||
|
model.beginResetModel();
|
||||||
|
points.clear();
|
||||||
|
model.endResetModel();
|
||||||
|
qDebug() << "Asking for amplitude calibration";
|
||||||
|
dev->SendCommandWithoutPayload(requestCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCalDialog::SaveToDevice()
|
||||||
|
{
|
||||||
|
for(unsigned int i=0;i<points.size();i++) {
|
||||||
|
auto p = points[i];
|
||||||
|
Protocol::PacketInfo info;
|
||||||
|
info.type = pointType();
|
||||||
|
info.amplitudePoint.freq = p.frequency / 10.0;
|
||||||
|
info.amplitudePoint.port1 = p.correctionPort1;
|
||||||
|
info.amplitudePoint.port2 = p.correctionPort2;
|
||||||
|
info.amplitudePoint.totalPoints = points.size();
|
||||||
|
info.amplitudePoint.pointNum = i;
|
||||||
|
dev->SendPacket(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCalDialog::RemovePoint()
|
||||||
|
{
|
||||||
|
unsigned int row = ui->view->currentIndex().row();
|
||||||
|
if(row < points.size()) {
|
||||||
|
model.beginRemoveRows(QModelIndex(), row, row);
|
||||||
|
points.erase(points.begin() + row);
|
||||||
|
model.endInsertRows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCalDialog::AddPoint()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AmplitudeModel::AmplitudeModel(AmplitudeCalDialog *c) :
|
||||||
|
QAbstractTableModel(),
|
||||||
|
c(c)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int AmplitudeModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return c->getPoints().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AmplitudeModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return ColIndexLast;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant AmplitudeModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if(role == Qt::DisplayRole && index.row() < c->getPoints().size()) {
|
||||||
|
auto p = c->getPoints()[index.row()];
|
||||||
|
switch(index.column()) {
|
||||||
|
case ColIndexFreq:
|
||||||
|
return Unit::ToString(p.frequency, "Hz", " kMG", 6);
|
||||||
|
break;
|
||||||
|
case ColIndexCorrectionFactors:
|
||||||
|
return QString::number(p.correctionPort1) + ", " + QString::number(p.correctionPort2);
|
||||||
|
break;
|
||||||
|
case ColIndexPort1:
|
||||||
|
return Unit::ToString(p.amplitudePort1, "dbm", " ", 4);
|
||||||
|
break;
|
||||||
|
case ColIndexPort2:
|
||||||
|
return Unit::ToString(p.amplitudePort2, "dbm", " ", 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmplitudeModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||||
|
{
|
||||||
|
if((unsigned int) index.row() >= c->getPoints().size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch(index.column()) {
|
||||||
|
case ColIndexPort1:
|
||||||
|
c->setAmplitude(value.toDouble(), index.row(), false);
|
||||||
|
return true;
|
||||||
|
case ColIndexPort2:
|
||||||
|
c->setAmplitude(value.toDouble(), index.row(), true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant AmplitudeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if(orientation == Qt::Horizontal && role == Qt::DisplayRole) {
|
||||||
|
switch(section) {
|
||||||
|
case ColIndexFreq: return "Frequency"; break;
|
||||||
|
case ColIndexCorrectionFactors: return "Correction Factors"; break;
|
||||||
|
case ColIndexPort1: return "Amplitude Port 1"; break;
|
||||||
|
case ColIndexPort2: return "Amplitude Port 2"; break;
|
||||||
|
default: return QVariant(); break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags AmplitudeModel::flags(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
int flags = Qt::NoItemFlags;
|
||||||
|
switch(index.column()) {
|
||||||
|
case ColIndexPort1: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
||||||
|
case ColIndexPort2: flags |= Qt::ItemIsEnabled | Qt::ItemIsEditable; break;
|
||||||
|
}
|
||||||
|
return (Qt::ItemFlags) flags;
|
||||||
|
}
|
77
Software/PC_Application/Calibration/amplitudecaldialog.h
Normal file
77
Software/PC_Application/Calibration/amplitudecaldialog.h
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#ifndef AMPLITUDECALDIALOG_H
|
||||||
|
#define AMPLITUDECALDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "mode.h"
|
||||||
|
#include "Device/device.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class AmplitudeCalDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AmplitudeCalDialog;
|
||||||
|
|
||||||
|
class AmplitudeModel : public QAbstractTableModel
|
||||||
|
{
|
||||||
|
friend AmplitudeCalDialog;
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
AmplitudeModel(AmplitudeCalDialog *c);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
ColIndexFreq,
|
||||||
|
ColIndexCorrectionFactors,
|
||||||
|
ColIndexPort1,
|
||||||
|
ColIndexPort2,
|
||||||
|
ColIndexLast
|
||||||
|
};
|
||||||
|
AmplitudeCalDialog *c;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AmplitudeCalDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AmplitudeCalDialog(Device *dev, QWidget *parent = nullptr);
|
||||||
|
~AmplitudeCalDialog();
|
||||||
|
void reject() override;
|
||||||
|
|
||||||
|
class CorrectionPoint {
|
||||||
|
public:
|
||||||
|
double frequency;
|
||||||
|
double correctionPort1;
|
||||||
|
double correctionPort2;
|
||||||
|
double amplitudePort1;
|
||||||
|
double amplitudePort2;
|
||||||
|
};
|
||||||
|
std::vector<CorrectionPoint> getPoints() const;
|
||||||
|
void setAmplitude(double amplitude, unsigned int point, bool port2);
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void ReceivedPoint(Protocol::AmplitudeCorrectionPoint p);
|
||||||
|
void LoadFromDevice();
|
||||||
|
void SaveToDevice();
|
||||||
|
void RemovePoint();
|
||||||
|
void AddPoint();
|
||||||
|
signals:
|
||||||
|
void pointsUpdated();
|
||||||
|
protected:
|
||||||
|
virtual Protocol::PacketType requestCommand() = 0;
|
||||||
|
virtual Protocol::PacketType pointType() = 0;
|
||||||
|
std::vector<CorrectionPoint> points;
|
||||||
|
Ui::AmplitudeCalDialog *ui;
|
||||||
|
Device *dev;
|
||||||
|
Mode *activeMode;
|
||||||
|
AmplitudeModel model;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SOURCECALDIALOG_H
|
107
Software/PC_Application/Calibration/amplitudecaldialog.ui
Normal file
107
Software/PC_Application/Calibration/amplitudecaldialog.ui
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>AmplitudeCalDialog</class>
|
||||||
|
<widget class="QDialog" name="AmplitudeCalDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>766</width>
|
||||||
|
<height>599</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="view">
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectItems</enum>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="add">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add Point</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="list-add" resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/add.png</normaloff>:/icons/add.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="remove">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete Point</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="list-remove" resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/remove.png</normaloff>:/icons/remove.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="help">
|
||||||
|
<property name="text">
|
||||||
|
<string>Help</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="help"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="load">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load from Device</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="document-open" resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/open.png</normaloff>:/icons/open.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="save">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save to Device</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="document-save" resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/save.png</normaloff>:/icons/save.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../icons.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
8
Software/PC_Application/Calibration/sourcecaldialog.cpp
Normal file
8
Software/PC_Application/Calibration/sourcecaldialog.cpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#include "sourcecaldialog.h"
|
||||||
|
|
||||||
|
SourceCalDialog::SourceCalDialog(Device *dev)
|
||||||
|
: AmplitudeCalDialog(dev)
|
||||||
|
{
|
||||||
|
setWindowTitle("Source Calibration Dialog");
|
||||||
|
LoadFromDevice();
|
||||||
|
}
|
17
Software/PC_Application/Calibration/sourcecaldialog.h
Normal file
17
Software/PC_Application/Calibration/sourcecaldialog.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef SOURCECALDIALOG_H
|
||||||
|
#define SOURCECALDIALOG_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include "amplitudecaldialog.h"
|
||||||
|
|
||||||
|
class SourceCalDialog : public AmplitudeCalDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SourceCalDialog(Device *dev);
|
||||||
|
protected:
|
||||||
|
Protocol::PacketType requestCommand() override { return Protocol::PacketType::RequestSourceCal; }
|
||||||
|
Protocol::PacketType pointType() override { return Protocol::PacketType::SourceCalPoint; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SOURCECALDIALOG_H
|
@ -434,6 +434,10 @@ void Device::ReceivedData()
|
|||||||
case Protocol::PacketType::SpectrumAnalyzerResult:
|
case Protocol::PacketType::SpectrumAnalyzerResult:
|
||||||
emit SpectrumResultReceived(packet.spectrumResult);
|
emit SpectrumResultReceived(packet.spectrumResult);
|
||||||
break;
|
break;
|
||||||
|
case Protocol::PacketType::SourceCalPoint:
|
||||||
|
case Protocol::PacketType::ReceiverCalPoint:
|
||||||
|
emit AmplitudeCorrectionPointReceived(packet.amplitudePoint);
|
||||||
|
break;
|
||||||
case Protocol::PacketType::DeviceInfo:
|
case Protocol::PacketType::DeviceInfo:
|
||||||
if(packet.info.ProtocolVersion != Protocol::Version) {
|
if(packet.info.ProtocolVersion != Protocol::Version) {
|
||||||
if(!lastInfoValid) {
|
if(!lastInfoValid) {
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(Protocol::Datapoint);
|
Q_DECLARE_METATYPE(Protocol::Datapoint);
|
||||||
Q_DECLARE_METATYPE(Protocol::ManualStatus);
|
Q_DECLARE_METATYPE(Protocol::ManualStatus);
|
||||||
Q_DECLARE_METATYPE(Protocol::DeviceInfo);
|
|
||||||
Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult);
|
Q_DECLARE_METATYPE(Protocol::SpectrumAnalyzerResult);
|
||||||
|
Q_DECLARE_METATYPE(Protocol::AmplitudeCorrectionPoint);
|
||||||
|
|
||||||
class USBInBuffer : public QObject {
|
class USBInBuffer : public QObject {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
@ -74,6 +74,7 @@ signals:
|
|||||||
void DatapointReceived(Protocol::Datapoint);
|
void DatapointReceived(Protocol::Datapoint);
|
||||||
void ManualStatusReceived(Protocol::ManualStatus);
|
void ManualStatusReceived(Protocol::ManualStatus);
|
||||||
void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult);
|
void SpectrumResultReceived(Protocol::SpectrumAnalyzerResult);
|
||||||
|
void AmplitudeCorrectionPointReceived(Protocol::AmplitudeCorrectionPoint);
|
||||||
void DeviceInfoUpdated();
|
void DeviceInfoUpdated();
|
||||||
void ConnectionLost();
|
void ConnectionLost();
|
||||||
void AckReceived();
|
void AckReceived();
|
||||||
|
@ -63,7 +63,7 @@ void FirmwareUpdateDialog::on_bStart_clicked()
|
|||||||
addStatus("Erasing device memory...");
|
addStatus("Erasing device memory...");
|
||||||
dev->SendCommandWithoutPayload(Protocol::PacketType::ClearFlash);
|
dev->SendCommandWithoutPayload(Protocol::PacketType::ClearFlash);
|
||||||
timer.setSingleShot(true);
|
timer.setSingleShot(true);
|
||||||
timer.start(10000);
|
timer.start(20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FirmwareUpdateDialog::addStatus(QString line)
|
void FirmwareUpdateDialog::addStatus(QString line)
|
||||||
|
@ -144,7 +144,6 @@ ManualControlDialog::ManualControlDialog(Device &dev, QWidget *parent) :
|
|||||||
MakeReadOnly(ui->refmag);
|
MakeReadOnly(ui->refmag);
|
||||||
MakeReadOnly(ui->refphase);
|
MakeReadOnly(ui->refphase);
|
||||||
|
|
||||||
qRegisterMetaType<Protocol::ManualStatus>("Status");
|
|
||||||
connect(&dev, &Device::ManualStatusReceived, this, &ManualControlDialog::NewStatus);
|
connect(&dev, &Device::ManualStatusReceived, this, &ManualControlDialog::NewStatus);
|
||||||
|
|
||||||
connect(ui->SourceCE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
connect(ui->SourceCE, &QCheckBox::toggled, [=](bool) { UpdateDevice(); });
|
||||||
|
@ -192,8 +192,6 @@ SpectrumAnalyzer::SpectrumAnalyzer(AppWindow *window)
|
|||||||
window->addDockWidget(Qt::BottomDockWidgetArea, markerDock);
|
window->addDockWidget(Qt::BottomDockWidgetArea, markerDock);
|
||||||
docks.insert(markerDock);
|
docks.insert(markerDock);
|
||||||
|
|
||||||
qRegisterMetaType<Protocol::SpectrumAnalyzerResult>("SpectrumResult");
|
|
||||||
|
|
||||||
// Set initial sweep settings
|
// Set initial sweep settings
|
||||||
auto pref = Preferences::getInstance();
|
auto pref = Preferences::getInstance();
|
||||||
if(pref.Startup.RememberSweepSettings) {
|
if(pref.Startup.RememberSweepSettings) {
|
||||||
|
@ -360,8 +360,6 @@ VNA::VNA(AppWindow *window)
|
|||||||
window->addDockWidget(Qt::BottomDockWidgetArea, markerDock);
|
window->addDockWidget(Qt::BottomDockWidgetArea, markerDock);
|
||||||
docks.insert(markerDock);
|
docks.insert(markerDock);
|
||||||
|
|
||||||
qRegisterMetaType<Protocol::Datapoint>("Datapoint");
|
|
||||||
|
|
||||||
// Set initial sweep settings
|
// Set initial sweep settings
|
||||||
auto pref = Preferences::getInstance();
|
auto pref = Preferences::getInstance();
|
||||||
if(pref.Acquisition.alwaysExciteBothPorts) {
|
if(pref.Acquisition.alwaysExciteBothPorts) {
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "VNA/vna.h"
|
#include "VNA/vna.h"
|
||||||
#include "Generator/generator.h"
|
#include "Generator/generator.h"
|
||||||
#include "SpectrumAnalyzer/spectrumanalyzer.h"
|
#include "SpectrumAnalyzer/spectrumanalyzer.h"
|
||||||
|
#include "Calibration/sourcecaldialog.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -100,6 +101,7 @@ AppWindow::AppWindow(QWidget *parent)
|
|||||||
connect(ui->actionQuit, &QAction::triggered, this, &AppWindow::close);
|
connect(ui->actionQuit, &QAction::triggered, this, &AppWindow::close);
|
||||||
connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
|
connect(ui->actionManual_Control, &QAction::triggered, this, &AppWindow::StartManualControl);
|
||||||
connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
connect(ui->actionFirmware_Update, &QAction::triggered, this, &AppWindow::StartFirmwareUpdateDialog);
|
||||||
|
connect(ui->actionSource_Calibration, &QAction::triggered, this, &AppWindow::SourceCalibrationDialog);
|
||||||
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
connect(ui->actionPreferences, &QAction::triggered, [=](){
|
||||||
Preferences::getInstance().edit();
|
Preferences::getInstance().edit();
|
||||||
// settings might have changed, update necessary stuff
|
// settings might have changed, update necessary stuff
|
||||||
@ -129,6 +131,9 @@ AppWindow::AppWindow(QWidget *parent)
|
|||||||
vna->activate();
|
vna->activate();
|
||||||
|
|
||||||
qRegisterMetaType<Protocol::Datapoint>("Datapoint");
|
qRegisterMetaType<Protocol::Datapoint>("Datapoint");
|
||||||
|
qRegisterMetaType<Protocol::ManualStatus>("Manual");
|
||||||
|
qRegisterMetaType<Protocol::SpectrumAnalyzerResult>("SpectrumAnalyzerResult");
|
||||||
|
qRegisterMetaType<Protocol::AmplitudeCorrectionPoint>("AmplitudeCorrection");
|
||||||
|
|
||||||
// List available devices
|
// List available devices
|
||||||
if(UpdateDeviceList() && Preferences::getInstance().Startup.ConnectToFirstDevice) {
|
if(UpdateDeviceList() && Preferences::getInstance().Startup.ConnectToFirstDevice) {
|
||||||
@ -181,6 +186,7 @@ void AppWindow::ConnectToDevice(QString serial)
|
|||||||
ui->actionDisconnect->setEnabled(true);
|
ui->actionDisconnect->setEnabled(true);
|
||||||
ui->actionManual_Control->setEnabled(true);
|
ui->actionManual_Control->setEnabled(true);
|
||||||
ui->actionFirmware_Update->setEnabled(true);
|
ui->actionFirmware_Update->setEnabled(true);
|
||||||
|
ui->actionSource_Calibration->setEnabled(true);
|
||||||
|
|
||||||
Mode::getActiveMode()->initializeDevice();
|
Mode::getActiveMode()->initializeDevice();
|
||||||
UpdateReference();
|
UpdateReference();
|
||||||
@ -207,6 +213,7 @@ void AppWindow::DisconnectDevice()
|
|||||||
ui->actionDisconnect->setEnabled(false);
|
ui->actionDisconnect->setEnabled(false);
|
||||||
ui->actionManual_Control->setEnabled(false);
|
ui->actionManual_Control->setEnabled(false);
|
||||||
ui->actionFirmware_Update->setEnabled(false);
|
ui->actionFirmware_Update->setEnabled(false);
|
||||||
|
ui->actionSource_Calibration->setEnabled(false);
|
||||||
for(auto a : deviceActionGroup->actions()) {
|
for(auto a : deviceActionGroup->actions()) {
|
||||||
a->setChecked(false);
|
a->setChecked(false);
|
||||||
}
|
}
|
||||||
@ -349,6 +356,12 @@ void AppWindow::DeviceNeedsUpdate(int reported, int expected)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppWindow::SourceCalibrationDialog()
|
||||||
|
{
|
||||||
|
auto d = new SourceCalDialog(device);
|
||||||
|
d->exec();
|
||||||
|
}
|
||||||
|
|
||||||
Device *AppWindow::getDevice() const
|
Device *AppWindow::getDevice() const
|
||||||
{
|
{
|
||||||
return device;
|
return device;
|
||||||
|
@ -44,6 +44,7 @@ private slots:
|
|||||||
void UpdateReference();
|
void UpdateReference();
|
||||||
void StartFirmwareUpdateDialog();
|
void StartFirmwareUpdateDialog();
|
||||||
void DeviceNeedsUpdate(int reported, int expected);
|
void DeviceNeedsUpdate(int reported, int expected);
|
||||||
|
void SourceCalibrationDialog();
|
||||||
private:
|
private:
|
||||||
void DeviceConnectionLost();
|
void DeviceConnectionLost();
|
||||||
void CreateToolbars();
|
void CreateToolbars();
|
||||||
|
@ -48,6 +48,8 @@
|
|||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionManual_Control"/>
|
<addaction name="actionManual_Control"/>
|
||||||
<addaction name="actionFirmware_Update"/>
|
<addaction name="actionFirmware_Update"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="actionSource_Calibration"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuWindow">
|
<widget class="QMenu" name="menuWindow">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -151,6 +153,14 @@
|
|||||||
<string>About</string>
|
<string>About</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionSource_Calibration">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Source Calibration</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="icons.qrc"/>
|
<include location="icons.qrc"/>
|
||||||
|
136
Software/VNA_embedded/Application/AmplitudeCal.cpp
Normal file
136
Software/VNA_embedded/Application/AmplitudeCal.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include "AmplitudeCal.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
#include "Communication.h"
|
||||||
|
#include "HW_HAL.hpp"
|
||||||
|
|
||||||
|
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||||
|
#define LOG_MODULE "CAL"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
|
||||||
|
// increment when Calibration struct format changed. If a wrong version is found in flash, it will revert to default values
|
||||||
|
static constexpr uint16_t version = 0x0000;
|
||||||
|
|
||||||
|
using CorrectionTable = struct {
|
||||||
|
uint8_t usedPoints;
|
||||||
|
uint32_t freq[AmplitudeCal::maxPoints]; // LSB = 10Hz
|
||||||
|
int16_t port1Correction[AmplitudeCal::maxPoints]; // LSB = 0.01db
|
||||||
|
int16_t port2Correction[AmplitudeCal::maxPoints]; // LSB = 0.01db
|
||||||
|
};
|
||||||
|
|
||||||
|
using Calibration = struct _calibration {
|
||||||
|
uint16_t version;
|
||||||
|
CorrectionTable Source;
|
||||||
|
CorrectionTable Receiver;
|
||||||
|
};
|
||||||
|
|
||||||
|
static Calibration cal;
|
||||||
|
|
||||||
|
static_assert(sizeof(cal) <= AmplitudeCal::flash_size, "Reserved flash size is too small");
|
||||||
|
|
||||||
|
bool AmplitudeCal::Load() {
|
||||||
|
HWHAL::flash.read(flash_address, sizeof(cal), &cal);
|
||||||
|
if(cal.version != version) {
|
||||||
|
LOG_WARN("Invalid version in flash, expected %u, got %u", version, cal.version);
|
||||||
|
SetDefault();
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
LOG_INFO("Loaded from flash");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmplitudeCal::Save() {
|
||||||
|
if(!HWHAL::flash.eraseRange(flash_address, flash_size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return HWHAL::flash.write(flash_address, sizeof(cal), &cal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCal::SetDefault() {
|
||||||
|
memset(&cal, 0, sizeof(cal));
|
||||||
|
cal.version = version;
|
||||||
|
cal.Source.usedPoints = 1;
|
||||||
|
cal.Source.freq[0] = 100000000;
|
||||||
|
cal.Receiver.usedPoints = 1;
|
||||||
|
cal.Receiver.freq[0] = 100000000;
|
||||||
|
LOG_INFO("Set to default");
|
||||||
|
}
|
||||||
|
|
||||||
|
static AmplitudeCal::Correction InterpolateCorrection(const CorrectionTable& table, uint64_t freq) {
|
||||||
|
// adjust LSB to match table
|
||||||
|
freq /= 10;
|
||||||
|
AmplitudeCal::Correction ret;
|
||||||
|
// find first valid index that is higher than the given frequency
|
||||||
|
uint8_t i = 0;
|
||||||
|
for (; i < table.usedPoints; i++) {
|
||||||
|
if (table.freq[i] >= freq) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == 0) {
|
||||||
|
// no previous index, nothing to interpolate
|
||||||
|
ret.port1 = table.port1Correction[0];
|
||||||
|
ret.port2 = table.port2Correction[0];
|
||||||
|
} else if (i >= table.usedPoints) {
|
||||||
|
// went beyond last point, nothing to interpolate
|
||||||
|
ret.port1 = table.port1Correction[table.usedPoints - 1];
|
||||||
|
ret.port2 = table.port2Correction[table.usedPoints - 1];
|
||||||
|
} else {
|
||||||
|
// frequency is between i and i-1, interpolate
|
||||||
|
float alpha = (freq - table.freq[i - 1]) / (table.freq[i] - table.freq[i - 1]);
|
||||||
|
ret.port1 = table.port1Correction[i - 1] * (1 - alpha) + table.port1Correction[i] * alpha;
|
||||||
|
ret.port2 = table.port2Correction[i - 1] * (1 - alpha) + table.port2Correction[i] * alpha;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
AmplitudeCal::Correction AmplitudeCal::SourceCorrection(uint64_t freq) {
|
||||||
|
return InterpolateCorrection(cal.Source, freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
AmplitudeCal::Correction AmplitudeCal::ReceiverCorrection(uint64_t freq) {
|
||||||
|
return InterpolateCorrection(cal.Receiver, freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SendCorrectionTable(const CorrectionTable& table, Protocol::PacketType type) {
|
||||||
|
for(uint8_t i=0;i<table.usedPoints;i++) {
|
||||||
|
// assemble packet
|
||||||
|
Protocol::PacketInfo p;
|
||||||
|
p.type = type;
|
||||||
|
p.amplitudePoint.totalPoints = table.usedPoints;
|
||||||
|
p.amplitudePoint.pointNum = i;
|
||||||
|
p.amplitudePoint.freq = table.freq[i];
|
||||||
|
p.amplitudePoint.port1 = table.port1Correction[i];
|
||||||
|
p.amplitudePoint.port2 = table.port2Correction[i];
|
||||||
|
Communication::Send(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCal::SendSource() {
|
||||||
|
SendCorrectionTable(cal.Source, Protocol::PacketType::SourceCalPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCal::SendReceiver() {
|
||||||
|
SendCorrectionTable(cal.Receiver, Protocol::PacketType::ReceiverCalPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addPoint(CorrectionTable& table, const Protocol::AmplitudeCorrectionPoint& p) {
|
||||||
|
table.freq[p.pointNum] = p.freq;
|
||||||
|
table.port1Correction[p.pointNum] = p.port1;
|
||||||
|
table.port2Correction[p.pointNum] = p.port2;
|
||||||
|
if(p.pointNum == p.totalPoints - 1) {
|
||||||
|
// this was the last point, update used points and save
|
||||||
|
table.usedPoints = p.totalPoints;
|
||||||
|
LOG_INFO("Last point received, saving to flash");
|
||||||
|
AmplitudeCal::Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCal::AddSourcePoint(const Protocol::AmplitudeCorrectionPoint& p) {
|
||||||
|
addPoint(cal.Source, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmplitudeCal::AddReceiverPoint(const Protocol::AmplitudeCorrectionPoint& p) {
|
||||||
|
addPoint(cal.Receiver, p);
|
||||||
|
}
|
30
Software/VNA_embedded/Application/AmplitudeCal.hpp
Normal file
30
Software/VNA_embedded/Application/AmplitudeCal.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "Flash.hpp"
|
||||||
|
#include "Firmware.hpp"
|
||||||
|
#include "Protocol.hpp"
|
||||||
|
|
||||||
|
namespace AmplitudeCal {
|
||||||
|
|
||||||
|
constexpr uint8_t maxPoints = 64;
|
||||||
|
constexpr uint32_t flash_address = Firmware::maxSize; // stored directly behind firmware in flash
|
||||||
|
constexpr uint32_t flash_size = 8192; // reserve two sectors for now
|
||||||
|
|
||||||
|
bool Load();
|
||||||
|
bool Save();
|
||||||
|
void SetDefault();
|
||||||
|
|
||||||
|
using Correction = struct _correction {
|
||||||
|
int16_t port1;
|
||||||
|
int16_t port2;
|
||||||
|
};
|
||||||
|
|
||||||
|
Correction SourceCorrection(uint64_t freq);
|
||||||
|
Correction ReceiverCorrection(uint64_t freq);
|
||||||
|
void SendSource();
|
||||||
|
void SendReceiver();
|
||||||
|
void AddSourcePoint(const Protocol::AmplitudeCorrectionPoint& p);
|
||||||
|
void AddReceiverPoint(const Protocol::AmplitudeCorrectionPoint& p);
|
||||||
|
|
||||||
|
}
|
@ -17,6 +17,8 @@
|
|||||||
#include "Manual.hpp"
|
#include "Manual.hpp"
|
||||||
#include "Generator.hpp"
|
#include "Generator.hpp"
|
||||||
#include "SpectrumAnalyzer.hpp"
|
#include "SpectrumAnalyzer.hpp"
|
||||||
|
#include "HW_HAL.hpp"
|
||||||
|
#include "AmplitudeCal.hpp"
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||||
#define LOG_MODULE "App"
|
#define LOG_MODULE "App"
|
||||||
@ -32,8 +34,6 @@ static TaskHandle_t handle;
|
|||||||
// has MCU controllable flash chip, firmware update supported
|
// has MCU controllable flash chip, firmware update supported
|
||||||
#define HAS_FLASH
|
#define HAS_FLASH
|
||||||
#include "Firmware.hpp"
|
#include "Firmware.hpp"
|
||||||
extern SPI_HandleTypeDef hspi1;
|
|
||||||
static Flash flash = Flash(&hspi1, FLASH_CS_GPIO_Port, FLASH_CS_Pin);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern ADC_HandleTypeDef hadc1;
|
extern ADC_HandleTypeDef hadc1;
|
||||||
@ -72,17 +72,17 @@ void App_Start() {
|
|||||||
LOG_INFO("Start");
|
LOG_INFO("Start");
|
||||||
Exti::Init();
|
Exti::Init();
|
||||||
#ifdef HAS_FLASH
|
#ifdef HAS_FLASH
|
||||||
if(!flash.isPresent()) {
|
if(!HWHAL::flash.isPresent()) {
|
||||||
LOG_CRIT("Failed to detect onboard FLASH");
|
LOG_CRIT("Failed to detect onboard FLASH");
|
||||||
LED::Error(1);
|
LED::Error(1);
|
||||||
}
|
}
|
||||||
auto fw_info = Firmware::GetFlashContentInfo(&flash);
|
auto fw_info = Firmware::GetFlashContentInfo();
|
||||||
if(fw_info.valid) {
|
if(fw_info.valid) {
|
||||||
if(fw_info.CPU_need_update) {
|
if(fw_info.CPU_need_update) {
|
||||||
// Function will not return, the device will reboot with the new firmware instead
|
// Function will not return, the device will reboot with the new firmware instead
|
||||||
// Firmware::PerformUpdate(&flash, fw_info);
|
// Firmware::PerformUpdate(&flash, fw_info);
|
||||||
}
|
}
|
||||||
if(!FPGA::Configure(&flash, fw_info.FPGA_bitstream_address, fw_info.FPGA_bitstream_size)) {
|
if(!FPGA::Configure(fw_info.FPGA_bitstream_address, fw_info.FPGA_bitstream_size)) {
|
||||||
LOG_CRIT("FPGA configuration failed");
|
LOG_CRIT("FPGA configuration failed");
|
||||||
LED::Error(3);
|
LED::Error(3);
|
||||||
}
|
}
|
||||||
@ -99,6 +99,8 @@ void App_Start() {
|
|||||||
EN_6V_GPIO_Port->BSRR = EN_6V_Pin;
|
EN_6V_GPIO_Port->BSRR = EN_6V_Pin;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
AmplitudeCal::Load();
|
||||||
|
|
||||||
if (!HW::Init()) {
|
if (!HW::Init()) {
|
||||||
LOG_CRIT("Initialization failed, unable to start");
|
LOG_CRIT("Initialization failed, unable to start");
|
||||||
LED::Error(4);
|
LED::Error(4);
|
||||||
@ -166,7 +168,7 @@ void App_Start() {
|
|||||||
HW::SetMode(HW::Mode::Idle);
|
HW::SetMode(HW::Mode::Idle);
|
||||||
sweepActive = false;
|
sweepActive = false;
|
||||||
LOG_DEBUG("Erasing FLASH in preparation for firmware update...");
|
LOG_DEBUG("Erasing FLASH in preparation for firmware update...");
|
||||||
if(flash.eraseChip()) {
|
if(HWHAL::flash.eraseRange(0, Firmware::maxSize)) {
|
||||||
LOG_DEBUG("...FLASH erased")
|
LOG_DEBUG("...FLASH erased")
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
} else {
|
} else {
|
||||||
@ -176,7 +178,7 @@ void App_Start() {
|
|||||||
break;
|
break;
|
||||||
case Protocol::PacketType::FirmwarePacket:
|
case Protocol::PacketType::FirmwarePacket:
|
||||||
LOG_INFO("Writing firmware packet at address %u", recv_packet.firmware.address);
|
LOG_INFO("Writing firmware packet at address %u", recv_packet.firmware.address);
|
||||||
if(flash.write(recv_packet.firmware.address, sizeof(recv_packet.firmware.data), recv_packet.firmware.data)) {
|
if(HWHAL::flash.write(recv_packet.firmware.address, sizeof(recv_packet.firmware.data), recv_packet.firmware.data)) {
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERR("Failed to write FLASH");
|
LOG_ERR("Failed to write FLASH");
|
||||||
@ -185,18 +187,30 @@ void App_Start() {
|
|||||||
break;
|
break;
|
||||||
case Protocol::PacketType::PerformFirmwareUpdate: {
|
case Protocol::PacketType::PerformFirmwareUpdate: {
|
||||||
LOG_INFO("Firmware update process triggered");
|
LOG_INFO("Firmware update process triggered");
|
||||||
auto fw_info = Firmware::GetFlashContentInfo(&flash);
|
auto fw_info = Firmware::GetFlashContentInfo();
|
||||||
if(fw_info.valid) {
|
if(fw_info.valid) {
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Ack);
|
||||||
// Some delay to allow communication to finish
|
// Some delay to allow communication to finish
|
||||||
vTaskDelay(100);
|
vTaskDelay(100);
|
||||||
Firmware::PerformUpdate(&flash, fw_info);
|
Firmware::PerformUpdate(fw_info);
|
||||||
// should never get here
|
// should never get here
|
||||||
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
|
Communication::SendWithoutPayload(Protocol::PacketType::Nack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
case Protocol::PacketType::RequestSourceCal:
|
||||||
|
AmplitudeCal::SendSource();
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::RequestReceiverCal:
|
||||||
|
AmplitudeCal::SendReceiver();
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::SourceCalPoint:
|
||||||
|
AmplitudeCal::AddSourcePoint(recv_packet.amplitudePoint);
|
||||||
|
break;
|
||||||
|
case Protocol::PacketType::ReceiverCalPoint:
|
||||||
|
AmplitudeCal::AddReceiverPoint(recv_packet.amplitudePoint);
|
||||||
|
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);
|
||||||
|
@ -457,6 +457,27 @@ static int16_t EncodeFirmwarePacket(const Protocol::FirmwarePacket &d, uint8_t *
|
|||||||
return 4 + Protocol::FirmwareChunkSize;
|
return 4 + Protocol::FirmwareChunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int16_t EncodeAmplitudeCorrectionPoint(
|
||||||
|
Protocol::AmplitudeCorrectionPoint d, uint8_t *buf, uint16_t bufSize) {
|
||||||
|
Encoder e(buf, bufSize);
|
||||||
|
e.add(d.totalPoints);
|
||||||
|
e.add(d.pointNum);
|
||||||
|
e.add(d.freq);
|
||||||
|
e.add(d.port1);
|
||||||
|
e.add(d.port2);
|
||||||
|
return e.getSize();
|
||||||
|
}
|
||||||
|
static Protocol::AmplitudeCorrectionPoint DecodeAmplitudeCorrectionPoint(uint8_t *buf) {
|
||||||
|
Protocol::AmplitudeCorrectionPoint d;
|
||||||
|
Decoder e(buf);
|
||||||
|
e.get(d.totalPoints);
|
||||||
|
e.get(d.pointNum);
|
||||||
|
e.get(d.freq);
|
||||||
|
e.get(d.port1);
|
||||||
|
e.get(d.port2);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
|
uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
|
||||||
if (!info || !len) {
|
if (!info || !len) {
|
||||||
info->type = PacketType::None;
|
info->type = PacketType::None;
|
||||||
@ -541,11 +562,17 @@ uint16_t Protocol::DecodeBuffer(uint8_t *buf, uint16_t len, PacketInfo *info) {
|
|||||||
case PacketType::SpectrumAnalyzerResult:
|
case PacketType::SpectrumAnalyzerResult:
|
||||||
info->spectrumResult = DecodeSpectrumAnalyzerResult(&data[4]);
|
info->spectrumResult = DecodeSpectrumAnalyzerResult(&data[4]);
|
||||||
break;
|
break;
|
||||||
|
case PacketType::SourceCalPoint:
|
||||||
|
case PacketType::ReceiverCalPoint:
|
||||||
|
info->amplitudePoint = DecodeAmplitudeCorrectionPoint(&data[4]);
|
||||||
|
break;
|
||||||
case PacketType::Ack:
|
case PacketType::Ack:
|
||||||
case PacketType::PerformFirmwareUpdate:
|
case PacketType::PerformFirmwareUpdate:
|
||||||
case PacketType::ClearFlash:
|
case PacketType::ClearFlash:
|
||||||
case PacketType::Nack:
|
case PacketType::Nack:
|
||||||
case PacketType::RequestDeviceInfo:
|
case PacketType::RequestDeviceInfo:
|
||||||
|
case PacketType::RequestReceiverCal:
|
||||||
|
case PacketType::RequestSourceCal:
|
||||||
// no payload, nothing to do
|
// no payload, nothing to do
|
||||||
break;
|
break;
|
||||||
case PacketType::None:
|
case PacketType::None:
|
||||||
@ -588,11 +615,17 @@ uint16_t Protocol::EncodePacket(const PacketInfo &packet, uint8_t *dest, uint16_
|
|||||||
case PacketType::SpectrumAnalyzerResult:
|
case PacketType::SpectrumAnalyzerResult:
|
||||||
payload_size = EncodeSpectrumAnalyzerResult(packet.spectrumResult, &dest[4], destsize - 8);
|
payload_size = EncodeSpectrumAnalyzerResult(packet.spectrumResult, &dest[4], destsize - 8);
|
||||||
break;
|
break;
|
||||||
|
case PacketType::SourceCalPoint:
|
||||||
|
case PacketType::ReceiverCalPoint:
|
||||||
|
payload_size = EncodeAmplitudeCorrectionPoint(packet.amplitudePoint, &dest[4], destsize - 8);
|
||||||
|
break;
|
||||||
case PacketType::Ack:
|
case PacketType::Ack:
|
||||||
case PacketType::PerformFirmwareUpdate:
|
case PacketType::PerformFirmwareUpdate:
|
||||||
case PacketType::ClearFlash:
|
case PacketType::ClearFlash:
|
||||||
case PacketType::Nack:
|
case PacketType::Nack:
|
||||||
case PacketType::RequestDeviceInfo:
|
case PacketType::RequestDeviceInfo:
|
||||||
|
case PacketType::RequestSourceCal:
|
||||||
|
case PacketType::RequestReceiverCal:
|
||||||
// no payload, nothing to do
|
// no payload, nothing to do
|
||||||
break;
|
break;
|
||||||
case PacketType::None:
|
case PacketType::None:
|
||||||
|
@ -134,6 +134,14 @@ using FirmwarePacket = struct _firmwarePacket {
|
|||||||
uint8_t data[FirmwareChunkSize];
|
uint8_t data[FirmwareChunkSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using AmplitudeCorrectionPoint = struct _amplitudecorrectionpoint {
|
||||||
|
uint8_t totalPoints;
|
||||||
|
uint8_t pointNum;
|
||||||
|
uint32_t freq;
|
||||||
|
int16_t port1;
|
||||||
|
int16_t port2;
|
||||||
|
};
|
||||||
|
|
||||||
enum class PacketType : uint8_t {
|
enum class PacketType : uint8_t {
|
||||||
None = 0,
|
None = 0,
|
||||||
Datapoint = 1,
|
Datapoint = 1,
|
||||||
@ -151,6 +159,10 @@ enum class PacketType : uint8_t {
|
|||||||
SpectrumAnalyzerSettings = 13,
|
SpectrumAnalyzerSettings = 13,
|
||||||
SpectrumAnalyzerResult = 14,
|
SpectrumAnalyzerResult = 14,
|
||||||
RequestDeviceInfo = 15,
|
RequestDeviceInfo = 15,
|
||||||
|
RequestSourceCal = 16,
|
||||||
|
RequestReceiverCal = 17,
|
||||||
|
SourceCalPoint = 18,
|
||||||
|
ReceiverCalPoint = 19,
|
||||||
};
|
};
|
||||||
|
|
||||||
using PacketInfo = struct _packetinfo {
|
using PacketInfo = struct _packetinfo {
|
||||||
@ -166,6 +178,7 @@ using PacketInfo = struct _packetinfo {
|
|||||||
ManualStatus status;
|
ManualStatus status;
|
||||||
SpectrumAnalyzerSettings spectrumSettings;
|
SpectrumAnalyzerSettings spectrumSettings;
|
||||||
SpectrumAnalyzerResult spectrumResult;
|
SpectrumAnalyzerResult spectrumResult;
|
||||||
|
AmplitudeCorrectionPoint amplitudePoint;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "FPGA_HAL.hpp"
|
#include "FPGA_HAL.hpp"
|
||||||
#include <complex>
|
#include <complex>
|
||||||
|
#include "HW_HAL.hpp"
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_DEBUG
|
#define LOG_LEVEL LOG_LEVEL_DEBUG
|
||||||
#define LOG_MODULE "FPGA"
|
#define LOG_MODULE "FPGA"
|
||||||
@ -33,7 +34,7 @@ void FPGA::WriteRegister(FPGA::Reg reg, uint16_t value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FPGA::Configure(Flash *f, uint32_t start_address, uint32_t bitstream_size) {
|
bool FPGA::Configure(uint32_t start_address, uint32_t bitstream_size) {
|
||||||
if(!PROGRAM_B.gpio) {
|
if(!PROGRAM_B.gpio) {
|
||||||
LOG_WARN("PROGRAM_B not defined, assuming FPGA configures itself in master configuration");
|
LOG_WARN("PROGRAM_B not defined, assuming FPGA configures itself in master configuration");
|
||||||
// wait too allow enough time for FPGA configuration
|
// wait too allow enough time for FPGA configuration
|
||||||
@ -64,7 +65,7 @@ bool FPGA::Configure(Flash *f, uint32_t start_address, uint32_t bitstream_size)
|
|||||||
}
|
}
|
||||||
// TODO this part might be doable with the DMA instead of the buffer
|
// TODO this part might be doable with the DMA instead of the buffer
|
||||||
// get chunk of bitstream from flash...
|
// get chunk of bitstream from flash...
|
||||||
f->read(start_address, size, buf);
|
HWHAL::flash.read(start_address, size, buf);
|
||||||
// ... and pass it on to FPGA
|
// ... and pass it on to FPGA
|
||||||
HAL_SPI_Transmit(&CONFIGURATION_SPI, buf, size, 100);
|
HAL_SPI_Transmit(&CONFIGURATION_SPI, buf, size, 100);
|
||||||
bitstream_size -= size;
|
bitstream_size -= size;
|
||||||
|
@ -105,7 +105,7 @@ enum class Window {
|
|||||||
Flattop = 0x03,
|
Flattop = 0x03,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Configure(Flash *f, uint32_t start_address, uint32_t bitstream_size);
|
bool Configure(uint32_t start_address, uint32_t bitstream_size);
|
||||||
|
|
||||||
using HaltedCallback = void(*)(void);
|
using HaltedCallback = void(*)(void);
|
||||||
bool Init(HaltedCallback cb = nullptr);
|
bool Init(HaltedCallback cb = nullptr);
|
||||||
|
@ -29,7 +29,7 @@ void Flash::read(uint32_t address, uint16_t length, void *dest) {
|
|||||||
CS(true);
|
CS(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Flash::write(uint32_t address, uint16_t length, uint8_t *src) {
|
bool Flash::write(uint32_t address, uint16_t length, void *src) {
|
||||||
if((address & 0xFF) != 0 || length%256 != 0) {
|
if((address & 0xFF) != 0 || length%256 != 0) {
|
||||||
// only writes to complete pages allowed
|
// only writes to complete pages allowed
|
||||||
LOG_ERR("Invalid write address/size: %lu/%u", address, length);
|
LOG_ERR("Invalid write address/size: %lu/%u", address, length);
|
||||||
@ -49,7 +49,7 @@ bool Flash::write(uint32_t address, uint16_t length, uint8_t *src) {
|
|||||||
// issue read command
|
// issue read command
|
||||||
HAL_SPI_Transmit(spi, cmd, 4, 100);
|
HAL_SPI_Transmit(spi, cmd, 4, 100);
|
||||||
// write data
|
// write data
|
||||||
HAL_SPI_Transmit(spi, src, 256, 1000);
|
HAL_SPI_Transmit(spi, (uint8_t*) src, 256, 1000);
|
||||||
CS(true);
|
CS(true);
|
||||||
if(!WaitBusy(20)) {
|
if(!WaitBusy(20)) {
|
||||||
LOG_ERR("Write timed out");
|
LOG_ERR("Write timed out");
|
||||||
@ -78,16 +78,66 @@ void Flash::EnableWrite() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Flash::eraseChip() {
|
bool Flash::eraseChip() {
|
||||||
LOG_INFO("Erasing...");
|
LOG_INFO("Erasing chip...");
|
||||||
EnableWrite();
|
EnableWrite();
|
||||||
CS(false);
|
CS(false);
|
||||||
// enable write latch
|
|
||||||
uint8_t chip_erase = 0x60;
|
uint8_t chip_erase = 0x60;
|
||||||
HAL_SPI_Transmit(spi, &chip_erase, 1, 100);
|
HAL_SPI_Transmit(spi, &chip_erase, 1, 100);
|
||||||
CS(true);
|
CS(true);
|
||||||
return WaitBusy(25000);
|
return WaitBusy(25000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Flash::eraseSector(uint32_t address) {
|
||||||
|
// align address with sector address
|
||||||
|
address -= address % SectorSize;
|
||||||
|
LOG_INFO("Erasing sector at %lu", address);
|
||||||
|
EnableWrite();
|
||||||
|
CS(false);
|
||||||
|
uint8_t cmd[4] = {
|
||||||
|
0x20,
|
||||||
|
(uint8_t) (address >> 16) & 0xFF,
|
||||||
|
(uint8_t) (address >> 8) & 0xFF,
|
||||||
|
(uint8_t) (address & 0xFF),
|
||||||
|
};
|
||||||
|
HAL_SPI_Transmit(spi, cmd, 4, 100);
|
||||||
|
CS(true);
|
||||||
|
return WaitBusy(25000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Flash::erase32Block(uint32_t address) {
|
||||||
|
// align address with block address
|
||||||
|
address -= address % Block32Size;
|
||||||
|
LOG_INFO("Erasing 32kB block at %lu", address);
|
||||||
|
EnableWrite();
|
||||||
|
CS(false);
|
||||||
|
uint8_t cmd[4] = {
|
||||||
|
0x52,
|
||||||
|
(uint8_t) (address >> 16) & 0xFF,
|
||||||
|
(uint8_t) (address >> 8) & 0xFF,
|
||||||
|
(uint8_t) (address & 0xFF),
|
||||||
|
};
|
||||||
|
HAL_SPI_Transmit(spi, cmd, 4, 100);
|
||||||
|
CS(true);
|
||||||
|
return WaitBusy(25000);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Flash::erase64Block(uint32_t address) {
|
||||||
|
// align address with block address
|
||||||
|
address -= address % Block64Size;
|
||||||
|
LOG_INFO("Erasing 64kB block at %lu", address);
|
||||||
|
EnableWrite();
|
||||||
|
CS(false);
|
||||||
|
uint8_t cmd[4] = {
|
||||||
|
0xD8,
|
||||||
|
(uint8_t) (address >> 16) & 0xFF,
|
||||||
|
(uint8_t) (address >> 8) & 0xFF,
|
||||||
|
(uint8_t) (address & 0xFF),
|
||||||
|
};
|
||||||
|
HAL_SPI_Transmit(spi, cmd, 4, 100);
|
||||||
|
CS(true);
|
||||||
|
return WaitBusy(25000);
|
||||||
|
}
|
||||||
|
|
||||||
void Flash::initiateRead(uint32_t address) {
|
void Flash::initiateRead(uint32_t address) {
|
||||||
address &= 0x00FFFFFF;
|
address &= 0x00FFFFFF;
|
||||||
CS(false);
|
CS(false);
|
||||||
@ -120,3 +170,38 @@ bool Flash::WaitBusy(uint32_t timeout) {
|
|||||||
LOG_ERR("Timeout occured");
|
LOG_ERR("Timeout occured");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Flash::eraseRange(uint32_t start, uint32_t len) {
|
||||||
|
if(start % SectorSize != 0) {
|
||||||
|
LOG_ERR("Start address of range has to be sector aligned (is %lu)", start);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(len % SectorSize != 0) {
|
||||||
|
LOG_ERR("Length of range has to be multiple of sector size (is %lu)", len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint32_t erased_len = 0;
|
||||||
|
while(erased_len < len) {
|
||||||
|
uint32_t remaining = len - erased_len;
|
||||||
|
if(remaining >= Block64Size && start % Block64Size == 0) {
|
||||||
|
erase64Block(start);
|
||||||
|
erased_len += Block64Size;
|
||||||
|
start += Block64Size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(remaining >= Block32Size && start % Block32Size == 0) {
|
||||||
|
erase32Block(start);
|
||||||
|
erased_len += Block32Size;
|
||||||
|
start += Block32Size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(remaining >= SectorSize && start % SectorSize == 0) {
|
||||||
|
eraseSector(start);
|
||||||
|
erased_len += SectorSize;
|
||||||
|
start += SectorSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Should never get here
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -17,8 +17,12 @@ public:
|
|||||||
|
|
||||||
bool isPresent();
|
bool isPresent();
|
||||||
void read(uint32_t address, uint16_t length, void *dest);
|
void read(uint32_t address, uint16_t length, void *dest);
|
||||||
bool write(uint32_t address, uint16_t length, uint8_t *src);
|
bool write(uint32_t address, uint16_t length, void *src);
|
||||||
bool eraseChip();
|
bool eraseChip();
|
||||||
|
bool eraseSector(uint32_t address);
|
||||||
|
bool erase32Block(uint32_t address);
|
||||||
|
bool erase64Block(uint32_t address);
|
||||||
|
bool eraseRange(uint32_t start, uint32_t len);
|
||||||
// Starts the reading process without actually reading any bytes
|
// Starts the reading process without actually reading any bytes
|
||||||
void initiateRead(uint32_t address);
|
void initiateRead(uint32_t address);
|
||||||
const SPI_HandleTypeDef* const getSpi() const {
|
const SPI_HandleTypeDef* const getSpi() const {
|
||||||
@ -26,6 +30,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr uint32_t SectorSize = 4096;
|
||||||
|
static constexpr uint32_t Block32Size = 32768;
|
||||||
|
static constexpr uint32_t Block64Size = 65536;
|
||||||
void CS(bool high) {
|
void CS(bool high) {
|
||||||
if(high) {
|
if(high) {
|
||||||
CS_gpio->BSRR = CS_pin;
|
CS_gpio->BSRR = CS_pin;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Protocol.hpp"
|
#include "Protocol.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "HW_HAL.hpp"
|
||||||
|
|
||||||
#define LOG_LEVEL LOG_LEVEL_INFO
|
#define LOG_LEVEL LOG_LEVEL_INFO
|
||||||
#define LOG_MODULE "FW"
|
#define LOG_MODULE "FW"
|
||||||
@ -19,11 +20,11 @@ using Header = struct {
|
|||||||
uint32_t crc;
|
uint32_t crc;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
Firmware::Info Firmware::GetFlashContentInfo(Flash *f) {
|
Firmware::Info Firmware::GetFlashContentInfo() {
|
||||||
Info ret;
|
Info ret;
|
||||||
memset(&ret, 0, sizeof(ret));
|
memset(&ret, 0, sizeof(ret));
|
||||||
Header h;
|
Header h;
|
||||||
f->read(0, sizeof(h), &h);
|
HWHAL::flash.read(0, sizeof(h), &h);
|
||||||
// sanity check values
|
// sanity check values
|
||||||
if (memcmp(&h.magic, "VNA!",
|
if (memcmp(&h.magic, "VNA!",
|
||||||
4) || h.FPGA_start == UINT32_MAX || h.FPGA_size > FPGA_MAXSIZE
|
4) || h.FPGA_start == UINT32_MAX || h.FPGA_size > FPGA_MAXSIZE
|
||||||
@ -40,7 +41,7 @@ Firmware::Info Firmware::GetFlashContentInfo(Flash *f) {
|
|||||||
if (h.FPGA_size + h.CPU_size - checked_size < read_size) {
|
if (h.FPGA_size + h.CPU_size - checked_size < read_size) {
|
||||||
read_size = h.FPGA_size + h.CPU_size - checked_size;
|
read_size = h.FPGA_size + h.CPU_size - checked_size;
|
||||||
}
|
}
|
||||||
f->read(h.FPGA_start + checked_size, read_size, buf);
|
HWHAL::flash.read(h.FPGA_start + checked_size, read_size, buf);
|
||||||
crc = Protocol::CRC32(crc, buf, read_size);
|
crc = Protocol::CRC32(crc, buf, read_size);
|
||||||
checked_size += read_size;
|
checked_size += read_size;
|
||||||
}
|
}
|
||||||
@ -55,7 +56,7 @@ Firmware::Info Firmware::GetFlashContentInfo(Flash *f) {
|
|||||||
if (h.CPU_size - checked_size < read_size) {
|
if (h.CPU_size - checked_size < read_size) {
|
||||||
read_size = h.CPU_size - checked_size;
|
read_size = h.CPU_size - checked_size;
|
||||||
}
|
}
|
||||||
f->read(h.CPU_start + checked_size, read_size, buf);
|
HWHAL::flash.read(h.CPU_start + checked_size, read_size, buf);
|
||||||
if(memcmp(buf, (void*)(0x8000000+checked_size), read_size)) {
|
if(memcmp(buf, (void*)(0x8000000+checked_size), read_size)) {
|
||||||
LOG_INFO("Difference to CPU firmware in external FLASH detected, update required");
|
LOG_INFO("Difference to CPU firmware in external FLASH detected, update required");
|
||||||
ret.CPU_need_update = true;
|
ret.CPU_need_update = true;
|
||||||
@ -158,7 +159,7 @@ static void copy_flash(uint32_t size, SPI_TypeDef *spi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Firmware::PerformUpdate(Flash *f, Info info) {
|
void Firmware::PerformUpdate(Info info) {
|
||||||
if(!info.valid) {
|
if(!info.valid) {
|
||||||
LOG_ERR("Invalid firmware data, not performing update");
|
LOG_ERR("Invalid firmware data, not performing update");
|
||||||
return;
|
return;
|
||||||
@ -174,8 +175,8 @@ void Firmware::PerformUpdate(Flash *f, Info info) {
|
|||||||
FLASH_WaitForLastOperation(50000);
|
FLASH_WaitForLastOperation(50000);
|
||||||
|
|
||||||
// Initiate readback from flash at CPU firmware start address
|
// Initiate readback from flash at CPU firmware start address
|
||||||
f->initiateRead(info.CPU_image_address);
|
HWHAL::flash.initiateRead(info.CPU_image_address);
|
||||||
|
|
||||||
copy_flash(info.CPU_image_size, f->getSpi()->Instance);
|
copy_flash(info.CPU_image_size, HWHAL::flash.getSpi()->Instance);
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
namespace Firmware {
|
namespace Firmware {
|
||||||
|
|
||||||
|
static constexpr uint32_t maxSize = 1048576;
|
||||||
|
|
||||||
using Info = struct info {
|
using Info = struct info {
|
||||||
uint32_t FPGA_bitstream_address;
|
uint32_t FPGA_bitstream_address;
|
||||||
uint32_t FPGA_bitstream_size;
|
uint32_t FPGA_bitstream_size;
|
||||||
@ -21,8 +23,8 @@ using Info = struct info {
|
|||||||
bool CPU_need_update;
|
bool CPU_need_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
Info GetFlashContentInfo(Flash *f);
|
Info GetFlashContentInfo();
|
||||||
void PerformUpdate(Flash *f, Info info);
|
void PerformUpdate(Info info);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,3 +3,5 @@
|
|||||||
Si5351C HWHAL::Si5351 = Si5351C(&hi2c2, 26000000);
|
Si5351C HWHAL::Si5351 = Si5351C(&hi2c2, 26000000);
|
||||||
MAX2871 HWHAL::Source = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
|
MAX2871 HWHAL::Source = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
|
||||||
MAX2871 HWHAL::LO1 = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
|
MAX2871 HWHAL::LO1 = MAX2871(&hspi1, FPGA_CS_GPIO_Port, FPGA_CS_Pin, nullptr, 0, nullptr, 0, nullptr, 0, GPIOA, GPIO_PIN_6);
|
||||||
|
extern SPI_HandleTypeDef hspi1;
|
||||||
|
Flash HWHAL::flash = Flash(&hspi1, FLASH_CS_GPIO_Port, FLASH_CS_Pin);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "Si5351C.hpp"
|
#include "Si5351C.hpp"
|
||||||
#include "max2871.hpp"
|
#include "max2871.hpp"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "Flash.hpp"
|
||||||
|
|
||||||
extern I2C_HandleTypeDef hi2c2;
|
extern I2C_HandleTypeDef hi2c2;
|
||||||
extern SPI_HandleTypeDef hspi1;
|
extern SPI_HandleTypeDef hspi1;
|
||||||
@ -13,6 +14,7 @@ namespace HWHAL {
|
|||||||
extern Si5351C Si5351;
|
extern Si5351C Si5351;
|
||||||
extern MAX2871 Source;
|
extern MAX2871 Source;
|
||||||
extern MAX2871 LO1;
|
extern MAX2871 LO1;
|
||||||
|
extern Flash flash;
|
||||||
|
|
||||||
// Mapping of the Si5351 channels to PLLs/Mixers
|
// Mapping of the Si5351 channels to PLLs/Mixers
|
||||||
namespace SiChannel {
|
namespace SiChannel {
|
||||||
|
Loading…
Reference in New Issue
Block a user