259 lines
6.3 KiB
C
259 lines
6.3 KiB
C
/*
|
|
* 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
|
|
|
|
void device_send(DEVICE* device, int n)
|
|
{
|
|
BUFFER buffer;
|
|
buffer.length = 0;
|
|
snprintf(buffer.body, sizeof(buffer.body),
|
|
"Time: %s, Value: 0x%06X\r\n",
|
|
make_timestamp(NULL),
|
|
device->value);
|
|
buffer.length = strlen(buffer.body);
|
|
sock_send(n, &buffer);
|
|
}
|
|
|
|
void device_read(DEVICE* device, int n)
|
|
{
|
|
BUFFER buffer;
|
|
buffer.length = 0;
|
|
snprintf(buffer.body, sizeof(buffer.body),
|
|
"READ 0x%06X\r\n",
|
|
device->value);
|
|
buffer.length = strlen(buffer.body);
|
|
sock_send(n, &buffer);
|
|
}
|
|
|
|
void device_write(DEVICE *device, int n, const char* tp)
|
|
{
|
|
unsigned long value;
|
|
|
|
value = strtol(tp, NULL, 16);
|
|
device->out_value = value;
|
|
hware_write(device->private_data, value);
|
|
return;
|
|
}
|
|
|
|
void device_print(DEVICE* device, FILE* fd)
|
|
{
|
|
fprintf(fd, "Time: %s, Value: 0x%06X\r\n",
|
|
make_timestamp(NULL),
|
|
device->value);
|
|
fflush(fd);
|
|
}
|
|
/*
|
|
* Finalise the current sample and move on to the next
|
|
*/
|
|
void device_sample(DEVICE* device)
|
|
{
|
|
device->sample_timer = device->current_time;
|
|
}
|
|
|
|
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;
|
|
char* str = make_timestamp(&device->current_time);
|
|
snprintf(buffer.body, sizeof(buffer.body),
|
|
"%s 0x%06X\r\n",
|
|
str,
|
|
device->value);
|
|
buffer.length = strlen(buffer.body);
|
|
sock_report(&buffer, 1, device);
|
|
snprintf(buffer.body, sizeof(buffer.body),
|
|
"REPORT %s 0x%06X\r\n",
|
|
str,
|
|
device->value);
|
|
buffer.length = strlen(buffer.body);
|
|
sock_report(&buffer, 2, device);
|
|
}
|
|
|
|
/**
|
|
* 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'};
|
|
DEVICE* device = (DEVICE*) malloc(sizeof(DEVICE));
|
|
*cpp = device;
|
|
memset(device, 0, sizeof(DEVICE));
|
|
strncpy(device->name, name, sizeof(device->name));
|
|
device->params.poll_period = 100; /* milliseconds between polls */
|
|
device->params.sample_period = 5; /* polls between sample calcs */
|
|
device->params.report_period = 10; /* samples between reports */
|
|
device->state = device_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));
|
|
device_sample(device);
|
|
return 0;
|
|
Error:
|
|
hware_errmsg(errBuff, sizeof(errBuff));
|
|
printf("DAQmx Error: %s\n", errBuff);
|
|
return error;
|
|
return 0;
|
|
}
|
|
|
|
int device_command(void* dev, const char* command)
|
|
{
|
|
// TODO
|
|
// DEVICE* device = (DEVICE*)(dev);
|
|
return 0;
|
|
}
|
|
|
|
static void device_event(DEVICE *device, char* event)
|
|
{
|
|
BUFFER buffer;
|
|
sprintf(buffer.body, "EVENT %s %s\r\n",
|
|
make_timestamp(&device->current_time),
|
|
event);
|
|
buffer.length = strlen(buffer.body);
|
|
dbg_printf(0, "%s", buffer.body);
|
|
sock_report(&buffer, 1, device);
|
|
sock_report(&buffer, 2, device);
|
|
}
|
|
|
|
/*
|
|
* poll the physical counter
|
|
*/
|
|
int device_poll(DEVICE* device)
|
|
{
|
|
char errBuff[2048]={'\0'};
|
|
HWARE_VALUE current_local_value;
|
|
int error=0;
|
|
|
|
#if 0
|
|
dbg_printf(0, "%s:-%s %s %4d\n",
|
|
device->name,
|
|
make_timestamp(&device->current_time),
|
|
make_timestamp(&device->report_timer),
|
|
device_time_to_next_report(device));
|
|
#endif
|
|
/* read the value from the hardware to a temp */
|
|
++device->poll_counter;
|
|
HWARE_TEST(hware_read(device->private_data, ¤t_local_value));
|
|
dbg_printf(0, "device_poll = 0x%06X @ %s\n",
|
|
current_local_value,
|
|
make_timestamp(&device->current_time));
|
|
|
|
if ((current_local_value != device->value)
|
|
|| (current_local_value != device->new_value))
|
|
{
|
|
if (current_local_value != device->new_value)
|
|
{
|
|
device->new_value = current_local_value;
|
|
device->new_count = device->params.sample_period;
|
|
}
|
|
else if (--device->new_count <= 0)
|
|
{
|
|
char str[100];
|
|
snprintf(str, sizeof(str), "changed 0x%06X 0x%06X",
|
|
current_local_value,
|
|
device->value);
|
|
device_event(device, str);
|
|
device->value = current_local_value;
|
|
}
|
|
}
|
|
/* 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)
|
|
{
|
|
device_report(device);
|
|
}
|
|
device_sample(device);
|
|
}
|
|
|
|
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 = device_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;
|
|
}
|