Files
sics/site_ansto/hardsup/Monitor/hctr.c
Douglas Clowes 2ab57e1eb2 Make C++ compiler friendly and handle all eight counters in one process.
r1171 | dcl | 2006-10-24 15:44:25 +1000 (Tue, 24 Oct 2006) | 2 lines
2012-11-15 12:48:57 +11:00

313 lines
7.6 KiB
C

#include "hctr.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <NIDAQmx.h>
#define DAQmxErrChk(functionCall) \
do { if( DAQmxFailed(error=(functionCall)) ) \
goto Error; } while(0)
/**
* This structure encapsulates the data that is private to
* the implementation of the NI DAQ counter interface
*/
typedef struct counter_private_t
{
/** NIDAQ opaque task handle */
TaskHandle taskHandle;
/** Actual physical counter value, as returned by NIDAQ
* read function */
uInt32 count32;
/** extended 64-bit counter value */
unsigned long long count64;
/** NIDAQ device number of card */
int device_number;
/** NI counter number on card */
int counter_number;
/** true if using external sync else timer based sampling */
bool sync;
/** sync line number on the card */
int sync_line_number;
/** output line number on the card */
int output_line_number;
/** NIDAQ opaque task handle for digital output */
TaskHandle taskHandle_dout;
} COUNTER_PRIVATE;
typedef struct mapping_t {
int cntr_num;
int sync_num;
int outp_num;
} MAPPING;
MAPPING mapping[8] = {
{ 0, 37, 36 },
{ 1, 33, 32 },
{ 2, 29, 28 },
{ 3, 25, 24 },
{ 4, 21, 20 },
{ 5, 17, 16 },
{ 6, 13, 12 },
{ 7, 9, 8 }
};
int hctr_ctor(const char* device_name, pHCTR* ptr)
{
int error = 0;
bool flag = false;
char text_string[] = "dev1/ctr0";
const char *name;
const char *text;
*ptr = (COUNTER_PRIVATE*) malloc(sizeof(COUNTER_PRIVATE));
memset(*ptr, 0, sizeof(COUNTER_PRIVATE));
name = device_name;
text = text_string;
while (name && *name)
{
if (isspace(*name))
++name;
else if (*name >= '0' && *name <= '7')
{
if (flag)
{
(*ptr)->counter_number = *name - '0';
(*ptr)->sync_line_number = mapping[(*ptr)->counter_number].sync_num;
(*ptr)->output_line_number = mapping[(*ptr)->counter_number].outp_num;
}
else
{
(*ptr)->device_number = *name - '0';
flag = true;
}
}
else if (tolower(*name) != *text)
{
/* TODO error */
break;
}
++name;
++text;
}
/*********************************************/
// Create a DAQmx task to hold the counter
/*********************************************/
DAQmxErrChk (DAQmxCreateTask("",&(*ptr)->taskHandle));
/*********************************************/
// Create a DAQmx counter within the task
/*********************************************/
DAQmxErrChk (
DAQmxCreateCICountEdgesChan((*ptr)->taskHandle,
device_name,
"",
DAQmx_Val_Rising,
(*ptr)->count32,
DAQmx_Val_CountUp));
/*********************************************/
// Start the DAQmx task
/*********************************************/
DAQmxErrChk (DAQmxStartTask((*ptr)->taskHandle));
return 0;
Error:
free(*ptr);
*ptr = NULL;
return error;
}
int hctr_read(pHCTR hctr, unsigned long long* value)
{
int error = 0;
uInt32 ctr;
DAQmxErrChk (DAQmxReadCounterScalarU32(hctr->taskHandle,
1.0,
&ctr,
NULL));
hctr->count64 += ctr - hctr->count32;
hctr->count32 = ctr;
*value = hctr->count64;
return 0;
Error:
return error;
}
int make_dout_task(pHCTR ptr)
{
int error = 0;
char port_range[40];
/*********************************************/
// Create a DAQmx task to hold the counter
/*********************************************/
DAQmxErrChk (DAQmxCreateTask("",&ptr->taskHandle_dout));
/*********************************************/
// Create the digital channel within the task
/*********************************************/
snprintf(port_range, sizeof(port_range), "DEV%d/LINE%d",
ptr->device_number, ptr->counter_number);
DAQmxErrChk (DAQmxCreateDOChan(ptr->taskHandle_dout,
port_range,
"",
DAQmx_Val_ChanPerLine));
/*********************************************/
// Start the DAQmx task
/*********************************************/
DAQmxErrChk (DAQmxStartTask(ptr->taskHandle_dout));
return error;
Error:
return error;
}
int hctr_outp(pHCTR hctr, int value)
{
int error = 0;
uInt8 data;
if (value < 0) {
if (hctr->taskHandle_dout != 0) {
data = 0;
DAQmxWriteDigitalLines(hctr->taskHandle_dout,
1,
1,
10.0,
DAQmx_Val_GroupByChannel,
&data,
NULL,
NULL);
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask(hctr->taskHandle_dout);
DAQmxClearTask(hctr->taskHandle_dout);
hctr->taskHandle_dout = 0;
}
return error;
}
if (hctr->taskHandle_dout == 0)
DAQmxErrChk (make_dout_task(hctr));
if (value > 0)
data = 1;
else
data = 0;
#if 0
DAQmxErrChk (
DAQmxWriteDigitalLines(hctr->taskHandle_dout,
1,
1,
10.0,
DAQmx_Val_GroupByChannel,
&data,
NULL,
NULL));
#else
DAQmxErrChk (
DAQmxWriteDigitalScalarU32(hctr->taskHandle_dout,
1,
10.0,
data,
NULL));
#endif
Error:
return error;
}
void hctr_sync(pHCTR hctr, bool external)
{
int error = 0;
char device_name[40];
if (hctr->sync != external)
{
hctr->sync = external;
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask(hctr->taskHandle);
DAQmxClearTask(hctr->taskHandle);
/*********************************************/
// Create a DAQmx task to hold the counter
/*********************************************/
DAQmxErrChk (DAQmxCreateTask("",&hctr->taskHandle));
/*********************************************/
// Create a DAQmx counter within the task
/*********************************************/
hctr->count32 = 0;
snprintf(device_name, sizeof(device_name), "dev%d/ctr%d",
hctr->device_number, hctr->counter_number);
DAQmxErrChk (
DAQmxCreateCICountEdgesChan(hctr->taskHandle,
device_name,
"",
DAQmx_Val_Rising,
hctr->count32,
DAQmx_Val_CountUp));
if (external)
{
char str[40];
snprintf(str, sizeof(str), "dev%d/PFI%d",
hctr->device_number, hctr->sync_line_number);
DAQmxErrChk (
DAQmxCfgSampClkTiming(hctr->taskHandle,
str,
10000,
DAQmx_Val_Rising,
DAQmx_Val_ContSamps,
10000));
}
/*********************************************/
// Start the DAQmx task
/*********************************************/
DAQmxErrChk (DAQmxStartTask(hctr->taskHandle));
}
Error:
return;
}
int hctr_dtor(pHCTR* hctr)
{
if( hctr && *hctr && (*hctr)->taskHandle!=0 )
{
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask((*hctr)->taskHandle);
DAQmxClearTask((*hctr)->taskHandle);
}
(*hctr)->taskHandle = 0;
if( hctr && *hctr && (*hctr)->taskHandle_dout!=0 )
{
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask((*hctr)->taskHandle_dout);
DAQmxClearTask((*hctr)->taskHandle_dout);
}
(*hctr)->taskHandle_dout = 0;
free (*hctr);
*hctr = NULL;
return 0;
}
bool hctr_failed(int error)
{
if (DAQmxFailed(error))
return true;
else
return false;
}
void hctr_errmsg(char* buff, int len)
{
*buff = '\0';
DAQmxGetExtendedErrorInfo(buff, len);
}