/*----------------------------------------------------------------------------*/ /** * @mainpage *
 *  Copyright (c) 2010        Southeastern Universities Research Association, *
 *                            Thomas Jefferson National Accelerator Facility  *
 *                                                                            *
 *    This software was developed under a United States Government license    *
 *    described in the NOTICE file included as part of this distribution.     *
 *                                                                            *
 *    Authors: Bryan Moffit                                                   *
 *             moffit@jlab.org                   Jefferson Lab, MS-12B3       *
 *             Phone: (757) 269-5660             12000 Jefferson Ave.         *
 *             Fax:   (757) 269-5800             Newport News, VA 23606       *
 *
 *             Gerard Visser
 *             gvisser@indiana.edu
 *             Indiana University
 *
 * __DATE__:
 *                                                                            *
 *----------------------------------------------------------------------------*
 *
 * Description:
 *     Driver library for readout of the 125MSPS ADC using vxWorks 5.5 
 *     (or later) or Intel based single board computer
 * 
*----------------------------------------------------------------------------*/ #include #include #include #include #include #ifdef VXWORKS #include #include #include #include #include #else #include #include "jvme.h" #endif #include #include "fa125Lib.h" #ifndef LSWAP #define LSWAP(x) ((((x) & 0x000000ff) << 24) | \ (((x) & 0x0000ff00) << 8) | \ (((x) & 0x00ff0000) >> 8) | \ (((x) & 0xff000000) >> 24)) #endif /* Mutex to guard TD read/writes */ pthread_mutex_t fa125Mutex = PTHREAD_MUTEX_INITIALIZER; #define FA125LOCK if(pthread_mutex_lock(&fa125Mutex)<0) perror("pthread_mutex_lock"); #define FA125UNLOCK if(pthread_mutex_unlock(&fa125Mutex)<0) perror("pthread_mutex_unlock"); /* Define global variables */ int nfa125=0; /* Number of initialized modules */ volatile struct fa125_a24 *fa125p[(FA125_MAX_BOARDS+1)]; /* pointers to FA125 memory map */ volatile struct fa125_a32 *fa125pd[(FA125_MAX_BOARDS+1)]; /* pointers to FA125 FIFO memory */ volatile unsigned int *FA125pmb; /* pointer to Multblock window */ int fa125ID[FA125_MAX_BOARDS]; /* array of slot numbers for FA125s */ unsigned int fa125A32Base = 0x09000000; /* Minimum VME A32 Address for use by FA125s */ unsigned long fa125A32Offset = 0x08000000; /* Difference in CPU A32 Base - VME A32 Base */ unsigned long fa125A24Offset=0; /* Difference in CPU A24 Base and VME A24 Base */ unsigned int fa125AddrList[FA125_MAX_BOARDS]; /* array of a24 addresses for FA125s */ int fa125MaxSlot=0; /* Highest Slot hold an FA125 */ int fa125MinSlot=0; /* Lowest Slot holding an FA125 */ int fa125TriggerSource=0; int berr_count=0; /* A count of the number of BERR that have occurred when running fa125Poll() */ /* store the dacOffsets in the library, until the firmware is able to read them back */ static unsigned short fa125dacOffset[FA125_MAX_BOARDS+1][72]; int fa125BlockError=FA125_BLOCKERROR_NO_ERROR; /* Whether (1) or not (0) Block Transfer had an error */ /** * @defgroup Config Initialization/Configuration * @defgroup PulserConfig Pulser Initialization/Configuration * @ingroup Config * @defgroup Status Status * @defgroup Readout Data Readout * @defgroup FWUpdate Firmware Updating Utilities * @defgroup Deprec Deprecated - To be removed */ /** * @ingroup Config * @brief Initialize the fa125 Library * * @param addr * - A24 VME Address of the fADC125 * @param addr_inc * - Amount to increment addr to find the next fADC125 * @param nadc * - Number of times to increment * * @param iFlag 17 bit integer *
 *       Low 6 bits - Specifies the default Signal distribution (clock,trigger) 
 *                    sources for the board (Internal, FrontPanel, VXS, VME(Soft))
 *       bit    0:  defines Sync Reset source
 *                 0  VXS (P0)
 *                 1  VME (software)
 *       bits 2-1:  defines Trigger source
 *           (0) 0 0  VXS (P0)
 *           (1) 0 1  Internal Timer
 *           (2) 1 0  Internal Multiplicity Sum
 *           (3) 1 1  P2 Connector (Backplane)
 *       bit    3:  NOT USED WITH THIS FIRMWARE VERSION
 *       bits 5-4:  defines Clock Source
 *           (0) 0 0  P2 Connector (Backplane)
 *           (1) 0 1  VXS (P0)
 *           (2) 1 0  Internal 125MHz Clock
 *       bit   16:  Exit before board initialization (just map structure pointer)
 *                 0: Initialize fa125(s)
 *                 1: Skip initialization
 *       bit   17:  Use fa125AddrList instead of addr and addr_inc
 *                  for VME addresses.
 *                 0: Initialize with addr and addr_inc
 *                 1: Use fa125AddrList 
 *       bit   18:  Skip firmware check.  Useful for firmware updating.
 *                 0: Perform firmware check
 *                 :1 Skip firmware check
 * 
