renamed from cntr.[hc] tp be consistent with digital input driver
r1201 | dcl | 2006-10-30 12:21:01 +1100 (Mon, 30 Oct 2006) | 2 lines
This commit is contained in:
683
site_ansto/hardsup/Monitor/device.c
Normal file
683
site_ansto/hardsup/Monitor/device.c
Normal file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
* Abstraction of the counter device.
|
||||
*
|
||||
*/
|
||||
#include "device.h"
|
||||
#include "params.h"
|
||||
#include "sock.h"
|
||||
#include "hware.h"
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define HWARE_TEST(functionCall) \
|
||||
if( hware_failed(error=(functionCall)) ) \
|
||||
goto Error; \
|
||||
else
|
||||
|
||||
/*
|
||||
* get a pointer to the current sample
|
||||
*/
|
||||
static SAMPLE* cur_sample(DEVICE* device)
|
||||
{
|
||||
return &device->sample_array[device->sample_index];
|
||||
}
|
||||
|
||||
/*
|
||||
* get a pointer to the num'th previous sample
|
||||
*/
|
||||
static SAMPLE* prv_sample(DEVICE* device, int num)
|
||||
{
|
||||
int idx = (device->sample_index + SAMPLE_ARRAY_SZ - num) % SAMPLE_ARRAY_SZ;
|
||||
return &device->sample_array[idx];
|
||||
}
|
||||
|
||||
void make_report(DEVICE* device)
|
||||
{
|
||||
dbg_printf(0, "make_report\n");
|
||||
int i;
|
||||
SAMPLE* sp = cur_sample(device);
|
||||
device->report = *sp;
|
||||
device->report.average_rate = device->report.counter_rate;
|
||||
device->report.minimum_rate = device->report.counter_rate;
|
||||
device->report.maximum_rate = device->report.counter_rate;
|
||||
for (i = 1; i <= device->params.report_period; ++i)
|
||||
{
|
||||
SAMPLE* psp;
|
||||
psp = prv_sample(device, i);
|
||||
if (psp->valid)
|
||||
{
|
||||
device->report.time_delta = time_diff(&sp->timestamp, &psp->timestamp);
|
||||
device->report.count_delta = sp->count64 - psp->count64;
|
||||
if (device->report.time_delta > 0.0)
|
||||
device->report.average_rate = device->report.count_delta
|
||||
/ device->report.time_delta;
|
||||
if (i < device->params.report_period)
|
||||
{
|
||||
device->report.num_polls += psp->num_polls;
|
||||
if (psp->counter_rate < device->report.minimum_rate)
|
||||
device->report.minimum_rate = psp->counter_rate;
|
||||
if (psp->counter_rate > device->report.maximum_rate)
|
||||
device->report.maximum_rate = psp->counter_rate;
|
||||
}
|
||||
}
|
||||
}
|
||||
sp = &device->report;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* given two samples, compute the count-rate
|
||||
*/
|
||||
static double compute_rate(DEVICE* device, SAMPLE* cur, SAMPLE* prv)
|
||||
{
|
||||
double result = 0.0;
|
||||
uInt32 delta_counter;
|
||||
if (device->params.direction == COUNT_DOWN)
|
||||
delta_counter = prv->counter_value - cur->counter_value;
|
||||
else
|
||||
delta_counter = cur->counter_value - prv->counter_value;
|
||||
double delta_timer = time_diff(&cur->timestamp, &prv->timestamp);
|
||||
result = 1.0 * delta_counter / delta_timer;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* given two samples, compute the average rate
|
||||
*/
|
||||
static double compute_average(DEVICE* device, SAMPLE* cur, SAMPLE* prv)
|
||||
{
|
||||
double result = 0.0;
|
||||
if (cur == prv)
|
||||
result = cur->counter_rate;
|
||||
else
|
||||
result = compute_rate(device, cur, prv);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
void device_send(DEVICE* device, int n)
|
||||
{
|
||||
SAMPLE* sp = cur_sample(device);
|
||||
BUFFER buffer;
|
||||
buffer.length = 0;
|
||||
snprintf(buffer.body, sizeof(buffer.body),
|
||||
"Time: %s, Count: %10llu, Delta: %6d, Time: %8.6f, Rate: %8.2f, Ave: %8.2f\r\n",
|
||||
make_timestamp(&sp->timestamp),
|
||||
sp->counter_value,
|
||||
sp->count_delta,
|
||||
sp->time_delta,
|
||||
sp->counter_rate,
|
||||
sp->average_rate);
|
||||
buffer.length = strlen(buffer.body);
|
||||
sock_send(n, &buffer);
|
||||
}
|
||||
|
||||
void device_read(DEVICE* device, int n)
|
||||
{
|
||||
SAMPLE* sp = cur_sample(device);
|
||||
BUFFER buffer;
|
||||
buffer.length = 0;
|
||||
snprintf(buffer.body, sizeof(buffer.body),
|
||||
"READ %c%c%c%c %s %.6f %10llu %8.2f\r\n",
|
||||
device->state == counter_idle ? 'I' :
|
||||
device->state == counter_stopped ? 'S' :
|
||||
device->state == counter_running ? 'R' :
|
||||
device->state == counter_paused ? 'P' : '?',
|
||||
device->terminal_due ? 'T' : ' ',
|
||||
device->range_error == 0 ? ' ' : 'R',
|
||||
device->range_gated ? 'G' : ' ',
|
||||
make_timestamp(&sp->timestamp),
|
||||
device->accumulated.tv_sec + .000001 * device->accumulated.tv_usec,
|
||||
sp->counter_value,
|
||||
sp->counter_rate);
|
||||
buffer.length = strlen(buffer.body);
|
||||
sock_send(n, &buffer);
|
||||
}
|
||||
|
||||
void device_print(DEVICE* device, FILE* fd)
|
||||
{
|
||||
SAMPLE* sp = cur_sample(device);
|
||||
fprintf(fd, "Time: %s, Count: %10llu, Delta: %6d, Time: %8.6f, Rate: %8.2f, Ave: %8.2f\r\n",
|
||||
make_timestamp(&sp->timestamp),
|
||||
sp->counter_value,
|
||||
sp->count_delta,
|
||||
sp->time_delta,
|
||||
sp->counter_rate,
|
||||
sp->average_rate);
|
||||
fflush(fd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finalise the current sample and move on to the next
|
||||
*/
|
||||
void device_sample(DEVICE* device)
|
||||
{
|
||||
SAMPLE* psp = cur_sample(device);
|
||||
dbg_printf(0, "device_sample: %4d\r\n"
|
||||
" polls: %4d\r\n"
|
||||
" time: %4s\r\n"
|
||||
" counter: %10llu\r\n"
|
||||
" count64: %10llu\r\n"
|
||||
" c_delta: %d\r\n"
|
||||
" t_delta: %6.3f\r\n"
|
||||
" rate: %10g\n",
|
||||
device->sample_index,
|
||||
psp->num_polls,
|
||||
make_timestamp(&psp->timestamp),
|
||||
psp->counter_value,
|
||||
psp->count64,
|
||||
psp->count_delta,
|
||||
psp->time_delta,
|
||||
psp->counter_rate);
|
||||
device->sample_timer = device->current_time;
|
||||
++device->sample_counter;
|
||||
|
||||
if (++device->sample_index >= SAMPLE_ARRAY_SZ)
|
||||
device->sample_index = 0;
|
||||
SAMPLE* sp = cur_sample(device);
|
||||
*sp = *psp;
|
||||
sp->valid = true;
|
||||
sp->num_polls = 0;
|
||||
sp->sample_counter = device->sample_counter;
|
||||
sp->poll_counter = device->poll_counter;
|
||||
}
|
||||
|
||||
void device_report(DEVICE* device)
|
||||
{
|
||||
dbg_printf(0, "device_report\n");
|
||||
/*
|
||||
* Set the time for this report
|
||||
*/
|
||||
device->report_timer = device->current_time;
|
||||
BUFFER buffer;
|
||||
SAMPLE* sp;
|
||||
sp = &device->report;
|
||||
char* str = make_timestamp(&sp->timestamp);
|
||||
snprintf(buffer.body, sizeof(buffer.body),
|
||||
"%s (%6.3f), %10llu (%8d), %8.2f (%8.2f,%8.2f,%8.2f)\r\n",
|
||||
str,
|
||||
sp->time_delta,
|
||||
sp->counter_value,
|
||||
sp->count_delta,
|
||||
sp->counter_rate,
|
||||
sp->minimum_rate,
|
||||
sp->average_rate,
|
||||
sp->maximum_rate);
|
||||
buffer.length = strlen(buffer.body);
|
||||
//fputs(buffer.body, stdout);
|
||||
sock_report(&buffer, 1);
|
||||
snprintf(buffer.body, sizeof(buffer.body),
|
||||
"REPORT %s %10llu %8.2f (%8.2f,%8.2f,%8.2f)\r\n",
|
||||
str,
|
||||
sp->counter_value,
|
||||
sp->counter_rate,
|
||||
sp->minimum_rate,
|
||||
sp->average_rate,
|
||||
sp->maximum_rate);
|
||||
buffer.length = strlen(buffer.body);
|
||||
//fputs(buffer.body, stdout);
|
||||
sock_report(&buffer, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the counter
|
||||
*
|
||||
* Initialise all of the control data associated with the logical counter.
|
||||
*
|
||||
* Create a 64-bit physical counter and start it.
|
||||
*/
|
||||
int device_init(DEVICE** cpp, char* name)
|
||||
{
|
||||
int error = 0;
|
||||
char errBuff[2048]={'\0'};
|
||||
SAMPLE* sp = NULL;
|
||||
DEVICE* device = (DEVICE*) malloc(sizeof(DEVICE));
|
||||
*cpp = device;
|
||||
memset(device, 0, sizeof(DEVICE));
|
||||
strncpy(device->name, name, sizeof(device->name));
|
||||
device->params.poll_period = 1000; /* milliseconds between polls */
|
||||
device->params.sample_period = 10; /* polls between sample calcs */
|
||||
device->params.report_period = 3; /* samples between reports */
|
||||
device->state = counter_stopped;
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
device->current_time = now;
|
||||
device->previous_time = now;
|
||||
device->sample_timer = now;
|
||||
device->report_timer = now;
|
||||
HWARE_TEST(hware_ctor(name, &device->private_data));
|
||||
sp = cur_sample(device);
|
||||
sp->timestamp = now;
|
||||
sp->counter_value = device->current_count;
|
||||
sp->valid = true;
|
||||
device_sample(device);
|
||||
return 0;
|
||||
Error:
|
||||
hware_errmsg(errBuff, sizeof(errBuff));
|
||||
printf("DAQmx Error: %s\n", errBuff);
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the logical counter
|
||||
*
|
||||
* Read the value of the physical counter and set the state to running
|
||||
*/
|
||||
int device_start(DEVICE *device)
|
||||
{
|
||||
int error = 0;
|
||||
char errBuff[2048]={'\0'};
|
||||
struct timeval now;
|
||||
int value;
|
||||
SAMPLE* sp = NULL;
|
||||
SAMPLE* psp = NULL;
|
||||
PARAMETERS* pp = &device->params;
|
||||
/* start the counter object */
|
||||
gettimeofday(&now, NULL);
|
||||
device->current_time = now;
|
||||
device->start_time = device->current_time;
|
||||
device->current_count = device->params.initial_count;
|
||||
device->accumulated.tv_sec = 0;
|
||||
device->accumulated.tv_usec = 0;
|
||||
device->poll_counter = 0;
|
||||
device->sample_counter = 0;
|
||||
device->terminal_due = false;
|
||||
device->state = counter_running;
|
||||
device->previous_time = device->current_time;
|
||||
dbg_printf(0, "Setting input line to %d\n", pp->source);
|
||||
HWARE_TEST(hware_source(device->private_data, pp->source));
|
||||
device->source = pp->source;
|
||||
HWARE_TEST(hware_read(device->private_data, &device->count64));
|
||||
sp = cur_sample(device);
|
||||
sp->timestamp = device->current_time;
|
||||
sp->counter_value = device->current_count;
|
||||
psp = prv_sample(device, 1);
|
||||
psp->timestamp = device->current_time;
|
||||
psp->counter_value = device->current_count;
|
||||
make_report(device);
|
||||
if (pp->output_line == 1)
|
||||
value = 1;
|
||||
else if (pp->output_line == 2)
|
||||
value = 0;
|
||||
else
|
||||
value = -1;
|
||||
dbg_printf(0, "Setting output line to %d\n", value);
|
||||
HWARE_TEST(hware_outp(device->private_data, value));
|
||||
return error;
|
||||
Error:
|
||||
device_errmsg(errBuff, sizeof(errBuff));
|
||||
printf("DAQmx Error: %s\n", errBuff);
|
||||
return error;
|
||||
}
|
||||
|
||||
int device_stop(DEVICE *device)
|
||||
{
|
||||
int error = 0;
|
||||
char errBuff[2048]={'\0'};
|
||||
PARAMETERS* pp = &device->params;
|
||||
int value;
|
||||
device->stop_time = device->current_time;
|
||||
device->state = counter_stopped;
|
||||
if (pp->output_line == 1)
|
||||
value = 0;
|
||||
else if (pp->output_line == 2)
|
||||
value = 1;
|
||||
else
|
||||
value = -1;
|
||||
dbg_printf(0, "Setting output line to %d\n", value);
|
||||
HWARE_TEST(hware_outp(device->private_data, value));
|
||||
dbg_printf(0, "Setting input line to %d\n", pp->source);
|
||||
HWARE_TEST(hware_source(device->private_data, pp->source));
|
||||
device->source = pp->source;
|
||||
return error;
|
||||
Error:
|
||||
device_errmsg(errBuff, sizeof(errBuff));
|
||||
printf("DAQmx Error: %s\n", errBuff);
|
||||
return error;
|
||||
}
|
||||
|
||||
int device_pause(DEVICE *device)
|
||||
{
|
||||
if (device->state == counter_running)
|
||||
device->state = counter_paused;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int device_resume(DEVICE *device)
|
||||
{
|
||||
if (device->state == counter_paused)
|
||||
device->state = counter_running;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int device_command(void* counter, const char* command)
|
||||
{
|
||||
DEVICE* device = static_cast<DEVICE*>(counter);
|
||||
if (strncasecmp(command, "pause", 5) == 0)
|
||||
return device_pause(device);
|
||||
else if (strncasecmp(command, "continue", 8) == 0)
|
||||
return device_resume(device);
|
||||
else if (strncasecmp(command, "resume", 6) == 0)
|
||||
return device_resume(device);
|
||||
else if (strncasecmp(command, "start", 6) == 0)
|
||||
return device_start(device);
|
||||
else if (strncasecmp(command, "stop", 4) == 0)
|
||||
return device_stop(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void device_event(DEVICE *device, char* event)
|
||||
{
|
||||
BUFFER buffer;
|
||||
sprintf(buffer.body, "EVENT %s %s\r\n",
|
||||
event,
|
||||
make_timestamp(&device->current_time));
|
||||
buffer.length = strlen(buffer.body);
|
||||
dbg_printf(0, "%s", buffer.body);
|
||||
//sock_report(&buffer, 0);
|
||||
sock_report(&buffer, 1);
|
||||
sock_report(&buffer, 2);
|
||||
}
|
||||
|
||||
static void device_range_check(DEVICE* device, int mode)
|
||||
{
|
||||
PARAMETERS* pp = &device->params;
|
||||
if (pp->range_check_enable)
|
||||
{
|
||||
if (pp->range_mode == mode)
|
||||
{
|
||||
double test;
|
||||
SAMPLE* sp = cur_sample(device);
|
||||
if (mode == 1)
|
||||
test = sp->counter_rate;
|
||||
else if (mode == 2)
|
||||
test = sp->counter_rate;
|
||||
else
|
||||
test = device->report.average_rate;
|
||||
if (pp->range_low > 0 && pp->range_low > test)
|
||||
{
|
||||
if (device->range_error != 1)
|
||||
device_event(device, "RANGE OUT LOW");
|
||||
device->range_error = 1;
|
||||
if (pp->range_gate_enable)
|
||||
device->range_gated = true;
|
||||
else
|
||||
device->range_gated = false;
|
||||
}
|
||||
else if (pp->range_high > 0 && pp->range_high < test)
|
||||
{
|
||||
if (device->range_error != 2)
|
||||
device_event(device, "RANGE OUT HIGH");
|
||||
device->range_error = 2;
|
||||
if (pp->range_gate_enable)
|
||||
device->range_gated = true;
|
||||
else
|
||||
device->range_gated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (device->range_error != 0)
|
||||
device_event(device, "RANGE IN");
|
||||
device->range_error = 0;
|
||||
device->range_gated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If range check has been disabled while in error - reset */
|
||||
if (device->range_error != 0)
|
||||
device_event(device, "RANGE IN");
|
||||
device->range_error = 0;
|
||||
device->range_gated = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void device_test_term(DEVICE* device)
|
||||
{
|
||||
PARAMETERS* pp = &device->params;
|
||||
SAMPLE* sp = cur_sample(device);
|
||||
SAMPLE* psp = prv_sample(device, 1);
|
||||
|
||||
if (!device->terminal_due)
|
||||
{
|
||||
if (pp->terminal_check_type == 1)
|
||||
{
|
||||
if (pp->direction == COUNT_DOWN)
|
||||
{
|
||||
/*
|
||||
* decremented to or through terminal
|
||||
*/
|
||||
// TODO FIXME improve wraparound handling
|
||||
if ((sp->counter_value <= pp->terminal_count &&
|
||||
psp->counter_value > pp->terminal_count) ||
|
||||
(sp->counter_value > psp->counter_value &&
|
||||
psp->counter_value > pp->terminal_count))
|
||||
{
|
||||
device->terminal_due = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* incremented to or through terminal
|
||||
*/
|
||||
// TODO FIXME improve wraparound handling
|
||||
if (
|
||||
#if 1
|
||||
sp->counter_value >= pp->terminal_count
|
||||
#else
|
||||
(sp->counter_value >= pp->terminal_count &&
|
||||
psp->counter_value < pp->terminal_count) ||
|
||||
(sp->counter_value < psp->counter_value &&
|
||||
psp->counter_value > pp->terminal_count)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
device->terminal_due = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pp->terminal_check_type == 2)
|
||||
{
|
||||
if ((uint64) device->accumulated.tv_sec >= pp->terminal_count)
|
||||
device->terminal_due = true;
|
||||
}
|
||||
if (device->terminal_due)
|
||||
{
|
||||
device_event(device, "TERMINAL");
|
||||
make_report(device);
|
||||
device_stop(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* poll the physical counter
|
||||
*/
|
||||
int device_poll(DEVICE* device)
|
||||
{
|
||||
PARAMETERS* pp = &device->params;
|
||||
char errBuff[2048]={'\0'};
|
||||
unsigned long long current_count_local;
|
||||
int count_delta_local;
|
||||
int error=0;
|
||||
SAMPLE* sp = NULL;
|
||||
SAMPLE* psp = NULL;
|
||||
|
||||
/* read the value from the hardware counter to a temp */
|
||||
++device->poll_counter;
|
||||
HWARE_TEST(hware_read(device->private_data, ¤t_count_local));
|
||||
dbg_printf(0, "device_poll = %llu @ %s\n",
|
||||
current_count_local,
|
||||
make_timestamp(&device->current_time));
|
||||
|
||||
sp = cur_sample(device);
|
||||
psp = prv_sample(device, 1);
|
||||
|
||||
/* calculate the number since last time and save new value */
|
||||
count_delta_local = current_count_local - device->count64;
|
||||
device->count64 = current_count_local;
|
||||
sp->num_polls += 1;
|
||||
/*
|
||||
* If the counter is running and not gated increment the count and runtime
|
||||
*/
|
||||
if (device->state == counter_running &&
|
||||
!(device->params.range_gate_enable && device->range_gated))
|
||||
{
|
||||
if (device->params.direction == COUNT_DOWN)
|
||||
{
|
||||
device->current_count -= count_delta_local;
|
||||
}
|
||||
else
|
||||
{
|
||||
device->current_count += count_delta_local;
|
||||
}
|
||||
/*
|
||||
* Add the time difference to the accumulated time
|
||||
*/
|
||||
device->accumulated.tv_sec += device->current_time.tv_sec - sp->timestamp.tv_sec;
|
||||
/* prevent negative tv_usec by borrowing one second in microseconds */
|
||||
device->accumulated.tv_usec += 1000000;
|
||||
device->accumulated.tv_usec += device->current_time.tv_usec;
|
||||
device->accumulated.tv_usec -= sp->timestamp.tv_usec;
|
||||
if (device->accumulated.tv_usec >= 1000000)
|
||||
{
|
||||
/* carry the seconds */
|
||||
device->accumulated.tv_sec += device->accumulated.tv_usec / 1000000;
|
||||
device->accumulated.tv_usec %= 1000000;
|
||||
}
|
||||
/* pay back the borrowed second */
|
||||
device->accumulated.tv_sec -= 1;
|
||||
}
|
||||
|
||||
/* calculate and check the count-rate between polls */
|
||||
sp->count_delta = device->count64 - sp->count64;
|
||||
sp->time_delta = time_diff(&device->current_time, &sp->timestamp);
|
||||
sp->counter_rate = (double) sp->count_delta / sp->time_delta;
|
||||
device_range_check(device, 2); /* poll range check */
|
||||
|
||||
device->previous_time = device->current_time;
|
||||
|
||||
/* save counter values in the sample */
|
||||
sp->counter_value = device->current_count;
|
||||
sp->count64 = device->count64;
|
||||
sp->timestamp = device->current_time;
|
||||
|
||||
/* calculate the count-rate for this sample so far */
|
||||
sp->count_delta = sp->count64 - psp->count64;
|
||||
sp->time_delta = time_diff(&sp->timestamp, &psp->timestamp);
|
||||
sp->counter_rate = (double) sp->count_delta / sp->time_delta;
|
||||
|
||||
/* test for the occurrence of a terminal event */
|
||||
device_test_term(device);
|
||||
|
||||
/* check if it is time to roll the sample */
|
||||
if (device_time_to_next_sample(device) <= 0)
|
||||
{
|
||||
/* check if it is time to roll the report */
|
||||
if (device_time_to_next_report(device) <= 0)
|
||||
{
|
||||
make_report(device);
|
||||
device_range_check(device, 0); /* report range check */
|
||||
device_report(device);
|
||||
}
|
||||
device_range_check(device, 1); /* sample range check */
|
||||
device_sample(device);
|
||||
}
|
||||
|
||||
/* set the source line */
|
||||
if (device->source != pp->source)
|
||||
{
|
||||
device->source = pp->source;
|
||||
HWARE_TEST(hware_source(device->private_data, device->source));
|
||||
}
|
||||
|
||||
/* drive the output line */
|
||||
if (device->output_line != pp->output_line)
|
||||
{
|
||||
int value;
|
||||
device->output_line = pp->output_line;
|
||||
if (pp->output_line == 1)
|
||||
{
|
||||
if (device->state == counter_running || device->state == counter_paused)
|
||||
value = 1;
|
||||
else
|
||||
value = 0;
|
||||
}
|
||||
else if (pp->output_line == 2)
|
||||
{
|
||||
if (device->state == counter_running || device->state == counter_paused)
|
||||
value = 0;
|
||||
else
|
||||
value = 1;
|
||||
}
|
||||
else
|
||||
value = -1;
|
||||
HWARE_TEST(hware_outp(device->private_data, value));
|
||||
}
|
||||
return error;
|
||||
Error:
|
||||
device_errmsg(errBuff, sizeof(errBuff));
|
||||
printf("DAQmx Error: %s\n", errBuff);
|
||||
return error;
|
||||
}
|
||||
|
||||
void device_term(DEVICE* device)
|
||||
{
|
||||
if (device->private_data)
|
||||
{
|
||||
hware_dtor(&device->private_data);
|
||||
device->private_data = NULL;
|
||||
}
|
||||
device->state = counter_idle;
|
||||
}
|
||||
|
||||
bool device_fatal(int error)
|
||||
{
|
||||
return hware_failed(error);
|
||||
}
|
||||
|
||||
void device_errmsg(char* buff, int len)
|
||||
{
|
||||
hware_errmsg(buff, len);
|
||||
}
|
||||
|
||||
double device_time_to_next_report(DEVICE* device)
|
||||
{
|
||||
uint64 last_report;
|
||||
uint64 timeofday;
|
||||
int timeout;
|
||||
struct timeval now;
|
||||
now = device->current_time;
|
||||
last_report = 1000 * (uint64) device->report_timer.tv_sec;
|
||||
last_report += (uint64) device->report_timer.tv_usec / 1000;
|
||||
timeofday = 1000 * (uint64) now.tv_sec;
|
||||
timeofday += (uint64) now.tv_usec / 1000;
|
||||
timeout = device->params.poll_period * device->params.sample_period *
|
||||
device->params.report_period;
|
||||
if ((last_report / timeout) != (timeofday / timeout))
|
||||
return 0.0;
|
||||
timeout = timeout - timeofday % timeout;
|
||||
return 0.001 * timeout;
|
||||
}
|
||||
|
||||
double device_time_to_next_sample(DEVICE* device)
|
||||
{
|
||||
uint64 last_sample;
|
||||
uint64 timeofday;
|
||||
int timeout;
|
||||
struct timeval now;
|
||||
now = device->current_time;
|
||||
last_sample = 1000 * (uint64) device->sample_timer.tv_sec;
|
||||
last_sample += (uint64) device->sample_timer.tv_usec / 1000;
|
||||
timeofday = 1000 * (uint64) now.tv_sec;
|
||||
timeofday += (uint64) now.tv_usec / 1000;
|
||||
timeout = device->params.poll_period * device->params.sample_period;
|
||||
if ((last_sample / timeout) != (timeofday / timeout))
|
||||
return 0.0;
|
||||
timeout = timeout - timeofday % timeout;
|
||||
return 0.001 * timeout;
|
||||
}
|
||||
122
site_ansto/hardsup/Monitor/device.h
Normal file
122
site_ansto/hardsup/Monitor/device.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef _DEVICE_H_
|
||||
#define _DEVICE_H_
|
||||
|
||||
#define MAX_DEVICES 8
|
||||
|
||||
#define SAMPLE_ARRAY_SZ 1000
|
||||
|
||||
#include "utility.h"
|
||||
#include "params.h"
|
||||
|
||||
typedef enum counter_state_t
|
||||
{
|
||||
/** The counter has not yet been created or has been destroyed */
|
||||
counter_idle = 0,
|
||||
/** The counter has not yet been started or has been stopped */
|
||||
counter_stopped,
|
||||
/** The counter is counting */
|
||||
counter_running,
|
||||
/** the counter has been paused */
|
||||
counter_paused
|
||||
} DEVICE_STATE;
|
||||
|
||||
/**
|
||||
* Logical counter sample
|
||||
*/
|
||||
typedef struct sample_t
|
||||
{
|
||||
/** sample number */
|
||||
int sample_counter;
|
||||
/** poll number */
|
||||
int poll_counter;
|
||||
/** time of last read */
|
||||
struct timeval timestamp;
|
||||
/** logical counter value */
|
||||
uint64 counter_value;
|
||||
/** extended physical counter value */
|
||||
uint64 count64;
|
||||
/** counts between current and previous */
|
||||
int count_delta;
|
||||
/** number of polls */
|
||||
int num_polls;
|
||||
/** this data is valid */
|
||||
bool valid;
|
||||
/** time between current and previous */
|
||||
double time_delta;
|
||||
/** computed */
|
||||
double counter_rate;
|
||||
/** computed */
|
||||
double average_rate;
|
||||
/** computed */
|
||||
double minimum_rate;
|
||||
/** computed */
|
||||
double maximum_rate;
|
||||
} SAMPLE, *pSAMPLE;
|
||||
|
||||
typedef struct counter_t
|
||||
{
|
||||
char name[64];
|
||||
DEVICE_STATE state;
|
||||
/** time of last start */
|
||||
struct timeval start_time;
|
||||
/** time of last stop */
|
||||
struct timeval stop_time;
|
||||
/** time of this read */
|
||||
struct timeval current_time;
|
||||
/** time of last read */
|
||||
struct timeval previous_time;
|
||||
/** time of next sample closure */
|
||||
struct timeval sample_timer;
|
||||
/** time of next report generation */
|
||||
struct timeval report_timer;
|
||||
/** accumulated runtime */
|
||||
struct timeval accumulated;
|
||||
/** Current value of logical 64-bit counter */
|
||||
uint64 current_count;
|
||||
/** an array of samples to be used for reporting */
|
||||
SAMPLE sample_array[SAMPLE_ARRAY_SZ];
|
||||
/** calculated values for reporting */
|
||||
SAMPLE report;
|
||||
/** index into the sample array of the current sample */
|
||||
int sample_index;
|
||||
/** number of polls */
|
||||
int poll_counter;
|
||||
/** number of samples */
|
||||
int sample_counter;
|
||||
/** is a terminal count exception due */
|
||||
bool terminal_due;
|
||||
/** error: 0:none, 1:low, 2:high */
|
||||
int range_error;
|
||||
/** is a range exception gate active */
|
||||
bool range_gated;
|
||||
/** Extended physical counter value */
|
||||
uint64 count64;
|
||||
/** Control parameters */
|
||||
PARAMETERS params;
|
||||
/** active value of parameter source */
|
||||
int source;
|
||||
/** active value of parameter output_line */
|
||||
int output_line;
|
||||
struct device_private_t* private_data;
|
||||
} DEVICE, *pDEVICE;
|
||||
|
||||
void make_report(DEVICE* device);
|
||||
void device_sample(DEVICE* device);
|
||||
void device_send(DEVICE* device, int n);
|
||||
void device_read(DEVICE* device, int n);
|
||||
void device_print(DEVICE* device, FILE* fd);
|
||||
void device_report(DEVICE* device);
|
||||
int device_init(DEVICE** cpp, char* name);
|
||||
int device_start(DEVICE* device);
|
||||
int device_stop(DEVICE* device);
|
||||
int device_pause(DEVICE* device);
|
||||
int device_resume(DEVICE* device);
|
||||
int device_command(void* device, const char* cmd);
|
||||
int device_poll(DEVICE* device);
|
||||
void device_term(DEVICE* device);
|
||||
bool device_fatal(int error);
|
||||
void device_errmsg(char* buff, int len);
|
||||
double device_time_to_next_sample(DEVICE* device);
|
||||
double device_time_to_next_report(DEVICE* device);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user