Difference between revisions of "V1495Lib.c"

From New IAC Wiki
Jump to navigation Jump to search
(Created page with '<pre> /* v1495Lib.c - CAEN v1495 logic unit library + VFAT user interface library -------------------------------------------------------------------------- ...')
 
 
Line 100: Line 100:
 
#define MAIN_MEM_PAGE_PROG_TH_BUF1  0x0082
 
#define MAIN_MEM_PAGE_PROG_TH_BUF1  0x0082
  
 
 
 
 
 
//#define EIEIO() __asm__ volatile("eieio")
 
//#define SYNC() __asm__ volatile("sync")
 
  
 
#define SYSTIME_TO_MS(t) ((t)*60/1000000)
 
#define SYSTIME_TO_MS(t) ((t)*60/1000000)
Line 114: Line 107:
  
 
#define NUM_WORDS 14 // these are the number of words in the V1495ReadoutStatus struct
 
#define NUM_WORDS 14 // these are the number of words in the V1495ReadoutStatus struct
 +
 
typedef struct
 
typedef struct
 
{
 
{
Line 136: Line 130:
  
  
// Binary codes
+
STATUS
/*
+
v1495Init(UINT32 Addr)
const unsigned int START_FILE  = 0x1A02C741;       // Start File
+
{
const unsigned int END_FILE    = 0x05C12170;       // End File
+
UINT32 laddr;
const unsigned int FILE_INFO  = 0x10B22EAB;       // File Info
+
USHORT  boardID = 0;
const unsigned int START_EVENT = 0xE1AC021D;       // Start Event
+
UCHAR BIDH, BIDL;
const unsigned int END_EVENT  = 0x14173aAD;       // End Event
+
int res, rdata;
const unsigned short int ZERO  = 0x0000;           // Zero for padding
+
 
 +
 
 +
/* A32 Addressing */
 +
 
 +
#ifdef VXWORKS68K51
 +
printf("v1495Init: ERROR: 68K Based CPU cannot support A32 addressing (use A24)\n");
 +
    return(ERROR);
 +
#endif
 +
 
 +
    /* get the v1495 address */
 +
res = sysBusToLocalAdrs(0x09,(char *)Addr,(char **)&laddr);
 +
    if (res != 0) {
 +
printf("v1495Init: ERROR in sysBusToLocalAdrs(0x09,0x%x,&laddr) \n",Addr);
 +
return(ERROR);
 +
    }
 +
    //cv1495MemOffset = laddr - addr;
 +
v1495 = (V1495ReadoutCtrlRegs *) laddr;
 +
 +
 +
      /* Check if Board exists at that address */
 +
    res = vxMemProbe((char *) v1495,0,2,(char *)&rdata);
 +
    if(res < 0) {
 +
printf("c1495Init: ERROR: No addressable board at addr=0x%x\n",(UINT32) v1495);
 +
v1495 = NULL;
 +
return(ERROR);
 +
} else {
 +
      /* Check if this is a Model v1495 */
 +
      BIDH = *((UCHAR *)v1495 + BOARD_ID_OFFSET_H);
 +
BIDL = *((UCHAR *)v1495 + BOARD_ID_OFFSET_L);
 +
      boardID = BIDH<<8 | BIDL;
 +
      if(boardID != V1495_BOARD_ID) {
 +
printf(" ERROR: Board ID 0x%X does not match 0x%04X \n",V1495_BOARD_ID, boardID);
 +
printf(" BIDH: 0x%X ; BIDL: 0x%X \n",BIDH, BIDL);
 +
return(ERROR);
 +
      }
 +
}   
 +
   
 +
printf("v1495Init: v1495 Module has been successfully initialized.\n\n",BIDH, BIDL);
 +
 
 +
/* Disable/Clear v1495 */
 +
v1495Reset();
 +
 +
return(OK);
 +
}
 +
 
 +
 
 +
 
 +
//Function for CODA Control Readout List
 +
int
 +
v1495FillData(UINT32 * data)
 +
{
 +
int i, nWords = 0;
 +
 
 +
// printf("Data addr: 0x%08X\n", data);
 +
 
 +
if(data == NULL) {
 +
    printf("v1495FillData: ERROR : data not initialized \n");
 +
    return(-1);
 +
  }
 +
 
 +
nWords = v1495ReadEvent();
 +
 
 +
//printf("v1495ReadEvent: filling %d words into data[0x%Xkk]\n",nWords,data);
 +
for(i=0; i< nWords; i++)
 +
{
 +
  data[i] = *((UINT32 *)(v1495Channels) + i);
 +
}
 +
 +
// if(nWords)
 +
// printf("v1495ReadEvent: %d words copied into data[]\n",nWords);
 +
 +
return nWords;
 +
}
 +
 
 +
 
 +
 
 +
// Transfers v1495 data to V1495ReadoutStatus struct
 +
int
 +
v1495ReadEvent(void)
 +
{
 +
int i, j, k, m, nWords = NUM_WORDS*NUM_VFATS;
 +
UINT32 fifo_len[NUM_VFATS], dCnt;
 +
unsigned short NumData = 0, ChannelsNum[2];
 +
UCHAR HeaderOK = 1, Header[3] = {0xA, 0xC, 0xE};
 +
USHORT HextoBin[4] = {0x0000, 0x0001, 0x0010, 0x0011};
 +
//volatile unsigned short * p;
 +
//UINT32 Addr = 0x80110000;
 +
 +
if(v1495 == NULL) {
 +
    printf("v1495ReadEvent: ERROR : v1495 not initialized \n");
 +
    return(ERROR);
 +
  }
 +
 +
// Check to see if there are any words stored in any of the dataFIFOs
 +
for(i=0;i<NUM_VFATS;i++)
 +
{
 +
fifo_len[i] = (v1495->FIFOLength[i]>>6) & FIFO_WORDS_MASK;
 +
NumData |= fifo_len[i];
 +
}
 +
 
 +
 
 +
if(NumData)
 +
{
 +
 +
for(i=0;i<NUM_VFATS;i++) // Initialize v1495Channels members to 0.
 +
{
 +
v1495Channels[i].TotalBytes = 0;
 +
v1495Channels[i].TotalFrames = 0;
 +
v1495Channels[i].DeltaBytes = 0;
 +
v1495Channels[i].DeltaFrames = 0;
 +
v1495Channels[i].LastSize = 0;
 +
v1495Channels[i].LengthSizeFIFO = 0;
 +
v1495Channels[i].LengthDataFIFO = 0;
 +
v1495Channels[i].Sent = 0;
 +
for(j=0;j<12;j++)
 +
v1495Channels[i].LastCapture[j] = 0;
 +
}
  
FILE *bin_file;
+
for(i=0;i<NUM_VFATS;i++)
unsigned int file_num = 1;
+
{
 +
 +
if(!v1495Channels[i].LengthDataFIFO)
 +
{
 +
v1495Channels[i].LengthSizeFIFO = v1495->FIFOLength[i] & FIFO_WORDS_MASK;
 +
v1495Channels[i].LengthDataFIFO = fifo_len[i];
 +
}
 +
if(v1495Channels[i].LengthDataFIFO)
 +
{
 +
v1495Channels[i].Sent =
 +
( v1495->EventsSentH[i]<<16 )| v1495->EventsSentL[i];
 +
v1495Channels[i].LengthDataFIFO--;
 +
v1495Channels[i].DeltaFrames++;
 +
v1495Channels[i].TotalFrames++;
 +
v1495Channels[i].LastSize = v1495->EventSize[i] & EVENT_SIZE_MASK;
  
 +
 +
  for(j=0; j<v1495Channels[i].LastSize; j++) {
 +
v1495Channels[i].LastCapture[j] = v1495->EventData[i][0];
 +
if(j==2) {
 +
if((v1495Channels[i].LastCapture[j]&0xF000) == 0xE000)
 +
v1495Channels[i].LastCapture[j] = (v1495Channels[i].LastCapture[j] & 0x0FFF) | ((USHORT)i<<12);
 +
else {
 +
printf("v1495ReadEvent: Error: header for word 3 from data packet != 0xE\n");
 +
return(ERROR);
 +
}
 +
}
 +
  }
 +
 +
  v1495Channels[i].DeltaBytes += 2 * v1495Channels[i].LastSize;
 +
  v1495Channels[i].TotalBytes += 2 * v1495Channels[i].LastSize;
 +
 +
  //printf("v1495ReadEvent: Data entered into v1495Channel[%i]\n",i);
 +
//prints out channel data in bin format
 +
// : Crashes ROC when called from CODA
 +
// : Workes from ROC command line  
 +
/*   for(j=3; j<11; j=j+2) {
 +
ChannelsNum[0] = (((j>>1)-1)<<5)+1;
 +
ChannelsNum[1] =  (j>>1)<<5;
 +
printf("Channels %d -> %d: ",ChannelsNum[0], ChannelsNum[1]);
 +
for(k=0;k<2;k++) {
 +
v1495HextoBin(v1495Channels[i].LastCapture[j+k],HextoBin);
 +
for(m=0;m<4;m++)
 +
printf("%04X ",HextoBin[m]);
 +
}
 +
 +
printf("\n");
 +
  }
 
*/
 
*/
 +
}
 +
  }
 +
 +
}
 +
else
 +
{
 +
printf("v1495ReadEvent: dataFIFO is empty\n");
 +
nWords = 0;
 +
}
 +
return(nWords);
 +
}
 +
 +
 +
STATUS
 +
v1495Sprint(void) // this function prints out myfav registers
 +
{
 +
 +
int i;
 +
unsigned short NumData, NumSize;
 +
 +
 +
if(v1495 == NULL) {
 +
    printf("v1495Sprint: ERROR : v1495 not initialized \n");
 +
    return(-1);
 +
  }
 +
 +
for(i=0;i<NUM_VFATS;i++)
 +
{
 +
NumData = (v1495->FIFOLength[i]>>6) & FIFO_WORDS_MASK;
 +
NumSize = v1495->FIFOLength[i] & FIFO_WORDS_MASK;
 +
 +
//printf("A0_FIFOSIZE Addr: 0x%08x Data: 0x%04x \n",&(v1495->FIFOLength[0]),v1495->FIFOLength[0]);
 +
printf("Number of words in GEM[%i]dataFIFO : %04u, 0x%04X \n",i,NumData,NumData);
 +
printf("Number of words in GEM[%i]sizeFIFO : %04u \n",i,NumSize);
 +
 +
printf("GEM[%i]_EVENTSSENTH Addr: 0x%08x Data: 0x%04x \n"
 +
,i,&(v1495->EventsSentH[i]),v1495->EventsSentH[i]);
 +
printf("GEM[%i]_EVENTSSENTL Addr: 0x%08x Data: 0x%04x \n"
 +
,i,&(v1495->EventsSentL[i]),v1495->EventsSentL[i]);
 +
 +
printf("GEM[%i] HARD_TRIGGER_WORD = 0x%X, SOFT_TRIGGER_WORD = 0x%X\n", i,
 +
(v1495->TriggerWords & 0x0038)>>3,
 +
(v1495->TriggerWords & 0x0007));
 +
 +
printf("\n");
 +
 +
}
 +
 +
 +
printf("\n");
 +
 +
return(OK);
 +
}
 +
 +
 +
void v1495StatusPrint(void)//UINT32 * buf)
 +
{
 +
unsigned int i, j, sent, ChipID[NUM_VFATS], EventID[NUM_VFATS];
 +
//UINT32 Addr = 0x80110000;
 +
//volatile V1495ReadoutCtrlRegs * pV1495ReadoutCtrl = (V1495ReadoutCtrlRegs *) Addr;
 +
 +
//v1495Channels = (V1495ReadoutStatus *)buf;
 +
 +
for(i=0; i<NUM_VFATS; i++)
 +
{
 +
 +
printf("V1495[%d]: #B[%u] #F[%u/%u] B/s[%u] F/s[%u]\n", // LstEvtCnt[%u] LstWrdCnt[%u]\n",
 +
i, v1495Channels[i].TotalBytes, v1495Channels[i].TotalFrames, v1495Channels[i].Sent, v1495Channels[i].DeltaBytes, v1495Channels[i].DeltaFrames);//, //v1495Channels[i].LastEventCount, v1495Channels[i].LastWordCount);
 +
 +
 +
v1495Channels[i].DeltaBytes = 0;
 +
v1495Channels[i].DeltaFrames = 0;
 +
 +
printf("  LastCap[%u]: ", v1495Channels[i].LastSize);
 +
for(j = 0; j < v1495Channels[i].LastSize; j++)
 +
printf("%04X ", v1495Channels[i].LastCapture[j]);
 +
printf("\n");
 +
if(v1495Channels[i].LastSize)
 +
{
 +
EventID[i] = (v1495Channels[i].LastCapture[1] & 0x0FF0)>>4;
 +
ChipID[i] = v1495Channels[i].LastCapture[2] & 0x0FFF;
 +
printf("Event Count: %d ; Chip ID : 0x%X\n", EventID[i], ChipID[i]);
 +
}
 +
}
 +
}
 +
 +
 +
 +
// takes in one Hex word and converts it to four Hex words representing binary
 +
void
 +
v1495HextoBin(USHORT LastCapture, USHORT * HextoBin)
 +
{
 +
USHORT i, j, shift, temp[4] = {0x11,0x10,0x01,0x00};
 +
 +
// printf("\nReceived 0x%04X : \n", LastCapture);
 +
 +
for(i=0;i<4;i++) {
 +
shift = i<<2;
 +
temp[i] = (LastCapture & (0xF000 >> (shift))) >> (12-shift);
 +
}
 +
 +
for(i=0;i<4;i++) {
 +
for(j=0;j<4;j++)
 +
temp[i] |= (temp[i]&(0x1<<(3-j)))<<(3*(3-j));
 +
temp[i] &= 0xFFF1;
 +
}
 +
 +
for(i=0;i<4;i++)
 +
HextoBin[i] = temp[i];
 +
 +
return;
 +
}
 +
 +
 +
 +
  
  
Line 348: Line 620:
 
}
 
}
  
