Please note that this Quick Start Guide is outdated and to be removed. The latest Handel Programmer's Guide can be found here or in the docs folder of a Handel release.

 

Intended Audience

This document is intended for users of the XIA microDXP hardware who would like to interface to it using the Handel driver library. This document assumes that users of the Handel driver library are familiar with the C programming language.

Conventions Used in this Document

  • This style is used to indicate source code.
  • CHECK_ERROR is a placeholder for user-defined error handling. (See the sample code for an example of how to implement such error handling.)

Preliminary Details

Header Files

Before introducing the details of programming with the Handel API, it is important to discuss the relevant header files and other external details related to Handel. The following headers must be included:

  • handel.h Defines and imports all available Handel routines.
  • md_generic.h Contains the constants for setting logging levels.
  • handel_errors.h Error status constants including XIA_SUCCESS.
  • handel_constants.h Contains the constants used for Handel calls.

Error Codes

A good programming practice with Handel is to compare the returned status value with  XIA_SUCCESS and then deal with any returned errors before proceeding. All Handel routines (except for some of the debugging routines) return an integer value indicating success or failure. While not discussed in great detail in this document, Handel does provide a comprehensive logging and error reporting mechanism that allows an error to be traced back to a specific line of code in Handel. Details on using this system are found in the Handel API.

.INI Files

The final piece of information external to the actual Handel source code is the initialization file. The simplest way to supply the hardware configuration to Handel is to use the supplied microDXP initialization file (udxp_std.ini). The .ini file must specify the COM port used for the microDXP. To do this, edit the line 
 
  com_port = 1
 
and set it to the appropriate value, where a setting of 1 represents COM1 and 2 represents COM2 and so on. The rest of the .ini file will have no effect since all of the other settings are read from the microDXP itself. For more details, see the comments in udxp_std.ini.

Example Code

Included with this document is a file called hqsg-udxp.c that illustrates all of the lessons presented in this tutorial. hqsg-udxp.c is sample code that initializes Handel, configures the microDXP hardware, starts a run, stops a run, reads out the MCA spectrum and saves the current configuration to the hardware. 

Setting up Logging

Handel provides a comprehensive logging and error reporting mechanism that allows an error to be traced back to a specific line of code in Handel.  To utilize the logging system, a log file needs to be set up, preferably at the beginning of the application.

/*
* Direct logging to a local file, the different log levels can be found in md_generic.h
*/

xiaSetLogLevel(MD_DEBUG);
xiaSetLogOutput("handel.log");

To prevent memory leak and release the file handle, the log file needs to be closed at the end of application.

xiaCloseLog();

 

Initializing Handel

The first step in any program that uses Handel is to initialize the software library. Handel provides two routines to achieve this goal: xiaInit() and xiaInitHandel(). The difference between these two initialization methods is that the former requires the name of an initialization file. In fact, xiaInit() is nothing more then a wrapper around the following two functions: xiaInitHandel() and xiaLoadSystem().

/*
 * Example1: Emulating xiaInit() using 
 * xiaInitHandel() and xiaLoadSystem().
 */
 
int status;
 
status = xiaInitHandel();
CHECK_ERROR(status);
 
status = xiaLoadSystem("handel_ini", "udxp_std.ini");
CHECK_ERROR(status);
 

The above example has the exact same behavior as
 
int status;
 
status = xiaInit("udxp_std.ini");
CHECK_ERROR(status);

If the configuration file to be used is known ahead of time, then calling xiaInit() is the preferred method for initializing the library.

Starting the System

Once the initialization task has been completed, the next step is to “start the system.” This process performs several operations including validating the hardware information supplied in the initialization file and verifying the specified communication interface (RS-232, for the microDXP). Calling xiaStartSystem() is straightforward:

status = xiaStartSystem();
CHECK_ERROR(status);

Once xiaStartSystem() has been called successfully, the system is ready to perform the standard DAQ operations such as starting a run, stopping a run, reading out the MCA and saving parameter information.

Configuring the microDXP for Data Acquisition

