The Canberra 556 AIM is an Ethernet multichannel analyzer in a NIM form factor. It has 2 ADC inputs, and a total of about 64K channels, each 32-bits deep. It can control programmable devices such as amplifiers, ADCs, high-voltage power supplies, etc. using an auxilliary bus called the Instrument Control Bus (ICB).
The AIM uses the IEEE 802.2 Extended SNAP protocol, which is a low-level protocol, and does not use TCP/IP. The protocol is not routeable, so the AIM must be placed on the same physical subnet as the IOC that is controlling it.
The AIM has a concept of module "ownership", i.e. a particular computer that can control it. Once an AIM is "owned" only that one computer can control the AIM, all other computers are prevented from accessing it. When the AIM is first powered on it is unowned, and any computer can take ownership. The EPICS driver attempts to gain ownership during the AIMConfig command. If it cannot, then it prints an error message. If the AIM is currently owned by another computer and you want to change what computer owns it, you can do one of two things. Either power off the AIM and back on, or issue the command mcaAIMFreeModule, described below.
The DSA-2000 is functionally the same as the AIM, but with a single ADC port and packaged in a rack-mount unit. The DSA-2000 contains the equivalent of the 9660 DSP which is set at ICB address 0. The DSA-2000 also contains an internal programmable high-voltage power supply. This is not the same as the ICB power supplies, and has its own driver described below.
The AIM and ICB device support runs on vxWorks, Linux, and Windows (win32-x86, windows-x64). It should also build and run on other Unix systems, including Mac OS X, as long as the libnet and libpcap libraries are available and installed. Note that Linux often comes with libpcap installed, but libnet often needs to be obtained separately.
The device support for the Canberra hardware uses the following:
There is a separate asyn server for each ADC input port on an AIM. Each AIM can thus have two asyn ports associated with it. Each port card can have multiple "addresses", where each address is a region of AIM memory associated with a physical signal input. Each input signal can have more than one "sequence" or time-slice allocated to it. The configuration of an AIM input with an asyn port, and the allocation of memory within the AIM for this input is done by routine AIMConfig. AIMConfig is called as follows:
# AIMConfig(portName, ethernet_address, portNumber(1 or 2), maxChans, # maxSignals, maxSequences, ethernetDevice)
The total amount of memory (in channels) allocated for the port will be maxChans*maxSignals*maxSequences. The total amount of memory in the AIM is about 64,000 channels, and this is shared by the two ports.
When creating an MCA record which uses the AIM device support the INP field must be specified in the form:
@asyn(portName address),NCHAN=nchans
where:
Assume we have an AIM with Ethernet address 0x59e. To port 1 of this AIM there is a single ADC which is set for 2048 channels. This ADC will be used for "conventional" data acquisition, i.e. with no multiplexor and not doing time-resolved work. To port 2 of this AIM there is a multiplexor. The switches in the multiplexor have been set for 4 inputs and 4096 channels. The records for these multiplexor inputs only use 1024 channels in this example.
The system has a second AIM at Ethernet address 0x100. To port 1 of this AIM there is a single ADC which is set for 1024 channels. This ADC will be used for time-resolved work, and we want to collect 20 spectra within the AIM. To port 2 of this AIM there is an MCS which has front panel switches set to 2 inputs and 8192 channels.
AIMConfig("AIM1/1", 0x59e, 1, 2048, 1, 1, "dc0") AIMConfig("AIM1/2", 0x59e, 2, 4096, 4, 1, "dc0") AIMConfig("AIM2/1", 0x100, 1, 1024, 1,20, "dc0") AIMConfig("AIM2/2", 0x100, 2, 8192, 2, 1, "dc0") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim1_adc1,DTYP=asynMCA,INP=@asyn(AIM1/1 0),NCHAN=2048") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim1_adc2_1,DTYP=asynMCA,INP=@asyn(AIM1/2 0),NCHAN=1024") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim1_adc2_2,DTYP=asynMCA,INP=@asyn(AIM1/2 1),NCHAN=1024") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim1_adc2_2,DTYP=asynMCA,INP=@asyn(AIM1/2 2),NCHAN=1024") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim1_adc2_3,DTYP=asynMCA,INP=@asyn(AIM1/2 3),NCHAN=1024") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim2_adc1,DTYP=asynMCA,INP=@asyn(AIM2/1 0),NCHAN=1024") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim2_adc2_1,DTYP=asynMCA,INP=@asyn(AIM2/2 0),NCHAN=8192") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim2_adc2_2,DTYP=asynMCA,INP=@asyn(AIM2/2 1),NCHAN=8192")
Note that it is convenient to set the multiplexor switches for the largest spectral size and largest number of inputs which you anticipate using. Smaller spectral sizes can be selected by setting NCHAN in the startup script (=NUSE and NMAX in MCA record) to a smaller value, without having to open the multiplexor and change the switch settings. Extra inputs are ignored simply by not assigning any records to those inputs. The only disadvantage of this approach is that it wastes AIM memory. However, the AIM has a total of more than 64,000 channels of acquisition memory which is more than enough for many applications.
There is a separate asyn server for ICB module (such as an ADC, amplifier, etc.) The configuration of an ICB module and creation of the asyn server is done by routine ICBConfig. ICBConfig is called as follows:
#icbConfig(portName, module, ethernetAddress, icbAddress, moduleType)
The following lines show how to set up ICB modules in an EPICS startup script. This assumes an AIM at address 0x59e, an ADC at ICB address 5, an amplifier at ICB address 3, a HVPS at ICB address 2, a TCA at ICB address 8, and a DSP at ICB address 7. The LIMIT parameter for the HVPS specifies the maximum voltage. The MCA parameter for the TCA specifies an associated MCA record for which programming the first three ROIs will program the TCA windows.
icbConfig("icbAdc1", 0x59e, 5, 0) dbLoadRecords("$(MCA)/mcaApp/Db/icb_adc.db", "P=mcaTest:,ADC=adc1,PORT=icbAdc1") icbConfig("icbAmp1", 0x59e, 3, 1) dbLoadRecords("$(MCA)/mcaApp/Db/icb_amp.db", "P=mcaTest:,AMP=amp1,PORT=icbAmp1") icbConfig("icbHvps1", 0x59e, 2, 2) dbLoadRecords("$(MCA)/mcaApp/Db/icb_hvps.db", "P=mcaTest:,HVPS=hvps1,PORT=icbHvps1,LIMIT=1000") icbConfig("icbTca1", 0x59e, 8, 3) dbLoadRecords("$(MCA)/mcaApp/Db/icb_tca.db", "P=mcaTest:,TCA=tca1,MCA=aim_adc2,PORT=icbTca1") #icbConfig("icbDsp1", 0x59e, 7, 4) #dbLoadRecords("$(MCA)/mcaApp/Db/icbDsp.db", "P=mcaTest:,DSP=dsp1,PORT=icbDsp1")
The DSA-2000 contains 3 logical modules that are supported by EPICS.
The following startup script configures a DSA-2000 MCA, DSP, and HVPS.
AIMConfig("AIM1/1", 0x8058, 1, 2048, 1, 1, "eth1") dbLoadRecords("$(MCA)/mcaApp/Db/mca.db", "P=mcaTest:,M=aim_adc1,DTYP=asynMCA,INP=@asyn(AIM1/1 0),NCHAN=2048") icbConfig("icbDsp1", 0x8058, 0, 4) dbLoadRecords("$(MCA)/mcaApp/Db/icbDsp.db", "P=mcaTest:,DSP=dsp1,PORT=icbDsp1") DSA2000Config("DSA2000", 0x8058) dbLoadRecords("$(MCA)/mcaApp/Db/DSA2000_HVPS.db", "P=mcaTest:,HVPS=hvps1:,PORT=DSA2000,LIMIT=5000")
There are several commands for the Canberra support that are defined in the EPICS iocsh shell.
Examples of these commands:
epics> mcaAIMShowModules Module Owner name Owner ID Status Memory size Free address NI008058 ioc13lab 00:01:AF:0C:11:F7 Reachable 262140 00000000 NI00059e gselab1 00:B0:D0:D9:A3:03 Reachable 261116 00004000 NI0006e6 ioc13idc 00:01:AF:00:74:CD Reachable 261116 00000000 NI0009ce ioc13bmd 08:00:3E:2E:63:37 Reachable 261116 00000000 NI0003ed ioc13idd 08:00:3E:2F:1F:F8 Reachable 261116 00000000 epics> icbShowModules NI59E:2 3 CI9641 2K HVPS 8965924 NI59E:3 7 CI9615 AMP 11923928 Preamp type: RC Coarse gain: 2.500000 Fine gain: 1.000000 Super fine gain: 1.000000 Shaping mode: GAUSSIAN Pole zero: 1 Baseline restore: SYM Dead-time control: Norm Time constant: 4.000000 Flags: 10 NI59E:5 6 CI9635 8K ADC 2945853 Range: 2048 Offset: 0 Acquisition mode: PHA Conversion gain: 2048 Lower level disc: 1.000000 Upper level disc: 100.000000 Zero: 0.000000 Flags: 40 NI59E:8 2 Unknown 3994275 # Release the second module in the above list (NI00059e) even if this command # is not being issued from the owner IOC, gselab1. epics> mcaAIMFreeModule 1 1
The driver on vxWorks uses the functions in muxLib or muxTkLib. On vxWorks 6.x this requires that the Board Support Package (BSP) be built with the INCLUDE_NET_POOL option.
The libnet (and possibly libpcap?) libraries need root permission in order to send non-TCP/IP packets on the network. Thus, the EPICS IOC application must be run by someone with root privilege, or else the application must be installed with SUID root.
The following must be installed:
It is necessary to specify the name of the Ethernet device in the AIMConfig command in the EPICS startup script. This is of the format:
\Device\NPF_{8ECC055D-047F-11D1-A537-0000F8753ED1}
The long number at the end is unique to each network card. The simplest way to get this name is to run with the example startup script in iocBoot/iocWindows/st.cmd with the string provided in the distribution. This will fail, but the driver will then print out a list of all the valid network device names on your system, along with their descriptions. Find the one that describes the network that your Canberra hardware is attached to, and replace the string in the AIMConfig commands below with that string.
Alternatively, you can get this number for your Window machine by using the "regedit" utility, and doing an "export" of the key:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards]
This should look like:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards] [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards\2] "ServiceName"="{15B576D2-6DF4-4C9F-B53C-DBF76B53194E}" "Description"="3Com 3C920 Integrated Fast Ethernet Controller (3C905C-TX Compatible)"
The number that is needed in the ServiceName field. Copy this number and paste into the AIMConfig command in your st.cmd startup command file.
For time-resolved spectroscopy it is very desirable to be able to rapidly change the region of the AIM memory into which an ADC acquires. The .SEQ field in the MCA record is designed for this purpose, and it is implemented in the AIM device support. By rapidly incrementing the value of the .SEQ field, for example with a database or Channel Access client, one can acquire a number of spectra in rapid succession, without incurring the delay of reading the spectra from the AIM and erasing the memory between acquisitions. The only delay is the few msec required to transmit a message changing the memory address of acquisition.
Tests were done with R6-10 of the mca module to measure the performance of the Canberra AIM modules in rapidly collecting spectra in a scan. The tests were done under the following conditions:
Model | Host | Compressed read | Uncompressed read |
---|---|---|---|
556 | Linux (libnet/libpcap) | 10.2 | 15.8 |
556 | vxWorks (etherLib) | 10.0 | 14.4 |
556 | vxWorks (LLC sockets, muxLib) | 10.0 | N.D. |
556A | Linux (libnet/libpcap) | 35.0 | 10.8 |
556A | vxWorks (etherLib) | 30.0 | 10.1 |
556A | vxWorks (LLC sockets, muxLib) | N.D. | 10.0 |
DSA2000 | Linux (libnet/libpcap) | 30.8 | 13.4 |
DSA2000 | vxWorks (etherLib) | N.D. | 12.0 |
DSA2000 | vxWorks (LLC sockets, muxLib) | N.D. | 12.0 |
The following IDL program measures how fast time-resolved data can be acquired. It was tested with record 13LAB:aim_adc1 configured with maxSequences=4 and with an input pulser at about 100 kHz.
;************************************************************ ; This program tests the time-resolved spectroscopy capabilities of the ; new MCA record with the AIM. The hardware configuration is an ADC with ; pulses coming in at about 100 kHz. ; Create EPICS MCA object rec = '13LAB:aim_adc1' casettimeout, .005 ; Fast channel access timeout max_sequences = 4 mca = obj_new('epics_mca', rec) ; Turn of acquisition, erase all of the spectra in the AIM mca->acquire_off for i=0,max_sequences-1 do begin mca->set_sequence, i mca->erase endfor ; Acquire data in sequence 0 for 1 second to determine input count rate mca->set_sequence, 0 presets = mca->get_presets() presets.real_time = 1.0 presets.live_time = 0.0 mca->set_presets, presets mca->erase mca->acquire_on mca->acquire_wait data = mca->get_data() count_rate = total(data) print, 'Input count rate = ', count_rate ; Clear presets, erase sequence 0 presets.live_time = 0.0 mca->set_presets, presets mca->erase ; Now collect time-resolved spectra as fast as possible mca->acquire_on t0 = systime(1) for i=0,max_sequences-1 do begin mca->set_sequence, i endfor t1 = systime(1) mca->acquire_off print, 'Elapsed time for time-resolved spectra= ', t1-t0 ; Read out each spectrum, print number of counts time = fltarr(max_sequences) for i=0, max_sequences-1 do begin mca->set_sequence, i data = mca->get_data() time(i) = total(data)/count_rate print, ' Total counts in sequence ', i, ' = ', total(data) print, ' time in sequence = ', time(i) * 1000., ' msec.' endfor print, 'Real time = ', t1-t0 print, 'Live time = ', total(time) print, 'Dead time = ', total(time)/(t1-t0)*100., ' percent' end ;************************************************************ The following are the results of the test: Input count rate = 125459. Elapsed time for time-resolved spectra= 0.24195898 Total counts in sequence 0 = 8187.00 time in sequence = 65.2564 msec. Total counts in sequence 1 = 3787.00 time in sequence = 30.1852 msec. Total counts in sequence 2 = 3803.00 time in sequence = 30.3127 msec. Total counts in sequence 3 = 2862.00 time in sequence = 22.8122 msec. Real time = 0.24195898 Live time = 0.148566 Dead time = 61.401506 percent
The total elapsed time to collect 4 time-resolved spectra is 241 msec. The first spectrum collected for 65 msec (because it includes the overhead of the acquire on command), while the other spectra were collected for 20-30 msec. The dead time was about 100 msec for 4 spectra, or about 25 msec per spectrum. Note that if the .SEQ field were incremented by a process in the crate, rather than IDL channel access the performance might be somewhat better.
The conclusion is that the MCA record and AIM can acquire about 20 spectra per second, which is fast enough for many applications.