
#include "avb_driver.h"

#include "TS_drv.h"
#include "Int.h"
#include "VIFunc.h"

#include "time_metrics.h"

#include <QDebug>

#include <windows.h>

//#define USE_DDC_TIME_TAG_BUFFER

const avb_1553_message_t avb_frame_end_of_minor__={0};
const avb_1553_message_t avb_frame_end_of_major__={0};
const avb_1553_message_t avb_frame_skip_next_message__={0};

static IAvbDriver* avbDriverInstance=0;

static bool sim_rt[32];

extern void DdcSimulator_SimulateBcTick();
extern bool DdcSimulator_isSimulator();

template<typename T_> struct ddc_buffer_map_t
{
  enum { max_buff=250 };
  typedef T_ value_t;
  typedef T_* ptype_t;

  T_* db[max_buff];

  int add(T_* b)
  {
    for(int i=3; i<max_buff; ++i)
      if (db[i]==b)
        return i;
    for(int i=3; i<max_buff; ++i)
      if (db[i]==0)
      {
        db[i]=b;
        return i;
      }
    return 0;
  }

  int set(int pos, T_* b)
  {
    if (pos>=3 && pos<max_buff)
    {
      db[pos]=b;
      return pos;
    }
    return 0;
  }

  T_* fromId(int id)
  {
    if (id>=3 && id<max_buff)
      return db[id];
    return 0;
  }

  int fromDb(T_* b)
  {
    for(int i=3; i<max_buff; ++i)
      if (db[i]==b)
        return i;
    return 0;
  }
};

typedef ddc_buffer_map_t<avb_1553_data_buffer_t> db_map_t;
typedef ddc_buffer_map_t<avb_1553_message_t> msg_map_t;
typedef ddc_buffer_map_t<avb_1553_bc_message_t> frame_map_t;

//avb_1553_bc_message_t avb_1553_end_of_minor_frame;


#define DCALL(x_)   (logError( x_ ))

static S32BIT bc_isr(Device_p d, S16BIT p1, S16BIT p2);
static S32BIT mon_isr(Device_p d);

typedef union {
  uint16_t raw;
  struct {
    unsigned int wc: 5;
    unsigned int sa: 5;
    unsigned int tr: 1;
    unsigned int rt: 5;
  };
  CMD idea;
} cw_t;

/*
static CMD cv_cmd(avb_1553_message_t& msg, avb_1553_terminal_t& rt)
{
  cw_t tmp;
  tmp.wc=msg.wc;
  tmp.sa=msg.sa;
  tmp.tr=msg.tr ? 1 : 0;
  tmp.rt=rt.adr;

  return tmp.idea;
}
*/

static CMD ENCODE_CMD(int rt, int tr, int sa, int wc)
{
  CMD idea;
  idea.subadr=sa;
  idea.tadr=rt;
  idea.t_r=tr;
  idea.wcnt=wc;
  return idea;
}

//static DWORD WINAPI ThreadProc(void* param);

struct ddc_wrapper_t {
  int cardNo;

  Device_p pCrd;
  DRV_CONFIG dCfg;
  CARD_STATE st;
  IDEA_INFO info;
  Error_t err;

  char rtl_ver[1024];
  char driver_ver[1024];
  char part_no[1024];
  char rtl_core_ver[1024];

  bool frame_installed;

  unsigned num_msg;

  frame_map_t fmap;
  msg_map_t mmap;
  db_map_t bmap;

  MESSAGE ddc_msg[256];
  U16BIT frameList[1024];

  unsigned int bc_served_events;
  unsigned int mon_served_events;
  unsigned int rt_served_events;

  avb_1553_isr_t app_isr;
  avb_1553_monitor_isr_t app_mon_isr;

  HANDLE hEvent;
  HANDLE hTh;
  DWORD idThread;

  Error_t logError(Error_t e)
  {
    if (!e)
       return e;
    char buffer[1024];
    ddcGetErrorMessage(pCrd, e, buffer);
    qWarning()<<"DDC Error: "<<e<<" "<<buffer;

    return e;
  }


