
#include "ads_manager.h"
#include "time_metrics.h"
#include "rtg_atomic.h"
#include "itc_triplebuffer.h"
//#include "itc_multibuffer.h"

#include "avb_driver.h"


#include <stdint.h>

#include <QCoreApplication>

#include <QTimer>
//#include <QThread>
#include <QVector>
#include <QLinkedList>

#include <QTimerEvent>

#include <QDebug>

static Ads1553Manager* managerInstance;

typedef itc_triplebuffer<avb_1553_data_buffer_t> b1553_mb_t;


typedef QVector<avb_1553_terminal_t*> term_v_t;
//static term_v_t term_v;

typedef struct {
  term_v_t term_v;
  bool tInUse[32];
  Ads1553TerminalStatus sts[32];
} term_db_t;

static term_db_t term_db;

Ads1553TerminalStatus::Ads1553TerminalStatus()
{
  memset(&d, 0, sizeof d);
}

const char *Ads1553TerminalStatus::name() const
{
  return d.rawT ? d.rawT->nickName : "?";
}

const char *Ads1553TerminalStatus::longName() const
{
  return d.rawT ? d.rawT->longName : "?";
}


typedef struct {
  Ads1553MessageStatus sts;
} msg_dynamic_sts_t;


class  Ads1553MsgPrivateContext {
public:
  b1553_mb_t mb;
  Ads1553MsgQ msg;
  itc_triplebuffer_register mbr;
  rtg_atom_t bc_emitted;
  ads_1553msg_t* msgDef;

  Ads1553MsgPrivateContext(const char* const name):
      mbr(name, mb),
      bc_emitted(false),
      msgDef(0)
  {
  }

  void setEmitted()
  {
    bc_emitted=true;
  }
  bool getResetEmitted()
  {
    rtg_atom_t r=rtg_atomic_exchange(&bc_emitted, 0);
    return r!=0;
  }
};

typedef QVector<Ads1553MsgPrivateContext*> msg_v_t;
static msg_v_t msg_v;

typedef QMap<unsigned int, msg_dynamic_sts_t*> dyn_msg_map_t;
typedef QVector<msg_dynamic_sts_t*> dyn_msg_vector_t;

static dyn_msg_map_t dyn_msg;
static dyn_msg_vector_t dyn_msg_v;


struct monitor_acq_buffer_t
{
  enum { buff_size_bytes=1024*1024 };
  enum { buff_size=buff_size_bytes/sizeof(ads_acq_data_t)};

  ads_acq_data_t buffer[buff_size];

  unsigned int pos;
  bool acquiring;
  bool updated;



  void add(Ads1553MsgQ* msg, avb_1553_mon_decoded_t& d)
  {
    if (!acquiring)
      return;

    buffer[pos].msg=msg;
    buffer[pos].decoded=d;
    ++pos;
    if (pos>=buff_size)
    {
      pos=buff_size;
      acquiring=false;
    }
    updated=true;
  }

  unsigned int remain_100()
  {
    if (pos==0)
      return 0;
    return static_cast<unsigned int>((double(pos)/double(buff_size))*100.0);
  }

};

static monitor_acq_buffer_t acq_buff;

class ConcreteAcqAnalyzer: public Ads1553AcqAnalyzer
{
public:
  monitor_acq_buffer_t* buff;

  unsigned int items() const { return buff->pos;}
  const ads_acq_data_t& get(unsigned int n) const
  {
    return buff->buffer[n];
  }
};

static ConcreteAcqAnalyzer acqAnalyzer;

Ads1553MessageStatus::Ads1553MessageStatus()
{
  memset(&d, 0, sizeof d);
}

const char *Ads1553MessageStatus::name() const
{
  return d.rawM ? d.rawM->nickName : "?";
}

const char *Ads1553MessageStatus::longName() const
{
  return d.rawM ? d.rawM->longName : "?";
}

unsigned int Ads1553Manager::numOfDynMessage() const
{
  return dyn_msg_v.size();
}

Ads1553MessageStatus *Ads1553Manager::messageStatusByIndex(unsigned int pos)
{
  return &(dyn_msg_v[pos]->sts);
}

static metricRegistered m1553Mng("ADS1553");

