Compare commits

...

11 Commits

Author SHA1 Message Date
David Given
b9623a09d3 Switch back to C++14; remove use of designated initialisers. 2021-08-04 21:25:11 +02:00
David Given
7be5623952 Merge from master. 2021-08-04 20:39:23 +02:00
David Given
7884813973 Add the Kaypro II format to the IBM page. 2021-08-03 23:06:10 +02:00
David Given
10464f3c43 Fix after merge. 2021-08-03 23:05:54 +02:00
David Given
1c64df9482 Merge from master. 2021-08-03 22:46:08 +02:00
David Given
145b1065c5 Test the kaypro2 profile. 2021-08-01 21:54:03 +02:00
David Given
0783f701f6 Merge from master. 2021-08-01 21:25:10 +02:00
David Given
7f13c1cbfb Randomly fiddle with the Kaypro 2 format until something works. 2021-07-27 19:36:32 +02:00
David Given
5a4f989236 Show more information when a track overrun occurs. 2021-07-27 19:36:15 +02:00
David Given
9dae587ca8 Update Kaypro II format. 2021-07-20 23:28:49 +02:00
David Given
7f3e9f2544 Add a prototype Kaypro2 format. 2021-07-19 23:29:49 +02:00
10 changed files with 145 additions and 59 deletions

View File

@@ -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

View File

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

View File

@@ -144,7 +144,7 @@ public:
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());
@@ -261,12 +261,15 @@ public:
}
}
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> fluxmap(new Fluxmap);
_bits.resize(bitsPerRevolution);
fluxmap->appendBits(_bits, clockRateUs*1e3);
return fluxmap;
}

View File

@@ -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

View File

@@ -115,13 +115,13 @@ public:
}
}
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;
}
};

View File

@@ -259,12 +259,12 @@ public:
}
//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);

View File

@@ -97,12 +97,12 @@ public:
}
}
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;
}
};

View File

@@ -120,7 +120,9 @@ private:
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<struct version_frame>(F_FRAME_GET_VERSION_REPLY);
return r->version;
@@ -128,29 +130,29 @@ public:
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<struct any_frame>(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<struct any_frame>(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<struct speed_frame>(F_FRAME_MEASURE_SPEED_REPLY);
@@ -159,7 +161,9 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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<struct any_frame>(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)

View File

@@ -418,6 +418,7 @@ FORMATS="\
ibm360_525 \
ibm720 \
ibm720_525 \
kaypro2 \
mac400 \
mac800 \
micropolis \
@@ -523,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

View File

@@ -0,0 +1,73 @@
comment: 'Kaypro II 5.25" 40-track 10-sector SSDD'
image_reader {
filename: "kaypro2.img"
img {
trackdata {
sector_size: 512
sector_range {
start_sector: 0
sector_count: 10
}
}
tracks: 40
sides: 1
physical_step: 1
}
}
image_writer {
filename: "kaypro2.img"
img {
trackdata {
sector_size: 512
sector_range {
start_sector: 0
sector_count: 10
}
}
tracks: 40
sides: 1
physical_step: 1
}
}
encoder {
ibm {
trackdata {
emit_iam: false
track_length_ms: 167
clock_rate_khz: 300
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
}
}
}
decoder {
ibm {}
}
cylinders {
start: 0
end: 39
}
heads {
start: 0
end: 0
}