int
+
// Reboots latest firmware in v1495
v1495test1()
 
{
 
  volatile V1495 *v1495 = (V1495 *) 0x80110000;
 
  unsigned short *data16 = (unsigned short *)&(v1495->control);
 
 
 
  printf("Control      [0x%08x] = 0x%04x\n",&(v1495->control),v1495->control);
 
  printf("firmwareRev  [0x%08x] = 0x%04x\n",&(v1495->firmwareRev),v1495->firmwareRev);
 
  printf("selflashVME  [0x%08x] = 0x%04x\n",&(v1495->selflashVME),v1495->selflashVME);
 
  printf("flashVME    [0x%08x] = 0x%04x\n",&(v1495->flashVME),v1495->flashVME);
 
  printf("selflashUSER [0x%08x] = 0x%04x\n",&(v1495->selflashUSER),v1495->selflashUSER);
 
  printf("flashUSER    [0x%08x] = 0x%04x\n",&(v1495->flashUSER),v1495->flashUSER);
 
  printf("configROM    [0x%08x] = 0x%04x\n",&(v1495->configROM[0]),v1495->configROM[0]);
 
 
 
  return(0);
 
}
 
 
 
/*int
 
v1495reload()
 
{
 
  volatile V1495 *v1495 = (V1495 *)0xfa510000;
 
  unsigned short *Conf_Flash;
 
  Conf_Flash = (short *)&(v1495->configUSER);
 
 
 
  printf("Reloading user FPGA firmware...");
 
 
 
  EIEIO;
 
  SYNC;
 
  *Conf_Flash = 1;
 
  EIEIO;
 
  SYNC;
 
 
 
  printf("done!\n");
 
 
 
  return 0;
 
}*/
 
 
 
 
int
 