  bool init(int card_num=0)
  {
    cardNo=card_num;

    qDebug()<<"DDC: "<<"card="<<cardNo;

    for(int i=0; i<2; ++i)
    {
      err=DCALL(ddcResetCard(&pCrd, &dCfg, cardNo));
      if (err)
      {
        IdeaResetCard(cardNo, IDEA_BC_AND_MON);
        IdeaShutdown(cardNo);
      }
      if (!err)
        break;
    }
    if (err)
    {
      IdeaShutdown(cardNo);
      return false;
    }
    info=ddcGetIdeaInfo(pCrd);

    qDebug()<<"DDC: "<<info.part_number<<" ("<<info.card_type<<"), driver: "<<info.driver_ver<<", selft test ="<<info.self_test;

    err=DCALL(ddcIdeaVersion(pCrd, rtl_ver, driver_ver, part_no));

    qDebug()<<"DDC: P/N "<<part_no<<", RTL: "<<rtl_ver<<", Driver: "<<driver_ver;

    err|=DCALL(ddcIdeaCoreVersion(pCrd, rtl_core_ver));

    qDebug()<<"DDC: RTL Core Version: "<<rtl_ver;

    err|=DCALL(ddcCardState(pCrd, &st));

    if (err)
      return false;

    qDebug()<<"DDC: State at reset: "<<st.bcrt<<", "<<st.card;

    if (st.bcrt!=IDEA_HALTED)
    {
      qDebug()<<"DDC: card not HALTED, halting it...";
      err=DCALL(ddcHaltIdea(pCrd));
      qDebug()<<"DDC: card halt "<<(err ? "FAILED" : "PASSED");
    }

    //hEvent=::CreateEvent(0, FALSE, FALSE, 0);
    //hTh=::CreateThread(0, 0, ThreadProc, 0, 0, &idThread);
    //::SetThreadPriority(hTh, THREAD_PRIORITY_TIME_CRITICAL);

    DCALL(ddcDef_int_mask(pCrd, 0xFFFF));

    //Error_t(*usr_handler_p)(Device_p, S16BIT, S16BIT) =
    //        (Error_t(*)(Device_p, S16BIT, S16BIT)) bc_isr;

    err=DCALL(ddcSetBCRTEvent(pCrd, bc_isr)); //(Error_t (* __DECL)(Device_p, S16BIT, S16BIT))bc_isr));
    err=DCALL(ddcSetMONEvent(pCrd, mon_isr));

    err=DCALL(ddcDef_monitor_stack(pCrd, CYCLIC_STACK));
    err=DCALL(ddcSelect_bus(pCrd, YES, YES));

    return err==0;
  }

  unsigned int getRunState()
  {
    DCALL(ddcCardState(pCrd, &st));

    return st.card;
  }

  void setMinorFrameTime(S32BIT time)
  {
    qDebug()<<"MF Time:"<<time;
    err=DCALL(ddcDef_minor_frame_time(pCrd, time));
  }


  int go_bc(int times)
  {
     DCALL(ddcHalt_bcrt(pCrd));

     DCALL(ddcDef_int_mask_bcrt(pCrd, ~ ((1<<4)|(1<<5)|(1<<6))));

     ddcDef_int_mask_bcrt(pCrd, ~ ((1<<4)|(1<<5)|(1<<6)));

     qDebug()<<"DDC: run Bc...";
     DCALL(ddcRun_bc(pCrd, 1, times<1 ? IDEA_FOREVER : times));


     if (DdcSimulator_isSimulator())
     {
       for(int i=1; i<31; ++i)
         DCALL(ddcSet_busy(pCrd, i, NO));
     }

     return err;
  }
  int go_mon()
  {
      if (app_mon_isr)
        ddcDef_int_mask_monitor(pCrd, ~ (1<<14));
      else
        ddcDef_int_mask_monitor(pCrd, ~0);

      qDebug()<<"DDC: run Mon...";
      err=DCALL(ddcRun_mon(pCrd));

      return err;
  }

  int halt_mon()
  {
      qDebug()<<"DDC: HaltMon";
      err=DCALL(ddcHalt_mon(pCrd));

      return err;

  }

  int halt_bc()
  {
      qDebug()<<"DDC: HaltBcRt";
      err=DCALL(ddcHalt_bcrt(pCrd));

      return err;
  }

  int stop()
  {
      qDebug()<<"DDC: HaltIdea";
      err=DCALL(ddcHaltIdea(pCrd));

      return err;
  }

  void enableSkipMessage(bool enable=true)
  {
      ddcSkip_next_message(pCrd, enable ? IDEA_NO : IDEA_YES);
  }

