/****************************************************************************
 *  F i l e   D a t a                                                        
 *  $Id: DAQ_IDAQ_INFN.c,v 1.1.1.1 2006/04/25 09:00:20 kusanagi Exp $
 *  $Revision: 1.1.1.1 $
 *  $Date: 2006/04/25 09:00:20 $
 *  $RCSfile: DAQ_IDAQ_INFN.c,v $
 *                                                                           
 ****************************************************************************
 *  S W   D e v e l o p m e n t   E n v i r o n m e n t                      
 *                                                                           
 *  $Author: kusanagi $
 *               :                                                           
 ****************************************************************************
 *  U p d a t i n g                                                          
 *                                                                           
 *  $Log: DAQ_IDAQ_INFN.c,v $
 *  Revision 1.1.1.1  2006/04/25 09:00:20  kusanagi
 *  These program extract in an XML format the info contained into the ROOT files generated by YODA from the PAMELA data. To visualize the XML files in a more human readable format a collection of XSL files are given in the Data subfolder.
 *
 *  Revision 1.69  2005/03/20 18:19:21  sebastiani
 *  CRC start valeu in DAQ_ module start from zero, like always
 *
 *  Revision 1.68  2005/03/06 14:54:46  sebastiani
 *  version running on 06 03 2005
 *
 *  Revision 1.67  2005/02/24 16:49:29  sebastiani
 *  DAQ_STORE_MM moved to be a macro , not a static var
 *
 *  Revision 1.66  2005/02/21 08:58:29  sebastiani
 *  all log comments completed
 *
 *  Revision 1.65  2005/01/26 18:46:48  sebastiani
 *  new bug fixes for WS
 *
 *  Revision 1.64  2004/11/19 15:14:52  sebastiani
 *  PRH_EXTERN_{VAR,ARR,TABLE} removed and put them on the autogenerated parameter heeader file
 *
 *  Revision 1.63  2004/11/05 16:43:07  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.62  2004/10/01 08:48:10  sebastiani
 *  TRD alarma renamed TRD_S4  - S4 Alarm renamed S4_POWER
 *  Callback function into DAQ_SendCmd2PIFWaitDAQReply_internal
 *
 *  Revision 1.61  2004/09/17 15:01:00  faber
 *  LU_INFN_LOG flags fixing
 *
 *  Revision 1.60  2004/09/09 14:52:55  sebastiani
 *  using PreparePage to send cmd to idaq/FE
 *  added some test
 *  added trigger param
 *  added/tested Force Send KHB_to_FE
 *  added/tested Send Cmd to IDAQ/FE
 *
 *  Revision 1.59  2004/08/31 09:08:35  sebastiani
 *  fix warning
 *
 *  Revision 1.58  2004/08/26 16:54:34  sebastiani
 *  version work fine
 *
 *  Revision 1.57  2004/08/13 14:42:19  sebastiani
 *  Add Neutron detector!
 *  need add file ND_READ_ACQ.dat on site ...
 *
 *  Revision 1.56  2004/08/11 15:49:59  sebastiani
 *  delete unuseful line
 *
 *  Revision 1.55  2004/08/02 15:49:47  alfarano
 *  alarm handling , scm & pm communication rewrite
 *
 *  Revision 1.54  2004/08/02 14:26:38  sebastiani
 *  fix mm bug
 *
 *  Revision 1.53  2004/08/02 12:16:24  sebastiani
 *  little fix
 *
 *  Revision 1.52  2004/07/21 14:08:32  sebastiani
 *  Fix close RUN we wait a event to close the run
 *  PM send Sint and don't wait for SintOK
 *  Header'Trailer Initialization
 *  FixPacketCounter
 *
 *  Revision 1.51  2004/07/20 14:36:26  sebastiani
 *  AC/CAL/TRK/TOF/TRG unmaksed all KHB alarms
 *  RM: Close Run before RunTrailer (send page 2)
 *
 *  Revision 1.50  2004/07/15 13:45:58  sebastiani
 *  fix some bugs
 *
 *  Revision 1.49  2004/07/12 09:19:33  sebastiani
 *  some fixing about alamrs
 *
 *  Revision 1.48  2004/06/22 09:34:52  faber
 *  *** empty log message ***
 *
 *  Revision 1.47  2004/06/22 08:57:01  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.46  2004/06/16 09:35:13  faber
 *  *** empty log message ***
 *
 *  Revision 1.45  2004/06/15 08:22:06  sebastiani
 *  adjust DAQ_DEFAULT_{DTO,ETO}_TICS
 *
 *  Revision 1.44  2004/06/04 14:24:38  sebastiani
 *  clear some files
 *
 *  Revision 1.43  2004/06/01 16:41:19  sebastiani
 *  EventReceive ANY
 *
 *  Revision 1.42  2004/05/27 17:50:40  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.41  2004/05/25 17:41:08  sebastiani
 *  fix alfarano's bugs
 *
 *  Revision 1.40  2004/05/24 10:27:32  faber
 *  *** empty log message ***
 *
 *  Revision 1.39  2004/05/20 16:51:02  sebastiani
 *  add append with offset and fix some bug
 *
 *  Revision 1.38  2004/05/20 16:03:52  faber
 *  ACQ flow dev continuing
 *
 *  Revision 1.37  2004/05/20 09:04:15  sebastiani
 *  ok
 *
 *  Revision 1.36  2004/05/19 08:44:38  sebastiani
 *  fix trk init and calib
 *
 *  Revision 1.35  2004/05/14 08:37:27  sebastiani
 *  same default param, some sebastiani's bugs
 *
 *  Revision 1.34  2004/05/12 14:46:14  faber
 *  *** empty log message ***
 *
 *  Revision 1.33  2004/05/12 08:10:11  faber
 *  *** empty log message ***
 *
 *  Revision 1.32  2004/05/11 17:45:10  sebastiani
 *  x-1 offset
 *
 *  Revision 1.31  2004/05/11 15:28:28  alfarano
 *  updates..
 *
 *  Revision 1.30  2004/05/11 13:58:49  sebastiani
 *  ETO/ATO 4+4 bit instead of 5.3 in DAQ_IDAQ_INFN
 *
 *  Revision 1.29  2004/05/06 08:52:24  faber
 *  development goes on..
 *
 *  Revision 1.28  2004/05/03 14:45:13  sebastiani
 *  correct len
 *
 *  Revision 1.27  2004/04/30 09:51:36  alfarano
 *  stupid error
 *
 *  Revision 1.26  2004/04/29 16:13:59  alfarano
 *  update cal
 *
 *  Revision 1.25  2004/04/29 15:22:42  sebastiani
 *  buffer->len+=SM_HEADER_LEN in WriteHeaderLen
 *
 *  Revision 1.24  2004/04/29 15:17:24  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.23  2004/04/29 08:30:59  sebastiani
 *  WriteHeader moved to DAQ_IDAQ_INFN.c
 *
 *  Revision 1.22  2004/02/13 10:11:30  alfarano
 *  calorimeter initialization func and more
 *
 *  Revision 1.21  2004/02/11 16:26:52  faber
 *  CM_TIME2REG introduced
 *
 *  Revision 1.20  2004/02/10 16:48:28  faber
 *  *** empty log message ***
 *
 *  Revision 1.19  2004/02/05 11:36:11  sebastiani
 *  DAQ_FE_DUMMY introduced and TEST_FE2LINK changed
 *
 *  Revision 1.18  2004/01/29 18:10:01  sebastiani
 *  DAQ_Format_Daq2Ram_ReadData introduced; DAQ_FORMAT_OPCODE_CMD_TEMPLATE modifed to work better
 *
 *  Revision 1.17  2004/01/22 10:10:25  faber
 *  *** empty log message ***
 *
 *  Revision 1.16  2004/01/12 17:51:28  tassa
 *  manca solo la parte di invio e ricezione sulla/dalla IDAQ
 *
 *  Revision 1.15  2003/11/04 11:57:45  sebastiani
 *  DAQ_Format_Cmd2Ram_ReadData added
 *
 *  Revision 1.14  2003/10/27 18:52:58  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.13  2003/10/21 13:16:01  sebastiani
 *  no logs on clear event any more
 *
 *  Revision 1.12  2003/10/17 08:44:15  sebastiani
 *  new implementation of DAQ_SaveBuffer2MM
 *
 *  Revision 1.11  2003/10/02 16:14:43  faber
 *  IDAQ deep ETO/ATO modifications
 *  All comments for functions
 *
 *  Revision 1.10  2003/10/01 18:13:01  faber
 *  temp buf size bug fix
 *
 *  Revision 1.9  2003/09/25 16:51:27  alfarano
 *  conflicts resolved
 *
 *  Revision 1.8  2003/09/25 12:57:07  faber
 *  first version of cmdgenerator.c
 *
 *  Revision 1.7  2003/09/22 14:05:38  alfarano
 *  functions moved from RM_RunManager to DAQ_IDAQ_INFN:StoreCmdQueue2PIF,SendCmdQueue2CMDIF; added DAQ_SendCmd2PIFWaitDAQReply
 *
 *  Revision 1.6  2003/09/19 15:57:35  faber
 *  Large development update INFN software
 *
 *  Revision 1.5  2003/09/10 16:15:52  faber
 *  PRH_EXTERN_VAR(XX_LOGMASK) removed (not needed any more)
 *
 *  Revision 1.4  2003/09/10 11:55:07  faber
 *  LU_MASK introduced. Log mask for module is now an unique array (PRH_ARR_LOG_MASK) indexed by __FILEID__
 *
 *  Revision 1.3  2003/08/22 07:57:08  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.2  2003/08/08 11:00:42  sebastiani
 *  Primo test funzionante IDAQ (GuidoBoard)
 *  Import Test Russi 30.8
 *
 *  Revision 1.1.1.1  2003/08/04 09:40:22  sebastiani
 *  Imported sources laben rel. 19.06.2003 integrated with pam2
 *
 *  Revision 1.7  2003/07/28 09:12:01  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.6  2003/07/25 15:32:57  sebastiani
 *  * Cmd2XX / ReadData cancelled (non valid!)
 *  * new way of declaration of buffers
 *
 *  Revision 1.5  2003/07/18 13:35:10  sebastiani
 *  PRH_ParamHandler_INFN_int.c sobstitues PRH_ParamHandler_INFN_*.*
 *  introduced DAQTEST directive
 *
 *  Revision 1.4  2003/07/17 11:15:52  sebastiani
 *  idaq manager
 *  new print for logging in minicom
 *
 *  Revision 1.3  2003/07/11 09:39:23  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.2  2003/07/10 15:56:27  sebastiani
 *  *** empty log message ***
 *
 *  Revision 1.1  2003/07/10 07:05:14  sebastiani
 *  first IDAQ driver import
 *
 *                                                                           
 *****************************************************************************/


