#include "testdatagenerator.h"
#include "qgrunsession.h"

#include <QDebug>

TestDataGenerator::TestDataGenerator(QObject *parent):
    QObject(parent),
    batch_counter(0)
{
}

TestDataGenerator::~TestDataGenerator()
{
}

void TestDataGenerator::initialize()
{
}

unsigned int TestDataGenerator::formatMarker() const
{
    return 0;
}

void TestDataGenerator::reinit()
{
    batch_counter=0;
}

unsigned int TestDataGenerator::generateNextBatch(void* /*data*/, unsigned int /*max_data_size*/, const RepFpgaProgramData* /*cfg*/)
{
    return 0;
}

unsigned int TestDataGenerator::generateNextBatchExt(void* /*header*/, void* /*data*/, unsigned int /*max_data_size*/, const RepFpgaProgramData* /*cfg*/)
{
    return 0;
}

bool TestDataGenerator::completed() const
{
    return true;
}

int TestDataGenerator::batchCounter() const
{
    return batch_counter;
}

bool TestDataGenerator::stop()
{
    return true;
}

QString TestDataGenerator::name() const
{
    return m_name;
}

//
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QDirIterator>

#include <QMessageBox>

#include "rep_fpga_interface.h"

//SAR
#define TV_HEADER_SPARE_DATA   5

class SarTestDataGenerator::Implementation
{
public:

    QString fname;

    QFile tv;
    bool completed;

    int sar_tv_batches;
    unsigned int sar_tv_size;
    int sar_tv_total_size;
    long start_offset;

    struct tv_t {
      unsigned int marker;
      unsigned int batches;
      unsigned int size;
      unsigned int spare[TV_HEADER_SPARE_DATA];
      //unsigned int data[1];
    };

    tv_t tvinfo;

    Implementation():
        completed(true),
        sar_tv_batches(0),
        sar_tv_size(0),
        sar_tv_total_size(0),
        start_offset(0)
    {
    }

    void loadSarVectorInfo()
    {

        tv.close();
        tv.setFileName(fname);
        if (!tv.open(QIODevice::ReadOnly))
        {
            sar_tv_batches=0;
#if 0
            QMessageBox::information(0, "SAR Vector",
               QString("Error openning SAR test vectro %1").arg(QFileInfo(tv.fileName()).absoluteFilePath()),
                QMessageBox::Ok);
#endif
        }
        sar_tv_total_size=tv.size();

        tv.read((char*)&tvinfo, sizeof tvinfo);
        sar_tv_batches=tvinfo.batches;
        sar_tv_size=tvinfo.size;
        start_offset=tv.pos();
    }
};

SarTestDataGenerator::~SarTestDataGenerator()
{
    p_.tv.close();
    delete &p_;
}

SarTestDataGenerator::SarTestDataGenerator(QObject *parent):
    TestDataGenerator(parent),
    p_(*new Implementation)
{
    p_.fname="HR_TEST_VECTOR.bin";
    m_name="SAR";
}


QString SarTestDataGenerator::fileName() const
{
    return p_.fname; //dbstv.fileName();
}
void SarTestDataGenerator::setFileName(const QString& name)
{
    if (name!=p_.fname)
    {
        p_.fname=name;
    }
}

void SarTestDataGenerator::initialize()
{
    reinit();
}

unsigned int SarTestDataGenerator::formatMarker() const
{
    return 0xA5A5A5A5UL;
}

void SarTestDataGenerator::reinit()
{
    TestDataGenerator::reinit();
    p_.loadSarVectorInfo();
    p_.completed=false;
}

unsigned int SarTestDataGenerator::generateNextBatch(void* data, unsigned int max_data_size, const RepFpgaProgramData* /*cfg*/)
{
    if (max_data_size<p_.sar_tv_size)
        return 0;
    qint64 rin=p_.tv.read((char*)data, p_.sar_tv_size);
    if (rin!=p_.sar_tv_size)
    {
        //p_.completed=true;
        batch_counter=0;
        p_.tv.seek(p_.start_offset);
        return 0;
    }
    ++batch_counter;
    return (unsigned int)rin;
}

