mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	Compare commits
	
		
			29 Commits
		
	
	
		
			FluxEngine
			...
			FluxEngine
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 28e0ef0463 | ||
|  | 4b07c38782 | ||
|  | e0256adf77 | ||
|  | 5748f017dd | ||
|  | 973f4c2c2d | ||
|  | 8e1774c69f | ||
|  | 56a36072f7 | ||
|  | 8755d108ed | ||
|  | ea40cd73d1 | ||
|  | 0e28899b72 | ||
|  | eee30db981 | ||
|  | 6959d18017 | ||
|  | 9f92ce0ef7 | ||
|  | 7658c1d774 | ||
|  | 31dc3504e6 | ||
|  | af0c9d4261 | ||
|  | 155b9daef6 | ||
|  | a2fdbc5c73 | ||
|  | 1e3581c5f3 | ||
|  | a1d345856e | ||
|  | 7a775afaea | ||
|  | c27c4fe312 | ||
|  | ad295c683c | ||
|  | 3f8fdaa27a | ||
|  | 9f5d01787f | ||
|  | 3c4487c42e | ||
|  | e5c2168a35 | ||
|  | 98ea5e9600 | ||
|  | ce6077fa22 | 
| @@ -15,7 +15,7 @@ install: | ||||
|  | ||||
| build_script: | ||||
|   - make | ||||
|   - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe cwftoflux.exe | ||||
|   - zip -9 fluxengine.zip fluxengine.exe brother120tool.exe | ||||
|  | ||||
| artifacts: | ||||
|   - path: fluxengine.zip | ||||
|   | ||||
| @@ -28,13 +28,37 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="4eef02b9-8ad1-43c4-85f1-b3335faa5fc4"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_3" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_3" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="06c4d5d4-f15f-4b29-a1d0-c24b2e38b1ec"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_FREQ" /> | ||||
|         <Data key="desired_freq" value="24" /> | ||||
|         <Data key="desired_freq" value="12" /> | ||||
|         <Data key="desired_unit" value="6" /> | ||||
|         <Data key="divider" value="1" /> | ||||
|         <Data key="divider" value="2" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
| @@ -50,7 +74,7 @@ | ||||
|         <Data key="src_clk_name" value="IMO" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|         <Data key="user_set_domain" value="True" /> | ||||
|       </Group> | ||||
|       <Group key="24cd38f7-f472-4403-837f-86807c8f5333"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
| @@ -193,6 +217,54 @@ | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="75187c05-9501-4450-b306-6ccdd3bb77db"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_5" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_5" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="b762c287-7f87-4b21-982e-84be01dc5115"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
|         <Data key="derive_type" value="NAMED_DIVIDER" /> | ||||
|         <Data key="desired_freq" value="0" /> | ||||
|         <Data key="desired_unit" value="15" /> | ||||
|         <Data key="divider" value="0" /> | ||||
|         <Data key="domain" value="DIGITAL" /> | ||||
|         <Data key="enabled" value="True" /> | ||||
|         <Data key="minus_accuracy" value="0.25" /> | ||||
|         <Data key="minus_tolerance" value="5" /> | ||||
|         <Data key="name" value="Clock_2" /> | ||||
|         <Data key="named_src_direct_connect" value="True" /> | ||||
|         <Data key="netlist_name" value="Clock_2" /> | ||||
|         <Data key="placement" value="AUTO" /> | ||||
|         <Data key="plus_accuracy" value="0.25" /> | ||||
|         <Data key="plus_tolerance" value="5" /> | ||||
|         <Data key="scope" value="LOCAL" /> | ||||
|         <Data key="src_clk_id" value="75C2148C-3656-4d8a-846D-0CAE99AB6FF7" /> | ||||
|         <Data key="src_clk_name" value="BUS_CLK" /> | ||||
|         <Data key="start_on_reset" value="True" /> | ||||
|         <Data key="sync_with_bus_clk" value="True" /> | ||||
|         <Data key="user_set_domain" value="False" /> | ||||
|       </Group> | ||||
|       <Group key="b0162966-0060-4af5-82d1-fcb491ad7619/be0a0e37-ad17-42ca-b5a1-1a654d736358"> | ||||
|         <Data key="check_tolerance" value="True" /> | ||||
|         <Data key="clock_version" value="v1" /> | ||||
| @@ -537,6 +609,7 @@ | ||||
|   <Group key="DWRInstGuidMapping"> | ||||
|     <Group key="Clock"> | ||||
|       <Data key="0b2f9bbb-00ce-4115-a788-ffb9d046a9e5" value="Clock_4" /> | ||||
|       <Data key="4eef02b9-8ad1-43c4-85f1-b3335faa5fc4" value="Clock_3" /> | ||||
|       <Data key="06c4d5d4-f15f-4b29-a1d0-c24b2e38b1ec" value="CounterClock" /> | ||||
|       <Data key="24cd38f7-f472-4403-837f-86807c8f5333" value="PULSE_CLOCK" /> | ||||
|       <Data key="63ed4137-0b09-4256-8a27-35c9a2653f1a" value="Clock_2" /> | ||||
| @@ -544,6 +617,8 @@ | ||||
|       <Data key="349ffa20-8576-4ac3-9a6f-34ef606de6cf" value="Clock_1" /> | ||||
|       <Data key="6616e828-6611-4893-a674-66c861d79d6c" value="SignalSamplingClock" /> | ||||
|       <Data key="12664fc6-9d70-44b1-8a49-887a292e1b7f" value="Clock_3" /> | ||||
|       <Data key="75187c05-9501-4450-b306-6ccdd3bb77db" value="Clock_5" /> | ||||
|       <Data key="b762c287-7f87-4b21-982e-84be01dc5115" value="Clock_2" /> | ||||
|       <Data key="b0162966-0060-4af5-82d1-fcb491ad7619/be0a0e37-ad17-42ca-b5a1-1a654d736358" value="UART_IntClock" /> | ||||
|       <Data key="cb7e877c-9fb4-4fc1-a708-f1e48eb5a68c" value="CounterClock" /> | ||||
|       <Data key="e4a53a4c-40e1-4747-a72a-10193ffdf31c" value="Clock_1" /> | ||||
| @@ -553,6 +628,7 @@ | ||||
|       <Data key="4a398466-709f-4228-9500-96178658e13e" value="RDATA" /> | ||||
|       <Data key="5a3407c1-b434-4438-a7b4-b9dfd2280495" value="MOTEA" /> | ||||
|       <Data key="8d318d8b-cf7b-4b6b-b02c-ab1c5c49d0ba" value="SW1" /> | ||||
|       <Data key="12e00eac-69b5-4717-85c8-25ef6b224d4c" value="DEBUG_PINS" /> | ||||
|       <Data key="41e2d8ed-5494-4d8c-8ff7-f4f789cece51" value="REDWC" /> | ||||
|       <Data key="264be2d3-9481-494b-8d9c-c1905a45e9cc" value="FDD" /> | ||||
|       <Data key="472f8fdb-f772-44fb-8897-cc690694237b" value="WDATA" /> | ||||
| @@ -561,6 +637,7 @@ | ||||
|       <Data key="1425177d-0d0e-4468-8bcc-e638e5509a9b" value="UartRx" /> | ||||
|       <Data key="a5d987c6-e45b-45b9-ad93-656fab06d720" value="TRK00" /> | ||||
|       <Data key="a93ef5b3-00f4-42c0-8fad-0e275a7e2537" value="MOTEB" /> | ||||
|       <Data key="b8380fb7-fdb8-449f-bd8d-c4ca96cdf55a" value="DEBUG_PINS" /> | ||||
|       <Data key="bc5d52a1-1b25-4aa0-9ba9-3f81d122772f" value="DEBUG_PINS" /> | ||||
|       <Data key="beca5e2d-f70f-4900-a4db-7eca1ed3126e/8b77a6c4-10a0-4390-971c-672353e2a49c" value="USBFS_Dm" /> | ||||
|       <Data key="beca5e2d-f70f-4900-a4db-7eca1ed3126e/618a72fc-5ddd-4df5-958f-a3d55102db42" value="USBFS_Dp" /> | ||||
| @@ -571,7 +648,7 @@ | ||||
|       <Data key="e51063a9-4fad-40c7-a06b-7cc4b137dc18" value="DSKCHG" /> | ||||
|       <Data key="ea7ee228-8b3f-426c-8bb8-cd7a81937769" value="DIR" /> | ||||
|       <Data key="ed092b9b-d398-4703-be89-cebf998501f6" value="UartTx" /> | ||||
|       <Data key="fbd1f839-40f9-498e-a48b-5f3048ea5c3d/52f31aa9-2f0a-497d-9a1f-1424095e13e6" value="SW_Tx_UART_1_tx" /> | ||||
|       <Data key="fbd1f839-40f9-498e-a48b-5f3048ea5c3d/52f31aa9-2f0a-497d-9a1f-1424095e13e6" value="UART_tx" /> | ||||
|       <Data key="fede1767-f3fd-4021-b3d7-8f9d88f36f9b" value="DRVSA" /> | ||||
|       <Data key="fff78075-035e-43d7-8577-bc5be4d21926" value="WGATE" /> | ||||
|     </Group> | ||||
| @@ -3675,6 +3752,20 @@ | ||||
|         <Data key="Port Format" value="2,2" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="12e00eac-69b5-4717-85c8-25ef6b224d4c"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="2,2" /> | ||||
|       </Group> | ||||
|       <Group key="1"> | ||||
|         <Data key="Port Format" value="2,3" /> | ||||
|       </Group> | ||||
|       <Group key="2"> | ||||
|         <Data key="Port Format" value="2,4" /> | ||||
|       </Group> | ||||
|       <Group key="3"> | ||||
|         <Data key="Port Format" value="2,0" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="41e2d8ed-5494-4d8c-8ff7-f4f789cece51"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="2,7" /> | ||||
| @@ -3757,6 +3848,17 @@ | ||||
|         <Data key="Port Format" value="12,1" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="b8380fb7-fdb8-449f-bd8d-c4ca96cdf55a"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="2,5" /> | ||||
|       </Group> | ||||
|       <Group key="1"> | ||||
|         <Data key="Port Format" value="2,4" /> | ||||
|       </Group> | ||||
|       <Group key="2"> | ||||
|         <Data key="Port Format" value="2,3" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="bc5d52a1-1b25-4aa0-9ba9-3f81d122772f"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="0,5" /> | ||||
| @@ -3812,7 +3914,7 @@ | ||||
|     </Group> | ||||
|     <Group key="fbd1f839-40f9-498e-a48b-5f3048ea5c3d/52f31aa9-2f0a-497d-9a1f-1424095e13e6"> | ||||
|       <Group key="0"> | ||||
|         <Data key="Port Format" value="2,0" /> | ||||
|         <Data key="Port Format" value="2,5" /> | ||||
|       </Group> | ||||
|     </Group> | ||||
|     <Group key="fede1767-f3fd-4021-b3d7-8f9d88f36f9b"> | ||||
| @@ -3840,7 +3942,7 @@ | ||||
|     <Data key="CYDEV_ECC_ENABLE" value="False" /> | ||||
|     <Data key="CYDEV_HEAP_SIZE" value="0x80" /> | ||||
|     <Data key="CYDEV_INSTRUCT_CACHE_ENABLED" value="True" /> | ||||
|     <Data key="CYDEV_PROTECTION_ENABLE" value="False" /> | ||||
|     <Data key="CYDEV_PROTECTION_ENABLE" value="True" /> | ||||
|     <Data key="CYDEV_STACK_SIZE" value="0x0800" /> | ||||
|     <Data key="CYDEV_TEMPERATURE" value="0C - 85/125C" /> | ||||
|     <Data key="CYDEV_TRACE_ENABLED" value="False" /> | ||||
|   | ||||
| @@ -2310,13 +2310,13 @@ | ||||
| <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||
| <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="DEBUG_PINS" persistent=""> | ||||
| <Hidden v="True" /> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||
| <dependencies> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="DEBUG_PINS_aliases.h" persistent="Generated_Source\PSoC5\DEBUG_PINS_aliases.h"> | ||||
| <Hidden v="True" /> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="HEADER;;;;" /> | ||||
| <PropertyDeltas /> | ||||
| @@ -3249,6 +3249,39 @@ | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| <filters /> | ||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||
| <CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFolderSerialize" version="3"> | ||||
| <CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtBaseContainerSerialize" version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="CAPTURE_CONTROL" persistent=""> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <CyGuid_0820c2e7-528d-4137-9a08-97257b946089 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemListSerialize" version="2"> | ||||
| <dependencies> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="CAPTURE_CONTROL.h" persistent="Generated_Source\PSoC5\CAPTURE_CONTROL.h"> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="HEADER;;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="CAPTURE_CONTROL.c" persistent="Generated_Source\PSoC5\CAPTURE_CONTROL.c"> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="SOURCE_C;CortexM3;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| <CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFileSerialize" version="3" xml_contents_version="1"> | ||||
| <CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItemSerialize" version="2" name="CAPTURE_CONTROL_PM.c" persistent="Generated_Source\PSoC5\CAPTURE_CONTROL_PM.c"> | ||||
| <Hidden v="False" /> | ||||
| </CyGuid_31768f72-0253-412b-af77-e7dba74d1330> | ||||
| <build_action v="SOURCE_C;CortexM3;;;" /> | ||||
| <PropertyDeltas /> | ||||
| </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b> | ||||
| </dependencies> | ||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| <filters /> | ||||
| </CyGuid_ebc4f06d-207f-49c2-a540-72acf4adabc0> | ||||
| </dependencies> | ||||
| </CyGuid_0820c2e7-528d-4137-9a08-97257b946089> | ||||
| </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8> | ||||
| @@ -3667,6 +3700,6 @@ | ||||
| </ignored_deps> | ||||
| </CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37> | ||||
| <boot_component v="" /> | ||||
| <current_generation v="52" /> | ||||
| <current_generation v="60" /> | ||||
| </CyGuid_fec8f9e8-2365-4bdb-96d3-a4380222e01b> | ||||
| </CyXmlSerializer> | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -306,6 +306,7 @@ static void cmd_read(struct read_frame* f) | ||||
|     dma_underrun = false; | ||||
|     int count = 0; | ||||
|     SAMPLER_CONTROL_Write(0); /* !reset */ | ||||
|     CAPTURE_CONTROL_Write(1); | ||||
|     CyDmaChSetInitialTd(dma_channel, td[dma_writing_to_td]); | ||||
|     CyDmaClearPendingDrq(dma_channel); | ||||
|     CyDmaChEnable(dma_channel, 1); | ||||
| @@ -364,7 +365,8 @@ static void cmd_read(struct read_frame* f) | ||||
|         } | ||||
|         dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td); | ||||
|     } | ||||
| abort: | ||||
| abort:; | ||||
|     CAPTURE_CONTROL_Write(0); | ||||
|     CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN); | ||||
|     while (CyDmaChGetRequest(dma_channel)) | ||||
|         ; | ||||
|   | ||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @@ -22,7 +22,7 @@ export LIBS = $(shell pkg-config --libs $(PACKAGES)) | ||||
| export EXTENSION = | ||||
| endif | ||||
|  | ||||
| CFLAGS += -Ilib -Idep/fmt | ||||
| CFLAGS += -Ilib -Idep/fmt -Iarch | ||||
|  | ||||
| export OBJDIR = .obj | ||||
|  | ||||
|   | ||||
| @@ -89,7 +89,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 | | ||||
| | [Macintosh 800kB](doc/disk-macintosh.md) |  🦖   |        | and probably the 400kB too          | | ||||
| | [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 } | ||||
|  | ||||
| @@ -105,6 +105,7 @@ at least, check the CRC so what data's there is probably good. | ||||
| |:-----------------------------------------|:-----:|:------:|-------| | ||||
| | [AES Superplus / No Problem](doc/disk-aeslanier.md) |  🦖   | | hard sectors! | | ||||
| | [Durango F85](doc/disk-durangof85.md)    |  🦖   |        | 5.25" | | ||||
| | [DVK MX](doc/disk-mx.md)                 |  🦖   |        | Soviet PDP-11 clone | | ||||
| | [Victor 9000](doc/disk-victor9k.md)      |  🦖   |        | 8-inch        | | ||||
| | [Zilog MCZ](doc/disk-zilogmcz.md)        |  🦖   |        | 8-inch _and_ hard sectors | | ||||
| {: .datatable } | ||||
| @@ -189,7 +190,7 @@ Jonathan Müller (`foonathan <https://github.com/foonathan>`) with | ||||
| contributions from many other people. It is licensed under the terms of the | ||||
| BSD license. Please see the contents of the directory for the full text. | ||||
|  | ||||
| As an exception, `dep/fnmatchemu` contains parts of the OpenBSD C library | ||||
| As an exception, `dep/emu` contains parts of the OpenBSD C library | ||||
| code, Todd Miller and William A. Rowe (and probably others). It is licensed | ||||
| under the terms of the 3-clause BSD license. Please see the contents of the | ||||
| directory for the full text. It's been lightly modified by me. | ||||
|   | ||||
| @@ -9,6 +9,9 @@ | ||||
| #define BROTHER_DATA_RECORD_CHECKSUM     3 | ||||
| #define BROTHER_DATA_RECORD_ENCODED_SIZE 415 | ||||
| 
 | ||||