/*============================= Include File ================================*/


#include <src/INFN/LU_SourceFileID_INFN.h>
#define __FILEID__ _DAQ_IDAQ_INFN__c


#ifndef I386
#include <src/INFN/PRH_ParamHandler_INFN_auto.h>
#include <src/INFN/PRH_ParamHandler_INFN_autopri.h>
#include <src/INFN/PRH_ParamHandler_INFN.h>
#include <src/INFN/LU_LogUtility_INFN.h>
LU_DECL_MASK();
#endif  // I386

#include <src/INFN/DAQ_IDAQ_INFN.h>
#include <src/INFN/CM_Common_INFN.h>


#ifndef I386
#include <src/INFN/KHB_Driver_INFN.h>
#include <src/INFN/HK_Manager_INFN.h>
#include <src/INFN/RM_RunManager_INFN.h>
#include <src/FileManager/MMSUManager/FT_MMSUManager_p.h>
#endif  // I386

/*============================ Global define ================================*/

#define DAQ_SSBUF_SHORTCMD_LIMIT 124
#define DAQ_SSBUF_LONGCMD_LIMIT  126

//#define DAQ_SSBUF_SHORTCMD_LIMIT 5
//#define DAQ_SSBUF_LONGCMD_LIMIT  6

#define DAQ_LINK_SPARE 0xFF

#define DAQ_FLASH_N_SECTOR 0x12


#ifdef I386
typedef unsigned int PRH_VAR_TYPE;
#define SUCCESSFUL 0
#endif  // I386


// #define ETOATO_EXTERN(name) PRH_EXTERN_VAR(DAQ_##name##_ETO); PRH_EXTERN_VAR(DAQ_##name##_ATO)
#define DEF_ETOATO(name,eto,ato) static BYTE DAQ_##name##_ETO=eto; static BYTE DAQ_##name##_ATO=ato;
#define ETOATO(name) DAQ_##name##_ETO,DAQ_##name##_ATO 




#ifdef I386
#define TEMP_BUF_LEN (64*1024)
#else
#define TEMP_BUF_LEN (SM_SRAMPAGESIZE*2)
#endif  // I386

/*============================== global types  ==============================*/




/*****************************************************************************/
/*=========================== Structure define ==============================*/

/* this resurse is protected from the DAQ_BUF_INFN_RES */

static DAQ_CMD_BUF tempbuf;
static BYTE __tempbuf[TEMP_BUF_LEN];

static unsigned int DAQ_FLASH_SECTOR_DIM_KB[DAQ_FLASH_N_SECTOR] = {16,8,8,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64};
static unsigned int DAQ_FLASH_SECTOR_LADDR[DAQ_FLASH_N_SECTOR];
static unsigned int DAQ_FLASH_SECTOR_UADDR[DAQ_FLASH_N_SECTOR];

/*****************************************************************************/
/*============================ Enumerate define =============================*/

/*****************************************************************************/

/*=== ZZZ   I N T E R N A L   ==*/

/*****************************************************************************/

/* Exec Time Out  and Answer Time Out definitions . To be defined */




DEF_ETOATO(FLASH_SECTORERASE,0,0);
DEF_ETOATO(FLASH_SETADDRESS,0,0);
DEF_ETOATO(FLASH_WRITEDATA,0,0);
DEF_ETOATO(FLASH_ENDBLOCK,0,0);
DEF_ETOATO(FLASH_READDATA,0,0);

