mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
Compare commits
27 Commits
FluxEngine
...
FluxEngine
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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))
|
||||
;
|
||||
|
||||
@@ -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.
|
||||
|
||||
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 |
@@ -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"
|
||||
|
||||
@@ -1,8 +1,38 @@
|
||||
#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)
|
||||
{
|
||||
@@ -40,7 +70,7 @@ static void write_bits(std::vector<bool>& bits, unsigned& cursor, uint32_t data,
|
||||
}
|
||||
}
|
||||
|
||||
void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
|
||||
static void write_sector_header(std::vector<bool>& bits, unsigned& cursor,
|
||||
int track, int sector)
|
||||
{
|
||||
write_bits(bits, cursor, 0xffffffff, 31);
|
||||
@@ -50,7 +80,7 @@ void writeBrotherSectorHeader(std::vector<bool>& bits, unsigned& cursor,
|
||||
write_bits(bits, cursor, encode_header_gcr(0x2f), 16);
|
||||
}
|
||||
|
||||
void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor, const Bytes& data)
|
||||
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);
|
||||
@@ -89,4 +119,49 @@ void writeBrotherSectorData(std::vector<bool>& bits, unsigned& cursor, const Byt
|
||||
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;
|
||||
}
|
||||
|
||||
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; }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
50
mkninja.sh
50
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
|
||||
@@ -123,7 +150,7 @@ buildlibrary libbackend.a \
|
||||
lib/decoders/decoders.cc \
|
||||
lib/decoders/fluxmapreader.cc \
|
||||
lib/decoders/fmmfm.cc \
|
||||
lib/encoder.cc \
|
||||
lib/encoders/encoders.cc \
|
||||
lib/f85/decoder.cc \
|
||||
lib/fb100/decoder.cc \
|
||||
lib/flags.cc \
|
||||
@@ -152,7 +179,10 @@ buildlibrary libbackend.a \
|
||||
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