bool SarTestDataGenerator::completed() const
{
    return p_.completed;
}

int SarTestDataGenerator::numberOfBatches() const
{
    return p_.sar_tv_batches;
}

//GM
#include "scsimulator.h"
#include "rep_fpga_interface.h"
#include <math.h>

class FakeRbmTestDataGenerator::Implementation
{
public:
    int pattern;
    int first_sweep;

    ScSimulator scSim;

    float* data;

    DbsTestDataGenerator* dbs;

    Implementation():
        pattern(0),
        first_sweep(0)
    {
    }
};

FakeRbmTestDataGenerator::~FakeRbmTestDataGenerator()
{
    delete &p_;
}

FakeRbmTestDataGenerator::FakeRbmTestDataGenerator(DbsTestDataGenerator *dbs, QObject *parent):
    TestDataGenerator(parent),
    p_(*new Implementation)
{
    p_.dbs=dbs;
    //p_.fname="HR_TEST_VECTOR.bin";
    m_name="RBM";
}


QString FakeRbmTestDataGenerator::imgFileName() const
{
    return ""; //p_.fname; //dbstv.fileName();
}
void FakeRbmTestDataGenerator::setImgFileName(const QString& /*name*/)
{
}

void FakeRbmTestDataGenerator::initialize()
{
    p_.dbs->initialize();
    reinit();
}

unsigned int FakeRbmTestDataGenerator::formatMarker() const
{
    if (p_.pattern==FakeRbmTestDataGenerator::vect)
        return p_.dbs->formatMarker();

    return TestDataGenerator::formatMarker();
}

void FakeRbmTestDataGenerator::reinit()
{
    //TestDataGenerator::reinit();
    p_.dbs->reinit();

    p_.scSim.reset();
    p_.first_sweep=0;
    //p_.completed=false;
}

unsigned int FakeRbmTestDataGenerator::generateNextBatch(void* data, unsigned int max_data_size, const RepFpgaProgramData* cfg)
{
    if (p_.pattern==FakeRbmTestDataGenerator::vect)
        return p_.dbs->generateNextBatch(data, max_data_size, cfg);

    static unsigned int p_time;

    RepFpgaSignal& s=*reinterpret_cast<RepFpgaSignal*>(data);

    if (max_data_size<sizeof s)
        return 0;

    //s.msgHeader=cfg->msgHeader;
    //s.msgHeader.len=sizeof s;
    s.fpgaHeader.dspHeader=cfg->dspHeader;
    s.fpgaHeader.acq_channel=RepFpgaSignalHeaderData::acq_ch_sum;
    s.fpgaHeader.signal_format=RepFpgaSignalHeaderData::sig_fmt_sweep;

    unsigned int rbins=s.fpgaHeader.dspHeader.rbins;
    if (rbins>2048)
        rbins=2048;

    unsigned int current_time=s.fpgaHeader.dspHeader.basicMode.btt.raw_timetag; //.d[raw_batchtag_t::tt_part];

    unsigned int delta_time=current_time-p_time;
    float dtime=delta_time*0.000064; //64us
    if (fabsf(dtime)>1)
        dtime=0.010;

    p_time=current_time;

    if (p_.first_sweep==0)
    {
        p_.first_sweep=1;
        return 0;
    }

    float reference=cfg->dspHeader.navData.platform_azimuth;
    float vx_nav=cfg->dspHeader.navData.vx;
    float vy_nav=cfg->dspHeader.navData.vy;

    //float vc=cosf(-reference);
    //float vs=sinf(-reference);

    float vmod=sqrtf(vy_nav*vy_nav+vx_nav*vx_nav);
    float gta=atan2(vy_nav, vx_nav);
    float dgta=(gta+reference);

    float vc=cosf(dgta);
    float vs=sinf(dgta);

    float vx=vmod*vs;
    float vy=vmod*vc;

    if (p_.pattern==FakeRbmTestDataGenerator::img)
    {
        p_.scSim.nextSweep(dtime, s.fpgaHeader.dspHeader.azimuth, vx, vy, rbins, &p_.data);

        for(unsigned int i=0; i<rbins; ++i)
        {
            float x=p_.data[i];
            s.data[i]=x;
        }
    }
    else if (p_.pattern==FakeRbmTestDataGenerator::pat1)
    {
        for(unsigned int r=0; r<2048; ++r)
        {
            s.data[r]=0;
            //sw2.payload.data[r]=c;
        }
    }
    else if (p_.pattern==FakeRbmTestDataGenerator::pat1)
    {
        for(unsigned int r=0; r<2048; ++r)
        {
            unsigned char c=(r+batch_counter*5) & 0xFF;
            s.data[r]=c;
            //sw2.payload.data[r]=c;
        }
    }
    else
    {
        for(int i=0; i<2048; ++i)
        {
            s.data[i]=160;
        }
    }

    ++batch_counter;

    return sizeof s;
}