/* READDATA / WRITEDATA ETO depends on length of the stream.  */

DEF_ETOATO(RAM_SETADDRESS,2,1);
DEF_ETOATO(RAM_WRITEDATA,2,1);
DEF_ETOATO(RAM_ENDBLOCK,2,1);
DEF_ETOATO(RAM_READDATA,2,1);

DEF_ETOATO(DSP_STARTPROGRAM,2,1);
DEF_ETOATO(DSP_SETADDRESS,2,1);
DEF_ETOATO(DSP_WRITEDATA,2,1);
DEF_ETOATO(DSP_READDATA,2,1);
DEF_ETOATO(DSP_RESET,2,1);
DEF_ETOATO(DSP_FLAGREAD,2,1);
DEF_ETOATO(DSP_CHECKMEMORY,2,1);



#ifndef I386
#define DAQ_FORMAT_OPCODE_CMD_TEMPLATE(function1,function2) status_code s1,s2; \
  if( (s1=OS_piResourceObtain_INFN(DAQ_BUF_INFN_RES,RTEMS_WAIT,RTEMS_NO_TIMEOUT)) != SUCCESSFUL) \
     return s1; \
  s1=function1; \
  if(s1 == DAQ_SC_SUCCESSFUL) \
     s2 = function2; \
  OS_piResourceRelease_INFN(DAQ_BUF_INFN_RES); \
  if(s1 != DAQ_SC_SUCCESSFUL) \
    return s1; \
  return s2
#else
#define DAQ_FORMAT_OPCODE_CMD_TEMPLATE(function1,function2) status_code s1,s2; \
  s1=function1; \
  if(s1 == DAQ_SC_SUCCESSFUL) \
     s2 = function2; \
  if(s1 != DAQ_SC_SUCCESSFUL) \
    return s1; \
  return s2
#endif // I386

/* coocked commands: */

DAQ_DECLBUF(readdata,1);
DAQ_DECLBUF(nullbuf,1);

void DAQ_Init_CoockedCommands() {
  DAQ_BUFFER_INIT(readdata);
  DAQ_BUFFER_INIT(nullbuf);
}

status_code DAQ_Init() {
  int i;
  unsigned int prec=-1;
  for(i=0;i<DAQ_FLASH_N_SECTOR;i++) {
    DAQ_FLASH_SECTOR_LADDR[i]=prec+1;
    prec=DAQ_FLASH_SECTOR_UADDR[i]=DAQ_FLASH_SECTOR_LADDR[i]+DAQ_FLASH_SECTOR_DIM_KB[i]*1024;
  }
  DAQ_Format_CMD_Init(&tempbuf,TEMP_BUF_LEN,0,__tempbuf);
  DAQ_Init_CoockedCommands();
  return DAQ_SC_SUCCESSFUL;
}


status_code DAQ_Format_CMD_Init(DAQ_CMD_BUF *cmdbuf,unsigned int size,unsigned int len,BYTE *buf) {
  cmdbuf->size=size;
  cmdbuf->len=len;
  cmdbuf->buf=buf;
  cmdbuf->eto = DAQ_ETO_UNSET;
  cmdbuf->ato = DAQ_ATO_UNSET;
  cmdbuf->crc16 = 0;
  cmdbuf->crc8  = 0;
  return DAQ_SC_SUCCESSFUL;
}

status_code DAQ_Format_CMD_Fill(DAQ_CMD_BUF *cmdbuf,unsigned int len,BYTE pattern) {
  int i;
  DAQ_CTRL_SET_LEN(cmdbuf,len);
  for(i=0;i<len;i++)
    cmdbuf->buf[i]=pattern;
  return DAQ_SC_SUCCESSFUL;
}


#ifdef TEST_I
status_code DAQ_BufDump(DAQ_CMD_BUF *b) {
  static char str[100];
  int i;
  sprintf(str,"BufDump: Len:%d ETO:%d ATO:%d",b->len,b->eto,b->ato);

#ifdef I386
  //  printf("%s\n",str);
#else
  //TS_piWriteOnUART(str);
  LU_WriteOnUART(str);
#endif  // I386


  for(i=0;i<b->len;i++) {
    sprintf(str,"0x%x",b->buf[i]);

#ifdef I386
  printf("%s\n",str);
#else    
  // TS_piWriteOnUART(str);
  LU_WriteOnUART(str);
#endif  // I386


  }

#ifdef I386
  //printf("BufDump END\n");
#else    
  // TS_piWriteOnUART("BufDump END");
  LU_WriteOnUART("BufDump END");
#endif  // I386
  return SUCCESSFUL;
}
#endif

status_code DAQ_Format_AppendBuffer_offset(DAQ_CMD_BUF *target,DAQ_CMD_BUF *source,unsigned int offset) {
  unsigned int l=target->len;
  // TBD: what to do with ETO/ATO ?
  if(offset >= source->len)
    {
      return CM_RC_INVALID_BUFFER_SIZE;
    }
  DAQ_CTRL_SET_LEN(target,target->len+source->len-offset);
  memcpy(&target->buf[l],&source->buf[offset],source->len-offset);
  return DAQ_SC_SUCCESSFUL;
}


status_code DAQ_Format_AppendBuffer(DAQ_CMD_BUF *target,DAQ_CMD_BUF *source) {
  unsigned int l=target->len;
  // TBD: what to do with ETO/ATO ?
  DAQ_CTRL_SET_LEN(target,target->len+source->len);
  memcpy(&target->buf[l],source->buf,source->len);
  return DAQ_SC_SUCCESSFUL;
}

status_code DAQ_Format_CopyBuffer(DAQ_CMD_BUF *target,DAQ_CMD_BUF *source) {
  // emtpy the buffer:
  if( target->size < source->len) 
    return DAQ_SC_DAQ_BUF_NO_SPACE_LEFT; 
  target->len=source->len;
  target->eto=source->eto;
  target->ato=source->ato;
  memcpy(&target->buf[0],source->buf,source->len);
  return DAQ_SC_SUCCESSFUL;
}


status_code DAQ_Compute_CRC16(DAQ_CMD_BUF *b) {
  b->crc16=CM_Compute_CRC16  (0,b->buf,b->len);
  return CM_RC_SUCCESSFUL;
}


status_code DAQ_Compute_CRC8 (DAQ_CMD_BUF *b) {
  b->crc8 =CM_Compute_CRC8_8 (0,b->buf,b->len);
  return CM_RC_SUCCESSFUL;
}