  void checkIntrStatus(avb_1553_intr_status_t& sts)
  {
    ViInt32 i_tot, i_mon_host, i_mon_card, i_bc_host, i_bc_card;
    IdeaDbgOSGetCounts(cardNo, &i_tot, &i_mon_host, &i_mon_card, &i_bc_host, &i_bc_card);

    sts.raised=i_bc_card;
    sts.served=bc_served_events;
  }

  void shutdown()
  {
    if (pCrd)
    {
      ddcHaltIdea(pCrd);
      ddcShutDownIdea(&pCrd);
      pCrd=0;
    }
  }

  ~ddc_wrapper_t()
  {
    shutdown();
  }
};

static ddc_wrapper_t ddc_cx;

metricRegistered metricDdcDriverISR("DRV1553");
#define mISR metricDdcDriverISR

static metricRegistered mISRMON("DDC_MON_ISR", 0, 0, &mISR);
static metricRegistered mISRSched("DDC_BC_SCHED", 0, 0, &mISR);
static metricRegistered mISRSUnknown("DDC_BC_UNKNOW", 0, 0, &mISR);

typedef struct {
  bool niceInterrupt;

  unsigned int major_frame_count;
  unsigned int major_frame_last_tt;
  unsigned int minor_frame_count;
  unsigned int minor_frame_last_tt;
  unsigned int minor_frame_sequencer;

  avb_1553_major_frame_handler_t begin_of_major_frame_handler;
  avb_1553_major_frame_handler_t end_of_major_frame_handler;
  avb_1553_major_frame_handler_t end_of_minor_frame_handler;

} frame_exec_t;

#ifdef DDC_NICE_INTERRUPTS
static volatile frame_exec_t frame_exec={true};
#else
static volatile frame_exec_t frame_exec;
#endif

static void bc_schedule_nice_interrupt(Device_p d)
{
    metricMeasure xx(mISRSched);

    if (frame_exec.minor_frame_sequencer>9999)
        return;

   ++frame_exec.minor_frame_sequencer;
   for(; frame_exec.minor_frame_sequencer<250; ++frame_exec.minor_frame_sequencer)
   {
       U16BIT type=0x0080;
       U16BIT subtype=ddc_cx.frameList[frame_exec.minor_frame_sequencer];
       if (subtype==END_OF_MAJOR)
       {
         frame_exec.minor_frame_sequencer=10000;
         break;
       }
       else if (subtype==2)
       {
           ++frame_exec.minor_frame_sequencer;
           break;
       }

       {
           MESSAGE m;
           Error_t sts=ddcRead_message(ddc_cx.pCrd, subtype, &m);
           if (sts)
               continue;
           if (m.det_error!=NO_ERROR)
           {
               if (m.det_error==BIT_LIT_IN_STATUS)
                   type=0x82;
               else
                   type=0x81;
           }
           S16BIT itype=type | (subtype<<8);
           S16BIT param=0;
           bc_isr(d, itype, param);
       }
   }
}

static S32BIT bc_isr(Device_p d, S16BIT itype, S16BIT param)
{

  metricMeasure xx(mISR);

  U16BIT type=itype & 0x00FF;
  U16BIT subtype=(itype>>8) & 0x00FF;

  switch(type)
  {
  case 0x83:
    switch(subtype)
    {
    case 0x00FE: //end of major
    case 0x00FF: //end of minor
      break;
    }

  case 0x80: //succ. message
  case 0x81: //comm. error
  case 0x82: //bit set status
      ++ddc_cx.bc_served_events;
      if (subtype==1)
      {
        ++frame_exec.major_frame_count;
        frame_exec.minor_frame_count=0;
        frame_exec.minor_frame_sequencer=0;
        U32BIT tt_val;

#ifdef USE_DDC_TIME_TAG_BUFFER
        {
          static U32BIT tt_buff[256];
          S16BIT tt_count;
          Error_t sts=ddcRead_time_tags(ddc_cx.pCrd, tt_buff, &tt_count);
          if (sts==0 && tt_count>0)
            tt_val=tt_buff[0];
          else
            ddcRead_mon_rtc(ddc_cx.pCrd, &tt_val);
        }
#else
        ddcRead_mon_rtc(ddc_cx.pCrd, &tt_val);
#endif

        frame_exec.major_frame_last_tt=tt_val;
        if (frame_exec.begin_of_major_frame_handler)
          frame_exec.begin_of_major_frame_handler(avbDriverInstance, frame_exec.major_frame_count, tt_val);
      }
      else if (subtype==2)
      {
          U32BIT tt_val;

          ddcRead_mon_rtc(ddc_cx.pCrd, &tt_val);
          frame_exec.minor_frame_last_tt=tt_val;

          ++frame_exec.minor_frame_count;
          if (frame_exec.niceInterrupt)
            bc_schedule_nice_interrupt(d);

          if (frame_exec.end_of_minor_frame_handler)
            frame_exec.end_of_minor_frame_handler(avbDriverInstance, frame_exec.minor_frame_count, tt_val);
      }
      else
      {
        avb_1553_message_t* msg=ddc_cx.mmap.fromId(subtype);
        if (msg)
        {
          U32BIT tt_val;
          ddcRead_mon_rtc(ddc_cx.pCrd, &tt_val);

          bool ok= (type==0x80);

          if (msg->msgHandler)
              msg->msgHandler(avbDriverInstance, ok, msg, tt_val);
        }
      }
      break;
  default:
      {
          metricMeasure xx(mISRSUnknown);
      }
      break;
  }

  return 0;
}