bool FakeRbmTestDataGenerator::completed() const
{
    if (p_.pattern==FakeRbmTestDataGenerator::vect)
        return p_.dbs->completed();

    return false;
}

int FakeRbmTestDataGenerator::numberOfBatches() const
{
    //if (p_.pattern==FakeRbmTestDataGenerator::vect)
    //    return TestDataGenerator::numberOfBatches();
    return 0;
}


FakeRbmTestDataGenerator::Pattern FakeRbmTestDataGenerator::pattern() const
{
    return (FakeRbmTestDataGenerator::Pattern)p_.pattern;
}
void FakeRbmTestDataGenerator::setPattern(FakeRbmTestDataGenerator::Pattern p)
{
    p_.pattern=p;
}

//TGT

#include "scsimulator.h"
#include "rep_fpga_interface.h"
#include <math.h>

class TgtTestDataGenerator::Implementation
{
public:
    int pattern;
    int first_sweep;

    ScSimulator scSim;

    float* data;

    Implementation():
        pattern(0),
        first_sweep(0)
    {
    }
};

TgtTestDataGenerator::~TgtTestDataGenerator()
{
    delete &p_;
}

TgtTestDataGenerator::TgtTestDataGenerator(QObject *parent):
    TestDataGenerator(parent),
    p_(*new Implementation)
{
    //p_.fname="HR_TEST_VECTOR.bin";
    m_name="TGT";
}

void TgtTestDataGenerator::initialize()
{
    reinit();
}

void TgtTestDataGenerator::reinit()
{
    TestDataGenerator::reinit();
    p_.scSim.reset();
    p_.first_sweep=0;
    //p_.completed=false;
}

unsigned int TgtTestDataGenerator::generateNextBatch(void* data, unsigned int max_data_size, const RepFpgaProgramData* cfg)
{
    static unsigned int p_time;

    RepFpgaSimulationTargetsData& s=*reinterpret_cast<RepFpgaSimulationTargetsData*>(data);

    if (max_data_size<sizeof s)
        return 0;

    //s.msgHeader=cfg->msgHeader;
    //s.msgHeader.len=sizeof s;
    s.fpgaHeader.dspHeader=cfg->dspHeader;
    s.fpgaHeader.acq_channel=RepFpgaSignalHeaderData::acq_ch_sum;
    s.fpgaHeader.signal_format=RepFpgaSignalHeaderData::sig_fmt_sim_targets;

    unsigned int rbins=s.fpgaHeader.dspHeader.rbins;
    if (rbins>2048)
        rbins=2048;

    unsigned int current_time=s.fpgaHeader.dspHeader.basicMode.btt.raw_timetag; //.d[raw_batchtag_t::tt_part];

    unsigned int delta_time=current_time-p_time;
    float dtime=delta_time*0.000064; //64us
    if (fabsf(dtime)>1)
        dtime=0.010;

    p_time=current_time;

    unsigned int bar_number=s.fpgaHeader.dspHeader.bar_number;

    RepResultTargets& simTargets=s.simTargets;

    simTargets.tgt_num=0;


    float rng_scale=1;

    if (s.fpgaHeader.dspHeader.basicMode.range_scale_meters>=41*1875)
        rng_scale=8;
    if (s.fpgaHeader.dspHeader.basicMode.range_scale_meters>=21*1875)
        rng_scale=4;
    else if (s.fpgaHeader.dspHeader.basicMode.range_scale_meters>=11*1875)
        rng_scale=2;

    if ((batch_counter % 8)==0)
    {
        static float rng_nm=2;
        RepTgtInfo& t=simTargets.tgt[0];
        t.altitude_m=bar_number*304; //gc_math::feet_to_meters(1000);
        t.azimuth_rad=s.fpgaHeader.dspHeader.azimuth;
        t.bar=bar_number;
        t.range_m=(rng_nm*1875)*rng_scale; //gc_math::nm_to_meters(rng_nm);
        rng_nm+=1;
        if (rng_nm>9)
            rng_nm=2;

        simTargets.tgt_num=1;
    }
    ++batch_counter;

    return sizeof s;
}