Unlike other XIA hardware, the microDXP stores all of its firmware and operating parameters on-board in non-volatile memory. Older versions of the microDXP can store up to 3 FPGA configurations (FiPPIs), each corresponding to a separate range of peaking times.  Within each FiPPI peaking time range, 5 specific peaking times and their associated configurations can be saved to a PARameter SET (PARSET) in memory. For a microDXP configured with 3 FiPPIs, this yields a total of 15 different peaking time configurations.

The latest versions of the microDXP has an updated FPGA design and can store the entire range of peaking times in a single FiPPI. The updated FiPPI is able to store 24 different peaking time configurations.

In addition to the PARSETs, there are two other sets: GENeral SETs (GENSET) and GLOBal SETs (GLOBSET). The microDXP contains a total of 5 GENSETs. The GENSETs are not tied to a specific FiPPI and the parameters in this set are gain and spectrum related. There is a single GLOBSET which contain values specific to the detector preamplifier, debugging and run control.

A key component of configuring the microDXP is choosing values for the various PARSETs and GENSETs, and saving these values to non-volatile memory. As illustrated in Appendix A, B and C, not all of the PARSET/GENSET parameters map directly to acquisition values in Handel. The fact is you only need to modify a small subset of the total number of available parameters in order to configure the microDXP for your system.

Once the microDXP has been properly configured, your application should only need to swap between the different PARSET/GENSET entries. Furthermore, on power-up, the microDXP remembers which PARSET/GENSET was used last and loads it into memory so there is no need to track PARSET/GENSET in your application.

Now that we have a solid understanding of what the microDXP stores in memory, let's step through an example of how to configure a microDXP. In this example, we want to configure the microDXP with the following settings:

  • FiPPI 0
  • PARSET 0
  • GENSET 0
  • Medium bin width granularity
  • 4k spectrum
  • Trigger threshold of 20
  • Positive polarity detector
  • Base gain of 32768
  • 100 microsecond reset interval for the preamplifier

Select the FiPPI

On the latest versions of the microDXP, there is only a single FiPPI and there is never a need to switch. Attempting to set the FiPPI to anything besides the default value of 0 will result in an error. On older versions of the microDXP, the FiPPI can be selected as follows:

int status;

ushort numberFippis = 0;

double fippi = 0.0;

unsigned short fippiMem = AV_MEM_FIPPI;

/* Read out supported number of FiPPI first */

status = xiaBoardOperation(0, "get_number_of_fippis", (void *)&numberFippis);

CHECK_ERROR(status);

status = xiaSetAcquisitionValues(0, "fippi", (void *)&fippi);

CHECK_ERROR(status);

status = xiaBoardOperation(0, "apply", (void *)&fippiMem);

CHECK_ERROR(status);

Configure the microDXP

The next step is to set all of the acquisition values. It is important after setting an acquisition value that you "apply" the new value with a call to xiaBoardOperation().

double binWidth = 2.0;

double nMCA = 4096.0;

double threshold = 20.0;

double gain =  32768.0;

double polarity = 1.0;

double resetInt = 100.0;

unsigned short parsetAndGenset = AV_MEM_PARSET | AV_MEM_GENSET;

 

status = xiaSetAcquisitionValues(0, "mca_bin_width", (void *)&binWidth);

CHECK_ERROR(status);

status = xiaSetAcquisitionValues(0, "number_mca_channels", (void *)&nMCA);

CHECK_ERROR(status);

status = xiaSetAcquisitionValues(0, "trigger_threshold", (void *)&threshold);

CHECK_ERROR(status);

status = xiaSetAcquisitionValues(0, "gain", (void *)&gain);

CHECK_ERROR(status);

status = xiaSetAcquisitionValues(0, "polarity", (void *)&polarity);

CHECK_ERROR(status);

status = xiaSetAcquisitionValues(0, "preamp_value", (void *)&resetInt);

CHECK_ERROR(status);

/* Need to call "apply" after setting acquisition values! */

status = xiaBoardOperation(0, "apply", (void *)&parsetAndGenset);