static metricRegistered mISR("IRS", 5000, 21000, &m1553Mng);
static metricRegistered mUPD("DataUpdater", 5000, 25000, &m1553Mng);
static metricRegistered mMsgAct("MsgAction", 5000, 21000, &m1553Mng);
static metricRegistered mMonUpd("MonitorUpdater", 0, 0, &m1553Mng);


typedef QMap<int, Ads1553MsgQ*> msg2_map_t;

static msg2_map_t msg2_map;

namespace {

#define CUSTOM_EVENT_BC (QEvent::User)
#define CUSTOM_EVENT_MON QEvent::Type((QEvent::User+1))

class MyCustomEvent: public QEvent
{
public:
  MyCustomEvent():
      QEvent(CUSTOM_EVENT_BC)
  {
  }

  static rtg_atom_t cookie;

  static rtg_atom_value_t inc()
  {
    return rtg_atomic_increment(&cookie);
  }
  static rtg_atom_value_t dec()
  {
    return rtg_atomic_decrement(&cookie);
  }
  static rtg_atom_value_t reset()
  {
    return rtg_atomic_exchange(&cookie, 0);
  }

  //static void operator delete(void*) {}

};
//unsigned long MyCustomEventMem[sizeof(MyCustomEvent)];

rtg_atom_t MyCustomEvent::cookie=0;

class MyCustomEventMonitor: public QEvent
{
public:
  MyCustomEventMonitor():
      QEvent(CUSTOM_EVENT_MON)
  {
  }

  static avb_1553_monitor_info_t* mdata;
  //static void operator delete(void*) {}

};

avb_1553_monitor_info_t* MyCustomEventMonitor::mdata;


static QObject* listener;

static void asynchSignalFromBus()
{
  if (listener)
  {
    if (MyCustomEvent::inc()==1)
    {
      m1553Mng.start();
      QCoreApplication::postEvent(listener, new MyCustomEvent);
    }
  }
}

static void asynchSignalFromMonitor(avb_1553_monitor_info_t* msg)
{
  if (listener)
  {
    MyCustomEventMonitor::mdata=msg;
    QCoreApplication::postEvent(listener, new MyCustomEventMonitor);
  }
}

}



struct frame_cx_t
{
    avb_1553_minor_frame_handler_t major_frame_handler;

    int minor_frame_counter;
};

static frame_cx_t frame_cx;

static ads_msg_scheduled_action_vector_t act_v;
static Ads1553Manager::run_sts_t run_sts;
static bool ads_monitor_only;

static bool mon_use_isr=false;

static IAvbDriver* avbDriver;

static void avb_1553_major_frame_handler(IAvbDriver* const drv, unsigned int frame_counter, avb_microseconds_t tt)
{
    frame_cx.minor_frame_counter=0;

    if (frame_cx.major_frame_handler)
        frame_cx.major_frame_handler(drv, frame_counter, tt);
}

static void avb_1553_minor_frame_handler(IAvbDriver* const /*drv*/, unsigned int /*frame_counter*/, avb_microseconds_t /*tt*/)
{
}

static void avb_1553_message_handler(IAvbDriver* const drv, bool ok, avb_1553_message_t* const msg, avb_microseconds_t tt)
{
  metricMeasure xx(mISR);

  ads_1553msg_t* const m=reinterpret_cast<ads_1553msg_t* const>(msg);

  if (!m)
    return;

  if (m->synch_routine)
  {
    m->synch_routine(drv, m, tt);
  }
  if (m->qmsg)
  {
    m->qmsg->setEmitted();

    if (m->desc.tr==avb_tx)
    {
      if (ok)
      {
        avb_1553_data_buffer_t* const b=m->qmsg->mb.back();
        drv->readDataBuffer(msg, b);
        m->qmsg->mb.push_back();
      }
    }
    else
    {
      avb_1553_data_buffer_t* const b=m->qmsg->mb.data_ready_test_and_pop();
      if (b)
      {
        //avb_1553_data_buffer_t* const b=&(mb->data);
        drv->writeDataBuffer(msg, b);
      }
    }

    asynchSignalFromBus();
  }
  /*
  if (m->async_routine)
  {
    asynchSignalFromBus();
  }
  */
}

Ads1553Manager::Ads1553Manager():
    tid(0),
    pending(0)
{
  setPollingPeriod(250);
  changeRunStatus(sts_null);
}

