mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-31 11:17:01 -07:00 
			
		
		
		
	Compare commits
	
		
			7 Commits
		
	
	
		
			FluxEngine
			...
			FluxEngine
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 4056364300 | ||
|  | 60bfe050d3 | ||
|  | 28d0ce765e | ||
|  | 4954d33307 | ||
|  | 55f3354287 | ||
|  | d6ae373fa8 | ||
|  | a626d5f9a0 | 
| @@ -15,7 +15,7 @@ install: | ||||
|  | ||||
| build_script: | ||||
|   - make | ||||
|   - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe | ||||
|   - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex | ||||
|  | ||||
| artifacts: | ||||
|   - path: fluxengine.zip | ||||
|   | ||||
							
								
								
									
										4626
									
								
								FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4626
									
								
								FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -3700,6 +3700,6 @@ | ||||
| </ignored_deps> | ||||
| </CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37> | ||||
| <boot_component v="" /> | ||||
| <current_generation v="60" /> | ||||
| <current_generation v="68" /> | ||||
| </CyGuid_fec8f9e8-2365-4bdb-96d3-a4380222e01b> | ||||
| </CyXmlSerializer> | ||||
| @@ -103,7 +103,43 @@ the unconnected pins and solder a short piece of wire to a GND pin on the | ||||
| board. Alternatively you'll need to splice it into your drive's power supply | ||||
| cable somehow. (The black one.) | ||||
|  | ||||
| ## Building the firmware | ||||
| ## Programming the board | ||||
|  | ||||
| You've got two options here. You can either use the precompiled firmware | ||||
| supplied with the source, or else install the Cypress SDK and build it | ||||
| yourself. If you want to hack the firmware source you need the latter, but | ||||
| if you trust me to do it for you use the precompiled firmware. In either | ||||
| case you'll need Windows and have to install some Cypress stuff. | ||||
|  | ||||
| **Before you read this:** If you're on Windows, good news! You can download a | ||||
| precompiled version of the FluxEngine client and precompiled firmware [from | ||||
| the GitHub releases | ||||
| page](https://github.com/davidgiven/fluxengine/releases/latest). Simply unzip | ||||
| it somewhere and run the `.exe` files from a `cmd` window (or other shell). | ||||
| Follow the instructions below to program the board with the firmware. | ||||
|  | ||||
| ### Using the precompiled firmware | ||||
|  | ||||
| On your Windows machine, [install the PSoC | ||||
| Programmer](https://www.cypress.com/products/psoc-programming-solutions). | ||||
| **Note:** _not_ the Cypress Programmer, which is for a different board! | ||||
| Cypress will make you register. | ||||
|  | ||||
| Once done, run it. Plug the blunt end of the FluxEngine board into a USB | ||||
| port (the end which is a USB connector). The programmer should detect it | ||||
| and report it as a KitProg. You may be prompted to upgrade the programmer | ||||
| hardware; if so, follow the instructions and do it. | ||||
|  | ||||
| Now go to File -> File Load and open | ||||
| `FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex` in the | ||||
| project. If you're on Windows, the precompiled zipfile also contains a copy | ||||
| of this file. Press the Program button (the one in the toolbar marked with a | ||||
| down arrow). Stuff will happen and you should be left with three green boxes | ||||
| in the status bar and 'Programming Succeeded' at the top of the log window. | ||||
|  | ||||
| You're done. You can unplug the board and close the programmer. | ||||
|  | ||||
| ### Building the firmware yourself | ||||
|  | ||||
| On your Windows machine, [install the Cypress SDK and CY8CKIT-059 | ||||
| BSP](http://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and). | ||||
| @@ -118,7 +154,7 @@ tutorial and making the LED on your board flash. It'll tell you where all the | ||||
| controls are and how to program the board. Remember that the big end of the | ||||
| board plugs into your computer for programming. | ||||
|  | ||||
| When you're ready, open the `FluxEngine.cydsn/FluxEngine.cywrk` workspace, | ||||
| When you're ready, open the `FluxEngine.cydsn/FluxEngine.cyprj` project, | ||||
| pick 'Program' from the menu, and the firmware should compile and be | ||||
| programmed onto your board. | ||||
|  | ||||
| @@ -139,11 +175,6 @@ the port and proceed normally. | ||||
|  | ||||
| ## Building the client | ||||
|  | ||||
| **Before you read this:** If you're on Windows, good news! You can download a | ||||
| *precompiled version of the FluxEngine client [from the GitHub releases | ||||
| *page](https://github.com/davidgiven/fluxengine/releases/latest). Simply unzip | ||||
| *it somewhere and run it from a `cmd` window (or other shell). | ||||
|  | ||||
| The client software is where the intelligence, such as it is, is. It's pretty | ||||
| generic libusb stuff and should build and run on Windows, Linux and OSX as | ||||
| well, although on Windows it'll need MSYS2 and mingw32. You'll need to | ||||
|   | ||||
| @@ -23,7 +23,7 @@ computer](https://ilesj.wordpress.com/2014/05/14/1541-why-so-complicated/) of | ||||
| 300 bytes per second (!). (The drive itself could transfer data reasonably | ||||
| quickly.) | ||||
|  | ||||
| A standard 1541 disk has 35 tracks of 17 to 20 sectors, each 256 bytes long. | ||||
| A standard 1541 disk has 35 tracks of 17 to 21 sectors, each 256 bytes long. | ||||
|  | ||||
| Reading discs | ||||
| ------------- | ||||
| @@ -34,15 +34,14 @@ Just do: | ||||
| fluxengine read c64 | ||||
| ``` | ||||
|  | ||||
| You should end up with an `c64.img` which is 187136 bytes long (for a normal | ||||
| 1541 disk). | ||||
| You should end up with an `c64.d64` file which is 174848 bytes long. You can | ||||
| load this straight into a Commodore 64 emulator such as | ||||
| [VICE](http://vice-emu.sourceforge.net/). | ||||
|  | ||||
| **Big warning!** The image may not work in an emulator. Commodore 64 disk images are | ||||
| **Big warning!** Commodore 64 disk images are | ||||
| complicated due to the way the tracks are different sizes and the odd sector | ||||
| size. FluxEngine chooses to store them in a simple 256 x 20 x 35 layout, | ||||
| with holes where missing sectors should be. This was easiest. If anyone can | ||||
| suggest a better way, please [get in | ||||
| touch](https://github.com/davidgiven/fluxengine/issues/new). | ||||
| size, so you need the special D64 or LDBS output formats to represent them | ||||
| sensibly. Don't use IMG unless you know what you're doing. | ||||
|  | ||||
| Useful references | ||||
| ----------------- | ||||
|   | ||||
| @@ -148,6 +148,15 @@ based on the extension: | ||||
|     it doesn't store a lot of the more esoteric LDBS features like format | ||||
|     types, timings, and data rates. | ||||
|  | ||||
|   - `.d64`: the venerable Commodore 64 disk image format as used by the 1540, | ||||
|     1541, etc. This is a special-purpose format due to the weird layout of | ||||
|     1540 disks and while you can use this for non-Commodore disks the result | ||||
|     will be gibberish. Use this to image Commodore 64 disks and load the | ||||
|     result into an emulator. | ||||
|  | ||||
|     FluxEngine's D64 support is currently limited to write only. It will work | ||||
|     with up to 40 logical tracks. | ||||
|  | ||||
| ### High density disks | ||||
|  | ||||
| High density disks use a different magnetic medium to low and double density | ||||
|   | ||||
| @@ -22,7 +22,7 @@ extern void hexdumpForSrp16(std::ostream& stream, const Bytes& bytes); | ||||
| class Error | ||||
| { | ||||
| public: | ||||
|     ~Error() | ||||
|     [[ noreturn ]] ~Error() | ||||
|     { | ||||
|         std::cerr << "Error: " << _stream.str() << std::endl; | ||||
|         exit(1); | ||||
|   | ||||
| @@ -7,6 +7,13 @@ | ||||
| #include "imagereader/imagereader.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| std::map<std::string, ImageReader::Constructor> ImageReader::formats = | ||||
| { | ||||
| 	{".adf", ImageReader::createImgImageReader}, | ||||
| 	{".d81", ImageReader::createImgImageReader}, | ||||
| 	{".img", ImageReader::createImgImageReader}, | ||||
| }; | ||||
|  | ||||
| static bool ends_with(const std::string& value, const std::string& ending) | ||||
| { | ||||
|     if (ending.size() > value.size()) | ||||
| @@ -14,15 +21,29 @@ static bool ends_with(const std::string& value, const std::string& ending) | ||||
|     return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<ImageReader> ImageReader::create(const ImageSpec& spec) | ||||
| ImageReader::Constructor ImageReader::findConstructor(const ImageSpec& spec) | ||||
| { | ||||
|     const auto& filename = spec.filename; | ||||
|  | ||||
|     if (ends_with(filename, ".img") || ends_with(filename, ".adf")) | ||||
|         return createImgImageReader(spec); | ||||
| 	for (const auto& e : formats) | ||||
| 	{ | ||||
| 		if (ends_with(filename, e.first)) | ||||
| 			return e.second; | ||||
| 	} | ||||
|  | ||||
|     Error() << "unrecognised image filename extension"; | ||||
|     return std::unique_ptr<ImageReader>(); | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<ImageReader> ImageReader::create(const ImageSpec& spec) | ||||
| { | ||||
|     verifyImageSpec(spec); | ||||
|     return findConstructor(spec)(spec); | ||||
| } | ||||
|  | ||||
| void ImageReader::verifyImageSpec(const ImageSpec& spec) | ||||
| { | ||||
|     if (!findConstructor(spec)) | ||||
|         Error() << "unrecognised image filename extension"; | ||||
| } | ||||
|  | ||||
| ImageReader::ImageReader(const ImageSpec& spec): | ||||
|   | ||||
| @@ -12,10 +12,21 @@ public: | ||||
|  | ||||
| public: | ||||
|     static std::unique_ptr<ImageReader> create(const ImageSpec& spec); | ||||
| 	static void verifyImageSpec(const ImageSpec& spec); | ||||
|  | ||||
| private: | ||||
| 	typedef  | ||||
| 		std::function< | ||||
| 			std::unique_ptr<ImageReader>(const ImageSpec& spec) | ||||
| 		> | ||||
| 		Constructor; | ||||
|  | ||||
| 	static std::map<std::string, Constructor> formats; | ||||
|  | ||||
|     static std::unique_ptr<ImageReader> createImgImageReader(const ImageSpec& spec); | ||||
|  | ||||
| 	static Constructor findConstructor(const ImageSpec& spec); | ||||
|  | ||||
| public: | ||||
| 	virtual SectorSet readImage() = 0; | ||||
|  | ||||
|   | ||||
							
								
								
									
										64
									
								
								lib/imagewriter/d64imagewriter.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								lib/imagewriter/d64imagewriter.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| #include "globals.h" | ||||
| #include "image.h" | ||||
| #include "flags.h" | ||||
| #include "dataspec.h" | ||||
| #include "sector.h" | ||||
| #include "sectorset.h" | ||||
| #include "imagewriter/imagewriter.h" | ||||
| #include "fmt/format.h" | ||||
| #include "ldbs.h" | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
|  | ||||
| static int sectors_per_track(int track) | ||||
| { | ||||
|     if (track < 17) | ||||
|         return 21; | ||||
|     if (track < 24) | ||||
|         return 19; | ||||
|     if (track < 30) | ||||
|         return 18; | ||||
|     return 17; | ||||
| } | ||||
|  | ||||
| class D64ImageWriter : public ImageWriter | ||||
| { | ||||
| public: | ||||
| 	D64ImageWriter(const SectorSet& sectors, const ImageSpec& spec): | ||||
| 		ImageWriter(sectors, spec) | ||||
| 	{} | ||||
|  | ||||
| 	void writeImage() | ||||
| 	{ | ||||
| 		std::cout << "writing D64 triangular image\n"; | ||||
|  | ||||
| 		std::ofstream outputFile(spec.filename, std::ios::out | std::ios::binary); | ||||
| 		if (!outputFile.is_open()) | ||||
| 			Error() << "cannot open output file"; | ||||
|  | ||||
|         uint32_t offset = 0; | ||||
| 		for (int track = 0; track < 40; track++) | ||||
| 		{ | ||||
|             int sectorCount = sectors_per_track(track); | ||||
|             for (int sectorId = 0; sectorId < sectorCount; sectorId++) | ||||
|             { | ||||
|                 const auto& sector = sectors.get(track, 0, sectorId); | ||||
|                 if (sector) | ||||
|                 { | ||||
|                     outputFile.seekp(offset); | ||||
|                     outputFile.write((const char*) sector->data.cbegin(), 256); | ||||
|                 } | ||||
|  | ||||
|                 offset += 256; | ||||
|             } | ||||
| 		} | ||||
|     } | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<ImageWriter> ImageWriter::createD64ImageWriter( | ||||
| 	const SectorSet& sectors, const ImageSpec& spec) | ||||
| { | ||||
|     return std::unique_ptr<ImageWriter>(new D64ImageWriter(sectors, spec)); | ||||
| } | ||||
|  | ||||
| @@ -7,6 +7,15 @@ | ||||
| #include "imagewriter/imagewriter.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| std::map<std::string, ImageWriter::Constructor> ImageWriter::formats = | ||||
| { | ||||
| 	{".adf", ImageWriter::createImgImageWriter}, | ||||
| 	{".d64", ImageWriter::createD64ImageWriter}, | ||||
| 	{".d81", ImageWriter::createImgImageWriter}, | ||||
| 	{".img", ImageWriter::createImgImageWriter}, | ||||
| 	{".ldbs", ImageWriter::createLDBSImageWriter}, | ||||
| }; | ||||
|  | ||||
| static bool ends_with(const std::string& value, const std::string& ending) | ||||
| { | ||||
|     if (ending.size() > value.size()) | ||||
| @@ -14,17 +23,29 @@ static bool ends_with(const std::string& value, const std::string& ending) | ||||
|     return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec) | ||||
| ImageWriter::Constructor ImageWriter::findConstructor(const ImageSpec& spec) | ||||
| { | ||||
|     const auto& filename = spec.filename; | ||||
|  | ||||
|     if (ends_with(filename, ".img") || ends_with(filename, ".adf")) | ||||
|         return createImgImageWriter(sectors, spec); | ||||
| 	else if (ends_with(filename, ".ldbs")) | ||||
| 		return createLDBSImageWriter(sectors, spec); | ||||
| 	for (const auto& e : formats) | ||||
| 	{ | ||||
| 		if (ends_with(filename, e.first)) | ||||
| 			return e.second; | ||||
| 	} | ||||
|  | ||||
|     Error() << "unrecognised image filename extension"; | ||||
|     return std::unique_ptr<ImageWriter>(); | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const ImageSpec& spec) | ||||
| { | ||||
| 	verifyImageSpec(spec); | ||||
| 	return findConstructor(spec)(sectors, spec); | ||||
| } | ||||
|  | ||||
| void ImageWriter::verifyImageSpec(const ImageSpec& spec) | ||||
| { | ||||
| 	if (!findConstructor(spec)) | ||||
| 		Error() << "unrecognised image filename extension"; | ||||
| } | ||||
|  | ||||
| ImageWriter::ImageWriter(const SectorSet& sectors, const ImageSpec& spec): | ||||
|   | ||||
| @@ -12,12 +12,25 @@ public: | ||||
|  | ||||
| public: | ||||
|     static std::unique_ptr<ImageWriter> create(const SectorSet& sectors, const ImageSpec& spec); | ||||
| 	static void verifyImageSpec(const ImageSpec& filename); | ||||
|  | ||||
| private: | ||||
| 	typedef  | ||||
| 		std::function< | ||||
| 			std::unique_ptr<ImageWriter>(const SectorSet& sectors, const ImageSpec& spec) | ||||
| 		> | ||||
| 		Constructor; | ||||
|  | ||||
| 	static std::map<std::string, Constructor> formats; | ||||
|  | ||||
|     static std::unique_ptr<ImageWriter> createImgImageWriter( | ||||
| 		const SectorSet& sectors, const ImageSpec& spec); | ||||
|     static std::unique_ptr<ImageWriter> createLDBSImageWriter( | ||||
| 		const SectorSet& sectors, const ImageSpec& spec); | ||||
|     static std::unique_ptr<ImageWriter> createD64ImageWriter( | ||||
| 		const SectorSet& sectors, const ImageSpec& spec); | ||||
|  | ||||
| 	static Constructor findConstructor(const ImageSpec& spec); | ||||
|  | ||||
| public: | ||||
| 	virtual void adjustGeometry(); | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "bytes.h" | ||||
| #include "decoders/rawbits.h" | ||||
| #include "track.h" | ||||
| #include "imagewriter/imagewriter.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags }; | ||||
| @@ -153,7 +154,8 @@ static void replace_sector(std::unique_ptr<Sector>& replacing, Sector& replaceme | ||||
| void readDiskCommand(AbstractDecoder& decoder) | ||||
| { | ||||
| 	const ImageSpec outputSpec(output); | ||||
|  | ||||
| 	ImageWriter::verifyImageSpec(outputSpec); | ||||
|          | ||||
| 	bool failures = false; | ||||
| 	SectorSet allSectors; | ||||
| 	auto tracks = readTracks(); | ||||
|   | ||||
| @@ -139,6 +139,7 @@ buildlibrary libfmt.a \ | ||||
| buildlibrary libbackend.a \ | ||||
| 	lib/imagereader/imagereader.cc \ | ||||
| 	lib/imagereader/imgimagereader.cc \ | ||||
| 	lib/imagewriter/d64imagewriter.cc \ | ||||
| 	lib/imagewriter/imagewriter.cc \ | ||||
| 	lib/imagewriter/imgimagewriter.cc \ | ||||
| 	lib/imagewriter/ldbsimagewriter.cc \ | ||||
|   | ||||
| @@ -16,7 +16,7 @@ static FlagGroup flags { &readerFlags }; | ||||
| int mainReadC64(int argc, const char* argv[]) | ||||
| { | ||||
| 	setReaderDefaultSource(":t=0-79x2:s=0"); | ||||
| 	setReaderDefaultOutput("c64.img"); | ||||
| 	setReaderDefaultOutput("c64.d64"); | ||||
|     setReaderRevolutions(2); | ||||
|     flags.parseFlags(argc, argv); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user