Formatting now works rather better, but this has revealed a problem with the

mapper --- which needs to switch to using Layout anyway.
This commit is contained in:
David Given
2022-09-09 00:34:44 +02:00
parent 56dadfc228
commit 003e919bd5
13 changed files with 243 additions and 91 deletions

View File

@@ -6,6 +6,7 @@
#include "usb/usb.h"
#include "fluxsink/fluxsink.h"
#include "lib/fluxsink/fluxsink.pb.h"
#include "lib/readerwriter.cc"
#include "fmt/format.h"
class HardwareFluxSink : public FluxSink
@@ -14,32 +15,8 @@ public:
HardwareFluxSink(const HardwareFluxSinkProto& conf):
_config(conf)
{
if (config.drive().has_hard_sector_count())
{
int retries = 5;
usbSetDrive(config.drive().drive(), config.drive().high_density(), config.drive().index_mode());
nanoseconds_t oneRevolution = config.drive().rotational_period_ms() * 1e6;
if (oneRevolution == 0)
{
Logger() << BeginSpeedOperationLogMessage();
do {
oneRevolution = usbGetRotationalPeriod(config.drive().hard_sector_count());
_hardSectorThreshold = oneRevolution * 3 / (4 * config.drive().hard_sector_count());
retries--;
} while ((oneRevolution == 0) && (retries > 0));
config.mutable_drive()->set_rotational_period_ms(oneRevolution / 1e6);
Logger() << EndSpeedOperationLogMessage { oneRevolution };
}
if (oneRevolution == 0) {
Error() << "Failed\nIs a disk in the drive?";
}
}
else
_hardSectorThreshold = 0;
nanoseconds_t oneRevolution;
measureDiskRotation(oneRevolution, _hardSectorThreshold);
}
~HardwareFluxSink()

View File

@@ -6,6 +6,7 @@
#include "usb/usb.h"
#include "fluxsource/fluxsource.h"
#include "lib/fluxsource/fluxsource.pb.h"
#include "lib/readerwriter.h"
#include "fmt/format.h"
class HardwareFluxSource : public FluxSource
@@ -50,35 +51,7 @@ private:
public:
HardwareFluxSource(const HardwareFluxSourceProto& conf): _config(conf)
{
int retries = 5;
usbSetDrive(config.drive().drive(), config.drive().high_density(), config.drive().index_mode());
Logger() << BeginSpeedOperationLogMessage();
_oneRevolution = config.drive().rotational_period_ms() * 1e6;
_hardSectorThreshold = 0;
if (_oneRevolution == 0)
{
Logger() << BeginOperationLogMessage{"Measuring drive rotational speed"};
do
{
_oneRevolution =
usbGetRotationalPeriod(config.drive().hard_sector_count());
if (config.drive().hard_sector_count() != 0)
_hardSectorThreshold =
_oneRevolution * 3 / (4 * config.drive().hard_sector_count());
else
_hardSectorThreshold = 0;
retries--;
} while ((_oneRevolution == 0) && (retries > 0));
config.mutable_drive()->set_rotational_period_ms(_oneRevolution / 1e6);
Logger() << EndOperationLogMessage{};
}
if (_oneRevolution == 0)
Error() << "Failed\nIs a disk in the drive?";
Logger() << EndSpeedOperationLogMessage{_oneRevolution};
measureDiskRotation(_oneRevolution, _hardSectorThreshold);
}
~HardwareFluxSource() {}

View File