int
 
v1495reload(unsigned int baseaddr)
 
v1495reload(unsigned int baseaddr)
Line 548: Line 784:
 
}
 
}
  
 
+
//Resets v1495 pointer to NULL
//<---------- Old v1495ReadoutCtrl.c
 
 
 
 
 
/*
 
void
 
v1495CRCCalc(void)
 
{
 
int i, nShorts = 12, nShifts = 16;
 
 
 
USHORT Message[12] = { 0xABFF, 0xC100, 0xE6EC, 0x0000, 0x0000, 0x0000, 0x0000,
 
0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
 
 
 
USHORT result, Poly = 0x8811, CRC = 0x291A;
 
 
 
result = CRC;
 
for(i=0;i<nShorts;i++)
 
{
 
for(j=0;j<nShifts;j++)
 
{
 
result = (Poly|result)^(Message[i]<<j);
 
}
 
}
 
 
 
if(result == CRC)
 
printf("Your checksum matches\n");
 
else
 
printf("Your checksum does not match\n");
 
 
 
return;
 
}
 
*/
 
 
 
/*
 
void
 
v1495ResetPractice(void)
 
{
 
int i;
 
 
 
for(i=0;i<14*NUM_VFATS;i++)
 
practiceArray[i] = i;
 
 
 
return;
 
}
 
*/
 
/*
 
void
 
v1495ReadOutPractice(void)
 
{
 
int i, j;
 
 
 
printf("practiceArray addr: 0x%04X \n",practiceArray);
 
 
 
for(i=0;i<NUM_VFATS;i++)
 
{
 
for(j=0;j<4;j++)
 
printf("%08X ", practiceArray[14*i+j]);
 
 
 
printf("\n");
 
 
 
for(j;j<8;j++)
 
printf("%08X ", practiceArray[14*i+j]);
 
 
 
printf("\n");
 
 
 
for(j;j<14;j++)
 
printf("%08X ", practiceArray[14*i+j]);
 
 
 
printf("\n\n");
 
}
 
return;
 
}
 
*/
 
 
 
 
void
 
void
 
v1495Release(void)
 
v1495Release(void)
Line 630: Line 793:
 
}
 
}
  
 +
 +
//Checks for number of entries in dataFIFO
 
int
 
int
 
v1495DataReady(void)
 
v1495DataReady(void)
Line 643: Line 808:
 
if(FIFOBigSize < (v1495->FIFOLength[i])& 0x3F)
 
if(FIFOBigSize < (v1495->FIFOLength[i])& 0x3F)
 
FIFOBigSize = v1495->FIFOLength[i]&0x3F;
 
FIFOBigSize = v1495->FIFOLength[i]&0x3F;
 +
 +
// Extra code for checking EventSize
 +
// EventSize does not always agree with FIFOLength
 +
// This code is commented out for now
 
/*
 
/*
 
for(i=0;i<6;i++)
 
for(i=0;i<6;i++)
Line 658: Line 827:
 
}
 
}
  
 
STATUS
 
v1495Sprint(void) // this function prints out myfav registers
 
{
 
 
int i;
 
unsigned short NumData, NumSize;
 
 
 
if(v1495 == NULL) {
 
    printf("v1495Sprint: ERROR : v1495 not initialized \n");
 
    return(-1);
 
  }
 
 
for(i=0;i<NUM_VFATS;i++)
 
{
 
NumData = (v1495->FIFOLength[i]>>6) & FIFO_WORDS_MASK;
 
NumSize = v1495->FIFOLength[i] & FIFO_WORDS_MASK;
 
 
//printf("A0_FIFOSIZE Addr: 0x%08x Data: 0x%04x \n",&(v1495->FIFOLength[0]),v1495->FIFOLength[0]);
 
printf("Number of words in GEM[%i]dataFIFO : %04u, 0x%04X \n",i,NumData,NumData);
 
printf("Number of words in GEM[%i]sizeFIFO : %04u \n",i,NumSize);
 
 
printf("GEM[%i]_EVENTSSENTH Addr: 0x%08x Data: 0x%04x \n"
 
,i,&(v1495->EventsSentH[i]),v1495->EventsSentH[i]);
 
printf("GEM[%i]_EVENTSSENTL Addr: 0x%08x Data: 0x%04x \n"
 
,i,&(v1495->EventsSentL[i]),v1495->EventsSentL[i]);
 
printf("\n");
 
 
}
 
 
 
printf("\n");
 
 
return(OK);
 
}
 
  
 
STATUS
 
STATUS
Line 710: Line 843:
  
  
//v1495Sprint();
 
  
 +
// Uses the fact that the DataValid and DataOut lines are high when VFATs are
 +
//    disconnected to check for VFAT
 +
// : Very buggy, therefore left out for now.
 
/*
 
/*
 
for(i=0;i<NUM_VFATS;i++) {
 
for(i=0;i<NUM_VFATS;i++) {
Line 726: Line 861:
  
 
return(OK);
 
return(OK);
}
 
 
STATUS
 
v1495Init(UINT32 Addr)
 
{
 
UINT32 laddr;
 
USHORT  boardID = 0;
 
UCHAR BIDH, BIDL;
 
int res, rdata;
 
 
 
/* A32 Addressing */
 
 
#ifdef VXWORKS68K51
 
printf("v1495Init: ERROR: 68K Based CPU cannot support A32 addressing (use A24)\n");
 
    return(ERROR);
 
#endif
 
 
    /* get the v1495 address */
 
res = sysBusToLocalAdrs(0x09,(char *)Addr,(char **)&laddr);
 
    if (res != 0) {
 
printf("v1495Init: ERROR in sysBusToLocalAdrs(0x09,0x%x,&laddr) \n",Addr);
 
return(ERROR);
 
    }
 
    //cv1495MemOffset = laddr - addr;
 