static IAvbDriver* avb_pointer;

void Ads1553Manager::setDriver(IAvbDriver* const d)
{
  avb_pointer=d;
}

void Ads1553Manager::create()
{
  managerInstance=new Ads1553Manager;
  listener=managerInstance;
  avbDriver=avb_pointer; //Avb_DriverCreate();

  if (mon_use_isr)
    avbDriver->set_mon_isr(asynchSignalFromMonitor);

  avbDriver->niceInterrupt(true);
}

Ads1553Manager& Ads1553Manager::instance()
{
  if (!managerInstance)
    create();
  return *managerInstance;
}

void Ads1553Manager::changeRunStatus(run_sts_t sts)
{
  if (run_sts==sts)
      return;

  run_sts=sts;
  Q_EMIT runStatusChanged(run_sts);
}


void Ads1553Manager::installTerminalList(avb_1553_terminal_t **const list)
{
  for(int i=0; list[i]; ++i)
  {
    term_db.term_v.push_back(list[i]);
    unsigned int rt=list[i]->adr;
    if (rt>=32)
      continue;
    term_db.sts[rt].d.valid=true;
    term_db.sts[rt].d.adr=rt;
    term_db.sts[rt].d.rawT=list[i];
    term_db.tInUse[rt]=true;
  }
  Q_EMIT terminalListChanged();
}

void Ads1553Manager::installMessages(ads_1553msg_t** const list)
{
  //configurazione dei messaggi gestiti
  for(int i=0; list[i]; ++i)
  {
    Ads1553MsgPrivateContext* m=new Ads1553MsgPrivateContext(list[i]->desc.nickName);
    m->msg.setRawInfo(list[i]);
    m->msg.setReadOnly(ads_monitor_only || list[i]->desc.tr);
    m->msg.setObjectName(list[i]->desc.nickName);
    if (true) //list[i]->desc.wc>=0)
    {
      if (list[i]->desc.wc>32)
      {
        qDebug()<<"WARNING: word count erros: "<<list[i]->desc.wc<<" ("<<list[i]->desc.nickName<<")";
        list[i]->desc.wc=32;
      }
      m->msg.setWordCount(list[i]->desc.wc);
    }
    else
      m->msg.setWordCount(0);

    m->msgDef=list[i];
    msg_v.push_back(m);

    list[i]->qmsg=m;

    if (list[i]->desc.type==avb_t_nop)
      continue;

    list[i]->desc.msgHandler=avb_1553_message_handler;

    msg_dynamic_sts_t* ds=new msg_dynamic_sts_t;
    ds->sts.d.cw.str.rt=list[i]->desc.target->adr;
    ds->sts.d.cw.str.tr=list[i]->desc.tr;
    ds->sts.d.cw.str.sa=list[i]->desc.sa;
    ds->sts.d.cw.str.wc=list[i]->desc.wc;
    ds->sts.d.code=ds->sts.d.cw.raw;
    ds->sts.d.rawM=&(list[i]->desc);
    ds->sts.d.valid=true;
    ds->sts.d.qMsg=&(m->msg);

    dyn_msg.insert(ds->sts.d.code, ds);
    dyn_msg_v.push_back(ds);
  }
  Q_EMIT messageListChanged();
  changeRunStatus(sts_ready);
}

void Ads1553Manager::setBeginOfMajorFrameHandler(avb_1553_major_frame_handler_t h)
{
    frame_cx.major_frame_handler=h;
}

void Ads1553Manager::installFrame(avb_1553_bc_message_t **const frame, unsigned int minor_frame_time_us)
{
    avb_1553_bc_frame_t f;
    f.minor_frame_time=minor_frame_time_us;
    f.msg=frame;
    f.oob_msg=0;
    int n=0;
    for(;frame[n]; ++n)
    {
    }

    avbDriver->set_begin_of_major_frame_handler(avb_1553_major_frame_handler);
    avbDriver->set_minor_frame_handler(avb_1553_minor_frame_handler);

    f.num_of_message=n;
    avbDriver->setUpBcFrame(f);
}