@@ -1,6 +1,7 @@
#include "globals.h"
#include "sector.h"
#include "image.h"
#include "layout.h"
Image::Image() {}
@@ -21,6 +22,20 @@ void Image::clear()
_geometry = {0, 0, 0};
}
void Image::createBlankImage()
{
clear();
for (const auto& trackAndHead : Layout::getTrackOrdering())
{
unsigned track = trackAndHead.first;
unsigned side = trackAndHead.second;
auto layout = Layout::getLayoutOfTrack(track, side);
Bytes blank(layout.sector_size());
for (unsigned sectorId : Layout::getSectorsInTrack(layout))
put(track, side, sectorId)->data = blank;
}
}
bool Image::empty() const
{
return _sectors.empty();
@@ -62,6 +77,15 @@ void Image::erase(unsigned track, unsigned side, unsigned sectorid)
_sectors.erase(key);
}
std::set<std::pair<unsigned, unsigned>> Image::tracks() const
{
std::set<std::pair<unsigned, unsigned>> result;
for (const auto& e : _sectors)
result.insert(
std::make_pair(std::get<0>(e.first), std::get<1>(e.first)));
return result;
}
void Image::calculateSize()
{
_geometry = {};

View File

@@ -56,6 +56,7 @@ public:
void calculateSize();
void clear();
void createBlankImage();
bool empty() const;
bool contains(unsigned track, unsigned side, unsigned sectorId) const;
std::shared_ptr<const Sector> get(
@@ -64,6 +65,8 @@ public:
unsigned track, unsigned side, unsigned sectorId);
void erase(unsigned track, unsigned side, unsigned sectorId);
std::set<std::pair<unsigned, unsigned>> tracks() const;
const_iterator begin() const
{
return const_iterator(_sectors.cbegin());

View File

@@ -56,6 +56,46 @@ private:
_cache;
};
void measureDiskRotation(
nanoseconds_t& oneRevolution, nanoseconds_t& hardSectorThreshold)
{
Logger() << BeginSpeedOperationLogMessage();
int retries = 5;
usbSetDrive(config.drive().drive(),
config.drive().high_density(),
config.drive().index_mode());
oneRevolution = config.drive().rotational_period_ms() * 1e6;
if (config.drive().hard_sector_count() != 0)
hardSectorThreshold =
oneRevolution * 3 / (4 * config.drive().hard_sector_count());
else
hardSectorThreshold = 0;
if (oneRevolution == 0)
{
Logger() << BeginOperationLogMessage{
"Measuring drive rotational speed"};
do
{
oneRevolution =
usbGetRotationalPeriod(config.drive().hard_sector_count());
if (config.drive().hard_sector_count() != 0)
hardSectorThreshold = oneRevolution * 3 /
(4 * config.drive().hard_sector_count());
retries--;
} while ((oneRevolution == 0) && (retries > 0));
config.mutable_drive()->set_rotational_period_ms(oneRevolution / 1e6);
Logger() << EndOperationLogMessage{};
}
if (oneRevolution == 0)
Error() << "Failed\nIs a disk in the drive?";
Logger() << EndSpeedOperationLogMessage{oneRevolution};
}
/* Given a set of sectors, deduplicates them sensibly (e.g. if there is a good
* and bad version of the same sector, the bad version is dropped). */

View File

@@ -14,6 +14,9 @@ class ImageWriter;
class Location;
class TrackFlux;
extern void measureDiskRotation(
nanoseconds_t& oneRevolution, nanoseconds_t& hardSectorThreshold);
extern void writeTracks(FluxSink& fluxSink,
const std::function<std::unique_ptr<const Fluxmap>(
const Location& location)> producer);
@@ -31,9 +34,8 @@ extern void writeDiskCommand(const Image& image,
extern void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink);
extern std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource,
AbstractDecoder& decoder,
const Location& location);
extern std::shared_ptr<TrackFlux> readAndDecodeTrack(
FluxSource& fluxSource, AbstractDecoder& decoder, const Location& location);
extern std::shared_ptr<const DiskFlux> readDiskCommand(
FluxSource& fluxsource, AbstractDecoder& decoder);

View File

@@ -116,6 +116,8 @@ public:
void discardChanges() override
{
_loadedTracks.clear();
_readSectors.clear();
_changedTracks.clear();
_changedSectors.clear();
}

View File

