
#define DDC_IDEA_SIMULATOR

#define AVB_1553_REAL_DEVICE

#ifndef AVB_1553_REAL_DEVICE

#include "TS_drv.h"
#include "Int.h"
#include "Mt.h"
#include "BC.h"

//#include <QThread>
//#include <QDebug>

//#include "time_metrics.h"
#include <stdint.h>

#ifndef WINVER
#define WINVER 0x501
#endif

#include <windows.h>


class SmallMimicDevice
{
public:
  struct ddc_mem_t
  {
    unsigned long long align;

    unsigned long tt_base;
    unsigned long intr_raised;

    unsigned long long spare[64];

    uint16_t ctrl[1024];

    unsigned long long spare2[64];

    uint16_t mem[8*1024];

    unsigned long long spare3[64];
  };

  HANDLE hSharedEvent;
  HANDLE hSharedMemory;
  void* shMemP;

  volatile ddc_mem_t* ddc_mem;
  volatile uint16_t* rtg_avb_sim_control__;
  volatile uint16_t* rtg_avb_sim_dpram__;
  unsigned int tgt_rt;

  enum { sh_mem_size=64*1024};

  SmallMimicDevice(bool create=false):
      hSharedEvent(0),
      hSharedMemory(0),
      ddc_mem(0),
      rtg_avb_sim_control__(0),
      rtg_avb_sim_dpram__(0)
  {
    instance=this;

    shMemP=0;

    hSharedMemory=::OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, "SmallMimic_DDC_SharedMemory");
    if (hSharedMemory==NULL || hSharedMemory==INVALID_HANDLE_VALUE)
    {
      if (create)
      {
        hSharedMemory=::CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sh_mem_size, "SmallMimic_DDC_SharedMemory");
        if (!hSharedMemory)
        {
          //qDebug()<<"SM: cannot create shared memory";
          hSharedMemory=0;
        }
      }
    }

    if (!hSharedMemory)
    {
      //qDebug()<<"SM-DDC Device: cannot open shared memory: Working stand-alone";
    }
    else
    {
      shMemP=::MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, 0, 0, sh_mem_size);
      if (!shMemP)
      {
        //qDebug()<<"SM-DDC Device: cannot map shared memory - Working stand-alone";
        CloseHandle(hSharedMemory);
        hSharedMemory=0;
      }
      else
      {
        hSharedEvent=::CreateEventA(0, FALSE, FALSE, "SmallMimic_DDC_Device_Event");
        if (!hSharedEvent || hSharedEvent==INVALID_HANDLE_VALUE)
        {
          //qDebug()<<"SM: cannot open shared event - Cannot generate pseudo-interrupt";
          CloseHandle(hSharedMemory);
          hSharedMemory=0;

          hSharedEvent=::CreateEvent(0, FALSE, FALSE, 0);
        }
      }
    }

    if (!shMemP)
    {
      shMemP=new char[sizeof(ddc_mem_t)];
    }

    ddc_mem=reinterpret_cast<volatile ddc_mem_t*>(shMemP);
    rtg_avb_sim_control__=&(ddc_mem->ctrl[0]);
    rtg_avb_sim_dpram__=&(ddc_mem->mem [0]);

    tgt_rt=0;


    //qDebug()<<"SM: DDC shared resources succesfully created";

    atexit(SmallMimicDevice::staticCleanUp);
  }

  uint16_t timetag()
  {
    static uint16_t tt;
    return tt++;
  }

  bool checkDdc(unsigned int rt)
  {
    if (!rtg_avb_sim_control__)
      return false;
    if (rt==0)
      return true;
    if (tgt_rt==0)
      tgt_rt=20;

    return rt==tgt_rt;
  }

  enum intr_type_t { intr_bc_eof=1<<3, intr_eom=1, intr_eom_sa=1<<4};

  void intrGenerate(unsigned int type)
  {
    ddc_mem->intr_raised|=type;
    SetEvent(hSharedEvent);
  }

  unsigned int intrGenAndClear()
  {
    unsigned int i=ddc_mem->intr_raised;
    ddc_mem->intr_raised=0;
    return i;
  }
  bool intrWait(unsigned int timeout=INFINITE)
  {
    DWORD res=::WaitForSingleObject(hSharedEvent, timeout);
    if (res==WAIT_OBJECT_0)
      return true;
    return false;
  }

  void writeModeData(unsigned int mc, uint16_t value)
  {
    if (mc==17)
      rtg_avb_sim_dpram__[0x110+1]=value;
  }

  void writeMessage(unsigned int rt, unsigned int subaddress, uint16_t* const data, unsigned int size)
  {

    if (!checkDdc(rt))
      return;

    uint16_t sp=rtg_avb_sim_dpram__[0x100];
    rtg_avb_sim_control__[0x3]=sp;

    if (sp>0x0FF)
      return;

    if (subaddress>31)
      return;

    rtg_avb_sim_dpram__[sp+3]=rt|(uint16_t(subaddress)<<5)|size;
    rtg_avb_sim_dpram__[sp+1]=timetag();
    rtg_avb_sim_dpram__[sp+0]=0x8000;

    rtg_avb_sim_dpram__[0x100]=uint16_t((sp+4) & 0x0FF);

    int gen_intr=0;

    if (subaddress==0)
    {
      if (size>=0x10)
      {
        int n=size-0x10;
        rtg_avb_sim_dpram__[0x110+n]=data[0];

        gen_intr=rtg_avb_sim_dpram__[0x109] & (1<<n);

      }
    }
    else
    {
      uint16_t bctrl=rtg_avb_sim_dpram__[0x1A0+subaddress];
      gen_intr=bctrl & 0x0200;

      unsigned int db_enable=bctrl & 0x8000;

      uint16_t buffer=rtg_avb_sim_dpram__[0x140+subaddress];
      rtg_avb_sim_dpram__[sp+2]=buffer;
      for(unsigned int i=0; i<size; ++i)
        rtg_avb_sim_dpram__[buffer+i]=data[i];

      if (db_enable)
      {
        uint16_t current=buffer & 0x20;
        if (current)
          buffer&=(~0x20);
        else
          buffer|=0x20;
        rtg_avb_sim_dpram__[0x140+subaddress]=buffer;
      }
    }

    rtg_avb_sim_dpram__[sp+1]=timetag();
    rtg_avb_sim_dpram__[sp+0]=0x4000;

    if (gen_intr)
    {
      SetEvent(hSharedEvent);
    }
  }

  static void staticCleanUp()
  {
    if (instance)
      delete instance;
  }

  ~SmallMimicDevice()
  {
    if (hSharedMemory)
      CloseHandle(hSharedMemory);
    if (hSharedEvent)
      CloseHandle(hSharedEvent);
  }

  static SmallMimicDevice* instance;
};

