mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
155 lines
4.0 KiB
C++
155 lines
4.0 KiB
C++
#include "lib/core/globals.h"
|
|
#include "usb.h"
|
|
#include "protocol.h"
|
|
#include "lib/core/bytes.h"
|
|
#include "greaseweazle.h"
|
|
|
|
Bytes fluxEngineToGreaseweazle(const Bytes& fldata, nanoseconds_t clock)
|
|
{
|
|
Bytes gwdata;
|
|
ByteWriter bw(gwdata);
|
|
ByteReader br(fldata);
|
|
uint32_t ticks_fl = 0;
|
|
uint32_t ticks_gw = 0;
|
|
|
|
auto write_28 = [&](uint32_t val)
|
|
{
|
|
bw.write_8(1 | (val << 1) & 0xff);
|
|
bw.write_8(1 | (val >> 6) & 0xff);
|
|
bw.write_8(1 | (val >> 13) & 0xff);
|
|
bw.write_8(1 | (val >> 20) & 0xff);
|
|
};
|
|
|
|
while (!br.eof())
|
|
{
|
|
uint8_t b = br.read_8();
|
|
ticks_fl += b & 0x3f;
|
|
if (b & F_BIT_PULSE)
|
|
{
|
|
uint32_t newticks_gw = ticks_fl * NS_PER_TICK / clock;
|
|
uint32_t delta = newticks_gw - ticks_gw;
|
|
if (delta < 250)
|
|
bw.write_8(delta);
|
|
else
|
|
{
|
|
int high = (delta - 250) / 255;
|
|
if (high < 5)
|
|
{
|
|
bw.write_8(250 + high);
|
|
bw.write_8(1 + (delta - 250) % 255);
|
|
}
|
|
else
|
|
{
|
|
bw.write_8(255);
|
|
bw.write_8(FLUXOP_SPACE);
|
|
write_28(delta - 249);
|
|
bw.write_8(249);
|
|
}
|
|
}
|
|
ticks_gw = newticks_gw;
|
|
}
|
|
}
|
|
bw.write_8(0); /* end of stream */
|
|
return gwdata;
|
|
}
|
|
|
|
Bytes greaseweazleToFluxEngine(const Bytes& gwdata, nanoseconds_t clock)
|
|
{
|
|
Bytes fldata;
|
|
ByteReader br(gwdata);
|
|
ByteWriter bw(fldata);
|
|
|
|
auto read_28 = [&]()
|
|
{
|
|
return ((br.read_8() & 0xfe) >> 1) | ((br.read_8() & 0xfe) << 6) |
|
|
((br.read_8() & 0xfe) << 13) | ((br.read_8() & 0xfe) << 20);
|
|
};
|
|
|
|
uint32_t ticks_gw = 0;
|
|
uint32_t lastevent_fl = 0;
|
|
uint32_t index_gw = ~0;
|
|
|
|
while (!br.eof())
|
|
{
|
|
uint8_t b = br.read_8();
|
|
if (!b)
|
|
break;
|
|
|
|
uint8_t event = 0;
|
|
if (b == 255)
|
|
{
|
|
switch (br.read_8())
|
|
{
|
|
case FLUXOP_INDEX:
|
|
index_gw = ticks_gw + read_28();
|
|
break;
|
|
|
|
case FLUXOP_SPACE:
|
|
ticks_gw += read_28();
|
|
break;
|
|
|
|
default:
|
|
error("bad opcode in Greaseweazle stream");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (b < 250)
|
|
ticks_gw += b;
|
|
else
|
|
{
|
|
int delta = 250 + (b - 250) * 255 + br.read_8() - 1;
|
|
ticks_gw += delta;
|
|
}
|
|
event = F_BIT_PULSE;
|
|
}
|
|
|
|
if (event)
|
|
{
|
|
uint32_t index_fl = round((index_gw * clock) / NS_PER_TICK);
|
|
uint32_t ticks_fl = round((ticks_gw * clock) / NS_PER_TICK);
|
|
if (index_gw != ~0)
|
|
{
|
|
if (index_fl < ticks_fl)
|
|
{
|
|
uint32_t delta_fl = index_fl - lastevent_fl;
|
|
while (delta_fl > 0x3f)
|
|
{
|
|
bw.write_8(0x3f);
|
|
delta_fl -= 0x3f;
|
|
}
|
|
bw.write_8(delta_fl | F_BIT_INDEX);
|
|
lastevent_fl = index_fl;
|
|
index_gw = ~0;
|
|
}
|
|
else if (index_fl == ticks_fl)
|
|
event |= F_BIT_INDEX;
|
|
}
|
|
|
|
uint32_t delta_fl = ticks_fl - lastevent_fl;
|
|
while (delta_fl > 0x3f)
|
|
{
|
|
bw.write_8(0x3f);
|
|
delta_fl -= 0x3f;
|
|
}
|
|
bw.write_8(delta_fl | event);
|
|
lastevent_fl = ticks_fl;
|
|
}
|
|
}
|
|
|
|
return fldata;
|
|
}
|
|
|
|
/* Left-truncates at the first index mark, so the resulting data as aligned at
|
|
* the index. */
|
|
Bytes stripPartialRotation(const Bytes& fldata)
|
|
{
|
|
for (unsigned i = 0; i < fldata.size(); i++)
|
|
{
|
|
uint8_t b = fldata[i];
|
|
if (b & F_BIT_INDEX)
|
|
return fldata.slice(i);
|
|
}
|
|
return fldata;
|
|
}
|