@@ -3,16 +3,19 @@
#include "lib/imagereader/imagereader.h"
#include "lib/imagewriter/imagewriter.h"
#include "lib/image.h"
#include "lib/layout.h"
#include "lib/sector.h"
#include "lib/bytes.h"
class ImageSectorInterface : public SectorInterface
{
public:
ImageSectorInterface(std::shared_ptr<ImageReader> reader,
std::shared_ptr<ImageWriter> writer):
_image(reader->readImage()),
_reader(reader),
_writer(writer)
{
discardChanges();
}
public:
@@ -47,7 +50,13 @@ public:
void discardChanges() override
{
_image = _reader->readImage();
if (_reader)
_image = _reader->readImage();
else
{
_image = std::make_shared<Image>();
_image->createBlankImage();
}
_changed = false;
}

View File

@@ -210,30 +210,33 @@ std::unique_ptr<Filesystem> Filesystem::createFilesystem(
std::unique_ptr<Filesystem> Filesystem::createFilesystemFromConfig()
{
std::shared_ptr<SectorInterface> sectorInterface;
if (config.has_flux_source())
if (config.has_flux_source() || config.has_flux_sink())
{
std::shared_ptr<FluxSource> fluxSource(
FluxSource::create(config.flux_source()));
std::shared_ptr<AbstractDecoder> decoder(
AbstractDecoder::create(config.decoder()));
std::shared_ptr<FluxSource> fluxSource;
std::shared_ptr<AbstractDecoder> decoder;
std::shared_ptr<FluxSink> fluxSink;
std::shared_ptr<AbstractEncoder> encoder;
if (config.flux_source().source_case() !=
FluxSourceProto::SOURCE_NOT_SET)
{
fluxSource = FluxSource::create(config.flux_source());
decoder = AbstractDecoder::create(config.decoder());
}
if (config.flux_sink().has_drive())
{
std::shared_ptr<FluxSink> fluxSink(
FluxSink::create(config.flux_sink()));
std::shared_ptr<AbstractEncoder> encoder(
AbstractEncoder::create(config.encoder()));
sectorInterface = SectorInterface::createFluxSectorInterface(
fluxSource, fluxSink, encoder, decoder);
fluxSink = FluxSink::create(config.flux_sink());
encoder = AbstractEncoder::create(config.encoder());
}
else
sectorInterface = SectorInterface::createFluxSectorInterface(
fluxSource, nullptr, nullptr, decoder);
sectorInterface = SectorInterface::createFluxSectorInterface(
fluxSource, fluxSink, encoder, decoder);
}
else
{
std::shared_ptr<ImageReader> reader(
ImageReader::create(config.image_reader()));
std::shared_ptr<ImageReader> reader;
std::shared_ptr<ImageWriter> writer;
if (config.image_reader().format_case() !=
ImageReaderProto::FORMAT_NOT_SET)
reader = ImageReader::create(config.image_reader());
if (config.image_writer().format_case() !=
ImageWriterProto::FORMAT_NOT_SET)
writer = ImageWriter::create(config.image_writer());

View File

@@ -190,6 +190,11 @@ MainWindowGen::MainWindowGen( wxWindow* parent, wxWindowID id, const wxString& t
gSizer9->Add( browseButton, 0, wxALL|wxEXPAND, 5 );
formatButton = new wxButton( idlePanel, wxID_ANY, wxT("Format disk"), wxDefaultPosition, wxDefaultSize, 0 );
formatButton->SetBitmap( wxArtProvider::GetBitmap( wxART_DELETE, wxART_BUTTON ) );
gSizer9->Add( formatButton, 0, wxALL|wxEXPAND, 5 );
fgSizer8->Add( gSizer9, 1, wxEXPAND, 5 );
@@ -387,6 +392,7 @@ MainWindowGen::MainWindowGen( wxWindow* parent, wxWindowID id, const wxString& t
readButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnReadButton ), NULL, this );
writeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnWriteButton ), NULL, this );
browseButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnBrowseButton ), NULL, this );
formatButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnFormatButton ), NULL, this );
this->Connect( imagerBackTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBackButton ) );
imagerSaveImageButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveImageButton ), NULL, this );
imagerSaveFluxButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveFluxButton ), NULL, this );
@@ -427,6 +433,7 @@ MainWindowGen::~MainWindowGen()
readButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnReadButton ), NULL, this );
writeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnWriteButton ), NULL, this );
browseButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnBrowseButton ), NULL, this );
formatButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnFormatButton ), NULL, this );
this->Disconnect( imagerBackTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBackButton ) );
imagerSaveImageButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveImageButton ), NULL, this );
imagerSaveFluxButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveFluxButton ), NULL, this );

View File

@@ -1654,6 +1654,81 @@
<event name="OnButtonClick">OnBrowseButton</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap">Load From Art Provider; wxART_DELETE; wxART_BUTTON</property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Format disk</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">formatButton</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnFormatButton</event>
</object>
</object>
</object>
</object>
</object>

View File

