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; }