status_code DAQ_Format_CMD(BOOL append,DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF *devcmd,
			   DAQ_OPCODE opcode,DAQ_FE fe,BYTE esectimeout,BYTE anstimeout) {
  BYTE *tbuf=idaqcmd->buf;
  BYTE *ssbuf=devcmd->buf;
  BYTE npk,rem,i;
  BYTE islong=devcmd->len > DAQ_SSBUF_SHORTCMD_LIMIT;
  status_code s;
  unsigned int flen,idaqcmd_len;

  if(islong) {
    npk=(devcmd->len-DAQ_SSBUF_SHORTCMD_LIMIT) / DAQ_SSBUF_LONGCMD_LIMIT;
    rem=(devcmd->len-DAQ_SSBUF_SHORTCMD_LIMIT) % DAQ_SSBUF_LONGCMD_LIMIT;
    flen=devcmd->len+4+npk+(rem?1:0);    
  }else{
    flen=devcmd->len+4;
  }

  if(append==DAQ_APPEND) {
    idaqcmd_len = idaqcmd->len + flen;
    tbuf=&idaqcmd->buf[idaqcmd->len];
  }else{
    idaqcmd_len = flen;
  }

  if(idaqcmd_len > idaqcmd->size)
    return DAQ_SC_DAQ_BUF_NO_SPACE_LEFT;
  
  idaqcmd->len = idaqcmd_len;


  // 0 (1) | cmd length (7)
  *tbuf++ =islong ?  0x7F : 0x7F & devcmd->len+3;
  // Opcode (4) | #link (4):
  *tbuf++ =(opcode << 4) | ( ((BYTE)fe) & 0x0F);
  // Esec timeout (4) | ans timeout (4):
  *tbuf++ =(esectimeout << 4) | (anstimeout & 0x0F);
  if(islong) {
    memcpy(tbuf,ssbuf,DAQ_SSBUF_SHORTCMD_LIMIT);
    ssbuf+=DAQ_SSBUF_SHORTCMD_LIMIT;
    tbuf+=DAQ_SSBUF_SHORTCMD_LIMIT; 
    for(i=0;i<npk;i++) {
      *tbuf++=0x7F;
      memcpy(tbuf,ssbuf,DAQ_SSBUF_LONGCMD_LIMIT);
      ssbuf+=DAQ_SSBUF_LONGCMD_LIMIT;
      tbuf+=DAQ_SSBUF_LONGCMD_LIMIT;
    }
    if(rem) {
      *tbuf++=rem+1;
      memcpy(tbuf,ssbuf,rem);
      tbuf+=rem;
    }
  }else{
    memcpy(tbuf,ssbuf,devcmd->len);
    tbuf+=devcmd->len;
  }
  *tbuf++=0xAA;
  return DAQ_SC_SUCCESSFUL;
}


status_code DAQ_Format_OneByteCmd(DAQ_CMD_BUF* cmdbuffer,BYTE cmd) {
  DAQ_CTRL_SET_LEN(cmdbuffer,1);
  cmdbuffer->buf[0]=cmd;
  return DAQ_SC_SUCCESSFUL;
}


status_code DAQ_Format_Flash_SectorErase(DAQ_CMD_BUF* cmdbuffer,BYTE sector) {
  DAQ_CTRL_SET_LEN(cmdbuffer,2);
  cmdbuffer->buf[0]=0x1E;
  if(sector > 0x11) {
#ifndef I386
    LU_INFN_LOG(LU_INTERNAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,sector);
#endif  // I386
    return DAQ_SC_BAD_FLASH_SECTOR;
  }
  cmdbuffer->buf[1]=sector;
  cmdbuffer->eto = DAQ_FLASH_SECTORERASE_ETO;
  cmdbuffer->ato = DAQ_FLASH_SECTORERASE_ATO;
  return DAQ_SC_SUCCESSFUL;
}


status_code DAQ_Format_Flash_SetAddress(DAQ_CMD_BUF* cmdbuffer,unsigned int addr) {
  DAQ_CTRL_SET_LEN(cmdbuffer,4);
  cmdbuffer->buf[0]=0x2D;
  cmdbuffer->buf[1]=(BYTE)  (addr & 0x000000ff);
  cmdbuffer->buf[2]=(BYTE) ((addr & 0x0000ff00) >> 8);
  cmdbuffer->buf[3]=(BYTE) ((addr & 0x00ff0000) >> 16);
  cmdbuffer->eto = DAQ_FLASH_SETADDRESS_ETO;
  cmdbuffer->ato = DAQ_FLASH_SETADDRESS_ATO;
  return DAQ_SC_SUCCESSFUL;
}

status_code DAQ_Format_Flash_WriteData(DAQ_CMD_BUF* cmdbuffer,DAQ_CMD_BUF *data) {
  DAQ_CTRL_SET_LEN(cmdbuffer,1);
  cmdbuffer->buf[0]=0x33;
  DAQ_Format_AppendBuffer(cmdbuffer,data);

  cmdbuffer->eto = DAQ_FLASH_WRITEDATA_ETO;
  cmdbuffer->ato = DAQ_FLASH_WRITEDATA_ATO;

  return DAQ_SC_SUCCESSFUL;
}

status_code DAQ_Format_Flash_EndBlock(DAQ_CMD_BUF* cmdbuffer) {
  cmdbuffer->eto = DAQ_FLASH_ENDBLOCK_ETO;
  cmdbuffer->ato = DAQ_FLASH_ENDBLOCK_ATO;
  return DAQ_Format_OneByteCmd(cmdbuffer,0x55);
}

status_code DAQ_Format_Flash_ReadData(DAQ_CMD_BUF* cmdbuffer) {
  cmdbuffer->eto = DAQ_FLASH_READDATA_ATO;
  cmdbuffer->ato = DAQ_FLASH_READDATA_ATO;
  return DAQ_Format_OneByteCmd(cmdbuffer,0x4B);
}


status_code DAQ_Format_Ram_SetAddress(DAQ_CMD_BUF* cmdbuffer,unsigned int addr) {
  DAQ_CTRL_SET_LEN(cmdbuffer,4);
  cmdbuffer->buf[0]=0x2D;
  cmdbuffer->buf[1]=(BYTE)  (addr & 0x000000ff);
  cmdbuffer->buf[2]=(BYTE) ((addr & 0x0000ff00) >> 8);
  cmdbuffer->buf[3]=(BYTE) ((addr & 0x00ff0000) >> 16);
  cmdbuffer->eto = DAQ_RAM_SETADDRESS_ETO;
  cmdbuffer->ato = DAQ_RAM_SETADDRESS_ATO;
  return DAQ_SC_SUCCESSFUL;
}


status_code DAQ_Format_Ram_WriteData(DAQ_CMD_BUF* cmdbuffer,DAQ_CMD_BUF *data) {
  DAQ_CTRL_SET_LEN(cmdbuffer,1);
  cmdbuffer->buf[0]=0x33;
  DAQ_Format_AppendBuffer(cmdbuffer,data);

  cmdbuffer->eto = DAQ_RAM_WRITEDATA_ETO;
  cmdbuffer->ato = DAQ_RAM_WRITEDATA_ATO;

  return DAQ_SC_SUCCESSFUL;
}

status_code DAQ_Format_Ram_EndBlock(DAQ_CMD_BUF* cmdbuffer) {
  cmdbuffer->eto = DAQ_RAM_ENDBLOCK_ETO;
  cmdbuffer->ato = DAQ_RAM_ENDBLOCK_ATO;
  return DAQ_Format_OneByteCmd(cmdbuffer,0x55); 
}