@@ -77,6 +77,7 @@ class MainWindowGen : public wxFrame
wxButton* readButton;
wxButton* writeButton;
wxButton* browseButton;
wxButton* formatButton;
wxPanel* imagePanel;
wxAuiToolBar* imagerToolbar;
wxAuiToolBarItem* imagerBackTool;
@@ -120,6 +121,7 @@ class MainWindowGen : public wxFrame
virtual void OnReadButton( wxCommandEvent& event ) { event.Skip(); }
virtual void OnWriteButton( wxCommandEvent& event ) { event.Skip(); }
virtual void OnBrowseButton( wxCommandEvent& event ) { event.Skip(); }
virtual void OnFormatButton( wxCommandEvent& event ) { event.Skip(); }
virtual void OnBackButton( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSaveImageButton( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSaveFluxButton( wxCommandEvent& event ) { event.Skip(); }

View File

@@ -232,8 +232,8 @@ public:
void OnControlsChanged(wxFileDirPickerEvent& event)
{
SaveConfig();
UpdateState();
wxCommandEvent e;
OnControlsChanged(e);
}
void OnReadButton(wxCommandEvent&)
@@ -472,6 +472,42 @@ public:
}
}
void OnFormatButton(wxCommandEvent& event) override
{
try
{
PrepareConfig();
visualiser->Clear();
_filesystemModel->Clear(Path());
_currentDisk = nullptr;
_state = STATE_BROWSING_WORKING;
UpdateState();
ShowConfig();
QueueBrowserOperation(
[this]()
{
_filesystem = Filesystem::createFilesystemFromConfig();
_filesystemCapabilities = _filesystem->capabilities();
_filesystemIsReadOnly = _filesystem->isReadOnly();
runOnUiThread(
[&]()
{
wxCommandEvent e;
OnBrowserFormatButton(e);
});
});
}
catch (const ErrorException& e)
{
wxMessageBox(e.message, "Error", wxOK | wxICON_ERROR);
_state = STATE_IDLE;
}
}
void OnBrowserMoreMenuButton(wxAuiToolBarEvent& event)
{
browserToolbar->SetToolSticky(event.GetId(), true);
@@ -1295,8 +1331,6 @@ public:
void UpdateState()
{
bool running = wxGetApp().IsWorkerThreadRunning();
if (_state < STATE_IDLE__LAST)
{
dataNotebook->SetSelection(0);
@@ -1330,6 +1364,7 @@ public:
{
dataNotebook->SetSelection(2);
bool running = !_filesystemQueue.empty();
bool selection = browserTree->GetSelection().IsOk();
browserToolbar->EnableTool(
@@ -1340,24 +1375,24 @@ public:
bool needsFlushing = _filesystemNeedsFlushing;
browserToolbar->EnableTool(browserInfoTool->GetId(),
(c & Filesystem::OP_GETDIRENT) && selection);
!running && (c & Filesystem::OP_GETDIRENT) && selection);
browserToolbar->EnableTool(browserViewTool->GetId(),
(c & Filesystem::OP_GETFILE) && selection);
!running && (c & Filesystem::OP_GETFILE) && selection);
browserToolbar->EnableTool(browserSaveTool->GetId(),
(c & Filesystem::OP_GETFILE) && selection);
!running && (c & Filesystem::OP_GETFILE) && selection);
browserMoreMenu->Enable(browserAddMenuItem->GetId(),
!ro && (c & Filesystem::OP_PUTFILE));
!running && !ro && (c & Filesystem::OP_PUTFILE));
browserMoreMenu->Enable(browserNewDirectoryMenuItem->GetId(),
!ro && (c & Filesystem::OP_CREATEDIR));
!running && !ro && (c & Filesystem::OP_CREATEDIR));
browserMoreMenu->Enable(browserRenameMenuItem->GetId(),
!ro && (c & Filesystem::OP_MOVE) && selection);
!running && !ro && (c & Filesystem::OP_MOVE) && selection);
browserMoreMenu->Enable(browserDeleteMenuItem->GetId(),
!ro && (c & Filesystem::OP_DELETE) && selection);
browserToolbar->EnableTool(
browserFormatTool->GetId(), !ro && (c & Filesystem::OP_CREATE));
!running && !ro && (c & Filesystem::OP_DELETE) && selection);
browserToolbar->EnableTool(browserFormatTool->GetId(),
!running && !ro && (c & Filesystem::OP_CREATE));
browserDiscardButton->Enable(needsFlushing);
browserCommitButton->Enable(needsFlushing);
browserDiscardButton->Enable(!running && needsFlushing);
browserCommitButton->Enable(!running && needsFlushing);
}
Refresh();