mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Do a very basic read/write visualisation. It looks like suck.
This commit is contained in:
@@ -50,4 +50,7 @@ private:
|
||||
std::stringstream _stream;
|
||||
};
|
||||
|
||||
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,25 +6,10 @@
|
||||
#include "fmt/format.h"
|
||||
#include "logger.h"
|
||||
|
||||
template <class... Ts>
|
||||
struct overloaded : Ts...
|
||||
{
|
||||
using Ts::operator()...;
|
||||
};
|
||||
template <class... Ts>
|
||||
overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
static bool indented = false;
|
||||
static std::function<void(std::shared_ptr<const AnyLogMessage>)> loggerImpl =
|
||||
Logger::textLogger;
|
||||
|
||||
static void indent()
|
||||
{
|
||||
if (!indented)
|
||||
std::cout << " ";
|
||||
indented = false;
|
||||
}
|
||||
|
||||
Logger& Logger::operator<<(std::shared_ptr<const AnyLogMessage> message)
|
||||
{
|
||||
loggerImpl(message);
|
||||
@@ -45,6 +30,13 @@ void Logger::textLogger(std::shared_ptr<const AnyLogMessage> message)
|
||||
std::string Logger::toString(const AnyLogMessage& message)
|
||||
{
|
||||
std::stringstream stream;
|
||||
|
||||
auto indent = [&]() {
|
||||
if (!indented)
|
||||
stream << " ";
|
||||
indented = false;
|
||||
};
|
||||
|
||||
std::visit(
|
||||
overloaded{
|
||||
/* Fallback --- do nothing */
|
||||
@@ -66,8 +58,15 @@ std::string Logger::toString(const AnyLogMessage& message)
|
||||
60e9 / m.rotationalPeriod);
|
||||
},
|
||||
|
||||
/* Indicates that we're working on a given cylinder and head */
|
||||
[&](const DiskContextLogMessage& m)
|
||||
/* Indicates that we're starting a write operation. */
|
||||
[&](const BeginWriteOperationLogMessage& m)
|
||||
{
|
||||
stream << fmt::format("{:2}.{}: ", m.cylinder, m.head);
|
||||
indented = true;
|
||||
},
|
||||
|
||||
/* Indicates that we're starting a read operation. */
|
||||
[&](const BeginReadOperationLogMessage& m)
|
||||
{
|
||||
stream << fmt::format("{:2}.{}: ", m.cylinder, m.head);
|
||||
indented = true;
|
||||
|
||||
14
lib/logger.h
14
lib/logger.h
@@ -15,12 +15,6 @@ struct EndSpeedOperationLogMessage
|
||||
nanoseconds_t rotationalPeriod;
|
||||
};
|
||||
|
||||
struct DiskContextLogMessage
|
||||
{
|
||||
unsigned cylinder;
|
||||
unsigned head;
|
||||
};
|
||||
|
||||
struct SingleReadLogMessage
|
||||
{
|
||||
std::shared_ptr<TrackDataFlux> trackDataFlux;
|
||||
@@ -34,13 +28,20 @@ struct TrackReadLogMessage
|
||||
|
||||
struct BeginReadOperationLogMessage
|
||||
{
|
||||
unsigned cylinder;
|
||||
unsigned head;
|
||||
};
|
||||
|
||||
struct EndReadOperationLogMessage
|
||||
{
|
||||
};
|
||||
|
||||
struct BeginWriteOperationLogMessage
|
||||
{
|
||||
unsigned cylinder;
|
||||
unsigned head;
|
||||
};
|
||||
|
||||
struct EndWriteOperationLogMessage
|
||||
{
|
||||
};
|
||||
@@ -50,7 +51,6 @@ class TrackFlux;
|
||||
typedef std::variant<std::string,
|
||||
SingleReadLogMessage,
|
||||
TrackReadLogMessage,
|
||||
DiskContextLogMessage,
|
||||
BeginSpeedOperationLogMessage,
|
||||
EndSpeedOperationLogMessage,
|
||||
BeginReadOperationLogMessage,
|
||||
|
||||
@@ -23,8 +23,7 @@ static std::unique_ptr<FluxSink> outputFluxSink;
|
||||
|
||||
static std::shared_ptr<Fluxmap> readFluxmap(FluxSource& fluxsource, unsigned cylinder, unsigned head)
|
||||
{
|
||||
Logger() << DiskContextLogMessage { cylinder, head }
|
||||
<< BeginReadOperationLogMessage();
|
||||
Logger() << BeginReadOperationLogMessage { cylinder, head };
|
||||
std::shared_ptr<Fluxmap> fluxmap = fluxsource.readFlux(cylinder, head);
|
||||
fluxmap->rescale(1.0/config.flux_source().rescale());
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
@@ -65,12 +64,12 @@ static std::set<std::shared_ptr<Sector>> collect_sectors(std::set<std::shared_pt
|
||||
return sector_set;
|
||||
}
|
||||
|
||||
void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWriter& writer)
|
||||
std::shared_ptr<DiskFlux> readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder)
|
||||
{
|
||||
if (config.decoder().has_copy_flux_to())
|
||||
outputFluxSink = FluxSink::create(config.decoder().copy_flux_to());
|
||||
|
||||
auto diskflux = std::make_unique<DiskFlux>();
|
||||
auto diskflux = std::make_shared<DiskFlux>();
|
||||
bool failures = false;
|
||||
for (int cylinder : iterate(config.cylinders()))
|
||||
{
|
||||
@@ -177,13 +176,20 @@ void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWrit
|
||||
all_sectors = collect_sectors(all_sectors);
|
||||
diskflux->image.reset(new Image(all_sectors));
|
||||
|
||||
if (failures)
|
||||
Logger() << "Warning: some sectors could not be decoded.";
|
||||
|
||||
return diskflux;
|
||||
}
|
||||
|
||||
void readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder, ImageWriter& writer)
|
||||
{
|
||||
auto diskflux = readDiskCommand(fluxsource, decoder);
|
||||
|
||||
writer.printMap(*diskflux->image);
|
||||
if (config.decoder().has_write_csv_to())
|
||||
writer.writeCsv(*diskflux->image, config.decoder().write_csv_to());
|
||||
writer.writeImage(*diskflux->image);
|
||||
|
||||
if (failures)
|
||||
std::cerr << "Warning: some sectors could not be decoded." << std::endl;
|
||||
}
|
||||
|
||||
void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define READER_H
|
||||
|
||||
class AbstractDecoder;
|
||||
class DiskFlux;
|
||||
class FluxSink;
|
||||
class FluxSource;
|
||||
class Fluxmap;
|
||||
@@ -10,6 +11,8 @@ class TrackDataFlux;
|
||||
|
||||
extern std::unique_ptr<TrackDataFlux> readAndDecodeTrack(
|
||||
FluxSource& source, AbstractDecoder& decoder, unsigned cylinder, unsigned head);
|
||||
|
||||
extern std::shared_ptr<DiskFlux> readDiskCommand(FluxSource& fluxsource, AbstractDecoder& decoder);
|
||||
extern void readDiskCommand(FluxSource& source, AbstractDecoder& decoder, ImageWriter& writer);
|
||||
extern void rawReadDiskCommand(FluxSource& source, FluxSink& sink);
|
||||
|
||||
|
||||
@@ -23,9 +23,7 @@ void writeTracks(FluxSink& fluxSink,
|
||||
{
|
||||
for (unsigned head : iterate(config.heads()))
|
||||
{
|
||||
Logger() << DiskContextLogMessage { cylinder, head }
|
||||
<< fmt::format("{0:>3}.{1}: writing", cylinder, head)
|
||||
<< BeginWriteOperationLogMessage();
|
||||
Logger() << BeginWriteOperationLogMessage { cylinder, head };
|
||||
|
||||
std::unique_ptr<Fluxmap> fluxmap = producer(cylinder, head);
|
||||
if (!fluxmap)
|
||||
@@ -64,9 +62,6 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
||||
{
|
||||
for (unsigned head : iterate(config.heads()))
|
||||
{
|
||||
Logger() << DiskContextLogMessage { cylinder, head }
|
||||
<< fmt::format("{0:>3}.{1}", cylinder, head);
|
||||
|
||||
auto sectors = encoder.collectSectors(cylinder, head, image);
|
||||
std::unique_ptr<Fluxmap> fluxmap =
|
||||
encoder.encode(cylinder, head, sectors, image);
|
||||
@@ -74,7 +69,7 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
||||
{
|
||||
/* Erase this track rather than writing. */
|
||||
|
||||
Logger() << BeginWriteOperationLogMessage() << "erasing";
|
||||
Logger() << BeginWriteOperationLogMessage { cylinder, head };
|
||||
fluxmap.reset(new Fluxmap());
|
||||
fluxSink.writeFlux(cylinder, head, *fluxmap);
|
||||
Logger() << EndWriteOperationLogMessage();
|
||||
@@ -91,14 +86,14 @@ void writeTracksAndVerify(FluxSink& fluxSink,
|
||||
* let's leave it disabled for now. */
|
||||
// fluxmap->precompensate(PRECOMPENSATION_THRESHOLD_TICKS,
|
||||
// 2);
|
||||
Logger() << BeginWriteOperationLogMessage() << "writing";
|
||||
Logger() << BeginWriteOperationLogMessage { cylinder, head };
|
||||
fluxSink.writeFlux(cylinder, head, *fluxmap);
|
||||
Logger() << EndWriteOperationLogMessage()
|
||||
<< fmt::format("{0} ms in {1} bytes",
|
||||
int(fluxmap->duration() / 1e6),
|
||||
fluxmap->bytes());
|
||||
|
||||
Logger() << "verifying" << BeginReadOperationLogMessage();
|
||||
Logger() << BeginReadOperationLogMessage { cylinder, head };
|
||||
std::shared_ptr<Fluxmap> writtenFluxmap =
|
||||
fluxSource.readFlux(cylinder, head);
|
||||
Logger() << EndReadOperationLogMessage()
|
||||
|
||||
@@ -64,12 +64,6 @@ bool MyApp::OnInit()
|
||||
Bind(EXEC_EVENT_TYPE, &MyApp::OnExec, this);
|
||||
MainWindow* frame = new MainWindow();
|
||||
frame->Show(true);
|
||||
|
||||
runOnWorkerThread(
|
||||
[] {
|
||||
printf("I'm a worker thread!\n");
|
||||
}
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -105,7 +99,6 @@ void runOnWorkerThread(std::function<void()> callback)
|
||||
|
||||
void MyApp::OnExec(const ExecEvent& event)
|
||||
{
|
||||
printf("exec handler\n");
|
||||
event.RunCallback();
|
||||
execSemaphore.Post();
|
||||
}
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
#include "proto.h"
|
||||
#include "gui.h"
|
||||
#include "logger.h"
|
||||
#include "reader.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "lib/usb/usbfinder.h"
|
||||
#include "fmt/format.h"
|
||||
#include <wx/wx.h>
|
||||
#include "mainwindow.h"
|
||||
#include <google/protobuf/text_format.h>
|
||||
|
||||
|
||||
extern const std::map<std::string, std::string> formats;
|
||||
|
||||
@@ -17,10 +20,7 @@ MainWindow::MainWindow(): MainWindowGen(nullptr)
|
||||
[&](std::shared_ptr<const AnyLogMessage> message) {
|
||||
runOnUiThread(
|
||||
[message, this]() {
|
||||
std::cout << "UI thread got message "
|
||||
<< Logger::toString(*message)
|
||||
<< '\n'
|
||||
<< std::flush;
|
||||
OnLogMessage(message);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -42,6 +42,8 @@ MainWindow::MainWindow(): MainWindowGen(nullptr)
|
||||
if (deviceCombo->GetCount() > 0)
|
||||
deviceCombo->SetValue(deviceCombo->GetString(0));
|
||||
|
||||
fluxSourceSinkCombo->SetValue(fluxSourceSinkCombo->GetString(0));
|
||||
|
||||
readFluxButton->Bind(wxEVT_BUTTON, &MainWindow::OnReadFluxButton, this);
|
||||
}
|
||||
|
||||
@@ -58,21 +60,72 @@ void MainWindow::OnReadFluxButton(wxCommandEvent&)
|
||||
fluxSourceSinkCombo->GetValue().ToStdString());
|
||||
|
||||
auto serial = deviceCombo->GetValue().ToStdString();
|
||||
if (!serial.empty() && (serial[0] = '/'))
|
||||
if (!serial.empty() && (serial[0] == '/'))
|
||||
setProtoByString(&config, "usb.greaseweazle.port", serial);
|
||||
else
|
||||
setProtoByString(&config, "usb.serial", serial);
|
||||
|
||||
runOnWorkerThread(
|
||||
/* Must make another copy of all local parameters. */
|
||||
[=]() {
|
||||
[config, this]() {
|
||||
::config = config;
|
||||
auto fluxSource = FluxSource::create(config.flux_source());
|
||||
auto decoder = AbstractDecoder::create(config.decoder());
|
||||
printf("Worker thread!\n");
|
||||
auto diskflux = readDiskCommand(*fluxSource, *decoder);
|
||||
runOnUiThread(
|
||||
[&]() {
|
||||
UpdateVisualisedFlux(diskflux);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void MainWindow::OnLogMessage(std::shared_ptr<const AnyLogMessage> message)
|
||||
{
|
||||
std::cout << "UI thread got message "
|
||||
<< Logger::toString(*message)
|
||||
<< '\n'
|
||||
<< std::flush;
|
||||
|
||||
std::visit(
|
||||
overloaded{
|
||||
/* Fallback --- do nothing */
|
||||
[&](const auto& m)
|
||||
{
|
||||
},
|
||||
|
||||
/* Indicates that we're starting a write operation. */
|
||||
[&](const BeginWriteOperationLogMessage& m)
|
||||
{
|
||||
visualiser->SetMode(m.cylinder, m.head, VISMODE_WRITING);
|
||||
},
|
||||
|
||||
[&](const EndWriteOperationLogMessage& m)
|
||||
{
|
||||
visualiser->SetMode(0, 0, VISMODE_NOTHING);
|
||||
},
|
||||
|
||||
/* Indicates that we're starting a read operation. */
|
||||
[&](const BeginReadOperationLogMessage& m)
|
||||
{
|
||||
visualiser->SetMode(m.cylinder, m.head, VISMODE_READING);
|
||||
},
|
||||
|
||||
[&](const EndReadOperationLogMessage& m)
|
||||
{
|
||||
visualiser->SetMode(0, 0, VISMODE_NOTHING);
|
||||
},
|
||||
|
||||
},
|
||||
*message);
|
||||
}
|
||||
|
||||
void MainWindow::UpdateVisualisedFlux(std::shared_ptr<DiskFlux>& flux)
|
||||
{
|
||||
_currentDisk = flux;
|
||||
visualiser->SetDiskFlux(flux);
|
||||
}
|
||||
|
||||
void MainWindow::UpdateDevices()
|
||||
{
|
||||
auto candidates = findUsbDevices();
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
class CandidateDevice;
|
||||
class ConfigProto;
|
||||
class DiskFlux;
|
||||
|
||||
class MainWindow : public MainWindowGen
|
||||
{
|
||||
@@ -15,13 +16,15 @@ public:
|
||||
private:
|
||||
void OnExit(wxCommandEvent& event);
|
||||
void OnReadFluxButton(wxCommandEvent&);
|
||||
void OnLogMessage(std::unique_ptr<AnyLogMessage> message);
|
||||
void OnLogMessage(std::shared_ptr<const AnyLogMessage> message);
|
||||
|
||||
void UpdateVisualisedFlux(std::shared_ptr<DiskFlux>& flux);
|
||||
void UpdateDevices();
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<ConfigProto>> _formats;
|
||||
std::vector<std::unique_ptr<CandidateDevice>> _devices;
|
||||
std::shared_ptr<DiskFlux> _currentDisk;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "globals.h"
|
||||
#include "visualisation.h"
|
||||
#include "fmt/format.h"
|
||||
#include <wx/wx.h>
|
||||
|
||||
#define BORDER 20
|
||||
#define TICK 10
|
||||
#define TRACKS 82
|
||||
|
||||
#define SECTORSIZE 4
|
||||
|
||||
VisualisationControl::VisualisationControl(wxWindow* parent,
|
||||
wxWindowID id,
|
||||
const wxPoint& pos,
|
||||
@@ -43,11 +46,46 @@ void VisualisationControl::OnPaint(wxPaintEvent&)
|
||||
|
||||
dc.DrawLine({ w2, scaletop }, { w2, scalebottom });
|
||||
dc.DrawLine({ w2-TICK, scaletop }, { w2+TICK, scaletop });
|
||||
dc.DrawLine({ w2-TICK, scalebottom }, { w2+TICK, scalebottom });
|
||||
dc.DrawLine(
|
||||
{ w2-TICK, int(scaletop + 80*trackstep) },
|
||||
{ w2+TICK, int(scaletop + 80*trackstep) });
|
||||
|
||||
for (int track = 0; track < TRACKS; track++)
|
||||
if (_mode != VISMODE_NOTHING)
|
||||
{
|
||||
if (_mode == VISMODE_READING)
|
||||
dc.SetBrush(*wxGREEN_BRUSH);
|
||||
else if (_mode == VISMODE_WRITING)
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
|
||||
int factor = (_head == 0) ? -1 : 1;
|
||||
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
int y = scaletop + (_cylinder * trackstep) - trackstep / 2;
|
||||
dc.DrawRectangle(
|
||||
{ w2 + factor*SECTORSIZE*2, y },
|
||||
{ factor*SECTORSIZE*82, (int)trackstep }
|
||||
);
|
||||
}
|
||||
|
||||
dc.SetPen(*wxBLACK_PEN);
|
||||
for (int track = 0; track <= TRACKS; track++)
|
||||
{
|
||||
int y = (double)track * trackstep;
|
||||
dc.DrawLine({ w2-TICK/2, scaletop+y }, { w2+TICK/2, scaletop+y });
|
||||
}
|
||||
}
|
||||
|
||||
void VisualisationControl::SetMode(int cylinder, int head, int mode)
|
||||
{
|
||||
_cylinder = cylinder;
|
||||
_head = head;
|
||||
_mode = mode;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void VisualisationControl::SetDiskFlux(std::shared_ptr<DiskFlux>& disk)
|
||||
{
|
||||
_disk = disk;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
#ifndef VISUALISATION_H
|
||||
#define VISUALISATION_H
|
||||
|
||||
#include <memory>
|
||||
#include <wx/control.h>
|
||||
|
||||
class DiskFlux;
|
||||
|
||||
enum {
|
||||
VISMODE_NOTHING,
|
||||
VISMODE_READING,
|
||||
VISMODE_WRITING
|
||||
};
|
||||
|
||||
class VisualisationControl : public wxWindow
|
||||
{
|
||||
public:
|
||||
@@ -12,10 +21,18 @@ public:
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = 0);
|
||||
|
||||
public:
|
||||
void SetMode(int head, int cylinder, int mode);
|
||||
void SetDiskFlux(std::shared_ptr<DiskFlux>& disk);
|
||||
|
||||
private:
|
||||
void OnPaint(wxPaintEvent & evt);
|
||||
|
||||
private:
|
||||
int _head;
|
||||
int _cylinder;
|
||||
int _mode = VISMODE_NOTHING;
|
||||
std::shared_ptr<DiskFlux> _disk;
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user