CHECK_ERROR(status);

Note that the apply operation specifies which section of the microDXP's memory needs to be applied. When switching to a different FiPPI you need to call xiaBoardOperation("apply") with the AV_MEM_FIPPI flag; when you modify PARSET, GENSET or GLOBSET acquisition values you need to use AV_MEM_PARSET, AV_MEM_GENSET, AV_MEM_GLOB or some combination therein.

Save the GENSET/PARSET

Now that we have configured the device and are happy with our settings, we want to save the parameters so that we can return to this state again.

unsigned short genset = 0;

unsigned short parset = 0;

status = xiaBoardOperation(0, "save_genset", (void *)&genset);

CHECK_ERROR(status);

status = xiaBoardOperation(0, "save_parset", (void *)&parset);

CHECK_ERROR(status);

Selecting a Peaking Time

In the previous code we simply saved our configuration to PARSET 0 for FiPPI 0 without any explanation of what PARSET 0 corresponds to. Each of the PARSETs are equal to a different peaking time. Do discover what peaking times are available for the selected FiPPI, use the following code:

int status;

int i;

double *peakingTimes = NULL;


/* Read out number of peaking times to pre-allocate peaking time array */

status = xiaBoardOperation(0, "get_number_pt_per_fippi", &numberPeakingTimes);

CHECK_ERROR(status);


peakingTimes = (double *)malloc(numberPeakingTimes * sizeof(double));

CHECK_MEM(peakingTimes);


status = xiaBoardOperation(0, "get_current_peaking_times", peakingTimes);

CHECK_ERROR(status);


/* Print out the current peaking times */


for (i = 0; i < MAX_PTS; i++) {

printf("peaking time %d = %lf\n", i, peakingTimes[i]);

}


free(peakingTimes);

 

where i corresponds to the PARSET responsible for that peaking time. To switch to peaking time/PARSET i, simply do:

double parset = (double)i;

status = xiaSetAcquisitionValues(0, "parset", (void *)&parset);

CHECK_ERROR(status);

Controlling the MCA

Once the microDXP is properly configured, it is ready to begin data acquisition tasks. This section discusses starting a run, stopping a run, reading out the MCA spectrum and, lastly, configuring the microDXP for preset length runs.

Starting and Stopping a Run

The Handel interface to starting and stopping the run are two simple routines: xiaStartRun() and xiaStopRun(). Both routines require a detector channel number (like xiaSetAcquisitionValues()) as their first argument, while xiaStartRun() also requires an unsigned short that determines if the MCA is to be cleared when the run is started. To start a run with the MCA cleared, run for 5 seconds and then stop the run, the following code may be used:

int status;

unsigned short clearMCA = 0;

 

status = xiaStartRun(0, clearMCA);

CHECK_ERROR(status);

/* Windows API call. You can use whatever routine is available on your platform to wait. */

Sleep((DWORD)5000);

status = xiaStopRun(0);

CHECK_ERROR(status);

 

NOTE
For historical reasons, Handel and the microDXP RS-232 command for starting a run have a different idea of how to interpret the clear MCA value. The RS-232 command uses 0 to mean "resume run" and 1 to mean "clear the MCA". Handel uses 0 to mean "clear the MCA" and 1 to mean "resume run".

 

Reading out the MCA Spectrum

Assuming that we are still running with FiPPI 0 and the PARSET 0 configuration from the previous section, we know that our MCA spectrum length is 4096. In order to reduce the number of bytes that have to be sent across the serial port connection, you can request either 1, 2, or 3 bytes per bin. The default setting in Handel is 3 bytes per bin, which is the same as the raw value stored in the DSP's memory. If you want to use 3 bytes per bin then you do not have to change anything. If you want to only return a single byte per bin, then use the following code:

double bytesPerBin = 1.0;

 

status = xiaSetAcquisitionValues(0, "bytes_per_bin", (void *)&bytesPerBin);

CHECK_ERROR(status);

 

