Hi Olivier
> I'm working on Hercules 16/12 fw support for FFADO ...
Ok.
> The async protocol was quite simple to get with a PCILynx card (not a lot
> of features).
:-) Nice.
> The iso protocol is quite strange because:
> 1) I don't see timestamps in the ISO packets ;
If that's true it wouldn't be the only device to omit explicit timestamps
from the iso packets.
> 2) some packets are "null", no data (only header) and it seems to be bad
> for timestamp managing.
Having packets containing no data like this is a regular feature of AV
firewire devices. The explanation is pretty simple. There are 8000 iso
cycles per second and a device can send at most one iso packet per cycle.
At (say) 48000 Hz this implies an average of 6 audio samples per firewire
packet (48000/8000). However, the audio clock is not locked to the firewire
bus cycle timer, so the "real" audio rate relative to the cycle timer will
be a little different from theory - 5.998 or 6.001 samples per cycle for
instance. To cater for the need to rubber-band the timing of samples,
devices will usually arrange to send a higher number of samples per packet
than is theoretically necessary - so for instance a device might send 8
samples per packet at 48 kHz. Obviously by doing this the device will
quickly run ahead of real time, so in order to "catch up" it sends the
occasional empty packet.
An empty packet is sent because according to some interpretations of the
firewire standard, a device registered for iso streaming must send exactly
one packet for iso cycle - even if the packet contains no real data. The
world certainly won't end if the empty packet isn't sent, but view it as
being a requirement for standards compliance.
By timing this correctly the long-term average sample-per-packet rate can be
made very close to the "real" sample rate relative to the cycle timer (5.998
or 6.001 in our example above).
I should also note that all this works in the other direction as well - when
sending data to the device you will send data with slightly more frames per
packet than technically required, with the odd empty frame sent to keep
everything in sync.
The need to extract sensible and accurate timing data from a situation which
includes the empty packets (which themselves aren't used for timestamping
since they contain no data) is precisely why FFADO runs a DLL (delay-locked
loop) to reconstruct the timing. Trying to do it any other way would be
tricky. Even so, the algorithm for the insertion of empty packets can
sometimes be dependent on the device, so if things don't work after an
initial try you may have to take a closer look at the relevant timings.
> All received packets are "recording" only data for example (dumpiso v3):
> 000025c0 04 03 02 01 c8 01 4a 1a 01 4e 07 a5 d7 00 00 00 |....?.J..N.??...|
> 000025d0 00 01 0c 00 00 70 00 56 a0 00 00 00 00 00 15 ff |.....p.V ......?|
> 000025e0 ff f9 00 00 15 ff ff e2 ff ff ff ff ff d3 00 00 |??...?????????..|
> 000025f0 07 00 00 40 00 00 01 ff ff c5 00 00 08 00 00 3e |...@...???.....>|
> 00002600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00002610 80 fc 00 00 80 ff 00 00 00 00 00 00 ff ff fa ff |.?...?......????|
> 00002620 ff b4 00 00 11 ff ff f6 ff ff b2 ff ff f3 ff ff |??...???????????|
> 00002630 a2 00 00 30 ff ff de 00 00 26 00 00 02 00 00 26 |?..0???..&.....&|
> 00002640 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00002650 80 fc 00 00 80 ff 00 00 00 00 00 00 ff ff f5 ff |.?...?......????|
> 00002660 ff c5 00 00 18 ff ff e8 00 00 33 ff ff aa 00 00 |??...???..3???..|
> 00002670 26 ff ff 7a ff ff d6 00 00 39 ff ff f2 00 00 10 |&??z???..9???...|
> 00002680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00002690 80 fc 00 00 80 ff 00 00 00 00 00 00 00 00 50 ff |.?...?........P?|
> 000026a0 ff de 00 00 3f ff ff ff 00 00 05 ff ff f8 00 00 |??..????...???..|
> 000026b0 1d 00 00 46 00 00 27 00 00 0b ff ff a9 00 00 5c |...F..'...???..\|
> 000026c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 000026d0 80 fc 01 00 80 ff 01 00 00 00 00 00 00 00 64 ff |.?...?........d?|
> 000026e0 ff d7 00 00 34 ff ff e5 00 00 04 ff ff ca ff ff |??..4???...?????|
> 000026f0 ed ff ff ec ff ff 96 ff ff e2 ff ff d4 00 00 00 |??????.??????...|
> 00002700 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00002710 80 fc 01 00 80 ff 01 00 00 00 00 00 00 00 41 00 |.?...?........A.|
> 00002720 00 0f ff ff aa 00 00 1c 00 00 2b ff ff ef 00 00 |..???.....+???..|
> 00002730 43 00 00 39 ff ff a4 00 00 56 00 00 35 00 00 13 |C..9???..V..5...|
> 00002740 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00002750 80 fc 01 00 80 ff 01 00 00 00 00 00 00 00 1d ff |.?...?.........?|
> 00002760 ff f7 ff ff d8 ff ff d2 ff ff a5 ff ff ed ff ff |????????????????|
> 00002770 eb 00 00 07 00 00 19 ff ff f5 ff ff f8 00 00 54 |?......??????..T|
> 00002780 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
> 00002790 80 fc 01 00 80 ff 01 00 00 00 00 00 01 02 03 04 |.?...?..........|
>
> It's a 48kHz data packet. It consists of:
> * a 8 byte header similar to a 2-quadlets CIP header:
> 00 70 00 56:
> - source node id=0
> - DBS = 70 = 7 * 0x40 bytes = 7 frames * 0x10 quadlets
Does this add up? Are there 7 frames per packet with each sized at 0x40
bytes? I ask because some manufacturers don't always use the CIP fields in
the standards-compliant way.
> Samples are grouped by 3 bytes.
By this I assume you mean that each sample is sent as a 24-bit integer.
That's the same as the MOTUs.
> First 36 bytes are the 12 analog channels.
> Then, I have 4 digital channels (coaxial and optical) which are on the 16
> next bytes (empty here because no input plugged), in 4 quadlets (Usually,
> the LSB bytes are null for 16 bit signal).
Ok. It would be interesting to try sending in an SPDIF signal and see where
it shows up.
> Finally I got "80 fc 01 00 80 ff 01 00" or "80 fc 00 00 80 ff 00 00", but
>I didn't figure out why and when it is "01" or "00"...
Do you know what the rest of these bytes mean?
It could be some kind of timing strobe. Or it may be where MIDI data is
stashed.
> The major issue with it is that sometime, (usually once over 8 at 48kHz),
> the packet is null, I mean no data: only a 8-byte header and the DBC is
> the same as the next (non-empty) coming packet one. When I'm running at
> 48kHz, the packets are actually sent at a frequency of 56 kHz to overcome
> this ...
See above - this seems perfectly natural to me. Note that the apparent
frequency of 56 kHz is not to "overcome" the null packet issue - it's a
fundamental requirement to ensure everything happens in sufficient time, as
explained above.
> and the StreamProcessor is verbose about it (putPacket "Instantanous...").
This *might* be due to your use of the cycle-at-arrival for timestamping.
This is essentially telling the stream processor that the sample was taken
by the ADC in the exact same cycle that it was delivered to you. That is,
that there is 0 latency. In the real world there is always some latency,
which you'll have to "fake" if there's no way to determine this from the
device itself.
It might be worth adding in a small constant offset to the cycle number you
send to the timestamp DLL. For example, if the packet arrives at cycle N,
try passing N-2 for instance (taking care to wrap correctly at 0).
Having said all that, this is all conjecture on my part. I haven't looked
into this aspect of the DLL handling all that much because it hasn't been
something I've needed on the devices I've worked on to date - all those
include timestamp information in the packet itself.
> Also, in the receive stream processor (HerculesReceiveStreamProcessor), I
> compute the timestamp based on the cycle got by the ISO receive handler
> function and I get some messages from StreamProcessor (putPacket) about
> "rather large TSP difference" and some warnings (after "null packets")
> from TimestampedBuffer (incrementFrameCounter) : "difference rather
> large...".
Having not seen the code or device it's a bit hard to make any sort of
comment here. However, at a wild guess are you attempting to timestamp even
the empty packets? If so I can imagine that this will confuse the
StreamProcessor.
Any empty iso packets should be more or less silently ignored by the
streaming system. They are expected (as above) but since they don't convey
any audio data the timestamp system should not be updated when they are seen.
> Have you ever encountered some similar devices? Is there a way to be clean
> with that? Perhaps I should use another computing of timestamps?
If you are not already utilising FFADO's built-in DLL-driven timestamp
system you should look into that. Not only does it make your job much
easier, its use is more or less required if your device is to fit in neatly
with the rest of the FFADO infrastructure.
Regards
jonathan