From 7f3e9f25441eb3404c513677d45aa37e28e46829 Mon Sep 17 00:00:00 2001 From: David Given Date: Mon, 19 Jul 2021 23:29:49 +0200 Subject: [PATCH 1/8] Add a prototype Kaypro2 format. --- mkninja.sh | 1 + src/formats/kaypro2.textpb | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/formats/kaypro2.textpb diff --git a/mkninja.sh b/mkninja.sh index 2470e77f4..1ac6be05c 100644 --- a/mkninja.sh +++ b/mkninja.sh @@ -404,6 +404,7 @@ FORMATS="\ ibm360_525 \ ibm720 \ ibm720_525 \ + kaypro2 \ mac400 \ mac800 \ micropolis \ diff --git a/src/formats/kaypro2.textpb b/src/formats/kaypro2.textpb new file mode 100644 index 000000000..6828cb794 --- /dev/null +++ b/src/formats/kaypro2.textpb @@ -0,0 +1,46 @@ +comment: 'Kaypro II 5.25" single-sided 48 tpi' + +image_reader { + filename: "kaypro2.img" + img {} +} + +image_writer { + filename: "kaypro2.img" + img { + trackdata { + sector_size: 512 + sectors: 10 + } + tracks: 40 + sides: 1 + physical_step: 1 + } +} + +encoder { + ibm { + trackdata { + track_length_ms: 195 + clock_rate_khz: 500 + sector_skew: "0123456789" + } + } +} + +decoder { + ibm { + sector_id_base: 0 + } +} + +cylinders { + start: 0 + end: 39 +} + +heads { + start: 0 + end: 0 +} + From 9dae587ca8073c7ca270f3bebf6dd9c7680b18ec Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 20 Jul 2021 23:28:49 +0200 Subject: [PATCH 2/8] Update Kaypro II format. --- src/formats/kaypro2.textpb | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/formats/kaypro2.textpb b/src/formats/kaypro2.textpb index 6828cb794..dc8f7ca6c 100644 --- a/src/formats/kaypro2.textpb +++ b/src/formats/kaypro2.textpb @@ -1,8 +1,16 @@ -comment: 'Kaypro II 5.25" single-sided 48 tpi' +comment: 'Kaypro II 5.25" 40-track 10-sector SSDD' image_reader { filename: "kaypro2.img" - img {} + img { + trackdata { + sector_size: 512 + sectors: 10 + } + tracks: 40 + sides: 1 + physical_step: 1 + } } image_writer { @@ -21,8 +29,8 @@ image_writer { encoder { ibm { trackdata { - track_length_ms: 195 - clock_rate_khz: 500 + track_length_ms: 167 + clock_rate_khz: 300 sector_skew: "0123456789" } } From 5a4f9892366327a6b90bab9415e2b0cd90edc242 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 27 Jul 2021 19:36:15 +0200 Subject: [PATCH 3/8] Show more information when a track overrun occurs. --- arch/ibm/encoder.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/ibm/encoder.cc b/arch/ibm/encoder.cc index 55e639477..7a64295c6 100644 --- a/arch/ibm/encoder.cc +++ b/arch/ibm/encoder.cc @@ -153,7 +153,7 @@ class IbmEncoder : public AbstractEncoder if (!trackdata.use_fm()) clockRateUs /= 2.0; int bitsPerRevolution = (trackdata.track_length_ms() * 1000.0) / clockRateUs; - _bits.resize(bitsPerRevolution); + _bits.resize(bitsPerRevolution*2); _cursor = 0; uint8_t idamUnencoded = decodeUint16(trackdata.idam_byte()); @@ -273,12 +273,15 @@ class IbmEncoder : public AbstractEncoder } } - if (_cursor >= _bits.size()) - Error() << "track data overrun"; + if (_cursor >= bitsPerRevolution) + Error() << fmt::format("track data overrun by {} bits ({:.3} ms)", + _cursor - bitsPerRevolution, + (_cursor - bitsPerRevolution) / (clockRateUs*1000.0)); while (_cursor < _bits.size()) writeFillerBytes(1, gapFill); std::unique_ptr fluxmap(new Fluxmap); + _bits.resize(bitsPerRevolution); fluxmap->appendBits(_bits, clockRateUs*1e3); return fluxmap; } From 7f13c1cbfb6ba863fab6bb95c41dbe615255d6a2 Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 27 Jul 2021 19:36:32 +0200 Subject: [PATCH 4/8] Randomly fiddle with the Kaypro 2 format until something works. --- src/formats/kaypro2.textpb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/formats/kaypro2.textpb b/src/formats/kaypro2.textpb index dc8f7ca6c..fdfd2a1a8 100644 --- a/src/formats/kaypro2.textpb +++ b/src/formats/kaypro2.textpb @@ -29,9 +29,14 @@ image_writer { encoder { ibm { trackdata { + emit_iam: false track_length_ms: 167 clock_rate_khz: 300 sector_skew: "0123456789" + start_sector_id: 0 + gap0: 80 + gap2: 22 + gap3: 44 } } } From 145b1065c53d8b4032b6fa4a187c4c306982c05d Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 1 Aug 2021 21:54:03 +0200 Subject: [PATCH 5/8] Test the kaypro2 profile. --- mkninja.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/mkninja.sh b/mkninja.sh index ae42bed1d..a825b9caa 100644 --- a/mkninja.sh +++ b/mkninja.sh @@ -524,6 +524,7 @@ encodedecodetest ibm180_525 encodedecodetest ibm360_525 encodedecodetest ibm720 encodedecodetest ibm720_525 +encodedecodetest kaypro2 encodedecodetest tids990 encodedecodetest commodore1581 encodedecodetest commodore1541 scripts/commodore1541_test.textpb From 10464f3c435b25c62db8e61ffde960780387766c Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 3 Aug 2021 23:05:54 +0200 Subject: [PATCH 6/8] Fix after merge. --- src/formats/kaypro2.textpb | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/formats/kaypro2.textpb b/src/formats/kaypro2.textpb index fdfd2a1a8..dba6833db 100644 --- a/src/formats/kaypro2.textpb +++ b/src/formats/kaypro2.textpb @@ -5,7 +5,10 @@ image_reader { img { trackdata { sector_size: 512 - sectors: 10 + sector_range { + start_sector: 0 + sector_count: 10 + } } tracks: 40 sides: 1 @@ -18,7 +21,10 @@ image_writer { img { trackdata { sector_size: 512 - sectors: 10 + sector_range { + start_sector: 0 + sector_count: 10 + } } tracks: 40 sides: 1 @@ -32,8 +38,18 @@ encoder { emit_iam: false track_length_ms: 167 clock_rate_khz: 300 - sector_skew: "0123456789" - start_sector_id: 0 + sectors { + sector: 0 + sector: 1 + sector: 2 + sector: 3 + sector: 4 + sector: 5 + sector: 6 + sector: 7 + sector: 8 + sector: 9 + } gap0: 80 gap2: 22 gap3: 44 @@ -42,9 +58,7 @@ encoder { } decoder { - ibm { - sector_id_base: 0 - } + ibm {} } cylinders { From 7884813973547ff3234647913e75d7a8567fabdf Mon Sep 17 00:00:00 2001 From: David Given Date: Tue, 3 Aug 2021 23:06:10 +0200 Subject: [PATCH 7/8] Add the Kaypro II format to the IBM page. --- README.md | 1 + doc/disk-ibm.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index d1aedb4c3..1f2d59e0e 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ people who've had it work). | [Brother 120kB](doc/disk-brother.md) | 🦄 | 🦖 | | | [Brother 240kB](doc/disk-brother.md) | 🦄 | 🦄 | | | [Brother FB-100](doc/disk-fb100.md) | 🦖 | | Tandy Model 100, Husky Hunter, knitting machines | +| [Kaypro II](doc/disk-ibm.md) | 🦄 | 🦄 | | | [Macintosh 800kB](doc/disk-macintosh.md) | 🦄 | 🦄 | and probably the 400kB too | | [TRS-80](doc/disk-trs80.md) | 🦖 | 🦖* | a minor variation of the IBM scheme | {: .datatable } diff --git a/doc/disk-ibm.md b/doc/disk-ibm.md index a74df292f..00c6fb3c9 100644 --- a/doc/disk-ibm.md +++ b/doc/disk-ibm.md @@ -14,6 +14,7 @@ metadata. Systems which use IBM scheme disks include but are not limited to: - the TRS-80 - late era Commodore machines (the 1571 and so on) - most CP/M machines + - the Kaypro II - etc FluxEngine supports reading these. However, some variants are more peculiar From b9623a09d3a9b68c76ecfc970073906ec6c1339a Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 4 Aug 2021 21:25:11 +0200 Subject: [PATCH 8/8] Switch back to C++14; remove use of designated initialisers. --- Makefile | 2 +- lib/imagereader/diskcopyimagereader.cc | 14 ++--- lib/imagereader/imdimagereader.cc | 12 ++-- lib/imagereader/nsiimagereader.cc | 12 ++-- lib/usb/fluxengineusb.cc | 78 ++++++++++++++------------ 5 files changed, 62 insertions(+), 56 deletions(-) diff --git a/Makefile b/Makefile index 38528f67c..4ea0328c5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ PACKAGES = zlib sqlite3 libusb-1.0 protobuf -export CFLAGS = -x c++ --std=c++2a -ffunction-sections -fdata-sections +export CFLAGS = -x c++ --std=c++14 -ffunction-sections -fdata-sections export LDFLAGS = -pthread export COPTFLAGS = -Os diff --git a/lib/imagereader/diskcopyimagereader.cc b/lib/imagereader/diskcopyimagereader.cc index 546ba3874..62a55c69d 100644 --- a/lib/imagereader/diskcopyimagereader.cc +++ b/lib/imagereader/diskcopyimagereader.cc @@ -115,13 +115,13 @@ class DiskCopyImageReader : public ImageReader } } - image.setGeometry({ - .numTracks = numCylinders, - .numSides = numHeads, - .numSectors = 12, - .sectorSize = 512 + 12, - .irregular = true - }); + Geometry g; + g.numTracks = numCylinders; + g.numSides = numHeads; + g.numSectors = 12; + g.sectorSize = 512 + 12; + g.irregular = true; + image.setGeometry(g); return image; } }; diff --git a/lib/imagereader/imdimagereader.cc b/lib/imagereader/imdimagereader.cc index d45485a3b..7c74420ba 100644 --- a/lib/imagereader/imdimagereader.cc +++ b/lib/imagereader/imdimagereader.cc @@ -259,12 +259,12 @@ class IMDImageReader : public ImageReader } //Write format detected in IMD image to screen to help user set the right write parameters - image.setGeometry({ - .numTracks = header.track, - .numSides = header.Head + 1U, - .numSectors = header.numSectors, - .sectorSize = sectorSize - }); + Geometry g; + g.numTracks = header.track; + g.numSides = header.Head + 1U; + g.numSectors = header.numSectors; + g.sectorSize = sectorSize; + image.setGeometry(g); size_t headSize = header.numSectors * sectorSize; size_t trackSize = headSize * (header.Head + 1); diff --git a/lib/imagereader/nsiimagereader.cc b/lib/imagereader/nsiimagereader.cc index e327ac325..c7e024c77 100644 --- a/lib/imagereader/nsiimagereader.cc +++ b/lib/imagereader/nsiimagereader.cc @@ -97,12 +97,12 @@ class NsiImageReader : public ImageReader } } - image.setGeometry({ - .numTracks = numCylinders, - .numSides = numHeads, - .numSectors = numSectors, - .sectorSize = sectorSize - }); + Geometry g; + g.numTracks = numCylinders; + g.numSides = numHeads; + g.numSectors = numSectors; + g.sectorSize = sectorSize; + image.setGeometry(g); return image; } }; diff --git a/lib/usb/fluxengineusb.cc b/lib/usb/fluxengineusb.cc index af9a570ed..4225c80d6 100644 --- a/lib/usb/fluxengineusb.cc +++ b/lib/usb/fluxengineusb.cc @@ -120,7 +120,9 @@ class FluxEngineUsb : public USB public: int getVersion() { - struct any_frame f = { .f = {.type = F_FRAME_GET_VERSION_CMD, .size = sizeof(f)} }; + struct any_frame f; + f.f.type = F_FRAME_GET_VERSION_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); auto r = await_reply(F_FRAME_GET_VERSION_REPLY); return r->version; @@ -128,29 +130,29 @@ class FluxEngineUsb : public USB void seek(int track) { - struct seek_frame f = { - .f = { .type = F_FRAME_SEEK_CMD, .size = sizeof(f) }, - .track = (uint8_t) track - }; + struct seek_frame f; + f.f.type = F_FRAME_SEEK_CMD; + f.f.size = sizeof(f); + f.track = (uint8_t) track; usb_cmd_send(&f, f.f.size); await_reply(F_FRAME_SEEK_REPLY); } void recalibrate() { - struct any_frame f = { - .f = { .type = F_FRAME_RECALIBRATE_CMD, .size = sizeof(f) }, - }; + struct any_frame f; + f.f.type = F_FRAME_RECALIBRATE_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); await_reply(F_FRAME_RECALIBRATE_REPLY); } nanoseconds_t getRotationalPeriod(int hardSectorCount) { - struct measurespeed_frame f = { - .f = {.type = F_FRAME_MEASURE_SPEED_CMD, .size = sizeof(f)}, - .hard_sector_count = (uint8_t) hardSectorCount, - }; + struct measurespeed_frame f; + f.f.type = F_FRAME_MEASURE_SPEED_CMD; + f.f.size = sizeof(f); + f.hard_sector_count = (uint8_t) hardSectorCount; usb_cmd_send(&f, f.f.size); auto r = await_reply(F_FRAME_MEASURE_SPEED_REPLY); @@ -159,7 +161,9 @@ class FluxEngineUsb : public USB void testBulkWrite() { - struct any_frame f = { .f = {.type = F_FRAME_BULK_WRITE_TEST_CMD, .size = sizeof(f)} }; + struct any_frame f; + f.f.type = F_FRAME_BULK_WRITE_TEST_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); /* These must match the device. */ @@ -198,7 +202,9 @@ class FluxEngineUsb : public USB void testBulkRead() { - struct any_frame f = { .f = {.type = F_FRAME_BULK_READ_TEST_CMD, .size = sizeof(f)} }; + struct any_frame f; + f.f.type = F_FRAME_BULK_READ_TEST_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); /* These must match the device. */ @@ -234,11 +240,11 @@ class FluxEngineUsb : public USB Bytes read(int side, bool synced, nanoseconds_t readTime, nanoseconds_t hardSectorThreshold) { - struct read_frame f = { - .f = { .type = F_FRAME_READ_CMD, .size = sizeof(f) }, - .side = (uint8_t) side, - .synced = (uint8_t) synced, - }; + struct read_frame f; + f.f.type = F_FRAME_READ_CMD; + f.f.size = sizeof(f); + f.side = (uint8_t) side; + f.synced = (uint8_t) synced; f.hardsec_threshold_ms = (hardSectorThreshold + 5e5) / 1e6; /* round to nearest ms */ uint16_t milliseconds = readTime / 1e6; ((uint8_t*)&f.milliseconds)[0] = milliseconds; @@ -260,10 +266,10 @@ class FluxEngineUsb : public USB unsigned safelen = bytes.size() & ~(FRAME_SIZE-1); Bytes safeBytes = bytes.slice(0, safelen); - struct write_frame f = { - .f = { .type = F_FRAME_WRITE_CMD, .size = sizeof(f) }, - .side = (uint8_t) side, - }; + struct write_frame f; + f.f.type = F_FRAME_WRITE_CMD; + f.f.size = sizeof(f); + f.side = (uint8_t) side; f.hardsec_threshold_ms = (hardSectorThreshold + 5e5) / 1e6; /* round to nearest ms */ ((uint8_t*)&f.bytes_to_write)[0] = safelen; ((uint8_t*)&f.bytes_to_write)[1] = safelen >> 8; @@ -278,10 +284,10 @@ class FluxEngineUsb : public USB void erase(int side, nanoseconds_t hardSectorThreshold) { - struct erase_frame f = { - .f = { .type = F_FRAME_ERASE_CMD, .size = sizeof(f) }, - .side = (uint8_t) side, - }; + struct erase_frame f; + f.f.type = F_FRAME_ERASE_CMD; + f.f.size = sizeof(f); + f.side = (uint8_t) side; f.hardsec_threshold_ms = (hardSectorThreshold + 5e5) / 1e6; /* round to nearest ms */ usb_cmd_send(&f, f.f.size); @@ -290,21 +296,21 @@ class FluxEngineUsb : public USB void setDrive(int drive, bool high_density, int index_mode) { - struct set_drive_frame f = { - .f = { .type = F_FRAME_SET_DRIVE_CMD, .size = sizeof(f) }, - .drive = (uint8_t) drive, - .high_density = high_density, - .index_mode = (uint8_t) index_mode - }; + struct set_drive_frame f; + f.f.type = F_FRAME_SET_DRIVE_CMD; + f.f.size = sizeof(f); + f.drive = (uint8_t) drive; + f.high_density = high_density; + f.index_mode = (uint8_t) index_mode; usb_cmd_send(&f, f.f.size); await_reply(F_FRAME_SET_DRIVE_REPLY); } void measureVoltages(struct voltages_frame* voltages) { - struct any_frame f = { - { .type = F_FRAME_MEASURE_VOLTAGES_CMD, .size = sizeof(f) }, - }; + struct any_frame f; + f.f.type = F_FRAME_MEASURE_VOLTAGES_CMD; + f.f.size = sizeof(f); usb_cmd_send(&f, f.f.size); auto convert_voltages_from_usb = [&](const struct voltages& vin, struct voltages& vout)