static S32BIT mon_isr(Device_p d)
{

  metricMeasure xx(mISRMON);

  ++ddc_cx.mon_served_events;

  if (ddc_cx.app_mon_isr)
      ddc_cx.app_mon_isr(0);

  return 0;
}


class AvbDDCDriver: public IAvbDriver
{
public:
  AvbDDCDriver()
  {
    ddc_cx.init();
  }
  virtual ~AvbDDCDriver()
  {
    ddc_cx.shutdown();
  }

  virtual bool initialize()
  {
    return false;
  }

  virtual avb_1553_intr_status_t getIntrStatus()
  {
    avb_1553_intr_status_t sts;
    ddc_cx.checkIntrStatus(sts);
    sts.major_frames=frame_exec.major_frame_count;
    sts.major_frame_tt=frame_exec.major_frame_last_tt;
    return sts;
  }

  virtual bool go(int times)
  {
    if (!ddc_cx.frame_installed)
      return false;
    return ddc_cx.go_bc(times)==0;
  }
  virtual bool stop()
  {
      return ddc_cx.halt_bc()==0;
  }
  virtual bool go_mon()
  {
      return ddc_cx.go_mon()==0;
  }
  virtual bool halt_mon()
  {
      return ddc_cx.halt_mon()==0;
  }

  virtual bool setUpMessages(unsigned int num_of_message, const avb_1553_message_t *const msg_table)
  {
    return false;
  }

  unsigned int calcTime(unsigned t, unsigned int wc)
  {
      if (t)
          return t;
      return (wc+4)*20+25;
  }