SmallMimicDevice* SmallMimicDevice::instance;

static Device_t fakeDevice;
static DRV_CONFIG fakeConfig;
static U16BIT bc_intr_mask=0xFFFF;

static S32BIT (*bc_isr_handler)(Device_p, S16BIT, S16BIT);
static S32BIT (*mon_isr_handler)(Device_p);

struct sim_ddc_mon_stack_t {
  unsigned int pos;
  unsigned char buffer[16*1024];
};

static sim_ddc_mon_stack_t sim_ddc_mon_stack;

typedef struct {
  unsigned int size;
  U16BIT data[32];
} ddc_sim_data_table_t;

#define SIM_DT_NUM 1024

static ddc_sim_data_table_t ddc_sim_dt[SIM_DT_NUM];

static S16BIT mc_data[32];

struct sim_message_table_t {
  MESSAGE msg[1024];
};

typedef struct {
  bool simulated;
  bool busy;
} sim_ddc_simulated_rt_t;
//static bool sim_ddc_rt[32];
static sim_ddc_simulated_rt_t sim_ddc_rt[32];


static sim_message_table_t message_table;

struct sim_frame_t {
  unsigned int m_time;

  bool bc_running;
  bool mon_running;

  bool skip_disabled;
  unsigned int len;
  U16BIT msg[1024];
};

