mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -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