CAUTION
If the number of counts in a bin exceeds the requested bytes per bin, the microDXP does not return an error. For example, if there are 0xADCDEF counts in a bin and you read out the MCA spectrum with bytes per bin set to 1, that bin will return 0xEF!

With the bytes per bin configured correctly, we are now ready to read out the MCA spectrum.

unsigned long mca[4096];

 

status = xiaGetRunData(0, "mca", (void *)mca);

CHECK_ERROR(status);

Preset Length runs

The microDXP supports preset runs, which allow you to specify that a run stop automatically after a certain amount of time has passed or other criteria have been met. The four types of preset runs are fixed livetime, fixed realtime, fixed output counts and fixed input counts. A fixed livetime run will execute until the specified amount of livetime has elapsed. Similarly, a fixed realtime run will execute until the specified amount of realtime has elapsed. The fixed input and output count runs continue until the requested number of counts have occured.

The following is an example of setting a fixed realtime run for 5 seconds, including how to poll the device waiting for the run to complete:

int status;

double realtime = 5.0;

double realtimeType = XIA_PRESET_FIXED_REALTIME;

double presetData[2];

unsigned short clearMCA = 0;

unsigned short runActive;

 

presetData[0] = realtimeType;

presetData[1] = realtime;

status = xiaBoardOperation(0, "set_preset", (void *)presetData);

CHECK_ERROR(status);

status = xiaStartRun(0, clearMCA);

CHECK_ERROR(status);

do {

    Sleep((DWORD)1);

    status = xiaGetRunData(0, "run_active", (void *)&runActive);

    CHECK_ERROR(status);

} while (runActive);

/* Once the run is no longer active, we know that the preset run has completed and that it is safe to stop the run. */

status = xiaStopRun(0);

CHECK_ERROR(status);

/* Read out the spectrum, etc. */

Firmware Upgrades

Upgrades to the microDXP firmware are distributed as XIA Upgrade Package (XUP) files. Handel has a set of routines that know how to decode and download these packages to the hardware. There are some important items to note about the upgrade process:

  • It makes a backup of the I2C and Flash memory.
  • It can take a while for the upgrade to complete.

To download an XUP to the microDXP, use the following code:

int status;

char *xupFile = "firmware.xup";

 

status = xiaBoardOperation(0, "download_xup", (void *)xupFile);

CHECK_ERROR(status);

If you want to exercise more control over where the backup files are stored, you can do the following before downloading the XUP:

int status;

char *xupBackupPath = "c:\\temp";

 

status = xiaBoardOperation(0, "set_xup_backup_path", (void *)xupBackupPath);

CHECK_ERROR(status);

Cleaning Up

Before exiting Handel, call xiaExit() to safely shutdown the serial port driver:

int status;

 

status = xiaExit();

CHECK_ERROR(status);

Appendix A -- Acquisition Values List

