Files
epics-base/modules/database/src/std/dev/devGeneralTime.c
Andrew Johnson 3c99391d93 Added SPDX License ID to all EPICS-original source files
In some cases the license-identification header was missing,
so I added that as well. Replaced the remaining headers that
specifically identified "Versions 3.13.7 and higher".

Makefiles and the build system were deliberately excluded.
2020-08-03 11:53:01 -05:00

295 lines
6.8 KiB
C

/*************************************************************************\
* SPDX-License-Identifier: EPICS
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Original Author: Sheng Peng, ORNL / SNS Project
* Date: 07/2004
*
* EPICS device support for general timestamp support
*
* Integrated into base by Peter Denison, Diamond Light Source
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "alarm.h"
#include "dbDefs.h"
#include "dbAccess.h"
#include "recGbl.h"
#include "devSup.h"
#include "epicsString.h"
#include "epicsGeneralTime.h"
#include "aiRecord.h"
#include "boRecord.h"
#include "longinRecord.h"
#include "stringinRecord.h"
#include "epicsExport.h"
/********* ai record **********/
static int getCurrentTime(double * pseconds)
{
epicsTimeStamp ts;
if (epicsTimeOK == epicsTimeGetCurrent(&ts)) {
*pseconds = ts.secPastEpoch + ((double)(ts.nsec)) * 1e-9;
return 0;
}
return -1;
}
static struct ai_channel {
char *name;
int (*get)(double *);
} ai_channels[] = {
{"TIME", getCurrentTime},
};
static long init_ai(dbCommon *pcommon)
{
aiRecord *prec = (aiRecord *)pcommon;
int i;
if (prec->inp.type != INST_IO) {
recGblRecordError(S_db_badField, (void *)prec,
"devAiGeneralTime::init_ai: Illegal INP field");
prec->pact = TRUE;
return S_db_badField;
}
for (i = 0; i < NELEMENTS(ai_channels); i++) {
struct ai_channel *pchan = &ai_channels[i];
if (!epicsStrCaseCmp(prec->inp.value.instio.string, pchan->name)) {
prec->dpvt = pchan;
return 0;
}
}
recGblRecordError(S_db_badField, (void *)prec,
"devAiGeneralTime::init_ai: Bad parm");
prec->pact = TRUE;
prec->dpvt = NULL;
return S_db_badField;
}
static long read_ai(aiRecord *prec)
{
struct ai_channel *pchan = (struct ai_channel *)prec->dpvt;
if (!pchan) return -1;
if (pchan->get(&prec->val) == 0) {
prec->udf = FALSE;
return 2;
}
prec->udf = TRUE;
recGblSetSevr(prec, READ_ALARM, INVALID_ALARM);
return -1;
}
aidset devAiGeneralTime = {
{6, NULL, NULL, init_ai, NULL},
read_ai, NULL
};
epicsExportAddress(dset, devAiGeneralTime);
/********* bo record **********/
static void resetErrors(void)
{
generalTimeResetErrorCounts();
}
static struct bo_channel {
char *name;
void (*put)(void);
} bo_channels[] = {
{"RSTERRCNT", resetErrors},
};
static long init_bo(dbCommon *pcommon)
{
boRecord *prec = (boRecord *)pcommon;
int i;
if (prec->out.type != INST_IO) {
recGblRecordError(S_db_badField, (void *)prec,
"devAiGeneralTime::init_ai: Illegal INP field");
prec->pact = TRUE;
return S_db_badField;
}
for (i = 0; i < NELEMENTS(bo_channels); i++) {
struct bo_channel *pchan = &bo_channels[i];
if (!epicsStrCaseCmp(prec->out.value.instio.string, pchan->name)) {
prec->dpvt = pchan;
prec->mask = 0;
return 2;
}
}
recGblRecordError(S_db_badField, (void *)prec,
"devBoGeneralTime::init_bo: Bad parm");
prec->pact = TRUE;
prec->dpvt = NULL;
return S_db_badField;
}
static long write_bo(boRecord *prec)
{
struct bo_channel *pchan = (struct bo_channel *)prec->dpvt;
if (!pchan) return -1;
pchan->put();
return 0;
}
bodset devBoGeneralTime = {
{5, NULL, NULL, init_bo, NULL},
write_bo
};
epicsExportAddress(dset, devBoGeneralTime);
/******* longin record *************/
static int errorCount(void)
{
return generalTimeGetErrorCounts();
}
static struct li_channel {
char *name;
int (*get)(void);
} li_channels[] = {
{"GETERRCNT", errorCount},
};
static long init_li(dbCommon *pcommon)
{
longinRecord *prec = (longinRecord *)pcommon;
int i;
if (prec->inp.type != INST_IO) {
recGblRecordError(S_db_badField, (void *)prec,
"devLiGeneralTime::init_li: Illegal INP field");
prec->pact = TRUE;
return S_db_badField;
}
for (i = 0; i < NELEMENTS(li_channels); i++) {
struct li_channel *pchan = &li_channels[i];
if (!epicsStrCaseCmp(prec->inp.value.instio.string, pchan->name)) {
prec->dpvt = pchan;
return 0;
}
}
recGblRecordError(S_db_badField, (void *)prec,
"devLiGeneralTime::init_li: Bad parm");
prec->pact = TRUE;
prec->dpvt = NULL;
return S_db_badField;
}
static long read_li(longinRecord *prec)
{
struct li_channel *pchan = (struct li_channel *)prec->dpvt;
if (!pchan) return -1;
prec->val = pchan->get();
return 0;
}
longindset devLiGeneralTime = {
{5, NULL, NULL, init_li, NULL},
read_li
};
epicsExportAddress(dset, devLiGeneralTime);
/********** stringin record **********/
static const char * timeProvider(void)
{
return generalTimeCurrentProviderName();
}
static const char * highestProvider(void)
{
return generalTimeHighestCurrentName();
}
static const char * eventProvider(void)
{
return generalTimeEventProviderName();
}
static struct si_channel {
char *name;
const char * (*get)(void);
} si_channels[] = {
{"BESTTCP", timeProvider},
{"TOPTCP", highestProvider},
{"BESTTEP", eventProvider},
};
static long init_si(dbCommon *pcommon)
{
stringinRecord *prec = (stringinRecord *)pcommon;
int i;
if (prec->inp.type != INST_IO) {
recGblRecordError(S_db_badField, (void *)prec,
"devSiGeneralTime::init_si: Illegal INP field");
prec->pact = TRUE;
return S_db_badField;
}
for (i = 0; i < NELEMENTS(si_channels); i++) {
struct si_channel *pchan = &si_channels[i];
if (!epicsStrCaseCmp(prec->inp.value.instio.string, pchan->name)) {
prec->dpvt = pchan;
return 0;
}
}
recGblRecordError(S_db_badField, (void *)prec,
"devSiGeneralTime::init_si: Bad parm");
prec->pact = TRUE;
prec->dpvt = NULL;
return S_db_badField;
}
static long read_si(stringinRecord *prec)
{
struct si_channel *pchan = (struct si_channel *)prec->dpvt;
const char *name;
if (!pchan) return -1;
name = pchan->get();
if (name) {
strncpy(prec->val, name, sizeof(prec->val));
prec->val[sizeof(prec->val) - 1] = '\0';
} else {
strcpy(prec->val, "No working providers");
recGblSetSevr(prec, READ_ALARM, MAJOR_ALARM);
}
prec->udf = FALSE;
return 0;
}
stringindset devSiGeneralTime = {
{5, NULL, NULL, init_si, NULL},
read_si
};
epicsExportAddress(dset, devSiGeneralTime);