bool TgtTestDataGenerator::completed() const
{
    return false;
}

int TgtTestDataGenerator::numberOfBatches() const
{
    return 0;
}


TgtTestDataGenerator::Pattern TgtTestDataGenerator::pattern() const
{
    return (TgtTestDataGenerator::Pattern)p_.pattern;
}
void TgtTestDataGenerator::setPattern(TgtTestDataGenerator::Pattern p)
{
    p_.pattern=p;
}



//DBS
static unsigned short flt_2_u16(float val)
{
  if(val >= 0.f)
  {
    val += 2.0f;
  }
  else
  {
    val += -2.0f;
  }
  unsigned int binfig = *((unsigned int*)&val);

  unsigned int sig    = (binfig >> 16) & 0x00008000U;
  unsigned int expChk = (binfig >> 28) & 0x00000007U;
  unsigned int redux  = (binfig >> 13) & 0x00007FFFU;
#if 0
  if(expChk != 0x00000004U)
  {
    volatile int bp = 123;
  }
#endif
  unsigned short res16  = (unsigned short)((sig | redux) & 0x0000FFFFU);

  return res16;
}

static unsigned int conv_sig_to_custom_float(float v1, float v2)
{
  {
    unsigned int I = flt_2_u16(v1);
    unsigned int Q = flt_2_u16(v2);
    I = ((I << 16) & 0xFFFF0000U) | (Q & 0x0000FFFFU);
    return I;
  }
}

class DsbFileNameIterator
{
public:
    QString base;
    QFile cacheFile;
    bool generateCache;

    DsbFileNameIterator():
        generateCache(false)
    {
    }

    void setBase(const QString& name)
    {
        base=name;
    }

    QString getSettingName(int n)
    {
        return QString("%1\\%2_sim_settings.dat").arg(base).arg(n);
    }
    QString getSignalName(int n)
    {
        return QString("%1\\%2sim_sig_in.dat").arg(base).arg(n);
    }
    bool readSetting(void* dst, int n)
    {
        memset(dst, 0, 512*4);
        QFile f(getSettingName(n));
        bool ok=f.open(QIODevice::ReadOnly|QIODevice::Text);
        if (!ok)
        {
            if (cacheFile.isOpen())
                cacheFile.close();
            return false;
        }
        unsigned int* d=reinterpret_cast<unsigned int*>(dst);
        for(int i=0; i<512; ++i)
        {
            QByteArray tmp=f.readLine();
            if (tmp.isEmpty())
                break;
            tmp=tmp.trimmed();
            unsigned int v=tmp.toUInt(0, 0);
            d[i]=v;
        }
        d[0]=0x5A5A5A5B;
        if (generateCache)
        {
            if (!cacheFile.isOpen())
            {
                cacheFile.setFileName("dbs_tcache.dat");
                cacheFile.open(QIODevice::WriteOnly);
                qDebug()<<"Open cache file"<<cacheFile.fileName();
            }
            if (cacheFile.isOpen())
                cacheFile.write((char*)dst, 510*4);
        }
        return true;
    }
    bool readSignal(void* dst, int n)
    {
        QFile f(getSignalName(n));
        bool ok=f.open(QIODevice::ReadOnly|QIODevice::Text);
        if (!ok)
        {
            if (cacheFile.isOpen())
                cacheFile.close();
            return false;
        }
        unsigned int* d=reinterpret_cast<unsigned int*>(dst);
        int i=0;
        for(i=0; i<100000000; ++i)
        {
            QByteArray tmp=f.readLine();
            if (tmp.isEmpty())
                break;
            tmp=tmp.trimmed();
            unsigned int v1=tmp.toUInt(0, 0);
            float f1=*reinterpret_cast<float*>(&v1);
            tmp=f.readLine();
            if (tmp.isEmpty())
                break;
            tmp=tmp.trimmed();
            unsigned int v2=tmp.toUInt(0, 0);
            float f2=*reinterpret_cast<float*>(&v2);
            d[i]=conv_sig_to_custom_float(f1,f2);
        }
        if (cacheFile.isOpen())
        {
            cacheFile.write((char*)dst, i*4);
        }
        return true;
    }
};

