usb: Send periodic noflux opcodes during long periods of no flux.

This new no-flux opcode replaces the long-flux opcode:
 long-flux = no-flux + regular-flux
Also rearrange the code a bit to avoid repetition.
This commit is contained in:
Keir Fraser
2020-10-21 12:38:46 +01:00
parent 633a4eb9ee
commit e7062e3ad8
3 changed files with 73 additions and 64 deletions

View File

@@ -98,8 +98,8 @@
/*
* Flux stream opcodes. Preceded by 0xFF byte.
*/
#define FLUXOP_LONGFLUX 1
#define FLUXOP_INDEX 2
#define FLUXOP_INDEX 1
#define FLUXOP_NOFLUX 2
/*

View File

@@ -111,8 +111,8 @@ class BusType:
## Flux read stream opcodes, preceded by 0xFF byte
class FluxOp:
LongFlux = 1
Index = 2
Index = 1
NoFlux = 2
## CmdError: Encapsulates a command acknowledgement.
@@ -263,38 +263,37 @@ class Unit:
def _decode_flux(self, dat):
flux, index = [], []
dat_i = iter(dat)
ticks_since_index = 0
ticks, ticks_since_index = 0, 0
def _read_28bit():
val = (next(dat_i) & 254) >> 1
val += (next(dat_i) & 254) << 6
val += (next(dat_i) & 254) << 13
val += (next(dat_i) & 254) << 20
return val
try:
while True:
i = next(dat_i)
if i < 250:
flux.append(i)
ticks_since_index += i
elif i == 255:
if i == 255:
opcode = next(dat_i)
if opcode == FluxOp.LongFlux:
val = (next(dat_i) & 254) >> 1
val += (next(dat_i) & 254) << 6
val += (next(dat_i) & 254) << 13
val += (next(dat_i) & 254) << 20
flux.append(val)
ticks_since_index += val
elif opcode == FluxOp.Index:
val = (next(dat_i) & 254) >> 1
val += (next(dat_i) & 254) << 6
val += (next(dat_i) & 254) << 13
val += (next(dat_i) & 254) << 20
index.append(ticks_since_index + val)
if opcode == FluxOp.Index:
val = _read_28bit()
index.append(ticks_since_index + ticks + val)
ticks_since_index = -val
pass
elif opcode == FluxOp.NoFlux:
ticks += _read_28bit()
else:
raise error.Fatal("Bad opcode in flux stream (%d)"
% opcode)
else:
val = 250 + (i - 250) * 255
val += next(dat_i) - 1
flux.append(val)
ticks_since_index += val
if i < 250:
val = i
else:
val = 250 + (i - 250) * 255
val += next(dat_i) - 1
ticks += val
flux.append(ticks)
ticks_since_index += ticks
ticks = 0
except StopIteration:
pass
error.check(flux[-1] == 0, "Missing terminator on flux read stream")
@@ -305,6 +304,11 @@ class Unit:
## Convert the given flux timings into an encoded data stream.
def _encode_flux(self, flux):
dat = bytearray()
def _write_28bit(x):
dat.append(1 | (x<<1) & 255)
dat.append(1 | (x>>6) & 255)
dat.append(1 | (x>>13) & 255)
dat.append(1 | (x>>20) & 255)
for val in flux:
if val == 0:
pass
@@ -317,11 +321,9 @@ class Unit:
dat.append(1 + (val-250) % 255)
else:
dat.append(255)
dat.append(FluxOp.LongFlux)
dat.append(1 | (val<<1) & 255)
dat.append(1 | (val>>6) & 255)
dat.append(1 | (val>>13) & 255)
dat.append(1 | (val>>20) & 255)
dat.append(FluxOp.NoFlux)
_write_28bit(val - 249);
dat.append(249)
dat.append(0) # End of Stream
return dat

View File

@@ -299,12 +299,20 @@ static struct {
uint8_t packet[USB_HS_MPS];
} rw;
static always_inline void _write_28bit(uint32_t x)
{
u_buf[U_MASK(u_prod++)] = 1 | (x << 1);
u_buf[U_MASK(u_prod++)] = 1 | (x >> 6);
u_buf[U_MASK(u_prod++)] = 1 | (x >> 13);
u_buf[U_MASK(u_prod++)] = 1 | (x >> 20);
}
static void rdata_encode_flux(void)
{
const uint16_t buf_mask = ARRAY_SIZE(dma.buf) - 1;
uint16_t cons = dma.cons, prod;
timcnt_t prev = dma.prev_sample, curr, next;
uint32_t ticks = rw.ticks_since_flux;
uint32_t ticks;
ASSERT(rw.idx < rw.nr_idx);
@@ -317,14 +325,10 @@ static void rdata_encode_flux(void)
if (rw.idx != index.count) {
/* We have just passed the index mark: Record information about
* the just-completed revolution. */
int partial_flux = ticks + (timcnt_t)(index.rdata_cnt - prev);
ASSERT(partial_flux >= 0);
unsigned int partial_flux = (timcnt_t)(index.rdata_cnt - prev);
u_buf[U_MASK(u_prod++)] = 0xff;
u_buf[U_MASK(u_prod++)] = FLUXOP_INDEX;
u_buf[U_MASK(u_prod++)] = 1 | (partial_flux << 1);
u_buf[U_MASK(u_prod++)] = 1 | (partial_flux >> 6);
u_buf[U_MASK(u_prod++)] = 1 | (partial_flux >> 13);
u_buf[U_MASK(u_prod++)] = 1 | (partial_flux >> 20);
_write_28bit(partial_flux);
rw.idx = index.count;
}
@@ -336,7 +340,7 @@ static void rdata_encode_flux(void)
curr = next - prev;
prev = next;
ticks += curr;
ticks = curr;
if (ticks == 0) {
/* 0: Skip. */
@@ -350,36 +354,31 @@ static void rdata_encode_flux(void)
u_buf[U_MASK(u_prod++)] = 250 + high;
u_buf[U_MASK(u_prod++)] = 1 + ((ticks-250) % 255);
} else {
/* 1525-(2^28-1): Six bytes */
/* 1525-(2^28-1): Seven bytes. */
u_buf[U_MASK(u_prod++)] = 0xff;
u_buf[U_MASK(u_prod++)] = FLUXOP_LONGFLUX;
u_buf[U_MASK(u_prod++)] = 1 | (ticks << 1);
u_buf[U_MASK(u_prod++)] = 1 | (ticks >> 6);
u_buf[U_MASK(u_prod++)] = 1 | (ticks >> 13);
u_buf[U_MASK(u_prod++)] = 1 | (ticks >> 20);
u_buf[U_MASK(u_prod++)] = FLUXOP_NOFLUX;
_write_28bit(ticks - 249);
u_buf[U_MASK(u_prod++)] = 249;
}
}
ticks = 0;
}
/* If it has been a long time since the last flux timing, transfer some of
* the accumulated time from the 16-bit timestamp into the 32-bit
* accumulator. This avoids 16-bit overflow and because, we take care to
* keep the 16-bit timestamp at least 200us behind, we cannot race the next
* flux timestamp. */
if (sizeof(timcnt_t) == sizeof(uint16_t)) {
curr = tim_rdata->cnt - prev;
if (unlikely(curr > sample_us(400))) {
prev += sample_us(200);
ticks += sample_us(200);
}
* the accumulated time to the host in a "long gap" sample. This avoids
* timing overflow and, because we take care to keep @prev well behind the
* sample clock, we cannot race the next flux timestamp. */
curr = tim_rdata->cnt - prev;
if (unlikely(curr > sample_us(400))) {
ticks = sample_us(200);
u_buf[U_MASK(u_prod++)] = 0xff;
u_buf[U_MASK(u_prod++)] = FLUXOP_NOFLUX;
_write_28bit(ticks);
prev += ticks;
}
/* Save our progress for next time. */
dma.cons = cons;
dma.prev_sample = prev;
rw.ticks_since_flux = ticks;
}
static uint8_t floppy_read_prep(const struct gw_read_flux *rf)
@@ -487,6 +486,16 @@ static void floppy_read(void)
* WRITE PATH
*/
static always_inline uint32_t _read_28bit(void)
{
uint32_t x;
x = (u_buf[U_MASK(u_cons++)] ) >> 1;
x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 6;
x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 13;
x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 20;
return x;
}
static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
{
unsigned int todo = nr;
@@ -527,11 +536,9 @@ static unsigned int _wdata_decode_flux(timcnt_t *tbuf, unsigned int nr)
/* 255: Six bytes */
if ((uint32_t)(u_prod - u_cons) < 6)
goto out;
u_cons += 2; /* skip 255, 1 */
x = (u_buf[U_MASK(u_cons++)] ) >> 1;
x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 6;
x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 13;
x |= (u_buf[U_MASK(u_cons++)] & 0xfe) << 20;
u_cons += 2; /* skip 255, FLUXOP_NOFLUX */
ticks += _read_28bit();
continue;
}
ticks += x;