Below is a list of all of the supported acquisition values for the microDXP. All of the acquisition values are of type double.

  • parset: The current PARSET.
  • genset: The current GENSET.
  • clock_speed: The digitizing clock in MHz. This value will be rounded to the nearest setting supported by the hardware, which is either DSPCLK, DSPCLK/2, DSPCLK/4 or DSPCLK/8. Not all selections are available on all hardware.
  • energy_gap_time: The gap time of the energy filter, specified in µs.
  • trigger_peak_time: The peaking time of the trigger filter, specified in µs.
  • trigger_gap_time: The gap time of the trigger filter, specified in µs.
  • baseline_length: The number of samples averaged together for the baseline filter.
  • trigger_threshold: Trigger filter threshold in arbitrary units.
  • baseline_threshold: Baseline filter threshold in arbitrary units.
  • energy_threshold: Energy filter threshold in arbitrary units.
  • number_mca_channels: The number of bins in the MCA spectrum, defined in bins.
  • mca_bin_width: Width of an individual bin in the MCA, using the "custom" width specified in the RS-232 Command Reference.
  • fippi: The current FiPPI.
  • bytes_per_bin: The number of bytes returned per bin when reading out the MCA spectrum. Can be either 1, 2 or 3 bytes.
  • adc_trace_wait: When acquiring an ADC trace for readout, the amount of time to wait between ADC samples, specified in µs.
  • gain: The base gain in arbitrary units.
  • polarity: The detector preamplifier polarity, where the allowed values are 0 = negative and 1 = positive.
  • preamp_value: Either the reset interval, for reset-type preamplifiers, or the decay time, for RC feedback-type detectors. The reset interval is specified in µs and the decay time is specified in terms of the digitization clock period.
  • gain_trim: Adjusts the base gain per PARSET, specified in arbitrary units.
  • peak_interval: The value of PEAKINT, specified in µs. Deprecated in v1.2.2.
  • peak_interval_offset: The peak interval specified as an offset from the peaking time and gap time, specified in µs. Effectively sets PEAKINT = SLOWLEN + SLOWGAP + peak_interval_offset. Added in v1.2.2.
  • peak_sample: The value of PEAKSAM, specified in µs. Deprecated in v1.2.2.
  • peak_sample_offset: Energy filter sampling time measured backward from the peaking time and gap time, specified in µs. Effectively sets PEAKSAM = SLOWLEN + SLOWGAP - peak_sample_offset. Added in v1.2.2.
  • max_width: The value of MAXWIDTH, specified in µs.
  • peak_mode: The value of PEAKINT, Sets the value of PEAKMODE to "Peak-Sensing" (PEAKMODE=0) or "Peak-Sampling" (PEAKMODE=1)Added in v1.2.2.

Appendix B -- Run Data List

These are the different types of run data that can be read using xiaGetRunData(). The C type of the run data is printed in italics after the name.

  • mca_length (unsigned long): The number of bins in the MCA spectrum.
  • mca (unsigned long *): The MCA spectrum.
  • livetime (double): The calculated energy filter livetime, reported in seconds.
  • runtime (double): The runtime, reported in seconds.
  • input_count_rate (double): The measured input count rate, reported as counts / second.
  • output_count_rate (double): The output count rate, reported as counts / second.
  • events_in_run (unsigned long): The total number of events in the current run.
  • triggers (unsigned long): The number of input triggers in the current run.
  • baseline_length (unsigned long): The current size of the baseline histogram buffer.
  • baseline (unsigned long *): The baseline histogram.
  • run_active (unsigned short): The current state of the processor: a 1 means that a run is currently active, a 0 means that no run is active.
  • all_statistics (double[6]) Returns an array of the six statistics available for the microDXP: livetime, runtime, triggers, events in run, input count rate and output count rate.

Appendix C -- Board Operations List

