Files
sics/site_ansto/hardsup/Digital/device.c
2014-05-16 17:23:44 +10:00

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, &current_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;
}