const char *Ads1553Manager::fromAdrToName(unsigned int rt)
{
    Ads1553MsgPrivateContext* m=0;
    foreach(m, msg_v)
    {
      const ads_1553msg_t* const x=m->msg.rawInfo();
      if (!x)
          continue;
      if (x->desc.target)
        if (x->desc.target->adr==rt)
            return x->desc.target->nickName;
      if (x->desc.target_rtrt_tx)
        if (x->desc.target_rtrt_tx->adr==rt)
            return x->desc.target_rtrt_tx->nickName;
    }
    return 0;
}

int Ads1553Manager::numOfTerminals() const
{
  return term_db.term_v.size();
}

avb_1553_terminal_t* Ads1553Manager::getTerminal(int id)
{
  return term_db.term_v[id];
}

int Ads1553Manager::numOfMessages() const
{
  return msg_v.size();
}

void Ads1553Manager::setPollingPeriod(int ms)
{
  if (ms!=0)
  {
    if (ms<10)
      ms=10;
    if (ms>5000)
      ms=5000;
  }

  polling_period=ms;
  mon_polling_period=2000/ms;
  if (mon_polling_period<2)
    mon_polling_period=2;

  mon_polling_period=1;

  if (polling_period)
    mUPD.period().set_deadline(polling_period*1000+1000);
  else
    mUPD.period().set_deadline(100*1000+1000);

  if (tid)
  {
    killTimer(tid);
    tid=0;
    if (polling_period)
      tid=startTimer(polling_period);
  }
}

void Ads1553Manager::run(bool run_forever)
{
  if (ads_monitor_only)
  {
      run_monitor();
      return;
  }

  if (!tid)
    tid=startTimer(polling_period);


  avbDriver->go(run_forever ? -1 : 1); //, only_mon ? IAvbDriver::mode_mon : IAvbDriver::mode_mon|IAvbDriver::mode_bc);
  avbDriver->go_mon();
}

void Ads1553Manager::run_monitor()
{
    if (!tid)
      tid=startTimer(polling_period);

    avbDriver->go_mon();
}

void Ads1553Manager::stop_monitor()
{
    avbDriver->halt_mon();
}

void Ads1553Manager::stop()
{
  avbDriver->stop();
}

void Ads1553Manager::shutdown()
{
  avbDriver->shutdown();
}

Ads1553MsgQ* Ads1553Manager::getMsgObj(int index)
{
  return &(msg_v[index]->msg);
}

Ads1553MsgQ *Ads1553Manager::getMsgObj(const char* const name)
{
  Ads1553MsgPrivateContext* m=0;
  QString n(name);
  foreach(m, msg_v)
  {
    if (QString(m->mbr.name())==n)
      return &m->msg;
  }
  return 0;
}

Ads1553MsgQ *Ads1553Manager::getMsgObj(int /*rt*/, int sa, int /*tr*/, int /*wc*/)
{
  return &(msg_v[sa]->msg);
}

void Ads1553Manager::acqStart()
{
  acq_buff.pos=0;
  acq_buff.updated=false;
  acq_buff.acquiring=true;
  Q_EMIT acqUpdated(acq_buff.acquiring, acq_buff.remain_100());
}

void Ads1553Manager::acqStop()
{
  acq_buff.acquiring=false;
  acq_buff.updated=false;
  Q_EMIT acqUpdated(acq_buff.acquiring, acq_buff.remain_100());
}

Ads1553AcqAnalyzer& Ads1553Manager::getAcqAnalyzer()
{
  acqAnalyzer.buff=&acq_buff;
  return acqAnalyzer;
}


#include <QFile>
#include <QDateTime>
static bool ads_monitor_save;

static QFile saveFile;

static void monitor_save(avb_1553_monitor_info_t* data)
{

    if (!ads_monitor_save)
    {
        if (saveFile.isOpen())
        {
            qDebug()<<"Monitor save file closed:";
            saveFile.close();
        }
        return;
    }
    if (data && data->size)
    {
        if (!saveFile.isOpen())
        {
            QString fname=QDateTime::currentDateTime().toString("dd-MM-yy-HH-mm-ss");
            fname=QString("bus1553_%1.rec").arg(fname);
            saveFile.setFileName(fname);
            saveFile.open(QIODevice::WriteOnly);
            qDebug()<<"Monitor save file:"<<fname;
        }
        {
            saveFile.write((char*)data->buffer, data->size*2);
            //saveFile.flush();
        }
    }
}