status_code DAQ_Format_Ram_ReadData(DAQ_CMD_BUF* cmdbuffer) {


  cmdbuffer->eto = DAQ_RAM_READDATA_ETO;
  cmdbuffer->ato = DAQ_RAM_READDATA_ATO;

  return DAQ_Format_OneByteCmd(cmdbuffer,0x4b); 
}


status_code DAQ_Format_Dsp_StartProgram(DAQ_CMD_BUF* cmdbuffer) {
  cmdbuffer->eto = DAQ_DSP_STARTPROGRAM_ETO;
  cmdbuffer->ato = DAQ_DSP_STARTPROGRAM_ATO;
  return DAQ_Format_OneByteCmd(cmdbuffer,0x1E); 
}

status_code DAQ_Format_Dsp_SetAddress(DAQ_CMD_BUF* cmdbuffer,BOOL PMDM,unsigned int addr) {
  DAQ_CTRL_SET_LEN(cmdbuffer,3);
  cmdbuffer->buf[0]=0x2d;
  cmdbuffer->buf[1]= (BYTE) ( ((PMDM ? 1 : 0) << 7) | ( (addr & 0x00007F00) >> 8  ) );
  cmdbuffer->buf[2]= (BYTE) ( addr & 0x000000FF );
  cmdbuffer->eto = DAQ_DSP_SETADDRESS_ETO;
  cmdbuffer->ato = DAQ_DSP_SETADDRESS_ATO;
  return DAQ_SC_SUCCESSFUL;
}

status_code DAQ_Format_Dsp_SetAddressPM(DAQ_CMD_BUF* cmdbuffer,unsigned int addr) {
  return DAQ_Format_Dsp_SetAddress(cmdbuffer,0,addr);
}

status_code DAQ_Format_Dsp_SetAddressDM(DAQ_CMD_BUF* cmdbuffer,unsigned int addr) {
  return DAQ_Format_Dsp_SetAddress(cmdbuffer,1,addr);
}

status_code DAQ_Format_Dsp_WriteData(DAQ_CMD_BUF* cmdbuffer,DAQ_CMD_BUF *data) {
  DAQ_CTRL_SET_LEN(cmdbuffer,2);
  cmdbuffer->buf[0]=0x33;
  cmdbuffer->buf[1]=(BYTE) data->len;

  cmdbuffer->eto = DAQ_DSP_WRITEDATA_ETO;
  cmdbuffer->ato = DAQ_DSP_WRITEDATA_ATO;

  return DAQ_Format_AppendBuffer(cmdbuffer,data);  
}

status_code DAQ_Format_Dsp_ReadData(DAQ_CMD_BUF* cmdbuffer) {

  cmdbuffer->eto = DAQ_DSP_READDATA_ETO;
  cmdbuffer->ato = DAQ_DSP_READDATA_ATO;

  return DAQ_Format_OneByteCmd(cmdbuffer,0x4b);
}

status_code DAQ_Format_Dsp_CheckMemory(DAQ_CMD_BUF* cmdbuffer) {
  cmdbuffer->eto = DAQ_DSP_CHECKMEMORY_ETO;
  cmdbuffer->ato = DAQ_DSP_CHECKMEMORY_ATO;
  return DAQ_Format_OneByteCmd(cmdbuffer,0x55);
}

status_code DAQ_Format_Dsp_ResetDSP(DAQ_CMD_BUF* cmdbuffer) {
  cmdbuffer->eto = DAQ_DSP_RESET_ETO;
  cmdbuffer->ato = DAQ_DSP_RESET_ATO;
  return DAQ_Format_OneByteCmd(cmdbuffer,0x66);
}



status_code DAQ_Format_Dsp_FlagRead(DAQ_CMD_BUF* cmdbuffer) {
  cmdbuffer->eto = DAQ_DSP_FLAGREAD_ETO;
  cmdbuffer->ato = DAQ_DSP_FLAGREAD_ATO;
  return DAQ_Format_OneByteCmd(cmdbuffer,0x78);
}



// ----------------------- Functions to format "IDAQ" Commands -------------------------

/*
 *  DAQ_Format_Fe2Daq
 *  
 *  Appends into the buffer 'idaqbuf' the "Fe2Daq" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the FE
 *     link     : the link to send the command to
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Fe2Daq(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer,DAQ_FE link) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_FE2DAQ,link,
			cmdbuffer->eto,cmdbuffer->ato);
}


/*
 *  DAQ_Format_Fe2Ram
 *  
 *  Appends into the buffer 'idaqbuf' the "Fe2Ram" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the FE
 *     link     : the link to send the command to
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Fe2Ram(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer,DAQ_FE link) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_FE2RAM,link,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Fe2Dsp
 *  
 *  Appends into the buffer 'idaqbuf' the "Fe2Dsp" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the FE
 *     link     : the link to send the command to.
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Fe2Dsp(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer,DAQ_FE link) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_FE2DSP,link,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Dsp2Daq
 *  
 *  Appends into the buffer 'idaqbuf' the "Dsp2Daq" IDAQ command.
 *    
 *  Input:
 *     cmdbuffer: the buffer containing the command for the DSP. 
 *                ETO/ATO information is transfered from cmdbuffer
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Dsp2Daq(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_DSP2DAQ,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Dsp2Ram
 *  
 *  Appends into the buffer 'idaqbuf' the "Dsp2Ram" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the DSP
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Dsp2Ram(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_DSP2RAM,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato);
}
/*
 *  DAQ_Format_Flash2Dsp
 *  
 *  Appends into the buffer 'idaqbuf' the "Flash2Dsp" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the DSP
 *                ETO/ATO information is transfered from cmdbuffer to idaqbuf
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Flash2Dsp(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_FLASH2DSP,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Flash2Dsp
 *  
 *  Appends into the buffer 'idaqbuf' the "Flash2Fe" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the Flash
 *                ETO/ATO information is transfered from cmdbuffer
 *     link     : the link to send the command to.
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Flash2Fe(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer,DAQ_FE link) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_FLASH2FE,link,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Ram2Daq
 *  
 *  Appends into the buffer 'idaqbuf' the "Ram2Daq" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the IDAQ RAM
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Ram2Daq(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_RAM2DAQ,DAQ_FE_SPARE,cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Ram2Dsp
 *  
 *  Appends into the buffer 'idaqbuf' the "Ram2Dsp" IDAQ command.
 *  
 *  Input:
 *     cmdbuffer: the buffer containing the command for the IDAQ DSP
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Ram2Dsp(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_RAM2DSP,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato);
}


/*
 *  DAQ_Format_ReleaseBusy
 *  
 *  Appends into the buffer 'idaqbuf' the "ReleaseBusy" IDAQ command.
 *  
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_ReleaseBusy(DAQ_CMD_BUF* idaqcmd) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,&nullbuf,DAQ_OP_RELEASEBUSY,DAQ_FE_SPARE,
			DAQ_RELEASEBUSY_ETO,DAQ_RELEASEBUSY_ATO);
}



status_code DAQ_Format_Spare(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_SPARE,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato);
}


/*
 *  DAQ_Format_Cmd2Fe
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Fe" IDAQ command.
 *  
 *  Input: 
 *     cmdbuffer: the buffer to send to the FE
 *                ETO/ATO information is transfered from cmdbuffer
 *     link     : the link ID of the FE
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */
status_code DAQ_Format_Cmd2Fe(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer,DAQ_FE link) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_CMD2FE,link,
			cmdbuffer->eto,cmdbuffer->ato);
}


