mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
First actual disk visualisations!
This commit is contained in:
@@ -70,6 +70,7 @@ std::shared_ptr<TrackDataFlux> Decoder::decodeToSectors(
|
||||
_trackdata = std::make_shared<TrackDataFlux>();
|
||||
_trackdata->fluxmap = fluxmap;
|
||||
_trackdata->trackInfo = trackInfo;
|
||||
_trackdata->rotationalPeriod = globalConfig()->drive().rotational_period_ms() * 1e6;
|
||||
|
||||
FluxmapReader fmr(*fluxmap);
|
||||
_fmr = &fmr;
|
||||
|
||||
@@ -23,6 +23,7 @@ struct TrackDataFlux
|
||||
std::shared_ptr<const Fluxmap> fluxmap;
|
||||
std::vector<std::shared_ptr<const Record>> records;
|
||||
std::vector<std::shared_ptr<const Sector>> sectors;
|
||||
nanoseconds_t rotationalPeriod;
|
||||
};
|
||||
|
||||
struct TrackFlux
|
||||
|
||||
@@ -21,7 +21,6 @@ public:
|
||||
_fluxVisualiserWidget = FluxVisualiserWidget::create();
|
||||
_mainWindow->fluxViewContainer->layout()->addWidget(
|
||||
_fluxVisualiserWidget);
|
||||
_fluxVisualiserWidget->refresh();
|
||||
|
||||
connect(_mainWindow->fluxSideComboBox,
|
||||
QOverload<int>::of(&QComboBox::activated),
|
||||
@@ -29,6 +28,17 @@ public:
|
||||
&FluxVisualiserWidget::setVisibleSide);
|
||||
}
|
||||
|
||||
public:
|
||||
void setTrackData(std::shared_ptr<const TrackFlux> track)
|
||||
{
|
||||
_fluxVisualiserWidget->setTrackData(track);
|
||||
}
|
||||
|
||||
void setDiskData(std::shared_ptr<const DiskFlux> disk)
|
||||
{
|
||||
_fluxVisualiserWidget->setDiskData(disk);
|
||||
}
|
||||
|
||||
private:
|
||||
MainWindow* _mainWindow;
|
||||
FluxVisualiserWidget* _fluxVisualiserWidget;
|
||||
|
||||
@@ -4,6 +4,10 @@ class MainWindow;
|
||||
|
||||
class FluxComponent
|
||||
{
|
||||
public:
|
||||
virtual void setTrackData(std::shared_ptr<const TrackFlux> track) = 0;
|
||||
virtual void setDiskData(std::shared_ptr<const DiskFlux> disk) = 0;
|
||||
|
||||
public:
|
||||
static FluxComponent* create(MainWindow* mainWindow);
|
||||
};
|
||||
|
||||
@@ -3,21 +3,26 @@
|
||||
#include "lib/fluxmap.h"
|
||||
#include "lib/flux.h"
|
||||
#include "lib/layout.h"
|
||||
#include "lib/decoders/fluxmapreader.h"
|
||||
#include "globals.h"
|
||||
#include "fluxvisualiserwidget.h"
|
||||
#include <QWheelEvent>
|
||||
#include <QFrame>
|
||||
#include <QConicalGradient>
|
||||
#include <range/v3/all.hpp>
|
||||
|
||||
W_OBJECT_IMPL(FluxVisualiserWidget)
|
||||
|
||||
class DiskFlux;
|
||||
class TrackFlux;
|
||||
|
||||
static const int TRACKS = 82;
|
||||
static constexpr int SIDES = 2;
|
||||
static constexpr int TRACKS = 82;
|
||||
static constexpr int SLOTS = 300;
|
||||
|
||||
static const float VBORDER = 1.0;
|
||||
static const float VOUTER_RADIUS = 50.0;
|
||||
static const float VINNER_RADIUS = 10.0;
|
||||
static constexpr float VBORDER = 1.0;
|
||||
static constexpr float VOUTER_RADIUS = 50.0;
|
||||
static constexpr float VINNER_RADIUS = 10.0;
|
||||
|
||||
class FluxVisualiserWidgetImpl : public FluxVisualiserWidget
|
||||
{
|
||||
@@ -36,6 +41,8 @@ public:
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setFrameShape(QFrame::NoFrame);
|
||||
setScene(_scene);
|
||||
|
||||
recompute();
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -48,7 +55,7 @@ public:
|
||||
void setVisibleSide(int mode)
|
||||
{
|
||||
_viewMode = mode;
|
||||
refresh();
|
||||
redraw();
|
||||
}
|
||||
|
||||
void setTrackData(std::shared_ptr<const TrackFlux> track)
|
||||
@@ -56,35 +63,46 @@ public:
|
||||
key_t key = {
|
||||
track->trackInfo->physicalTrack, track->trackInfo->physicalSide};
|
||||
_tracks[key] = track;
|
||||
|
||||
recompute(
|
||||
track->trackInfo->physicalSide, track->trackInfo->physicalTrack);
|
||||
}
|
||||
|
||||
void setDiskData(std::shared_ptr<const DiskFlux> disk)
|
||||
{
|
||||
_tracks.clear();
|
||||
for (const auto& track : disk->tracks)
|
||||
{
|
||||
key_t key = {track->trackInfo->physicalTrack,
|
||||
track->trackInfo->physicalSide};
|
||||
_tracks[key] = track;
|
||||
}
|
||||
|
||||
recompute();
|
||||
}
|
||||
|
||||
public:
|
||||
void refresh() override
|
||||
private:
|
||||
void redraw()
|
||||
{
|
||||
_scene->clear();
|
||||
|
||||
switch (_viewMode)
|
||||
{
|
||||
case SIDE_0:
|
||||
drawSide(VOUTER_RADIUS, VOUTER_RADIUS, 0);
|
||||
_scene->setSceneRect(
|
||||
0.0, 0.0, VOUTER_RADIUS * 2, VOUTER_RADIUS * 2);
|
||||
break;
|
||||
|
||||
case SIDE_1:
|
||||
drawSide(VOUTER_RADIUS, VOUTER_RADIUS);
|
||||
drawSide(VOUTER_RADIUS, VOUTER_RADIUS, 1);
|
||||
_scene->setSceneRect(
|
||||
0.0, 0.0, VOUTER_RADIUS * 2, VOUTER_RADIUS * 2);
|
||||
break;
|
||||
|
||||
case BOTH_SIDES:
|
||||
drawSide(VOUTER_RADIUS, VOUTER_RADIUS);
|
||||
drawSide(VOUTER_RADIUS, VOUTER_RADIUS * 3 + VBORDER);
|
||||
drawSide(VOUTER_RADIUS, VOUTER_RADIUS, 0);
|
||||
drawSide(VOUTER_RADIUS, VOUTER_RADIUS * 3 + VBORDER, 1);
|
||||
|
||||
_scene->setSceneRect(
|
||||
0.0, 0.0, VOUTER_RADIUS * 2, VOUTER_RADIUS * 4 + VBORDER);
|
||||
@@ -94,26 +112,145 @@ public:
|
||||
fitInView(sceneRect(), Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
private:
|
||||
void drawSide(float x, float y)
|
||||
void drawSide(float x, float y, int side)
|
||||
{
|
||||
QPen black(QColorConstants::Black);
|
||||
black.setWidth(0);
|
||||
|
||||
float step = (VOUTER_RADIUS - VINNER_RADIUS) / TRACKS;
|
||||
for (int track = 0; track < 82; track++)
|
||||
{
|
||||
QConicalGradient gradient(x, y, 0);
|
||||
gradient.setStops(_viewData[side][track].gradientStops);
|
||||
QBrush brush(gradient);
|
||||
QPen pen(brush, step * 1.15);
|
||||
|
||||
float r = VOUTER_RADIUS - track * step;
|
||||
_scene->addEllipse(x - r, y - r, r * 2, r * 2, black);
|
||||
_scene->addEllipse(x - r, y - r, r * 2, r * 2, pen);
|
||||
}
|
||||
}
|
||||
|
||||
void recompute()
|
||||
{
|
||||
for (int side = 0; side < SIDES; side++)
|
||||
for (int track = 0; track < TRACKS; track++)
|
||||
recompute(side, track);
|
||||
}
|
||||
|
||||
void recompute(int side, int track)
|
||||
{
|
||||
VData& vdata = _viewData[side][track];
|
||||
QGradientStops& stops = vdata.gradientStops;
|
||||
stops.clear();
|
||||
ranges::fill(vdata.slot, VSlot());
|
||||
|
||||
auto it = _tracks.find(key_t(track, side));
|
||||
if (it != _tracks.end())
|
||||
{
|
||||
const TrackFlux& trackFlux = *it->second;
|
||||
for (auto& trackDataFlux : trackFlux.trackDatas)
|
||||
{
|
||||
nanoseconds_t rotationalPeriod =
|
||||
trackDataFlux->rotationalPeriod;
|
||||
if (rotationalPeriod == 0.0)
|
||||
rotationalPeriod = 200e6;
|
||||
const Fluxmap& fm = *trackDataFlux->fluxmap;
|
||||
FluxmapReader fmr(fm);
|
||||
|
||||
fmr.seekToIndexMark();
|
||||
nanoseconds_t indexTimeNs = fmr.tell().ns();
|
||||
fmr.rewind();
|
||||
|
||||
int slotIndex = -1;
|
||||
for (;;)
|
||||
{
|
||||
int event;
|
||||
unsigned ticks;
|
||||
fmr.getNextEvent(event, ticks);
|
||||
|
||||
if (event & F_BIT_PULSE)
|
||||
{
|
||||
nanoseconds_t ns = fmr.tell().ns();
|
||||
while (ns < indexTimeNs)
|
||||
ns += rotationalPeriod;
|
||||
ns = fmod(ns - indexTimeNs, rotationalPeriod);
|
||||
|
||||
int newIndex = (ns / rotationalPeriod) * SLOTS;
|
||||
if (slotIndex != -1)
|
||||
{
|
||||
while (
|
||||
(slotIndex < newIndex) && (slotIndex < SLOTS))
|
||||
{
|
||||
vdata.slot[slotIndex].count++;
|
||||
slotIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
vdata.slot[newIndex].pulses++;
|
||||
slotIndex = newIndex;
|
||||
}
|
||||
|
||||
if (event & F_EOF)
|
||||
break;
|
||||
}
|
||||
|
||||
if (slotIndex != -1)
|
||||
vdata.slot[slotIndex].count++;
|
||||
}
|
||||
|
||||
float maxDensity = 0.0;
|
||||
for (int i = 0; i < SLOTS; i++)
|
||||
{
|
||||
VSlot& slot = vdata.slot[i];
|
||||
if (slot.count != 0)
|
||||
{
|
||||
float factor = (float)slot.pulses / (float)slot.count;
|
||||
maxDensity = std::max(maxDensity, factor);
|
||||
}
|
||||
}
|
||||
maxDensity = 300;
|
||||
|
||||
for (int i = 0; i < SLOTS; i++)
|
||||
{
|
||||
VSlot& slot = vdata.slot[i];
|
||||
if (slot.count == 0)
|
||||
stops.append(
|
||||
QPair((float)i / SLOTS, QColorConstants::LightGray));
|
||||
else
|
||||
{
|
||||
float factor =
|
||||
(float)slot.pulses / (float)slot.count / maxDensity;
|
||||
int c = factor * 255.0;
|
||||
stops.append(QPair((float)i / SLOTS, QColor(c, c, c)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stops.empty())
|
||||
{
|
||||
stops.append(QPair(0.0, QColorConstants::LightGray));
|
||||
stops.append(QPair(1.0, QColorConstants::LightGray));
|
||||
}
|
||||
|
||||
redraw();
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::pair<unsigned, unsigned> key_t;
|
||||
|
||||
struct VSlot
|
||||
{
|
||||
int count;
|
||||
int pulses;
|
||||
};
|
||||
|
||||
struct VData
|
||||
{
|
||||
QGradientStops gradientStops;
|
||||
VSlot slot[SLOTS];
|
||||
};
|
||||
|
||||
QGraphicsScene* _scene;
|
||||
std::map<key_t, std::shared_ptr<const TrackFlux>> _tracks;
|
||||
int _viewMode = BOTH_SIDES;
|
||||
VData _viewData[SIDES][TRACKS];
|
||||
};
|
||||
|
||||
FluxVisualiserWidget* FluxVisualiserWidget::create()
|
||||
|
||||
@@ -7,9 +7,6 @@ class FluxVisualiserWidget : public QGraphicsView
|
||||
W_OBJECT(FluxVisualiserWidget)
|
||||
|
||||
public:
|
||||
virtual void refresh() = 0;
|
||||
W_SLOT(refresh)
|
||||
|
||||
virtual void setVisibleSide(int mode) = 0;
|
||||
W_SLOT(setVisibleSide)
|
||||
|
||||
|
||||
@@ -9,7 +9,12 @@
|
||||
#include <QThreadPool>
|
||||
#include <QtConcurrent>
|
||||
|
||||
class TrackFlux;
|
||||
class DiskFlux;
|
||||
|
||||
Q_DECLARE_METATYPE(const ConfigProto*)
|
||||
W_REGISTER_ARGTYPE(std::shared_ptr<const TrackFlux>)
|
||||
W_REGISTER_ARGTYPE(std::shared_ptr<const DiskFlux>)
|
||||
|
||||
extern QThreadPool workerThreadPool;
|
||||
|
||||
|
||||
@@ -37,15 +37,6 @@ public:
|
||||
&QAbstractButton::clicked,
|
||||
this,
|
||||
&MainWindowImpl::readDisk);
|
||||
|
||||
connect(revolutionsSlider,
|
||||
&QSlider::valueChanged,
|
||||
revolutionsSpinBox,
|
||||
&QSpinBox::setValue);
|
||||
connect(revolutionsSpinBox,
|
||||
QOverload<int>::of(&QSpinBox::valueChanged),
|
||||
revolutionsSlider,
|
||||
&QSlider::setValue);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -56,6 +47,18 @@ public:
|
||||
{
|
||||
},
|
||||
|
||||
/* A track has been read. */
|
||||
[&](const TrackReadLogMessage& m)
|
||||
{
|
||||
_fluxComponent->setTrackData(m.track);
|
||||
},
|
||||
|
||||
/* A complete disk has been read. */
|
||||
[&](const DiskReadLogMessage& m)
|
||||
{
|
||||
_fluxComponent->setDiskData(m.disk);
|
||||
},
|
||||
|
||||
/* Large-scale operation start. */
|
||||
[this](const BeginOperationLogMessage& m)
|
||||
{
|
||||
|
||||
@@ -347,118 +347,6 @@
|
||||
<string>Flux view</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By index pulse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By sector number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Revolution:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSlider" name="revolutionsSlider">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::TicksAbove</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="revolutionsSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Alignment:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QFrame" name="fluxViewContainer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QFrame {
|
||||
background: white;
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4" stretch="1,0">
|
||||
<item>
|
||||
@@ -498,6 +386,75 @@ background: white;
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QFrame" name="fluxViewContainer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QFrame {
|
||||
background: white;
|
||||
}
|
||||
</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Alignment:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By index pulse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>By sector number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
|
||||
Reference in New Issue
Block a user