class DbsTestDataGenerator::Implementation
{
public:
    enum { dbs_tv_size=399864};

    QString fname;

    QFile dbstv;
    bool completed;
    bool is_dir;

    DsbFileNameIterator fIter;

    Implementation():
        completed(true)
    {
    }
};

DbsTestDataGenerator::~DbsTestDataGenerator()
{
    delete &p_;
}

DbsTestDataGenerator::DbsTestDataGenerator(QObject *parent):
    TestDataGenerator(parent),
    p_(*new Implementation)
{
    p_.is_dir=false;
    p_.fname="DBS-gabrifo-0h5m41s-0h6m34s_le.hds"; //"DBS-gabbiano-0h5m41s-0h6m34s_le.hds";
    m_name="DBS";
}


QString DbsTestDataGenerator::fileName() const
{
    return p_.fname; //dbstv.fileName();
}
void DbsTestDataGenerator::setFileName(const QString& name)
{
    if (name!=p_.fname)
    {
        p_.fname=name;
    }
}

void DbsTestDataGenerator::initialize()
{
    QFileInfo finfo(p_.fname);
    p_.is_dir=finfo.isDir();
    if (p_.is_dir)
    {
        p_.fIter.setBase(p_.fname);
    }
    else
    {
        p_.dbstv.setFileName(p_.fname); //"DBS-gabbiano-0h5m41s-0h6m34s_le.hds"); //"DBS-file_16_from_0h5m41s_to_0h6m34s.hds");
        p_.dbstv.open(QIODevice::ReadOnly);
    }
}

unsigned int DbsTestDataGenerator::formatMarker() const
{
    return 0x5771212L;
}

void DbsTestDataGenerator::reinit()
{
    TestDataGenerator::reinit();

    //p_.dbstv.reset();
    p_.dbstv.close();
    initialize();
    //p_.dbstv.setFileName(p_.fname);
    //p_.dbstv.open(QIODevice::ReadOnly);
    p_.completed=false;
}

unsigned int DbsTestDataGenerator::generateNextBatch(void* data, unsigned int max_data_size, const RepFpgaProgramData* /*cfg*/)
{
    qint64 rin=0;
    if (max_data_size<Implementation::dbs_tv_size)
        return 0;
    if (p_.is_dir)
    {
       bool ok=p_.fIter.readSetting(data, batch_counter);
       if (ok)
       {
           unsigned char* p=reinterpret_cast<unsigned char*>(data);
           ok=p_.fIter.readSignal(&p[510*4], batch_counter);
           if (ok)
               rin=Implementation::dbs_tv_size;
       }
    }
    else
      rin=p_.dbstv.read((char*)data, Implementation::dbs_tv_size);
    if (rin!=Implementation::dbs_tv_size)
    {
        p_.completed=true;
        return 0;
    }
    ++batch_counter;
    return (unsigned int)rin;
}

bool DbsTestDataGenerator::completed() const
{
    return p_.completed;
}


//Playback:

class RecTestVector
{
public:
    enum { k_max_size=128*1024*1024};
    FILE* fd;
    uint32_t* memory;
    unsigned int pos;
    unsigned int wsize;
    int size;
    unsigned int allocated_size;

    RecTestVector():
        fd(0),
        memory(0),
        pos(0),
        wsize(0),
        size(0),
        allocated_size(0)
    {
    }