  virtual bool setUpBcFrame(avb_1553_bc_frame_t& frame)
  {
    static INJ_ERR kInjErr;

#ifdef USE_DDC_TIME_TAG_BUFFER
    static MESSAGE msgBeginOfFrame={IDEA_NOP, ENCODE_CMD(1, 0, 1, 1), ENCODE_CMD(1, 0, 1, 1), 50, 1, 1, IDEA_BUS_A, IDEA_IMR_TIME_TAG, IDEA_IMR_INT_ON_END_OF_MESSAGE, &kInjErr};
#else
    static MESSAGE msgBeginOfFrame={IDEA_NOP, ENCODE_CMD(1, 0, 1, 1), ENCODE_CMD(1, 0, 1, 1), 50, 1, 1, IDEA_BUS_A, IDEA_IMR_NO_OPERATION, IDEA_IMR_INT_ON_END_OF_MESSAGE, &kInjErr};
#endif
    static MESSAGE msgEndOfMinor={IDEA_NOP, ENCODE_CMD(1, 0, 1, 1), ENCODE_CMD(1, 0, 1, 1), 50, 1, 1, IDEA_BUS_A, IDEA_IMR_NO_OPERATION, IDEA_IMR_INT_ON_END_OF_MESSAGE, &kInjErr};

    ddc_cx.num_msg=0;
    unsigned int N=frame.num_of_message;

    bool end_of_major_find=false;

    for(int i=0; i<32; ++i)
        sim_rt[i]=0;

    ddc_cx.logError(ddcDef_message(ddc_cx.pCrd, 1, &msgBeginOfFrame));
    ddc_cx.logError(ddcDef_message(ddc_cx.pCrd, 2, &msgEndOfMinor));

    ddc_cx.frameList[0]=1;
    unsigned int fpos=1;

    for(unsigned int i=0; i<N; ++i, ++fpos)
    {
      avb_1553_bc_message_t* bc_msg_p=frame.msg[i];
      if (!bc_msg_p)
          break;

      ++ddc_cx.num_msg;

      avb_1553_bc_message_t& bc_msg=*bc_msg_p;

      avb_1553_message_t* msg=bc_msg.msg;

      if (msg==&avb_frame_end_of_minor__)
      {
          qDebug()<<"F["<<i<<"] END OF MINOR";

          ddc_cx.frameList[fpos]=2;
          ++fpos;
          ++ddc_cx.num_msg;

          ddc_cx.frameList[fpos]=IDEA_END_OF_MINOR;
          continue;
      }
      if (msg==&avb_frame_end_of_major__)
      {
          qDebug()<<"F["<<fpos<<"] END OF MAJOR";

          ddc_cx.frameList[fpos]=2;
          ++fpos;
          ++ddc_cx.num_msg;
          ddc_cx.frameList[fpos]=IDEA_END_OF_MAJOR;
          end_of_major_find=true;
          continue;
      }

      int bc_i=ddc_cx.fmap.fromDb(&bc_msg);
      if (bc_i)
      {
          qDebug()<<"F["<<fpos<<"]="<<bc_i;

          ddc_cx.frameList[fpos]=bc_i;
          continue;
      }

      bc_i=ddc_cx.fmap.add(&bc_msg);


      bc_msg.avbReserved_=bc_i;

      MESSAGE& dm=ddc_cx.ddc_msg[bc_i];

      ddc_cx.frameList[fpos]=bc_i;

      qDebug()<<"F["<<fpos<<"] NEW MESSAGE: "<<bc_i<<" "<<msg->nickName;

      memset(&dm, 0, sizeof dm);

      dm.inj_error_ptr=&kInjErr;

      dm.first_intermessage_routine=IDEA_IMR_NO_OPERATION;
      dm.second_intermessage_routine=IDEA_IMR_NO_OPERATION;

      dm.first_intermessage_routine=(msg->type==avb_t_nop_skip_next) ? IDEA_IMR_SKIP_NEXT : IDEA_IMR_NO_OPERATION;
      dm.second_intermessage_routine=bc_msg.interrupt ? IDEA_IMR_INT_ON_END_OF_MESSAGE : IDEA_IMR_NO_OPERATION;


      if (!msg || !msg->target)
      {
          qDebug()<<"M["<<bc_i<<"] IDEA NOP";

          dm.comm_type=IDEA_NOP;
          dm.time_to_next_message=calcTime(bc_msg.time_to_next, 10);
          dm.cmd_1.subadr=1;
          dm.cmd_1.tadr=1;
          dm.cmd_1.wcnt=10;
          dm.cmd_1.t_r=0;
          dm.cmd_2=dm.cmd_1;
          continue;
      }

      if (msg->msgHandler && !frame_exec.niceInterrupt)
        dm.second_intermessage_routine=IDEA_IMR_INT_ON_END_OF_MESSAGE;

      dm.cmd_1.subadr=msg->sa;
      dm.cmd_1.tadr=msg->target->adr; //msg->tr==avb_tx ? msg->src->adr : msg->dst->adr;
      dm.cmd_1.t_r=msg->tr==avb_tx ? 1 : 0;
      dm.cmd_1.wcnt=msg->wc>=32 ? 0 : msg->wc;
      dm.cmd_2=dm.cmd_1;

      if (msg->target->mode==avb_term_simulated)
          sim_rt[msg->target->adr]=true;

      if (msg->target->mode==avb_term_disabled || msg->type==avb_t_nop || msg->type==avb_t_nop_skip_next)
          dm.comm_type=IDEA_NOP;
      else
        dm.comm_type=(msg->sa==0 || msg->sa==31) ? IDEA_MODE : ( (msg->tr==avb_tx) ? TRANSMIT : RECEIVE);

      dm.time_to_next_message=calcTime(bc_msg.time_to_next, msg->wc);

      dm.bus=bc_msg.bus==avb_bus_B ? BUS_B : BUS_A;

      qDebug()<<"M["<<bc_i<<"] ct="<<dm.comm_type<<" CMD1: "<<dm.cmd_1.tadr<<"-"<<dm.cmd_1.t_r<<"-"<<dm.cmd_1.subadr<<"-"<<dm.cmd_1.wcnt;

      int msg_i=ddc_cx.mmap.fromDb(msg);
      if (msg_i)
      {
          qDebug()<<"M["<<bc_i<<"] DB: "<<msg_i;

          dm.data_table_no=msg_i;
          dm.last_data_table_no=dm.data_table_no;

          ddc_cx.logError(ddcDef_message(ddc_cx.pCrd, bc_i, &dm));
          continue;
      }

      msg_i=ddc_cx.mmap.add(msg);

      msg->avbReserved_=msg_i;

      qDebug()<<"M["<<bc_i<<"] NEW DB: "<<msg_i<<" size="<<msg->wc;

      ddc_cx.logError(ddcDef_table_size(ddc_cx.pCrd, msg_i, msg->wc));

      dm.data_table_no=msg_i;
      dm.last_data_table_no=msg_i;

      ddc_cx.logError(ddcDef_message(ddc_cx.pCrd, bc_i, &dm));
    }


    if (!end_of_major_find)
    {
        ddc_cx.frameList[ddc_cx.num_msg]=2;
        ++ddc_cx.num_msg;
        ddc_cx.frameList[ddc_cx.num_msg]=IDEA_END_OF_MAJOR;
        ++ddc_cx.num_msg;
    }
    ++ddc_cx.num_msg; //the default major frame begin message

    ddc_cx.setMinorFrameTime(frame.minor_frame_time);

    qDebug()<<"Def Frame: "<<ddc_cx.num_msg;
    for(unsigned int n=0; n<ddc_cx.num_msg; ++n)
        qDebug()<<"  "<<n<<": "<<ddc_cx.frameList[n];

    ddc_cx.logError(ddcDef_frame(ddc_cx.pCrd, ddc_cx.num_msg, ddc_cx.frameList));

    ddc_cx.setMinorFrameTime(frame.minor_frame_time);

    for(int i=1; i<30; ++i)
        if (sim_rt[i])
        {
            static RT_DEFS rt;
            rt.inj_error=&kInjErr;
            ddc_cx.logError(ddcDef_emulate_rt(ddc_cx.pCrd, i, IDEA_YES));
            ddc_cx.logError(ddcDef_rt(ddc_cx.pCrd, i, &rt));
        }
        else
            ddc_cx.logError(ddcDef_emulate_rt(ddc_cx.pCrd, i, IDEA_NO));

    ddc_cx.frame_installed=true;

    return true;
  }