static sim_frame_t sim_frame;

static IDEA_INFO sim_info;

//extern metricRegistered metricDdcDriverISR;
//static metricRegistered mSimISR("DDC_SimIRS", 0, 0, &metricDdcDriverISR);

static void DdcSimulatore_SimulateBcTick_(bool showDbg=false);

void DdcSimulator_SimulateBcTick()
{
  DdcSimulatore_SimulateBcTick_(true);
}

#include <Mmsystem.h>

#ifdef USE_MM_TIMER
#define TIMEOUT_VAR default_wait_time
#else
#define TIMEOUT_VAR minor_frame_time

#define timeSetEvent(a_, b_, c_, d_, e_)  (0)
#define timeKillEvent(x_)  ((void)(0))
#endif


class WorkerThread//: public QThread
{
public:

  WorkerThread(void (*cb)(void)):
      stopMe(false),
      //mmT(0),
      hEvent(0),
      callback(cb)
  {
    hEvent=CreateEvent(0, FALSE, FALSE, 0);
    hCtrlEvent=CreateEvent(0, TRUE, TRUE, 0);
    ResetEvent(hCtrlEvent);
    pauseMe=true;
    minor_frame_time=100;
    wait_time=&TIMEOUT_VAR;
    default_wait_time=INFINITE;
    //start(); //QThread::TimeCriticalPriority);
  }

  unsigned int minor_frame_time;
  unsigned int* wait_time;
  unsigned int default_wait_time;
  unsigned int fpos;

  void setTime(unsigned int ms)
  {
    minor_frame_time=ms;
  }

  void go()
  {
    stopMe=false;

    fpos=0;

    if (minor_frame_time<10)
      minor_frame_time=10;

    pauseMe=false;
    SetEvent(hCtrlEvent);
    mmT=timeSetEvent(minor_frame_time, 0, (LPTIMECALLBACK)hEvent, 0, TIME_PERIODIC|TIME_CALLBACK_EVENT_SET); //|TIME_KILL_SYNCHRONOUS);
  }

  virtual void kill()
  {
    stop();
    stopMe=true;
    pauseMe=true;
    CloseHandle(hCtrlEvent);
    if (hEvent)
      CloseHandle(hEvent);

  }

  virtual void stop()
  {
    if (mmT)
      timeKillEvent(mmT);
    pauseMe=true;
    ResetEvent(hCtrlEvent);
  }

protected:
  volatile bool stopMe;
  volatile bool pauseMe;
  MMRESULT mmT;
  HANDLE hEvent;
  HANDLE hCtrlEvent;
  void (*callback)(void);

  virtual void run()
  {
    do
    {
      WaitForSingleObject(hCtrlEvent, 1000);
      for(; !pauseMe && !stopMe;)
      {
        DWORD res=WaitForSingleObject(hEvent, *wait_time); //INFINITE);
        if (res==WAIT_FAILED)
          break;
        if (res==WAIT_OBJECT_0 || res==WAIT_TIMEOUT)
          DdcSimulatore_SimulateBcTick_();
      }
    } while(!stopMe);
  }
};

static WorkerThread* wth;

static unsigned int sim_ddc_generated_interrupts;