The allowed board operations for the microDXP, accessed via. xiaBoardOperation(). If no C type is specifed after the operation, a dummy, non-NULL value must be passed into the value argument.

  • get_serial_number (char[16]): Get the microDXP board's serial number.
  • get_peaking_time_ranges (double *): Returns an array of doubles with size (# of FiPPIs * 2). For each FiPPI the shortest peaking time and longest peaking time are returned, in that order.
  • get_number_of_fippis (unsigned short): Gets the number of FiPPIs that are on the board.
  • get_current_peaking_times (double[5]): Get the current peaking times for the selected FiPPI, where the peaking time at index i in the returned list corresponds to PARSET i for the selected FiPPI.
  • get_history_sector: Advanced operation.
  • get_temperature (double): Returns the current temperature of the board, accurate to 1/16th of a degree of Celsius.
  • download_xup (char *): Download the specified XUP file to the board.
  • apply: Applies the current DSP parameter settings to the hardware. This should be done after modifying any acquisition values.
  • save_parset (unsigned short): Saves the current DSP parameter settings to the specified PARSET.
  • save_genset (unsigned short): Saves the current DSP parameter settings to the specified GENSET.
  • set_preset (double[2]): Configure a preset run by passing in the preset type and value. The allowed types, defined in handel_constants.h are XIA_PRESET_FIXED_REALTIME, XIA_PRESET_FIXED_LIVETIME, XIA_PRESET_FIXED_TRIGGERS, XIA_PRESET_FIXED_EVENTS. The values are defined as time in seconds, for the time based runs and counts for the other types.
  • get_board_info (unsigned char[26]): Returns the array of board information listed in command 0x49 of the RS-232 Command Reference.
  • get_preamp_type (unsigned short): Returns the current preamplifier type, where 0 = reset and 1 = RC feedback.
  • set_xup_backup_path (char *): Sets the path where XUP backups are written.
  • get_hardware_status (unsigned char[5]): Returns the array of status information listed in command 0x4B of the RS-232 Command Reference.
  • create_master_param_set: Advanced operation.
  • backup: Advanced operation.

Appendix D -- PARSET/Acquisition Value Mapping

Shows the mapping from PARSET parameter to Handel acquisition value. Note that not all PARSET parameters can or need to be changed from Handel and therefore do not have a corresponding acquisition value. Some PARSET values are sensitive to the currently loaded GENSET and store one value for each GENSET. As a Handel user, you only need to worry about setting the value; the microDXP manages the per-GENSET values automatically.

 

PARSET name Acquisition value name Description
NUMPARSET N/A The number of parameters in PARSET excluding NUMPARSET and PARVERSION.
PARVERSION N/A The version of the PARSET.
BINSCALEXP N/A  
BINSCALE N/A  
FIPSCALE N/A  
BLFILTER baseline_length The length of the baseline filter.
SLOWLEN N/A The length of the "slow" or energy filter. This value combined with the decimation of the FiPPI this PARSET is a part of determines the peaking time.
SLOWGAP energy_gap_time The size of the "slow" or energy filter gap.
PEAKINT peak_interval FiPPI setting
FASTLEN trigger_peak_time The length of the "fast" or trigger filter.
FASTGAP trigger_gap_time The size of the "fast" or trigger filter gap.
THRESHOLD trigger_threshold The threshold for the "fast" or trigger filter.
MINWIDTH N/A  
MAXWIDTH max_width FiPPI setting
SLOWTHRESH energy_threshold The threshold for the "slow" or energy filter.
BASETHRESH baseline_threshold The threshold for the baseline filter.
BASTHRADJ N/A  
PEAKSAM peak_sample FiPPI setting
GAINTWEAK0-4 gain_trim Adjusts the gain for this specific combination of PARSET and GENSET.
THRESHOLD0-4 trigger_threshold The trigger threshold for this specific combination of PARSET and GENSET.
BASETHRESH0-4 baseline_threshold The baseline threshold for this specific combination of PARSET and GENSET.
SLOWTHRESH0-4 energy_threshold The energy threshold for this specific combination of PARSET and GENSET.

Appendix E -- GENSET/Acquisition Value Mapping

 

GENSET name Acquisition value name Description
NUMGENSET N/A The number of parameters in GENSET excluding NUMGENSET and GENVERSION.
GENVERSION N/A The version of the GENSET.
MCALEN number_mca_channels The number of channels in the MCA spectrum.
MCALIMLO N/A  
MCALIMHI N/A  
BASEBINNING N/A  
BLCUT N/A  
BINMULTIPLE N/A  
BINGRANULAR mca_bin_width MCA bin width granularity.
GAINBASE gain The base gain setting.

Appendix F -- GLOBSET/Acquisition Value Mapping

 

GLOBSET name Acquisition value name Description
NUMGLOBSET N/A The number of parameters in GLOBSET excluding NUMGLOBSET and GLOBVERSION.
GLOBVERSION N/A The version of the GLOBSET.
POLARITY polarity Detector preamplifier polarity.
RUNTASKS N/A  
FIPCONTROL N/A  
PRESETLENLO/PRESETLENHI N/A Controlled via set_preset board operation.
PRESET N/A Controlled xia set_preset board operation.
RESETINT preamp_value Reset interval for reset-type preamplifiers.
TAURC preamp_value Decay time for RC feedback-type preamplifiers.
IDLEMODE N/A  
IDLEDELAY N/A  
SLEEPMODE N/A  
TRACEWAIT N/A  
STATSMODE N/A