/*
 *  DAQ_Format_Cmd2Flash
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Flash" IDAQ command.
 *  
 *  Input: 
 *     cmdbuffer: the buffer containing the command for the IDAQ Flash
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */
status_code DAQ_Format_Cmd2Flash(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_CMD2FLASH,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Cmd2Dsp
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command.
 *  
 *  Input: 
 *     cmdbuffer: the buffer containing the command for the IDAQ DSP
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */
status_code DAQ_Format_Cmd2Dsp(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_CMD2DSP,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Cmd2Flash
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Ram" IDAQ command.
 *  
 *  Input: 
 *     cmdbuffer: the buffer containing the command for the IDAQ RAM
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */
status_code DAQ_Format_Cmd2Ram(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_CMD2RAM,DAQ_FE_SPARE,
			cmdbuffer->eto,cmdbuffer->ato
			);
}


/*
 *  DAQ_Format_Ram2Fe
 *  
 *  Appends into the buffer 'idaqbuf' the "Ram2Fe" IDAQ command.
 *  
 *  Input: 
 *     cmdbuffer: the buffer containing the command for the IDAQ RAM
 *                ETO/ATO information is transfered from cmdbuffer
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */
status_code DAQ_Format_Ram2Fe(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* cmdbuffer,DAQ_FE link) {
  return DAQ_Format_CMD(DAQ_APPEND,idaqcmd,cmdbuffer,DAQ_OP_RAM2FE,link,
			cmdbuffer->eto,cmdbuffer->ato);
}

/*
 *  DAQ_Format_Cmd2Ram_SetAddress
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Ram" IDAQ command that set the address for the RAM.
 *  
 *  Input: 
 *     cmdbuffer: the buffer to send to the FE
 *     addr     : the IDAQ RAM address to set to.
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Ram_SetAddress(DAQ_CMD_BUF* idaqcmd,unsigned int addr) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Ram_SetAddress(&tempbuf,addr),
				 DAQ_Format_Cmd2Ram(idaqcmd,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Ram_WriteData
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Ram" IDAQ command that Write the data into the IDAQ RAM.
 *  
 *  Input: 
 *     data     : the buffer containing the data to write.
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Ram_WriteData (DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF* data) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Ram_WriteData(&tempbuf,data),
				 DAQ_Format_Cmd2Ram(idaqcmd,&tempbuf)
				 );
}




/*
 *  DAQ_Format_Cmd2Ram_ReadData
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Ram" IDAQ command that Read data from the IDAQ RAM.
 *  
 *  Input: 
 *     
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Ram_ReadData (DAQ_CMD_BUF* idaqcmd) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Ram_ReadData(&tempbuf),
				 DAQ_Format_Cmd2Ram(idaqcmd,&tempbuf)
				 );
}



/*
 *  DAQ_Format_Cmd2Ram_EndBlock
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Ram" IDAQ command containg the "end block" command for the
 *  IDAQ RAM.
 *  
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Cmd2Ram_EndBlock  (DAQ_CMD_BUF* idaqcmd) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Ram_EndBlock(&tempbuf),
				 DAQ_Format_Cmd2Ram(idaqcmd,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Dsp_StartProgram
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command that send the "start program" command 
 *  to the IDAQ DSP
 *
 *  Input: 
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Dsp_StartProgram(DAQ_CMD_BUF* idaqcmd) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Dsp_StartProgram(&tempbuf),
				 DAQ_Format_Cmd2Dsp(idaqcmd,&tempbuf);
				 );
}

/*
 *  DAQ_Format_Cmd2Dsp_SetAddressPM
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command that set the address for program memory
 *  of the IDAQ DSP
 *
 *  Input: 
 *     addr     : the DSP program memory address to set to.
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Cmd2Dsp_SetAddressPM(DAQ_CMD_BUF* idaqcmd,unsigned int addr) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Dsp_SetAddressPM(&tempbuf,addr),
				 DAQ_Format_Cmd2Dsp(idaqcmd,&tempbuf)
				 );
}


/*
 *  DAQ_Format_Cmd2Dsp_SetAddressDM
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command that set the address for data    memory
 *  of the IDAQ DSP
 *
 *  Input: 
 *     addr     : the DSP data    memory address to set to.
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Cmd2Dsp_SetAddressDM(DAQ_CMD_BUF* idaqcmd,unsigned int addr) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Dsp_SetAddressDM(&tempbuf,addr),
				 DAQ_Format_Cmd2Dsp(idaqcmd,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Dsp_WriteData
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command that write the data into the IDAQ DSP  
 *
 *  Input: 
 *     data     : the buffer containing the data to write into the DSP.
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Cmd2Dsp_WriteData(DAQ_CMD_BUF* idaqcmd,DAQ_CMD_BUF *data) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Dsp_WriteData(&tempbuf,data),
				 DAQ_Format_Cmd2Dsp(idaqcmd,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Dsp_CheckMemory
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command that is "check memory" for the IDAQ DSP
 *
 *  Input: 
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Cmd2Dsp_CheckMemory(DAQ_CMD_BUF* cmdbuffer) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Dsp_CheckMemory(&tempbuf),
				 DAQ_Format_Cmd2Dsp(cmdbuffer,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Dsp_CheckMemory
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command that is "reset DSP" for the IDAQ DSP
 *
 *  Input: 
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Cmd2Dsp_ResetDSP(DAQ_CMD_BUF* cmdbuffer) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Dsp_ResetDSP(&tempbuf),
				 DAQ_Format_Cmd2Dsp(cmdbuffer,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Dsp_FlagRea
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Dsp" IDAQ command that is "flag READ" for the IDAQ DSP
 *
 *  Input: 
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Dsp_FlagRead(DAQ_CMD_BUF* cmdbuffer) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Dsp_FlagRead(&tempbuf),
				 DAQ_Format_Cmd2Dsp(cmdbuffer,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Flash_SectorErase
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Flash" IDAQ command to Erase a flash sector
 *
 *  Input: 
 *     sector   : the IDAQ flash sector to erase.
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Flash_SectorErase(DAQ_CMD_BUF* cmdbuffer,BYTE sector) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Flash_SectorErase(&tempbuf,sector),
				 DAQ_Format_Cmd2Flash(cmdbuffer,&tempbuf)
				 );
}


/*
 *  DAQ_Format_Cmd2Flash_SetAddress
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Flash" IDAQ command to set the address for the Flash.
 *
 *  Input: 
 *     addr     : the IDAQ flash address to set to
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */


status_code DAQ_Format_Cmd2Flash_SetAddress(DAQ_CMD_BUF* cmdbuffer,unsigned int addr) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Flash_SetAddress(&tempbuf,addr),
				 DAQ_Format_Cmd2Flash(cmdbuffer,&tempbuf)
				 );
}

