mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-24 11:11:02 -07:00
Compare commits
4 Commits
FluxEngine
...
qd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8fd984c5c | ||
|
|
14ed696993 | ||
|
|
047521475f | ||
|
|
d906d92016 |
@@ -1058,27 +1058,27 @@
|
||||
<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="DSKCHG" persistent="">
|
||||
<Hidden v="False" />
|
||||
<Hidden v="True" />
|
||||
</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="DSKCHG_aliases.h" persistent="Generated_Source\PSoC5\DSKCHG_aliases.h">
|
||||
<Hidden v="False" />
|
||||
<Hidden v="True" />
|
||||
</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="DSKCHG.c" persistent="Generated_Source\PSoC5\DSKCHG.c">
|
||||
<Hidden v="False" />
|
||||
<Hidden v="True" />
|
||||
</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="DSKCHG.h" persistent="Generated_Source\PSoC5\DSKCHG.h">
|
||||
<Hidden v="False" />
|
||||
<Hidden v="True" />
|
||||
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
|
||||
<build_action v="HEADER;;;;" />
|
||||
<PropertyDeltas />
|
||||
@@ -3282,6 +3282,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="READY" 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="READY_aliases.h" persistent="Generated_Source\PSoC5\READY_aliases.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="READY.c" persistent="Generated_Source\PSoC5\READY.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="READY.h" persistent="Generated_Source\PSoC5\READY.h">
|
||||
<Hidden v="False" />
|
||||
</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>
|
||||
<build_action v="HEADER;;;;" />
|
||||
<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>
|
||||
|
||||
Binary file not shown.
@@ -12,7 +12,7 @@
|
||||
#define STEP_SETTLING_TIME 50 /* ms */
|
||||
|
||||
#define DISKSTATUS_WPT 1
|
||||
#define DISKSTATUS_DSKCHG 2
|
||||
#define DISKSTATUS_READY 2 /* Only used on QuickDisk drives */
|
||||
|
||||
#define STEP_TOWARDS0 1
|
||||
#define STEP_AWAYFROM0 0
|
||||
@@ -37,6 +37,7 @@ static uint8_t dma_channel;
|
||||
static volatile int dma_writing_to_td = 0;
|
||||
static volatile int dma_reading_from_td = 0;
|
||||
static volatile bool dma_underrun = false;
|
||||
static crunch_state_t cs = {};
|
||||
|
||||
#define DECLARE_REPLY_FRAME(STRUCT, TYPE) \
|
||||
STRUCT r = {.f = { .type = TYPE, .size = sizeof(STRUCT) }}
|
||||
@@ -269,13 +270,8 @@ static void init_capture_dma(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_read(struct read_frame* f)
|
||||
static void init_capture(void)
|
||||
{
|
||||
SIDE_REG_Write(f->side);
|
||||
seek_to(current_track);
|
||||
|
||||
/* Do slow setup *before* we go into the real-time bit. */
|
||||
|
||||
SAMPLER_CONTROL_Write(1); /* reset */
|
||||
|
||||
{
|
||||
@@ -288,38 +284,103 @@ static void cmd_read(struct read_frame* f)
|
||||
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
init_capture_dma();
|
||||
}
|
||||
|
||||
/* Wait for the beginning of a rotation. */
|
||||
|
||||
print("wait");
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
index_irq = false;
|
||||
|
||||
crunch_state_t cs = {};
|
||||
static void start_capture(void)
|
||||
{
|
||||
memset(&cs, 0, sizeof(crunch_state_t));
|
||||
cs.outputptr = usb_buffer;
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
|
||||
dma_writing_to_td = 0;
|
||||
dma_reading_from_td = -1;
|
||||
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);
|
||||
|
||||
/* Wait for the first DMA transfer to complete, after which we can start the
|
||||
* USB transfer. */
|
||||
/* Wait for the first DMA transfer to complete, after which we can start
|
||||
* the USB transfer. */
|
||||
|
||||
while ((dma_writing_to_td == 0) && !index_irq)
|
||||
while (dma_writing_to_td == 0)
|
||||
;
|
||||
dma_reading_from_td = 0;
|
||||
}
|
||||
|
||||
/* returns true if capture is aborted */
|
||||
static bool do_capture_chunk(void)
|
||||
{
|
||||
/* Wait for the next block to be read. */
|
||||
while (dma_reading_from_td == dma_writing_to_td)
|
||||
{
|
||||
/* On an underrun, give up immediately. */
|
||||
if (dma_underrun)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t dma_buffer_usage = 0;
|
||||
while (dma_buffer_usage < BUFFER_SIZE)
|
||||
{
|
||||
cs.inputptr = dma_buffer[dma_reading_from_td] + dma_buffer_usage;
|
||||
cs.inputlen = BUFFER_SIZE - dma_buffer_usage;
|
||||
crunch(&cs);
|
||||
dma_buffer_usage += BUFFER_SIZE - cs.inputlen;
|
||||
if (cs.outputlen == 0)
|
||||
{
|
||||
while (USBFS_GetEPState(FLUXENGINE_DATA_IN_EP_NUM) != USBFS_IN_BUFFER_EMPTY)
|
||||
{
|
||||
if (dma_underrun)
|
||||
return true;
|
||||
}
|
||||
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE);
|
||||
cs.outputptr = usb_buffer;
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void stop_capture(void)
|
||||
{
|
||||
CAPTURE_CONTROL_Write(0);
|
||||
CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN);
|
||||
while (CyDmaChGetRequest(dma_channel))
|
||||
;
|
||||
|
||||
donecrunch(&cs);
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
if (cs.outputlen != BUFFER_SIZE)
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen);
|
||||
if ((cs.outputlen == BUFFER_SIZE) || (cs.outputlen == 0))
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0);
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
deinit_dma();
|
||||
}
|
||||
|
||||
static void cmd_read(struct read_frame* f)
|
||||
{
|
||||
SIDE_REG_Write(f->side);
|
||||
seek_to(current_track);
|
||||
|
||||
/* Do slow setup *before* we go into the real-time bit. */
|
||||
|
||||
init_capture();
|
||||
|
||||
/* Wait for the beginning of a rotation. */
|
||||
|
||||
index_irq = false;
|
||||
while (!index_irq)
|
||||
;
|
||||
index_irq = false;
|
||||
|
||||
/* Start transferring. */
|
||||
|
||||
start_capture();
|
||||
int revolutions = f->revolutions;
|
||||
while (!dma_underrun)
|
||||
{
|
||||
@@ -333,65 +394,77 @@ static void cmd_read(struct read_frame* f)
|
||||
if (revolutions == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Wait for the next block to be read. */
|
||||
while (dma_reading_from_td == dma_writing_to_td)
|
||||
{
|
||||
/* On an underrun, give up immediately. */
|
||||
if (dma_underrun)
|
||||
goto abort;
|
||||
}
|
||||
|
||||
uint8_t dma_buffer_usage = 0;
|
||||
while (dma_buffer_usage < BUFFER_SIZE)
|
||||
{
|
||||
cs.inputptr = dma_buffer[dma_reading_from_td] + dma_buffer_usage;
|
||||
cs.inputlen = BUFFER_SIZE - dma_buffer_usage;
|
||||
crunch(&cs);
|
||||
dma_buffer_usage += BUFFER_SIZE - cs.inputlen;
|
||||
count++;
|
||||
if (cs.outputlen == 0)
|
||||
{
|
||||
while (USBFS_GetEPState(FLUXENGINE_DATA_IN_EP_NUM) != USBFS_IN_BUFFER_EMPTY)
|
||||
{
|
||||
if (index_irq || dma_underrun)
|
||||
goto abort;
|
||||
}
|
||||
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE);
|
||||
cs.outputptr = usb_buffer;
|
||||
cs.outputlen = BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td);
|
||||
if (do_capture_chunk())
|
||||
goto abort;
|
||||
}
|
||||
abort:;
|
||||
CAPTURE_CONTROL_Write(0);
|
||||
CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN);
|
||||
while (CyDmaChGetRequest(dma_channel))
|
||||
;
|
||||
|
||||
donecrunch(&cs);
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
unsigned zz = cs.outputlen;
|
||||
if (cs.outputlen != BUFFER_SIZE)
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen);
|
||||
if ((cs.outputlen == BUFFER_SIZE) || (cs.outputlen == 0))
|
||||
USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0);
|
||||
wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM);
|
||||
deinit_dma();
|
||||
stop_capture();
|
||||
|
||||
if (dma_underrun)
|
||||
{
|
||||
print("underrun after %d packets");
|
||||
send_error(F_ERROR_UNDERRUN);
|
||||
}
|
||||
else
|
||||
{
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_READ_REPLY);
|
||||
send_reply(&r);
|
||||
}
|
||||
print("count=%d i=%d d=%d zz=%d", count, index_irq, dma_underrun, zz);
|
||||
}
|
||||
|
||||
static void cmd_read_qd(struct read_frame* f)
|
||||
{
|
||||
SIDE_REG_Write(f->side);
|
||||
|
||||
/* Do slow setup *before* we go into the real-time bit. */
|
||||
|
||||
init_capture();
|
||||
|
||||
/* Reset the drive. */
|
||||
|
||||
STEP_REG_Write(2);
|
||||
CyDelay(10); /* ms */
|
||||
STEP_REG_Write(0);
|
||||
|
||||
/* Motor on, and wait for ready. */
|
||||
|
||||
MOTOR_REG_Write(1);
|
||||
while (!(DISKSTATUS_REG_Read() & DISKSTATUS_READY))
|
||||
;
|
||||
|
||||
/* Turning the motor off has no effect until the head hits the stop,
|
||||
* at which point it'll stop automatically. */
|
||||
|
||||
MOTOR_REG_Write(0);
|
||||
|
||||
/* Start transferring. */
|
||||
|
||||
start_capture();
|
||||
while (!dma_underrun)
|
||||
{
|
||||
CyWdtClear();
|
||||
|
||||
/* Have we reached the end? */
|
||||
if (!(DISKSTATUS_REG_Read() & DISKSTATUS_READY))
|
||||
break;
|
||||
|
||||
if (do_capture_chunk())
|
||||
goto abort;
|
||||
}
|
||||
abort:;
|
||||
stop_capture();
|
||||
|
||||
/* Reset the drive again to ensure the motor stops. */
|
||||
|
||||
STEP_REG_Write(2);
|
||||
CyDelay(10); /* ms */
|
||||
STEP_REG_Write(0);
|
||||
|
||||
if (dma_underrun)
|
||||
send_error(F_ERROR_UNDERRUN);
|
||||
else
|
||||
{
|
||||
DECLARE_REPLY_FRAME(struct any_frame, F_FRAME_READ_QD_REPLY);
|
||||
send_reply(&r);
|
||||
}
|
||||
}
|
||||
|
||||
static void init_replay_dma(void)
|
||||
@@ -647,6 +720,10 @@ static void handle_command(void)
|
||||
cmd_read((struct read_frame*) f);
|
||||
break;
|
||||
|
||||
case F_FRAME_READ_QD_CMD:
|
||||
cmd_read_qd((struct read_frame*) f);
|
||||
break;
|
||||
|
||||
case F_FRAME_WRITE_CMD:
|
||||
cmd_write((struct write_frame*) f);
|
||||
break;
|
||||
|
||||
@@ -112,6 +112,7 @@ FluxSpec::FluxSpec(const DataSpec& spec)
|
||||
|
||||
locations.clear();
|
||||
|
||||
quickdisk = spec.has("qd") && spec.at("qd").only();
|
||||
const auto& drives = spec.at("d").data;
|
||||
if (drives.size() != 1)
|
||||
Error() << "you must specify exactly one drive";
|
||||
@@ -128,7 +129,7 @@ FluxSpec::FluxSpec(const DataSpec& spec)
|
||||
for (const auto& e : spec.modifiers)
|
||||
{
|
||||
const auto name = e.second.name;
|
||||
if ((name != "t") && (name != "s") && (name != "d"))
|
||||
if ((name != "t") && (name != "s") && (name != "d") && (name != "qd"))
|
||||
Error() << fmt::format("unknown fluxspec modifier '{}'", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
std::string filename;
|
||||
std::vector<Location> locations;
|
||||
unsigned drive;
|
||||
bool quickdisk : 1;
|
||||
};
|
||||
|
||||
class ImageSpec
|
||||
|
||||
@@ -15,7 +15,12 @@ std::unique_ptr<FluxSource> FluxSource::create(const FluxSpec& spec)
|
||||
const auto& filename = spec.filename;
|
||||
|
||||
if (filename.empty())
|
||||
return createHardwareFluxSource(spec.drive);
|
||||
{
|
||||
if (spec.quickdisk)
|
||||
return createQuickdiskFluxSource(spec.drive);
|
||||
else
|
||||
return createHardwareFluxSource(spec.drive);
|
||||
}
|
||||
else if (ends_with(filename, ".flux"))
|
||||
return createSqliteFluxSource(filename);
|
||||
else if (ends_with(filename, "/"))
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "flags.h"
|
||||
|
||||
extern FlagGroup hardwareFluxSourceFlags;
|
||||
extern FlagGroup quickdiskFluxSourceFlags;
|
||||
|
||||
class Fluxmap;
|
||||
class FluxSpec;
|
||||
@@ -16,6 +17,7 @@ public:
|
||||
private:
|
||||
static std::unique_ptr<FluxSource> createSqliteFluxSource(const std::string& filename);
|
||||
static std::unique_ptr<FluxSource> createHardwareFluxSource(unsigned drive);
|
||||
static std::unique_ptr<FluxSource> createQuickdiskFluxSource(unsigned drive);
|
||||
static std::unique_ptr<FluxSource> createStreamFluxSource(const std::string& path);
|
||||
|
||||
public:
|
||||
|
||||
50
lib/fluxsource/quickdiskfluxsource.cc
Normal file
50
lib/fluxsource/quickdiskfluxsource.cc
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "fluxmap.h"
|
||||
#include "usb.h"
|
||||
#include "fluxsource/fluxsource.h"
|
||||
|
||||
FlagGroup quickdiskFluxSourceFlags;
|
||||
|
||||
class QuickdiskFluxSource : public FluxSource
|
||||
{
|
||||
public:
|
||||
QuickdiskFluxSource(unsigned drive):
|
||||
_drive(drive)
|
||||
{
|
||||
}
|
||||
|
||||
~QuickdiskFluxSource()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
std::unique_ptr<Fluxmap> readFlux(int track, int side)
|
||||
{
|
||||
usbSetDrive(_drive, false);
|
||||
Bytes crunched = usbReadQD(side);
|
||||
auto fluxmap = std::make_unique<Fluxmap>();
|
||||
fluxmap->appendBytes(crunched.uncrunch());
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
void recalibrate()
|
||||
{
|
||||
}
|
||||
|
||||
bool retryable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned _drive;
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createQuickdiskFluxSource(unsigned drive)
|
||||
{
|
||||
return std::unique_ptr<FluxSource>(new QuickdiskFluxSource(drive));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "track.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
FlagGroup readerFlags { &hardwareFluxSourceFlags, &fluxmapReaderFlags };
|
||||
FlagGroup readerFlags { &hardwareFluxSourceFlags, &quickdiskFluxSourceFlags, &fluxmapReaderFlags };
|
||||
|
||||
static DataSpecFlag source(
|
||||
{ "--source", "-s" },
|
||||
@@ -85,8 +85,6 @@ std::vector<std::unique_ptr<Track>> readTracks()
|
||||
|
||||
std::cout << "Reading from: " << source << std::endl;
|
||||
|
||||
setHardwareFluxSourceDensity(highDensityFlag);
|
||||
|
||||
if (!destination.get().empty())
|
||||
{
|
||||
outdb = sqlOpen(destination, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
@@ -102,8 +100,9 @@ std::vector<std::unique_ptr<Track>> readTracks()
|
||||
);
|
||||
}
|
||||
|
||||
std::shared_ptr<FluxSource> fluxSource = FluxSource::create(spec);
|
||||
setHardwareFluxSourceDensity(highDensityFlag);
|
||||
|
||||
std::shared_ptr<FluxSource> fluxSource = FluxSource::create(spec);
|
||||
std::vector<std::unique_ptr<Track>> tracks;
|
||||
for (const auto& location : spec.locations)
|
||||
{
|
||||
|
||||
21
lib/usb.cc
21
lib/usb.cc
@@ -76,7 +76,7 @@ static void bad_reply(void)
|
||||
{
|
||||
struct error_frame* f = (struct error_frame*) buffer;
|
||||
if (f->f.type != F_FRAME_ERROR)
|
||||
Error() << fmt::format("bad USB reply 0x{:2x}", f->f.type);
|
||||
Error() << fmt::format("bad USB reply 0x{:02x}", f->f.type);
|
||||
switch (f->error)
|
||||
{
|
||||
case F_ERROR_BAD_COMMAND:
|
||||
@@ -221,6 +221,25 @@ Bytes usbRead(int side, int revolutions)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
Bytes usbReadQD(int side)
|
||||
{
|
||||
struct read_frame f = {
|
||||
.f = { .type = F_FRAME_READ_QD_CMD, .size = sizeof(f) },
|
||||
.side = (uint8_t) side,
|
||||
.revolutions = 1
|
||||
};
|
||||
usb_cmd_send(&f, f.f.size);
|
||||
|
||||
auto fluxmap = std::unique_ptr<Fluxmap>(new Fluxmap);
|
||||
|
||||
Bytes buffer(1024*1024);
|
||||
int len = large_bulk_transfer(FLUXENGINE_DATA_IN_EP, buffer);
|
||||
buffer.resize(len);
|
||||
|
||||
await_reply<struct any_frame>(F_FRAME_READ_REPLY);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void usbWrite(int side, const Bytes& bytes)
|
||||
{
|
||||
unsigned safelen = bytes.size() & ~(FRAME_SIZE-1);
|
||||
|
||||
@@ -10,6 +10,7 @@ extern void usbSeek(int track);
|
||||
extern nanoseconds_t usbGetRotationalPeriod();
|
||||
extern void usbTestBulkTransport();
|
||||
extern Bytes usbRead(int side, int revolutions);
|
||||
extern Bytes usbReadQD(int side);
|
||||
extern void usbWrite(int side, const Bytes& bytes);
|
||||
extern void usbErase(int side);
|
||||
extern void usbSetDrive(int drive, bool high_density);
|
||||
|
||||
@@ -170,6 +170,7 @@ buildlibrary libbackend.a \
|
||||
lib/fluxsink/sqlitefluxsink.cc \
|
||||
lib/fluxsource/fluxsource.cc \
|
||||
lib/fluxsource/hardwarefluxsource.cc \
|
||||
lib/fluxsource/quickdiskfluxsource.cc \
|
||||
lib/fluxsource/kryoflux.cc \
|
||||
lib/fluxsource/sqlitefluxsource.cc \
|
||||
lib/fluxsource/streamfluxsource.cc \
|
||||
@@ -203,6 +204,7 @@ buildlibrary libfrontend.a \
|
||||
src/fe-readibm.cc \
|
||||
src/fe-readmac.cc \
|
||||
src/fe-readmx.cc \
|
||||
src/fe-readqd.cc \
|
||||
src/fe-readvictor9k.cc \
|
||||
src/fe-readzilogmcz.cc \
|
||||
src/fe-rpm.cc \
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
enum
|
||||
{
|
||||
FLUXENGINE_VERSION = 8,
|
||||
FLUXENGINE_VERSION = 9,
|
||||
|
||||
FLUXENGINE_VID = 0x1209,
|
||||
FLUXENGINE_PID = 0x6e00,
|
||||
@@ -54,6 +54,8 @@ enum
|
||||
F_FRAME_BULK_TEST_REPLY, /* any_frame */
|
||||
F_FRAME_READ_CMD, /* read_frame */
|
||||
F_FRAME_READ_REPLY, /* any_frame */
|
||||
F_FRAME_READ_QD_CMD, /* read_frame */
|
||||
F_FRAME_READ_QD_REPLY, /* any_frame */
|
||||
F_FRAME_WRITE_CMD, /* write_frame */
|
||||
F_FRAME_WRITE_REPLY, /* any_frame */
|
||||
F_FRAME_ERASE_CMD, /* erase_frame */
|
||||
|
||||
26
src/fe-readqd.cc
Normal file
26
src/fe-readqd.cc
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "globals.h"
|
||||
#include "flags.h"
|
||||
#include "reader.h"
|
||||
#include "fluxmap.h"
|
||||
#include "decoders/decoders.h"
|
||||
#include "image.h"
|
||||
#include "sector.h"
|
||||
#include "sectorset.h"
|
||||
#include "record.h"
|
||||
#include "ibm/ibm.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
static FlagGroup flags { &readerFlags };
|
||||
|
||||
int mainReadQd(int argc, const char* argv[])
|
||||
{
|
||||
setReaderDefaultSource(":qd=1");
|
||||
setReaderDefaultOutput("qd.img");
|
||||
setReaderRevolutions(2);
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
IbmDecoder decoder(0);
|
||||
readDiskCommand(decoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ extern command_cb mainReadFB100;
|
||||
extern command_cb mainReadIBM;
|
||||
extern command_cb mainReadMac;
|
||||
extern command_cb mainReadMx;
|
||||
extern command_cb mainReadQd;
|
||||
extern command_cb mainReadVictor9K;
|
||||
extern command_cb mainReadZilogMCZ;
|
||||
extern command_cb mainRpm;
|
||||
@@ -71,6 +72,7 @@ static std::vector<Command> readables =
|
||||
{ "ibm", mainReadIBM, "Reads the ubiquitous IBM format disks.", },
|
||||
{ "mac", mainReadMac, "Reads Apple Macintosh disks.", },
|
||||
{ "mx", mainReadMx, "Reads MX disks.", },
|
||||
{ "qd", mainReadQd, "Reads QuickDisk disks.", },
|
||||
{ "victor9k", mainReadVictor9K, "Reads Victor 9000 disks.", },
|
||||
{ "zilogmcz", mainReadZilogMCZ, "Reads Zilog MCZ disks.", },
|
||||
};
|
||||
|
||||
@@ -85,6 +85,15 @@ static void test_fluxspec(void)
|
||||
{{1, 9, 1}}));
|
||||
assert((std::string)spec == ":d=1:s=1:t=9");
|
||||
}
|
||||
|
||||
spec.set("");
|
||||
assert(FluxSpec(spec).quickdisk == false);
|
||||
|
||||
spec.set(":qd=0");
|
||||
assert(FluxSpec(spec).quickdisk == false);
|
||||
|
||||
spec.set(":qd=1");
|
||||
assert(FluxSpec(spec).quickdisk == true);
|
||||
}
|
||||
|
||||
static void test_imagespec(void)
|
||||
|
||||
Reference in New Issue
Block a user