  run_status_t getRunState()
  {
      switch(ddc_cx.getRunState())
      {
      default:
          return sts_halt;
      case RUN_BCRT_MONITOR_STATE:
          return sts_bc_mon_run;
      case RUN_MONITOR_STATE:
          return sts_mon_run;
      case RUN_BCRT_STATE:
          return sts_bc_run;
      }
  }

  void set_isr(avb_1553_isr_t isr)
  {
      ddc_cx.app_isr=isr;
  }

  void set_mon_isr(avb_1553_monitor_isr_t isr)
  {
      ddc_cx.app_mon_isr=isr;
  }

  void enableMonitorIsr(bool enable)
  {
      if (enable)
        ddcDef_int_mask_monitor(ddc_cx.pCrd, ~(1<<14));
      else
        ddcDef_int_mask_monitor(ddc_cx.pCrd, 0xFFFF);

  }
  bool getMonitorRawBuffer(avb_1553_monitor_info_t *const b)
  {
      static S16BIT buffer[64*1024];
      S16BIT count=(S16BIT)sizeof(buffer)/sizeof(S16BIT);
      S16BIT messages=sizeof(buffer)/(40*sizeof(S16BIT));

      ddc_cx.err=ddc_cx.logError(ddcRead_mon_stack_part(ddc_cx.pCrd, buffer, &count, &messages));
      if (!b)
          return false;
      b->size=count;
      b->buffer=(avb_1553_word_t*)buffer;

      if (ddc_cx.err)
          return false;
      return true;
  }

  void writeSyncWord(avb_1553_word_t w)
  {
      ddcWrite_mode_data(ddc_cx.pCrd, 0, 17, w);
  }

  bool enableSkipMessage(bool enable)
  {
      ddc_cx.enableSkipMessage(enable);
      return false;
  }

