#include <ansi_c.h>
 
#include "CAENV673A.h"
 
#include "CAENV673A_DEF.h"
 
//#include "pcivme_dll.h"
 
#ifdef SISVME
 
#include "sisvme_dll.h"
 
#endif
 
#ifdef WIENVME
 
#include "wienvme_dll.h"
 
#endif
 
#ifdef WUSBVME
 
#include "wusbvme_dll.h"
 
#endif
 
 
 
unsigned int ModuleAddress[10];
 
static const unsigned short bufevnum[2][4]=
 
    {CAENV673A_ENR0B0, CAENV673A_ENR0B1, CAENV673A_ENR0B2, CAENV673A_ENR0B3,
 
     CAENV673A_ENR1B0, CAENV673A_ENR1B1, CAENV673A_ENR1B2, CAENV673A_ENR1B3};
 
 
 
int V673A_map (int ModuleNumber,
 
                         unsigned long ModuleOffset, int print)
 
{
 
  unsigned long vsr, mmt, fix;
 
  
 
  ModuleAddress[ModuleNumber] =  ModuleOffset;
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_FIX, &fix);
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_MMT, &mmt);
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_VSR, &vsr);
 
  if (print) {
 
    printf("fixed code = 0x%04x\n", fix
);  
    printf("manufacturer number = %i\n", MANUFACTURER
(mmt
));  
    printf("module type = %i\n", MODULE_TYPE
(mmt
));  
    printf("version = %i\n", VERSION
(vsr
));  
    printf("serial no. = %i\n", SERIAL
(vsr
));  
  }
 
  if ((fix != CAEN_FIX_CODE) || (mmt != CAENV673A_MMT_VALUE)) return -1;
 
  return 0;
 
}
 
 
 
int V673A_init (int ModuleNumber)
 
{
 
  unsigned long dum16;
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_CLRTDC, &dum16);
 
 
 
  dum16= 0xF77F;
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MCR0,dum16);
 
  dum16= 0xF77F;
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MCR1, dum16);
 
 
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_CLALLB, &dum16);
 
  /* range 2**(NBITS+1)*1.0416s
 
     NBITS = 
 
             4         32 ns
 
             5         64
 
             6         128
 
             7         256
 
             8         512
 
             9        1024
 
             A        2048
 
             B        4096
 
             C        8200
 
             D       16400
 
             E       32000
 
   */          
 
  dum16=0x003A;// RANGE  2048 ns
 
  //dum16=0x003E; //range 32us  
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_CRR0, dum16);
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_CRR1, dum16);
 
 
 
  dum16=0x001A;
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_CLKCR0, dum16);
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_CLKCR1, dum16);
 
  
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BEGDLL, &dum16);
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_CLALLB, &dum16);
 
 
 
  dum16=0xF35F; // both edges  + stop mode
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MCR0, dum16);
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MCR1, dum16);
 
 
 
  dum16=0xFFFF; 
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MR0L, dum16);
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MR0H, dum16);
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MR1L, dum16);
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + CAENV673A_MR1H, dum16);
 
  
 
  return 0;
 
}
 
 
 
int V673A_status (int ModuleNumber)
 
{
 
  unsigned long dum16;
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BSR, &dum16); 
 
  return dum16;
 
}
 
 
 
int V673A_ntrig (int ModuleNumber)
 
{
 
  unsigned long ntr[2];
 
  
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_ENR0, &ntr[0] );
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_ENR1, &ntr[1] );
 
  
 
  if (ntr[0] == ntr[1]) return ntr[0];
 
  else printf ("CAENV673A [%d] ENR0=%04x ENR1=%04x\n",ModuleNumber
, ntr
[0],ntr
[1]);  
  return -1;
 
}
 
 
 
int V673A_read0 (int ModuleNumber, unsigned long whereto[], int size)
 
{
 
  unsigned long status, ndata;
 
  unsigned int data;
 
  
 
  ndata = 0;
 
  if (size<=0) return 0;
 
 
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BSR, &status);
 
  if (!(status & (1<<5))) {
 
    //printf ("CAENV673A  BSR STATUS=%04x\n",status);
 
    return 0;
 
  }
 
  VME_A24D32_R(ModuleAddress[ModuleNumber] + CAENV673A_SEQ0, &data  );
 
  *whereto= data;
 
  if ((*whereto) & (1<<23)) {
 
    ndata++;
 
    do {  
 
    VME_A24D32_R(ModuleAddress[ModuleNumber] + CAENV673A_SEQ0, &data);
 
      *(++whereto) = data;
 
      ndata++;
 
    } while (!((*whereto) & ((1<<30) | (1<<31))) && ndata<size);
 
    if (ndata>=size) {
 
       
 
       printf("V673A_read0 Increase buffer size ndata=%d\ndata=0x%x\n", ndata
,data
);    
       return ndata;
 
    }
 
    if (!((*whereto) & (1<<31))) return ndata;
 
  }
 
    
 
  return 0;  
 
 
 
}
 
 
 
