//
// test.c
//
// Description : test program for V729
//
// Author : S. Korpar
// Date : 2005/07/15
// adapted to CAEN V1719 by R. Pestotnik 2012/09/07
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <vector>
#include <sys/time.h>
#include <sys/stat.h>
#include <signal.h>
#include <string>
#include "vme.h"
#include "CAEN_V729_DEF.h"
#define V729_OFFSET 0x880000
#define IREG_OFFSET 0x2000
#define V729_WAIT 1
#define TRUE 1
#define FALSE 0
uint32_t V729_module=0;
int timer_out;
struct sigaction oact;
//---------------------------------------------------------
void SigInt (int sig)
{
timer_out=1;
}
//---------------------------------------------------------
void timerast (int signumber)
{
timer_out = TRUE;
}
//---------------------------------------------------------
void tmlnk (int tout)
{
timer_out = FALSE;
struct sigaction act;
struct itimerval tdelay;
act.sa_handler = timerast;
sigemptyset (&act.sa_mask);
act.sa_flags = 0;
tdelay.it_value.tv_sec = tout / 100;
tdelay.it_value.tv_usec = 10000 * (tout % 100);
tdelay.it_interval.tv_sec = 0;
tdelay.it_interval.tv_usec = 0;
if (sigaction (SIGALRM, &act, &oact) < 0)
{
}
if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0)
{
}
}
//---------------------------------------------------------
void tmulk ()
{
struct itimerval tdelay;
tdelay.it_value.tv_sec = 0;
tdelay.it_value.tv_usec = 0;
tdelay.it_interval.tv_sec = 0;
tdelay.it_interval.tv_usec = 0;
if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0)
{
}
if (sigaction (SIGALRM, &oact, NULL) < 0)
{
}
}
//---------------------------------------------------------
int wait_while(int num){
int i, tmp;
for ( i =0; i <num; i++ ) tmp = 0;
return tmp;
}
//---------------------------------------------------------
void V729_map( uint32_t addr)
{
V729_module = addr;
return;
}
//---------------------------------------------------------
void V729_info(FILE *kam)
{
unsigned short code, mid, ver;
VME_A24D16_R(V729_module+0xFA,&code);
VME_A24D16_R(V729_module+0xFC,&mid);
VME_A24D16_R(V729_module+0xFE,&ver);
fprintf(kam
, "code/mid/ver = 0x%04X/0x%04X/0x%04X\n", code
, mid
, ver
);
fprintf(kam
, "Fixed code (0xFAF5) = 0x%04X\n", code
);
fprintf(kam
, "Manufacturer/Type = 0x%02X/0x%03X\n",
(mid & 0xFC00)>>10, mid & 0x3FF);
fprintf(kam
, "Version/Serial = %d/%d\n",
(ver & 0xF000)>>12, ver & 0xFFF);
return;
}
//---------------------------------------------------------
void V729_reg( uint32_t val){
uint32_t push=0;
VME_A24D16_W(V729_module+V729_FSR, &val);
VME_A24D16_W(V729_module+V729_UFSR, &push); //push
usleep(V729_WAIT);
}
//---------------------------------------------------------
void V729_reset(int nall,int nbefore,int obae,int obaf)
{
uint32_t cbl;
// cbl=4096+12-100;
cbl=4096+12-nbefore;
uint32_t val=0;
VME_A24D16_W(V729_module+V729_RR, &val); // reset
printf("nbefore=%d\t", nbefore
);
// set AE
V729_reg( (obae & 0xFF)<<8 ) ; //
V729_reg( (obae & 0xF00) ) ; //
// set AF and CBL
V729_reg( ((obaf & 0xFF)<<8) + (cbl & 0xFF) );
V729_reg( (obaf & 0xF00) + ((cbl & 0xF00)>>8) );
VME_A24D16_W(V729_module+V729_SR,&nall); //total number of samples
return;
}
//---------------------------------------------------------
void V729_set_bias(int range, int bias1, int bias2)
{
int i;
uint32_t bias;
switch (range) {
case 0: //User
for (i=0x18;i<0x27;i+=4){
VME_A24D16_W(V729_module+i, &bias1); //bias
usleep(V729_WAIT);
VME_A24D16_W(V729_module+i+2, &bias2); //bias
usleep(V729_WAIT);
}
printf("Bias + %x - %x\n", bias1
, bias2
);
break;
case 1: //Single Ended +
for (i=0x18;i<0x27;i+=4){
bias = 0xCC; VME_A24D16_W(V729_module+i, &bias); //bias
usleep(V729_WAIT);
bias =0x733; VME_A24D16_W(V729_module+i+2, &bias); //bias
usleep(V729_WAIT);
}
break;
case 2: //Single Ended -
for (i=0x18;i<0x27;i+=4){
bias =0x733; VME_A24D16_W(V729_module+i, &bias); //bias
usleep(V729_WAIT);
bias= 0xD99 ; VME_A24D16_W(V729_module+i+2, &bias); //bias
usleep(V729_WAIT);
}
break;
case 4: //Differential Unipolar
for (i=0x18;i<0x27;i+=4){
bias = 0x400; VME_A24D16_W(V729_module+i,&bias); //bias
usleep(V729_WAIT);
bias = 0xA66; VME_A24D16_W(V729_module+i+2, &bias); //bias
usleep(V729_WAIT);
}
break;
case 3: //Single Ended Bipolar
case 5: //Differential Bipolar
default:
for (i=0x18;i<0x27;i+=2){
bias=0x733; VME_A24D16_W(V729_module+i, &bias); //bias
usleep(V729_WAIT);
}
break;
}
return;
}
//---------------------------------------------------------
void V729_aquisition_mode(uint32_t mode) // mode 0 aqusition mode, 0x30 buffers programming
{
#ifdef V729_DEBUG
int status;
VME_A24D16_R(V729_module+V729_CSR, &status);
usleep(V729_WAIT);
fprintf(stderr
, "0x0E = 0x%04X\n", status
);
#endif
VME_A24D16_W(V729_module+V729_CSR, &mode); //aquisition mode
usleep(V729_WAIT);
#ifdef V729_DEBUG
VME_A24D16_W(V729_module+V729_CSR, &status);
usleep(V729_WAIT);
fprintf(stderr
, "0x0E = 0x%04X\n", status
);
#endif
return;
}
//---------------------------------------------------------
void V729_soft_stop()
{
uint32_t sw=1;
VME_A24D16_W(V729_module+0x16,&sw);
// usleep(V729_WAIT);
sw =0;
VME_A24D16_W(V729_module+0x16,&sw);
// usleep(V729_WAIT);
return;
}
//---------------------------------------------------------
void V729_clear_buffer()
{
const int tout=100; /* 1/100 of a second */
tmlnk (tout);
uint32_t data1,data2;
do {
VME_A24D32_R(V729_module+V729_OBR1, &data1);
if (timer_out) break;
} while (data1 & (0x3<<29));
do {
VME_A24D32_R(V729_module+V729_OBR2, &data2);
if (timer_out) break;
} while (data2 & (0x3<<29));
tmulk();
return;
}
void V729_get_buffer(uint32_t *data1, uint32_t *data2)
{
VME_A24D32_R(V729_module+V729_OBR1, data1);
// usleep(V729_WAIT);
VME_A24D32_R(V729_module+V729_OBR2, data2);
// usleep(V729_WAIT);
return;
}
int V729_status()
{
uint32_t status;
VME_A24D16_R(V729_module+V729_CSR, &status);
return status;
}
//---------------------------------------------------------
void V729_init(uint32_t addr, int nall, int cbl, uint32_t bias1, uint32_t bias2){
V729_map(addr);
V729_info(stderr);
V729_reset(nall,cbl,nall,0xC00);
V729_set_bias(0,bias1,bias2);
V729_aquisition_mode(0);
CAENVME_SetFIFOMode(udev,1);
sleep(1);
}
//---------------------------------------------------------
int V729_event(int mask, int nall, uint32_t *data,uint32_t *data1,uint32_t *data2){
uint32_t status;
const int tout=100; /* 1/100 of a second */
tmlnk (tout);
int count=0;
//status= 0x80 ; VME_A16D16_W(IREG_OFFSET+0x8,&status); // pulse ch 8
status = 0x1a ; VME_A16D16_W(IREG_OFFSET+0xC,&status); // clr1 enable1 .... clear busy1 flag
do {
//usleep(1);
VME_A24D16_R(V729_module+V729_CSR, &status);
// fprintf(stderr,"0x%X, 0x%X\n",status,(status & 0x5) ^ 0x5);
count++;
if (timer_out) {
tmulk ();
printf("[%d] daq=%x status AE01=%d AE23=%d Waiting for DATA TRG bit... at line %d\n",count
, (status
>>4)&0x3, status
&0x1,(status
>>2)&0x1 , __LINE__
);
V729_clear_buffer();
return -1;
}
} while ((status & 0x5) ^ 0x5);
tmulk ();
int nb;
const int blt=1;
if (blt){
VME_A24D32_FIFOBLTR(V729_module+V729_OBR1,data1,(nall+5)*sizeof(uint32_t),&nb);
VME_A24D32_FIFOBLTR(V729_module+V729_OBR2,data2,(nall+5)*sizeof(uint32_t),&nb);
for (int i=0;i<nall+5;i++){
data[2*i] = data1[i];
data[2*i+1] = data2[i];
}
nb*=2;
} else {
VME_MRRST(); // MultiReadReset
int nc=0;
for (int i=0;i<nall+5;i++){
//if (mask & 0x3)
VME_A24D32_MR(V729_module+V729_OBR1, &data[nc++]);
//if (mask & 0xc)
VME_A24D32_MR(V729_module+V729_OBR2, &data[nc++]);
}
int j = VME_MREXEC(data); // MultiReadExecute
nb=j*sizeof(uint32_t);
}
return nb;
}
//---------------------------------------------------------
int V729_decode(uint32_t mask, int nall, uint32_t *data, uint16_t *dadc, int debug){
uint16_t *adc[4];
for (int i=0;i<4;i++) adc[i] = &dadc[4+i*(nall+2)];
int nc=0;
int narrays=0;
if (mask & 0x3) narrays++;
if (mask & 0xc) narrays++;
int indx[4] ={0,0,0,0};
int shft[4] ={0,0,0,0};
int ashft[4]={0,0,0,0};
int nmask=0;
for (int i=0;i<4;i++) if (mask & (1<<i) ) {
indx[nmask] = i;
shft[nmask] = (i%2)*12;
if (( (mask & 0x3) > 0 ) && (i>1)) ashft[nmask]=1 ;
else ashft[nmask]=0;
nmask++;
}
for (int j=0;j<nmask;j++){
nc=0;
for (int i=0;i<nall+5;i++){
int ii=narrays*i+ashft[j];
uint32_t data1 = data[ii];
if (data1 & (1<<31)) {
if (debug
) fprintf(stdout
,"data1: empty flags: 0x%X, time tag: 0x%06X\n", (data1
>>29) & 0x3, data1
& 0xFFFFFF);
} else if ((data1>>29) & 0x3){
if (nc<nall){
adc[j][nc] = (data1>>shft[j]) & 0xFFF;
if (debug
) printf("[%d/%d] ADC%d adc0=%d\n", i
,nc
,indx
[j
], adc
[j
][nc
]);
nc++;
}
} else {
if (debug
) fprintf(stdout
,"Data(%4d) %d indx=%d %d nc=%d(%d) %d 0x%08X\n", i
, indx
[j
],narrays
*i
+ashft
[j
],j
,nc
,nmask
,narrays
, data1
);
}
}
}
return nc;
}
//---------------------------------------------------------
// test program
#ifdef V729_MAIN
int ctrlc=0;
void CatchSig (int i){
ctrlc = 1;
}
int main(int argc,char **argv){
if (argc == 1) {
printf ("*********************************************************************************:\n");
printf ("Usage: %s <arguments> ......... CAEN V729A data aquisition:\n\n", argv
[0]);
printf ("-d <debuglevel> \n");
printf ("-a <VME address> \n");
printf ("-c <n samples before stop> \n");
printf ("-n <number of events> \n");
printf ("-l <nall> number of samples \n");
printf ("-m <channel mask: 4bits (1 bit/ch)> \n");
printf ("-o <output file name> \n");
printf ("*********************************************************************************:\n");
}
uint32_t mask=0xF;
int cbl=13;
int nall=1330;
char filename[0xFF]="";
int verbose = 0;
int neve = 1;
uint32_t addr= V729_OFFSET;
uint32_t bias1 = 0x600; // vecje vrednosti povzročajo težave in zacno kanali oscilirat ....
uint32_t bias2 = 0x200;
int append=0;
int c=0;
while ((c = getopt (argc, argv, "b:e:a:d:c:l:n:o:m:f:")) != -1)
switch (c){
case 'd':
break;
case 'c':
break;
case 'l':
if (nall%16) {
printf ("buffer length should be multiple of 16 , modulo = %d\n",nall
%16);
// exit(-1);
}
break;
case 'n':
break;
case 'a':
break; // address
case 'b':
break; // bias
case 'e':
break; // bias
case 'm':
break; // mask
case 'o':
append=0;
break; // output
case 'f':
append=1;
break; // output
}
// intercept routine
if (signal
(SIGINT
, CatchSig
) == SIG_ERR
) perror ("sigignore");
// reset timers
time_t t,told=0, tstart;
tstart=t;
// open file
FILE *fp=NULL;
int output=0;
if (verbose
) printf("Data in the file:%s\n", filename
);
if (append
) fp
=fopen(filename
,"a");
else fp
=fopen(filename
,"w");
output=1;
}
// alloocate storage
uint32_t *data = new uint32_t[2*(nall+5)];
uint32_t *data1 = new uint32_t[2*(nall+5)];
uint32_t *data2 = new uint32_t[2*(nall+5)];
int nmask=0;
for (int i=0;i<4;i++) if (mask & (1<<i)) nmask++;
int adclen = nall+2;
int len = nmask* adclen+2;
uint16_t *adc = new uint16_t[len]; // 4 channels + 4 ch header + 1 event hdr
// write headers
uint16_t *evhdr = &adc[0];
evhdr[0] = 0;
evhdr[1] = len *sizeof(uint16_t);
int imask=0;
for (int ch=0;ch<4;ch++){
if ( mask & (1<<ch) ) {
uint16_t *chhdr= &adc[2+imask*adclen];
chhdr[0] = ch+1;
chhdr[1] = adclen *sizeof(uint16_t);
imask++;
}
}
// start
int ncount =0;
int nerrors=0;
int nball =0;
// open VME and initialize board
char *serial = new char[100];
VME_START(serial);
printf("CAEN V1718 BoardFWRelease %s\n", serial
);
V729_init(addr, nall, cbl, bias1,bias2);
// event loop
for (int j=0; j<neve; j++) {
if (ctrlc) break;
int nb= V729_event(mask,nall,data, data1,data2);
if (nb<0) { // timeout
j--;
nerrors++;
} else {
V729_decode(mask,nall,data,adc, verbose);
// V729_clear_buffer();
if (output
) nball
+= fwrite(adc
, 1, sizeof(uint16_t)*len
, fp
);
ncount++;
}
if (t
/4!=told
) printf("%d events in %2.2f min (%d s) USBerr=%d TIMEOUTS=%d %s",ncount
, (double)(t
-tstart
)/60.
,int(t
-tstart
), VMEerrors
, nerrors
, ctime(&t
));
told=t/4;
}
// end
VME_STOP();
printf("%d events in %2.2f min (%d s) USBerr=%d TIMEOUTS=%d %s\n",ncount
, (double)(t
-tstart
)/60.
,int(t
-tstart
),VMEerrors
, nerrors
, ctime(&t
));
return 0;
}
#endif //V729_MAIN