| #define BROTHER_TRACKS_PER_DISK          78 | ||||
| #define BROTHER_SECTORS_PER_TRACK        12 | ||||
| 
 | ||||
| class Sector; | ||||
| class Fluxmap; | ||||
| 
 | ||||
| @@ -22,9 +25,15 @@ public: | ||||
|     void decodeDataRecord(); | ||||
| }; | ||||
| 
 | ||||
| extern void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor, | ||||
| 		int track, int sector); | ||||
| extern void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor, | ||||
| 		const Bytes& data); | ||||
| class BrotherEncoder : public AbstractEncoder | ||||
| { | ||||
| public: | ||||
| 	virtual ~BrotherEncoder() {} | ||||
| 
 | ||||
| public: | ||||
|     std::unique_ptr<Fluxmap> encode(int physicalTrack, int physicalSide, const SectorSet& allSectors); | ||||
| }; | ||||
| 
 | ||||
| extern FlagGroup brotherEncoderFlags; | ||||
| 
 | ||||
| #endif | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include "fluxmap.h" | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "record.h" | ||||
| #include "brother.h" | ||||
| #include "sector.h" | ||||
							
								
								
									
										167
									
								
								arch/brother/encoder.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								arch/brother/encoder.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | ||||
| #include "globals.h" | ||||
| #include "record.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "brother.h" | ||||
| #include "crc.h" | ||||
| #include "sectorset.h" | ||||
| #include "writer.h" | ||||
|  | ||||
| FlagGroup brotherEncoderFlags; | ||||
|  | ||||
| static DoubleFlag clockRateUs( | ||||
| 	{ "--clock-rate" }, | ||||
| 	"Encoded data clock rate (microseconds).", | ||||
| 	3.83); | ||||
|  | ||||
| static DoubleFlag postIndexGapMs( | ||||
| 	{ "--post-index-gap" }, | ||||
| 	"Post-index gap before first sector header (milliseconds).", | ||||
| 	1.0); | ||||
|  | ||||
| static DoubleFlag sectorSpacingMs( | ||||
| 	{ "--sector-spacing" }, | ||||
| 	"Time between successive sector headers (milliseconds).", | ||||
| 	16.2); | ||||
|  | ||||
| static DoubleFlag postHeaderSpacingMs( | ||||
| 	{ "--post-header-spacing" }, | ||||
| 	"Time between a sector's header and data records (milliseconds).", | ||||
| 	0.69); | ||||
|  | ||||
| static StringFlag sectorSkew( | ||||
| 	{ "--sector-skew" }, | ||||
| 	"Order in which to write sectors.", | ||||
| 	"05a3816b4927"); | ||||
|  | ||||
| static int encode_header_gcr(uint16_t word) | ||||
| { | ||||
| 	switch (word) | ||||
| 	{ | ||||
| 		#define GCR_ENTRY(gcr, data) \ | ||||
| 			case data: return gcr; | ||||
| 		#include "header_gcr.h" | ||||
| 		#undef GCR_ENTRY | ||||
| 	}                        | ||||
| 	return -1;              | ||||
| }; | ||||
|  | ||||
| static int encode_data_gcr(uint8_t data) | ||||
| { | ||||
| 	switch (data) | ||||
| 	{ | ||||
| 		#define GCR_ENTRY(gcr, data) \ | ||||
| 			case data: return gcr; | ||||
| 		#include "data_gcr.h" | ||||
| 		#undef GCR_ENTRY | ||||
| 	}                        | ||||
| 	return -1;              | ||||
| }; | ||||
|  | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint32_t data, int width) | ||||
| { | ||||
| 	cursor += width; | ||||
| 	for (int i=0; i<width; i++) | ||||
| 	{ | ||||
| 		unsigned pos = cursor - i - 1; | ||||
| 		if (pos < bits.size()) | ||||
| 			bits[pos] = data & 1; | ||||
| 		data >>= 1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void write_sector_header(std::vector<bool>& bits, unsigned& cursor, | ||||
| 		int track, int sector) | ||||
| { | ||||
| 	write_bits(bits, cursor, 0xffffffff, 31); | ||||
| 	write_bits(bits, cursor, BROTHER_SECTOR_RECORD, 32); | ||||
| 	write_bits(bits, cursor, encode_header_gcr(track), 16); | ||||
| 	write_bits(bits, cursor, encode_header_gcr(sector), 16); | ||||
| 	write_bits(bits, cursor, encode_header_gcr(0x2f), 16); | ||||
| } | ||||
|  | ||||
| static void write_sector_data(std::vector<bool>& bits, unsigned& cursor, const Bytes& data) | ||||
| { | ||||
| 	write_bits(bits, cursor, 0xffffffff, 32); | ||||
| 	write_bits(bits, cursor, BROTHER_DATA_RECORD, 32); | ||||
|  | ||||
| 	uint16_t fifo = 0; | ||||
| 	int width = 0; | ||||
|  | ||||
| 	if (data.size() != BROTHER_DATA_RECORD_PAYLOAD) | ||||
| 		Error() << "unsupported sector size"; | ||||
|  | ||||
| 	auto write_byte = [&](uint8_t byte) | ||||
| 	{ | ||||
| 		fifo |= (byte << (8 - width)); | ||||
| 		width += 8; | ||||
|  | ||||
| 		while (width >= 5) | ||||
| 		{ | ||||
| 			uint8_t quintet = fifo >> 11; | ||||
| 			fifo <<= 5; | ||||
| 			width -= 5; | ||||
|  | ||||
| 			write_bits(bits, cursor, encode_data_gcr(quintet), 8); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	for (uint8_t byte : data) | ||||
| 		write_byte(byte); | ||||
|  | ||||
| 	uint32_t realCrc = crcbrother(data); | ||||
| 	write_byte(realCrc>>16); | ||||
| 	write_byte(realCrc>>8); | ||||
| 	write_byte(realCrc); | ||||
| 	write_byte(0x58); /* magic */ | ||||
|     write_byte(0xd4); | ||||
|     while (width != 0) | ||||
|         write_byte(0); | ||||
| } | ||||
|  | ||||
| static int charToInt(char c) | ||||
| { | ||||
| 	if (isdigit(c)) | ||||
| 		return c - '0'; | ||||
| 	return 10 + tolower(c) - 'a'; | ||||
| } | ||||
|  | ||||
| std::unique_ptr<Fluxmap> BrotherEncoder::encode( | ||||
| 	int physicalTrack, int physicalSide, const SectorSet& allSectors) | ||||
| { | ||||
| 	if ((physicalTrack < 0) || (physicalTrack >= BROTHER_TRACKS_PER_DISK) | ||||
|         || (physicalSide != 0)) | ||||
| 		return std::unique_ptr<Fluxmap>(); | ||||
|  | ||||
| 	int bitsPerRevolution = 200000.0 / clockRateUs; | ||||
| 	const std::string& skew = sectorSkew.get(); | ||||
| 	std::vector<bool> bits(bitsPerRevolution); | ||||
| 	unsigned cursor = 0; | ||||
|  | ||||
| 	for (int sectorCount=0; sectorCount<BROTHER_SECTORS_PER_TRACK; sectorCount++) | ||||
| 	{ | ||||
| 		int sectorId = charToInt(skew.at(sectorCount)); | ||||
| 		double headerMs = postIndexGapMs + sectorCount*sectorSpacingMs; | ||||
| 		unsigned headerCursor = headerMs*1e3 / clockRateUs; | ||||
| 		double dataMs = headerMs + postHeaderSpacingMs; | ||||
| 		unsigned dataCursor = dataMs*1e3 / clockRateUs; | ||||
|  | ||||
| 		const auto& sectorData = allSectors.get(physicalTrack, 0, sectorId); | ||||
|  | ||||
| 		fillBitmapTo(bits, cursor, headerCursor, { true, false }); | ||||
| 		write_sector_header(bits, cursor, physicalTrack, sectorId); | ||||
| 		fillBitmapTo(bits, cursor, dataCursor, { true, false }); | ||||
| 		write_sector_data(bits, cursor, sectorData->data); | ||||
| 	} | ||||
|  | ||||
| 	if (cursor > bits.size()) | ||||
| 		Error() << "track data overrun"; | ||||
| 	fillBitmapTo(bits, cursor, bits.size(), { true, false }); | ||||
|  | ||||
| 	// The pre-index gap is not normally reported. | ||||
| 	// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl; | ||||
| 	 | ||||
| 	std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 	fluxmap->appendBits(bits, clockRateUs*1e3); | ||||
| 	return fluxmap; | ||||
| } | ||||
| @@ -153,6 +153,9 @@ void MacintoshDecoder::decodeSectorRecord() | ||||
|     uint8_t formatByte = decode_data_gcr(header[3]); | ||||
|     uint8_t wantedsum = decode_data_gcr(header[4]); | ||||
| 
 | ||||
|     if (encodedSector > 11) | ||||
|         return; | ||||
| 
 | ||||
|     _sector->logicalTrack = _track->physicalTrack; | ||||
|     _sector->logicalSide = decode_side(encodedSide); | ||||
|     _sector->logicalSector = encodedSector; | ||||
| @@ -37,7 +37,7 @@ AbstractDecoder::RecordType MxDecoder::advanceToNextRecord() | ||||
|         const FluxMatcher* matcher = nullptr; | ||||
|         _sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher); | ||||
|         readRawBits(32); /* skip the ID mark */ | ||||
|         readRawBits(32); /* skip the track number */ | ||||
|         _logicalTrack = decodeFmMfm(readRawBits(32)).reader().read_be16(); | ||||
|     } | ||||
|     else if (_currentSector == 10) | ||||
|     { | ||||
| @@ -67,7 +67,7 @@ void MxDecoder::decodeSectorRecord() | ||||
|         gotChecksum += br.read_le16(); | ||||
|     uint16_t wantChecksum = br.read_le16(); | ||||
| 
 | ||||
|     _sector->logicalTrack = _track->physicalTrack; | ||||
|     _sector->logicalTrack = _logicalTrack; | ||||
|     _sector->logicalSide = _track->physicalSide; | ||||
|     _sector->logicalSector = _currentSector; | ||||
|     _sector->data = bytes.slice(0, SECTOR_SIZE); | ||||
| @@ -15,6 +15,7 @@ public: | ||||
| private: | ||||
|     nanoseconds_t _clock; | ||||
|     int _currentSector; | ||||
|     int _logicalTrack; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										65
									
								
								doc/disk-mx.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								doc/disk-mx.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| Disk: DVK MX | ||||
| ============ | ||||
|  | ||||
| The DVK (in Russian, ДВК, Диалоговый вычислительный комплекс or Dialogue | ||||
| Computing Complex) was a late 1970s Soviet personal computer, a cut-down | ||||
| version of the professional SM EVM (СМ ЭВМ, abbreviation of Система Малых ЭВМ | ||||
| --- literally System of Mini Computers), which _itself_ was an unlicensed | ||||
| clone of the PDP-11. The MX board was an early floppy drive controller board | ||||
| for it. | ||||
|  | ||||
| <div style="text-align: center"> | ||||
| <a href="http://www.leningrad.su/museum/show_big.php?n=1006"><img src="dvk3m.jpg" style="max-width: 60%" alt="A Durango F85, held precariously"></a> | ||||
| </div> | ||||
|  | ||||
| The MX format is interesting in that it has to be read a track at a time. The | ||||
| format contains the usual ID prologue at the beginning of the track, then | ||||
| eleven data blocks and checksums, then the epilogue, then it stops. The | ||||
| actual encoding is normal FM. There were four different disk variants, in all | ||||
| combinations of single- and double-sided and 40- and 80-tracked; but every | ||||
| track contained eleven 256-byte sectors. | ||||
|  | ||||
| The format varies subtly depending on whether you're using the 'new' driver | ||||
| or the 'old' driver. FluxEngine should read both. | ||||
|  | ||||
| A track is: | ||||
|  | ||||
|   * 8 x 0x0000 words (FM encoded as 01010101...) | ||||
|   * 1 x 0x00F3 --- start of track | ||||
|   * 1 x 0xnnnn --- track number | ||||
|   * 11 of: | ||||
|     * 128 words (256 bytes) of data | ||||
|     * 16 bit checksum | ||||
|   * **if 'new' format:** | ||||
|     * 3 x 0x83nn --- `n = (track_number<<1) + side_number` | ||||
|   * **if 'old' format:** | ||||
|     * 3 x 0x8301 | ||||
|  | ||||
| The checksum is just the unsigned integer sum of all the words in the sector. | ||||
| Words are all stored little-endian. | ||||
|  | ||||
| Reading discs | ||||
| ------------- | ||||
|  | ||||
| ``` | ||||
| fluxengine read mx | ||||
| ``` | ||||
|  | ||||
| You should end up with an `mx.img` which will vary in length depending on the format. The default is double-sided 80-track. For the other formats, use: | ||||
|  | ||||
|   * single-sided 40-track: `-s :s=0:t=0-79x2` | ||||
|   * double-sided 40-track: `-s :s=0-1:t=0-79x2` | ||||
|   * single-sided 40-track: `-s :s=0:t=0-79` | ||||
|   * double-sided 40-track: `-s :s=0-1:t=0-79` | ||||
|  | ||||
|  | ||||
| Useful references | ||||
| ----------------- | ||||
|  | ||||
|   - [The Soviet Digital Electronics | ||||
|     Museum](http://www.leningrad.su/museum/main.php) (source of the image | ||||
|     above) | ||||
|  | ||||
|   - [a random post on the HxC2001 support | ||||
|     forum](http://torlus.com/floppy/forum/viewtopic.php?t=1384) with lots of | ||||
|     information on the format | ||||
							
								
								
									
										
											BIN
										
									
								
								doc/dvk3m.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/dvk3m.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 159 KiB | 
| @@ -1,92 +0,0 @@ | ||||
| #include "globals.h" | ||||
| #include "record.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "brother.h" | ||||
| #include "crc.h" | ||||
|  | ||||
| static int encode_header_gcr(uint16_t word) | ||||
| { | ||||
| 	switch (word) | ||||
| 	{ | ||||
| 		#define GCR_ENTRY(gcr, data) \ | ||||
| 			case data: return gcr; | ||||
| 		#include "header_gcr.h" | ||||
| 		#undef GCR_ENTRY | ||||
| 	}                        | ||||
| 	return -1;              | ||||
| }; | ||||
|  | ||||
| static int encode_data_gcr(uint8_t data) | ||||
| { | ||||
| 	switch (data) | ||||
| 	{ | ||||
| 		#define GCR_ENTRY(gcr, data) \ | ||||
| 			case data: return gcr; | ||||
| 		#include "data_gcr.h" | ||||
| 		#undef GCR_ENTRY | ||||
| 	}                        | ||||
| 	return -1;              | ||||
| }; | ||||
|  | ||||
| static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint32_t data, int width) | ||||
| { | ||||
| 	cursor += width; | ||||
| 	for (int i=0; i<width; i++) | ||||
| 	{ | ||||
| 		unsigned pos = cursor - i - 1; | ||||
| 		if (pos < bits.size()) | ||||
| 			bits[pos] = data & 1; | ||||
| 		data >>= 1; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor, | ||||
| 		int track, int sector) | ||||
| { | ||||
| 	write_bits(bits, cursor, 0xffffffff, 31); | ||||
| 	write_bits(bits, cursor, BROTHER_SECTOR_RECORD, 32); | ||||
| 	write_bits(bits, cursor, encode_header_gcr(track), 16); | ||||
| 	write_bits(bits, cursor, encode_header_gcr(sector), 16); | ||||
| 	write_bits(bits, cursor, encode_header_gcr(0x2f), 16); | ||||
| } | ||||
|  | ||||
| void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor, const Bytes& data) | ||||
| { | ||||
| 	write_bits(bits, cursor, 0xffffffff, 32); | ||||
| 	write_bits(bits, cursor, BROTHER_DATA_RECORD, 32); | ||||
|  | ||||
| 	uint16_t fifo = 0; | ||||
| 	int width = 0; | ||||
|  | ||||
| 	if (data.size() != BROTHER_DATA_RECORD_PAYLOAD) | ||||
| 		Error() << "unsupported sector size"; | ||||
|  | ||||
| 	auto write_byte = [&](uint8_t byte) | ||||
| 	{ | ||||
| 		fifo |= (byte << (8 - width)); | ||||
| 		width += 8; | ||||
|  | ||||
| 		while (width >= 5) | ||||
| 		{ | ||||
| 			uint8_t quintet = fifo >> 11; | ||||
| 			fifo <<= 5; | ||||
| 			width -= 5; | ||||
|  | ||||
| 			write_bits(bits, cursor, encode_data_gcr(quintet), 8); | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	for (uint8_t byte : data) | ||||
| 		write_byte(byte); | ||||
|  | ||||
| 	uint32_t realCrc = crcbrother(data); | ||||
| 	write_byte(realCrc>>16); | ||||
| 	write_byte(realCrc>>8); | ||||
| 	write_byte(realCrc); | ||||
| 	write_byte(0x58); /* magic */ | ||||
|     write_byte(0xd4); | ||||
|     while (width != 0) | ||||
|         write_byte(0); | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										18
									
								
								lib/encoders/encoders.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/encoders/encoders.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| #ifndef ENCODERS_H | ||||
| #define ENCODERS_H | ||||
|  | ||||
| class Fluxmap; | ||||
| class SectorSet; | ||||
|  | ||||
| class AbstractEncoder | ||||
| { | ||||
| public: | ||||
|     virtual ~AbstractEncoder() {} | ||||
|  | ||||
| public: | ||||
|     virtual std::unique_ptr<Fluxmap> encode( | ||||
|         int physicalTrack, int physicalSide, const SectorSet& allSectors) = 0; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @@ -21,6 +21,7 @@ public: | ||||
|  | ||||
| public: | ||||
|     nanoseconds_t duration() const { return _duration; } | ||||
|     unsigned ticks() const { return _ticks; } | ||||
|     size_t bytes() const { return _bytes.size(); } | ||||
|     const Bytes& rawBytes() const { return _bytes; } | ||||
|  | ||||
|   | ||||
| @@ -160,8 +160,9 @@ void readDiskCommand(AbstractDecoder& decoder, const std::string& outputFilename | ||||
| 					track->rawrecords.size(), | ||||
| 					track->sectors.size()); | ||||
| 				if (track->sectors.size() > 0) | ||||
| 					std::cout << fmt::format("{:.2f}us clock; ", | ||||
| 						track->sectors.begin()->clock / 1000.0); | ||||
| 					std::cout << fmt::format("{:.2f}us clock ({:.0f}kHz); ", | ||||
| 						track->sectors.begin()->clock / 1000.0, | ||||
|                         1000000.0 / track->sectors.begin()->clock); | ||||
|  | ||||
| 				for (auto& sector : track->sectors) | ||||
| 				{ | ||||
|   | ||||
| @@ -6,9 +6,14 @@ | ||||
| #include "protocol.h" | ||||
| #include "usb.h" | ||||
| #include "dataspec.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "fluxsource/fluxsource.h" | ||||
| #include "fluxsink/fluxsink.h" | ||||
| #include "fmt/format.h" | ||||
| #include "record.h" | ||||
| #include "image.h" | ||||
| #include "sector.h" | ||||
| #include "sectorset.h" | ||||
|  | ||||
| FlagGroup writerFlags { &hardwareFluxSourceFlags }; | ||||
|  | ||||
| @@ -60,10 +65,12 @@ void writeTracks( | ||||
|         { | ||||
|             if (!outdb) | ||||
|             { | ||||
|                 std::cout << "erasing" << std::endl; | ||||
|                 std::cout << "erasing\n"; | ||||
|                 usbSeek(location.track); | ||||
|                 usbErase(location.side); | ||||
|             } | ||||
|             else | ||||
|                 std::cout << "skipping\n"; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| @@ -96,3 +103,16 @@ void fillBitmapTo(std::vector<bool>& bitmap, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void writeDiskCommand( | ||||
|     AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename) | ||||
| { | ||||
|     SectorSet allSectors; | ||||
|  | ||||
| 	readSectorsFromFile(allSectors, geometry, inputFilename); | ||||
| 	writeTracks( | ||||
| 		[&](int track, int side) -> std::unique_ptr<Fluxmap> | ||||
| 		{ | ||||
| 			return encoder.encode(track, side, allSectors); | ||||
| 		} | ||||
| 	); | ||||
| } | ||||
|   | ||||
| @@ -6,6 +6,8 @@ | ||||
| extern FlagGroup writerFlags; | ||||
|  | ||||
| class Fluxmap; | ||||
| class AbstractEncoder; | ||||
| class Geometry; | ||||
|  | ||||
| extern void setWriterDefaultDest(const std::string& dest); | ||||
|  | ||||
| @@ -15,5 +17,7 @@ extern void fillBitmapTo(std::vector<bool>& bitmap, | ||||
| 		unsigned& cursor, unsigned terminateAt, | ||||
| 		const std::vector<bool>& pattern); | ||||
| 	 | ||||
| extern void writeDiskCommand( | ||||
|     AbstractEncoder& encoder, const Geometry& geometry, const std::string& inputFilename); | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										76
									
								
								mkninja.sh
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								mkninja.sh
									
									
									
									
									
								
							| @@ -89,6 +89,33 @@ buildprogram() { | ||||
|     echo build $prog$EXTENSION : strip $prog-debug$EXTENSION | ||||
| } | ||||
|  | ||||
| buildsimpleprogram() { | ||||
| 	local prog | ||||
| 	prog=$1 | ||||
| 	shift | ||||
|  | ||||
|     local flags | ||||
|     flags= | ||||
|     while true; do | ||||
|         case $1 in | ||||
|             -*) | ||||
|                 flags="$flags $1" | ||||
|                 shift | ||||
|                 ;; | ||||
|  | ||||
|             *) | ||||
|                 break | ||||
|         esac | ||||
|     done | ||||
|  | ||||
| 	local src | ||||
| 	src=$1 | ||||
| 	shift | ||||
|  | ||||
| 	buildlibrary lib$prog.a $flags $src | ||||
| 	buildprogram $prog lib$prog.a "$@" | ||||
| } | ||||
|  | ||||
| runtest() { | ||||
|     local prog | ||||
|     prog=$1 | ||||
| @@ -110,22 +137,27 @@ buildlibrary libfmt.a \ | ||||
|     dep/fmt/posix.cc \ | ||||
|  | ||||
| buildlibrary libbackend.a \ | ||||
|     lib/aeslanier/decoder.cc \ | ||||
|     lib/amiga/decoder.cc \ | ||||
|     lib/apple2/decoder.cc \ | ||||
|     lib/brother/decoder.cc \ | ||||
|     lib/brother/encoder.cc \ | ||||
|     arch/aeslanier/decoder.cc \ | ||||
|     arch/amiga/decoder.cc \ | ||||
|     arch/apple2/decoder.cc \ | ||||
|     arch/brother/decoder.cc \ | ||||
|     arch/brother/encoder.cc \ | ||||
|     arch/c64/decoder.cc \ | ||||
|     arch/f85/decoder.cc \ | ||||
|     arch/fb100/decoder.cc \ | ||||
|     arch/ibm/decoder.cc \ | ||||
|     arch/macintosh/decoder.cc \ | ||||
|     arch/mx/decoder.cc \ | ||||
|     arch/victor9k/decoder.cc \ | ||||
|     arch/zilogmcz/decoder.cc \ | ||||
|     lib/bytes.cc \ | ||||
|     lib/c64/decoder.cc \ | ||||
|     lib/common/crunch.c \ | ||||
|     lib/crc.cc \ | ||||
|     lib/dataspec.cc \ | ||||
|     lib/decoders/decoders.cc \ | ||||
|     lib/decoders/fluxmapreader.cc \ | ||||
|     lib/decoders/fmmfm.cc \ | ||||
|     lib/encoder.cc \ | ||||
|     lib/f85/decoder.cc \ | ||||
|     lib/fb100/decoder.cc \ | ||||
|     lib/encoders/encoders.cc \ | ||||
|     lib/flags.cc \ | ||||
|     lib/fluxmap.cc \ | ||||
|     lib/fluxsink/fluxsink.cc \ | ||||
| @@ -138,21 +170,19 @@ buildlibrary libbackend.a \ | ||||
|     lib/fluxsource/streamfluxsource.cc \ | ||||
|     lib/globals.cc \ | ||||
|     lib/hexdump.cc \ | ||||
|     lib/ibm/decoder.cc \ | ||||
|     lib/image.cc \ | ||||
|     lib/macintosh/decoder.cc \ | ||||
|     lib/mx/decoder.cc \ | ||||
|     lib/reader.cc \ | ||||
|     lib/sector.cc \ | ||||
|     lib/sectorset.cc \ | ||||
|     lib/sql.cc \ | ||||
|     lib/usb.cc \ | ||||
|     lib/victor9k/decoder.cc \ | ||||
|     lib/writer.cc \ | ||||
|     lib/zilogmcz/decoder.cc \ | ||||
|  | ||||
| buildlibrary libfrontend.a \ | ||||
|     src/fe-cwftoflux.cc \ | ||||
|     src/fe-erase.cc \ | ||||
|     src/fe-fluxtoau.cc \ | ||||
|     src/fe-fluxtovcd.cc \ | ||||
|     src/fe-inspect.cc \ | ||||
|     src/fe-readadfs.cc \ | ||||
|     src/fe-readaeslanier.cc \ | ||||
| @@ -183,24 +213,14 @@ buildprogram fluxengine \ | ||||
|     libbackend.a \ | ||||
|     libfmt.a \ | ||||
|  | ||||
| buildlibrary libbrother120tool.a \ | ||||
|     -Idep/emu \ | ||||
|     tools/brother120tool.cc \ | ||||
|  | ||||
| buildlibrary libemu.a \ | ||||
|     dep/emu/fnmatch.c | ||||
|  | ||||
| buildprogram brother120tool \ | ||||
|     libbrother120tool.a \ | ||||
|     libemu.a \ | ||||
|     libfmt.a \ | ||||
|  | ||||
| buildlibrary libcwftoflux.a \ | ||||
|     tools/cwftoflux.cc \ | ||||
|  | ||||
| buildprogram cwftoflux \ | ||||
|     libcwftoflux.a \ | ||||
| buildsimpleprogram brother120tool \ | ||||
| 	-Idep/emu \ | ||||
|     tools/brother120tool.cc \ | ||||
|     libbackend.a \ | ||||
|     libemu.a \ | ||||
|     libfmt.a \ | ||||
|  | ||||
| runtest dataspec-test       tests/dataspec.cc | ||||
|   | ||||
| @@ -37,7 +37,7 @@ static double clockRate; | ||||
| 
 | ||||
| static void syntax() | ||||
| { | ||||
|     std::cout << "Syntax: cwftoflux <cwffile> <fluxfile>\n"; | ||||
|     std::cout << "Syntax: fluxengine convert cwftoflux <cwffile> <fluxfile>\n"; | ||||
|     exit(0); | ||||
| } | ||||
| 
 | ||||
| @@ -116,7 +116,7 @@ static void read_track() | ||||
|     sqlWriteFlux(outputDb, track_number, trackheader.side, fluxmap); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, const char* argv[]) | ||||
| int mainConvertCwfToFlux(int argc, const char* argv[]) | ||||
| { | ||||
|     if (argc != 3) | ||||
|         syntax(); | ||||
							
								
								
									
										100
									
								
								src/fe-fluxtoau.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/fe-fluxtoau.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| #include "globals.h" | ||||
| #include "flags.h" | ||||
| #include "fluxmap.h" | ||||
| #include "sql.h" | ||||
| #include "bytes.h" | ||||
| #include "protocol.h" | ||||
| #include "dataspec.h" | ||||
| #include "fluxsource/fluxsource.h" | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "fmt/format.h" | ||||
| #include <fstream> | ||||
|  | ||||
| static FlagGroup flags { &hardwareFluxSourceFlags }; | ||||
|  | ||||
| static DataSpecFlag source( | ||||
|     { "--source", "-s" }, | ||||
|     "source for data", | ||||
|     ":d=0:t=0:s=0"); | ||||
|  | ||||
| static StringFlag output( | ||||
|     { "--output", "-o" }, | ||||
|     "output AU file to write", | ||||
|     "output.au"); | ||||
|  | ||||
| static SettableFlag highDensityFlag( | ||||
|     { "--high-density", "--hd" }, | ||||
|     "set the drive to high density mode"); | ||||
|  | ||||
| static SettableFlag withIndex( | ||||
|     { "--with-index" }, | ||||
|     "place index markers in the right hand channel"); | ||||
|  | ||||
| int mainConvertFluxToAu(int argc, const char* argv[]) | ||||
| { | ||||
|     flags.parseFlags(argc, argv); | ||||
|  | ||||
|     const auto& locations = source.get().locations; | ||||
|     if (locations.size() != 1) | ||||
|         Error() << "the source dataspec must contain exactly one track (two sides count as two tracks)"; | ||||
|     const auto& location = *(locations.begin()); | ||||
|  | ||||
|     std::cerr << "Reading source flux...\n"; | ||||
|     setHardwareFluxSourceDensity(highDensityFlag); | ||||
|     std::shared_ptr<FluxSource> fluxsource = FluxSource::create(source); | ||||
|     const auto& fluxmap = fluxsource->readFlux(location.track, location.side); | ||||
|     unsigned totalTicks = fluxmap->ticks() + 2; | ||||
|     unsigned channels = withIndex ? 2 : 1; | ||||
|  | ||||
|     std::cerr << "Writing output file...\n"; | ||||
|     std::ofstream of(output, std::ios::out | std::ios::binary); | ||||
|     if (!of.is_open()) | ||||
|         Error() << "cannot open output file"; | ||||
|  | ||||
|     /* Write header */ | ||||
|  | ||||
|     { | ||||
|         Bytes header; | ||||
|         header.resize(24); | ||||
|         ByteWriter bw(header); | ||||
|  | ||||
|         bw.write_be32(0x2e736e64); | ||||
|         bw.write_be32(24); | ||||
|         bw.write_be32(totalTicks * channels); | ||||
|         bw.write_be32(2); /* 8-bit PCM */ | ||||
|         bw.write_be32(TICK_FREQUENCY); | ||||
|         bw.write_be32(channels); /* channels */ | ||||
|  | ||||
|         of.write((const char*) header.cbegin(), header.size()); | ||||
|     } | ||||
|  | ||||
|     /* Write data */ | ||||
|  | ||||
|     { | ||||
|         Bytes data; | ||||
|         data.resize(totalTicks * channels); | ||||
|         memset(data.begin(), 0x80, data.size()); | ||||
|  | ||||
|         FluxmapReader fmr(*fluxmap); | ||||
|         unsigned timestamp = 0; | ||||
|         while (!fmr.eof()) | ||||
|         { | ||||
|             unsigned ticks; | ||||
|             int op = fmr.readOpcode(ticks); | ||||
|             if (op == -1) | ||||
|                 break; | ||||
|             timestamp += ticks; | ||||
|  | ||||
|             if (op == F_OP_PULSE) | ||||
|                 data[timestamp*channels + 0] = 0x7f; | ||||
|             if (withIndex && (op == F_OP_INDEX)) | ||||
|                 data[timestamp*channels + 1] = 0x7f; | ||||
|         } | ||||
|  | ||||
|         of.write((const char*) data.cbegin(), data.size()); | ||||
|     } | ||||
|  | ||||
|     std::cerr << "Done. Warning: do not play this file, or you will break your speakers" | ||||
| 	         " and/or ears!\n"; | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										83
									
								
								src/fe-fluxtovcd.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/fe-fluxtovcd.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| #include "globals.h" | ||||
| #include "flags.h" | ||||
| #include "fluxmap.h" | ||||
| #include "sql.h" | ||||
| #include "bytes.h" | ||||
| #include "protocol.h" | ||||
| #include "dataspec.h" | ||||
| #include "fluxsource/fluxsource.h" | ||||
| #include "decoders/fluxmapreader.h" | ||||
| #include "fmt/format.h" | ||||
| #include <fstream> | ||||
|  | ||||
| static FlagGroup flags { &hardwareFluxSourceFlags }; | ||||
|  | ||||
| static DataSpecFlag source( | ||||
|     { "--source", "-s" }, | ||||
|     "source for data", | ||||
|     ":d=0:t=0:s=0"); | ||||
|  | ||||
| static StringFlag output( | ||||
|     { "--output", "-o" }, | ||||
|     "output VCD file to write", | ||||
|     "output.vcd"); | ||||
|  | ||||
| static SettableFlag highDensityFlag( | ||||
|     { "--high-density", "--hd" }, | ||||
|     "set the drive to high density mode"); | ||||
|  | ||||
| int mainConvertFluxToVcd(int argc, const char* argv[]) | ||||
| { | ||||
|     flags.parseFlags(argc, argv); | ||||
|  | ||||
|     const auto& locations = source.get().locations; | ||||
|     if (locations.size() != 1) | ||||
|         Error() << "the source dataspec must contain exactly one track (two sides count as two tracks)"; | ||||
|     const auto& location = *(locations.begin()); | ||||
|  | ||||
|     std::cerr << "Reading source flux...\n"; | ||||
|     setHardwareFluxSourceDensity(highDensityFlag); | ||||
|     std::shared_ptr<FluxSource> fluxsource = FluxSource::create(source); | ||||
|     const auto& fluxmap = fluxsource->readFlux(location.track, location.side); | ||||
|  | ||||
|     std::cerr << "Writing destination VCD...\n"; | ||||
|     std::ofstream of(output, std::ios::out); | ||||
|     if (!of.is_open()) | ||||
|         Error() << "cannot open output file"; | ||||
|  | ||||
|     of << "$timescale 1ns $end\n" | ||||
|        << "$var wire 1 i index $end\n" | ||||
|        << "$var wire 1 p pulse $end\n" | ||||
|        << "$upscope $end\n" | ||||
|        << "$enddefinitions $end\n" | ||||
|        << "$dumpvars 0i 0p $end\n"; | ||||
|  | ||||
|     FluxmapReader fmr(*fluxmap); | ||||
|     unsigned timestamp = 0; | ||||
|     unsigned lasttimestamp = 0; | ||||
|     while (!fmr.eof()) | ||||
|     { | ||||
|         unsigned ticks; | ||||
|         int op = fmr.readOpcode(ticks); | ||||
|         if (op == -1) | ||||
|             break; | ||||
|  | ||||
|         unsigned newtimestamp = timestamp + ticks; | ||||
|         if (newtimestamp != lasttimestamp) | ||||
|         { | ||||
|             of << fmt::format("\n#{} 0i 0p\n", (uint64_t)((lasttimestamp+1) * NS_PER_TICK)); | ||||
|             timestamp = newtimestamp; | ||||
|             of << fmt::format("#{} ", (uint64_t)(timestamp * NS_PER_TICK)); | ||||
|         } | ||||
|  | ||||
|         if (op == F_OP_PULSE) | ||||
|             of << "1p "; | ||||
|         if (op == F_OP_INDEX) | ||||
|             of << "1i "; | ||||
|  | ||||
|         lasttimestamp = timestamp; | ||||
|     } | ||||
|     of << "\n"; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @@ -12,7 +12,7 @@ | ||||
| #include "track.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| static FlagGroup flags; | ||||
| static FlagGroup flags { &readerFlags }; | ||||
|  | ||||
| static SettableFlag dumpFluxFlag( | ||||
| 	{ "--dump-flux", "-F" }, | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
| #include "reader.h" | ||||
| #include "fluxmap.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "brother/brother.h" | ||||
| #include "sector.h" | ||||
| #include "sectorset.h" | ||||
|   | ||||
| @@ -1,108 +1,28 @@ | ||||
| #include "globals.h" | ||||
| #include "flags.h" | ||||
| #include "fluxmap.h" | ||||
| #include "sector.h" | ||||
| #include "sectorset.h" | ||||
| #include "decoders/decoders.h" | ||||
| #include "encoders/encoders.h" | ||||
| #include "brother/brother.h" | ||||
| #include "image.h" | ||||
| #include "writer.h" | ||||
| #include "fmt/format.h" | ||||
| #include "image.h" | ||||
| #include <fstream> | ||||
| #include <ctype.h> | ||||
|  | ||||
| static FlagGroup flags { &writerFlags }; | ||||
| static FlagGroup flags { &writerFlags, &brotherEncoderFlags }; | ||||
|  | ||||
| static StringFlag inputFilename( | ||||
|     { "--input", "-i" }, | ||||
|     "The input image file to read from.", | ||||
|     "brother.img"); | ||||
|  | ||||
| static DoubleFlag clockRateUs( | ||||
| 	{ "--clock-rate" }, | ||||
| 	"Encoded data clock rate (microseconds).", | ||||
| 	3.83); | ||||
|  | ||||
| static DoubleFlag postIndexGapMs( | ||||
| 	{ "--post-index-gap" }, | ||||
| 	"Post-index gap before first sector header (milliseconds).", | ||||
| 	1.0); | ||||
|  | ||||
| static DoubleFlag sectorSpacingMs( | ||||
| 	{ "--sector-spacing" }, | ||||
| 	"Time between successive sector headers (milliseconds).", | ||||
| 	16.2); | ||||
|  | ||||
| static DoubleFlag postHeaderSpacingMs( | ||||
| 	{ "--post-header-spacing" }, | ||||
| 	"Time between a sector's header and data records (milliseconds).", | ||||
| 	0.69); | ||||
|  | ||||
|  | ||||
| static StringFlag sectorSkew( | ||||
| 	{ "--sector-skew" }, | ||||
| 	"Order in which to write sectors.", | ||||
| 	"05a3816b4927"); | ||||
|  | ||||
| static int charToInt(char c) | ||||
| { | ||||
| 	if (isdigit(c)) | ||||
| 		return c - '0'; | ||||
| 	return 10 + tolower(c) - 'a'; | ||||
| } | ||||
|  | ||||
| int mainWriteBrother(int argc, const char* argv[]) | ||||
| { | ||||
| 	setWriterDefaultDest(":d=0:t=0-77:s=0"); | ||||
|     flags.parseFlags(argc, argv); | ||||
|  | ||||
| 	SectorSet allSectors; | ||||
| 	BrotherEncoder encoder; | ||||
| 	Geometry geometry = {78, 1, 12, 256}; | ||||
| 	readSectorsFromFile(allSectors, geometry, inputFilename); | ||||
|  | ||||
| 	int bitsPerRevolution = 200000.0 / clockRateUs; | ||||
| 	std::cerr << bitsPerRevolution << " bits per 200ms revolution" << std::endl | ||||
| 	          << fmt::format("post-index gap: {:.3f}ms\n", (double)postIndexGapMs); | ||||
|  | ||||
| 	const std::string& skew = sectorSkew; | ||||
|  | ||||
| 	writeTracks( | ||||
| 		[&](int track, int side) -> std::unique_ptr<Fluxmap> | ||||
| 		{ | ||||
| 			if ((track < 0) || (track > 77) || (side != 0)) | ||||
| 				return std::unique_ptr<Fluxmap>(); | ||||
|  | ||||
| 			std::vector<bool> bits(bitsPerRevolution); | ||||
| 			unsigned cursor = 0; | ||||
|  | ||||
| 			for (int sectorCount=0; sectorCount<geometry.sectors; sectorCount++) | ||||
| 			{ | ||||
| 				int sectorId = charToInt(skew.at(sectorCount)); | ||||
| 				double headerMs = postIndexGapMs + sectorCount*sectorSpacingMs; | ||||
| 				unsigned headerCursor = headerMs*1e3 / clockRateUs; | ||||
| 				double dataMs = headerMs + postHeaderSpacingMs; | ||||
| 				unsigned dataCursor = dataMs*1e3 / clockRateUs; | ||||
|  | ||||
| 				auto& sectorData = allSectors.get(track, 0, sectorId); | ||||
|  | ||||
| 				fillBitmapTo(bits, cursor, headerCursor, { true, false }); | ||||
| 				writeBrotherSectorHeader(bits, cursor, track, sectorId); | ||||
| 				fillBitmapTo(bits, cursor, dataCursor, { true, false }); | ||||
| 				writeBrotherSectorData(bits, cursor, sectorData->data); | ||||
| 			} | ||||
|  | ||||
| 			if (cursor > bits.size()) | ||||
| 				Error() << "track data overrun"; | ||||
|             fillBitmapTo(bits, cursor, bits.size(), { true, false }); | ||||
|  | ||||
| 			// The pre-index gap is not normally reported. | ||||
| 			// std::cerr << "pre-index gap " << 200.0 - (double)cursor*clockRateUs/1e3 << std::endl; | ||||
| 			 | ||||
| 			std::unique_ptr<Fluxmap> fluxmap(new Fluxmap); | ||||
| 			fluxmap->appendBits(bits, clockRateUs*1e3); | ||||
| 			return fluxmap; | ||||
| 		} | ||||
| 	); | ||||
| 	writeDiskCommand(encoder, geometry, inputFilename); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|   | ||||
| @@ -3,6 +3,9 @@ | ||||
| typedef int command_cb(int agrc, const char* argv[]); | ||||
|  | ||||
| extern command_cb mainErase; | ||||
| extern command_cb mainConvertCwfToFlux; | ||||
| extern command_cb mainConvertFluxToAu; | ||||
| extern command_cb mainConvertFluxToVcd; | ||||
| extern command_cb mainInspect; | ||||
| extern command_cb mainReadADFS; | ||||
| extern command_cb mainReadAESLanier; | ||||
| @@ -15,9 +18,9 @@ extern command_cb mainReadDFS; | ||||
| extern command_cb mainReadF85; | ||||
| extern command_cb mainReadFB100; | ||||
| extern command_cb mainReadIBM; | ||||
| extern command_cb mainReadVictor9K; | ||||
| extern command_cb mainReadMac; | ||||
| extern command_cb mainReadMx; | ||||
| extern command_cb mainReadVictor9K; | ||||
| extern command_cb mainReadZilogMCZ; | ||||
| extern command_cb mainRpm; | ||||
| extern command_cb mainSeek; | ||||
| @@ -36,16 +39,18 @@ struct Command | ||||
|  | ||||
| static command_cb mainRead; | ||||
| static command_cb mainWrite; | ||||
| static command_cb mainConvert; | ||||
|  | ||||
| static std::vector<Command> commands = | ||||
| { | ||||
|     { "erase",             mainErase,             "Permanently but rapidly erases some or all of a disk." }, | ||||
|     { "convert",           mainConvert,           "Converts various types of data file.", }, | ||||
|     { "inspect",           mainInspect,           "Low-level analysis and inspection of a disk." }, | ||||
|     { "read",              mainRead,              "Reads a disk, producing a sector image.", }, | ||||
|     { "rpm",               mainRpm,               "Measures the disk rotational speed.", }, | ||||
|     { "seek",              mainSeek,              "Moves the disk head.", }, | ||||
|     { "testbulktransport", mainTestBulkTransport, "Measures your USB bandwidth.", }, | ||||
|     { "upgradefluxfile",   mainUpgradeFluxFile,   "Upgrades a flux file from a previous version of this software.", }, | ||||
|     { "read",              mainRead,              "Reads a disk, producing a sector image.", }, | ||||
|     { "write",             mainWrite,             "Writes a sector image to a disk.", }, | ||||
|     { "writeflux",         mainWriteFlux,         "Writes a raw flux file. Warning: you can't use this to copy disks.", }, | ||||
|     { "writetestpattern",  mainWriteTestPattern,  "Writes a machine-generated test pattern to a disk.", }, | ||||
| @@ -75,10 +80,17 @@ static std::vector<Command> writeables = | ||||
|     { "brother",       mainWriteBrother,  "Writes 120kB and 240kB Brother word processor disks.", }, | ||||
| }; | ||||
|  | ||||
| static void readWriteHelp(std::vector<Command>& subcommands, const std::string& command) | ||||
| static std::vector<Command> convertables = | ||||
| { | ||||
|     { "cwftoflux",     mainConvertCwfToFlux, "Converts CatWeasel stream files to flux.", }, | ||||
|     { "fluxtoau",      mainConvertFluxToAu,  "Converts (one track of a) flux file to an .au audio file.", }, | ||||
|     { "fluxtovcd",     mainConvertFluxToVcd, "Converts (one track of a) flux file to a VCD file.", }, | ||||
| }; | ||||
|  | ||||
| static void extendedHelp(std::vector<Command>& subcommands, const std::string& command) | ||||
| { | ||||
|     std::cout << "fluxengine: syntax: fluxengine " << command << " <format> [<flags>...]\n" | ||||
|                  "These formats are supported:\n"; | ||||
|                  "These subcommands are supported:\n"; | ||||
|  | ||||
|     for (Command& c : subcommands) | ||||
|         std::cout << "  " << c.name << ": " << c.help << "\n"; | ||||
| @@ -86,15 +98,15 @@ static void readWriteHelp(std::vector<Command>& subcommands, const std::string& | ||||
|     exit(0); | ||||
| } | ||||
|  | ||||
| static int mainReadWrite(std::vector<Command>& subcommands, const std::string& command, | ||||
| static int mainExtended(std::vector<Command>& subcommands, const std::string& command, | ||||
|          int argc, const char* argv[]) | ||||
| { | ||||
|     if (argc == 1) | ||||
|         readWriteHelp(subcommands, command); | ||||
|         extendedHelp(subcommands, command); | ||||
|  | ||||
|     std::string format = argv[1]; | ||||
|     if (format == "--help") | ||||
|         readWriteHelp(subcommands, command); | ||||
|         extendedHelp(subcommands, command); | ||||
|  | ||||
|     for (Command& c : subcommands) | ||||
|     { | ||||
| @@ -107,10 +119,13 @@ static int mainReadWrite(std::vector<Command>& subcommands, const std::string& c | ||||
| } | ||||
|  | ||||
| static int mainRead(int argc, const char* argv[]) | ||||
| { return mainReadWrite(readables, "read", argc, argv); } | ||||
| { return mainExtended(readables, "read", argc, argv); } | ||||
|  | ||||
| static int mainWrite(int argc, const char* argv[]) | ||||
| { return mainReadWrite(writeables, "write", argc, argv); } | ||||
| { return mainExtended(writeables, "write", argc, argv); } | ||||
|  | ||||
| static int mainConvert(int argc, const char* argv[]) | ||||
| { return mainExtended(convertables, "convert", argc, argv); } | ||||
|  | ||||
| static void help() | ||||
| { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user