void Ads1553Manager::setMonitorSave(bool enable)
{
    ads_monitor_save=enable;
    if (!ads_monitor_save)
    {
        monitor_save(0);
    }
}

void Ads1553Manager::processMonitor()
{
  static int upd_delay;

  static avb_1553_monitor_info_t buff;

  if (!avbDriver)
    return;


  if (!avbDriver->getMonitorRawBuffer(&buff))
      return;

  monitor_save(&buff);
  metricMeasure xx(mMonUpd);

  bool run=(run_sts & sts_bc_running);
  unsigned int processed_msg=0;
  unsigned int fail_msg=0;

  unsigned char* buffer_end=(unsigned char*)&buff.buffer[(buff.size)];
  for(unsigned char* base=(unsigned char*)buff.buffer; base && base<buffer_end; )
  {
      avb_1553_mon_decoded_t decoded;

      if (!avbDriver->mon_decode_msg(&decoded, base))
      {
          qDebug()<<"Ads: Error decoding monitor msg";
          break;
      }
      ++processed_msg;

      base=(unsigned char*)decoded.next;

      unsigned int rt=decoded.rt;

      if (rt>=32)
        break;

      Ads1553TerminalStatus& s=term_db.sts[rt];

      if (!s.d.valid)
      {
        term_db.tInUse[rt]=true;
      }

      ++s.d.msg;

      if (decoded.no_response)
      {
          if (rt!=11)
            ++fail_msg;
        ++s.d.errs;
        ++s.d.nr;
      }
      else if (decoded.err)
      {
        ++s.d.errs;
        ++fail_msg;
      }

      if (decoded.tr)
        ++s.d.tx;
      else
        ++s.d.rx;
      s.d.rawErr=decoded.internal_eror_code;
      s.d.last_sw.raw=decoded.sts.raw;
      s.d.updated=true;
      s.d.valid=true;

      unsigned int code=decoded.cmd.raw;
      msg_dynamic_sts_t* ds=0;
      if (!dyn_msg.contains(code))
      {
        ds=new msg_dynamic_sts_t;
        ds->sts.d.cw=decoded.cmd;
        ds->sts.d.code=code;
        ds->sts.d.valid=true;
        ds->sts.d.qMsg=0;
        dyn_msg.insert(ds->sts.d.code, ds);
        dyn_msg_v.push_back(ds);
      }
      else
        ds=dyn_msg[code];
      if (!ds)
        continue;
      ds->sts.d.updated=true;
      ++ds->sts.d.msg;
      if (decoded.tr)
      {
        ds->sts.d.sw_valid=decoded.tx_sts_received;
      }
      else
        ds->sts.d.sw_valid=decoded.rx_sts_received;

      ds->sts.d.sw=decoded.sts;
      ds->sts.d.rawErr=decoded.internal_eror_code;
      ds->sts.d.tWc=decoded.wc;
      ds->sts.d.nr=decoded.no_response;
      if (decoded.err)
        ++(ds->sts.d.errs);
      if (decoded.bit_in_status_err)
        ++(ds->sts.d.exception_bits);

      if (decoded.wc>32)
        ds->sts.d.rawErr=0xFFFF;
      else
        for(unsigned int i=0; i<decoded.wc; ++i)
          ds->sts.d.lastContents[i]=decoded.data[i];

      ds->sts.d.delta_tt=decoded.timetag-ds->sts.d.last_tt;
      ds->sts.d.last_tt=decoded.timetag;

      acq_buff.add(ds->sts.d.qMsg, decoded);

      if (ds->sts.d.qMsg)
      {
        ds->sts.d.qMsg->execDataChecks(decoded);
      }
  }

  buff.processed_message=processed_msg;
  buff.total_message+=processed_msg;

  if (upd_delay>3)
  {
    upd_delay=0;
    Q_EMIT monitorUpdated(&buff);

    if (acq_buff.updated)
    {
      acq_buff.updated=false;
      Q_EMIT acqUpdated(acq_buff.acquiring, acq_buff.remain_100());
    }

  }
  ++upd_delay;


  if (run)
  {
    com_sts_t c;

    if (processed_msg==0 || !run)
      c=sts_comm_idle;
    else if (fail_msg==processed_msg)
      c=sts_comm_error;
    else if (fail_msg==0)
      c=sts_comm_ok;
    else
      c=sts_comm_some_errors;

    Q_EMIT commStatusChanged(c);
  }
}

