Counter Inputs
It is very simple to read a counter input with the help of the LIBAD4 library. Therefore the example opens the measurement system (ad_open
), then sets the operating mode (ad_set_counter_mode
) and after that reads the counter status (ad_discrete_in
). At last it closes the measurement system again (ad_close
). Evidently the measurement system would be opened just once at the start of the program and closed at the end in a real program. The operating mode of the counter needs to be set just once and not before every reading.
You will find the source code of the example in LIBAD4 SDK in the directory examples/counter (and in there in the according directories c, cs and vb for C/C++, C# and Visual Basic™.Net). Like all examples, this one does away with a proper error treatment due to simplicity of handling…
The example provides the routine do_counter() showing how to use the LIBAD4 functions ad_open(), ad_set_counter_mode(), ad_discrete_in() and ad_close(). The name of the measurement device (driver), running mode (mode), a flag for activating the reset line (enable_rst) and the numbers of the counting lines (chav) are passed to the routine. All arguments are retrieved from the command line in main(), are processed accordingly and then handed over to do_counter().
The first parameter on the command gets passed as driver and denotes the measurement system. For example "usb-oi16:@100" opens the USB-OI16 with the serial number 100. You will find detailed descriptions for the necessary names of the different measurement systems in the LIBAD4 manual in chapter 6, measurement systems.
This name will be passed on by do_counter() directly to ad_open(). The return value of ad_open() is a handle, that represents the opened measurement system and has to be returned to all functions of the LIBAD4. In case of an error-1 will be returned.
The parameter mode defines the operating mode and will be denoted in main() by the optional command line -counter (AD_CNT_COUNTER), -updown (AD_CNT_UPDOWN) or -quad (AD_CNT_QUAD_DECODER.This value defaults -1 and ensures that the operating mode is fixed.
main() fills the array chav[] by converting the remaining arguments of the command line to numbers. The function do_counter() denotes the operating mode of the counter in a loop across all channels. The variable par is to be assigned accordingly and to be passed on to ad_set_counter_mode. par.cha denotes the channel and par.mode the operating mode. The settings in par.mux_a as well as in par.mux_b regulate, which digital lines are connected to which counter inputs (for example fixed port A/1 and port A72). If -rst is stated on the command line, the reset input of the counter is activated. The example connects the reset (par.mux_rst) firmly with port A/3.
Then the current counter reading is ascertained by calling ad_discrete_in. The argument (adh) specifies the measurement system (as passed by ad_open()), the second argument specifies the channel (consisting the channel type AD_CHA_TYPE_COUNTER and channel number chav[i]) and the third argument specifies the measurement range (for counter channels always 0). The last argument data] passed, records the current counter reading. On error the function returns a non-zero error code. This error code corresponds to the host computer's operating system (for example in Windows an error number is returned from <winerror.h>).
The measurement system will be closed at the end of the loop ad_close().
LIBAD - Programming Interface (API)
/* Libad Counter Example
*
* Example showing how to setup counter mode and read counter value
* using bmcm's LIBAD4.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "libad.h"
/* Setup counter and read actual value.
*/
void
do_counter (const char *driver, int mode, int enable_rst, int chac, int chav[])
{
int32_t adh;
int i;
/* Open DAQ system.
*/
adh = ad_open (driver);
if (adh == -1)
{
printf ("failed to open %s: err = %d\n", driver, errno);
return;
}
/* Set counter mode and read actual value.
*/
for (i = 0; i < chac; i++)
{
struct ad_counter_mode par;
uint32_t data;
int rc;
if (mode != -1)
{
/* Setup counter mode, using Port A/1 and Port A/2 as
* both counter inputs. The counter's reset input
* gets connected to Port A/3 (if enabled).
*/
memset (&par, 0, sizeof(par));
par.cha = AD_CHA_TYPE_COUNTER | chav[i];
par.mode = mode;
par.mux_a = 0;
par.mux_b = 1;
if (enable_rst)
{
par.mux_rst = 2;
par.flags |= AD_CNT_ENABLE_RST;
}
rc = ad_set_counter_mode (adh, &par);
if (rc != 0)
{
printf ("error: failed to setup counter %d: err = %d\n", chav[i], rc);
return;
}
}
rc = ad_discrete_in (adh, AD_CHA_TYPE_COUNTER|1, 0, &data);
if (rc == 0)
printf ("counter %d: %d\n", chav[i], data);
else
printf ("error: failed to read counter %d: err = %d\n", chav[i], rc);
}
/* Close DAQ system again.
*/
ad_close (adh);
}
/* Show usage.
*/
void
usage ()
{
printf ("usage: counter <driver> [-counter|-updown|-quad] [-rst] <cha1> .. <chan>\n"
" <driver> string to pass to ad_open()\n"
" - will prompt for name\n"
" -counter configure counter mode\n"
" -updown configure up/down counter mode\n"
" -quad configure quad-decoder counter mode\n"
" -rst enable counter's reset input\n"
" <cha1..n> number of counter channel to (configure and) read\n");
}
/* Main entry point.
*/
int
main (int argc, char *argv[])
{
if (argc > 1)
{
char *name, *p, tmp[80];
int i, start, mode, enable_rst, chac, chav[16];
/* First command line argument is the DAQ's name.
* If "-" is passed, then let's read the name from
* the console.
*/
name = argv[1];
if (strcmp (argv[1], "-") == 0)
{
printf ("data acquisition system to open: ");
fgets (tmp, sizeof(tmp), stdin);
p = strchr (tmp, '\n');
if (p)
*p = 0;
name = tmp;
}
/* Counter mode defaults to -1 (i.e. do not configure), but
* may get overridden by command line.
*/
start = 2;
mode = -1;
enable_rst = 0;
while (argc > start)
{
if (strcmp (argv[start], "-counter") == 0)
{
mode = AD_CNT_COUNTER;
start++;
}
else if (strcmp (argv[start], "-updown") == 0)
{
mode = AD_CNT_UPDOWN;
start++;
}
else if (strcmp (argv[start], "-quad") == 0)
{
mode = AD_CNT_QUAD_DECODER;
start++;
}
else if (strcmp (argv[start], "-rst") == 0)
{
enable_rst = 1;
start++;
}
else
break;
}
/* Convert remaining command line arguments
* into numbers and add those to the channel array.
*/
chac = 0;
for (i = start; i < argc; i++)
{
chav[chac] = atoi (argv[i]);
chac++;
if (chac >= 16)
break;
}
/* Configure counter and read actual values, printing results
* to the console.
*/
do_counter (name, mode, enable_rst, chac, chav);
if (strcmp (argv[1], "-") == 0)
{
printf ("press return to continue...\n");
fgets (tmp, sizeof(tmp), stdin);
}
return 0;
}
else
{
usage ();
return 1;
}
}
// Libad Counter Example
//
// Example showing how to setup counter mode and read counter value
// using bmcm's LIBAD4.
using System;
using LIBAD4;
static class Example
{
// Setup counter and read actual value.
static void
do_counter (string driver, int mode, bool enable_rst, int[] chav)
{
// Open DAQ system.
int adh = LIBAD.ad_open (driver);
if (adh == -1)
{
Console.WriteLine ("failed to open {0}: err = {1}", driver, LIBAD.errno);
return;
}
// Set counter mode and read actual value.
for (int i = 0; i < chav.Length; i++)
{
uint data = 0;
int rc;
if (mode >= 0)
{
LIBAD.ad_counter_mode par;
/* Setup counter mode, using Port A/1 and Port A/2 as
* both counter inputs. The counter's reset input
* gets connected to Port A/3 (if enabled).
*/
par = new LIBAD.ad_counter_mode ();
par.cha = LIBAD.AD_CHA_TYPE_COUNTER | chav[i];
par.mode = (byte) (mode & 0xff);
par.mux_a = 0;
par.mux_b = 1;
if (enable_rst)
{
par.mux_rst = 2;
par.flags |= LIBAD.AD_CNT_ENABLE_RST;
}
rc = LIBAD.ad_set_counter_mode (adh, ref par);
if (rc != 0)
{
Console.WriteLine ("error: failed to setup counter %d: err = %d\n", chav[i], rc);
return;
}
}
rc = LIBAD.ad_discrete_in (adh, LIBAD.AD_CHA_TYPE_COUNTER | chav[i], 0, ref data);
if (rc == 0)
Console.WriteLine ("counter {0,2}: {1}", chav[i], data);
else
Console.WriteLine ("error: failed to write cha {0}: err = {1}", chav[i], rc);
}
// Close DAQ system again.
LIBAD.ad_close (adh);
}
// Show usage.
static void
usage ()
{
Console.WriteLine ("usage: counter <driver> [-counter|-updown|-quad] [-rst] <cha1> .. <chan>");
Console.WriteLine (" <driver> string to pass to ad_open()");
Console.WriteLine (" - will prompt for name");
Console.WriteLine (" -counter configure counter mode");
Console.WriteLine (" -updown configure up/down counter mode");
Console.WriteLine (" -quad configure quad-decoder counter mode");
Console.WriteLine (" -rst enable counter's reset input");
Console.WriteLine (" <cha1..n> number of counter channel to (configure and) read");
}
// Main entry point.
static int
Main (string[] argv)
{
if (argv.Length > 0)
{
// First command line argument is the DAQ's name.
// If "-" is passed, then let's read the name from
// the console.
string name = argv[0];
if (argv[0] == "-")
{
Console.Write ("data acquisition system to open: ");
name = Console.ReadLine ();
}
// Direction defaults to input, but may get overridden by -o
// on the command line.
int start = 1;
int mode = -1;
bool enable_rst = false;
while (argv.Length > start)
{
if (argv[start] == "-counter")
{
mode = LIBAD.AD_CNT_COUNTER;
start++;
}
else if (argv[start] == "-updown")
{
mode = LIBAD.AD_CNT_UPDOWN;
start++;
}
else if (argv[start] == "-quad")
{
mode = LIBAD.AD_CNT_QUAD_DECODER;
start++;
}
else if (argv[start] == "-rst")
{
enable_rst = true;
start++;
}
else
break;
}
// Convert remaining command line arguments into
// numbers and add those to the channel array.
int[] chav = new int[argv.Length - start];
for (int i = start; i < argv.Length; i++)
{
chav[i - start] = int.Parse (argv[i]);
}
// Configure counter and read actual values, printing results
// to the console.
do_counter (name, mode, enable_rst, chav);
if (argv[0]== "-")
{
Console.WriteLine ("press return to continue...");
Console.ReadLine ();
}
return 0;
}
else
{
usage ();
return 1;
}
}
}
' Libad Counter Example
'
' Example showing how to setup counter mode and read counter value
' using bmcm's LIBAD4.
Imports System
Imports LIBAD4
Module Example
' Setup counter and read actual value.
Sub do_counter (driver As String, mode As Integer, enable_rst As Boolean, ByVal chav As Integer())
' Open DAQ system.
Dim adh As Integer
adh = LIBAD.ad_open (driver)
If adh = -1 Then
Console.WriteLine ("failed to open {0}: err = {1}", driver, LIBAD.errno)
Exit Sub
End If
' Set counter mode and read actual value.
For i = 0 To chav.Length-1
Dim data As Uinteger
Dim rc As Integer
If mode >= 0 Then
Dim par As LIBAD.ad_counter_mode
' Setup counter mode, using Port A/1 and Port A/2 as
' both counter inputs. The counter's reset input
' gets connected to Port A/3 (if enabled).
par = new LIBAD.ad_counter_mode ()
par.cha = LIBAD.AD_CHA_TYPE_COUNTER Or chav(i)
par.mode = mode And &Hff
par.mux_a = 0
par.mux_b = 1
If enable_rst Then
par.mux_rst = 2
par.flags = par.Flags Or LIBAD.AD_CNT_ENABLE_RST
End If
rc = LIBAD.ad_set_counter_mode (adh, par)
If rc <> 0 Then
Console.WriteLine ("error: failed to setup counter %d: err = %d\n", chav(i), rc)
Exit Sub
End If
End If
rc = LIBAD.ad_discrete_in (adh, LIBAD.AD_CHA_TYPE_COUNTER or chav(i), 0, data)
If rc = 0 Then
Console.WriteLine ("counter {0,2}: {1}", chav(i), data)
Else
Console.WriteLine ("error: failed to write cha {0}: err = {1}", chav(i), rc)
End If
Next
' Close DAQ system again.
LIBAD.ad_close (adh)
End Sub
' Show usage.
Sub Usage
Console.WriteLine ("usage: counter <driver> [-counter|-updown|-quad] [-rst] <cha1> .. <chan>")
Console.WriteLine (" <driver> string to pass to ad_open()")
Console.WriteLine (" - will prompt for name")
Console.WriteLine (" -counter configure counter mode")
Console.WriteLine (" -updown configure up/down counter mode")
Console.WriteLine (" -quad configure quad-decoder counter mode")
Console.WriteLine (" -rst enable counter's reset input")
Console.WriteLine (" <cha1..n> number of counter channel to (configure and) read")
End Sub
' Main entry point.
Sub Main (ByVal argv As String())
If argv.Length > 0 Then
' First command line argument is the DAQ's name.
' If "-" is passed, then let's read the name from
' the console.
Dim name As String
name = argv(0)
If argv(0) = "-" Then
Console.Write ("data acquisition sytem to open: ")
name = Console.ReadLine ()
End If
' Direction defaults to input, but may get overridden by -o
' on the command line.
Dim start As Integer
Dim mode As Integer
Dim enable_rst As Boolean
start = 1
mode = -1
enable_rst = False
Do While argv.Length > start
If argv(start) = "-counter" Then
mode = LIBAD.AD_CNT_COUNTER
start = start + 1
Else If argv(start) = "-updown" Then
mode = LIBAD.AD_CNT_UPDOWN
start = start + 1
Else If argv(start) = "-quad" Then
mode = LIBAD.AD_CNT_QUAD_DECODER
start = start + 1
Else If argv(start) = "-rst" Then
enable_rst = True
start = start + 1
Else
Exit Do
End If
Loop
' Convert remaining command line arguments into
' numbers and add those to the channel array.
Dim chav(argv.Length-1 - start) As Integer
For i = start To argv.Length-1
chav(i - start) = Int32.Parse (argv(i))
Next
' Configure counter and read actual values, printing results
' to the console.
do_counter (name, mode, enable_rst, chav)
If argv(0) = "-" Then
Console.WriteLine ("press return to continue...")
Console.ReadLine ()
End If
Environment.Exit (0)
Else
Usage
Environment.Exit (1)
End If
End Sub
End Module