v1495 = (V1495ReadoutCtrlRegs *) laddr;
 
 
 
      /* Check if Board exists at that address */
 
    res = vxMemProbe((char *) v1495,0,2,(char *)&rdata);
 
    if(res < 0) {
 
printf("c1495Init: ERROR: No addressable board at addr=0x%x\n",(UINT32) v1495);
 
v1495 = NULL;
 
return(ERROR);
 
} else {
 
      /* Check if this is a Model v1495 */
 
      BIDH = *((UCHAR *)v1495 + BOARD_ID_OFFSET_H);
 
BIDL = *((UCHAR *)v1495 + BOARD_ID_OFFSET_L);
 
      boardID = BIDH<<8 | BIDL;
 
      if(boardID != V1495_BOARD_ID) {
 
printf(" ERROR: Board ID 0x%X does not match 0x%04X \n",V1495_BOARD_ID, boardID);
 
printf(" BIDH: 0x%X ; BIDL: 0x%X \n",BIDH, BIDL);
 
return(ERROR);
 
      }
 
}   
 
   
 
printf("v1495Init: v1495 Module has been successfully initialized.\n\n",BIDH, BIDL);
 
 
/* Disable/Clear v1495 */
 
v1495Reset();
 
 
return(OK);
 
}
 
 
// takes in one Hex word and converts it to four Hex words representing binary
 
void
 
v1495HextoBin(USHORT LastCapture, USHORT * HextoBin)
 
{
 
USHORT i, j, shift, temp[4] = {0x11,0x10,0x01,0x00};
 
 
// printf("\nReceived 0x%04X : \n", LastCapture);
 
 
for(i=0;i<4;i++) {
 
shift = i<<2;
 
temp[i] = (LastCapture & (0xF000 >> (shift))) >> (12-shift);
 
}
 
 
for(i=0;i<4;i++) {
 
for(j=0;j<4;j++)
 
temp[i] |= (temp[i]&(0x1<<(3-j)))<<(3*(3-j));
 
temp[i] &= 0xFFF1;
 
}
 
 
for(i=0;i<4;i++)
 
HextoBin[i] = temp[i];
 
 
return;
 
}
 
 
 
int
 
v1495ReadEvent(void)
 
{
 
int i, j, k, m, nWords = NUM_WORDS*NUM_VFATS;
 
UINT32 fifo_len[NUM_VFATS], dCnt;
 
unsigned short NumData = 0, ChannelsNum[2];
 
UCHAR HeaderOK = 1, Header[3] = {0xA, 0xC, 0xE};
 
USHORT HextoBin[4] = {0x0000, 0x0001, 0x0010, 0x0011};
 
//volatile unsigned short * p;
 
//UINT32 Addr = 0x80110000;
 
 
if(v1495 == NULL) {
 
    printf("v1495ReadEvent: ERROR : v1495 not initialized \n");
 
    return(ERROR);
 
  }
 
 
// Check to see if there are any words stored in any of the dataFIFOs
 
for(i=0;i<NUM_VFATS;i++)
 
{
 
fifo_len[i] = (v1495->FIFOLength[i]>>6) & FIFO_WORDS_MASK;
 
NumData |= fifo_len[i];
 
}
 
 
 
if(NumData)
 
{
 
 
for(i=0;i<NUM_VFATS;i++) // Initialize v1495Channels members to 0.
 
{
 
v1495Channels[i].TotalBytes = 0;
 
v1495Channels[i].TotalFrames = 0;
 
v1495Channels[i].DeltaBytes = 0;
 
v1495Channels[i].DeltaFrames = 0;
 
v1495Channels[i].LastSize = 0;
 
v1495Channels[i].LengthSizeFIFO = 0;
 
v1495Channels[i].LengthDataFIFO = 0;
 
v1495Channels[i].Sent = 0;
 
for(j=0;j<12;j++)
 
v1495Channels[i].LastCapture[j] = 0;
 
}
 
 
for(i=0;i<NUM_VFATS;i++)
 
{
 
 
if(!v1495Channels[i].LengthDataFIFO)
 
{
 
v1495Channels[i].LengthSizeFIFO = v1495->FIFOLength[i] & FIFO_WORDS_MASK;
 
v1495Channels[i].LengthDataFIFO = fifo_len[i];
 
}
 
if(v1495Channels[i].LengthDataFIFO)
 
{
 
v1495Channels[i].Sent =
 
( v1495->EventsSentH[i]<<16 )| v1495->EventsSentL[i];
 
v1495Channels[i].LengthDataFIFO--;
 
v1495Channels[i].DeltaFrames++;
 
v1495Channels[i].TotalFrames++;
 
v1495Channels[i].LastSize = v1495->EventSize[i] & EVENT_SIZE_MASK;
 
 
 
  for(j=0; j<v1495Channels[i].LastSize; j++) {
 
v1495Channels[i].LastCapture[j] = v1495->EventData[i][0];
 
if(j==2) {
 
if((v1495Channels[i].LastCapture[j]&0xF000) == 0xE000)
 
v1495Channels[i].LastCapture[j] = (v1495Channels[i].LastCapture[j] & 0x0FFF) | ((USHORT)i<<12);
 
else {
 
printf("v1495ReadEvent: Error: header for word 3 from data packet != 0xE\n");
 
return(ERROR);
 
}
 
}
 
  }
 
 
  v1495Channels[i].DeltaBytes += 2 * v1495Channels[i].LastSize;
 
  v1495Channels[i].TotalBytes += 2 * v1495Channels[i].LastSize;
 
 
  //printf("v1495ReadEvent: Data entered into v1495Channel[%i]\n",i);
 
 
 
/*   for(j=3; j<11; j=j+2) {
 
ChannelsNum[0] = (((j>>1)-1)<<5)+1;
 
ChannelsNum[1] =  (j>>1)<<5;
 
printf("Channels %d -> %d: ",ChannelsNum[0], ChannelsNum[1]);
 
for(k=0;k<2;k++) {
 
v1495HextoBin(v1495Channels[i].LastCapture[j+k],HextoBin);
 
for(m=0;m<4;m++)
 
printf("%04X ",HextoBin[m]);
 
}
 
 
printf("\n");
 
  }
 
*/
 
}
 
  }
 
 
}
 
else
 
{
 
printf("v1495ReadEvent: dataFIFO is empty\n");
 
nWords = 0;
 
}
 
return(nWords);
 
}
 
 
int
 
v1495FillData(UINT32 * data)
 
{
 
int i, nWords = 0;
 
 
// printf("Data addr: 0x%08X\n", data);
 
 
if(data == NULL) {
 
    printf("v1495FillData: ERROR : data not initialized \n");
 
    return(-1);
 
  }
 
 
nWords = v1495ReadEvent();
 
 
//printf("v1495ReadEvent: filling %d words into data[0x%Xkk]\n",nWords,data);
 
for(i=0; i< nWords; i++)
 
{
 
  data[i] = *((UINT32 *)(v1495Channels) + i);
 
}
 
 
// if(nWords)
 
// printf("v1495ReadEvent: %d words copied into data[]\n",nWords);
 
 
return nWords;
 
}
 
 
 
 
void v1495StatusPrint(void)//UINT32 * buf)
 