void DdcSimulatore_SimulateBcTick_(bool showDbg)
{
  static unsigned int fpos;

  if (!sim_frame.bc_running)
    return;

  //metricMeasure xx(mSimISR);

  for(;fpos<sim_frame.len; ++fpos)
  {
    int i=sim_frame.msg[fpos];

    //if (showDbg) qDebug()<<"SIM: "<<fpos<<" -> "<<i;

    if (i==IDEA_END_OF_MINOR)
    {
      //if (showDbg) qDebug()<<"SIM: END OF MINOR";
      ++fpos;
      break;
    }
    if (i==IDEA_END_OF_MAJOR)
    {
      fpos=0;
      //if (showDbg) qDebug()<<"SIM: END OF MAJOR";
      break;
    }

    MESSAGE& m=message_table.msg[i];

    unsigned int rt=m.cmd_1.tadr;

    if (SmallMimicDevice::instance)
    {
      if (m.comm_type==RECEIVE)
      {
        //SmallMimicDevice::instance->writeMessage(rt, m.cmd_1.subadr, ddc_sim_dt[m.data_table_no].data, m.cmd_1.wcnt);
      }
      else if (m.comm_type==MODE)
      {
        if (m.cmd_1.wcnt==17)
        {
          SmallMimicDevice::instance->writeModeData(11, mc_data[m.cmd_1.wcnt]);
          SmallMimicDevice::instance->intrGenerate(SmallMimicDevice::intr_eom|SmallMimicDevice::intr_eom_sa);
        }
      }
    }
    if (m.first_intermessage_routine==IDEA_IMR_INT_ON_END_OF_MESSAGE || m.second_intermessage_routine==IDEA_IMR_INT_ON_END_OF_MESSAGE)
    {
      if (bc_isr_handler && (bc_intr_mask & ((1<<4)|(1<<5)|(1<<6)))==0)
      {
        S16BIT itype=sim_ddc_rt[rt].simulated ? 0x80 : 0x81;
        S16BIT param=0;
        itype=itype|(i<<8);
        bc_isr_handler(0, itype, param);
        ++sim_ddc_generated_interrupts;
      }
    }
    if (sim_frame.mon_running)
    {
      if (m.comm_type!=IDEA_NOP)
      {
        U16BIT header[8+32];
        memset(header, 0, sizeof header);
        if (m.comm_type==TRANSMIT)
        {
          void* px=&(m.cmd_1);
          short* spx=(short*)px;

          header[2]=*spx;
          header[1]=*spx;
          header[0]=2<<6;
        }
        else
        {
          void* px=&(m.cmd_1);
          short* spx=(short*)px;

          header[1]=*spx;
          header[2]=*spx;
          header[0]=1<<6;

        }
        U32BIT tt_val;
        ddcRead_mon_rtc(0, &tt_val);
        header[5]=(tt_val>>16) & 0x0FFFF;
        header[6]=tt_val & 0x0FFFF;

        unsigned int x_wc=0;

        if (m.comm_type==MODE)
        {
          if (m.cmd_1.wcnt==17)
          {
            x_wc=1;
            header[8]=mc_data[17];
          }
        }
        else //if (m.comm_type==RECEIVE)
        {
          x_wc=m.cmd_1.wcnt==0 ? 32 : m.cmd_1.wcnt;
          if (x_wc>32)
            x_wc=0;
          for(unsigned int i=0; i<x_wc; ++i)
            header[8+i]=ddc_sim_dt[m.data_table_no].data[i];
        }

        unsigned short sts_w=m.cmd_1.subadr<<12;

        if (sim_ddc_rt[rt].simulated)
        {
           if (sim_ddc_rt[rt].busy)
             sts_w|=(1<<4);

           header[7]=0;
           header[3]=sts_w;
           header[4]=sts_w;

           if (m.comm_type==TRANSMIT)
             x_wc=m.cmd_1.wcnt==0 ? 32 : m.cmd_1.wcnt;
        }
        else
          header[7]=2;

        if (x_wc>32)
          x_wc=0;

        header[0]|=x_wc<<8;

        {
          unsigned int p=sim_ddc_mon_stack.pos;

          if ((p+(sizeof header))<(sizeof sim_ddc_mon_stack.buffer))
          {
            unsigned int s=(x_wc+8)*2;
            memcpy(&sim_ddc_mon_stack.buffer[p], header, s);
            if (sim_ddc_mon_stack.pos==p) //A simple concurrent test that can lost message
            {
              p+=s;
              sim_ddc_mon_stack.pos=p;
            }
          }
        }
      }
    }

    if (i==IDEA_END_OF_MINOR)
    {
      ++fpos;
      break;
    }
    if (i==IDEA_END_OF_MAJOR)
    {
      fpos=0;
      break;
    }

    if ((!sim_frame.skip_disabled) && (m.first_intermessage_routine==IDEA_IMR_SKIP_NEXT || m.second_intermessage_routine==IDEA_IMR_SKIP_NEXT))
    {
      ++fpos;
      continue;
    }

  }
}

