diff --git a/FluxEngine.cydsn/FluxEngine.cyprj b/FluxEngine.cydsn/FluxEngine.cyprj
index 50510e35..4566365c 100644
--- a/FluxEngine.cydsn/FluxEngine.cyprj
+++ b/FluxEngine.cydsn/FluxEngine.cyprj
@@ -2310,13 +2310,13 @@
-
+
-
+
@@ -3249,6 +3249,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FluxEngine.cydsn/TopDesign/TopDesign.cysch b/FluxEngine.cydsn/TopDesign/TopDesign.cysch
index c27d80c8..ffe2bf13 100644
Binary files a/FluxEngine.cydsn/TopDesign/TopDesign.cysch and b/FluxEngine.cydsn/TopDesign/TopDesign.cysch differ
diff --git a/FluxEngine.cydsn/UdbSampler/UdbSampler.cyudb b/FluxEngine.cydsn/UdbSampler/UdbSampler.cyudb
index ead7a66b..457f8ac7 100644
Binary files a/FluxEngine.cydsn/UdbSampler/UdbSampler.cyudb and b/FluxEngine.cydsn/UdbSampler/UdbSampler.cyudb differ
diff --git a/FluxEngine.cydsn/main.c b/FluxEngine.cydsn/main.c
index 509310ee..9b956ba5 100644
--- a/FluxEngine.cydsn/main.c
+++ b/FluxEngine.cydsn/main.c
@@ -306,6 +306,7 @@ static void cmd_read(struct read_frame* f)
dma_underrun = false;
int count = 0;
SAMPLER_CONTROL_Write(0); /* !reset */
+ CAPTURE_CONTROL_Write(1);
CyDmaChSetInitialTd(dma_channel, td[dma_writing_to_td]);
CyDmaClearPendingDrq(dma_channel);
CyDmaChEnable(dma_channel, 1);
@@ -364,7 +365,8 @@ static void cmd_read(struct read_frame* f)
}
dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td);
}
-abort:
+abort:;
+ CAPTURE_CONTROL_Write(0);
CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN);
while (CyDmaChGetRequest(dma_channel))
;
diff --git a/lib/brother/brother.h b/lib/brother/brother.h
index 05435258..73313486 100644
--- a/lib/brother/brother.h
+++ b/lib/brother/brother.h
@@ -9,6 +9,9 @@
#define BROTHER_DATA_RECORD_CHECKSUM 3
#define BROTHER_DATA_RECORD_ENCODED_SIZE 415
+#define BROTHER_TRACKS_PER_DISK 78
+#define BROTHER_SECTORS_PER_TRACK 12
+
class Sector;
class Fluxmap;
@@ -22,9 +25,15 @@ class BrotherDecoder : public AbstractDecoder
void decodeDataRecord();
};
-extern void writeBrotherSectorHeader(std::vector& bits, unsigned& cursor,
- int track, int sector);
-extern void writeBrotherSectorData(std::vector& bits, unsigned& cursor,
- const Bytes& data);
+class BrotherEncoder : public AbstractEncoder
+{
+public:
+ virtual ~BrotherEncoder() {}
+
+public:
+ std::unique_ptr encode(int physicalTrack, int physicalSide, const SectorSet& allSectors);
+};
+
+extern FlagGroup brotherEncoderFlags;
#endif
diff --git a/lib/brother/decoder.cc b/lib/brother/decoder.cc
index 46420deb..18c0a354 100644
--- a/lib/brother/decoder.cc
+++ b/lib/brother/decoder.cc
@@ -3,6 +3,7 @@
#include "fluxmap.h"
#include "decoders/fluxmapreader.h"
#include "decoders/decoders.h"
+#include "encoders/encoders.h"
#include "record.h"
#include "brother.h"
#include "sector.h"
diff --git a/lib/brother/encoder.cc b/lib/brother/encoder.cc
index 412a3709..20911866 100644
--- a/lib/brother/encoder.cc
+++ b/lib/brother/encoder.cc
@@ -1,8 +1,38 @@
#include "globals.h"
#include "record.h"
#include "decoders/decoders.h"
+#include "encoders/encoders.h"
#include "brother.h"
#include "crc.h"
+#include "sectorset.h"
+#include "writer.h"
+
+FlagGroup brotherEncoderFlags;
+
+static DoubleFlag clockRateUs(
+ { "--clock-rate" },
+ "Encoded data clock rate (microseconds).",
+ 3.83);
+
+static DoubleFlag postIndexGapMs(
+ { "--post-index-gap" },
+ "Post-index gap before first sector header (milliseconds).",
+ 1.0);
+
+static DoubleFlag sectorSpacingMs(
+ { "--sector-spacing" },
+ "Time between successive sector headers (milliseconds).",
+ 16.2);
+
+static DoubleFlag postHeaderSpacingMs(
+ { "--post-header-spacing" },
+ "Time between a sector's header and data records (milliseconds).",
+ 0.69);
+
+static StringFlag sectorSkew(
+ { "--sector-skew" },
+ "Order in which to write sectors.",
+ "05a3816b4927");
static int encode_header_gcr(uint16_t word)
{
@@ -40,7 +70,7 @@ static void write_bits(std::vector& bits, unsigned& cursor, uint32_t data,
}
}
-void writeBrotherSectorHeader(std::vector& bits, unsigned& cursor,
+static void write_sector_header(std::vector& bits, unsigned& cursor,
int track, int sector)
{
write_bits(bits, cursor, 0xffffffff, 31);
@@ -50,7 +80,7 @@ void writeBrotherSectorHeader(std::vector& bits, unsigned& cursor,
write_bits(bits, cursor, encode_header_gcr(0x2f), 16);
}
-void writeBrotherSectorData(std::vector& bits, unsigned& cursor, const Bytes& data)
+static void write_sector_data(std::vector& bits, unsigned& cursor, const Bytes& data)
{
write_bits(bits, cursor, 0xffffffff, 32);
write_bits(bits, cursor, BROTHER_DATA_RECORD, 32);
@@ -89,4 +119,49 @@ void writeBrotherSectorData(std::vector& bits, unsigned& cursor, const Byt
write_byte(0);
}
+static int charToInt(char c)
+{
+ if (isdigit(c))
+ return c - '0';
+ return 10 + tolower(c) - 'a';
+}
+
+std::unique_ptr BrotherEncoder::encode(
+ int physicalTrack, int physicalSide, const SectorSet& allSectors)
+{
+ if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_DISK)
+ || (physicalSide != 0))
+ return std::unique_ptr();
+
+ int bitsPerRevolution = 200000.0 / clockRateUs;
+ const std::string& skew = sectorSkew.get();
+ std::vector bits(bitsPerRevolution);
+ unsigned cursor = 0;
+
+ for (int sectorCount=0; sectorCountdata);
+ }
+
+ if (cursor > bits.size())
+ Error() << "track data overrun";
+ fillBitmapTo(bits, cursor, bits.size(), { true, false });
+
+ // The pre-index gap is not normally reported.
+ // std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;
+
+ std::unique_ptr fluxmap(new Fluxmap);
+ fluxmap->appendBits(bits, clockRateUs*1e3);
+ return fluxmap;
+}
diff --git a/lib/encoder.cc b/lib/encoders/encoders.cc
similarity index 100%
rename from lib/encoder.cc
rename to lib/encoders/encoders.cc
diff --git a/lib/encoders/encoders.h b/lib/encoders/encoders.h
new file mode 100644
index 00000000..046a950d
--- /dev/null
+++ b/lib/encoders/encoders.h
@@ -0,0 +1,18 @@
+#ifndef ENCODERS_H
+#define ENCODERS_H
+
+class Fluxmap;
+class SectorSet;
+
+class AbstractEncoder
+{
+public:
+ virtual ~AbstractEncoder() {}
+
+public:
+ virtual std::unique_ptr encode(
+ int physicalTrack, int physicalSide, const SectorSet& allSectors) = 0;
+};
+
+#endif
+
diff --git a/lib/macintosh/decoder.cc b/lib/macintosh/decoder.cc
index fb90dad2..f7ec7568 100644
--- a/lib/macintosh/decoder.cc
+++ b/lib/macintosh/decoder.cc
@@ -153,6 +153,9 @@ void MacintoshDecoder::decodeSectorRecord()
uint8_t formatByte = decode_data_gcr(header[3]);
uint8_t wantedsum = decode_data_gcr(header[4]);
+ if (encodedSector > 11)
+ return;
+
_sector->logicalTrack = _track->physicalTrack;
_sector->logicalSide = decode_side(encodedSide);
_sector->logicalSector = encodedSector;
diff --git a/lib/reader.cc b/lib/reader.cc
index b664d36a..b2285c39 100644
--- a/lib/reader.cc
+++ b/lib/reader.cc
@@ -160,8 +160,9 @@ void readDiskCommand(AbstractDecoder& decoder, const std::string& outputFilename
track->rawrecords.size(),
track->sectors.size());
if (track->sectors.size() > 0)
- std::cout << fmt::format("{:.2f}us clock; ",
- track->sectors.begin()->clock / 1000.0);
+ std::cout << fmt::format("{:.2f}us clock ({:.0f}kHz); ",
+ track->sectors.begin()->clock / 1000.0,
+ 1000000.0 / track->sectors.begin()->clock);
for (auto& sector : track->sectors)
{
diff --git a/lib/writer.cc b/lib/writer.cc
index 5f52441d..b497732d 100644
--- a/lib/writer.cc
+++ b/lib/writer.cc
@@ -6,9 +6,14 @@
#include "protocol.h"
#include "usb.h"
#include "dataspec.h"
+#include "encoders/encoders.h"
#include "fluxsource/fluxsource.h"
#include "fluxsink/fluxsink.h"
#include "fmt/format.h"
+#include "record.h"
+#include "image.h"
+#include "sector.h"
+#include "sectorset.h"
FlagGroup writerFlags { &hardwareFluxSourceFlags };
@@ -60,10 +65,12 @@ void writeTracks(
{
if (!outdb)
{
- std::cout << "erasing" << std::endl;
+ std::cout << "erasing\n";
usbSeek(location.track);
usbErase(location.side);
}
+ else
+ std::cout << "skipping\n";
}
else
{
@@ -96,3 +103,16 @@ void fillBitmapTo(std::vector& bitmap,
}
}
+void writeDiskCommand(
+ AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename)
+{
+ SectorSet allSectors;
+
+ readSectorsFromFile(allSectors, geometry, inputFilename);
+ writeTracks(
+ [&](int track, int side) -> std::unique_ptr
+ {
+ return encoder.encode(track, side, allSectors);
+ }
+ );
+}
diff --git a/lib/writer.h b/lib/writer.h
index ad331dcb..38232d7e 100644
--- a/lib/writer.h
+++ b/lib/writer.h
@@ -6,6 +6,8 @@
extern FlagGroup writerFlags;
class Fluxmap;
+class AbstractEncoder;
+class Geometry;
extern void setWriterDefaultDest(const std::string& dest);
@@ -15,5 +17,7 @@ extern void fillBitmapTo(std::vector& bitmap,
unsigned& cursor, unsigned terminateAt,
const std::vector& pattern);
+extern void writeDiskCommand(
+ AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename);
#endif
diff --git a/mkninja.sh b/mkninja.sh
index 4a8dae08..33f4a2b6 100644
--- a/mkninja.sh
+++ b/mkninja.sh
@@ -150,7 +150,7 @@ buildlibrary libbackend.a \
lib/decoders/decoders.cc \
lib/decoders/fluxmapreader.cc \
lib/decoders/fmmfm.cc \
- lib/encoder.cc \
+ lib/encoders/encoders.cc \
lib/f85/decoder.cc \
lib/fb100/decoder.cc \
lib/flags.cc \
diff --git a/src/fe-readbrother.cc b/src/fe-readbrother.cc
index 0f701ee2..0c1a9d6b 100644
--- a/src/fe-readbrother.cc
+++ b/src/fe-readbrother.cc
@@ -3,6 +3,7 @@
#include "reader.h"
#include "fluxmap.h"
#include "decoders/decoders.h"
+#include "encoders/encoders.h"
#include "brother/brother.h"
#include "sector.h"
#include "sectorset.h"
diff --git a/src/fe-writebrother.cc b/src/fe-writebrother.cc
index 42dc5e2b..34369a68 100644
--- a/src/fe-writebrother.cc
+++ b/src/fe-writebrother.cc
@@ -1,108 +1,28 @@
#include "globals.h"
#include "flags.h"
-#include "fluxmap.h"
-#include "sector.h"
-#include "sectorset.h"
#include "decoders/decoders.h"
+#include "encoders/encoders.h"
#include "brother/brother.h"
-#include "image.h"
#include "writer.h"
#include "fmt/format.h"
+#include "image.h"
#include
-#include
-static FlagGroup flags { &writerFlags };
+static FlagGroup flags { &writerFlags, &brotherEncoderFlags };
static StringFlag inputFilename(
{ "--input", "-i" },
"The input image file to read from.",
"brother.img");
-static DoubleFlag clockRateUs(
- { "--clock-rate" },
- "Encoded data clock rate (microseconds).",
- 3.83);
-
-static DoubleFlag postIndexGapMs(
- { "--post-index-gap" },
- "Post-index gap before first sector header (milliseconds).",
- 1.0);
-
-static DoubleFlag sectorSpacingMs(
- { "--sector-spacing" },
- "Time between successive sector headers (milliseconds).",
- 16.2);
-
-static DoubleFlag postHeaderSpacingMs(
- { "--post-header-spacing" },
- "Time between a sector's header and data records (milliseconds).",
- 0.69);
-
-
-static StringFlag sectorSkew(
- { "--sector-skew" },
- "Order in which to write sectors.",
- "05a3816b4927");
-
-static int charToInt(char c)
-{
- if (isdigit(c))
- return c - '0';
- return 10 + tolower(c) - 'a';
-}
-
int mainWriteBrother(int argc, const char* argv[])
{
setWriterDefaultDest(":d=0:t=0-77:s=0");
flags.parseFlags(argc, argv);
- SectorSet allSectors;
+ BrotherEncoder encoder;
Geometry geometry = {78, 1, 12, 256};
- readSectorsFromFile(allSectors, geometry, inputFilename);
-
- int bitsPerRevolution = 200000.0 / clockRateUs;
- std::cerr << bitsPerRevolution << " bits per 200ms revolution" << std::endl
- << fmt::format("post-index gap: {:.3f}ms\n", (double)postIndexGapMs);
-
- const std::string& skew = sectorSkew;
-
- writeTracks(
- [&](int track, int side) -> std::unique_ptr
- {
- if ((track < 0) || (track > 77) || (side != 0))
- return std::unique_ptr();
-
- std::vector bits(bitsPerRevolution);
- unsigned cursor = 0;
-
- for (int sectorCount=0; sectorCountdata);
- }
-
- if (cursor > bits.size())
- Error() << "track data overrun";
- fillBitmapTo(bits, cursor, bits.size(), { true, false });
-
- // The pre-index gap is not normally reported.
- // std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl;
-
- std::unique_ptr fluxmap(new Fluxmap);
- fluxmap->appendBits(bits, clockRateUs*1e3);
- return fluxmap;
- }
- );
+ writeDiskCommand(encoder, geometry, inputFilename);
return 0;
}