{
 
unsigned int i, j, sent, ChipID[NUM_VFATS], EventID[NUM_VFATS];
 
//UINT32 Addr = 0x80110000;
 
//volatile V1495ReadoutCtrlRegs * pV1495ReadoutCtrl = (V1495ReadoutCtrlRegs *) Addr;
 
 
//v1495Channels = (V1495ReadoutStatus *)buf;
 
 
for(i=0; i<NUM_VFATS; i++)
 
{
 
 
printf("V1495[%d]: #B[%u] #F[%u/%u] B/s[%u] F/s[%u]\n", // LstEvtCnt[%u] LstWrdCnt[%u]\n",
 
i, v1495Channels[i].TotalBytes, v1495Channels[i].TotalFrames, v1495Channels[i].Sent, v1495Channels[i].DeltaBytes, v1495Channels[i].DeltaFrames);//, //v1495Channels[i].LastEventCount, v1495Channels[i].LastWordCount);
 
 
 
v1495Channels[i].DeltaBytes = 0;
 
v1495Channels[i].DeltaFrames = 0;
 
 
printf("  LastCap[%u]: ", v1495Channels[i].LastSize);
 
for(j = 0; j < v1495Channels[i].LastSize; j++)
 
printf("%04X ", v1495Channels[i].LastCapture[j]);
 
printf("\n");
 
if(v1495Channels[i].LastSize)
 
{
 
EventID[i] = (v1495Channels[i].LastCapture[1] & 0x0FF0)>>4;
 
ChipID[i] = v1495Channels[i].LastCapture[2] & 0x0FFF;
 
printf("Event Count: %d ; Chip ID : 0x%X\n", EventID[i], ChipID[i]);
 
}
 
}
 
 
}
 
}
  

Latest revision as of 17:24, 29 June 2009


/* v1495Lib.c - CAEN v1495 logic unit library + VFAT user interface library



    --------------------------------------------------------------------------

                   --- CAEN SpA - Front End Electronics  ---

    --------------------------------------------------------------------------

    Name        :   V1495Upgrade.c

    Project     :   V1495Upgrade

    Description :   V1495 Upgrade Software


	  This program writes the configuration file (Altera RBF Format) into the
	  flash memory of the Module V1495. This allows to upgrade the firmware
	  for either the VME_INT and the USER fpga from the VME.
	  The program is based on the CAEN Bridge (V1718 or V2718).
	  The software can be compiled for other VME CPUs, changing the functions
      in the custom VME functions (VME_Init(),VME_Write(), VME_Read()).
      Comment away CAENVMElib.h include in this case.

    Date        :   March 2006
    Release     :   1.0
    Author      :   C.Tintori

    --------------------------------------------------------------------------


    --------------------------------------------------------------------------
*/

/*

  Revision History:
  1.0    CT     First release
  1.1    LC     USER Flash page map changed. Only STD update allowed.

Adjustment for Motorola VME controllers: Sergey Boyarinov April 23 2007

*/
/*

  example:

download module
ld < /usr/local/clas/devel/coda/src/rol/VXWORKS_ppc/obj/v1495.o

goto directory where your firmware is stored
cd "/usr/local/clas/devel/coda/src/rol/code.s"

download user firmware
v1495firmware(0xfa510000,"v1495USER1.0.rbf",0,0)

download VME firmware (BE CAREFUL !!!)
v1495firmware(0xfa510000,"v1495V2LB_rev03_build_8321.rbf",0,1)


*/




#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <vxWorks.h>
#include <stdioLib.h>
#include <usrLib.h>
#include <taskLib.h>
#include <semLib.h>
#include <intLib.h>
#include <cacheLib.h>
#include <iv.h>
#include <math.h>

#include "v1495Lib.h"



/*sergey*/
#define EIEIO    __asm__ volatile ("eieio")
#define SYNC     __asm__ volatile ("sync")

/* Parameters for the access to the Flash Memory */
#define VME_FIRST_PAGE_STD    768    /* first page of the image STD */
#define VME_FIRST_PAGE_BCK    1408   /* first page of the image BCK */
#define USR_FIRST_PAGE_STD    48     /* first page of the image STD */
#define USR_FIRST_PAGE_BCK    1048   /* first page of the image BCK */
#define PAGE_SIZE       264 /* Number of bytes per page in the target flash */

/* flash memory Opcodes */
#define MAIN_MEM_PAGE_READ          0x00D2
#define MAIN_MEM_PAGE_PROG_TH_BUF1  0x0082


#define SYSTIME_TO_MS(t)	((t)*60/1000000)
#define SYSTIME_TO_US(t)	((t)*60/1000)
#define NUM_VFATS		6


#define NUM_WORDS		14 // these are the number of words in the V1495ReadoutStatus struct

typedef struct
{
	volatile unsigned int TotalBytes;
	volatile unsigned int TotalFrames;
	volatile unsigned int DeltaBytes;
	volatile unsigned int DeltaFrames;
	volatile unsigned int LastSize;
	volatile unsigned int LengthDataFIFO;
	volatile unsigned int LengthSizeFIFO;
	volatile unsigned int Sent;
	volatile unsigned short LastCapture[12];
} V1495ReadoutStatus;


//volatile UINT32 practiceArray[168];

/* Define Global structs */
volatile V1495ReadoutCtrlRegs * v1495;
volatile V1495ReadoutStatus v1495Channels[6];



STATUS 
v1495Init(UINT32 Addr)
{
	UINT32 laddr;
	USHORT  boardID = 0;
	UCHAR BIDH, BIDL;
	int res, rdata; 


	/* A32 Addressing */

#ifdef VXWORKS68K51
	printf("v1495Init: ERROR: 68K Based CPU cannot support A32 addressing (use A24)\n");
    	return(ERROR);
#endif

    	/* get the v1495 address */
	res = sysBusToLocalAdrs(0x09,(char *)Addr,(char **)&laddr);
    	if (res != 0) {
		printf("v1495Init: ERROR in sysBusToLocalAdrs(0x09,0x%x,&laddr) \n",Addr);
	return(ERROR);
    	}
    	//cv1495MemOffset = laddr - addr;
	v1495 = (V1495ReadoutCtrlRegs *) laddr;
	
	
      	/* Check if Board exists at that address */
    	res = vxMemProbe((char *) v1495,0,2,(char *)&rdata);
    	if(res < 0) {	
		printf("c1495Init: ERROR: No addressable board at addr=0x%x\n",(UINT32) v1495);
		v1495 = NULL;
		return(ERROR);
	} else {
      	/* Check if this is a Model v1495 */
      		BIDH = *((UCHAR *)v1495 + BOARD_ID_OFFSET_H);
		BIDL = *((UCHAR *)v1495 + BOARD_ID_OFFSET_L);
	      	boardID = BIDH<<8 | BIDL;
	      	if(boardID != V1495_BOARD_ID) {
			printf(" ERROR: Board ID 0x%X does not match 0x%04X \n",V1495_BOARD_ID, boardID);
			printf(" BIDH: 0x%X ; BIDL: 0x%X \n",BIDH, BIDL);
			return(ERROR);
	      	}
	}    	
    	
	printf("v1495Init: v1495 Module has been successfully initialized.\n\n",BIDH, BIDL);

	/* Disable/Clear v1495 */
	v1495Reset();
		
	return(OK);
}