IDEA_INFO ddcGetIdeaInfo(Device_p /*pCrd*/)
{
  return sim_info;
}

Error_t __DECL ddcResetCard(Device_p *pCrd, DRV_CONFIG *config, U16BIT /*LogNum*/)
{
  if (!SmallMimicDevice::instance)
  {
    SmallMimicDevice::instance=new SmallMimicDevice;
  }

  *pCrd=&fakeDevice;
  if (config)
    *config=fakeConfig;
  if (!wth)
    wth=new WorkerThread(0);

  return 0;
}

Error_t IdeaResetCard(ViInt16 /*CardNo*/, ViInt16 /*Mode*/)
{
  return 0;
}

Error_t __DECL ddcHaltIdea(Device_p /*pCrd*/)
{
  return 0;
}

Error_t IdeaShutdown(ViInt16 /*CardNo*/)
{
  return 0;
}

Error_t __DECL ddcShutDownIdea(Device_p *pCrd)
{
  wth->kill();

  *pCrd=0;
  return 0;
}

Error_t __DECL ddcIdeaCoreVersion(Device_p /*pCrd*/, char *rtl_core_ver)
{
  strcpy(rtl_core_ver, "GC-DDC-SIM-CORE-1.0");
  return 0;
}

Error_t __DECL ddcCardState(Device_p /*pCrd*/, CARD_STATE *state)
{
  memset(state, 0, sizeof *state);
  state->bcrt=sim_frame.bc_running ? RUNNING: HALTED;
  state->mon=sim_frame.mon_running ? RUNNING : HALTED;
  if (sim_frame.bc_running && sim_frame.mon_running)
    state->card=RUN_BCRT_MONITOR_STATE;
  else if (sim_frame.bc_running)
    state->card=RUN_BCRT_STATE;
  else if (sim_frame.mon_running)
    state->card=RUN_MONITOR_STATE;
  else
    state->card=HALT_STATE;

  return 0;
}

Error_t __DECL ddcIdeaVersion(Device_p /*pCrd*/,char *rtl_ver,char *driver_ver,char *part_no)
{
  if (rtl_ver)
    strcpy(rtl_ver, "GA-DCC-Sim-RTL-1.0");
  if (driver_ver)
    strcpy(driver_ver, "GA-DCC-Sim-RTL-1.0");
  if (part_no)
    strcpy(part_no, "GA-DCC-Sim-RTL-1.0");

  return 0;

}

Error_t ddcDef_int_mask(Device_p, U16BIT mask)
{
  bc_intr_mask=mask;
  return 0;
}

Error_t ddcDef_int_mask_monitor(Device_p /*pCrd*/, U16BIT maskreg)
{
  maskreg=maskreg & 0xF000;
  bc_intr_mask=bc_intr_mask & 0x0FFF;
  bc_intr_mask|=maskreg;
  return 0;
}

Error_t ddcDef_int_mask_bcrt(Device_p /*pCrd*/, U16BIT maskreg)
{
  maskreg=maskreg & 0x0FFF;
  bc_intr_mask=bc_intr_mask & 0xF000;
  bc_intr_mask|=maskreg;
  return 0;
}

Error_t ddcSelect_bus(Device_p /*pCrd*/, U16BIT /*bus_a_state*/, U16BIT /*bus_b_state*/)
{
  return 0;
}

Error_t ddcRead_mon_rtc(Device_p, U32BIT* tt_val)
{
  DWORD tt=GetTickCount();

  *tt_val=tt*1000;
  return 0;
}

Error_t ddcDef_monitor_stack(Device_p /*pCrd*/, U16BIT /*type*/)
{
  return 0;
}

Error_t ddcDef_minor_frame_time(Device_p /*pCrd*/, S32BIT val)
{
  sim_frame.m_time=val;
  wth->setTime(val/1000);
  return 0;
}