    unsigned int lookup_marker(const char* pattern)
    {
        uint32_t marker0=0;
        uint32_t marker1=0;
        memcpy(&marker0, pattern, 4);
        memcpy(&marker1, &pattern[4], 4);

        if (pos>=wsize)
            pos=0;

        for(; pos<wsize; ++pos)
        {
            if ((memory[pos]==marker0) && (memory[pos+1]==marker1))
            {
                return (pos+=2);
            }
        }
        return 0;
    }

    unsigned int lookupSign(const char* str="SUM\0\0\0\0\0")
    {
        unsigned int n=lookup_marker(str/*"SUM\0\0\0\0\0"*/);
        if (n)
            return lookup_marker("SIGNSIGN");
        return 0;
    }

    unsigned int lookupHeader()
    {
        unsigned int n=lookup_marker("DSPHDRIN");
        if (n)
            return lookup_marker("DATADATA");
        return 0;
    }

    const char* init(const char* fname)
    {
        const char* file_name="E:\\tmp\\rec\\dbs.bin"; //"E:\\tmp\\rec\\rws_40nm.dat"
        if (fname)
            file_name=fname;
        if (fd)
        {
            fclose(fd);
        }

        fd=fopen(file_name, "rb"); //dsp_cfar_10nm_400kn_tgt80x32us_th25.dat", "rb");


        if (!fd)
        {
            qDebug()<<"PLAYBACK"<<"cannot open input file";
            return "cannot open input file";
        }

        fseek(fd, 0, SEEK_END);
        long expected_size=ftell(fd);

        fseek(fd, 0, SEEK_SET);

        qDebug()<<"PLAYBACK"<<"Size:"<<expected_size;

        if (expected_size<100)
        {
            fclose(fd);
            fd=0;
            return "invalid size";
        }
        unsigned int required_size=expected_size+32*4096*4;

        if ((required_size>allocated_size) && (allocated_size>0))
        {
            free(memory);
            memory=0;
        }
        if (memory==0)
        {
            memory=(uint32_t*)new char[required_size];
            allocated_size=required_size;
        }

        if (memory)
        {
            size=fread(memory, 1, expected_size, fd);
            if (size<0)
                size=0;
            wsize=size>>2;
        }
        fclose(fd);
        pos=0;

        return 0;
    }

    bool getNext(void** hdr, void** sum, int n_ch)
    {
        unsigned int h=lookupHeader();
        if (!h)
            return false;
        *hdr=&memory[h];

        if (n_ch<1)
            return true;
        unsigned int s=lookupSign();
        if (!s)
            return false;
         //*sum=&memory[s];
         sum[0]=&memory[s];

         if (n_ch<2)
             return true;
         s=lookupSign("GUARD\0\0\0");
         if (!s)
             return false;
         sum[1]=&memory[s];

         if (n_ch<3)
             return true;
         s=lookupSign("DAZ\0\0\0\0\0");
         if (!s)
             return false;
         sum[2]=&memory[s];

         if (n_ch<4)
             return true;
         s=lookupSign("DEL\0\0\0\0\0");
         if (!s)
             return false;
         sum[3]=&memory[s];

         return true;
    }
};

class PlaybackDataGenerator::Implementation
{
public:
    enum { dbs_tv_size=399864};

    QString fname;
    QString openFileName;

    int n_ch;

    //QFile dbstv;
    RecTestVector tv;

    bool completed;
    bool is_dir;

    DsbFileNameIterator fIter;

    Implementation():
        n_ch(1),
        completed(true)
    {
    }
};

PlaybackDataGenerator::~PlaybackDataGenerator()
{
    delete &p_;
}

PlaybackDataGenerator::PlaybackDataGenerator(QObject *parent):
    TestDataGenerator(parent),
    p_(*new Implementation)
{
    p_.is_dir=false;
    //p_.fname="E:/tmp/rec/dbs.bin"; //"DBS-gabrifo-0h5m41s-0h6m34s_le.hds"; //"DBS-gabbiano-0h5m41s-0h6m34s_le.hds";
    p_.fname="./playback/dbs-gabbiano-v2.dat";
    m_name="PLAYBACK";

    p_.n_ch=4;
    p_.fname="./playback/stt4_con_simulazione.dat";
}