//Function for CODA Control Readout List
int
v1495FillData(UINT32 * data)
{
	int i, nWords = 0;	

//	printf("Data addr: 0x%08X\n", data);

	if(data == NULL) {
    		printf("v1495FillData: ERROR : data not initialized \n");
    		return(-1);
  	}

	nWords = v1495ReadEvent();

	//printf("v1495ReadEvent: filling %d words into data[0x%Xkk]\n",nWords,data);	
	for(i=0; i< nWords; i++)
	{
	   data[i] = *((UINT32 *)(v1495Channels) + i);		
	}
	
//	if(nWords)
//		printf("v1495ReadEvent: %d words copied into data[]\n",nWords);	
	
	return nWords;
}



// Transfers v1495 data to V1495ReadoutStatus struct
int
v1495ReadEvent(void)
{
	int i, j, k, m, nWords = NUM_WORDS*NUM_VFATS; 
	UINT32 fifo_len[NUM_VFATS], dCnt;
	unsigned short NumData = 0, ChannelsNum[2];
	UCHAR HeaderOK = 1, Header[3] = {0xA, 0xC, 0xE};
	USHORT HextoBin[4] = {0x0000, 0x0001, 0x0010, 0x0011};
	//volatile unsigned short * p;
	//UINT32 Addr = 0x80110000;
	
	if(v1495 == NULL) {
    		printf("v1495ReadEvent: ERROR : v1495 not initialized \n");
    		return(ERROR);
  	}
	
	// Check to see if there are any words stored in any of the dataFIFOs
	for(i=0;i<NUM_VFATS;i++)
	{
		fifo_len[i] = (v1495->FIFOLength[i]>>6) & FIFO_WORDS_MASK;
		NumData |= fifo_len[i];
	}


	if(NumData)
	{
		
		for(i=0;i<NUM_VFATS;i++) // Initialize v1495Channels members to 0.
		{
			v1495Channels[i].TotalBytes = 0;
			v1495Channels[i].TotalFrames = 0;
			v1495Channels[i].DeltaBytes = 0;
			v1495Channels[i].DeltaFrames = 0;
			v1495Channels[i].LastSize = 0;
			v1495Channels[i].LengthSizeFIFO = 0;
			v1495Channels[i].LengthDataFIFO = 0;
			v1495Channels[i].Sent = 0;
			for(j=0;j<12;j++)
				v1495Channels[i].LastCapture[j] = 0;
		}

		for(i=0;i<NUM_VFATS;i++)
		{
			
			if(!v1495Channels[i].LengthDataFIFO)
			{
				v1495Channels[i].LengthSizeFIFO = v1495->FIFOLength[i] & FIFO_WORDS_MASK;
				v1495Channels[i].LengthDataFIFO = fifo_len[i];
			}
			if(v1495Channels[i].LengthDataFIFO)
			{
				v1495Channels[i].Sent =
					( v1495->EventsSentH[i]<<16 )| v1495->EventsSentL[i];
				v1495Channels[i].LengthDataFIFO--;
				v1495Channels[i].DeltaFrames++;
				v1495Channels[i].TotalFrames++;
				v1495Channels[i].LastSize = v1495->EventSize[i] & EVENT_SIZE_MASK;

			
		   for(j=0; j<v1495Channels[i].LastSize; j++) {
			v1495Channels[i].LastCapture[j] = v1495->EventData[i][0];
			if(j==2) {
				if((v1495Channels[i].LastCapture[j]&0xF000) == 0xE000)	
					v1495Channels[i].LastCapture[j] = (v1495Channels[i].LastCapture[j] & 0x0FFF) | ((USHORT)i<<12);
				else {
					printf("v1495ReadEvent: Error: header for word 3 from data packet != 0xE\n");
					return(ERROR);
				}
			}
		   }
	
		   v1495Channels[i].DeltaBytes += 2 * v1495Channels[i].LastSize;
		   v1495Channels[i].TotalBytes += 2 * v1495Channels[i].LastSize;
				
		   //printf("v1495ReadEvent: Data entered into v1495Channel[%i]\n",i);
//prints out channel data in bin format
// : Crashes ROC when called from CODA	
// : Workes from ROC command line	   
/*		   for(j=3; j<11; j=j+2) {
			ChannelsNum[0] = (((j>>1)-1)<<5)+1;
			ChannelsNum[1] =  (j>>1)<<5;
			printf("Channels %d -> %d: ",ChannelsNum[0], ChannelsNum[1]);
			for(k=0;k<2;k++) {
				v1495HextoBin(v1495Channels[i].LastCapture[j+k],HextoBin);
				for(m=0;m<4;m++)
					printf("%04X ",HextoBin[m]);		
			}

			printf("\n");
		   }
*/
		}
	   }

	}
	else
	{
		printf("v1495ReadEvent: dataFIFO is empty\n");
		nWords = 0;
	}	
	return(nWords);
}


STATUS
v1495Sprint(void) // this function prints out myfav registers
{
	
	int i;
	unsigned short NumData, NumSize;


	if(v1495 == NULL) {
    		printf("v1495Sprint: ERROR : v1495 not initialized \n");
    		return(-1);
  	}
	
	for(i=0;i<NUM_VFATS;i++)
	{
		NumData = (v1495->FIFOLength[i]>>6) & FIFO_WORDS_MASK;
		NumSize = v1495->FIFOLength[i] & FIFO_WORDS_MASK;

		//printf("A0_FIFOSIZE Addr: 0x%08x Data: 0x%04x \n",&(v1495->FIFOLength[0]),v1495->FIFOLength[0]);
		printf("Number of words in GEM[%i]dataFIFO : %04u, 0x%04X \n",i,NumData,NumData);	
		printf("Number of words in GEM[%i]sizeFIFO : %04u \n",i,NumSize);
	
		printf("GEM[%i]_EVENTSSENTH Addr: 0x%08x Data: 0x%04x \n"
			,i,&(v1495->EventsSentH[i]),v1495->EventsSentH[i]);
		printf("GEM[%i]_EVENTSSENTL Addr: 0x%08x Data: 0x%04x \n"
			,i,&(v1495->EventsSentL[i]),v1495->EventsSentL[i]);
		
		printf("GEM[%i] HARD_TRIGGER_WORD = 0x%X, SOFT_TRIGGER_WORD = 0x%X\n", i,
						(v1495->TriggerWords & 0x0038)>>3,
						(v1495->TriggerWords & 0x0007));
						
		printf("\n");
	
	}
	
	
	printf("\n");

	return(OK);
}


