Addi-Pack Samples
Overview
This section contains detailed explanations of every Addi-Pack sample program provided with Addi-Pack. Samples are provided in C, C++, and Python, and demonstrate how to interact with ADDI-DATA cards through the API in both interactive and automated ways.
Each sample:
Is interactive by default (if no command-line arguments are provided),
Can also be run in fully scripted or automated mode using command-line options,
Is designed to be a complete, working program ready to build and execute.
Sample Utilities
Goal
Provide common functions used by all samples. Such as user prompts, argument parsing, device selection, and interrupt handling.
These utilities form the foundation of all Addi-Pack samples.
The SampleUtils and ArgParser modules have distinct responsibilities:
ArgParser Provides the command-line argument interface used by the samples. It handles: - parsing options such as
--mode=interruptor--card=apcie1032, - checking whether an option or flag is present, - retrieving option values (e.g.--timebase ms), - validating argument syntax.SampleUtils Implements all interactive behaviour of the samples. It is responsible for: - deciding whether to run in scripted or interactive mode (based on whether an option is set), - prompting the user when an argument is missing or invalid, - selecting a device according to capabilities, - selecting modes, - validating numeric and hexadecimal parameters, - helper utilities (interrupt callback, timing helpers, exit helpers, etc.).
Together, these modules allow each sample to support both automated command-line execution and interactive question-based execution. They are not part of the public API, but they can be reused for rapid prototyping.
Tip
Even though ArgParser is technically a private helper, you can safely use it in your own C/C++ projects to build interactive CLI tools consistent with the official samples.
Using it has several benefits:
No external dependency: the parser is fully embedded in Addi-Pack and does not require any third-party library.
Cross-platform behavior: the same command-line arguments work identically on Windows and Linux.
Consistent user experience: your tools behave exactly like the official samples (same options, same style, same error handling).
Faster prototyping: no need to implement argument parsing, validation or help messages yourself.
Reliable and tested: the parser is used internally by all ADDI-DATA samples, ensuring stable behavior.
Key Concepts
Interactive vs Non-Interactive Mode
If the user passes options (e.g. –reload=1000 –mode=polling), the sample runs automatically.
Otherwise, prompts are displayed dynamically to ask for missing parameters.
Automatic Device Selection
The function AddiDataUtilsSelectDeviceByCapability() filters all detected devices and selects one based on user input or CLI arguments.
Input Validation
Utilities like AddiDataUtilsGetValidInt() or AddiDataUtilsGetValidString() ensure that all parameters are valid before starting the test or operation.
Interrupt Management
Functions such as AddiDataUtilsInterruptCallback() and AddiDataUtilsHasInterruptHappened() are shared across interrupt-based samples.
C Utilities
Main header:
#include <addi-data/addi-pack/utilities/sample_utils.h>
Below are the main utility functions available in C samples:
Function |
Purpose |
|---|---|
AddiDataUtilsPromptString() |
Prompt the user for a string, with optional accepted values and default. |
AddiDataUtilsPromptInt() |
Prompt the user for an integer within a specified range [min, max]. |
AddiDataUtilsPromptHex() |
Prompt the user for a hexadecimal value within a specified range [min, max]. |
AddiDataUtilsGetValidString() |
Get a validated string from CLI args or fallback to prompt. |
AddiDataUtilsGetValidInt() |
Get a validated integer from CLI args or fallback to prompt. |
AddiDataUtilsGetValidHex() |
Get a validated hexadecimal value from CLI args or fallback to prompt. |
AddiDataUtilsMatchesCardFilter() |
Check whether a device matches a card filter string. |
AddiDataUtilsSelectDeviceByCapability() |
Select a device matching a predicate from a list of devices. |
AddiDataUtilsSelectMode() |
Select a string mode from a list, using CLI –<name> or prompt. |
AddiDataUtilsParseTimebase() |
Convert a timebase string (“us”, “ms”, “s”) into a TIMEBASE_UNITS enum value. |
AddiDataUtilsInterruptCallback() |
Default interrupt handler that logs the source, mask, and elapsed time since the last interrupt. |
AddiDataUtilsResetInterruptFlag() |
Reset the interrupt flag and internal timer. |
AddiDataUtilsHasInterruptHappened() |
Check whether an interrupt has occurred since the last reset. |
AddiDataUtilsExitOnUserInput() |
Wait for the user to press ENTER and exit the program. |
AddiDataUtilsPrintAvailableTcwOptions() |
Print a list of available TCW (Timer-Counter-Watchdog) options supported by the device. |
AddiDataUtilsGetTcwOptionsFromUser() |
Prompt the user to select TCW options interactively. |
AddiDataUtilsGetValidTimebaseList() |
Get a list of valid timebases supported by the device. |
AddiDataUtilsDisplayAllPortsConfigurations() |
Display the configuration (input/output) of all digital ports. |
Example – Using the utilities in C
// Used to filter cards with at least one timer
int hasTimer(const AddiDataDeviceStruct* device) { return device->functions.timer.number_timers > 0; }
// Initialise the argument parser
AddiDataArgParserInit();
AddiDataArgParserAddOption("card", 'c', "Filter by card name", 1);
AddiDataArgParserAddOption("reload", 'r', "Reload value", 1);
AddiDataArgParserParse(argc, argv);
// Get the number of available devices
uint8_t number_of_cards = 0;
AddiDataGetNumberOfDevices(&number_of_cards)
// Allocate and populate the device list
AddiDataDeviceStruct* devices = malloc(sizeof(AddiDataDeviceStruct) * number_of_cards);
AddiDataGetDeviceList(devices);
// Select a device with at least one timer
const AddiDataDeviceStruct* device = AddiDataUtilsSelectDeviceByCapability(devices, number_of_cards, "card", hasTimer, "timer");
// Get a valid reload value from command-line or prompt
int reload = AddiDataUtilsGetValidInt("reload", "Enter reload value", 1, 10000);
// Display selected card and reload value
printf("Using %s | Reload = %d\n", device->general.product_name, reload);
C++ Utilities
In C++, the same utilities are provided via wrappers and helper classes.
Example – Using ArgParser and SampleUtils in C++
#include <addi-data/addi-pack/cpp/sample_utils.hpp>
#include <addi-data/addi-pack/cpp/timer_interface.hpp>
using namespace addidata;
using namespace addipack;
using namespace utils;
bool hasTimer(const std::shared_ptr<Device>& device) {
return device->getDeviceInformation().functions.timer.number_timers > 0;
}
int main(int argc, char* argv[]) {
ArgParser::init();
ArgParser::addOption("card", 'c', "Filter by card name");
ArgParser::addOption("reload", 'r', "Reload value");
ArgParser::parse(argc, argv);
auto devices = DeviceDiscovery::getDeviceList();
auto device = selectDeviceByCapability(devices, "card", hasTimer, "timer");
int reload = getValidInt("reload", "Enter reload value", 1, 10000);
std::cout << "Selected device: " << device->getDeviceInformation().id << " | Reload = " << reload << std::endl;
}
Python Utilities
Example – Using SampleUtils in Python
from sample_utils import *
def has_timer(device):
return device.get_card_information().functions.timer.number_timers > 0
def parse_args():
parser = argparse.ArgumentParser(description="example")
parser.add_argument("-c", "--card", help="Filter device by name (apcie1032, apci1500 ...)")
parser.add_argument("-r", "--reload", type=int, help="Reload value")
return parser.parse_args()
def main():
args = parse_args()
device = select_device_by_capability(args.card, has_timer, "timer")
info = device.get_card_information()
reload_value = get_valid_int(args.reload, "reload", 1, 10000)
print(f"Selected {info.id} with reload={reload_value}")
get_devices_info
Goal
List all detected ADDI-DATA cards connected to the system and display their detailed properties.
This is the first sample to run after installation, as it verifies that:
The Addi-Pack drivers are correctly installed,
The API can communicate with the hardware,
Cards are properly enumerated and accessible.
This sample calls the core device discovery functions:
AddiDataGetNumberOfDevices() → returns the number of cards detected
AddiDataGetDeviceList() → fills a list of AddiDataDeviceStruct entries
It then prints for each card:
Product name and type (PCI or PCIe)
Bus information (bus, slot, vendor and device IDs)
Function capabilities (digital I/O, timers, counters, watchdogs)
Interrupt number and BAR addresses
The user can filter cards interactively (by name, type, or model) or directly using a command-line argument such as –card=apcie1032.
Key Features
Dynamic card detection
Enumerates all ADDI-DATA devices automatically, regardless of model.
Flexible filtering
–card=apcie → lists only PCIe cards
–card=apci → lists only PCI cards
–card=1032 → lists only 1032 cards
Automatic behavior
If only one card is found, it’s automatically selected.
If multiple cards are found, the user can choose or filter interactively.
Cross-platform output
Works identically on Windows and Linux, and displays unified information.
Example Usage
Interactive mode (default):
./get_device_info
One device found. Automatically selecting it.
========= Device 0 (apcie-1032) =========
Product Name: APCIe-1032
Bus: 3 | Device: 0 | Vendor ID: 0x15B8 | Device ID: 0x1032
Interrupt: 17 | Bus Type: PCIe
Digital Inputs: 32 | Outputs: 0 | Ports: 1 | Mask: 0xFFFF
Timers: 0 | Counters: 0 | Watchdogs: 0
Filtered mode:
./get_device_info --card=apci1500
It displays only matching cards (here apci1500).
digital_input
Goal
Read digital input channels in polling or interrupt mode.
This sample demonstrates how to acquire input states from ADDI-DATA cards, either by continuously reading the lines or by waiting for hardware events.
Concept and Purpose
The digital_input sample is designed to validate input acquisition and interrupt configuration on any card supporting digital inputs.
It serves both as:
A functional test, confirming that inputs toggle and can trigger events.
A reference implementation, showing how to configure edge detection, logic, and masks.
The sample operates in two distinct modes:
read → polling mode: the application continuously reads and displays input states.
interrupt → event-driven mode: the program waits for hardware-triggered input changes.
Execution Workflow
Device detection and selection
The sample first detects all installed ADDI-DATA cards with input capability using AddiDataUtilsSelectDeviceByCapability(). If multiple compatible cards are found, the user can select one interactively or provide it via the command line (e.g. –card=apcie1032).
Mode selection
The user chooses between:
read mode → constant polling,
interrupt mode → asynchronous event handling.
This can be specified via –mode= or through an interactive prompt.
Configuration phase (interrupt mode)
When running in interrupt mode, several parameters are configured:
Port index (–port): selects which input port to monitor.
Interrupt mask (–mask): selects which input bits trigger events.
Event type (–event): rising/falling/any edge or level-based detection.
Logic (–logic): whether multiple active inputs combine with OR or AND.
The sample validates all these parameters and applying interactive prompts as needed.
Runtime phase
In read mode, the sample prints live input states in binary form. The screen is refreshed continuously until the user presses ENTER.
In interrupt mode, the sample:
Registers the default interrupt callback AddiDataUtilsInterruptCallback.
Enables device and digital interrupts.
Prints a message every time an interrupt occurs, including:
the source,
the input mask,
and the elapsed time since the previous interrupt.
Termination
When the user presses ENTER, the sample:
Disables all interrupt sources,
Restores device state,
Frees allocated resources,
And exits cleanly.
Runtime Behavior
In read mode: - The program polls all input lines periodically (every 100 ms by default). - Values are printed as a live binary bit field:
- Example output:
Inputs: 0000000000001111
Press ENTER to stop reading.
In interrupt mode: - The card triggers an interrupt whenever the configured event occurs on one of the selected bits. - Each interrupt produces a console message such as:
[INTERRUPT] Callback: source=0x02 | mask=0x0004 | elapsed=12.45 ms
The elapsed field measures the delay between consecutive events, helping assess response time and signal stability.
digital_output
Goal
Control and test digital output lines on ADDI-DATA cards, either individually or as a group.
This sample demonstrates how to write digital output values using the Addi-Pack API, in both interactive and scripted (CLI) modes.
Concept and Purpose
The digital_output sample is designed to validate the correct functioning of the digital outputs on any compatible card. It allows developers or test engineers to quickly verify that all output lines can be toggled as expected.
It provides two complementary operating modes:
single mode: interactively set individual output channels one by one.
mask mode: apply a bitmask to modify multiple outputs simultaneously.
interrupt mode: monitor hardware fault events on digital outputs
Execution Workflow
Device detection and selection
The sample first detects all installed ADDI-DATA devices using AddiDataUtilsSelectDeviceByCapability(), filtering only those with output capability. If several compatible cards are present, the user can choose interactively or provide a –card filter (e.g. –card=apci1564).
Mode selection
The user selects between:
single → manually set each output line.
mask → apply one value to all lines defined by a bitmask.
interrupt → enable and monitor on digital output interrupts.
This can be done interactively or using –mode=single / –mode=mask.
Configuration phase
Depending on the chosen mode, the sample requests or parses additional parameters:
Mode = single
Channel index to modify (0 → number_outputs - 1)
Output value to write (0 or 1)
Mode = mask
Output mask (–mask=0xFF): defines which bits to affect
Value (–value=0 or –value=1): sets all selected outputs high or low
Mode = interrupt
Output interrupt mask (–mask):
Bit 0x01 → enable VCC (power supply failure) interrupt
Bit 0x02 → enable CC (short-circuit) interrupt
Output operation
For single mode, the program loops indefinitely, asking the user for a channel and a value until they press ENTER.
For mask mode, the selected mask is written once with the chosen value.
For interrupt mode, the program registers the default interrupt callback AddiDataUtilsInterruptCallback, enables device and output interrupts, and prints a message each time an interrupt occurs, including the source, mask, and elapsed time since the last event.
Termination
When finished, all resources are released, and the program exits cleanly after waiting for user confirmation.
Runtime Behavior
Single Mode (interactive control)
The user specifies one channel and a value (0 or 1).
The output state is immediately applied and confirmed in the console.
The loop continues until the user presses ENTER on an empty line.
Typical output:
Select output channel [0-15] (empty = quit): 3
Set value for this channel [0-1]: 1
Channel 3 set to 1
Select output channel [0-15] (empty = quit): 5
Set value for this channel [0-1]: 0
Channel 5 set to 0
Mask Mode (group operation)
The user defines a hexadecimal mask and a single value (0/1).
All output lines corresponding to bits set in the mask are updated simultaneously.
Example:
Enter output mask in hexadecimal (max 0xFFFF): 0x0F
Set value for the entire mask [0-1]: 1
Writing value 1 to mask 0x0F...
Digital outputs updated successfully.
In this example, the first four outputs (0–3) are set to logical 1.
digital_port
Goal
Configure and interact with digital I/O ports on ADDI-DATA cards.
- This sample demonstrates how to:
Discover devices and select one with digital I/O port capabilities
Configure port directions (input/output)
Read digital inputs from a port
Write digital outputs to a port using a mask
It is designed to be a complete, working program ready to build and execute.
Key Features
Device Discovery and Selection: The user can filter devices by name (e.g., “apci1696”) to find compatible hardware. The sample checks if the selected device has digital I/O ports.
Display Initial Configuration: The sample reads and displays the current direction and status of all digital ports. It shows which ports are configured as inputs or outputs and their current values.
Port Direction Configuration: The user can enter a hexadecimal mask to set the direction of all ports at once. For example, a mask of 0xF would set ports 0-3 as outputs and the rest as inputs.
Mode Selection: The user can choose between “display” mode to continuously show port statuses or “write” mode to set outputs. In “display” mode, the sample refreshes the port status every 200ms until the user presses ENTER. In “write” mode, the user selects a specific output port and provides a mask and value to set the outputs.
Workflow
Device Discovery & Selection: - The user can filter devices by name (e.g., “apci1696”) to find compatible hardware. - The sample checks if the selected device has digital I/O ports.
Display Initial Configuration: - The sample reads and displays the current direction and status of all digital ports. - It shows which ports are configured as inputs or outputs and their current values.
Port Direction Configuration: - The user can enter a hexadecimal mask to set the direction of all ports at once. - For example, a mask of 0xF would set ports 0-3 as outputs and the rest as inputs.
Mode Selection: - The user can choose between “display” mode to continuously show port statuses or “write” mode to set outputs. - In “display” mode, the sample refreshes the port status every 200ms until the user presses ENTER. - In “write” mode, the user selects a specific output port and provides a mask and value to set the outputs.
timer
Goal
Initialise, start, and read hardware timers in polling or interrupt mode.
This sample demonstrates how to configure and operate hardware timers available on ADDI-DATA cards, using both continuous polling and event-driven (interrupt) approaches.
Concept and Purpose
The timer sample is designed to validate the timer subsystem of ADDI-DATA cards. It shows how to configure timebases, reload values, and operational options dynamically, with support for both standard and interrupt-driven operation.
It serves as both a reference implementation and a diagnostic tool for timing features on cards such as:
APCI-1500 / APCIe-1500
APCI-1564 / APCIe-1564
APCIe-1032
The timer is typically used for periodic events, time measurements, or watchdog triggers.
Execution Workflow
Device detection and selection
The program enumerates all installed cards and filters those with timer capability using AddiDataUtilsSelectDeviceByCapability(). If multiple cards are detected, the user can select one interactively or specify it through –card=<name>.
Mode selection
Two operating modes are available:
polling → the sample periodically reads and prints the timer status.
interrupt → the program waits for timer expiration events, notified by hardware interrupts.
This can be set interactively or by passing –mode=polling or –mode=interrupt.
Timer configuration
Once the device and mode are selected, the program interactively requests or parses:
Timer index (–timer): which timer to configure. Most cards have multiple independent timers (e.g. 3 on the APCI-1500).
Timebase (–timebase): defines the unit for reload timing — microseconds (us), milliseconds (ms), or seconds (s).
Reload value (–reload): defines the countdown duration before expiration. The maximum value depends on the card and the timebase.
Timer options: optional configuration flags such as continuous or single-shot operation, retrieved via AddiDataUtilsGetTcwOptionsFromUser().
Initialization and startup
The timer is configured and started in three steps:
AddiDataInitTimer() → apply configuration (index, timebase, reload, options)
AddiDataTriggerTimer() → trigger initial value
AddiDataStartTimer() → start periodic operation
When interrupt mode is selected, the program also registers the default callback AddiDataUtilsInterruptCallback and enables timer interrupts via:
AddiDataEnableDeviceInterrupts()
AddiDataEnableTimerInterrupt()
Runtime phase
In polling mode, the program repeatedly calls AddiDataReadTimerStatus() to display: - current value, - status flag, - trigger state.
In interrupt mode, messages are printed each time the timer interrupt fires, including timestamps and elapsed times.
Termination
When the user presses ENTER, the timer is stopped and interrupts are disabled. The program then frees allocated memory and exits cleanly.
Runtime Behavior
Polling mode:
Displays live timer countdown values every 100 ms.
Example output:
Timer: value=487 | status=1 | triggered=0 | expired=0 Timer: value=238 | status=1 | triggered=0 | expired=0
The display refreshes until ENTER is pressed.
Interrupt mode:
The card raises a hardware interrupt each time the timer expires.
The registered callback prints timing information such as:
[INTERRUPT] Timer event received | ID=0 | elapsed=100.03 ms
The user can observe event frequency and verify timing accuracy.
counter
Goal
Initialise, start, and read hardware counters in polling or interrupt mode.
This sample demonstrates how to configure and operate hardware counters available on ADDI-DATA cards, for tasks such as event counting, frequency measurement, or pulse detection.
Concept and Purpose
The counter sample is designed to validate and illustrate the behavior of hardware counters on ADDI-DATA cards. It shows how to configure reload values, counting modes, and options, while supporting both continuous polling and interrupt-driven operations.
It serves as a reference implementation for developers and testers working on:
Counting external pulses or encoder signals,
Measuring frequencies or durations,
Detecting input edges and generating interrupts on threshold events.
Supported cards include (but are not limited to):
APCI-1500 / APCIe-1500
APCI-1564 / APCIe-1564
Execution Workflow
Device detection and selection
The sample detects all installed ADDI-DATA cards and filters those supporting counters using AddiDataUtilsSelectDeviceByCapability().
The user can then select the desired device interactively or provide a filter via –card (e.g. –card=apcie1564).
Mode selection
The program offers two operation modes:
polling → continuously read and print counter values.
interrupt → wait for counter overflow or event-driven notifications.
The mode can be selected through –mode= or via an interactive menu.
Counter configuration
Once the mode is chosen, the program requests the following parameters:
Counter index (–counter): selects which hardware counter to use. Some cards (e.g. APCI-1500) have multiple counters (typically 3).
Reload value (–reload): defines the threshold after which the counter resets or triggers an interrupt.
Counter options: retrieved interactively via AddiDataUtilsGetTcwOptionsFromUser(), allowing configuration such as counting direction or gate control.
Initialization and startup
The counter is configured and started in three steps:
AddiDataInitCounter() → apply reload value and mode options.
AddiDataStartCounter() → enable counting.
Optionally, AddiDataEnableCounterInterrupt() and AddiDataSetDeviceInterruptCallback() if interrupt mode is selected.
When interrupts are used, the callback AddiDataUtilsInterruptCallback prints timestamped events each time a counter interrupt occurs (e.g. overflow or external trigger).
Runtime phase
In polling mode, the program continuously calls AddiDataReadCounterStatus() to display: - the current count value, - the counter status flag, - and the trigger state.
In interrupt mode, the program remains idle until hardware events trigger an interrupt.
Termination
On user input (press ENTER), the counter is stopped, interrupts are disabled, and all resources are released before the program exits.
Runtime Behavior
Polling mode:
The current counter value is printed at regular intervals (100 ms by default).
Example output:
Counter: value=52 | status=1 | triggered=0 | expired=0 Counter: value=103 | status=1 | triggered=0 | expired=0
This mode is useful for verifying real-time increments when an external signal (pulse train) is applied.
Interrupt mode:
The card raises a hardware interrupt when the counter reaches its reload value or an event condition.
The callback prints messages such as:
[INTERRUPT] Counter event | ID=1 | elapsed=250.12 ms
This helps evaluate signal stability and interrupt timing precision.
watchdog
Goal
Configure and test the hardware watchdog mechanism available on ADDI-DATA cards.
This sample demonstrates how to initialise, start, trigger, and observe watchdog expiration events. It validates both interrupt handling and system safety behavior using the Addi-Pack API.
Concept and Purpose
The watchdog sample is designed to verify that the hardware watchdog correctly monitors system activity and generates interrupts when it is not regularly triggered.
A watchdog is a safety timer that resets or signals the system if it is not “fed” (triggered) within a defined period. This mechanism is crucial for ensuring system reliability in industrial environments.
This sample shows how to:
Configure watchdog parameters (timebase, reload value, options),
Trigger it periodically (software “kick”),
Detect expiration events via interrupts.
Supported cards include (depending on model and firmware):
APCI-1500 / APCIe-1500
APCI-1564 / APCIe-1564
Execution Workflow
Device detection and selection
The sample enumerates all installed devices and filters those with watchdog capability using AddiDataUtilsSelectDeviceByCapability().
The user can specify a card via –card=<name> or select interactively.
Watchdog configuration
The user specifies:
Watchdog index (–watchdog): ID of the watchdog to configure.
Timebase (–timebase): us, ms, or s for microsecond, millisecond, or second precision.
Reload value (–reload): defines the duration before expiration (e.g., 500 ms or 10 s).
Additional options are set through AddiDataUtilsGetTcwOptionsFromUser(), allowing configuration of continuous cycle or hardware gate modes.
Initialization phase
The watchdog is initialized via AddiDataInitWatchdog(). Device and watchdog interrupts are enabled with:
AddiDataEnableDeviceInterrupts()
AddiDataEnableWatchdogInterrupt()
A default callback (AddiDataUtilsInterruptCallback) is registered to report expiration events.
For visual verification, all digital outputs are set high (AddiDataWriteAllDigitalOutputs(…, 1)) so that they toggle on watchdog events.
Triggering and monitoring phase
The watchdog is started (AddiDataStartWatchdog()), then manually triggered three times by calling AddiDataTriggerWatchdog() with a 1-second delay between each call.
After the third trigger, the sample waits for the watchdog to expire naturally. When it does, an interrupt message is displayed, confirming proper expiration handling.
Termination
Once expiration is detected or the user presses ENTER, the program:
Stops the watchdog (AddiDataStopWatchdog()),
Disables interrupts,
Resets all outputs,
Frees resources and exits cleanly.
Runtime Behavior
Example console output:
Using card: apcie-1564
Watchdog will be triggered 3 times...
Triggering Watchdog [1/3]
Triggering Watchdog [2/3]
Triggering Watchdog [3/3]
Waiting for watchdog to expire...
[INTERRUPT] Watchdog event | ID=0 | elapsed=5000.12 ms
Watchdog expired. Press ENTER to exit...
The elapsed time shown corresponds to the time between the last trigger and the hardware expiration interrupt.
Card-Specific Notes
Some cards exhibit hardware-dependent behaviors that differ from the generic TCW (Timer/Counter/Watchdog) model. The following notes help avoid unexpected results during testing or integration.
APCI-1564 / APCIe-1564
A watchdog interrupt will not occur if you simply wait for expiration. One of the following must happen before expiration:
Trigger manually via
AddiDataTriggerWatchdog(),or set all digital outputs to
1usingAddiDataWriteAllDigitalOutputs().
Without one of these actions, the watchdog remains inactive, meaning no expiration and no interrupt.
Behavior varies depending on activation method:
Manual trigger → typically one interrupt on expiration.
Setting all outputs high → sometimes two interrupts (expiration + internal reset).
Note
These quirks are specific to the 1564 family and may vary slightly depending on firmware version. It is recommended to always perform either a trigger or output write before waiting for expiration on this card.
APCI-1500 / APCIe-1500
All three timers share the same timebase (µs, ms, s). Changing the timebase for one timer updates it for all timers.
To avoid unexpected timing mismatches, always configure the same timebase for every enabled timer on this card.
reload_valueremains independent per timer — only the timebase is global.
Note
This constraint applies to both timers and watchdog timing behavior on APCI-1500 family cards.
APCI-2032 / APCIe-2032
The watchdog has an attribute “has_expired”, which is set to true when the watchdog reaches 0.
PCI cards do not generate an interrupt on expiration; instead, the application must poll “has_expired” to detect expiration events.
APCI-2032 / APCIe-2032 are currently the only ADDI-DATA cards that support digital output interrupts (VCC / CC fault detection).
Interrupt Source Mapping
The meaning of interrupt_source bits is not universal across cards.
This means:
interrupt_source = 0x1does not necessarily mean the same thing on APCIx-1500, APCIx-1032 or APCIx-1564.Always refer to the card-specific interrupt handler and mapping table.
Typical examples by card:
APCI-1500 / APCIe-1500
0x01→ Port A interrupt
0x02→ Port B interrupt
0x04→ Timer 1 interrupt
0x08→ Timer 2 interrupt
0x10→ Timer 3 interrupt
0x20→ Watchdog interrupt
0x40/0x80→ Voltage / short-circuit faults
APCIe-1032
0x01→ DigitalInputEventLogic
0x04→ Timer interrupt (PCIe only)
APCI-1564 / APCIe-1564
0x01→ Digital Input Event Logic
0x02→ Digital Output interrupt
0x04→ Timer interrupt (per timer bitmask ininterrupt_mask)
0x08→ Counter interrupt (per counter bitmask ininterrupt_mask)
APCI-2032 / APCIe-2032
0x01→ Digital Output interrupt PCI
0x02→ Digital Output interrupt PCIe
0x04→ Watchdog interrupt