Ads1553TerminalStatus *Ads1553Manager::terminalStatus(unsigned int adr)
{
  if (adr>=32)
    return 0;
  return &term_db.sts[adr];
}

void Ads1553Manager::timerEvent(QTimerEvent * t)
{
  static int msg_divisor;

  if (t->timerId()==tid)
  {
    if (!avbDriver)
        return;

    //avbDriver->simulateBcTick();

    Ads1553Manager::run_sts_t s=Ads1553Manager::sts_device_err;

    IAvbDriver::run_status_t rsts=avbDriver->getRunState();

    if (rsts==IAvbDriver::sts_halt)
        s=Ads1553Manager::sts_halted;
    else if (rsts==IAvbDriver::sts_bc_mon_run)
        s=Ads1553Manager::sts_bc_mon_running;
    else if (rsts==IAvbDriver::sts_bc_run)
        s=Ads1553Manager::sts_bc_running;
    else if (rsts==IAvbDriver::sts_mon_run)
        s=Ads1553Manager::sts_mon_running;

    changeRunStatus(s);

    if (pending)
    {
      if (msg_divisor<=0)
      {
        processMessages();
        msg_divisor=1;
        pending=0;
      }
      else
        --msg_divisor;
    }

    if (!mon_use_isr)
    {
      processMonitor();
    }


  }
}

static void sched_add(ads_msg_scheduled_action_vector_t& v, int delay, ads_simple_action_t act, void * arg)
{
  ads_msg_scheduled_action_t tmp;
  tmp.act=act;
  tmp.arg=arg;
  tmp.delay=delay;
  v.push_back(tmp);
}
static void sched_exec(ads_msg_scheduled_action_vector_t& v)
{
  for(ads_msg_scheduled_action_vector_t::iterator iter=v.begin(); iter!=v.end(); ++iter)
  {
    if ((*iter).delay>0)
      --((*iter).delay);
    if ((*iter).delay<=0)
    {
      (*iter).act((*iter).arg);
      v.erase(iter);
      break;
    }
  }
}

void Ads1553Manager::scheduleMessageAction(Ads1553MsgQ& msg, int num_msg_pending, ads_simple_action_t act, void * arg)
{
  sched_add(msg.sched_act, num_msg_pending, act, arg);
}

void Ads1553Manager::scheduleAction(int delay, ads_simple_action_t act, void* arg)
{
  sched_add(act_v, delay, act, arg);
}

void Ads1553Manager::processMessages()
{
  metricMeasure xx(mUPD);

  if (pending)
  {
    m1553Mng.stop();

    Ads1553MsgPrivateContext* m=0;
    foreach(m, msg_v)
    {
      if (ads_monitor_only || m->msg.isReadOnly())
      {
        avb_1553_data_buffer_t* const b=m->mb.data_ready_test_and_pop(); //m->mb.pop_front();
        if (b)
        {
          for(int i=0; i<32; ++i)
          {
            if (b->data[i]!=m->msg.data(i))
              m->msg.setDataNoSignal(i, b->data[i]);
          }

          m->msg.updateFromBus();
        }
      }
      else
      {
        m->msg.updateFromUser();
      }
    }
  }
}

IAvbDriver* Ads1553Manager::getDriver()
{
    return avbDriver;
}

void Ads1553Manager::writeDeviceBuffer(Ads1553MsgQ& msg, avb_1553_data_buffer_t& buffer)
{
  const ads_1553msg_t* const m=msg.rawInfo();
  if (!m)
    return;
  if (!avbDriver)
    return;
  if (!ads_monitor_only)
    avbDriver->writeDataBuffer(&(m->desc), &(buffer.data[0]));
}