Error_t ddcDef_table_size(Device_p /*pCrd*/, S16BIT id, S16BIT size)
{
  if (id<0 || id>=SIM_DT_NUM)
    return 1;
  ddc_sim_dt[id].size=size;
  return 0;
}

Error_t ddcDef_rt_map(Device_p /*pCrd*/, S16BIT /*tadr*/, S16BIT /*tr_bit*/, S16BIT /*sadr*/, S16BIT /*table_id*/)
{
  return 0;
}


Error_t ddcSetBCRTEvent(Device_p /*pCrd*/, S32BIT (*usr_handler)(Device_p, S16BIT, S16BIT))
{
  bc_isr_handler=usr_handler;
  return 0;
}

Error_t ddcSetMONEvent(Device_p /*pCrd*/, S32BIT (*usr_handler)(Device_p))
{
  mon_isr_handler=usr_handler;
  return 0;
}

Error_t ddcHalt_bcrt(Device_p /*pCrd*/)
{
  sim_frame.bc_running=false;
  //if (!sim_frame.mon_running)
    wth->stop();
  return 0;
}

Error_t ddcHalt_mon(Device_p /*pCrd*/)
{
  sim_frame.mon_running=false;
  //if (!sim_frame.bc_running)
  //  wth->stop();
  return 0;
}

Error_t ddcRun_bc(Device_p /*pCrd*/, S16BIT /*position*/, S32BIT /*times*/)
{
  sim_frame.bc_running=true;
  //if (!sim_frame.mon_running)
  wth->go();
  return 0;
}

Error_t ddcRun_mon(Device_p /*pCrd*/)
{
  sim_frame.mon_running=true;
  //if (!sim_frame.bc_running)
  //  wth->go();
  return 0;
}

Error_t ddcDef_message(Device_p /*pCrd*/, S16BIT id, tagMESSAGE *message)
{
  if (id<1 || id>=1024)
    return 1;
  message_table.msg[id]=*message;
  return 0;
}

Error_t ddcDef_frame(Device_p /*pCrd*/, S16BIT length, U16BIT *frame)
{
  for(int i=0; i<length; ++i)
    sim_frame.msg[i]=frame[i];
  sim_frame.len=length;
  return 0;
}

Error_t ddcSkip_next_message(Device_p /*pCrd*/, S16BIT yes_no)
{
  sim_frame.skip_disabled=yes_no;
  return 0;
}

Error_t IdeaDbgOSGetCounts(ViInt16 /*pCrd*/, ViPInt32 tot, ViPInt32 mon_host, ViPInt32 mon_card, ViPInt32 bc_host, ViPInt32 bc_card)
{
  *mon_host=0;
  *mon_card=0;
  *tot=sim_ddc_generated_interrupts;
  *bc_card=sim_ddc_generated_interrupts;
  *bc_host=sim_ddc_generated_interrupts;
  return 0;
}

Error_t ddcRead_mon_stack_part(Device_p /*pCrd*/, S16BIT *buf, S16BIT *count, S16BIT *messages)
{
  //*count=0;
  //*messages=0;
  unsigned int s=sim_ddc_mon_stack.pos;
  //if (s> (unsigned int)((*messages)*40))
  //  s= (*messages)*40;
  memcpy(buf, sim_ddc_mon_stack.buffer, s);
  *messages=s/(sizeof(U16BIT)*40);
  *count=s/2;
  sim_ddc_mon_stack.pos=0;
  return 0;
}

Error_t ddcRead_time_tags(Device_p /*pCrd*/, void * /*buf*/, S16BIT *count)
{
  *count=0;
  return 0;
}

Error_t ddcWrite_mode_data(Device_p /*pCrd*/, S16BIT /*tadr*/, S16BIT mode_code, S16BIT val)
{
  mc_data[mode_code]=val;
  return 0;
}

Error_t ddcDef_rt(Device_p /*pCrd*/, S16BIT tadr, _tagRT_DEFS * /*rt*/)
{
  sim_ddc_rt[tadr].simulated=true;
  return 0;
}

