mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	First hypothetically working version of the agat encoder.
This commit is contained in:
		
							
								
								
									
										7
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								Makefile
									
									
									
									
									
								
							| @@ -48,7 +48,7 @@ AR ?= $(CCPREFIX)ar | ||||
| PKG_CONFIG ?= pkg-config | ||||
| WX_CONFIG ?= wx-config | ||||
| PROTOC ?= protoc | ||||
| CFLAGS ?= -g -O3 | ||||
| CFLAGS ?= -g -O0 | ||||
| CXXFLAGS += -std=c++17 | ||||
| LDFLAGS ?= | ||||
| PLATFORM ?= UNIX | ||||
| @@ -163,17 +163,18 @@ define do-encodedecodetest-impl | ||||
| tests: $(OBJDIR)/$1$3.flux.encodedecode | ||||
| $(OBJDIR)/$1$3.flux.encodedecode: scripts/encodedecodetest.sh $(FLUXENGINE_BIN) $2 | ||||
| 	@mkdir -p $(dir $$@) | ||||
| 	@echo ENCODEDECODETEST .flux $1 $3 | ||||
| 	@echo ENCODEDECODETEST $1 flux $(FLUXENGINE_BIN) $2 $3 | ||||
| 	@scripts/encodedecodetest.sh $1 flux $(FLUXENGINE_BIN) $2 $3 > $$@ | ||||
|  | ||||
| tests: $(OBJDIR)/$1$3.scp.encodedecode | ||||
| $(OBJDIR)/$1$3.scp.encodedecode: scripts/encodedecodetest.sh $(FLUXENGINE_BIN) $2 | ||||
| 	@mkdir -p $(dir $$@) | ||||
| 	@echo ENCODEDECODETEST .scp $1 $3 | ||||
| 	@echo ENCODEDECODETEST $1 scp $(FLUXENGINE_BIN) $2 $3 | ||||
| 	@scripts/encodedecodetest.sh $1 scp $(FLUXENGINE_BIN) $2 $3 > $$@ | ||||
|  | ||||
| endef | ||||
|  | ||||
| $(call do-encodedecodetest,agat840) | ||||
| $(call do-encodedecodetest,amiga) | ||||
| $(call do-encodedecodetest,apple2) | ||||
| $(call do-encodedecodetest,atarist360) | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
|  | ||||
| #define AGAT_SECTOR_SIZE 256 | ||||
|  | ||||
| static constexpr uint64_t SECTOR_ID = 0x8924555549111444; | ||||
| static constexpr uint64_t DATA_ID = 0x8924555514444911; | ||||
|  | ||||
| class Encoder; | ||||
| class EncoderProto; | ||||
| class Decoder; | ||||
|   | ||||
| @@ -1,6 +1,19 @@ | ||||
| syntax = "proto2"; | ||||
|  | ||||
| import "lib/common.proto"; | ||||
|  | ||||
| message AgatDecoderProto {} | ||||
|  | ||||
| message AgatEncoderProto {} | ||||
| message AgatEncoderProto { | ||||
| 	optional double target_clock_period_us = 1 | ||||
| 		[default=2.00, (help)="Data clock period of target format."]; | ||||
| 	optional double target_rotational_period_ms = 2 | ||||
| 		[default=360, (help)="Rotational period of target format."]; | ||||
| 	optional int32 post_index_gap_bytes = 3 | ||||
| 		[default=20, (help)="Post-index gap before first sector header."]; | ||||
| 	optional int32 pre_sector_gap_bytes = 4 | ||||
| 		[default=20, (help)="Gap before each sector header."]; | ||||
| 	optional int32 pre_data_gap_bytes = 5 | ||||
| 		[default=20, (help)="Gap before each sector data record."]; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -33,10 +33,7 @@ | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| static const uint64_t SECTOR_ID = 0x8924555549111444; | ||||
| static const FluxPattern SECTOR_PATTERN(64, SECTOR_ID); | ||||
|  | ||||
| static const uint64_t DATA_ID = 0x8924555514444911; | ||||
| static const FluxPattern DATA_PATTERN(64, DATA_ID); | ||||
|  | ||||
| static const FluxMatchers ALL_PATTERNS = { | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| #include "globals.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "lib/globals.h" | ||||
| #include "lib/decoders/decoders.h" | ||||
| #include "lib/encoders/encoders.h" | ||||
| #include "agat.h" | ||||
| #include "crc.h" | ||||
| #include "readerwriter.h" | ||||
| #include "image.h" | ||||
| #include "lib/crc.h" | ||||
| #include "lib/readerwriter.h" | ||||
| #include "lib/image.h" | ||||
| #include "lib/layout.h" | ||||
| #include "arch/agat/agat.pb.h" | ||||
| #include "lib/encoders/encoders.pb.h" | ||||
|  | ||||
| @@ -17,16 +18,98 @@ public: | ||||
|     { | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     void writeRawBits(uint64_t data, int width) | ||||
|     { | ||||
|         _cursor += width; | ||||
|         _lastBit = data & 1; | ||||
|         for (int i = 0; i < width; i++) | ||||
|         { | ||||
|             unsigned pos = _cursor - i - 1; | ||||
|             if (pos < _bits.size()) | ||||
|                 _bits[pos] = data & 1; | ||||
|             data >>= 1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| 	void writeBytes(const Bytes& bytes) | ||||
| 	{ | ||||
| 		encodeMfm(_bits, _cursor, bytes, _lastBit); | ||||
| 	} | ||||
|  | ||||
| 	void writeByte(uint8_t byte) | ||||
| 	{ | ||||
| 		Bytes b; | ||||
| 		b.writer().write_8(byte); | ||||
| 		writeBytes(b); | ||||
| 	} | ||||
|  | ||||
| 	void writeFillerRawBytes(int count, uint16_t byte) | ||||
| 	{ | ||||
| 		for (int i = 0; i < count; i++) | ||||
| 			writeRawBits(byte, 16); | ||||
| 	}; | ||||
|  | ||||
| 	void writeFillerBytes(int count, uint8_t byte) | ||||
| 	{ | ||||
| 		Bytes b{byte}; | ||||
| 		for (int i = 0; i < count; i++) | ||||
| 			writeBytes(b); | ||||
| 	}; | ||||
|  | ||||
| public: | ||||
|     std::unique_ptr<Fluxmap> encode(std::shared_ptr<const TrackInfo>& trackInfo, | ||||
|         const std::vector<std::shared_ptr<const Sector>>& sectors, | ||||
|         const Image& image) override | ||||
|     { | ||||
|         Error() << "unimplemented"; | ||||
|         auto trackLayout = | ||||
|             Layout::getLayoutOfTrack(trackInfo->logicalTrack, trackInfo->logicalSide); | ||||
|  | ||||
|         double clockRateUs = _config.target_clock_period_us() / 2.0; | ||||
|         int bitsPerRevolution = | ||||
|             (_config.target_rotational_period_ms() * 1000.0) / clockRateUs; | ||||
|         _bits.resize(bitsPerRevolution); | ||||
|         _cursor = 0; | ||||
|  | ||||
| 		writeFillerRawBytes(_config.post_index_gap_bytes(), 0xaaaa); | ||||
|  | ||||
|         for (const auto& sector : sectors) | ||||
| 		{ | ||||
| 			/* Header */ | ||||
|  | ||||
| 			writeFillerRawBytes(_config.pre_sector_gap_bytes(), 0xaaaa); | ||||
| 			writeRawBits(SECTOR_ID, 64); | ||||
| 			writeByte(0x5a); | ||||
| 			writeByte((sector->logicalTrack << 1) | sector->logicalSide); | ||||
| 			writeByte(sector->logicalSector); | ||||
| 			writeByte(0x5a); | ||||
|  | ||||
| 			/* Data */ | ||||
|  | ||||
| 			writeFillerRawBytes(_config.pre_data_gap_bytes(), 0xaaaa); | ||||
| 			auto data = sector->data.slice(0, AGAT_SECTOR_SIZE); | ||||
| 			writeRawBits(DATA_ID, 64); | ||||
| 			writeBytes(data); | ||||
| 			writeByte(agatChecksum(data)); | ||||
| 			writeByte(0x5a); | ||||
| 		} | ||||
|  | ||||
|         if (_cursor >= _bits.size()) | ||||
|             Error() << "track data overrun"; | ||||
|         fillBitmapTo(_bits, _cursor, _bits.size(), {true, false}); | ||||
|  | ||||
|         auto fluxmap = std::make_unique<Fluxmap>(); | ||||
|         fluxmap->appendBits(_bits, | ||||
|             calculatePhysicalClockPeriod( | ||||
|                 _config.target_clock_period_us() * 1e3, _config.target_rotational_period_ms() * 1e6)); | ||||
|         return fluxmap; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     const AgatEncoderProto& _config; | ||||
| 	uint32_t _cursor; | ||||
| 	bool _lastBit; | ||||
|     std::vector<bool> _bits; | ||||
| }; | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user