/*
 *  DAQ_Format_Cmd2Flash_SetAddress
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Flash" IDAQ command to Write data into 
 *  the IDAQ Flash
 *
 *  Input: 
 *     data     : the Buffer containing the data to write into the Flash
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Flash_WriteData(DAQ_CMD_BUF* cmdbuffer,DAQ_CMD_BUF *data) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Flash_WriteData(&tempbuf,data),
				 DAQ_Format_Cmd2Flash(cmdbuffer,&tempbuf)
				 );
}
/*
 *  DAQ_Format_Cmd2Flash_EndBlock
 *  
 *  Appends into the buffer 'idaqbuf' the "Cmd2Flash" IDAQ command that is 'end block'
 *
 *  Input: 
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Cmd2Flash_EndBlock(DAQ_CMD_BUF* cmdbuffer) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Flash_EndBlock(&tempbuf),
				 DAQ_Format_Cmd2Flash(cmdbuffer,&tempbuf)
				 );
}



/*
 *  DAQ_Format_Ram2Daq_ReadData
 *  
 *  Appends into the buffer 'idaqbuf' the "Ram2Daq" IDAQ command that is 'read data'
 *
 *  Input: 
 *
 *  Output:
 *     idaqbuf  : the new command queue for the IDAQ. New command formatted is appended into the
 *                end of this buffer.
 *
 *  Return:
 *     see DAQ_STATUS_CODE
 *     
 */

status_code DAQ_Format_Ram2Daq_ReadData(DAQ_CMD_BUF* cmdbuffer) {
  DAQ_FORMAT_OPCODE_CMD_TEMPLATE(
				 DAQ_Format_Ram_ReadData(&tempbuf),
				 DAQ_Format_Ram2Daq(cmdbuffer,&tempbuf)
				 );
}




#ifndef I386

status_code DAQ_ReadStatusWord(UINT16 *statusword) {
  UINT16 combuf=0xAA;
  status_code s;
  s=HK_KHB_Cmd2FE(KHB_IDAQ,1,1,&combuf,statusword,10);
  if(s==CM_RC_SUCCESSFUL)
    /*@LOG Read IDAQ status word - idaq_st_word */
    LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,*statusword);
  else
    /*@LOG Error reading IDAQ status word - status */
    LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,s);
  return s;
}

status_code DAQ_WriteHeader2Buffer(DAQ_CMD_BUF *buffer,UINT32 counter,
				   BYTE pkt_type,UINT32 len,TI_TIME obt) {
  BYTE *start;
  if(buffer->size - buffer->len < SM_PKTHEADER_LEN) 
    return CM_RC_NO_SPACE_LEFT;
  start=(&(buffer->buf[buffer->len]));

  start[0]=PM_HEADER_1;
  start[1]=PM_HEADER_2;
  start[2]=PM_HEADER_3;

  start[3]=pkt_type;
  start[4]=pkt_type;

  start[5]=(counter>>16) & 0xff;
  start[6]=(counter>>8)  & 0xff;
  start[7]=(counter & 0xff);

  start[8] =(obt>>24) & 0xFF;
  start[9] =(obt>>16) & 0xFF;
  start[10]=(obt>> 8) & 0xFF;
  start[11]=(obt    ) & 0xFF;


  start[12]=(len>>16) & 0xff;
  start[13]=(len>>8 ) & 0xff;
  start[14]=(len    ) & 0xff;

  start[15]=CM_Compute_CRC16(0,start,15) & 0xff;
  buffer->len+=SM_PKTHEADER_LEN;
  
  return CM_RC_SUCCESSFUL;
}

status_code DAQ_WaitFreeCMDIF() {
  UINT32 counter;
  UINT16 n=0;
  OS_piTaskSuspend(1);
  while( (counter=SD_piGetCMDCounterLeft()) > 0 && (n++ < PRH_VAR_DAQ_WAITFREECMDIF_N)) {
    OS_piTaskSuspend(2);
  }
  if(counter > 0)
    return CM_RC_CMDIF_BUSY;
  return CM_RC_SUCCESSFUL;
      
}

status_code DAQ_WaitAllExpPageAvail() {
  UINT32 counter=0;
  while( !PM_pi_AllExpPageAvail() && counter++ < PRH_VAR_ALLPAGEAVAIL_ATTEMPT)
    OS_piTaskSuspend(2);
  if(counter > PRH_VAR_ALLPAGEAVAIL_ATTEMPT)
    return CM_RC_CMDIF_BUSY;
  return CM_RC_SUCCESSFUL;      
}


status_code DAQ_ResetPIF(UINT32 eto,UINT32 dto,SM_ACQMODE mode,BYTE pkttype) {
  status_code status;

  if ((status = DAQ_WaitFreeCMDIF()) == CM_RC_CMDIF_BUSY)
    {
      SD_piPIFReset();
      /*@LOG DAQ_ResetPIF: queue busy - status */
      LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    }

  if(status = DAQ_WaitAllExpPageAvail())
    /*@LOG Page not available in DAQ_ResetPIF */
    LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);

  SD_piSetEventTimeout(eto);
  SD_piSetDataTimeout(dto);
  PM_pi_SetAcqMode(mode);
  PM_pi_SetPktType(pkttype);
  return CM_RC_SUCCESSFUL;
}

BOOL DAQ_WaitFreePif() {
  UINT32 ppCounter=0;
  BOOL fullPIF;
  while( ( fullPIF = !PM_pi_ExpPageAvail() ) && ppCounter < PRH_VAR_RM_N_TRIES_PREPARE_PAGE) {
    ppCounter++;
    if(PRH_VAR_RM_TRIES_PREPARE_PAGE_SLEEP)
      OS_piTaskSuspend(PRH_VAR_RM_TRIES_PREPARE_PAGE_SLEEP);
  }
  return !fullPIF;
}