QString PlaybackDataGenerator::fileName() const
{
    return p_.fname; //dbstv.fileName();
}
void PlaybackDataGenerator::setFileName(const QString& name)
{
    if (name!=p_.fname)
    {
        p_.fname=name;
    }
}

int PlaybackDataGenerator::ch() const
{
    return p_.n_ch;
}
void PlaybackDataGenerator::setCh(int n)
{
    if ((n<5) && (n>=0))
        p_.n_ch=n;
}

void PlaybackDataGenerator::initialize()
{
    p_.tv.init(p_.fname.toLatin1().constData());
#if 0
    QFileInfo finfo(p_.fname);
    p_.is_dir=finfo.isDir();
    if (p_.is_dir)
    {
        p_.fIter.setBase(p_.fname);
    }
    else
    {
        p_.dbstv.setFileName(p_.fname); //"DBS-gabbiano-0h5m41s-0h6m34s_le.hds"); //"DBS-file_16_from_0h5m41s_to_0h6m34s.hds");
        p_.dbstv.open(QIODevice::ReadOnly);
    }
#endif
}

unsigned int PlaybackDataGenerator::formatMarker() const
{
    return 0x5771212L;
}

void PlaybackDataGenerator::reinit()
{

    TestDataGenerator::reinit();

    const char* err_msg=p_.tv.init(p_.fname.toLatin1().constData());
    if (err_msg)
    {
        QMessageBox::warning(0, "PLAYBACK Error", err_msg);
    }
    //p_.dbstv.reset();
    //p_.dbstv.close();
    //initialize();
    //p_.dbstv.setFileName(p_.fname);
    //p_.dbstv.open(QIODevice::ReadOnly);
    p_.completed=false;
}

unsigned int PlaybackDataGenerator::generateNextBatchExt(void* /*header*/, void* /*data*/, unsigned int /*max_data_size*/, const RepFpgaProgramData* /*cfg*/)
{
    void* h;
    void* s[4];

    bool ok=p_.tv.getNext(&h, s, 0); //p_.n_ch);

    if (ok)
    {

    }
    return 0;
}

unsigned int PlaybackDataGenerator::generateNextBatch(void* data, unsigned int max_data_size, const RepFpgaProgramData* /*cfg*/)
{
    qint64 rin=0;

    void* h;
    void* s[4];

    bool ok=p_.tv.getNext(&h, s, p_.n_ch);

    if (ok)
    {
        const unsigned int max_pri=32; //64
        const unsigned int max_rbin=2048; //4096
        const unsigned int max_ssize=max_rbin*max_pri;
        unsigned int size=4*1024;

        ++batch_counter;

        uint32_t* raw=(uint32_t*)data;
        raw[0]=0x12345678UL;
        raw[8]=0x304F5645UL;
        memcpy(&raw[8+3], h, 4*1024);
        for(int i=0; i<p_.n_ch; ++i)
        {
            memcpy(&raw[1024+(max_ssize)*i], s[i], (max_ssize)*4); //memcpy(&raw[1024+(64*4096)*i], s[i], (3200*32)*4);
            size+=max_ssize*4; //64*4096*4;
            //size+=32*2048*4;
        }
        return size; //4*1024+((3200*32)*4);
    }

#if 0
    if (max_data_size<Implementation::dbs_tv_size)
        return 0;
    if (p_.is_dir)
    {
       bool ok=p_.fIter.readSetting(data, batch_counter);
       if (ok)
       {
           unsigned char* p=reinterpret_cast<unsigned char*>(data);
           ok=p_.fIter.readSignal(&p[510*4], batch_counter);
           if (ok)
               rin=Implementation::dbs_tv_size;
       }
    }
    else
      rin=p_.dbstv.read((char*)data, Implementation::dbs_tv_size);
    if (rin!=Implementation::dbs_tv_size)
    {
        p_.completed=true;
        return 0;
    }
    ++batch_counter;
#endif
    return (unsigned int)rin;
}

bool PlaybackDataGenerator::completed() const
{
    return p_.completed;
}
