This starts writes for larger sector sizes earlier, allowing large
sectors to be supported independent of the write_bc size.
It also allows some write latencies to be hidden by the time it takes to
receive the data.
This also makes better use of write_bc for buffering. Waiting for a full
sector means that space in write_bc is _not_ used for buffering
processing delays of the sector. Draining the sector data earlier frees
space earlier from the buffer.
[keirf: Minor tweaks and refactoring.]
In essence, we take the rotational position from index as a fraction
(start_ticks/max_ticks) and start the bitstream at the same position.
This is especially important for HFEv3 where the track data may be
elongated by opcodes.
Original commit message by ejona86:
hfe: Compensate for opcodes during seeking
This reduces the worst-case observed skew from 3 ms to 50 us. There is a
risk that in the future an opcode is added that is numerous and not
evenly distributed, but that seems unlikely and we'd need to swap to a
more complicated/advanced scheme.
Fluxes shorter than half a bitcell are definitely invalid and it
is reasonable to assume they are bogus. Instead of pushing a 1
bit for very short flux, instead merge the flux into the next.
Refs #827
This is a better guess than trying to account for, or totally
ignoring, opcode overhead every time we seek to a new track.
Note that this commit also initialises tracklen_ticks earlier, even
for regular HFE image files.
[keirf: commits squashed and commit messages amended]
fake_fired inserts an index pulse to avoid host-side timeouts. However,
the realtime options don't carry any risk of host-side timeouts because
the index pulses occur at the normal rate.
index-suppression=no causes behavior like write-drain=eot, since when
fake_fired is set during writing it also changes restart_pos. This
commit disables that behavior for write-drain=realtime, but not for
write-drain=instant which still carries timeout risk. Some users may be
depending on the implicit behavior.
This MCU runs timers on a 16-bit hardware timer. Since the next
timer deadline may be longer than 65535 ticks, we set a coarser
deadline to fire before the actual event: When this triggers,
we expect to set a fine deadline to run the actual timer handler.
The problem is that this coarse deadline is set 5ms early, and this
*also* overflows 65535 ticks at 18MHz. An assumption in the timer
arithmetic gets broken and we end up setting a coarse-grained timer
deadline way in the future. This breaks the 32-bit timebase (which
itself relies on somewhat timely timer to extrapolate from the 24-bit
systick hardware timer). And all random hell breaks loose.
The solution is simple: Set the coarse deadline only 1ms early.
Refs #808
1. This makes the DMA ring less lumpy and potentially quicker to fill
since the worst-case time values are reduced.
2. The tail value at the end of a sub-divided chain is guaranteed
to be greater than 2^14 sampleclk ticks. This should make it
easier to interrupt during the tail period to re-enable RDATA
output.
3. By detecting overflow at 2^15 ticks we prevent a hard overflow
at 2^16 ticks earlier in the {hfe,qd}_rdata_flux processing loop.
The motivation for this NFA work is the game Repton Thru Time for
the BBC Micro. An HFE dump of the original game disk has a long NFA
(>100ms) on Track 1.