void v1495StatusPrint(void)//UINT32 * buf)
{
	unsigned int i, j, sent, ChipID[NUM_VFATS], EventID[NUM_VFATS];
	//UINT32 Addr = 0x80110000;
	//volatile V1495ReadoutCtrlRegs * pV1495ReadoutCtrl = (V1495ReadoutCtrlRegs *) Addr;

	//v1495Channels = (V1495ReadoutStatus *)buf;

	for(i=0; i<NUM_VFATS; i++)
	{
		
		printf("V1495[%d]: #B[%u] #F[%u/%u] B/s[%u] F/s[%u]\n", // LstEvtCnt[%u] LstWrdCnt[%u]\n",
			i, v1495Channels[i].TotalBytes, v1495Channels[i].TotalFrames, v1495Channels[i].Sent, 				v1495Channels[i].DeltaBytes, v1495Channels[i].DeltaFrames);//, 					//v1495Channels[i].LastEventCount, v1495Channels[i].LastWordCount);
		
		
		v1495Channels[i].DeltaBytes = 0;
		v1495Channels[i].DeltaFrames = 0;

		printf("  LastCap[%u]: ", v1495Channels[i].LastSize);
		for(j = 0; j < v1495Channels[i].LastSize; j++)
			printf("%04X ", v1495Channels[i].LastCapture[j]);
		printf("\n");
		if(v1495Channels[i].LastSize)
		{
			EventID[i] = (v1495Channels[i].LastCapture[1] & 0x0FF0)>>4;
			ChipID[i] = v1495Channels[i].LastCapture[2] & 0x0FFF;
			printf("Event Count: %d ; Chip ID : 0x%X\n", EventID[i], ChipID[i]);
		}
	}
}



// takes in one Hex word and converts it to four Hex words representing binary
void 
v1495HextoBin(USHORT LastCapture, USHORT * HextoBin)
{
	USHORT i, j, shift, temp[4] = {0x11,0x10,0x01,0x00};

//	printf("\nReceived 0x%04X : \n", LastCapture);

	for(i=0;i<4;i++) {
		shift = i<<2; 
		temp[i] = (LastCapture & (0xF000 >> (shift))) >> (12-shift);
	}

	for(i=0;i<4;i++) 	{
		for(j=0;j<4;j++)
			temp[i] |= (temp[i]&(0x1<<(3-j)))<<(3*(3-j));
		temp[i] &= 0xFFF1;
	}

	for(i=0;i<4;i++)
		HextoBin[i] = temp[i];

	return;
}






/****************************************************************************
 write_flash_page
    flag=0 for USER flash (default)
        =1 for VME flash
****************************************************************************/
int
write_flash_page1(unsigned int addr, unsigned char *page, int pagenum, int flag)
{
  volatile V1495 *v1495 = (V1495 *) addr;
  int i, flash_addr, data;
  unsigned char addr0, addr1, addr2;
  int res = 0;
  unsigned short *Sel_Flash; /* VME Address of the FLASH SELECTION REGISTER */
  unsigned short *RW_Flash;  /* VME Address of the FLASH Read/Write REGISTER */

  if(flag==1)
  {
    Sel_Flash = (short *)&(v1495->selflashVME);
    RW_Flash = (short *)&(v1495->flashVME);
  }
  else
  {
    Sel_Flash = (short *)&(v1495->selflashUSER);
    RW_Flash = (short *)&(v1495->flashUSER);
  }

  EIEIO;
  SYNC;
  flash_addr = pagenum << 9;
  addr0 = (unsigned char)flash_addr;
  addr1 = (unsigned char)(flash_addr>>8);
  addr2 = (unsigned char)(flash_addr>>16);

  EIEIO;
  SYNC;
  /* enable flash (NCS = 0) */
  data = 0;
  *Sel_Flash = data;

  EIEIO;
  SYNC;
  /* write opcode */
  data = MAIN_MEM_PAGE_PROG_TH_BUF1;
  *RW_Flash = data;

  EIEIO;
  SYNC;
  /* write address */
  data = addr2;
  *RW_Flash = data;
  data = addr1;
  *RW_Flash = data;
  data = addr0;
  *RW_Flash = data;

  EIEIO;
  SYNC;
  /* write flash page */
  for(i=0; i<PAGE_SIZE; i++)
  {
    data = page[i];
    *RW_Flash = data;
  }

  EIEIO;
  SYNC;
  /* wait 20ms (max time required by the flash to complete the writing) */
  taskDelay(10); /* 1 tick = 10ms */

  EIEIO;
  SYNC;
  /* disable flash (NCS = 1) */
  data = 1;
  *Sel_Flash = data;


  EIEIO;
  SYNC;
  /* wait 20ms (max time required by the flash to complete the writing) */
  taskDelay(20);
  EIEIO;
  SYNC;

  return(res);
}

/****************************************************************************
 read_flash_page
****************************************************************************/
int
read_flash_page1(unsigned int addr, unsigned char *page, int pagenum, int flag)
{
  volatile V1495 *v1495 = (V1495 *) addr;
  int i, flash_addr, data;
  /*volatile*/ unsigned short data16;
  unsigned char addr0,addr1,addr2;
  int res = 0;
  unsigned short *Sel_Flash; /* VME Address of the FLASH SELECTION REGISTER */
  unsigned short *RW_Flash;  /* VME Address of the FLASH Read/Write REGISTER */

  if(flag==1)
  {
    Sel_Flash = (short *)&(v1495->selflashVME);
    RW_Flash = (short *)&(v1495->flashVME);
  }
  else
  {
    Sel_Flash = (short *)&(v1495->selflashUSER);
    RW_Flash = (short *)&(v1495->flashUSER);
  }

  EIEIO;
  SYNC;
  flash_addr = pagenum << 9;
  addr0 = (unsigned char)flash_addr;
  addr1 = (unsigned char)(flash_addr>>8);
  addr2 = (unsigned char)(flash_addr>>16);

  EIEIO;
  SYNC;
  /* enable flash (NCS = 0) */
  data = 0;
  *Sel_Flash = data;


  EIEIO;
  SYNC;
  /* write opcode */
  data = MAIN_MEM_PAGE_READ;
  *RW_Flash = data;



  EIEIO;
  SYNC;
  /* write address */
  data = addr2;
  *RW_Flash = data;
  data = addr1;
  *RW_Flash = data;
  data = addr0;
  *RW_Flash = data;


  EIEIO;
  SYNC;
  /* additional don't care bytes */
  data = 0;
  for(i=0; i<4; i++)
  {
    *RW_Flash = data;
  }

  EIEIO;
  SYNC;
  /* read flash page */
  for(i=0; i<PAGE_SIZE; i++)
  {
    data16 = *RW_Flash;
    page[i] = (unsigned char)data16;
  }
  EIEIO;
  SYNC;

  /* disable flash (NCS = 1) */
  data = 1;
  *Sel_Flash = data;
  EIEIO;
  SYNC;

  return(res);
}


int
v1495test(unsigned int baseaddr)
{
  // the address location below starts at the USER FPGA access location which is 
  //0x8000 lower in memory than the dial switches for the module address location.

  // if SW3=0 SW4=8 SW7=1 SW8=1 => 0x80118000 is the 32 bit address and 0x90118000 is the 24 bit adresss

  // then try v1495test(0x80110000)
  volatile V1495 *v1495 = (V1495 *) baseaddr;
  unsigned short *data16 = (unsigned short *)&(v1495->control);

  printf("Control      [0x%08x] = 0x%04x\n",&(v1495->control),v1495->control);
  printf("firmwareRev  [0x%08x] = 0x%04x\n",&(v1495->firmwareRev),v1495->firmwareRev);
  printf("selflashVME  [0x%08x] = 0x%04x\n",&(v1495->selflashVME),v1495->selflashVME);
  printf("flashVME     [0x%08x] = 0x%04x\n",&(v1495->flashVME),v1495->flashVME);
  printf("selflashUSER [0x%08x] = 0x%04x\n",&(v1495->selflashUSER),v1495->selflashUSER);
  printf("flashUSER    [0x%08x] = 0x%04x\n",&(v1495->flashUSER),v1495->flashUSER);
  printf("configROM    [0x%08x] = 0x%04x\n",&(v1495->configROM[0]),v1495->configROM[0]);

  return(0);
}

