mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9623a09d3 | ||
|
|
7be5623952 | ||
|
|
7884813973 | ||
|
|
10464f3c43 | ||
|
|
1c64df9482 | ||
|
|
145b1065c5 | ||
|
|
0783f701f6 | ||
|
|
7f13c1cbfb | ||
|
|
5a4f989236 | ||
|
|
9dae587ca8 | ||
|
|
7f3e9f2544 |
2
Makefile
2
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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
73
src/formats/kaypro2.textpb
Normal file
73
src/formats/kaypro2.textpb
Normal 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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user