From 098b2371a4c3ad99e24789e6142d8573fcd85698 Mon Sep 17 00:00:00 2001 From: David Given Date: Wed, 27 Mar 2019 21:58:41 +0100 Subject: [PATCH] Crunched datastreams are now used when writing. --- FluxEngine.cydsn/main.c | 157 +++++++++++++++++++++------------------- lib/bytes.cc | 28 ++++++- lib/common/crunch.c | 3 +- lib/usb.cc | 33 +++++---- lib/usb.h | 2 +- lib/writer.cc | 3 +- protocol.h | 8 ++ 7 files changed, 141 insertions(+), 93 deletions(-) diff --git a/FluxEngine.cydsn/main.c b/FluxEngine.cydsn/main.c index c1faf4c9..e66e0de9 100644 --- a/FluxEngine.cydsn/main.c +++ b/FluxEngine.cydsn/main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "project.h" #include "../protocol.h" @@ -119,6 +120,18 @@ static void send_error(int code) send_reply((struct any_frame*) &r); } +static void debug(const char* msg, ...) +{ + DECLARE_REPLY_FRAME(struct debug_frame, F_FRAME_DEBUG); + + va_list ap; + va_start(ap, msg); + vsnprintf(r.payload, sizeof(r.payload), msg, ap); + va_end(ap); + + send_reply((struct any_frame*) &r); +} + /* buffer must be big enough for a frame */ static int usb_read(int ep, uint8_t buffer[FRAME_SIZE]) { @@ -283,8 +296,7 @@ static void cmd_read(struct read_frame* f) ; index_irq = false; - crunch_state_t cs; - cs.fifolen = 0; + crunch_state_t cs = {}; cs.outputptr = usb_buffer; cs.outputlen = BUFFER_SIZE; @@ -422,32 +434,80 @@ static void cmd_write(struct write_frame* f) init_replay_dma(); bool writing = false; /* to the disk */ - bool listening = false; bool finished = false; int packets = f->bytes_to_write / FRAME_SIZE; - int count_read = 0; int count_written = 0; + int count_read = 0; dma_writing_to_td = 0; dma_reading_from_td = -1; dma_underrun = false; + crunch_state_t cs = {}; + cs.outputlen = BUFFER_SIZE; + USBFS_EnableOutEP(FLUXENGINE_DATA_OUT_EP_NUM); + int old_reading_from_td = -1; for (;;) { - if (dma_reading_from_td != old_reading_from_td) - { - count_written++; - old_reading_from_td = dma_reading_from_td; - } + /* Read data from USB into the buffers. */ - if (dma_reading_from_td != -1) + if (NEXT_BUFFER(dma_writing_to_td) != dma_reading_from_td) { - /* We want to be writing to disk. */ + if (writing && (dma_underrun || index_irq)) + goto abort; - if (!writing) + /* Read crunched data, if necessary. */ + + if (cs.inputlen == 0) { - print("start writing\r"); + if (finished) + { + /* There's no more data to read, so fake some. */ + + for (int i=0; iinputlen && state->outputlen) { if (state->fifolen < 8) { @@ -72,7 +72,6 @@ void uncrunch(crunch_state_t* state) state->outputlen--; } } - while (state->inputlen && state->outputlen); } void doneuncrunch(crunch_state_t* state) diff --git a/lib/usb.cc b/lib/usb.cc index f2ff67b6..d87aa758 100644 --- a/lib/usb.cc +++ b/lib/usb.cc @@ -5,6 +5,7 @@ #include "bytes.h" #include "crunch.h" #include +#include #define TIMEOUT 5000 @@ -81,18 +82,26 @@ static void bad_reply(void) Error() << "USB underrun (not enough bandwidth)"; default: - Error() << "unknown device error " << f->error; + Error() << fmt::format("unknown device error {}", f->error); } } template static T* await_reply(int desired) { - usb_cmd_recv(buffer, sizeof(buffer)); - struct any_frame* r = (struct any_frame*) buffer; - if (r->f.type != desired) - bad_reply(); - return (T*) r; + for (;;) + { + usb_cmd_recv(buffer, sizeof(buffer)); + struct any_frame* r = (struct any_frame*) buffer; + if (r->f.type == F_FRAME_DEBUG) + { + std::cout << "dev: " << ((struct debug_frame*)r)->payload << std::endl; + continue; + } + if (r->f.type != desired) + bad_reply(); + return (T*) r; + } } int usbGetVersion(void) @@ -208,14 +217,10 @@ Bytes usbRead(int side, int revolutions) return buffer; } -void usbWrite(int side, const Fluxmap& fluxmap) +void usbWrite(int side, const Bytes& bytes) { - unsigned safelen = fluxmap.bytes() & ~(FRAME_SIZE-1); - - /* Convert from intervals to absolute timestamps. */ - - Bytes buffer(fluxmap.rawBytes()); - buffer.resize(safelen); + unsigned safelen = bytes.size() & ~(FRAME_SIZE-1); + Bytes safeBytes = bytes.slice(0, safelen); struct write_frame f = { .f = { .type = F_FRAME_WRITE_CMD, .size = sizeof(f) }, @@ -228,7 +233,7 @@ void usbWrite(int side, const Fluxmap& fluxmap) usb_cmd_send(&f, f.f.size); - large_bulk_transfer(FLUXENGINE_DATA_OUT_EP, buffer); + int len = large_bulk_transfer(FLUXENGINE_DATA_OUT_EP, safeBytes); await_reply(F_FRAME_WRITE_REPLY); } diff --git a/lib/usb.h b/lib/usb.h index ec79a1b0..3f47da94 100644 --- a/lib/usb.h +++ b/lib/usb.h @@ -10,7 +10,7 @@ extern void usbSeek(int track); extern nanoseconds_t usbGetRotationalPeriod(); extern void usbTestBulkTransport(); extern Bytes usbRead(int side, int revolutions); -extern void usbWrite(int side, const Fluxmap& fluxmap); +extern void usbWrite(int side, const Bytes& bytes); extern void usbErase(int side); extern void usbSetDrive(int drive, bool high_density); diff --git a/lib/writer.cc b/lib/writer.cc index 0b56eae9..8d60727e 100644 --- a/lib/writer.cc +++ b/lib/writer.cc @@ -61,8 +61,9 @@ void writeTracks( sqlWriteFlux(outdb, location.track, location.side, *fluxmap); else { + Bytes crunched = fluxmap->rawBytes().crunch(); usbSeek(location.track); - usbWrite(location.side, *fluxmap); + usbWrite(location.side, crunched); } std::cout << fmt::format( "{0} ms in {1} bytes", int(fluxmap->duration()/1e6), fluxmap->bytes()) << std::endl; diff --git a/protocol.h b/protocol.h index 72077cc4..b827ced1 100644 --- a/protocol.h +++ b/protocol.h @@ -43,6 +43,7 @@ enum enum { F_FRAME_ERROR = 0, /* any_frame */ + F_FRAME_DEBUG, /* debug_frame */ F_FRAME_GET_VERSION_CMD, /* any_frame */ F_FRAME_GET_VERSION_REPLY, /* version_frame */ F_FRAME_SEEK_CMD, /* seek_frame */ @@ -69,6 +70,7 @@ enum F_ERROR_BAD_COMMAND, F_ERROR_UNDERRUN, F_ERROR_INVALID_VALUE, + F_ERROR_INTERNAL, }; struct frame_header @@ -88,6 +90,12 @@ struct error_frame uint8_t error; }; +struct debug_frame +{ + struct frame_header f; + char payload[60]; +}; + struct version_frame { struct frame_header f;