void Ads1553Manager::customEvent(QEvent * evn)
{
  {
    if (evn->type()==CUSTOM_EVENT_BC)
    {
      MyCustomEvent::reset();

      metricMeasure xx(mMsgAct);

      ++pending;

      Ads1553MsgPrivateContext* m=0;
      foreach(m, msg_v)
      {
        bool exec=m->getResetEmitted();

        if (exec)
        {
          if (m->msgDef && m->msgDef->async_routine)
            m->msgDef->async_routine(&(m->msg));

        }

        if (!m->msg.isReadOnly() && m->msg.isPending())
        {
          m->msg.resetPending();
          avb_1553_data_buffer_t* const b=m->mb.back();

          for(int i=0; i<32; ++i)
            b->data[i]=m->msg.data(i);

          m->mb.push_back();
        }

        if (exec)
        {
          sched_exec(m->msg.sched_act);
        }
      }

      if (!polling_period)
        processMessages();
    }
    else if (evn->type()==CUSTOM_EVENT_MON)
    {
        processMonitor();
        //Q_EMIT monitorUpdated(MyCustomEventMonitor::mdata);
    }
  }
}

void Ads1553Manager::setMonitorOnly(bool enable)
{
    ads_monitor_only=enable;
}

bool Ads1553Manager::monitorOnly()
{
    return ads_monitor_only;
}

unsigned int Ads1553Manager::getTimetag()
{
  return avbDriver->getTimetag();
}

void Ads1553Manager::addCheck(Ads1553MsgQ & /*msg*/, Ads1553MessageCheck &chk)
{
  Q_EMIT checkAdded(chk);
}

Ads1553MsgQ::Ads1553MsgQ()
{
  modified=true;
  pending_out=false;
  messageModified.events_pending=0xFFFFFFFF;

  setWordCount(0);
  /*
  for(int i=0; i<32; ++i)
  {
    data_[i].setRef(&buffer[i]);
    data_[i].setParentMsg(this, i);
  }
  */
  for(int i=0; i<32; ++i)
    buffer[i]=0;

  force_refresh=true;
}

void Ads1553MsgQ::updateFromBus()
{
  ADS_EMIT(messageReceived(this));

  if (force_refresh)
  {
    messageModified.events_pending=0xFFFFFFFF;
    force_refresh=false;
  }

  if (messageModified.events_pending)
  {
    ADS_EMIT_MASK(messageModified, this);
    messageModified.events_pending=0;
  }
}

void Ads1553MsgQ::setData(int w, avb_1553_word_t value)
{
  buffer[w]=value;
  //messageModified.events_pending|=(1<<w);
  setModifiedMask(1<<w);
  updateFromBus();
}

void Ads1553MsgQ::setData32(int w, long value)
{
  buffer[w+1]=value;
  buffer[w]=value>>16;
  //messageModified.events_pending|=((1<<w)|(1<<(w+1)));
  setModifiedMask((1<<w)|(1<<(w+1)));

  updateFromBus();
}

void Ads1553MsgQ::setDataNoSignal(int w, avb_1553_word_t value)
{
  buffer[w]=value;
  //messageModified.events_pending|=(1<<w);
  setModifiedMask(1<<w);
}

void Ads1553MsgQ::setData32NoSignal(int w, long value)
{
  buffer[w+1]=value;
  buffer[w]=value>>16;
  //messageModified.events_pending|=((1<<w)|(1<<(w+1)));
  setModifiedMask((1<<w)|(1<<(w+1)));
}

void Ads1553MsgQ::addDataCheck(Ads1553MessageCheck& chk)
{
  dataChecks.push_back(&chk);
  Ads1553Manager::instance().addCheck(*this, chk);
}

void Ads1553MsgQ::execDataChecks(avb_1553_mon_decoded_t& decoded)
{
  Ads1553MessageCheck* d;
  foreach(d, dataChecks)
    d->execute(decoded);
}

bool Ads1553MsgQ::isReadOnly() const
{
  return m_readonly;
}

void Ads1553MsgQ::setReadOnly(bool v)
{
  m_readonly=v;
}

void Ads1553MsgQ::updateFromUser()
{
  updateFromBus();
}

ADS_SIGNAL_IMPLEMENT(Ads1553MsgQ, messageReceived, (Ads1553MsgQ* msg), (msg))
ADS_SIGNAL_IMPLEMENT(Ads1553MsgQ, messageModified, (Ads1553MsgQ* msg), (msg))


//Checks:

Ads1553MessageCheck::Ads1553MessageCheck()
{
  memset(&info, 0, sizeof info);
  info.name="?";
  info.description="?";
  info.lastFailReason="?";
}

ADS_SIGNAL_IMPLEMENT(Ads1553MessageCheck, updated, (Ads1553MessageCheck& chk), (chk))