// Reboots latest firmware in v1495
int
v1495reload(unsigned int baseaddr)
{
  volatile V1495 *v1495 = (V1495 *)baseaddr;
  unsigned short *Conf_Flash;
  Conf_Flash = (short *)&(v1495->configUSER);

  printf("Reloading user FPGA firmware...");

  EIEIO;
  SYNC;
  *Conf_Flash = 1;
  EIEIO;
  SYNC;

  printf("done!\n");

  return 0;
}


/*****************************************************************************
   MAIN

     baseaddr: full board address (for example 0x80510000)
     filename: RBF file name
     page: =0 for standard, =1 for backup
     user_vme: Firmware to update selector = 0 => USER, 1 => VME

*****************************************************************************/
int
v1495firmware(unsigned int baseaddr, char *filename, int page, int user_vme)
{
  int finish,i;
  int bp, bcnt, pa;
  char c;
  unsigned char pdw[PAGE_SIZE], pdr[PAGE_SIZE];
  unsigned long vboard_base_address;
  FILE *cf;

  /*page = 0;     ONLY STD !!!!!!!!!!!!! */
  /*user_vme = 0; ONLY USER !!!!!!!!!!!! */

  printf("\n");
  printf("********************************************************\n");
  printf("* CAEN SpA - Front-End Division                        *\n");
  printf("* ---------------------------------------------------- *\n");
  printf("* Firmware Upgrade of the V1495                        *\n");
  printf("* Version 1.1 (27/07/06)                               *\n");
  printf("*   Sergey Boyarinov: CLAS version 23-Apr-2007         *\n");
  printf("********************************************************\n\n");

  /* open the configuration file */
  cf = fopen(filename,"rb");
  if(cf==NULL)
  {
    printf("\n\nCan't open v1495 firmware file >%s< - exit\n",filename);
    exit(1);
  }

  if(user_vme == 0) /* FPGA "User" */
  {
    if(page == 0)
    {
      pa = USR_FIRST_PAGE_STD;
    }
    else if(page == 1)
    {
      printf("Backup image not supported for USER FPGA\n");
      exit(0);
	}
    else
    {
      printf("Bad Image.\n");
	  exit(0);
    }

    printf("Updating firmware of the FPGA USER with the file %s\n",filename);
  }
  else if(user_vme == 1) /* FPGA "VME_Interface" */
  {
    if(page == 0)
    {
      printf("Writing STD page of the VME FPGA\n");
      pa = VME_FIRST_PAGE_STD;
	}
    else if(page == 1)
    {
      printf("Writing BCK page of the VME FPGA\n");
      pa = VME_FIRST_PAGE_BCK;
	}
    else
    {
      printf("Bad Image.\n");
      exit(0);
	}

    printf("Updating firmware of the FPGA VME with the file %s\n", filename);
  }
  else
  {
    printf("Bad FPGA Target.\n");
	exit(0);
  }


  bcnt = 0; /* byte counter */
  bp = 0;   /* byte pointer in the page */
  finish = 0;

  /* while loop */
  while(!finish)
  {
    c = (unsigned char) fgetc(cf); /* read one byte from file */

    /* mirror byte (lsb becomes msb) */
    pdw[bp] = 0;
    for(i=0; i<8; i++)
    {
	if(c & (1<<i))
	{
        pdw[bp] = pdw[bp] | (0x80>>i);
	}
    }

    bp++;
    bcnt++;
    if(feof(cf))
    {
      printf("End of file: bp=%d bcnt=%d\n",bp,bcnt);
      finish = 1;
    }

    /* write and verify a page */
    if((bp == PAGE_SIZE) || finish)
    {
      write_flash_page1(baseaddr, pdw, pa, user_vme);
      read_flash_page1(baseaddr, pdr, pa, user_vme);
      for(i=0; i<PAGE_SIZE; i++)
      {
        if(pdr[i] != pdw[i])
        {
          printf("[%3d] written 0x%02x, read back 0x%02x",i,pdw[i],pdr[i]);
          printf(" -> Flash writing failure (byte %d of page %d)!\n",i,pa);
          printf("\nFirmware not loaded !\n");
          exit(0);
        }
	  }
      bp=0;
      pa++;
    }
  } /* end of while loop */

  fclose(cf);
  printf("\nFirmware loaded successfully. Written %d bytes\n", bcnt);
//  printf("Write 1 at address 0x8016 to reload updated version of the User FPGA\n");

  printf("\n");
  v1495reload(baseaddr);

  return(0);
}

//Resets v1495 pointer to NULL
void
v1495Release(void)
{
	v1495 = NULL;

	return;
}


//Checks for number of entries in dataFIFO
int
v1495DataReady(void)
{
	int i, FIFOBigSize = 0, EventBigSize = 0;

	if(v1495 == NULL) {
    		printf("v1495Sprint: ERROR : v1495 not initialized \n");
    		return(-1);
  	}

	for(i=0;i<NUM_VFATS;i++)
		if(FIFOBigSize < (v1495->FIFOLength[i])& 0x3F)
			FIFOBigSize = v1495->FIFOLength[i]&0x3F;

// Extra code for checking EventSize
// EventSize does not always agree with FIFOLength
// This code is commented out for now
/*
	for(i=0;i<6;i++)
		if(v1495->EventsSentH[i] || EventBigSize < v1495->EventsSentL[i])
			EventBigSize = v1495->EventsSentL[i];
	
	
	if(FIFOBigSize != EventBigSize)
	{
		printf("v1495DataReady: Error: Number of words in sizeFIFO does not equal EventSize.\n");
		return(ERROR);
	}
*/
	return FIFOBigSize;
}


STATUS
v1495Reset(void)
{
	int i;

	if(v1495 == NULL) {
    		printf("v1495Reset: ERROR : v1495 not initialized \n");
    		return(-1);
  	}	

	v1495->Reset = 0;

	printf("v1495 module has been reset: \n\n");



// Uses the fact that the DataValid and DataOut lines are high when VFATs are 
//    disconnected to check for VFAT
// : Very buggy, therefore left out for now.
	/*
	for(i=0;i<NUM_VFATS;i++) {
		if(v1495->EventsSentH[i] > 0 || v1495->EventsSentL[i] > 0)
			printf("GEM[%i] is not present. EventsSentL:0x%04X\n",i,v1495->EventsSentL[i]);
		else if (v1495->EventsSentL[i] == 0)
			printf("GEM[%i] is present. \n",i);
		else
			printf("v1495Reset: ERROR: GEM[%i] has reported invalid value for .EventsSentL 					\n",i);	
	}

	printf("\n");
	*/

	return(OK);
}