* @return OK, or ERROR if the address is invalid or a board is not present. */ int fa125Init (UINT32 addr, UINT32 addr_inc, int nadc, int iFlag) { int res=0; volatile unsigned int rdata=0; unsigned long laddr=0; unsigned int a32addr=0; volatile struct fa125_a24 *fa125; int useList=0, noBoardInit=0, noFirmwareCheck=0; int nfind=0, islot=0, FA_SLOT=0, ii=0; int trigSrc=0, clkSrc=0, srSrc=0; unsigned int boardID=0, fw_version=0; int maxSlot = 1; int minSlot = 21; /* Initialize some global variables */ nfa125=0; memset((char *)fa125ID,0,sizeof(fa125ID)); memset((char *)fa125dacOffset,0,sizeof(fa125dacOffset)); /* Check if we're skipping initialization, and just mapping the structure pointer */ if(iFlag & FA125_INIT_SKIP) noBoardInit=1; /* Check if we're initializing using a list */ if(iFlag & FA125_INIT_USE_ADDRLIST) { useList=1; nfind = nadc; } /* Are we skipping the firmware check? */ if(iFlag & FA125_INIT_SKIP_FIRMWARE_CHECK) { noFirmwareCheck=1; printf("%s: INFO: Firmware Check Disabled\n", __FUNCTION__); } /* Check for valid address */ if((addr==0) && (useList==0)) { /* Loop through JLab Standard GEOADDR to VME addresses to make a list */ useList=1; nfind=16; for(islot=3; islot<11; islot++) /* First 8 */ fa125AddrList[islot-3] = (islot<<19); /* Skip Switch Slots */ for(islot=13; islot<21; islot++) /* Last 8 */ fa125AddrList[islot-5] = (islot<<19); } else if(addr > 0x00ffffff) /* A32 Addressing */ { printf("\n%s: ERROR: A32 Addressing not allowed for FA125 configuration space\n\n", __FUNCTION__); return(ERROR); } else if((addr!=0) && (useList==0)) { /* A24 Addressing */ if(addr_inc==0) /* Just one module */ { fa125AddrList[0] = addr; nfind=1; } else /* Up to nadc modules */ { for(islot=0; islotmain.id),VX_READ,4,(char *)&rdata); #else res = vmeMemProbe((char *)&(fa125->main.id),4,(char *)&rdata); #endif if(res < 0) { printf("%s: WARN: No addressable board at addr=0x%x\n", __FUNCTION__,(UINT32) fa125AddrList[islot]); } else { /* Check that it is an FA125 */ if(rdata != FA125_ID) { printf("\n%s: ERROR: For module at 0x%x, Invalid Board ID: 0x%x\n\n", __FUNCTION__,fa125AddrList[islot],rdata); continue; } else { /* Check the Firmware Versions */ if(!noFirmwareCheck) { int fw_error=0; /* MAIN */ fw_version = vmeRead32(&fa125->main.version); if(fw_version==0xffffffff) { /* buggy firmware.. re-read */ printf("%s: bum main read\n",__FUNCTION__); fw_version = vmeRead32(&fa125->main.version); } if(fw_version != FA125_MAIN_SUPPORTED_FIRMWARE) { printf("\n%s: ERROR: For module at 0x%x, Unsupported MAIN firmware version 0x%x\n\n", __FUNCTION__,fa125AddrList[islot],fw_version); fw_error=1; } /* PROC */ fw_version = vmeRead32(&fa125->proc.version); if(fw_version==0xffffffff) { /* buggy firmware.. re-read */ printf("%s: bum proc read\n",__FUNCTION__); fw_version = vmeRead32(&fa125->proc.version); } if(fw_version != FA125_PROC_SUPPORTED_FIRMWARE) { printf("\n%s: ERROR: For module at 0x%x, Unsupported PROC firmware version 0x%x\n\n", __FUNCTION__,fa125AddrList[islot],fw_version); fw_error=1; } /* FE - just check the first one */ fw_version = vmeRead32(&fa125->fe[0].version); if(fw_version==0xffffffff) { /* buggy firmware.. re-read */ printf("%s: bum FE read\n",__FUNCTION__); fw_version = vmeRead32(&fa125->fe[0].version); } if(fw_version != FA125_FE_SUPPORTED_FIRMWARE) { printf("\n%s: ERROR: For module at 0x%x, Unsupported FE firmware version 0x%x\n\n", __FUNCTION__,fa125AddrList[islot],fw_version); fw_error=1; } if(fw_error) continue; } /* Get the Geographic Address */ boardID = vmeRead32(&fa125->main.slot_ga); if((boardID<2) || (boardID>21)) { printf("%s: For module at 0x%x, Invalid Slot Number %d\n", __FUNCTION__,fa125AddrList[islot],boardID); continue; } if(boardID >= maxSlot) maxSlot = boardID; if(boardID <= minSlot) minSlot = boardID; fa125p[boardID] = (struct fa125_a24 *) (fa125AddrList[islot]+fa125A24Offset); fa125ID[nfa125] = boardID; printf("Initialized FA125 %2d Slot # %2d at address 0x%08lx (0x%08x)\n", nfa125,fa125ID[nfa125], (unsigned long)fa125p[fa125ID[nfa125]], (unsigned int)((unsigned long)fa125p[fa125ID[nfa125]] - fa125A24Offset)); } nfa125++; } } if(noBoardInit) { if(nfa125>0) { printf("%s: %d FA125(s) successfully mapped (not initialized)\n", __FUNCTION__,nfa125); return OK; } } if(nfa125==0) { printf("\n%s: ERROR: Unable to initialize any FA125 modules\n\n", __FUNCTION__); return ERROR; } /* Determine the clock, sync, trigger configuration */ /* Sync Reset */ srSrc = (iFlag&0x1); /* Trigger */ trigSrc = (iFlag&0x6)>>1; fa125TriggerSource = trigSrc; /* Clock Source */ clkSrc = (iFlag&0x30)>>4; /* Perform some initialization here */ for(islot=0; islotmain.adr32, (a32addr>>16) | FA125_ADR32_ENABLE); /* Write the register and enable */ vmeWrite32(&fa125p[fa125ID[ii]]->main.ctrl1, vmeRead32(&fa125p[fa125ID[ii]]->main.ctrl1) | FA125_CTRL1_ENABLE_BERR);/* Enable Bus Error termination */ } } /* If there are more than 1 FA125 in the crate then setup the Muliblock Address window. This must be the same on each board in the crate */ if(nfa125 > 1) { a32addr = fa125A32Base + (nfa125+1)*FA125_MAX_A32_MEM; /* set MB base above individual board base */ #ifdef VXWORKS res = sysBusToLocalAdrs(0x09,(char *)a32addr,(char **)&laddr); if (res != 0) { printf("\n%s: ERROR in sysBusToLocalAdrs(0x09,0x%x,&laddr) \n\n",__FUNCTION__,a32addr); return(ERROR); } #else res = vmeBusToLocalAdrs(0x09,(char *)a32addr,(char **)&laddr); if (res != 0) { printf("\n%s: ERROR in vmeBusToLocalAdrs(0x09,0x%x,&laddr) \n\n",__FUNCTION__,a32addr); return(ERROR); } #endif FA125pmb = (unsigned int *)(laddr); /* Set a pointer to the FIFO */ if(!noBoardInit) { unsigned int ctrl1=0; for (ii=0;iimain.adr_mb, (a32addr+FA125_MAX_A32MB_SIZE) | (a32addr>>16) | FA125_ADRMB_ENABLE); ctrl1 = vmeRead32(&fa125p[fa125ID[ii]]->main.ctrl1) & ~(FA125_CTRL1_FIRST_BOARD | FA125_CTRL1_LAST_BOARD); vmeWrite32(&fa125p[fa125ID[ii]]->main.ctrl1, ctrl1 | FA125_CTRL1_ENABLE_MULTIBLOCK); } } /* Set First Board and Last Board */ fa125MaxSlot = maxSlot; fa125MinSlot = minSlot; if(!noBoardInit) { vmeWrite32(&fa125p[minSlot]->main.ctrl1, vmeRead32(&fa125p[minSlot]->main.ctrl1) | FA125_CTRL1_FIRST_BOARD); vmeWrite32(&fa125p[maxSlot]->main.ctrl1, vmeRead32(&fa125p[maxSlot]->main.ctrl1) | FA125_CTRL1_LAST_BOARD); } } if(nfa125 > 0) printf("%s: %d FA125(s) successfully initialized\n",__FUNCTION__,nfa125); return(OK); } void fa125CheckAddresses(int id) { unsigned int offset=0, expected=0; unsigned long base=0; int ife=0; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id]==NULL)) { printf("\n%s: ERROR: FA125 in slot %d not initialized\n\n",__FUNCTION__,id); return; } printf("%s:\n\t ---------- Checking FA125 address space ---------- \n",__FUNCTION__); base = (unsigned long) &fa125p[id]->main; for(ife=0; ife<12; ife++) { offset = ((unsigned long) &fa125p[id]->fe[ife]) - base; expected = 0x1000 + ife*0x1000; if(offset != expected) printf("\n%s: ERROR fa125p[%d]->fe[%d] not at offset = 0x%x (@ 0x%x)\n\n", __FUNCTION__,id,ife,expected,offset); } offset = ((unsigned long) &fa125p[id]->fe[0].ie) - base; expected = 0x10b0; if(offset != expected) printf("\n%s: ERROR fa125p[%d]->fe[0].ie not at offset = 0x%x (@ 0x%x)\n\n", __FUNCTION__,id,expected,offset); offset = ((unsigned long) &fa125p[id]->proc) - base; expected = 0xD000; if(offset != expected) printf("\n%s: ERROR fa125p[%d]->proc not at offset = 0x%x (@ 0x%x)\n\n", __FUNCTION__,id,expected,offset); offset = ((unsigned long) &fa125p[id]->proc.trigsrc) - base; expected = 0xD008; if(offset != expected) printf("\n%s: ERROR fa125p[%d]->proc.trigsrc not at offset = 0x%x (@ 0x%x)\n\n", __FUNCTION__,id,expected,offset); } /** * @ingroup Config * @brief Convert an index into a slot number, where the index is * the element of an array of fA125s in the order in which they were * initialized. * * @param i Initialization number * @return Slot number if Successfull, otherwise ERROR. * */ int fa125Slot(unsigned int i) { if(i>=nfa125) { printf("\n%s: ERROR: Index (%d) >= FA125s initialized (%d).\n\n", __FUNCTION__,i,nfa125); return ERROR; } return fa125ID[i]; } /** * @ingroup Status * @brief Print Status of fADC125 to standard out * @param id Slot Number * @param pflag Print option flag * - bit 0 (FA125_STATUS_SHOWREGS): Show some register values to standard out * @return OK if successful, otherwise ERROR. */ int fa125Status(int id, int pflag) { struct fa125_a24_main m; struct fa125_a24_proc p; struct fa125_a24_fe f[12]; unsigned int clksrc, trigsrc, srsrc; unsigned int faBase, a32Base, ambMin, ambMax; int i=0, showregs=0, sign=1; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(pflag & FA125_STATUS_SHOWREGS) showregs=1; FA125LOCK; m.id = vmeRead32(&fa125p[id]->main.id); m.swapctl = vmeRead32(&fa125p[id]->main.swapctl); m.version = vmeRead32(&fa125p[id]->main.version); m.pwrctl = vmeRead32(&fa125p[id]->main.pwrctl); m.slot_ga = vmeRead32(&fa125p[id]->main.slot_ga); m.clock = vmeRead32(&fa125p[id]->main.clock); for(i=0; i<4; i++) m.serial[i] = vmeRead32(&fa125p[id]->main.serial[i]); f[0].version = vmeRead32(&fa125p[id]->fe[0].version); if(f[0].version==0xffffffff) { f[0].version = vmeRead32(&fa125p[id]->fe[0].version); } p.version = vmeRead32(&fa125p[id]->proc.version); p.csr = vmeRead32(&fa125p[id]->proc.csr); p.trigsrc = vmeRead32(&fa125p[id]->proc.trigsrc); p.ctrl2 = vmeRead32(&fa125p[id]->proc.ctrl2); m.adr32 = vmeRead32(&fa125p[id]->main.adr32); m.adr_mb = vmeRead32(&fa125p[id]->main.adr_mb); m.ctrl1 = vmeRead32(&fa125p[id]->main.ctrl1); m.block_count = vmeRead32(&fa125p[id]->main.block_count); p.trig_count = vmeRead32(&fa125p[id]->proc.trig_count); p.ev_count = vmeRead32(&fa125p[id]->proc.ev_count); m.blockCSR = vmeRead32(&fa125p[id]->main.blockCSR); f[0].config1 = vmeRead32(&fa125p[id]->fe[0].config1); f[0].nw = vmeRead32(&fa125p[id]->fe[0].nw) & FA125_FE_NW_MASK; f[0].pl = vmeRead32(&fa125p[id]->fe[0].pl) & FA125_FE_PL_MASK; f[0].ie = vmeRead32(&fa125p[id]->fe[0].ie); f[0].ped_sf = vmeRead32(&fa125p[id]->fe[0].ped_sf); sign = (f[0].ped_sf&FA125_FE_PED_SF_PBIT_SIGN)?-1:1; for(i=0; i<12; i++) { f[i].test = vmeRead32(&fa125p[id]->fe[i].test); } FA125UNLOCK; faBase = (unsigned int) &fa125p[id]->main.id; a32Base = (m.adr32 & FA125_ADR32_BASE_MASK)<<16; ambMin = (m.adr_mb & FA125_ADRMB_MIN_MASK)<<16; ambMax = (m.adr_mb & FA125_ADRMB_MAX_MASK); #ifdef VXWORKS printf("\nSTATUS for FA125 in slot %d at base address 0x%x \n", id, (UINT32) fa125p[id]); #else printf("\nSTATUS for FA125 in slot %d at VME (Local) base address 0x%x (0x%lx)\n", id, (UINT32)((unsigned long)fa125p[id] - fa125A24Offset), (unsigned long) fa125p[id]); #endif printf("--------------------------------------------------------------------------------\n"); printf(" Main Firmware Revision = 0x%08x\n", m.version); printf(" FrontEnd Firmware Revision = 0x%08x\n", f[0].version); printf(" Processing Revision = 0x%08x\n", p.version); printf(" Main SN = 0x%04x%08x\n",m.serial[0], m.serial[1]); printf(" Mezzanine SN = 0x%04x%08x\n",m.serial[2], m.serial[3]); printf("\n"); if(showregs) { printf("Registers:\n"); printf(" blockCSR (0x%04lx) = 0x%08x\t", (unsigned long)(&fa125p[id]->main.blockCSR) - faBase, m.blockCSR); printf(" ctrl1 (0x%04lx) = 0x%08x\n", (unsigned long)(&fa125p[id]->main.ctrl1) - faBase, m.ctrl1); printf(" adr32 (0x%04lx) = 0x%08x\t", (unsigned long)(&fa125p[id]->main.adr32) - faBase, m.adr32); printf(" adr_mb (0x%04lx) = 0x%08x\n", (unsigned long)(&fa125p[id]->main.adr_mb) - faBase, m.adr_mb); printf(" trigsrc (0x%04lx) = 0x%08x\t", (unsigned long)(&fa125p[id]->proc.trigsrc) - faBase, p.trigsrc); printf(" clock (0x%04lx) = 0x%08x\n", (unsigned long)(&fa125p[id]->main.clock) - faBase, m.clock); printf(" config1 (0x%04lx) = 0x%08x\n", (unsigned long)(&fa125p[id]->fe[0].config1) - faBase, f[0].config1); printf("\n"); for(i=0; i<12; i=i+2) { printf(" test %2d (0x%04lx) = 0x%08x\t", i, (unsigned long)(&fa125p[id]->fe[i].test) - faBase, f[i].test); printf(" test %2d (0x%04lx) = 0x%08x\n", i+1, (unsigned long)(&fa125p[id]->fe[i+1].test) - faBase, f[i+1].test); } printf("\n"); } if(m.ctrl1 & FA125_CTRL1_ENABLE_MULTIBLOCK) { printf(" Alternate VME Addressing: Multiblock Enabled\n"); if(m.adr32&FA125_ADR32_ENABLE) printf(" A32 Enabled at VME (Local) base 0x%08x (0x%08lx)\n",a32Base, (unsigned long) fa125pd[id]); else printf(" A32 Disabled\n"); printf(" Multiblock VME Address Range 0x%08x - 0x%08x\n",ambMin,ambMax); } else { printf(" Alternate VME Addressing: Multiblock Disabled\n"); if(m.adr32&FA125_ADR32_ENABLE) printf(" A32 Enabled at VME (Local) base 0x%08x (0x%08lx)\n",a32Base, (unsigned long) fa125pd[id]); else printf(" A32 Disabled\n"); } printf("\n"); /* POWER */ if(m.pwrctl) printf(" Power is ON\n"); else printf(" Power is OFF\n"); /* CLOCK */ printf(" Clock Source (0x%02x) :",m.clock); clksrc = m.clock & 0xffff; if(clksrc == FA125_CLOCK_P2) printf(" P2\n"); else if (clksrc == FA125_CLOCK_P0) printf(" P0 (VXS)\n"); else if (clksrc == FA125_CLOCK_INTERNAL) printf(" Internal\n"); else printf(" ????\n"); /* TRIGGER */ printf(" Trigger Source (0x%02x) :",p.trigsrc); trigsrc = p.trigsrc & FA125_TRIGSRC_TRIGGER_MASK; if(trigsrc == FA125_TRIGSRC_TRIGGER_P0) printf(" P0 (VXS)\n"); else if (trigsrc == FA125_TRIGSRC_TRIGGER_SOFTWARE) printf(" Software (VME)\n"); else if (trigsrc == FA125_TRIGSRC_TRIGGER_INTERNAL_SUM) printf(" Internal Sum\n"); else if (trigsrc == FA125_TRIGSRC_TRIGGER_P2) printf(" P2\n"); /* SYNCRESET */ printf(" SyncReset Source :"); srsrc = (p.ctrl2 & FA125_PROC_CTRL2_SYNCRESET_SOURCE_MASK)>>2; if(srsrc == FA125_PROC_CTRL2_SYNCRESET_P0) printf(" P0 (VXS)\n"); else if (srsrc == FA125_PROC_CTRL2_SYNCRESET_VME) printf(" VME (software)\n"); printf("\n"); printf(" Bus Error %s\n", (m.ctrl1&FA125_CTRL1_ENABLE_BERR)?"ENABLED":"DISABLED"); if(m.ctrl1 & FA125_CTRL1_ENABLE_MULTIBLOCK) { if(m.ctrl1&FA125_CTRL1_FIRST_BOARD) printf(" MultiBlock transfer ENABLED (First Board)\n"); else if(m.ctrl1&FA125_CTRL1_LAST_BOARD) printf(" MultiBlock transfer ENABLED (Last Board)\n"); else printf(" MultiBlock transfer ENABLED\n"); } else printf(" MultiBlock transfer DISABLED\n"); printf("\n"); printf(" Processing Configuration: \n"); printf(" Mode = %s (%d) - %s\n\n", fa125_mode_names[(f[0].config1&FA125_FE_CONFIG1_MODE_MASK) + 1], (f[0].config1&FA125_FE_CONFIG1_MODE_MASK)+1, (f[0].config1 & FA125_FE_CONFIG1_ENABLE)?"ENABLED":"DISABLED"); printf(" Lookback (PL) = %5d %5dns\n", f[0].pl, 8*f[0].pl); printf(" Time Window (NW) = %5d %5dns\n", f[0].nw, 8*f[0].nw); printf(" Integration End (IE) = %5d %5dns\n", (f[0].ie & FA125_FE_IE_INTEGRATION_END_MASK), 8*(f[0].ie & FA125_FE_IE_INTEGRATION_END_MASK)); printf(" Pedestal Gap (PG) = %5d %5dns\n", ((f[0].ie & FA125_FE_IE_PEDESTAL_GAP_MASK)>>12), 8*((f[0].ie & FA125_FE_IE_PEDESTAL_GAP_MASK)>>12)); printf(" Initial Pedestal exponent (P1) = %5d\n", (f[0].ped_sf & FA125_FE_PED_SF_NP_MASK)); printf(" Initial Pedestal window (NP = 2**P1) = %5d %5dns\n", (1<<(f[0].ped_sf & FA125_FE_PED_SF_NP_MASK)), 8*(1<<(f[0].ped_sf & FA125_FE_PED_SF_NP_MASK))); printf(" Local Pedestal exponent (P2) = %5d\n", (f[0].ped_sf & FA125_FE_PED_SF_NP2_MASK)>>8); printf(" Local Pedestal window (NP2= 2**P2) = %5d %5dns\n", (1<<((f[0].ped_sf & FA125_FE_PED_SF_NP2_MASK)>>8)), 8*(1<<((f[0].ped_sf & FA125_FE_PED_SF_NP2_MASK)>>8))); printf("\n"); printf(" Scale Factors:\n"); printf(" Integration (IBIT) = %d Amplitude (ABIT) = %d Pedestal (PBIT) = %d\n", ((f[0].ped_sf & FA125_FE_PED_SF_IBIT_MASK)>>16), ((f[0].ped_sf & FA125_FE_PED_SF_ABIT_MASK)>>19), sign*((f[0].ped_sf & FA125_FE_PED_SF_PBIT_MASK)>>22)); printf(" (2**IBIT) = %-3d (2**ABIT) = %-3d (2**PBIT) = ", 1<<((f[0].ped_sf & FA125_FE_PED_SF_IBIT_MASK)>>16), 1<<((f[0].ped_sf & FA125_FE_PED_SF_ABIT_MASK)>>19)); if(sign==1) printf("%-2d\n\n",1<<((f[0].ped_sf & FA125_FE_PED_SF_PBIT_MASK)>>22)); else printf("1/%-2d\n\n",1<<((f[0].ped_sf & FA125_FE_PED_SF_PBIT_MASK)>>22)); printf(" Max Peak Count = %d \n",(f[0].config1 & FA125_FE_CONFIG1_NPULSES_MASK)>>4); printf(" Playback Mode = %s \n", (f[0].config1 & FA125_FE_CONFIG1_PLAYBACK_ENABLE)?"ENABLED":"DISABLED"); printf("\n"); printf(" Block Count = %d\n",m.block_count); printf(" Trig Count = %d\n",p.trig_count); printf(" Ev Count = %d\n",p.ev_count); printf("\n"); fa125CheckThresholds(id,1); printf("--------------------------------------------------------------------------------\n"); return OK; } /** * @ingroup Status * @brief Print a summary of all initialized fADC1250s * @param pflag Not used */ void fa125GStatus(int pflag) { int ifa, id; struct fa125_a24_main m[20]; struct fa125_a24_proc p[20]; struct fa125_a24_fe f[20]; unsigned int a24addr[20]; int th_check[20], sign[20]; FA125LOCK; for (ifa=0;ifamain.version); m[id].adr32 = vmeRead32(&fa125p[id]->main.adr32); m[id].adr_mb = vmeRead32(&fa125p[id]->main.adr_mb); m[id].pwrctl = vmeRead32(&fa125p[id]->main.pwrctl); m[id].clock = vmeRead32(&fa125p[id]->main.clock); m[id].ctrl1 = vmeRead32(&fa125p[id]->main.ctrl1); m[id].blockCSR = vmeRead32(&fa125p[id]->main.blockCSR); m[id].block_count = vmeRead32(&fa125p[id]->main.block_count); p[id].version = vmeRead32(&fa125p[id]->proc.version); p[id].trigsrc = vmeRead32(&fa125p[id]->proc.trigsrc); p[id].ctrl2 = vmeRead32(&fa125p[id]->proc.ctrl2); p[id].blocklevel = vmeRead32(&fa125p[id]->proc.blocklevel); p[id].trig_count = vmeRead32(&fa125p[id]->proc.trig_count); p[id].trig2_count = vmeRead32(&fa125p[id]->proc.trig2_count); p[id].sync_count = vmeRead32(&fa125p[id]->proc.sync_count); f[id].version = vmeRead32(&fa125p[id]->fe[0].version); f[id].config1 = vmeRead32(&fa125p[id]->fe[0].config1); f[id].pl = vmeRead32(&fa125p[id]->fe[0].pl) & FA125_FE_PL_MASK; f[id].nw = vmeRead32(&fa125p[id]->fe[0].nw) & FA125_FE_NW_MASK; f[id].ie = vmeRead32(&fa125p[id]->fe[0].ie); f[id].ped_sf = vmeRead32(&fa125p[id]->fe[0].ped_sf); sign[id] = (f[id].ped_sf & FA125_FE_PED_SF_PBIT_SIGN)?-1:1; } FA125UNLOCK; for (ifa=0;ifa>2 == FA125_PROC_CTRL2_SYNCRESET_P0 ? " VXS " : (p[id].ctrl2 & FA125_PROC_CTRL2_SYNCRESET_SOURCE_MASK)>>2 == FA125_PROC_CTRL2_SYNCRESET_VME? " VME " : " ??? "); printf("%s ", (m[id].ctrl1 & FA125_CTRL1_ENABLE_MULTIBLOCK) ? "YES":" NO"); printf(" VXS"); printf("%s ", m[id].ctrl1 & (FA125_CTRL1_FIRST_BOARD) ? "-F": m[id].ctrl1 & (FA125_CTRL1_LAST_BOARD) ? "-L": " "); printf("%s ", m[id].ctrl1 & FA125_CTRL1_ENABLE_BERR ? "YES" : " NO"); printf("\n"); } printf("--------------------------------------------------------------------------------\n"); printf("\n"); printf(" fADC125 Processing Mode Config\n\n"); printf(" Block\n"); printf("Slot Level Mode ......PL...... ....NW..... ....IE.... ...PG...\n"); printf("--------------------------------------------------------------------------------\n"); for(ifa=0; ifa>12), 8*((f[id].ie & FA125_FE_IE_PEDESTAL_GAP_MASK)>>12)); printf("\n"); } printf("--------------------------------------------------------------------------------\n"); printf("\n"); printf(" fADC125 Processing Mode Config\n\n"); printf(" Pedestal Windows Scale \n"); printf(" ---Initial--- ----Local---- ..Factors.. Playback Thres\n"); printf("Slot P1 ...NP1.... P2 ...NP2.... I A P NPK Mode Check\n"); printf("--------------------------------------------------------------------------------\n"); for(ifa=0; ifa>8, 8*(1<<((f[id].ped_sf & FA125_FE_PED_SF_NP2_MASK)>>8)), (1<<((f[id].ped_sf & FA125_FE_PED_SF_NP2_MASK)>>8)) ); printf("%d ", (f[id].ped_sf & FA125_FE_PED_SF_IBIT_MASK)>>16); printf("%d ", (f[id].ped_sf & FA125_FE_PED_SF_ABIT_MASK)>>19); printf("%2d ", sign[id] * ((f[id].ped_sf & FA125_FE_PED_SF_PBIT_MASK)>>22 )); printf("%2d ", (f[id].config1 & FA125_FE_CONFIG1_NPULSES_MASK)>>4); printf("%s ", (f[id].config1 & FA125_FE_CONFIG1_PLAYBACK_ENABLE) ?" Enabled":"Disabled"); printf("%s", (th_check[id]==OK)?" OK":"ERR"); printf("\n"); } printf("--------------------------------------------------------------------------------\n"); printf("\n"); printf(" fADC125 Signal Scalers\n\n"); printf("Slot Trig1 Trig2 SyncReset\n"); printf("--------------------------------------------------------------------------------\n"); for(ifa=0; ifa NP + NE * (2) NW > NU * (3) NU > 14 * (4) NE >= NU-PG-PED * (5) NE >= 6 * (6) NPK > 0 * (7) NP >= NP2 * (8) NP2 > 0 * (9) H > TH > TL * (10) PED > 4 * (11) PG > 0 * (12) PED+PG < NU * * @return OK if successful, otherwise ERROR. */ int fa125SetProcMode(int id, char *mode, unsigned int PL, unsigned int NW, unsigned int IE, unsigned int PG, unsigned int NPK, unsigned int P1, unsigned int P2) { int imode=0, pmode=0, supported_modes[FA125_SUPPORTED_NMODES] = FA125_SUPPORTED_MODES; int cdc_modes[FA125_CDC_NMODES] = FA125_CDC_MODES; int mode_supported=0, cdc_mode=0; int NE=20; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } pmode = fa125GetModeNumber(mode); /* Check if mode is supported */ for(imode=0; imodeFA125_MAX_PL)) { printf("%s: WARN: Invalid PL (%d). Setting default (%d)\n", __FUNCTION__,PL,FA125_DEFAULT_PL); PL = FA125_DEFAULT_PL; } if((NW==0) || (NW>FA125_MAX_NW)) { printf("%s: WARN: Invalid NW (%d). Setting default (%d)\n", __FUNCTION__,NW,FA125_DEFAULT_NW); NW = FA125_DEFAULT_NW; } if((IE==0) || (IE>FA125_MAX_IE)) { printf("%s: WARN: Invalid IE (%d). Setting default (%d)\n", __FUNCTION__,IE,FA125_DEFAULT_IE); IE = FA125_DEFAULT_IE; } if((PG==0) || (PG>FA125_MAX_PG)) { printf("%s: WARN: Invalid PG (%d). Setting default (%d)\n", __FUNCTION__,PG,FA125_DEFAULT_PG); PG = FA125_DEFAULT_PG; } if((NPK==0) || (NPK>FA125_MAX_NPK)) { printf("%s: WARN: Invalid NPK (%d). Setting default (%d)\n", __FUNCTION__,NPK,FA125_DEFAULT_NPK); NPK = FA125_DEFAULT_NPK; } if(cdc_mode && (NPK!=1)) { printf("%s: WARN: Invalid NPK (%d) for CDC mode. Setting to 1\n", __FUNCTION__,NPK); NPK=1; } /* Consistancy check */ if(NW > PL) { printf("\n%s: ERROR: Window must be <= Latency\n\n",__FUNCTION__); return ERROR; } if(NW <= ((2^P1) + NE)) { printf("\n%s: ERROR: Window must be > Initial Pedestal Window + NE (%d)\n\n",__FUNCTION__ ,NE); return ERROR; } if(P1 < P2) { printf("\n%s: ERROR: Initial Pedestal Window Must be >= Local Pedestal Window\n\n", __FUNCTION__); return ERROR; } FA125LOCK; /* Disable ADC processing while writing window info */ vmeWrite32(&fa125p[id]->fe[0].config1, ((pmode-1) | (NPK<<4))); vmeWrite32(&fa125p[id]->fe[0].pl, PL); vmeWrite32(&fa125p[id]->fe[0].nw, NW); vmeWrite32(&fa125p[id]->fe[0].ie, IE | (PG<<12)); vmeWrite32(&fa125p[id]->fe[0].ped_sf, (vmeRead32(&fa125p[id]->fe[0].ped_sf) & ~(FA125_FE_PED_SF_NP_MASK | FA125_FE_PED_SF_NP2_MASK)) | (P1 | (P2<<8)) ); /* Enable ADC processing */ vmeWrite32(&fa125p[id]->fe[0].config1, ((pmode-1) | (NPK<<4) | FA125_FE_CONFIG1_ENABLE) ); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Set the Integration, Amplitude, and Pedestal scale factors for the selected module * @param id Slot number * @param IBIT Integration Scale Factor * @param ABIT Amplitude Scale Factor * @param PBIT Pedestal Scale Factor * @return OK if successful, otherwise ERROR. */ int fa125SetScaleFactors(int id, unsigned int IBIT, unsigned int ABIT, int PBIT) { int rval=OK, pbit_sign_bit=0, p2=0; unsigned int ped_sf=0, check=0, uint_PBIT=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(IBIT>FA125_MAX_IBIT) { printf("\n%s: ERROR: Invalid IBIT scale factor. Must be <= %d\n\n", __FUNCTION__,FA125_MAX_IBIT); return ERROR; } if(ABIT>FA125_MAX_ABIT) { printf("\n%s: ERROR: Invalid ABIT scale factor. Must be <= %d\n\n", __FUNCTION__,FA125_MAX_ABIT); return ERROR; } if(abs(PBIT)>FA125_MAX_PBIT) { printf("\n%s: ERROR: Invalid PBIT scale factor. Must be <= %d\n\n", __FUNCTION__,FA125_MAX_PBIT); return ERROR; } if(PBIT<0) pbit_sign_bit = 1; FA125LOCK; ped_sf = vmeRead32(&fa125p[id]->fe[0].ped_sf); p2 = ((ped_sf & FA125_FE_PED_SF_NP2_MASK)>>8); if((p2 + PBIT) < 0) { printf("%s: ERROR: P2 + PBIT < 0 (%d + %d) = %d\n", __FUNCTION__, p2, PBIT, p2 + PBIT); printf("\tSetting PBIT to default = %d\n", FA125_DEFAULT_PBIT); PBIT = FA125_DEFAULT_PBIT; pbit_sign_bit = 0; rval = ERROR; } if((p2 + PBIT) > 7) { printf("%s: ERROR: P2 + PBIT > 7 (%d + %d) = %d\n", __FUNCTION__, p2, PBIT, p2 + PBIT); printf("\tSetting PBIT to default = %d\n", FA125_DEFAULT_PBIT); PBIT = FA125_DEFAULT_PBIT; pbit_sign_bit = 0; rval = ERROR; } uint_PBIT = pbit_sign_bit ? (unsigned int)((-1) * PBIT) : PBIT; vmeWrite32(&fa125p[id]->fe[0].ped_sf, (ped_sf & (FA125_FE_PED_SF_NP_MASK | FA125_FE_PED_SF_NP2_MASK)) | (IBIT<<16) | (ABIT<<19) | (uint_PBIT<<22) | (pbit_sign_bit<<25)); check = (vmeRead32(&fa125p[id]->fe[0].ped_sf) & FA125_FE_PED_SF_CALC_MASK) >> 26; if(check != (p2 + PBIT)) { printf("%s: FIRMWARE ERROR: P2 + PBIT fw: = %d lib: %d\n", __FUNCTION__,check, p2 + PBIT); printf(" register = 0x%08x\n",vmeRead32(&fa125p[id]->fe[0].ped_sf)); rval = ERROR; } FA125UNLOCK; return rval; } /** * @ingroup Status * @brief Return the value stored for the Integration Scale Factor * @param id Slot number * @return Integration Scale Factor if successful, otherwise ERROR. */ int fa125GetIntegrationScaleFactor(int id) { int rval=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } FA125LOCK; rval = (vmeRead32(&fa125p[id]->fe[0].ped_sf) & FA125_FE_PED_SF_IBIT_MASK)>>16; FA125UNLOCK; return rval; } /** * @ingroup Status * @brief Return the value stored for the Amplitude Scale Factor * @param id Slot number * @return Amplitude Scale Factor if successful, otherwise ERROR. */ int fa125GetAmplitudeScaleFactor(int id) { int rval=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } FA125LOCK; rval = (vmeRead32(&fa125p[id]->fe[0].ped_sf) & FA125_FE_PED_SF_ABIT_MASK)>>19; FA125UNLOCK; return rval; } /** * @ingroup Status * @brief Return the value stored for the Pedestal Scale Factor * @param id Slot number * @return Pedestal Scale Factor if successful, otherwise ERROR. */ int fa125GetPedestalScaleFactor(int id) { int rval=0, sign=1; unsigned int ped_sf=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } FA125LOCK; ped_sf = vmeRead32(&fa125p[id]->fe[0].ped_sf); sign = (ped_sf & FA125_FE_PED_SF_PBIT_SIGN)?-1:1; rval = sign * ((ped_sf & FA125_FE_PED_SF_PBIT_MASK)>>22); FA125UNLOCK; return rval; } /** * @ingroup Config * @brief Set the Low and High timing threshold for the selected channel in the selected module. * @param id Slot number * @param chan Channel Number * @param lo Low timing threshold * @param hi High timing threshold * @return Pedestal Scale Factor if successful, otherwise ERROR. */ int fa125SetTimingThreshold(int id, unsigned int chan, unsigned int lo, unsigned int hi) { unsigned int wval = 0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(chan>=FA125_MAX_ADC_CHANNELS) { printf("\n%s: ERROR: Invalid channel (%d). Must be 0-%d\n\n", __FUNCTION__,chan,FA125_MAX_ADC_CHANNELS); return ERROR; } if(lo>FA125_MAX_LOW_TTH) { printf("\n%s: ERROR: Invalid value for Low Timing Threshold (%d)\n\n", __FUNCTION__,lo); return ERROR; } if(hi>FA125_MAX_HIGH_TTH) { printf("\n%s: ERROR: Invalid value for High Timing Threshold (%d)\n\n", __FUNCTION__,hi); return ERROR; } FA125LOCK; /* Write the lo value */ if((chan%2)==0) { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3]) & 0xFFFF0000) | (lo<<8); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3], wval); } else { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3]) & 0xFFFF) | (lo<<24); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3], wval); } /* Write the hi value */ if((chan%3)==0) { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & 0x07fffe00) | (hi); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2], wval); } else if((chan%3)==1) { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & 0x07fc01ff) | (hi<<9); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2], wval); } else { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & 0x0003ffff) | (hi<<18); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2], wval); } FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Set the Low and High timing threshold for all channels in the selected module. * @param id Slot number * @param lo Low timing threshold * @param hi High timing threshold * @return OK if successful, otherwise ERROR. */ int fa125SetCommonTimingThreshold(int id, unsigned int lo, unsigned int hi) { int chan=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(lo>FA125_MAX_LOW_TTH) { printf("\n%s: ERROR: Invalid value for Low Timing Threshold (%d)\n\n", __FUNCTION__,lo); return ERROR; } if(hi>FA125_MAX_HIGH_TTH) { printf("\n%s: ERROR: Invalid value for High Timing Threshold (%d)\n\n", __FUNCTION__,hi); return ERROR; } for(chan=0;chan21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(chan>=FA125_MAX_ADC_CHANNELS) { printf("\n%s: ERROR: Invalid channel (%d). Must be 0-%d\n\n", __FUNCTION__,chan,FA125_MAX_ADC_CHANNELS); return ERROR; } FA125LOCK; if((chan%2)==0) { *lo = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3]) & FA125_FE_TIMING_THRES_LO_MASK(chan))>>8; } else { *lo = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3]) & FA125_FE_TIMING_THRES_LO_MASK(chan))>>24; } if((chan%3)==0) { *hi = vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & FA125_FE_TIMING_THRES_HI_MASK(chan); } else if((chan%3)==1) { *hi = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & FA125_FE_TIMING_THRES_HI_MASK(chan))>>9; } else { *hi = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & FA125_FE_TIMING_THRES_HI_MASK(chan))>>18; } FA125UNLOCK; return OK; } int fa125PrintTimingThresholds(int id) { int ichan, rval, i, lo[FA125_MAX_ADC_CHANNELS], hi[FA125_MAX_ADC_CHANNELS]; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } for(ichan=0; ichan21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } for(ichan=0; ichanTH) && (TH>TL) ) ) { rval = ERROR; if(pflag) { if(header_printed==0) { printf("\n"); printf("%s: ERROR: Invalid Threshold Settings for Module in slot %d\n", __FUNCTION__, id); header_printed=1; } printf(" chan = %3d H = %4d TL = %4d TH = %4d\n", ichan, H, TL, TH); } } } if(pflag) { if(rval==ERROR) printf("\n"); else printf("%s: Threshold conditions OK!\n", __FUNCTION__); } return rval; } /** * @ingroup Config * @brief Power Off the fADC125 * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125PowerOff (int id) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } printf("%s: Power Off for slot %d\n",__FUNCTION__,id); FA125LOCK; vmeWrite32(&fa125p[id]->main.pwrctl, 0); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Power On the fADC125 * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125PowerOn (int id) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } printf("%s: Power On (0x%08x) for slot %d\n",__FUNCTION__, FA125_PWRCTL_KEY_ON,id); FA125LOCK; vmeWrite32(&fa125p[id]->main.pwrctl, FA125_PWRCTL_KEY_ON); FA125UNLOCK; #ifdef VXWORKS taskDelay(18); #else usleep(300000); // delay 300 ms for stable power; #endif return OK; } /** * @ingroup Config * @brief Set DAC value of a specific channel * @param id Slot number * @param dacChan * @param dacData * @return OK if successful, otherwise ERROR. */ static int fa125SetLTC2620 (int id, int dacChan, int dacData) { UINT32 sdat[5]={0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff}; UINT32 bmask,dmask,x; int k,j; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if ((dacChan<0)||(dacChan>79)) { printf("\n%s: ERROR: Invalid DAC Channel %d\n\n", __FUNCTION__,dacChan); return ERROR; } sdat[(dacChan/8)%5] = 0x00200000; // set command nibble and have other fields zeroed sdat[(dacChan/8)%5] |= (dacData & 0x0000ffff); // fill in the data sdat[(dacChan/8)%5] |= ((dacChan%8) << 16); // fill in the subchannel if (dacChan>=40) { bmask=FA125_DACCTL_DACCS_MASK|FA125_DACCTL_ADACSI_MASK; // these assserted for the duration dmask=FA125_DACCTL_BDACSI_MASK; // this is the data bit mask } else { bmask=FA125_DACCTL_DACCS_MASK|FA125_DACCTL_BDACSI_MASK; // these assserted for the duration dmask=FA125_DACCTL_ADACSI_MASK; // this is the data bit mask } FA125LOCK; for(k=4;k>=0;k--) for(j=31;j>=0;j--) { x = bmask | ( ((sdat[k]>>j)&1)!=0 ? dmask : 0 ); vmeWrite32(&fa125p[id]->main.dacctl, x); vmeWrite32(&fa125p[id]->main.dacctl, x | FA125_DACCTL_DACSCLK_MASK); } vmeWrite32(&fa125p[id]->main.dacctl, 0); // this deasserts CS, setting the DAC FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Set the DAC offset for a specific fADC125 Channel. * @param id Slot number * @param chan Channel Number * @param dacData DAC value to set * @return OK if successful, otherwise ERROR. */ int fa125SetOffset (int id, int chan, int dacData) { int rval=0; const int DAC_CHAN_OFFSET[72] = { 34, 33, 32, 39, 38, 37, 36, 27, 26, 25, 24, 31, 74, 73, 72, 79, 78, 77, 76, 67, 66, 65, 64, 71, 30, 29, 28, 18, 17, 16, 23, 22, 21, 20, 10, 9, 70, 69, 68, 58, 57, 56, 63, 62, 61, 60, 50, 49, 8, 15, 14, 13, 12, 2, 1, 0, 7, 6, 5, 4, 48, 55, 54, 53, 52, 42, 41, 40, 47, 46, 45, 44 }; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if ((chan<0)||(chan>71)) { printf("\n%s: ERROR: Invalid Channel %d\n\n",__FUNCTION__,chan); return ERROR; } rval = fa125SetLTC2620(id,DAC_CHAN_OFFSET[chan],dacData); fa125dacOffset[id][chan] = dacData; return rval; } /** * @ingroup Config * @brief Set the DAC offset for a specific fADC125 Channel from a specified file * @param id Slot number * @param filename Name of file from which to read DAC offsets * Format must be of the type: * dac0 dac1 dac2 ... dac71 * @return OK if successful, otherwise ERROR. */ int fa125SetOffsetFromFile(int id, char *filename) { FILE *fd_1; int ichan; int offset_control=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(filename == NULL) { printf("\n%s: ERROR: No file specified.\n\n",__FUNCTION__); return ERROR; } fd_1 = fopen(filename,"r"); if(fd_1 > 0) { printf("%s: Reading Data from file: %s\n",__FUNCTION__,filename); for(ichan=0;ichan<72;ichan++) { fscanf(fd_1,"%d",&offset_control); fa125SetOffset(id, ichan, offset_control); } fclose(fd_1); } else { printf("\n%s: ERROR opening file: %s\n\n",__FUNCTION__,filename); return ERROR; } return OK; } /** * @ingroup Status * @brief Readback the DAC offset set for a specific fADC125 Channel * @param id Slot number * @param chan Channel Number * @return DAC offset if successful, otherwise ERROR. */ unsigned short fa125ReadOffset(int id, int chan) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if((chan<0)||(chan>71)) { printf("\n%s: ERROR: channel (%d) out of range.\n\n", __FUNCTION__,chan); return ERROR; } return fa125dacOffset[id][chan]; } /** * @ingroup Status * @brief Readback the DAC offset set for a specific fADC125 Channel into a specified file * @param id Slot number * @param filename Filename to store all DAC offset * @return DAC offset if successful, otherwise ERROR. */ int fa125ReadOffsetToFile(int id, char *filename) { FILE *fd_1; int ichan; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(filename == NULL) { printf("\n%s: ERROR: No file specified.\n\n",__FUNCTION__); return ERROR; } fd_1 = fopen(filename,"w"); if(fd_1 > 0) { printf("%s: Writing DAC offsets to file: %s\n",__FUNCTION__,filename); for(ichan=0;ichan<72;ichan++) { fprintf(fd_1,"%5d ",fa125dacOffset[id][ichan]); if(((ichan+1)%12)==0) fprintf(fd_1,"\n"); } fprintf(fd_1,"\n"); fclose(fd_1); } else { printf("\n%s: ERROR opening file: %s\n\n",__FUNCTION__,filename); return ERROR; } return OK; } /** * @ingroup Config * @brief Set the readout threshold for a specific fADC125 Channel. * @param id Slot number * @param tvalue Threshold Value * @param chan Channel Number * @return OK if successful, otherwise ERROR. */ int fa125SetThreshold(int id, unsigned short chan, unsigned short tvalue) { if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SetThreshold: ERROR : FA125 in slot %d is not initialized \n\n",id,0,0,0,0,0); return(ERROR); } if(tvalue>FA125_MAX_HIGH_HTH) { logMsg("\nfa125SetThreshold: ERROR: Invalid threshold (%d). Must be <= %d \n\n", tvalue,FA125_MAX_HIGH_HTH,3,4,5,6); return ERROR; } if(chan>=FA125_MAX_ADC_CHANNELS) { logMsg("\nfa125SetThreshold: ERROR: Invalid channel (%d). Must be 0-%d\n\n", chan,FA125_MAX_ADC_CHANNELS,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->fe[chan/6].threshold[chan%6],tvalue); FA125UNLOCK; return(OK); } /** * @ingroup Config * @brief Disable a specific fADC125 Channel. * @param id Slot number * @param chan Channel Number * @return OK if successful, otherwise ERROR. */ int fa125SetChannelDisable(int id, int channel) { int feChip=0, feChan=0; unsigned int chipMask=0; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SetChannelDisable: ERROR : FA125 in slot %d is not initialized \n\n", id,0,0,0,0,0); return(ERROR); } if((channel<0) || (channel>=FA125_MAX_ADC_CHANNELS)) { logMsg("\nfaSetChannelDisable: ERROR: Invalid channel (%d). Must be 0-%d\n\n", channel, FA125_MAX_ADC_CHANNELS-1,3,4,5,6); return ERROR; } feChip = (int)(channel/6); feChan = (int)(channel%6); FA125LOCK; chipMask = (vmeRead32(&fa125p[id]->fe[feChip].config2) & FA125_FE_CONFIG2_CH_MASK) | (1<fe[feChip].config2,chipMask); FA125UNLOCK; return(OK); } /** * @ingroup Config * @brief Disable specific fADC125 Channels using three separate channel masks * @param id Slot number * @param cmask0 Disable channel mask for channels 0-23 * @param cmask1 Disable channel mask for channels 24-47 * @param cmask2 Disable channel mask for channels 48-71 * @return OK if successful, otherwise ERROR. */ int fa125SetChannelDisableMask(int id, unsigned int cmask0, unsigned int cmask1, unsigned int cmask2) { int ichip=0; unsigned int chipMask=0; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SetChannelDisableMask: ERROR : FA125 in slot %d is not initialized \n\n", id,0,0,0,0,0); return(ERROR); } if((cmask0 > 0xFFFFFF) || (cmask1 > 0xFFFFFF) || (cmask2 > 0xFFFFFF)) { logMsg("\nfa125SetChannelDisableMask: ERROR : Invalid channel mask(s) (0x%08x, 0x%08x, 0x%08x).\n", cmask0,cmask1,cmask2,0,0,0); logMsg(" : Each mask must be less than 24 bits.\n\n", 0,0,0,0,0,0); return(ERROR); } FA125LOCK; for(ichip=0; ichip<4; ichip++) { chipMask = (cmask0>>(ichip*6)) & FA125_FE_CONFIG2_CH_MASK; vmeWrite32(&fa125p[id]->fe[ichip].config2,chipMask); } for(ichip=4; ichip<8; ichip++) { chipMask = (cmask1>>((ichip-4)*6)) & FA125_FE_CONFIG2_CH_MASK; vmeWrite32(&fa125p[id]->fe[ichip].config2,chipMask); } for(ichip=8; ichip<12; ichip++) { chipMask = (cmask2>>((ichip-8)*6)) & FA125_FE_CONFIG2_CH_MASK; vmeWrite32(&fa125p[id]->fe[ichip].config2,chipMask); } FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Enable a specific fADC125 Channel. * @param id Slot number * @param chan Channel Number * @return OK if successful, otherwise ERROR. */ int fa125SetChannelEnable(int id, int channel) { int feChip=0, feChan=0; unsigned int chipMask=0; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfaSetChannelEnable: ERROR : ADC in slot %d is not initialized\n\n",id,0,0,0,0,0); return ERROR; } if((channel<0) || (channel>=FA125_MAX_ADC_CHANNELS)) { logMsg("\nfaSetChannelEnable: ERROR: Invalid channel (%d). Must be 0-%d\n\n", channel, FA125_MAX_ADC_CHANNELS-1,3,4,5,6); return ERROR; } feChip = (int)(channel/6); feChan = (int)(channel%6); FA125LOCK; chipMask = (vmeRead32(&fa125p[id]->fe[feChip].config2) & FA125_FE_CONFIG2_CH_MASK) & ~(1<fe[feChip].config2,chipMask); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Enable specific fADC125 Channels using three separate channel masks * @param id Slot number * @param cmask0 Enable channel mask for channels 0-23 * @param cmask1 Enable channel mask for channels 24-47 * @param cmask2 Enable channel mask for channels 48-71 * @return OK if successful, otherwise ERROR. */ int fa125SetChannelEnableMask(int id, unsigned int cmask0, unsigned int cmask1, unsigned int cmask2) { int ichip=0; unsigned int chipMask=0; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SetChannelEnableMask: ERROR : FA125 in slot %d is not initialized \n\n", id,0,0,0,0,0); return(ERROR); } if((cmask0 > 0xFFFFFF) || (cmask1 > 0xFFFFFF) || (cmask2 > 0xFFFFFF)) { logMsg("\nfa125SetChannelEnableMask: ERROR : Invalid channel mask(s) (0x%08x, 0x%08x, 0x%08x).\n", cmask0,cmask1,cmask2,0,0,0); logMsg(" : Each mask must be less than 24 bits.\n\n", 0,0,0,0,0,0); return(ERROR); } cmask0 = (~cmask0) & 0xFFFFFF; cmask1 = (~cmask1) & 0xFFFFFF; cmask2 = (~cmask2) & 0xFFFFFF; FA125LOCK; for(ichip=0; ichip<4; ichip++) { chipMask = (cmask0>>(ichip*6)) & FA125_FE_CONFIG2_CH_MASK; vmeWrite32(&fa125p[id]->fe[ichip].config2,chipMask); } for(ichip=4; ichip<8; ichip++) { chipMask = (cmask1>>((ichip-4)*6)) & FA125_FE_CONFIG2_CH_MASK; vmeWrite32(&fa125p[id]->fe[ichip].config2,chipMask); } for(ichip=8; ichip<12; ichip++) { chipMask = (cmask2>>((ichip-8)*6)) & FA125_FE_CONFIG2_CH_MASK; vmeWrite32(&fa125p[id]->fe[ichip].config2,chipMask); } FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Set a common readout threshold for all fADC125 Channels. * @param id Slot number * @param tvalue Threshold Value * @return OK if successful, otherwise ERROR. */ int fa125SetCommonThreshold(int id, unsigned short tvalue) { int ii,rval=OK; for(ii=0;iife[chan/6].threshold[chan%6]) & FA125_FE_THRESHOLD_MASK; FA125UNLOCK; return rval; } /** * @ingroup Status * @brief Print to standarad out the set readout threshold for all fADC125 Channels in the specified module. * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125PrintThreshold(int id) { int ii; unsigned short tval[FA125_MAX_ADC_CHANNELS]; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125PrintThreshold: ERROR : FA125 in slot %d is not initialized \n\n",id,0,0,0,0,0); return(ERROR); } FA125LOCK; for(ii=0;iife[ii/6].threshold[ii%6]); } FA125UNLOCK; printf(" Threshold Settings for FA125 in slot %d:",id); for(ii=0;ii21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if ((chan<0)||(chan>2)) { printf("\n%s: ERROR: Invalid Channel %d\n\n",__FUNCTION__,chan); return ERROR; } rval = fa125SetLTC2620(id,DAC_CHAN_PULSER[chan],dacData); return rval; } /** * @ingroup Status * @brief Print the temperature of the main board and mezzanine to standard out. * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125PrintTemps(int id) { double temp1=0, temp2=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } FA125LOCK; temp1 = 0.0625*((int) vmeRead32(&fa125p[id]->main.temperature[0])); temp2 = 0.0625*((int) vmeRead32(&fa125p[id]->main.temperature[1])); FA125UNLOCK; printf("%s: Main board temperature: %5.2lf \tMezzanine board temperature: %5.2lf\n", __FUNCTION__, temp1, temp2); return OK; } /** * @ingroup Config * @brief Set the clock source for the specified fADC125 * @param id Slot number * @param clksrc Defines Clock Source * 0 P2 Clock * 1 VXS (P0) * 2 Internal 125MHz Clock * @return OK if successful, otherwise ERROR. */ int fa125SetClockSource(int id, int clksrc) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(clksrc>2) { printf("\n%s: ERROR: Invalid Clock Source specified (%d)\n\n", __FUNCTION__,clksrc); return ERROR; } switch(clksrc) { case 0: /* P2 Clock */ clksrc = FA125_CLOCK_P2; break; case 1: /* VXS (P0) Clock */ clksrc = FA125_CLOCK_P0; break; case 2: /* Internal Clock */ default: clksrc = FA125_CLOCK_INTERNAL; break; } FA125LOCK; vmeWrite32(&fa125p[id]->main.clock, clksrc); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Set the trigger source for the specified fADC125 * @param id Slot number * @param trigsrc Defines Trigger Source * 0 P0 (VXS) * 1 Software (VME) * 2 Internal Sum * 3 P2 * @return OK if successful, otherwise ERROR. */ int fa125SetTriggerSource(int id, int trigsrc) { unsigned int regset=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if((trigsrc<0) || (trigsrc>3)) { printf("\n%s: ERROR: Invalid Trigger Source specified (%d)\n\n", __FUNCTION__,trigsrc); return ERROR; } switch(trigsrc) { case 1: /* Software */ regset = FA125_TRIGSRC_TRIGGER_SOFTWARE; break; case 2: /* Internal Sum */ regset = FA125_TRIGSRC_TRIGGER_INTERNAL_SUM; break; case 3: /* P2 */ regset = FA125_TRIGSRC_TRIGGER_P2; break; case 0: /* P0 */ default: regset = FA125_TRIGSRC_TRIGGER_P0; break; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.trigsrc, regset); FA125UNLOCK; return OK; } /** * @ingroup Status * @brief Returns the trigger source for the specified fADC125 * @param id Slot number * @return * - 0 P0 (VXS) * - 1 Software * - 2 Internal Sum * - 3 P2 * - ERROR otherwise */ int fa125GetTriggerSource(int id) { int rval=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } FA125LOCK; rval = vmeRead32(&fa125p[id]->proc.trigsrc); FA125UNLOCK; return rval; } /** * @ingroup Config * @brief Set the Sync Reset source for the specified fADC125 * @param id Slot number * @param srsrc Sync Reset source * - 0: Software (VME) * - 1: P0 (VXS) * @return OK if successful, otherwise ERROR. */ int fa125SetSyncResetSource(int id, int srsrc) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if((srsrc<0) || (srsrc>1)) { printf("\n%s: ERROR: Invalid SyncReset Source specified (%d)\n\n", __FUNCTION__,srsrc); return ERROR; } switch(srsrc) { case 1: /* VME (software) */ srsrc = FA125_PROC_CTRL2_SYNCRESET_VME; break; case 0: /* VXS (P0) */ default: srsrc = FA125_PROC_CTRL2_SYNCRESET_P0; break; } FA125LOCK; /* Set source */ vmeWrite32(&fa125p[id]->proc.ctrl2, (vmeRead32(&fa125p[id]->proc.ctrl2) & ~FA125_PROC_CTRL2_SYNCRESET_SOURCE_MASK) | srsrc); /* Enable */ vmeWrite32(&fa125p[id]->fe[0].test, (vmeRead32(&fa125p[id]->fe[0].test) & ~FA125_FE_TEST_SYNCRESET_ENABLE) | FA125_FE_TEST_SYNCRESET_ENABLE); FA125UNLOCK; return OK; } /** * @ingroup Readout * @brief Poll the specified fADC125's busy status. * @param id Slot number * @returns Busy status * - 0: Not Busy * - 1: Busy * - ERROR: otherwise */ int fa125Poll(int id) { int res; int rval=0; static int nzero=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; #ifdef VXWORKS res = vxMemProbe((char *) &(fa125p[id]->proc.csr),VX_READ,4,(char *)&rval); #else res = vmeMemProbe((char *) &(fa125p[id]->proc.csr),4,(char *)&rval); #ifdef DOBYTESWAP rval = LSWAP(rval); #endif //DOBYTESWAP #endif FA125UNLOCK; /* Sometimes get 0xffffffff. This is accompanied with a bus error. */ if(res==ERROR) { #define SHOWBERR #ifndef VXWORKS #ifdef SHOWBERR vmeClearException(1); #else vmeClearException(0); #endif #endif berr_count++; rval=0; /* logMsg("%s: BERR nzero = %6d\n",__FUNCTION__,nzero,3,4,5,6); */ return 0; } if(rval&FA125_PROC_CSR_BUSY) { /* logMsg("%s: poll = 1, nzero = %6d\n",__FUNCTION__,nzero,3,4,5,6); */ nzero=0; return 1; } else { nzero++; return 0; } } /** * @ingroup Readout * @brief Return the Bus Error count that occurred while checking the busy status * @return Bus Error count * @sa fa125Poll */ unsigned int fa125GetBerrCount() { return berr_count; } /** * @ingroup Deprec * @brief Clear used with serial acquisition buffers. Deprecated as this is no longer the way to readout data from the module. * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125Clear(int id) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.csr, FA125_PROC_CSR_CLEAR); vmeWrite32(&fa125p[id]->proc.csr, 0); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Enable buffers and FIFOs for data acquisition. * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125Enable(int id) { int ife=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; for(ife=0; ife<12; ife++) { vmeWrite32(&fa125p[id]->fe[ife].test, (vmeRead32(&fa125p[id]->fe[ife].test) & ~FA125_FE_TEST_COLLECT_ON) | FA125_FE_TEST_COLLECT_ON); } FA125UNLOCK; printf("%s(%2d): ENABLED\n",__FUNCTION__,id); return OK; } /** * @ingroup Config * @brief Disable buffers and FIFOs for data acquisition. * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125Disable(int id) { int ife=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; for(ife=0; ife<12; ife++) { vmeWrite32(&fa125p[id]->fe[ife].test, (vmeRead32(&fa125p[id]->fe[ife].test) & ~FA125_FE_TEST_COLLECT_ON)); } FA125UNLOCK; printf("%s(%2d): DISABLED\n",__FUNCTION__,id); return OK; } /** * @ingroup Config * @brief Perform the selected Reset to a specific fADC125 * @param id Slot number * @param reset Type of reset to perform * - 0: Soft Reset - Reset of all state machines and FIFOs. Register values will remain. * - 1: Hard Reset - Soft reset + reset of all register values. * @return OK if successful, otherwise ERROR. */ int fa125Reset(int id, int reset) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; switch(reset) { case 0: vmeWrite32(&fa125p[id]->main.blockCSR, FA125_BLOCKCSR_PULSE_SOFT_RESET); vmeWrite32(&fa125p[id]->main.blockCSR, FA125_BLOCKCSR_PULSE_SOFT_RESET); vmeWrite32(&fa125p[id]->main.blockCSR, FA125_BLOCKCSR_PULSE_SOFT_RESET); break; case 1: vmeWrite32(&fa125p[id]->main.blockCSR, FA125_BLOCKCSR_PULSE_HARD_RESET); break; default: vmeWrite32(&fa125p[id]->main.blockCSR, FA125_BLOCKCSR_PULSE_SOFT_RESET); } vmeWrite32(&fa125p[id]->main.blockCSR, 0); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Reset all counters (trigger count, clock count, sync reset count, trig2 count) * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125ResetCounters(int id) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.trig_count,FA125_PROC_TRIGCOUNT_RESET); vmeWrite32(&fa125p[id]->proc.clock125_count,FA125_PROC_CLOCK125COUNT_RESET); vmeWrite32(&fa125p[id]->proc.sync_count,FA125_PROC_SYNCCOUNT_RESET); vmeWrite32(&fa125p[id]->proc.trig2_count,FA125_PROC_TRIG2COUNT_RESET); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Returns the token to the first module * This routine only has an effect on the first module of the Multiblock setup. * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125ResetToken(int id) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->main.blockCSR, FA125_BLOCKCSR_TAKE_TOKEN); vmeWrite32(&fa125p[id]->main.blockCSR, 0); FA125UNLOCK; return OK; } /** * @ingroup Status * @brief Return the slot mask of modules with the token. * @return Token Slot Mask if successful, otherwise ERROR. */ int fa125GetTokenMask() { unsigned int rmask=0; int ifa=0, id=0, rval=0; for(ifa=0; ifamain.blockCSR) & FA125_BLOCKCSR_HAS_TOKEN)>>4; rmask |= (rval<21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.blocklevel, blocklevel); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Set the number of un-processed triggers in the trigger buffer before * the module goes BUSY * @param id Slot number * @param ntrig Number of Triggers * @return OK if successful, otherwise ERROR. */ int fa125SetNTrigBusy(int id, int ntrig) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n", __FUNCTION__,id); return ERROR; } if((ntrig<0) || (ntrig>0xff)) { printf("\n%s: ERROR: Invalid ntrig (%d).\n\n", __FUNCTION__,ntrig); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.ntrig_busy, ntrig); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Set the number of un-processed triggers in the trigger buffer before * the module goes BUSY, for all initialized modules. * @param ntrig Number of Triggers * @return OK if successful, otherwise ERROR. */ int fa125GSetNTrigBusy(int ntrig) { int id=0; if((ntrig<0) || (ntrig>0xff)) { printf("\n%s: ERROR: Invalid ntrig (%d).\n\n", __FUNCTION__,ntrig); return ERROR; } FA125LOCK; for(id=0; idproc.ntrig_busy, ntrig); FA125UNLOCK; return OK; } /** * @ingroup Status * @brief Get the number of un-processed triggers in the trigger buffer before * the module goes BUSY * @param id Slot number * @return Number of Triggers if successful, otherwise ERROR. */ int fa125GetNTrigBusy(int id) { int rval=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n", __FUNCTION__,id); return ERROR; } FA125LOCK; rval = vmeRead32(&fa125p[id]->proc.ntrig_busy) & FA125_NTRIG_BUSY_MASK; FA125UNLOCK; return rval; } /** * @ingroup Readout * @brief Initiate a software trigger for a specific fADC125 module. * @param id Slot number * @return OK if successful, otherwise ERROR. */ int fa125SoftTrigger(int id) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.softtrig, 1); vmeWrite32(&fa125p[id]->proc.softtrig, 0); FA125UNLOCK; return OK; } /** * @ingroup PulserConfig * @brief Set the delay between the output pulse and f1TDC trigger * @param id Slot number * @param delay The number of samples of delay between the output pulse and the trigger * @return OK if successful, otherwise ERROR. */ int fa125SetPulserTriggerDelay(int id, int delay) { if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SetPulserTriggerDelay: ERROR : ADC in slot %d is not initialized \n\n",id,0,0,0,0,0); return ERROR; } if(delay>FA125_PROC_PULSER_TRIG_DELAY_MASK) { logMsg("\nfa125SetPulserTriggerDelay: ERROR: delay (%d) out of range. Must be <= %d\n\n", delay,FA125_PROC_PULSER_TRIG_DELAY_MASK,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.pulser_trig_delay, (vmeRead32(&fa125p[id]->proc.pulser_trig_delay) &~ FA125_PROC_PULSER_TRIG_DELAY_MASK) | delay); FA125UNLOCK; return OK; } /** * @ingroup PulserConfig * @brief Set the width of the output pulse * @param id Slot number * @param width The number of samples that make up the width of the output pulse * @return OK if successful, otherwise ERROR. */ int fa125SetPulserWidth(int id, int width) { if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SetPulserWidth: ERROR : ADC in slot %d is not initialized \n\n",id,0,0,0,0,0); return ERROR; } if(width>(FA125_PROC_PULSER_WIDTH_MASK>>12)) { logMsg("\nfa125SetPulserWidth: ERROR: width (%d) out of range. Must be <= %d\n\n", width,(FA125_PROC_PULSER_WIDTH_MASK>>12),3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.pulser_trig_delay, (vmeRead32(&fa125p[id]->proc.pulser_trig_delay) &~ FA125_PROC_PULSER_WIDTH_MASK) | (width<<12)); FA125UNLOCK; return OK; } /** * @ingroup PulserConfig * @brief Trigger the pulser * * @param id * - Slot Number * @param output * - 0: Pulse out only * - 1: fa125 Trigger only * - 2: Both pulse and trigger * @return OK if successful, otherwise ERROR. */ int fa125SoftPulser(int id, int output) { unsigned int selection=0; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SoftPulser: ERROR : ADC in slot %d is not initialized \n\n",id,0,0,0,0,0); return ERROR; } switch(output) { case 0: /* Just the pulse out */ selection = FA125_PROC_PULSER_CONTROL_PULSE; break; case 1: /* Just the trigger out */ selection = FA125_PROC_PULSER_CONTROL_DELAYED_TRIGGER; break; case 2: /* Pulse and trigger out */ selection = FA125_PROC_PULSER_CONTROL_PULSE | FA125_PROC_PULSER_CONTROL_DELAYED_TRIGGER; break; default: logMsg("\nfa125SoftPulser: ERROR: Invalid output option (%d)\n\n", output,2,3,4,5,6); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->proc.pulser_control, selection); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Setup fADC125 Progammable Pulse Generator * * @param id Slot number * @param fe_chip Front End FPGA to write to * @param sdata Array of sample data to be programmed * @param nsamples Number of samples contained in sdata * * @sa fa125PPGEnable fa125PPGDisable * @return OK if successful, otherwise ERROR. */ int fa125SetPPG(int id, int fe_chip, unsigned short *sdata, int nsamples) { int ii; unsigned short rval; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125SetPPG: ERROR : ADC in slot %d is not initialized \n\n",id,0,0,0,0,0); return(ERROR); } if(sdata == NULL) { logMsg("\nfa125SetPPG: ERROR: Invalid Pointer to sample data\n\n",1,2,3,4,5,6); return(ERROR); } if((nsamples <= 0)||(nsamples>FA125_PPG_MAX_SAMPLES)) { logMsg("fa125SetPPG: WARN: Invalid nsamples (%d). Setting to %d\n", nsamples, FA125_PPG_MAX_SAMPLES,3,4,5,6); nsamples = FA125_PPG_MAX_SAMPLES; } FA125LOCK; for(ii=0;ii<(nsamples-2);ii++) { vmeWrite32(&fa125p[id]->fe[fe_chip].test_waveform, (sdata[ii]|FA125_FE_TEST_WAVEFORM_WRITE_PPG_DATA)); rval = vmeRead32(&fa125p[id]->fe[fe_chip].test_waveform)&FA125_FE_TEST_WAVEFORM_PPG_DATA_MASK; if( (rval) != sdata[ii]) logMsg("\nfaSetPPG(%d): ERROR: Write error (%d) %x != %x (ii=%d)\n\n", fe_chip,ii,rval, sdata[ii],ii,6); } /* Write the last two samples without the write flag */ vmeWrite32(&fa125p[id]->fe[fe_chip].test_waveform, (sdata[(nsamples-2)]&FA125_FE_TEST_WAVEFORM_PPG_DATA_MASK)); rval = vmeRead32(&fa125p[id]->fe[fe_chip].test_waveform)&FA125_FE_TEST_WAVEFORM_PPG_DATA_MASK; if(rval != sdata[(nsamples-2)]) logMsg("\nfaSetPPG(%d): ERROR: Write error (%d) %x != %x\n\n",fe_chip,nsamples-2, rval, sdata[nsamples-2],5,6); vmeWrite32(&fa125p[id]->fe[fe_chip].test_waveform, (sdata[(nsamples-1)]&FA125_FE_TEST_WAVEFORM_PPG_DATA_MASK)); rval = vmeRead32(&fa125p[id]->fe[fe_chip].test_waveform)&FA125_FE_TEST_WAVEFORM_PPG_DATA_MASK; if(rval != sdata[(nsamples-1)]) logMsg("\nfaSetPPG(%d): ERROR: Write error (%d) %x != %x\n\n",fe_chip,nsamples-1, rval, sdata[nsamples-1],5,6); FA125UNLOCK; return(OK); } /** * @ingroup Config * @brief Enable the programmable pulse generator * @param id Slot number * @sa fa125SetPPG fa125PPGDisable * @return OK if successful, otherwise ERROR. */ int fa125PPGEnable(int id) { if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125PPGEnable: ERROR : ADC in slot %d is not initialized \n\n",id,0,0,0,0,0); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->fe[0].config1, vmeRead32(&fa125p[id]->fe[0].config1) | FA125_FE_CONFIG1_PLAYBACK_ENABLE); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Disable the programmable pulse generator * @param id Slot number * @sa fa125SetPPG fa125PPGEnable * @return OK if successful, otherwise ERROR. */ int fa125PPGDisable(int id) { if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125PPGDisable: ERROR : ADC in slot %d is not initialized \n\n",id,0,0,0,0,0); return ERROR; } FA125LOCK; vmeWrite32(&fa125p[id]->fe[0].config1, vmeRead32(&fa125p[id]->fe[0].config1) & ~FA125_FE_CONFIG1_PLAYBACK_ENABLE); FA125UNLOCK; return OK; } /** * @ingroup Readout * @brief Return a Block Ready status * @param id Slot number * @return 1 if block is ready for readout, 0 if not, otherwise ERROR. */ int fa125Bready(int id) { int rval=0; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125Bready: ERROR : FA125 in slot %d is not initialized \n\n",id,0,0,0,0,0); return(ERROR); } FA125LOCK; rval = (vmeRead32(&fa125p[id]->main.blockCSR) & FA125_BLOCKCSR_BLOCK_READY)>>2; FA125UNLOCK; return rval; } /** * @ingroup Readout * @brief Return a Block Ready status mask for all initialized fADC125s * @return block ready mask, otherwise ERROR. */ unsigned int fa125GBready() { int ii, id, stat=0; unsigned int dmask=0; FA125LOCK; for(ii=0;iimain.blockCSR) & FA125_BLOCKCSR_BLOCK_READY)>>2; /* printf("%s(%2d): main.blockCSR = 0x%08x\n", */ /* __FUNCTION__,id, fa125p[id]->main.blockCSR); */ if(stat) dmask |= (1<0 will print the error flag to standard out. * @return Block Error flag. * @sa FA125_BLOCKERROR_FLAGS */ int fa125ReadBlockStatus(int pflag) { if(pflag) { if(fa125BlockError!=FA125_BLOCKERROR_NO_ERROR) { printf("\n%s: ERROR: %s\n", __FUNCTION__,fa125_blockerror_names[fa125BlockError]); } } return fa125BlockError; } /** * @ingroup Readout * @brief General Data readout routine * * @param id Slot number of module to read * @param data local memory address to place data * @param nwrds Max number of words to transfer * @param rflag Readout Flag *
 *              0 - programmed I/O from the specified board
 *              1 - DMA transfer using Universe/Tempe DMA Engine 
 *                    (DMA VME transfer Mode must be setup prior)
 *              2 - Multiblock DMA transfer (Multiblock must be enabled
 *                     and daisychain in place or SD being used)
 * 
* @return Number of words inserted into data if successful. Otherwise ERROR. */ int fa125ReadBlock(int id, volatile UINT32 *data, int nwrds, int rflag) { int ii, blknum; int stat, retVal, xferCount, rmode, async; int dCnt, berr=0; int dummy=0; volatile unsigned int *laddr; unsigned int bhead, ehead, val; unsigned int vmeAdr, csr; if(id==0) id=fa125ID[0]; if((id<=0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\nfa125ReadBlock: ERROR : FA125 in slot %d is not initialized\n\n",id,0,0,0,0,0); return(ERROR); } if(data==NULL) { logMsg("\nfa125ReadBlock: ERROR: Invalid Destination address\n\n",0,0,0,0,0,0); return(ERROR); } fa125BlockError=FA125_BLOCKERROR_NO_ERROR; if(nwrds <= 0) nwrds= (FA125_MAX_ADC_CHANNELS*FA125_MAX_DATA_PER_CHANNEL) + 8; rmode = rflag&0x0f; async = rflag&0x80; if(rmode >= 1) { /* Block Transfers */ /*Assume that the DMA programming is already setup. */ /* Don't Bother checking if there is valid data - that should be done prior to calling the read routine */ /* Check for 8 byte boundary for address - insert dummy word (Slot 0 FA125 Dummy DATA)*/ if((unsigned long) (data)&0x7) { #ifdef VXWORKS *data = FA125_DUMMY_DATA; #else *data = LSWAP(FA125_DUMMY_DATA); #endif dummy = 1; laddr = (data + 1); } else { dummy = 0; laddr = data; } FA125LOCK; if(rmode == 2) { /* Multiblock Mode */ if((vmeRead32(&fa125p[id]->main.ctrl1)&FA125_CTRL1_FIRST_BOARD)==0) { logMsg("\nfa125ReadBlock: ERROR: FA125 in slot %d is not First Board\n\n",id,0,0,0,0,0); FA125UNLOCK; return(ERROR); } vmeAdr = (unsigned int)((unsigned long)(FA125pmb) - fa125A32Offset); } else { vmeAdr = (unsigned int)((unsigned long)fa125pd[id] - fa125A32Offset); } #ifdef VXWORKS retVal = sysVmeDmaSend((UINT32)laddr, vmeAdr, (nwrds<<2), 0); #else retVal = vmeDmaSend((unsigned long)laddr, vmeAdr, (nwrds<<2)); #endif if(retVal != 0) { logMsg("\nfa125ReadBlock: ERROR in DMA transfer Initialization 0x%x\n\n",retVal,0,0,0,0,0); FA125UNLOCK; return(retVal); } if(async) { /* Asynchonous mode - return immediately - don't wait for done!! */ FA125UNLOCK; return(OK); } else { /* Wait until Done or Error */ #ifdef VXWORKS retVal = sysVmeDmaDone(10000,1); #else retVal = vmeDmaDone(); #endif } if(retVal > 0) { /* Check to see that Bus error was generated by FA125 */ if(rmode == 2) { csr = vmeRead32(&fa125p[fa125MaxSlot]->main.blockCSR); /* from Last FA125 */ stat = (csr)&FA125_BLOCKCSR_BERR_ASSERTED; /* from Last FA125 */ } else { csr = vmeRead32(&fa125p[id]->main.blockCSR); /* from Last FA125 */ stat = (csr)&FA125_BLOCKCSR_BERR_ASSERTED; /* from Last FA125 */ } if((retVal>0) && (stat)) { #ifdef VXWORKS xferCount = (nwrds - (retVal>>2) + dummy); /* Number of Longwords transfered */ #else xferCount = ((retVal>>2) + dummy); /* Number of Longwords transfered */ #endif FA125UNLOCK; return(xferCount); /* Return number of data words transfered */ } else { #ifdef VXWORKS xferCount = (nwrds - (retVal>>2) + dummy); /* Number of Longwords transfered */ #else xferCount = ((retVal>>2) + dummy); /* Number of Longwords transfered */ #endif logMsg("fa125ReadBlock: DMA transfer terminated by unknown BUS Error (csr=0x%x xferCount=%d id=%d)\n", csr,xferCount,id,0,0,0); FA125UNLOCK; fa125BlockError=FA125_BLOCKERROR_UNKNOWN_BUS_ERROR; return(xferCount); } } else if (retVal == 0) { /* Block Error finished without Bus Error */ #ifdef VXWORKS logMsg("fa125ReadBlock: WARN: DMA transfer terminated by word count 0x%x\n",nwrds,0,0,0,0,0); fa125BlockError=FA125_BLOCKERROR_TERM_ON_WORDCOUNT; #else logMsg("fa125ReadBlock: WARN: DMA transfer returned zero word count 0x%x\n",nwrds,0,0,0,0,0); fa125BlockError=FA125_BLOCKERROR_ZERO_WORD_COUNT; #endif FA125UNLOCK; return(nwrds); } else { /* Error in DMA */ #ifdef VXWORKS logMsg("\nfa125ReadBlock: ERROR: sysVmeDmaDone returned an Error\n\n",0,0,0,0,0,0); #else logMsg("\nfa125ReadBlock: ERROR: vmeDmaDone returned an Error\n\n",0,0,0,0,0,0); #endif FA125UNLOCK; fa125BlockError=FA125_BLOCKERROR_DMADONE_ERROR; return(retVal>>2); } } else { /*Programmed IO */ /* Check if Bus Errors are enabled. If so then disable for Prog I/O reading */ FA125LOCK; berr = vmeRead32(&fa125p[id]->main.ctrl1)&FA125_CTRL1_ENABLE_BERR; if(berr) vmeWrite32(&fa125p[id]->main.ctrl1, vmeRead32(&fa125p[id]->main.ctrl1) & ~FA125_CTRL1_ENABLE_BERR); dCnt = 0; /* Read Block Header - should be first word */ bhead = fa125pd[id]->data; #ifndef VXWORKS bhead = LSWAP(bhead); #endif if((bhead&FA125_DATA_TYPE_DEFINE)&&((bhead&FA125_DATA_TYPE_MASK) == FA125_DATA_BLOCK_HEADER)) { blknum = bhead&FA125_DATA_BLKNUM_MASK; ehead = fa125pd[id]->data; #ifndef VXWORKS ehead = LSWAP(ehead); #endif #ifdef VXWORKS data[dCnt] = bhead; #else data[dCnt] = LSWAP(bhead); /* Swap back to little-endian */ #endif dCnt++; #ifdef VXWORKS data[dCnt] = ehead; #else data[dCnt] = LSWAP(ehead); /* Swap back to little-endian */ #endif dCnt++; } else { /* We got bad data - Check if there is any data at all */ if( (vmeRead32(&fa125p[id]->proc.ev_count) & FA125_PROC_EVCOUNT_MASK) == 0) { logMsg("fa125ReadBlock: FIFO Empty (0x%08x)\n",bhead,0,0,0,0,0); FA125UNLOCK; return(0); } else { logMsg("\nfa125ReadBlock: ERROR: Invalid Header Word 0x%08x\n\n",bhead,0,0,0,0,0); FA125UNLOCK; return(ERROR); } } ii=0; while(iidata; data[ii+2] = val; #ifndef VXWORKS val = LSWAP(val); #endif if( (val&FA125_DATA_TYPE_DEFINE) && ((val&FA125_DATA_TYPE_MASK) == FA125_DATA_BLOCK_TRAILER) ) break; ii++; } ii++; dCnt += ii; if(berr) vmeWrite32(&fa125p[id]->main.ctrl1, vmeRead32(&fa125p[id]->main.ctrl1) | FA125_CTRL1_ENABLE_BERR); FA125UNLOCK; return(dCnt); } FA125UNLOCK; return(OK); } struct data_struct { unsigned int new_type; unsigned int type; unsigned int slot_id_hd; unsigned int mod_id_hd; unsigned int slot_id_tr; unsigned int n_evts; unsigned int blk_num; unsigned int n_words; unsigned int evt_num_1; unsigned int time_now; unsigned int time_1; unsigned int time_2; unsigned int chan; unsigned int width; unsigned int npk; unsigned int le_time; unsigned int time_quality; unsigned int overflow_cnt; unsigned int pedestal; unsigned int fm_amplitude; unsigned int peak_amplitude; unsigned int peak_time; unsigned int valid_1; unsigned int adc_1; unsigned int valid_2; unsigned int adc_2; unsigned int over; unsigned int adc_sum; unsigned int pulse_num; unsigned int thres_bin; unsigned int quality; unsigned int integral; unsigned int time; unsigned int chan_a; unsigned int source_a; unsigned int chan_b; unsigned int source_b; unsigned int group; unsigned int time_coarse; unsigned int time_fine; unsigned int vmin; unsigned int vpeak; unsigned int scaler[18];/* data stream scalers */ }; volatile struct data_struct fadc_data; /** * @ingroup Status * @brief Decode a data word from an fADC125 and print to standard out. * @param data 32bit fADC125 data word */ void fa125DecodeData(unsigned int data) { /* for new data format - 10/23/13 - EJ */ static unsigned int type_last = 15;/* initialize to type FILLER WORD */ static unsigned int time_last = 0; static unsigned int scaler_index = 0; static unsigned int num_scalers = 1; static unsigned int slot_id_ev_hd = 0; static unsigned int slot_id_dnv = 0; static unsigned int slot_id_fill = 0; static int nsamples=0; static int ipk=0; /* static int goto_raw=0; */ int i_print =1; if( scaler_index )/* scaler data word */ { fadc_data.type = 16;/* scaler data words as type 16 */ fadc_data.new_type = 0; if( scaler_index < num_scalers ) { fadc_data.scaler[scaler_index - 1] = data; if( i_print ) printf("%8X - SCALER(%d) = %d\n", data, (scaler_index - 1), data); scaler_index++; } else/* last scaler word */ { fadc_data.scaler[scaler_index - 1] = data; if( i_print ) printf("%8X - SCALER(%d) = %d\n", data, (scaler_index - 1), data); scaler_index = 0; num_scalers = 1; } } else/* non-scaler word */ { if( data & 0x80000000 )/* data type defining word */ { fadc_data.new_type = 1; fadc_data.type = (data & 0x78000000) >> 27; } else/* data type continuation word */ { fadc_data.new_type = 0; fadc_data.type = type_last; } switch( fadc_data.type ) { case 0:/* BLOCK HEADER */ fadc_data.slot_id_hd = (data & 0x7C00000) >> 22; fadc_data.mod_id_hd = (data & 0x3C0000) >> 18; fadc_data.n_evts = (data & 0x000FF); fadc_data.blk_num = (data & 0x7F00) >> 8; if( i_print ) printf("%8X - BLOCK HEADER - slot = %d id = %d n_evts = %d n_blk = %d\n", data, fadc_data.slot_id_hd, fadc_data.mod_id_hd, fadc_data.n_evts, fadc_data.blk_num); break; case 1:/* BLOCK TRAILER */ fadc_data.slot_id_tr = (data & 0x7C00000) >> 22; fadc_data.n_words = (data & 0x3FFFFF); if( i_print ) printf("%8X - BLOCK TRAILER - slot = %d n_words = %d\n", data, fadc_data.slot_id_tr, fadc_data.n_words); break; case 2:/* EVENT HEADER */ if( fadc_data.new_type ) { slot_id_ev_hd = (data & 0x7C00000) >> 22; fadc_data.evt_num_1 = (data & 0x03FFFFF); if( i_print ) printf("%8X - EVENT HEADER - slot = %d evt_num = %d\n", data, slot_id_ev_hd, fadc_data.evt_num_1); } break; case 3:/* TRIGGER TIME */ if( fadc_data.new_type ) { fadc_data.time_1 = (data & 0xFFFFFF); if( i_print ) printf("%8X - TRIGGER TIME 1 - time = 0x%08x\n", data, fadc_data.time_1); fadc_data.time_now = 1; time_last = 1; } else { if( time_last == 1 ) { fadc_data.time_2 = (data & 0xFFFFFF); if( i_print ) printf("%8X - TRIGGER TIME 2 - time = 0x%08x\n", data, fadc_data.time_2); fadc_data.time_now = 2; } else if( i_print ) printf("%8X - TRIGGER TIME - (ERROR)\n", data); time_last = fadc_data.time_now; } break; case 4:/* WINDOW RAW DATA */ if( fadc_data.new_type ) { fadc_data.chan = (data & 0x7F00000) >> 20; fadc_data.width = (data & 0xFFF); if( i_print ) printf("%8X - WINDOW RAW DATA - chan = %2d width = %d\n", data, fadc_data.chan, fadc_data.width); nsamples=0; } else { fadc_data.valid_1 = 1; fadc_data.valid_2 = 1; fadc_data.adc_1 = (data & 0x1FFF0000) >> 16; if( data & 0x20000000 ) fadc_data.valid_1 = 0; fadc_data.adc_2 = (data & 0x1FFF); if( data & 0x2000 ) fadc_data.valid_2 = 0; if( i_print ) printf("%8X - RAW SAMPLES (%3d) - valid = %d adc = %4d (%03X) valid = %d adc = %4d (%03X)\n", data, nsamples,fadc_data.valid_1, fadc_data.adc_1, fadc_data.adc_1, fadc_data.valid_2, fadc_data.adc_2, fadc_data.adc_2); nsamples += 2; } break; case 5:/* PULSE DATA, CDC */ if( fadc_data.new_type ) { fadc_data.chan = (data & 0x7F00000) >> 20; fadc_data.npk = (data & 0xF8000)>>15; fadc_data.le_time = (data & 0x7FF0)>>4; fadc_data.time_quality = (data & (1<<3))>>3; fadc_data.overflow_cnt = (data & 0x7); if( i_print ) printf("%8X - PULSE DATA (CDC IT) - chan = %2d LE time = %d Q = %d OVF = %d\n", data, fadc_data.chan, fadc_data.le_time, fadc_data.time_quality, fadc_data.overflow_cnt); } else { fadc_data.pedestal = (data & 0x7F800000)>>23; fadc_data.integral = (data & 0x007FFE00)>>9; fadc_data.fm_amplitude = (data & 0x000001FF); if( i_print ) printf("%8X - PULSE DATA (CDC IT) - ped = %d integral = %d firstmax ampl = %d\n", data, fadc_data.pedestal, fadc_data.integral, fadc_data.fm_amplitude); } break; case 6:/* PULSE DATA, FDC - Integral and Time */ if( fadc_data.new_type ) { fadc_data.chan = (data & 0x7F00000) >> 20; fadc_data.npk = (data & 0xF8000)>>15; fadc_data.le_time = (data & 0x7FF0)>>4; fadc_data.time_quality = (data & (1<<3))>>3; fadc_data.overflow_cnt = (data & 0x7); ipk = 0; if( i_print ) printf("%8X - PULSE DATA (FDC IT) - chan = %2d NPK = %d LE time = %d Q = %d OVF = %d\n", data, fadc_data.chan, fadc_data.npk, fadc_data.le_time, fadc_data.time_quality, fadc_data.overflow_cnt); } else { ipk++; fadc_data.pedestal = (data & 0x7F800000)>>23; fadc_data.integral = (data & 0x007FFE00)>>9; fadc_data.fm_amplitude = (data & 0x000001FF); if( i_print ) printf("%8X - PULSE DATA (FDC IT) %d - ped = %d integral = %d firstmax ampl = %d\n", data, ipk, fadc_data.pedestal, fadc_data.integral, fadc_data.fm_amplitude); } break; case 9:/* PULSE DATA, FDC - Peak Ampl and Time */ if( fadc_data.new_type ) { fadc_data.chan = (data & 0x7F00000) >> 20; fadc_data.le_time = (data & 0x7FF0)>>4; fadc_data.time_quality = (data & (1<<3))>>3; fadc_data.overflow_cnt = (data & 0x7); ipk = 0; if( i_print ) printf("%8X - PULSE DATA (FDC AT) - chan = %2d NPK = %d LE time = %d Q = %d OVF = %d\n", data, fadc_data.chan, fadc_data.npk, fadc_data.le_time, fadc_data.time_quality, fadc_data.overflow_cnt); } else { ipk++; fadc_data.peak_amplitude = (data & 0x7ff80000)>>19; fadc_data.peak_time = (data & 0x0007f800)>>11; fadc_data.pedestal = (data & 0x000007ff); if( i_print ) printf("%8X - PULSE DATA (FDC AT) %d - Ampl = %d Time = %d Pedestal = %d\n", data, ipk, fadc_data.peak_amplitude, fadc_data.peak_time, fadc_data.pedestal); } break; case 7: case 8: case 10: case 11: case 12:/* UNDEFINED TYPE */ if( i_print ) printf("%8X - UNDEFINED TYPE = %d\n", data, fadc_data.type); break; case 13:/* END OF EVENT */ if( i_print ) printf("%8X - END OF EVENT = %d\n", data, fadc_data.type); break; case 14:/* DATA NOT VALID (no data available) */ slot_id_dnv = (data & 0x7C00000) >> 22; if( i_print ) printf("%8X - DATA NOT VALID = %d slot = %d\n", data, fadc_data.type, slot_id_dnv); break; case 15:/* FILLER WORD */ slot_id_fill = (data & 0x7C00000) >> 22; if( i_print ) printf("%8X - FILLER WORD = %d slot = %d\n", data, fadc_data.type, slot_id_fill); break; } type_last = fadc_data.type; /* save type of current data word */ } } /************************************************************ * fa125 Firmware Updating Routines ************************************************************/ #define MCS_MAX_SIZE (FA125_FIRMWARE_MAX_PAGES*FA125_FIRMWARE_MAX_BYTE_PER_PAGE) static unsigned int MCS_dataSize = 0; /* Size of the array holding the firmware */ static unsigned int MCS_pageSize = 0; /* Number of pages read from MCS file */ static unsigned char MCS_DATA[FA125_FIRMWARE_MAX_PAGES][FA125_FIRMWARE_MAX_BYTE_PER_PAGE]; /* The array holding the firmware */ static int MCS_loaded = 0; /* 1(0) if firmware loaded (not loaded) */ static unsigned char tmp_pageData[FA125_FIRMWARE_MAX_BYTE_PER_PAGE]; static int fa125FirmwareDebug=0; static int fa125FirmwareErrorFlags[(FA125_MAX_BOARDS+1)]; /* Firmware Updating Error Flags for each slot */ enum ifpgatype {MAIN, FE, PROC, NFPGATYPE}; struct fpga_fw_info { char name[5]; unsigned int size; unsigned int location; unsigned int page_location; unsigned int page_byte_location; }; struct firmware_stats { struct timespec erase_time; unsigned int nblocks_erased; struct timespec buffer_write_time; unsigned int nbuffers_written; struct timespec buffer_push_time; unsigned int nbuffers_pushed; struct timespec main_page_read_time; unsigned int npages_read; }; static struct timespec tsSubtract(struct timespec time1, struct timespec time2) { /* Local variables. */ struct timespec result; /* Subtract the second time from the first. */ if ((time1.tv_sec < time2.tv_sec) || ((time1.tv_sec == time2.tv_sec) && (time1.tv_nsec <= time2.tv_nsec))) { /* TIME1 <= TIME2? */ result.tv_sec = result.tv_nsec = 0; } else { /* TIME1 > TIME2 */ result.tv_sec = time1.tv_sec - time2.tv_sec; if (time1.tv_nsec < time2.tv_nsec) { result.tv_nsec = time1.tv_nsec + 1000000000L - time2.tv_nsec; result.tv_sec--; /* Borrow a second. */ } else { result.tv_nsec = time1.tv_nsec - time2.tv_nsec; } } return (result); } static struct timespec tsAdd(struct timespec time1, struct timespec time2) { /* Local variables. */ struct timespec result ; /* Add the two times together. */ result.tv_sec = time1.tv_sec + time2.tv_sec ; result.tv_nsec = time1.tv_nsec + time2.tv_nsec ; if (result.tv_nsec >= 1000000000L) { /* Carry? */ result.tv_sec++ ; result.tv_nsec = result.tv_nsec - 1000000000L ; } return (result) ; } struct firmware_stats fa125FWstats; struct fpga_fw_info sfpga[NFPGATYPE] = { {"MAIN", 0x45480, 0x0, 0, 0}, {"FE" , 0xC435A, 0x754E0, 0, 0}, {"PROC", 0x1659FA, 0x1E1B90, 0, 0} }; /* Static Firmware Updating routine prototypes */ static int fa125FirmwareWaitForReady(int id, int nwait, int *rwait); static int fa125FirmwareBlockErase(int id, int iblock, int stayon, int waitForDone); static int fa125FirmwareWriteToBuffer(int id, int ipage); static int fa125FirmwarePushBufferToMain(int id, int ipage, int waitForDone); static int fa125FirmwareWaitForPushBufferToMain(int id, int ipage); static int fa125FirmwareReadMainPage(int id, int ipage, int stayon); static int fa125FirmwareReadBuffer(int id); static int fa125FirmwareVerifyFull(int id); static int fa125FirmwareVerifyPage(int ipage); static int fa125FirmwareVerifyErasedPage(int ipage); static int hex2num(char c); /** * @ingroup FWUpdate * @brief Set the debugging flags for diagnosing firmware updating problems. * @param debug Debug bit flags * @sa FA125_FIRMWARE_DEBUG_FLAGS */ void fa125FirmwareSetDebug(unsigned int debug) { fa125FirmwareDebug=debug; } static int fa125FirmwareWaitForReady(int id, int nwait, int *rwait) { int iwait=0, rval=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } for(iwait=0; iwaitmain.configCSR) & FA125_CONFIGCSR_BUSY; if(rval==FA125_CONFIGCSR_BUSY) break; } *rwait = iwait; if(iwait==nwait) { printf("\n%s: ERROR: Operation still in progress after %d tries.\n\n", __FUNCTION__,iwait); return ERROR; } return OK; } static int fa125FirmwareBlockErase(int id, int iblock, int stayon, int waitForDone) { #ifdef DOSTAYON int rwait=0; #endif if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; /* Configuration csr for block erase */ vmeWrite32(&fa125p[id]->main.configCSR, FA125_CONFIGCSR_PROG_ENABLE | (FA125_OPCODE_ERASE<<24)); /* Erase blocks using top 10 bits of page address [30... 21] 0-1023 */ vmeWrite32(&fa125p[id]->main.configAdrData, (iblock<<21)); vmeWrite32(&fa125p[id]->main.configAdrData, FA125_CONFIGADRDATA_EXEC | (iblock<<21)); vmeWrite32(&fa125p[id]->main.configAdrData, (iblock<<21)); if(waitForDone==0) { FA125UNLOCK; return OK; } taskDelay(6); #ifdef DOSTAYON /* Pull Execute low before asserting new configuration type */ if(stayon==0) { taskDelay(1); vmeWrite32(&fa125p[id]->main.configAdrData, 0); if(fa125FirmwareWaitForReady(id,100,&rwait)!=OK) { printf("\n%s: ERROR: Pull down execute timeout (rwait = %d).\n\n", __FUNCTION__, rwait); FA125UNLOCK; return ERROR; } if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_WAIT_FOR_READY) { printf("%s: Pull Execute low. wait ticks = %d\n", __FUNCTION__,rwait); } } #endif FA125UNLOCK; return OK; } static int fa125FirmwareWriteToBuffer(int id, int ipage) { int ibadr=0; unsigned char data=0; int rwait=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } if(ipage>(FA125_FIRMWARE_MAX_PAGES-1)) { printf("\n%s: ERROR: ipage > Maximum page count (%d > %d)\n\n", __FUNCTION__, ipage, (FA125_FIRMWARE_MAX_PAGES-1)); } if(MCS_loaded==0) { printf("\n%s: ERROR: MCS file not loaded into memory\n\n", __FUNCTION__); return ERROR; } FA125LOCK; /* Configuration csr for buffer write */ vmeWrite32(&fa125p[id]->main.configCSR, FA125_CONFIGCSR_PROG_ENABLE | (FA125_OPCODE_BUFFER_WRITE<<24)); /* Write configuration data byte using byte addresses 0-527 */ for(ibadr=0; ibadr<528; ibadr++) { data = MCS_DATA[ipage][ibadr]; vmeWrite32(&fa125p[id]->main.configAdrData, (ibadr<<8) | data); vmeWrite32(&fa125p[id]->main.configAdrData, FA125_CONFIGADRDATA_EXEC | (ibadr<<8) | data); vmeWrite32(&fa125p[id]->main.configAdrData, (ibadr<<8) | data); if(fa125FirmwareWaitForReady(id,1000000,&rwait)!=OK) { printf("\n%s: ERROR: Buffer Write timeout (byte address = %d, page = %d) (rwait = %d).\n\n", __FUNCTION__, ibadr,ipage, rwait); vmeWrite32(&fa125p[id]->main.configAdrData, 0); FA125UNLOCK; return ERROR; } } FA125UNLOCK; return OK; } static int fa125FirmwarePushBufferToMain(int id, int ipage, int waitForDone) { if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } if(ipage>(FA125_FIRMWARE_MAX_PAGES-1)) { printf("\n%s: ERROR: ipage > Maximum page count (%d > %d)\n\n", __FUNCTION__, ipage, (FA125_FIRMWARE_MAX_PAGES-1)); return ERROR; } FA125LOCK; /* Configuration csr for buffer to main memory */ vmeWrite32(&fa125p[id]->main.configCSR, FA125_CONFIGCSR_PROG_ENABLE | (FA125_OPCODE_BUFFER_PUSH<<24)); /* Push buffer contents using page address */ vmeWrite32(&fa125p[id]->main.configAdrData, (ipage<<18)); vmeWrite32(&fa125p[id]->main.configAdrData, FA125_CONFIGADRDATA_EXEC | (ipage<<18)); vmeWrite32(&fa125p[id]->main.configAdrData, (ipage<<18)); FA125UNLOCK; if(waitForDone==0) { return OK; } if(fa125FirmwareWaitForPushBufferToMain(id, ipage)!=OK) return ERROR; return OK; } static int fa125FirmwareWaitForPushBufferToMain(int id, int ipage) { int rwait=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } FA125LOCK; if(fa125FirmwareWaitForReady(id,100000,&rwait)!=OK) { printf("\n%s: ERROR: Push to main memory timeout (page = %d) (rwait = %d).\n\n", __FUNCTION__, ipage,rwait); vmeWrite32(&fa125p[id]->main.configAdrData, 0); FA125UNLOCK; return ERROR; } if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_WAIT_FOR_READY) { printf("%s: Push buffer contents using page address. rwait = %d\n", __FUNCTION__,rwait); } /* Pull Execute low before asserting new configuration type */ vmeWrite32(&fa125p[id]->main.configAdrData, 0); if(fa125FirmwareWaitForReady(id,100,&rwait)!=OK) { printf("\n%s: ERROR: Pull down execute timeout (rwait = %d).\n\n", __FUNCTION__, rwait); FA125UNLOCK; return ERROR; } FA125UNLOCK; return OK; } static int fa125FirmwareReadMainPage(int id, int ipage, int stayon) { int ibadr=0; int rwait=0; unsigned int csraddr = 0; unsigned int data=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } if(ipage>(FA125_FIRMWARE_MAX_PAGES-1)) { printf("\n%s: ERROR: ipage > Maximum page count (%d > %d)\n\n", __FUNCTION__, ipage, FA125_FIRMWARE_MAX_PAGES-1); } memset((char *)tmp_pageData, 0, sizeof(tmp_pageData)); /* taskDelay(1); */ FA125LOCK; /* Configuration csr for main memory read */ vmeWrite32(&fa125p[id]->main.configCSR, FA125_CONFIGCSR_PROG_ENABLE | (FA125_OPCODE_MAIN_READ<<24)); for(ibadr=0; ibadrmain.configAdrData, csraddr); vmeWrite32(&fa125p[id]->main.configAdrData, FA125_CONFIGADRDATA_EXEC | csraddr); vmeWrite32(&fa125p[id]->main.configAdrData, csraddr); if(fa125FirmwareWaitForReady(id,10000,&rwait)!=OK) { printf("\n%s: ERROR: Main memory read timeout (byte address = %d, page = %d) (rwait = %d).\n\n", __FUNCTION__, ibadr,ipage,rwait); FA125UNLOCK; return ERROR; } data = vmeRead32(&fa125p[id]->main.configCSR); tmp_pageData[ibadr] = data & FA125_CONFIGCSR_DATAREAD_MASK; } /* Pull Execute low before asserting new configuration type */ #ifdef DOSTAYON if(stayon==0) { vmeWrite32(&fa125p[id]->main.configAdrData, 0); if(fa125FirmwareWaitForReady(id,100,&rwait)!=OK) { printf("\n%s: ERROR: Pull down execute timeout (rwait = %d).\n\n", __FUNCTION__, rwait); FA125UNLOCK; return ERROR; } taskDelay(1); } #endif FA125UNLOCK; return OK; } static int fa125FirmwareReadBuffer(int id) { int ibadr=0; int rwait=0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } memset((char *)tmp_pageData, 0, sizeof(tmp_pageData)); FA125LOCK; /* Configuration csr for buffer memory read */ vmeWrite32(&fa125p[id]->main.configCSR, FA125_CONFIGCSR_PROG_ENABLE | (FA125_OPCODE_BUFFER_READ<<24)); /* taskDelay(1); */ /* Read main memory using full address (page and byte) */ for(ibadr=0; ibadrmain.configAdrData, (ibadr<<8)); vmeWrite32(&fa125p[id]->main.configAdrData, FA125_CONFIGADRDATA_EXEC | (ibadr<<8)); vmeWrite32(&fa125p[id]->main.configAdrData, (ibadr<<8)); if(fa125FirmwareWaitForReady(id,100,&rwait)!=OK) { printf("\n%s: ERROR: Main memory read timeout (byte address = %d) (rwait = %d).\n\n", __FUNCTION__, ibadr,rwait); FA125UNLOCK; return ERROR; } tmp_pageData[ibadr] = vmeRead32(&fa125p[id]->main.configCSR) & FA125_CONFIGCSR_DATAREAD_MASK; } /* Pull Execute low before asserting new configuration type */ vmeWrite32(&fa125p[id]->main.configAdrData, 0); FA125UNLOCK; return OK; } static int fa125FirmwareVerifyFull(int id) { int ipage=0; int stayon=1; struct timespec time_start, time_end, res; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } if(MCS_loaded==0) { printf("\n%s: ERROR: MCS file not loaded into memory\n\n", __FUNCTION__); return ERROR; } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.npages_read = 0; fa125FWstats.main_page_read_time.tv_sec = 0; fa125FWstats.main_page_read_time.tv_nsec = 0; } #endif FA125LOCK; vmeWrite32(&fa125p[id]->main.configCSR, 0); FA125UNLOCK; printf("%3d: ",id); fflush(stdout); for(ipage=0; ipage<=MCS_pageSize; ipage++) { if((ipage%(8*0x10))==0) { printf("."); fflush(stdout); } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { clock_gettime(CLOCK_MONOTONIC, &time_start); } #endif if(ipage==(MCS_pageSize-1)) stayon=0; /* Read a page from main memory */ if(fa125FirmwareReadMainPage(id, ipage, stayon)!=OK) { vmeWrite32(&fa125p[id]->main.configAdrData, 0); printf("\n%s: Error reading from main memory (page = %d)\n\n", __FUNCTION__,ipage); return ERROR; } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.npages_read++; clock_gettime(CLOCK_MONOTONIC, &time_end); res = tsSubtract(time_end, time_start); fa125FWstats.main_page_read_time = tsAdd(fa125FWstats.main_page_read_time, res); } #endif /* Verify the page with that read from the file */ if(fa125FirmwareVerifyPage(ipage)!=OK) { printf("\n%s: ERROR in verifying page %d\n\n", __FUNCTION__,ipage); return ERROR; } } printf("\n"); return OK; } /** * @ingroup FWUpdate * @brief Verify that the firmware has been written correctly to all initialized fADC125s * @return OK if successful, otherwise ERROR. */ int fa125FirmwareGVerifyFull() { int ifa=0, id=0; if(MCS_loaded==0) { printf("\n%s: ERROR: MCS file not loaded into memory\n\n", __FUNCTION__); return ERROR; } printf("** Verifying Main Memory **\n"); for(ifa=0; ifa0) { printf("\n%s: ERROR: Total number of errors = %d\n\n", __FUNCTION__,nerror); return ERROR; } return OK; } static int fa125FirmwareVerifyErasedPage(int ipage) { int ibyte=0; int nerror=0; for(ibyte=0; ibyte0) { printf("\n%s: ERROR: Total number of errors = %d\n\n", __FUNCTION__,nerror); return ERROR; } return OK; } static int hex2num(char c) { c = toupper(c); if(c > 'F') return 0; if(c >= 'A') return 10 + c - 'A'; if((c > '9') || (c < '0') ) return 0; return c - '0'; } /** * @ingroup FWUpdate * @brief Read in the firmware from selected MCS file. * @param filename Name of file that contains the firmware in MCS format. * @return OK if successful, otherwise ERROR. */ int fa125FirmwareReadMcsFile(char *filename) { FILE *mcsFile=NULL; char ihexLine[200], *pData; int len=0, datalen=0; unsigned int nbytes=0, line=0, hiChar=0, loChar=0; int ibyte=0, ipage=0; unsigned int readMCS=0; int ichar; int ifpga=MAIN, fpga_bytes=0, getFirmwareLocation=0; unsigned int mcs_addr=0xFFF0, addr0=0, addr1=0, addr2=0, addr3=0; unsigned int prev_elar_data=-1, elar_data=0, data0=0, data1=0, data2=0, data3=0; unsigned int mcs_line_number=0; /* Initialize the local storage array */ memset((char *)MCS_DATA,0xff,sizeof(MCS_DATA)); mcsFile = fopen(filename,"r"); if(mcsFile==NULL) { perror("fopen"); printf("\n%s: ERROR opening file (%s) for reading\n\n", __FUNCTION__,filename); return ERROR; } ifpga=MAIN; /* First firmware is for the MAIN FPGA */ while(!feof(mcsFile)) { mcs_line_number++; /* Get the current line */ if(!fgets(ihexLine, sizeof(ihexLine), mcsFile)) break; /* Get the the length of this line */ len = strlen(ihexLine); if(len >= 5) { /* Check for the start code */ if(ihexLine[0] != ':') { printf("\n%s: ERROR parsing file at line %d\n\n", __FUNCTION__,line); return ERROR; } /* Get the byte count */ hiChar = hex2num(ihexLine[1]); loChar = hex2num(ihexLine[2]); datalen = (hiChar)<<4 | loChar; if(strncmp("00",&ihexLine[7], 2) == 0) /* Data Record */ { /* Get the address */ addr3 = hex2num(ihexLine[3]); addr2 = hex2num(ihexLine[4]); addr1 = hex2num(ihexLine[5]); addr0 = hex2num(ihexLine[6]); mcs_addr = (elar_data<<16) | (addr3<<12) | (addr2<<8) | (addr1<<4) | addr0; /* Determine the initial page and byte number from this address */ ipage = (int)(mcs_addr / FA125_FIRMWARE_MAX_BYTE_PER_PAGE); ibyte = (int)(mcs_addr % FA125_FIRMWARE_MAX_BYTE_PER_PAGE); if(getFirmwareLocation==1) { /* ipage = sfpga[ifpga].page_location; */ /* ibyte = sfpga[ifpga].page_byte_location; */ sfpga[ifpga].page_location = ipage; sfpga[ifpga].page_byte_location = ibyte; getFirmwareLocation=0; } pData = &ihexLine[9]; /* point to the beginning of the data */ while(datalen--) { hiChar = hex2num(*pData++); loChar = hex2num(*pData++); MCS_DATA[ipage][ibyte] = ((hiChar)<<4) | (loChar); fpga_bytes++; if(readMCS>=MCS_MAX_SIZE) { printf("\n%s: ERROR: TOO BIG!\n\n",__FUNCTION__); return ERROR; } /* if(ipage<2) */ /* printf("%4d %3d: 0x%02x\n",ipage,ibyte,MCS_DATA[ipage][ibyte]); */ if((ibyte+1)==FA125_FIRMWARE_MAX_BYTE_PER_PAGE) { /* If at the end of the page, start up a new one */ ibyte=0; ipage++; } else { ibyte++; } readMCS++; nbytes++; } } else if(strncmp("04",&ihexLine[7], 2) == 0) /* ELAR */ { /* Get the elar data */ data3 = hex2num(ihexLine[9]); data2 = hex2num(ihexLine[10]); data1 = hex2num(ihexLine[11]); data0 = hex2num(ihexLine[12]); elar_data = (data3<<12) | (data2<<8) | (data1<<4) | data0; /* if(prev_addr!=0xFFF0) */ if(elar_data != (prev_elar_data + 1)) { if(ifpga!=NFPGATYPE) { sfpga[ifpga].size = fpga_bytes; ifpga++; getFirmwareLocation=1; /* ipage = sfpga[ifpga].page_location; */ /* ibyte = sfpga[ifpga].page_byte_location; */ fpga_bytes=0; } /* printf("%8d: fpga_bytes = %8d ipage = 0x%06x (bytes = 0x%x)\n", */ /* mcs_line_number,fpga_bytes,ipage, ipage*FA125_FIRMWARE_MAX_BYTE_PER_PAGE); */ } prev_elar_data = elar_data; } else if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MCS_SKIPPED_LINES) { printf("%s: Skipped line (%d): \t>%s<\n", __FUNCTION__,line,ihexLine); } } line++; } MCS_pageSize = ipage+1; MCS_dataSize = readMCS; if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MCS_FILE) { printf("MCS_dataSize = %d MCS_pageSize = %d\n",MCS_dataSize,MCS_pageSize); for(ichar=0; ichar<16*10; ichar++) { if((ichar%16) == 0) printf("\n"); printf("0x%02x ",MCS_DATA[0][ichar]); } printf("\n\n"); } MCS_loaded = 1; fa125FirmwarePrintFPGAStats(); fclose(mcsFile); return OK; } /** * @ingroup FWUpdate * @brief Prints to standard out, the memory size and location of each FPGA firmware */ void fa125FirmwarePrintFPGAStats() { int ifpga=MAIN; for(ifpga=MAIN; ifpga21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.nblocks_erased=0; fa125FWstats.erase_time.tv_sec = 0; fa125FWstats.erase_time.tv_nsec = 0; } #endif printf("** Erasing Main Memory **\n"); for(iblock=0; iblockmain.configAdrData, 0); printf("\n%s: Error reading from main memory (page = %d)\n\n", __FUNCTION__,ipage); return ERROR; } /* Verify the page was erased */ if(fa125FirmwareVerifyErasedPage(ipage)!=OK) { printf("\n%s: ERROR: Block erase failed to erase block %d (page %d)\n\n", __FUNCTION__,iblock,ipage); return ERROR; } } } printf("\n"); fflush(stdout); } return OK; } /** * @ingroup FWUpdate * @brief Erase the entire contents of the configuration ROM for all initialized fADC125s * @return OK if successful, otherwise ERROR. */ int fa125FirmwareGEraseFull() { int ipage=0; int iblock=0, nblocks=1024; int stayon=1; struct timespec time_start, time_end, res; int id=0, ifa=0; int nerrors=0; #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.nblocks_erased=0; fa125FWstats.erase_time.tv_sec = 0; fa125FWstats.erase_time.tv_nsec = 0; } #endif memset((char *)fa125FirmwareErrorFlags, 0, sizeof(fa125FirmwareErrorFlags)); printf("** Erasing Main Memory **\n"); printf("All: "); fflush(stdout); for(iblock=0; iblockmain.configAdrData, 0); printf("\n%s: Slot %d: Error reading from main memory (page = %d)\n\n", __FUNCTION__,id,ipage); fa125FirmwareErrorFlags[id] |= FA125_FIRMWARE_ERROR_VERIFY_ERASE; /* return ERROR; */ } /* Verify the page with that read from the file */ if(fa125FirmwareVerifyErasedPage(ipage)!=OK) { printf("\n%s: Slot %d: Block erase failed to erase block %d (page %d)\n\n", __FUNCTION__,id, iblock,ipage); fa125FirmwareErrorFlags[id] |= FA125_FIRMWARE_ERROR_VERIFY_ERASE; /* return ERROR; */ } } } /* nblocks */ printf("\n"); } /* nfa125 */ fflush(stdout); } /* Count how many modules had errors */ for(ifa=0; ifa21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.nbuffers_written = 0; fa125FWstats.buffer_write_time.tv_sec = 0; fa125FWstats.buffer_write_time.tv_nsec = 0; fa125FWstats.nbuffers_pushed = 0; fa125FWstats.buffer_push_time.tv_sec = 0; fa125FWstats.buffer_push_time.tv_nsec = 0; } #endif printf("** Writing file to memory **\n"); for(ipage=0; ipage<=MCS_pageSize; ipage++) { if((ipage%(8*0x10))==0) { printf("."); fflush(stdout); } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { clock_gettime(CLOCK_MONOTONIC, &time_start); } #endif if(fa125FirmwareWriteToBuffer(id, ipage)!=OK) { printf("\n%s: Error writing to buffer\n\n",__FUNCTION__); return ERROR; } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.nbuffers_written++; clock_gettime(CLOCK_MONOTONIC, &time_end); res = tsSubtract(time_end, time_start); fa125FWstats.buffer_write_time = tsAdd(fa125FWstats.buffer_write_time, res); } #endif if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_WRITE_BUFFER) { if(fa125FirmwareReadBuffer(id)!=OK) { printf("\n%s: Error reading from buffer\n\n",__FUNCTION__); return ERROR; } if(fa125FirmwareVerifyPage(ipage)!=OK) { printf("\n\n%s: ERROR in verifying page %d\n\n", __FUNCTION__,ipage); return ERROR; } } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { clock_gettime(CLOCK_MONOTONIC, &time_start); } #endif if(fa125FirmwarePushBufferToMain(id, ipage, 1)!=OK) { printf("\n%s: Error in pushing buffer to main memory (page = %d)\n\n", __FUNCTION__,ipage); return ERROR; } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.nbuffers_pushed++; clock_gettime(CLOCK_MONOTONIC, &time_end); res = tsSubtract(time_end, time_start); fa125FWstats.buffer_push_time = tsAdd(fa125FWstats.buffer_push_time, res); } #endif } printf("\n"); fflush(stdout); printf("** Verifying Main Memory **\n"); if(fa125FirmwareVerifyFull(id)!=OK) { printf("\n%s: Error in verifying full firmware\n\n", __FUNCTION__); return ERROR; } return OK; } /** * @ingroup FWUpdate * @brief Write the contents of the read in MCS file to the Configuration ROM of all initialized fADC125s * @return OK if successful, otherwise ERROR. */ int fa125FirmwareGWriteFull() { int id=0, ifa=0; int ipage=0; struct timespec time_start, time_end, res; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { logMsg("\n%s: ERROR : FA125 in slot %d is not initialized\n\n",(int)__FUNCTION__,id,3,4,5,6); return ERROR; } #ifndef VXWORKSPPC if(fa125FirmwareDebug&FA125_FIRMWARE_DEBUG_MEASURE_TIMES) { fa125FWstats.nbuffers_written = 0; fa125FWstats.buffer_write_time.tv_sec = 0; fa125FWstats.buffer_write_time.tv_nsec = 0; fa125FWstats.nbuffers_pushed = 0; fa125FWstats.buffer_push_time.tv_sec = 0; fa125FWstats.buffer_push_time.tv_nsec = 0; } #endif printf("** Writing file to memory **\n"); printf("All: "); fflush(stdout); for(ipage=0; ipage<=MCS_pageSize; ipage++) { for(ifa=0; ifa21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized\n\n", __FUNCTION__, id); return(ERROR); } if((suppress < 0) || (suppress > 1)) { printf("\n%s: ERROR: Invalid suppress value (%d)\n\n", __FUNCTION__, suppress); return ERROR; } if(suppress) val = 0; else val = FA125_PROC_CTRL2_TRIGTIME_ENABLE; FA125LOCK; vmeWrite32(&fa125p[id]->proc.ctrl2, val); FA125UNLOCK; return OK; } /** * @ingroup Config * @brief Enable/Disable suppression of one or both of the trigger time words * in the data stream for all initialized modules. * @param suppress Suppression Flag * - 0: Trigger time words are enabled in datastream * - 1: Suppress BOTH trigger time words */ void fa125GDataSuppressTriggerTime(int suppress) { int ifa; for(ifa = 0; ifa < nfa125; ifa++) fa125DataSuppressTriggerTime(fa125Slot(ifa), suppress); } // Alex #if 0 int fa125SetTimingThreshold(int id, unsigned int chan, unsigned int lo, unsigned int hi) { unsigned int wval = 0; if(id==0) id=fa125ID[0]; if((id<0) || (id>21) || (fa125p[id] == NULL)) { printf("\n%s: ERROR : FA125 in slot %d is not initialized \n\n",__FUNCTION__,id); return ERROR; } if(chan>=FA125_MAX_ADC_CHANNELS) { printf("\n%s: ERROR: Invalid channel (%d). Must be 0-%d\n\n", __FUNCTION__,chan,FA125_MAX_ADC_CHANNELS); return ERROR; } if(lo>FA125_MAX_LOW_TTH) { printf("\n%s: ERROR: Invalid value for Low Timing Threshold (%d)\n\n", __FUNCTION__,lo); return ERROR; } if(hi>FA125_MAX_HIGH_TTH) { printf("\n%s: ERROR: Invalid value for High Timing Threshold (%d)\n\n", __FUNCTION__,hi); return ERROR; } FA125LOCK; /* Write the lo value */ if((chan%2)==0) { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3]) & 0x3F000000) | (lo<<8); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3], wval); } else { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3]) & 0x3F00) | (lo<<24); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_lo[(chan/2)%3], wval); } /* Write the hi value */ if((chan%3)==0) { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & 0x07fffe00) | (hi); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2], wval); } else if((chan%3)==1) { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & 0x07fc01ff) | (hi<<9); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2], wval); } else { wval = (vmeRead32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2]) & 0x0003ffff) | (hi<<18); vmeWrite32(&fa125p[id]->fe[chan/6].timing_thres_hi[(chan/3)%2], wval); } FA125UNLOCK; return OK; } #endif