MIMO cable and timestamps (raw ethernet)

With rx_streaming_samples.cc as a starting point, I created a new
usrp2::rx_sample_handler that simply buffers samples in memory. The
handler’s operator() is shown below. I need precise timing data between
receives, so it counts sample clock overflows to form a 64-bit time. To
make sure it was working as I expected, it predicts the next
metadata->timestamp according to the number of samples in the current
frame and the decimation. In the next frame, I compare the actual
timestamp to the expected timestamp and report any discrepancies. Once I
got my own bugs out and worked around what appears to be a startup
glitch, it’s been working fine and never reports a problem unless
there’s an overrun. Elsewhere I check rx_missing() so know when overruns
happen even if I don’t see an S go by.

Today I tried synchronizing a transmitter USRP2 and receiver USRP2 using
a MIMO cable. Now it’s reporting very frequent timestamp errors, but no
overruns:

Time error in frame 2. Off by -1073638088 ticks.
Time error in frame 20. Off by -1073897439 ticks.
Time error in frame 39. Off by 1258260742 ticks.
Time error in frame 40. Off by 8396679 ticks.
Time error in frame 57. Off by -8413060 ticks.
Time error in frame 76. Off by -171977540 ticks.
Time error in frame 94. Off by -12634786 ticks.
Time error in frame 95. Off by -2876 ticks.
Time error in frame 107. Off by 193028100 ticks.
Time error in frame 113. Off by -184639590 ticks.
Time error in frame 132. Off by -1079918709 ticks.
...

Just having the MIMO cable hooked up causes the problem. I doesn’t
matter whether I config_mimo() to set up one box with MC_WE_LOCK_TO_MIMO
and one with MC_PROVIDE_CLK_TO_MIMO or configure both to
MC_WE_DONT_LOCK. In either case it spews errors. If I disconnect the
MIMO cable, no time errors are reported.

I’m using gnuradio 3.3.0. Both USRP2s have u2_rev3-20100603.bin. One has
txrx_xcvr_raw_eth_20100608.bin and an xcvr2450, the other has
txrx_raw_eth_20100608.bin and a DBSRX.

Have I misunderstood something? Is there something more I need to do? Is
there a bug in my code? Any other thoughts or suggestions?

-Marc

bool operator()(const uint32_t *items, size_t numItems, const
usrp2::rx_metadata *metadata)

Oops. The code got cut off. Here’s the full routine. -Marc

bool operator()(const uint32_t *items, size_t numItems, const
usrp2::rx_metadata *metadata)
{
if (_numFrames == 0)
{
// The expected time prediction for the second frame is always
off by 19 ticks,
// suggesting that the first frame is messed up somehow.
// As a work-around, we just ignore the first frame as if it
never happened.
++_numFrames;
return true;
}

if (_numFrames == 1)
    _startingSampleClock32 = metadata->timestamp;
else
{
    if (metadata->timestamp != _expectedSampleClock32)
    {
        ++_numTimeErrors;
        fprintf (stdout, "Time error in frame %llu. Off by %d 

ticks.\n", _numFrames, metadata->timestamp - _expectedSampleClock32);
}
}
++_numFrames;
_expectedSampleClock32 = metadata->timestamp + numItems*_decimation;

size_t  numRemaining = _buffer.size() - _numSamples;
size_t  numToCopy = std::min(numItems, numRemaining);

memcpy(&_buffer[_numSamples], items, numToCopy*sizeof(_buffer[0]));
_numSamples += numToCopy;

if (_numSamples == _buffer.size())
{
    _endingSampleClock32 = metadata->timestamp + 

numToCopy*_decimation;
return false;
}
return true;
}