  int getLastDriverError()
  {
      return ddc_cx.err;
  }
  const char* const getDriverErrrorMessage(int error_code)
  {
      static char tmp[1024];
      ddcGetErrorMessage(ddc_cx.pCrd, ddc_cx.err, tmp);
      return tmp;
  }

  bool mon_decode_msg(avb_1553_mon_decoded_t * const decoded, void * const buffer)
  {
      MON_MSG msg;

      memset(decoded, 0, sizeof *decoded);

      Error_t err=ddcDecode_mon_message(ddc_cx.pCrd, (U16BIT*)buffer, &msg);
      if (err)
          return false;
      bool c1=msg.comm_type==RECEIVE || msg.comm_type==MODE || msg.error_inf.illegal==YES;

      decoded->invalid=msg.error_inf.illegal==YES;
      decoded->modecode=msg.comm_type==MODE;
      decoded->bus=msg.bus==BUS_A ? 0 : 1;
      decoded->broadcast=msg.broadcast==YES;

      decoded->cmd.raw=c1 ? msg.cmd_1 : msg.cmd_2;
      decoded->rx_sts_received=msg.stat_r_flag==1;
      decoded->tx_sts_received=msg.stat_t_flag==1;

      decoded->sts.raw=c1 ? msg.rx_status : msg.tx_status;

      decoded->rtrt_tx_cmd.raw=!c1 ? msg.cmd_1 : msg.cmd_2;
      decoded->rtrt_tx_sts.raw=!c1 ? msg.rx_status : msg.tx_status;

      //decoded->data=(avb_1553_word_t*)msg.data_buf;
      decoded->next=msg.next_msg;
      decoded->timetag=msg.rtc;
      decoded->wc=msg.word_count;

      for(int w=0; w<msg.word_count; ++w)
        decoded->data[w]=(avb_1553_word_t)msg.data_buf[w];

      decoded->rt=c1 ? msg.s_cmd_1.tadr : msg.s_cmd_2.tadr;
      decoded->err=msg.error==YES ? true : false;
      decoded->sa=c1 ? msg.s_cmd_1.sadr : msg.s_cmd_2.sadr;
      decoded->tr=c1 ? msg.s_cmd_1.tr : msg.s_cmd_2.tr;

      decoded->internal_eror_code=msg.error_inf.code;

      if (decoded->err)
      {
        decoded->no_response=msg.error_inf.type==TYPE_NO_RESPONSE;
        decoded->bit_in_status_err=msg.error_inf.tx_status!=NO_ERROR || msg.error_inf.tx_status!=NO_ERROR;
      }

      return true;
  }

  virtual void simulateBcTick()
  {
    DdcSimulator_SimulateBcTick();
  }

  virtual bool readDataBuffer(avb_1553_message_t* const msg, void* const dst, unsigned int wc)
  {
    if (wc>32)
      return false;
    S16BIT w= (S16BIT) ((wc==0) ? msg->wc : wc);
    ddcRead_data(ddc_cx.pCrd, msg->avbReserved_, (S16BIT*)dst, w);
    return true;
  }

  virtual bool writeDataBuffer(const avb_1553_message_t* const msg, void* const src, unsigned int wc=0)
  {
    if (wc>32)
      return false;
    S16BIT w= (S16BIT) ((wc==0) ? msg->wc : wc);
    ddcWrite_data(ddc_cx.pCrd, msg->avbReserved_, (S16BIT*)src, w, 1);
    return true;
  }

  virtual void set_begin_of_major_frame_handler(avb_1553_major_frame_handler_t handler)
  {
    frame_exec.begin_of_major_frame_handler=handler;
  }

  virtual void set_minor_frame_handler(avb_1553_major_frame_handler_t handler)
  {
    frame_exec.end_of_minor_frame_handler=handler;
  }

  virtual void set_end_of_frame_handler(avb_1553_major_frame_handler_t handler)
  {
    frame_exec.end_of_major_frame_handler=handler;
  }

  virtual avb_microseconds_t getTimetag()
  {
    U32BIT tt_val;
    ddcRead_mon_rtc(ddc_cx.pCrd, &tt_val);
    return tt_val;
  }

  virtual void niceInterrupt(bool enable)
  {
      frame_exec.niceInterrupt=enable;
  }
  virtual const char* const getDeviceName()
  {
      return ddc_cx.part_no;
  }
};


IAvbDriver* Avb_DriverCreate()
{
  return avbDriverInstance=new AvbDDCDriver;
}

IAvbDriver::~IAvbDriver()
{
}