int V673A_read1 (int ModuleNumber, unsigned long whereto[], int size)
 
{
 
  unsigned long  status, ndata;
 
  unsigned int data;
 
 
 
  ndata = 0;
 
  if (size<=0) return 0;
 
  
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BSR, &status);
 
  if (!(status & (1<<7))) return 0;
 
 
 
  
 
  VME_A24D32_R(ModuleAddress[ModuleNumber] + CAENV673A_SEQ1, &data);
 
  *whereto = data;    
 
  if ((*whereto) & (1<<23)) {
 
    ndata++;
 
    do {
 
    VME_A24D32_R(ModuleAddress[ModuleNumber] + CAENV673A_SEQ1, &data);  
 
      *(++whereto) =  data;
 
      ndata++;
 
    } while (!((*whereto) & ((1<<30) | (1<<31))) && ndata<size);
 
    if (ndata>=size) {
 
       printf("V673A_read1 Increase buffer size ndata=%d\ndata=0x%x\n", ndata
,data
);  
       return ndata;
 
    }
 
    if (!((*whereto) & (1<<31))) return ndata;
 
  }
 
    
 
  return 0;  
 
 
 
}
 
 
 
int V673A_firstevnt (int ModuleNumber)
 
{
 
  unsigned long status, ptr;
 
  int evn[2];
 
  
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BSR, &status);
 
  if (!(status & 0x8000)) return -1;
 
  
 
  if (status & 0x0020) {
 
    VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_PTR0, &ptr);
 
    ptr &= 0x3;
 
    evn[0]=0;
 
    VME_A24D16_R(ModuleAddress[ModuleNumber] + bufevnum[0][ptr], &evn[0]);
 
   } else {
 
    evn[0]=0x10000;
 
  }
 
  if (status & 0x0080) {
 
    VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_PTR1, &ptr);
 
    ptr &= 0x3;
 
    evn[1]=0;
 
    VME_A24D16_R(ModuleAddress[ModuleNumber] + bufevnum[1][ptr], &evn[1]);
 
   } else {
 
    evn[1]=0x10000;
 
  }
 
  //printf ("first event [%d] evn: %d %d \n",ModuleNumber ,evn[0]&0xffff,evn[1]&0xffff);
 
  if (evn[0] < evn[1]) {
 
    return evn[0];
 
   } else {
 
    return evn[1];
 
  }
 
}
 
 
 
int V673A_getevnt (int ModuleNumber, int evn, unsigned long whereto[], int size)
 
{
 
  unsigned long dum16;
 
  unsigned long status, bptr, bevn, ndata;
 
  int msize=size;
 
  ndata=0;
 
 
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BSR, &status);
 
  if (!(status & 0x8000)) return -1;
 
  
 
  while (1) {
 
    if (status & 0x0020) {
 
      VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_PTR0, &bptr);
 
      bptr &= 0x3;
 
      VME_A24D16_R(ModuleAddress[ModuleNumber] + bufevnum[0][bptr], &bevn);
 
      if (bevn == evn) {
 
        ndata += V673A_read0(ModuleNumber, whereto, msize);
 
        msize-=ndata;
 
        whereto += ndata;
 
        break;
 
       } else if (bevn < evn) {
 
        VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_CLRCB0, &dum16);
 
        VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BSR, &status);
 
        if (!(status & 0x8000)) return ndata;
 
       } else {
 
        break;
 
      }
 
     } else {
 
      break;
 
    }
 
  }
 
  while (1) {
 
    if (status & 0x0080) {
 
      VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_PTR1, &bptr);
 
      bptr &= 0x3;
 
      VME_A24D16_R(ModuleAddress[ModuleNumber] + bufevnum[1][bptr], &bevn);
 
      if (bevn == evn) {
 
        ndata += V673A_read1(ModuleNumber, whereto, msize);
 
        msize-=ndata;
 
        break;
 
       } else if (bevn < evn) {
 
        VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_CLRCB1, &dum16);
 
        VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_BSR, &status);
 
        if (!(status & 0x8000)) return ndata;
 
       } else {
 
        break;
 
      }
 
     } else {
 
      break;
 
    }
 
  }
 
  return ndata;  
 
}
 
 
 
 
 
 
 
int V673A_clallb (int ModuleNumber){
 
  unsigned long dum16;  
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + CAENV673A_CLALLB, &dum16); 
 
  return 0;
 
}
 
 
 
int V673A_getreg (int ModuleNumber, int reg){
 
  unsigned long dum16;
 
  VME_A24D16_R(ModuleAddress[ModuleNumber] + reg, &dum16); 
 
  return dum16;
 
}
 
 
 
void V673A_setreg (int ModuleNumber, int reg, int set){
 
  unsigned long dum16=set;
 
  VME_A24D16_W(ModuleAddress[ModuleNumber] + reg, dum16);
 
  return;
 
}