Error_t ddcSet_busy(Device_p /*pCrd*/, S16BIT tadr, S16BIT /*immediate*/)
{
  sim_ddc_rt[tadr].busy=true;
  return 0;
}

Error_t ddcDef_emulate_rt(Device_p /*pCrd*/, S16BIT /*tadr*/, S16BIT /*emulate*/)
{
  return 0;
}

Error_t ddcDecode_mon_message(Device_p /*pCrd*/, U16BIT *buf, MON_MSG *msg)
{
  static volatile int invalid_msg;

  memset(msg, 0, sizeof *msg);
  msg->broadcast=0;
  unsigned int cmode=(buf[0]>>6) & 0x3;
  unsigned int c1=1;
  unsigned int c2=2;
  if (cmode==2)
  {
    c1=2;
    c2=1;

  }
  msg->comm_type= cmode==2 ? TRANSMIT : cmode==0 ? MODE : RECEIVE;

  msg->cmd_1=buf[c1];
  msg->cmd_2=buf[c2];
  msg->s_cmd_1=*(struct com*)&buf[c1];
  msg->s_cmd_2=*(struct com*)&buf[c2];

  msg->cmd_1_flag=c1==1 ? 1: 0;
  msg->cmd_2_flag=c1==1 ? 0 : 1;

  msg->tx_status=buf[3];
  msg->rx_status=buf[4];

  msg->word_count=(buf[0]>>8) & 0x3F;
  msg->data_buf=(S16BIT*)(buf+8);
  msg->next_msg=(S16BIT*)(buf+8+ msg->word_count);

  msg->rtc=(buf[5]<<16) | buf[6];

  unsigned int ec=(buf[7]>>1) & 0xF;
  if (ec==0)
  {
    if (cmode==2)
    {
      msg->stat_r_flag=0;
      msg->stat_t_flag=1;
    }
    else
    {
      msg->stat_r_flag=1;
      msg->stat_t_flag=0;
    }
    //msg->rx_status=buf[c1];
    //msg->tx_status=buf[c2];
    msg->error=NO;
    msg->error_inf.type=0;
  }
  else
  {
    msg->error=YES;
    msg->error_inf.type=TYPE_NO_RESPONSE;
    msg->stat_r_flag=0;
    msg->stat_t_flag=0;
  }

  if (msg->s_cmd_1.tadr==0)
    ++invalid_msg;

  return 0;
}

Error_t ddcGetErrorMessage(Device_p /*pCrd*/, S32BIT /*error_number*/, char *error_string)
{
  strcpy(error_string, "unknown");
  return 0;
}


Error_t ddcWrite_data(Device_p /*pCrd*/, S16BIT id, S16BIT *buf, S16BIT count, S16BIT pos)
{
  if (id<1 || id>250)
    return 1;
  S16BIT n=(count+pos)-1;
  if (n<0 || n>32)
    return 2;
  if (pos<1 || pos>32)
    return 3;

  memcpy(&(ddc_sim_dt[id].data[pos-1]), buf, 2*((count-pos)+1));

  return 0;
}

Error_t ddcRead_data(Device_p /*pCrd*/, S16BIT id, S16BIT *buf, S16BIT count)
{
  /*
  static U16BIT sim_counter;

  if (id<1 || id>250)
    return 1;
  if (count<1 || count>32)
    return 2;
  for(int i=0; i<32; ++i)
    ddc_sim_dt[id].data[i]= ++sim_counter;
  */
  memcpy(buf, ddc_sim_dt[id].data, count*2);
  return 0;
}

Error_t ddcRead_message(Device_p /*pCrd*/, S16BIT /*id*/, tagMESSAGE *message)
{
  message->det_error=NO_ERROR;
  return 0;
}

bool DdcSimulator_isSimulator()
{
  return true;
}

#else

bool DdcSimulator_isSimulator()
{
  return false;
}

void DdcSimulator_SimulateBcTick()
{
}

#endif

