redhawksdr

Redhawk FEI sample rate tolerance check failure?


I'm building a Redhawk 2.1.2 FEI device and encountering a tolerance check failure when I try to do an allocation through the IDE (haven't tried python interface or anything). The request is for 8 MHz and I get a return value of 7999999.93575246725231409 Hz which is waaaay within the 20% tolerance, but I still get this error:

2017-12-24 11:27:10 DEBUG FrontendTunerDevice:484 -  allocateCapacity - SR requested: 8000000.000000  SR got: 7999999.935752
2017-12-24 11:27:10 INFO  FrontendTunerDevice:490 - allocateCapacity(0): returned sr 7999999.935752 does not meet tolerance criteria of 20.000000 percent

The offending code from frontendInterfaces/libsrc/cpp/fe_tuner_device.cpp:

// check tolerances
if( (floatingPointCompare(frontend_tuner_allocation.sample_rate,0)!=0) &&
    (floatingPointCompare(frontend_tuner_status[tuner_id].sample_rate,frontend_tuner_allocation.sample_rate)<0 || 
     floatingPointCompare(frontend_tuner_status[tuner_id].sample_rate,frontend_tuner_allocation.sample_rate+frontend_tuner_allocation.sample_rate * frontend_tuner_allocation.sample_rate_tolerance/100.0)>0 ))
{
    std::ostringstream eout;
    eout<<std::fixed<<"allocateCapacity("<<int(tuner_id)<<"): returned sr "<<frontend_tuner_status[tuner_id].sample_rate<<" does not meet tolerance criteria of "<<frontend_tuner_allocation.sample_rate_tolerance<<" percent";
    LOG_INFO(FrontendTunerDevice<TunerStatusStructType>, eout.str());
    throw std::logic_error(eout.str().c_str());
}

And the function from frontendInterfaces/libsrc/cpp/fe_tuner_device.h:

inline double floatingPointCompare(double lhs, double rhs, size_t places = 1){
    return round((lhs-rhs)*pow(10,places));
    /*if(round((lhs-rhs)*(pow(10,places))) == 0)
        return 0; // equal
    if(lhs<rhs)
        return -1; // lhs < rhs
    return 1; // lhs > rhs*/
}

I actually copied into a non-Redhawk C++ program that I use to test the devices interfaces and the checks pass. I broke everything out to find the difference and noticed that in Redhawk the sample rate being returned from the Device (or at least printed to the screen) is slightly different than the one outside Redhawk - by like a tiny fraction of a Hz:

// in Redhawk using cout::precision(17)
Sample Rate: 7999999.93575246725231409
// outside Redhawk using cout::precision(17)
Sample Rate: 7999999.96948242187500000

I don't know why there's a difference in the actual sample rates returned but in the Redhawk version it's just enough to make the second part of the check fail:

floatingPointCompare(7999999.93575246725231409,8000000.00000000000000000)<0
1

Basically because:

double a = 7999999.93575246725231409 - 8000000.00000000000000000; // = -0.06424753274768591
double b = pow(10,1); // = 10.00000000000000000
double c = a*b;       // = -0.6424753274 
double d = round(c);  // = -1.00000000000000000

So if a returned sample rate is less than the request by more than 0.049999 Hz then it will fail the allocation regardless of the tolerance %? Maybe I'm just missing something here.


Solution

  • There should be a document somewhere that describes this in detail but I went to the FMRdsSimulator device's source.

        // For FEI tolerance, it is not a +/- it's give me this or better.
    
        float minAcceptableSampleRate = request.sample_rate;
    
        float maxAcceptableSampleRate = (1 + request.sample_rate_tolerance/100.0) * request.sample_rate;
    

    So that should explain why the allocation was failing.