diff --git a/lib/encoder.cc b/lib/encoder.cc index 8ba48221..e2ec43a1 100644 --- a/lib/encoder.cc +++ b/lib/encoder.cc @@ -12,6 +12,7 @@ Fluxmap& Fluxmap::appendBits(const std::vector& bits, nanoseconds_t clock) { unsigned delta = (now - duration()) / NS_PER_TICK; appendInterval(delta); + appendPulse(); } } diff --git a/lib/fluxmap.cc b/lib/fluxmap.cc index 6acdbb9c..92be85c4 100644 --- a/lib/fluxmap.cc +++ b/lib/fluxmap.cc @@ -32,6 +32,11 @@ Fluxmap& Fluxmap::appendInterval(uint32_t ticks) ticks -= 0x7f; } appendByte((uint8_t)ticks); + return *this; +} + +Fluxmap& Fluxmap::appendPulse() +{ appendByte(0x80); return *this; } diff --git a/lib/fluxmap.h b/lib/fluxmap.h index e0c04df4..1877a4f2 100644 --- a/lib/fluxmap.h +++ b/lib/fluxmap.h @@ -20,6 +20,7 @@ public: } Fluxmap& appendInterval(uint32_t ticks); + Fluxmap& appendPulse(); Fluxmap& appendIndex(); Fluxmap& appendBytes(const Bytes& bytes); diff --git a/lib/fluxreader/kryoflux.cc b/lib/fluxreader/kryoflux.cc index 6a6746c4..f6961774 100644 --- a/lib/fluxreader/kryoflux.cc +++ b/lib/fluxreader/kryoflux.cc @@ -6,7 +6,10 @@ #include #include -#define SCLK_HZ 24027428.57142857 +#define MCLK_HZ (((18432000.0 * 73.0) / 14.0) / 2.0) +#define SCLK_HZ (MCLK_HZ / 2) +#define ICLK_HZ (MCLK_HZ / 16) + #define TICKS_PER_SCLK (TICK_FREQUENCY / SCLK_HZ) std::unique_ptr readStream(const std::string& dir, unsigned track, unsigned side) @@ -30,37 +33,41 @@ std::unique_ptr readStream(const std::string& filename) if (!f.is_open()) Error() << fmt::format("cannot open input file '{}'", filename); - return readStream(f); + Bytes bytes; + ByteWriter bw(bytes); + bw.append(f); + + return readStream(bytes); } -std::unique_ptr readStream(std::istream& f) +std::unique_ptr readStream(const Bytes& bytes) { - std::unique_ptr fluxmap(new Fluxmap); - auto writeFlux = [&](uint32_t sclk) - { - int ticks = (double)sclk * TICKS_PER_SCLK; - fluxmap->appendInterval(ticks); - }; + ByteReader br(bytes); - uint32_t extrasclks = 0; - for (;;) + /* Pass 1: scan the stream looking for index marks. */ + + std::set indexmarks; + br.seek(0); + while (!br.eof()) { - int b = f.get(); /* returns -1 or UNSIGNED char */ - if (b == -1) - break; - + uint8_t b = br.read_8(); + unsigned len = 0; switch (b) { case 0x0d: /* OOB block */ { - int blocktype = f.get(); - (void) blocktype; - uint16_t blocklen = f.get() | (f.get()<<8); - if (f.fail() || f.eof()) - goto finished; + int blocktype = br.read_8(); + len = br.read_le16(); + if (br.eof()) + goto finished_pass_1; - while (blocklen--) - f.get(); + if (blocktype == 0x02) + { + /* index data, sent asynchronously */ + uint32_t streampos = br.read_le32(); + indexmarks.insert(streampos); + len -= 4; + } break; } @@ -69,7 +76,104 @@ std::unique_ptr readStream(std::istream& f) if ((b >= 0x00) && (b <= 0x07)) { /* Flux2: double byte value */ - b = (b<<8) | f.get(); + len = 1; + } + else if (b == 0x08) + { + /* Nop1: do nothing */ + len = 0; + } + else if (b == 0x09) + { + /* Nop2: skip one byte */ + len = 1; + } + else if (b == 0x0a) + { + /* Nop3: skip two bytes */ + len = 2; + } + else if (b == 0x0b) + { + /* Ovl16: the next block is 0x10000 sclks longer than normal. */ + len = 0; + } + else if (b == 0x0c) + { + /* Flux3: triple byte value */ + len = 2; + } + else if ((b >= 0x0e) && (b <= 0xff)) + { + /* Flux1: single byte value */ + len = 0; + } + else + Error() << fmt::format( + "unknown stream block byte 0x{:02x} at 0x{:08x}", b, (uint64_t)br.pos-1); + } + } + + br.skip(len); + } +finished_pass_1: + + /* Pass 2: actually read the data. */ + + std::unique_ptr fluxmap(new Fluxmap); + int streamdelta = 0; + auto writeFlux = [&](uint32_t sclk) + { + const auto& nextindex = indexmarks.begin(); + if (nextindex != indexmarks.end()) + { + uint32_t nextindexpos = *nextindex + streamdelta; + if (br.pos >= nextindexpos) + { + fluxmap->appendIndex(); + indexmarks.erase(nextindex); + } + } + int ticks = (double)sclk * TICKS_PER_SCLK; + fluxmap->appendInterval(ticks); + fluxmap->appendPulse(); + }; + + uint32_t extrasclks = 0; + br.seek(0); + while (!br.eof()) + { + unsigned b = br.read_8(); + switch (b) + { + case 0x0d: /* OOB block */ + { + int blocktype = br.read_8(); + uint16_t blocklen = br.read_le16(); + if (br.eof()) + goto finished_pass_2; + + switch (blocktype) + { + case 0x01: /* streaminfo */ + { + uint32_t blockpos = br.pos - 3; + streamdelta = blockpos - br.read_le32(); + blocklen -= 4; + break; + } + } + + br.skip(blocklen); + break; + } + + default: + { + if ((b >= 0x00) && (b <= 0x07)) + { + /* Flux2: double byte value */ + b = (b<<8) | br.read_8(); writeFlux(extrasclks + b); extrasclks = 0; } @@ -80,13 +184,12 @@ std::unique_ptr readStream(std::istream& f) else if (b == 0x09) { /* Nop2: skip one byte */ - f.get(); + br.skip(1); } else if (b == 0x0a) { /* Nop3: skip two bytes */ - f.get(); - f.get(); + br.skip(2); } else if (b == 0x0b) { @@ -96,8 +199,7 @@ std::unique_ptr readStream(std::istream& f) else if (b == 0x0c) { /* Flux3: triple byte value */ - int ticks = f.get() << 8; - ticks |= f.get(); + int ticks = br.read_be16(); /* yes, really big-endian */ writeFlux(extrasclks + ticks); extrasclks = 0; } @@ -109,13 +211,13 @@ std::unique_ptr readStream(std::istream& f) } else Error() << fmt::format( - "unknown stream block byte 0x{:02x} at 0x{:08x}", b, (uint64_t)f.tellg()-1); + "unknown stream block byte 0x{:02x} at 0x{:08x}", b, (uint64_t)br.pos-1); } } } -finished: - if (!f.eof()) +finished_pass_2: + if (!br.eof()) Error() << "I/O error reading stream"; return fluxmap; } diff --git a/lib/fluxreader/kryoflux.h b/lib/fluxreader/kryoflux.h index ea35ec1f..00724456 100644 --- a/lib/fluxreader/kryoflux.h +++ b/lib/fluxreader/kryoflux.h @@ -3,6 +3,6 @@ extern std::unique_ptr readStream(const std::string& dir, unsigned track, unsigned side); extern std::unique_ptr readStream(const std::string& path); -extern std::unique_ptr readStream(std::istream& stream); +extern std::unique_ptr readStream(const Bytes& bytes); #endif diff --git a/src/fe-upgradefluxfile.cc b/src/fe-upgradefluxfile.cc index 2a50454a..020c8c96 100644 --- a/src/fe-upgradefluxfile.cc +++ b/src/fe-upgradefluxfile.cc @@ -20,6 +20,7 @@ static void update_version_1_to_2() if (b < 0x80) { after.appendInterval(b + pending); + after.appendPulse(); pending = 0; } else diff --git a/src/fe-writetestpattern.cc b/src/fe-writetestpattern.cc index d91374b3..2e5cc7e3 100644 --- a/src/fe-writetestpattern.cc +++ b/src/fe-writetestpattern.cc @@ -31,7 +31,10 @@ int main(int argc, const char* argv[]) std::unique_ptr fluxmap(new Fluxmap); while (fluxmap->duration() < (sequenceLength*1000000.0)) + { fluxmap->appendInterval(ticksPerInterval); + fluxmap->appendPulse(); + } return fluxmap; } diff --git a/tests/kryoflux.cc b/tests/kryoflux.cc index 1796ba39..40eaadbf 100644 --- a/tests/kryoflux.cc +++ b/tests/kryoflux.cc @@ -5,28 +5,6 @@ #include "fluxmap.h" #include "kryoflux.h" -struct memstreambuf : std::streambuf -{ - memstreambuf(const Bytes& bytes) - { - this->setg((char*) bytes.begin(), (char*) bytes.begin(), (char*) bytes.end()); - } -}; - -class memstream : public std::istream -{ -public: - memstream(const Bytes& bytes): - std::istream(&_buffer), - _buffer(bytes) - { - rdbuf(&_buffer); - } - -private: - memstreambuf _buffer; -}; - static Bytes operator + (const Bytes& left, const Bytes& right) { Bytes output; @@ -47,8 +25,7 @@ static Bytes operator * (const Bytes& left, size_t count) static void test_convert(const Bytes& kryofluxbytes, const Bytes& fluxmapbytes) { - memstream stream(kryofluxbytes); - std::unique_ptr fluxmap = readStream(stream); + std::unique_ptr fluxmap = readStream(kryofluxbytes); if (fluxmap->rawBytes() != fluxmapbytes) { @@ -58,7 +35,7 @@ static void test_convert(const Bytes& kryofluxbytes, const Bytes& fluxmapbytes) hexdump(std::cout, fluxmap->rawBytes()); std::cout << std::endl << "Expected this:" << std::endl; hexdump(std::cout, fluxmapbytes); - exit(1); + abort(); } } diff --git a/tools/cwftoflux.cc b/tools/cwftoflux.cc index 8d60d068..458282a3 100644 --- a/tools/cwftoflux.cc +++ b/tools/cwftoflux.cc @@ -104,6 +104,7 @@ static void read_track() double interval_us = b * (1e6/clockRate); fluxmap.appendInterval(interval_us / US_PER_TICK); + fluxmap.appendPulse(); if (index && !oldindex) fluxmap.appendIndex();