Skip to content

Commit

Permalink
First actual disk visualisations!
Browse files Browse the repository at this point in the history
  • Loading branch information
davidgiven committed Jan 18, 2024
1 parent 9e2d6f8 commit 4faf936
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 135 deletions.
1 change: 1 addition & 0 deletions lib/decoders/decoders.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions lib/flux.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion src/gui2/fluxcomponent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,24 @@ class FluxComponentImpl :
_fluxVisualiserWidget = FluxVisualiserWidget::create();
_mainWindow->fluxViewContainer->layout()->addWidget(
_fluxVisualiserWidget);
_fluxVisualiserWidget->refresh();

connect(_mainWindow->fluxSideComboBox,
QOverload<int>::of(&QComboBox::activated),
_fluxVisualiserWidget,
&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;
Expand Down
4 changes: 4 additions & 0 deletions src/gui2/fluxcomponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
169 changes: 153 additions & 16 deletions src/gui2/fluxvisualiserwidget.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -36,6 +41,8 @@ class FluxVisualiserWidgetImpl : public FluxVisualiserWidget
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setFrameShape(QFrame::NoFrame);
setScene(_scene);

recompute();
}

public:
Expand All @@ -48,43 +55,54 @@ class FluxVisualiserWidgetImpl : public FluxVisualiserWidget
void setVisibleSide(int mode)
{
_viewMode = mode;
refresh();
redraw();
}

void setTrackData(std::shared_ptr<const TrackFlux> track)
{
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);
Expand All @@ -94,26 +112,145 @@ class FluxVisualiserWidgetImpl : public FluxVisualiserWidget
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()
Expand Down
3 changes: 0 additions & 3 deletions src/gui2/fluxvisualiserwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
5 changes: 5 additions & 0 deletions src/gui2/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
21 changes: 12 additions & 9 deletions src/gui2/mainwindow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,6 @@ class MainWindowImpl : public MainWindow
&QAbstractButton::clicked,
this,
&MainWindowImpl::readDisk);

connect(revolutionsSlider,
&QSlider::valueChanged,
revolutionsSpinBox,
&QSpinBox::setValue);
connect(revolutionsSpinBox,
QOverload<int>::of(&QSpinBox::valueChanged),
revolutionsSlider,
&QSlider::setValue);
}

public:
Expand All @@ -56,6 +47,18 @@ class MainWindowImpl : public MainWindow
{
},

/* 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)
{
Expand Down
Loading

0 comments on commit 4faf936

Please sign in to comment.