static status_code DAQ_SendCmd2PIFWaitDAQReply_internal(BOOL catch_sint,
							SM_PAGEID page,
							BOOL storemm, 
							DAQ_CMD_BUF *reply,
							BOOL storeram,
							status_code (*callback)()) 
{

  status_code status = CM_RC_SUCCESSFUL;
  status_code callback_status = CM_RC_SUCCESSFUL;
  rtems_event_set evout;
  unsigned int intLevel;
  unsigned int ppCounter;
  BOOL fullPIF;
  
  if(page < SM_CALEXP0 || page > SM_CALEXP3)
    return CM_RC_BADPAGE;
  
  if (storemm) {
    PM_pi_EnableStore_In_DataTimeOut();
  } else {
    PM_pi_DisableStore_In_DataTimeOut();
  }
  
  /* clear all events */
  OS_piEventClear(OS_EVENT_PKT_READY | 
		  //		  OS_EVENT_SINT | 
		  OS_EVENT_ETO | 
		  OS_EVENT_FLUSH_HB | 
		  OS_EVENT_UNCOMPLETED_CMDIF);
    
  PM_pi_UseCalibrationPage(page);

  OS_piInterDisable(&intLevel);
  SD_piClearInt(SD_DATA_TO | SD_PAGE_OVR | SD_EVT_TO);		
  SD_piUnMaskInt(SD_DATA_TO | SD_PAGE_OVR | SD_EVT_TO);		
  OS_piInterEnable(intLevel);
  //  OS_piInterDisable(&intLevel);

  fullPIF=!DAQ_WaitFreePif();
   //OS_piInterEnable(intLevel);

  if(fullPIF) {
    /* TBD: Some alarm here ? */
    /*	Reset  the pif: */
    // SD_piPIFReset();
    /*@LOG fullPIFF in DAQ_SendCmd2PIFWaitDAQReply_internal - status */
    LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
    status=UNSATISFIED;
  }else{ //ca    
    PM_pi_SetExpPktCpyFlag(storeram);      
    status = PM_piPreparePage(TRUE);
    if(status!=CM_RC_SUCCESSFUL){
      /*@LOG PreparePage failed in DAQ_SendCmd2PIFWaitDAQReply_internal - status */
      LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
      PM_pi_SetExpPktCpyFlag(FALSE);
      return status;
    }

    if(callback != NULL)  
      callback_status=callback();

    status=OS_piEventReceive(OS_EVENT_PKT_READY | 
			     (catch_sint ? OS_EVENT_SINT : 0) |
			     OS_EVENT_ETO | 
			     OS_EVENT_FLUSH_HB |
			     OS_EVENT_UNCOMPLETED_CMDIF, 
			     RTEMS_WAIT | RTEMS_EVENT_ANY , 
			     PRH_VAR_DAQ_EVENT_RECEIVE_TIMEOUT,&evout);

    OS_piInterDisable(&intLevel);
    SD_piMaskInt(SD_DATA_TO | SD_PAGE_OVR | SD_EVT_TO);
    OS_piInterEnable(intLevel);

    if(callback_status != CM_RC_SUCCESSFUL)
      return callback_status;

    PM_pi_SetExpPktCpyFlag(FALSE);
    switch (status) {
    case SUCCESSFUL:
      if(evout & OS_EVENT_SINT) {
	PM_pi_DisableStore_In_DataTimeOut();
	status = CM_RC_SINT;
      }else if(evout & OS_EVENT_FLUSH_HB) {
	RM_WriteHBInfos(FALSE);
      }else if(evout & OS_EVENT_PKT_READY) {
	if (storeram && reply && reply->buf)
	  {
	    if (PM_pi_GetPacket(&(reply->len),reply->buf) == SM_STR_OK)
	      status = CM_RC_SUCCESSFUL;
	    else 
	      status = CM_RC_STOREERROR;
	  }
      }else if(evout & OS_EVENT_ETO) {
	/* TBD: some alarm */
	status = CM_RC_RUNTIMEOUT;
      }else if(evout & OS_EVENT_UNCOMPLETED_CMDIF) {
	status = CM_RC_UNCOMPLETED_CMDIF;
      }
      break;
    case RTEMS_TIMEOUT:
      status = CM_RC_TIMEOUT;
      /*@LOG Timeout in DAQ_SendCmd2PIFWaitDAQReply_internal - status */
      LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
      break;
    default:
      status=UNSATISFIED;
      /*@LOG UNSATISFIED in DAQ_SendCmd2PIFWaitDAQReply_internal - status */
      LU_INFN_LOG(LU_CRITICAL|LU_HA,LU_MASK(__FILEID__),__FILEID__,__LINE__,status);
      break;  
    }
  }

  return status;
}

status_code DAQ_SendCmd2PIFWaitDAQReply(SM_PAGEID page,BOOL storemm, DAQ_CMD_BUF *reply,BOOL storeram) {
  return DAQ_SendCmd2PIFWaitDAQReply_internal(DAQ_CATCH_SINT, page, storemm, reply, storeram,NULL);
}

status_code DAQ_SendCmd2PIFWaitDAQReply_NoSINT(SM_PAGEID page,BOOL storemm, DAQ_CMD_BUF *reply,BOOL storeram) {
  return DAQ_SendCmd2PIFWaitDAQReply_internal(DAQ_NO_CATCH_SINT, page, storemm, reply, storeram,NULL);
}

status_code DAQ_SendCmd2PIFWaitDAQReply_CallBack(SM_PAGEID page,BOOL storemm, 
						 DAQ_CMD_BUF *reply,
						 BOOL storeram,
						 status_code (*callback)()) {
  return DAQ_SendCmd2PIFWaitDAQReply_internal(DAQ_CATCH_SINT, page, storemm, reply, storeram,callback);
}


status_code DAQ_StoreCmdQueue2PIF(SM_PAGEID page,DAQ_CMD_BUF *buf) {
  status_code status=CM_RC_SUCCESSFUL;
  SM_STRSTAT s;
  if(buf) {  
    s=PM_pi_CopyToSRAM(page , buf->buf , buf->len);
    if(s==SM_STR_OK)
      status=CM_RC_SUCCESSFUL;
    else
      status=CM_RC_STOREERROR;
  }else
    status=CM_RC_EMPTY_BUFFER;
  return status;
}

status_code DAQ_SendCmdQueue2CMDIF(SM_PAGEID page){
  UINT32 size;
  status_code status=CM_RC_SUCCESSFUL;
  SM_STRSTAT s;

  if(page < SM_CALEXP0 || page > SM_CALEXP3)
    status=CM_RC_BADPAGE;

  if(status==CM_RC_SUCCESSFUL){ 
    PM_pi_UseCalibrationPage(page);
    status = PM_piPreparePage(FALSE);
    if( status == CM_RC_SUCCESSFUL ) {
      if(status=DAQ_WaitFreeCMDIF())
	status =CM_RC_UNCOMPLETED_CMDIF;
    }
    /*
    size=PM_pi_GetDataLength(page);
    if(size == 0)
      status=CM_RC_EMPTY_BUFFER;
    
    if (status==CM_RC_SUCCESSFUL && FT_piSavePage(page,(page*SM_SRAMPAGESIZE) + size - 1,  FS_CMD) != FT_SUCCESS)
      status=CM_RC_STOREERROR;
    else
      if(status=DAQ_WaitFreeCMDIF())
	status =CM_RC_UNCOMPLETED_CMDIF;
    */
  }
  return status;
}

status_code DAQ_SaveBuffer2MM(DAQ_CMD_BUF *buffer, FS_FILEID id,UINT32 timeout)
{
  SM_STRSTAT strstat;
  status_code s=CM_RC_SUCCESSFUL;
  rtems_event_set out;
  if(buffer->len == 0)
    return CM_RC_EMPTY_BUFFER;
  if(id == FS_HK && timeout > 0) {
    /* wait for the OS_EVENT_SKETCHBOARD_FREE */
    s=OS_piEventReceive(OS_EVENT_SKETCHBOARD_FREE,RTEMS_WAIT,timeout,&out);
    if(s == RTEMS_TIMEOUT)
      s=CM_RC_TIMEOUT;
  }
  if ((s != CM_RC_TIMEOUT) &&
      (strstat = PM_pi_StorePacket(buffer->len,buffer->buf,id)) != SM_STR_OK) {
    s = CM_RC_STOREERROR;
  }
  //TDB

  return(s);
}





#endif // I386



