Commit aed78e7f authored by franksen's avatar franksen
Browse files

first version

parent 19634194
TOP=..
include $(TOP)/config/CONFIG_APP
include $(TOP)/config/RULES_ARCHS
# Makefile.Vx
TOP = ../..
include $(TOP)/config/CONFIG_APP
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
SRCS.c = devSoftPs.c
PROD = devSoftPs.o
DBDINSTALL += devSoftPs.dbd
DBDINSTALL += devSoftPs.LDOBJS
include $(TOP)/config/RULES.Vx
#----------------------------------------
# ADD RULES AFTER THIS LINE
LDOBJS += devSoftPs.o
#include <vxWorks.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <alarm.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <dbStaticLib.h>
#include <recSup.h>
#include <devSup.h>
#include <link.h>
#include <aoRecord.h>
#include <aiRecord.h>
/* Create the dset for devAoSoftPs */
static long init_record_ao();
static long write_ao();
static long report();
#if 0
static long init();
#endif
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_ao;
DEVSUPFUN special_linconv;
}devAoSoftPs={
6,
report,
NULL,
init_record_ao,
NULL,
write_ao,
NULL
};
/* Create the dset for devAiSoftPs */
static long init_record_ai();
static long read_ai();
#if 0
static long get_ioint_info();
#endif
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_ai;
DEVSUPFUN special_linconv;
}devAiSoftPs={
6,
report,
NULL,
init_record_ai,
/* get_ioint_info, */
NULL,
read_ai,
NULL
};
/* Internal structures */
/* one per power supply */
struct ps {
struct ps *next;
double set_val, abs_set_val;
struct dbAddr set;
struct dbAddr rdbk;
struct offset *offsets;
};
/* one per offset channel per power supply */
struct offset {
struct offset *next;
struct ps *pps;
const char *name;
double set_val, abs_set_val;
dbCommon *set, *rdbk;
};
static struct ps *root;
static struct ps *search_ps(struct dbAddr *pset, struct dbAddr *prdbk)
{
struct ps *pps;
struct dbAddr *pps_set;
struct dbAddr *pps_rdbk;
/* simple linear search for name */
for (pps = root; pps; pps = pps->next) {
pps_set = &pps->set;
pps_rdbk = &pps->rdbk;
if (pps_set->precord==pset->precord&&pps_rdbk->precord==prdbk->precord) {
return pps;
}
}
/* not found -> create new and link into list */
pps = (struct ps *)dbCalloc(1, sizeof(struct ps));
pps->next = root;
root = pps;
/* setup with what we have */
pps->set = *pset;
pps->rdbk = *prdbk;
return pps;
}
static struct offset *search_offset(struct ps *pps, const char *name)
{
struct offset *poffset;
/* simple linear search for name */
for (poffset = pps->offsets; poffset; poffset = poffset->next) {
if (strcmp(poffset->name, name) == 0) {
return poffset;
}
}
/* not found -> create new and link into list */
poffset = (struct offset *)dbCalloc(1, sizeof(struct offset));
poffset->next = pps->offsets;
pps->offsets = poffset;
/* setup with what we have */
poffset->pps = pps;
poffset->name = name;
return poffset;
}
static struct offset *analyze_link_data(char *string)
{
struct ps *pps;
struct offset *poffset;
struct dbAddr sum_set_addr, sum_rdbk_addr;
long res;
char full_name[40];
char *pp[4];
char *offset_name, *sum_set_name, *sum_rdbk_name, *dev_name;
int i;
if (!string) {
errlogPrintf("No string\n");
return NULL;
}
#if 0
else
printf("string=%s\n",string);
#endif
for (i=0; i<4 && string; i++) {
pp[i] = string;
string = strpbrk(pp[i],",");
if (string) { *string = 0; string++; }
}
offset_name=pp[0];
sum_set_name=pp[1];
sum_rdbk_name=pp[2];
dev_name=pp[3];
#if 0
if (offset_name) printf("offset_name=%s\n",offset_name);
if (sum_set_name) printf("sum_set_name=%s\n",sum_set_name);
if (sum_rdbk_name) printf("sum_rdbk_name=%s\n",sum_rdbk_name);
if (dev_name) printf("dev_name=%s\n",dev_name);
#endif
if (!offset_name || !sum_rdbk_name || !sum_set_name || !dev_name) {
errlogPrintf("Wrong number of parameters\n");
return NULL;
}
sprintf(full_name, "%s:%s", dev_name, sum_set_name);
res = dbNameToAddr(full_name, &sum_set_addr);
if (res != OK) {
errlogPrintf("Cannot find record %s\n", full_name);
return NULL;
}
sprintf(full_name, "%s:%s", dev_name, sum_rdbk_name);
res = dbNameToAddr(full_name, &sum_rdbk_addr);
if (res != OK) {
errlogPrintf("Cannot find record %s\n", full_name);
return NULL;
}
pps = search_ps(&sum_set_addr, &sum_rdbk_addr);
poffset = search_offset(pps, offset_name);
return poffset;
}
static long init_record_ao(aoRecord *pao)
{
struct offset *poffset;
struct pv_link * plink;
if (pao->out.type != INST_IO) {
recGblRecordError(S_db_badField, pao,
"devAoSoftPs (init_record) Illegal OUT field");
pao->pact = TRUE;
return S_db_badField;
}
poffset = analyze_link_data(pao->out.value.instio.string);
if (!poffset) {
recGblRecordError(S_db_badField, pao,
"devAoSoftPs (init_record) Illegal OUT field");
pao->pact = TRUE;
return S_db_badField;
}
pao->dpvt = poffset;
poffset->set = (dbCommon *)pao;
/* reconfigure our OUT link */
pao->out.type = DB_LINK;
plink = &pao->out.value.pv_link;
plink->pvname = poffset->pps->set.precord->name;
plink->precord = (dbCommon *)pao;
plink->pvt = &poffset->pps->set; /* target the sum set value */
plink->getCvt = NULL;
plink->pvlMask = pvlOptPP | pvlOptMS;
plink->lastGetdbrType = 0;
/* Make sure record processing routine does not perform any conversion */
pao->linr = 0;
return 2; /* no warm reboot */
}
static long init_record_ai(struct aiRecord *pai)
{
struct offset *poffset;
struct pv_link * plink;
if (pai->inp.type != INST_IO) {
recGblRecordError(S_db_badField, pai,
"devAiSoftPs (init_record) Illegal INP field");
pai->pact = TRUE;
return S_db_badField;
}
poffset = analyze_link_data(pai->inp.value.instio.string);
if (!poffset) {
recGblRecordError(S_db_badField, pai,
"devAiSoftPs (init_record) Illegal INP field");
pai->pact = TRUE;
return S_db_badField;
}
pai->dpvt = poffset;
poffset->rdbk = (dbCommon *)pai;
/* reconfigure our INP link */
pai->inp.type = CA_LINK;
plink = &pai->inp.value.pv_link;
plink->pvname = poffset->pps->rdbk.precord->name;
plink->precord = (dbCommon *)pai;
plink->pvt = NULL;
plink->getCvt = NULL;
plink->pvlMask = pvlOptCPP | pvlOptMS | pvlOptInpNative;
plink->lastGetdbrType = 0;
dbCaAddLink(&pai->inp);
/* Make sure record processing routine does not perform any conversion */
pai->linr = 0;
return(0);
}
static long write_ao(struct aoRecord *pao)
{
long status/* , options = 0, nelements = 1 */;
struct offset *po;
struct offset *poffset = (struct offset *)pao->dpvt;
struct ps *pps = poffset->pps;
double value = 0.0;
poffset->set_val = pao->val;
poffset->abs_set_val = fabs(pao->val);
for (po = pps->offsets; po; po = po->next) {
value += po->set_val;
}
pps->set_val = value;
pps->abs_set_val = fabs(value);
status = dbPutLink(&pao->out, DBR_DOUBLE, &value, 1);
return status;
}
static long read_ai(struct aiRecord *pai)
{
long status, options=0, nelements=1;
struct offset *po;
struct offset *poffset = (struct offset *)pai->dpvt;
struct ps *pps = poffset->pps;
double abs_sum_set_val = 0.0, set_val = 0.0;
double sum_set_val, sum_rdbk_val, diff, abs_set_val;
status = dbGetLink(&pai->inp, DBR_DOUBLE, &sum_rdbk_val, &options, &nelements);
if (status) return status;
sum_set_val = pps->set_val;
set_val = poffset->set_val;
abs_set_val = poffset->abs_set_val;
for (po = pps->offsets; po; po = po->next) {
abs_sum_set_val += po->abs_set_val;
}
diff = sum_rdbk_val - sum_set_val;
/* :TODO: should define some epsilon depending on max set value */
if (abs_sum_set_val > 0.0) {
diff *= abs_set_val / abs_sum_set_val;
}
pai->val = set_val + diff;
pai->udf = FALSE;
return 2; /* don't convert */
}
#if 0
static long init(int pass)
{
struct ps *pps;
struct offset *poffset;
long status = 0;
static int done = FALSE;
if (done || pass==0) return 0;
/* check the whole list and merge lock sets */
for (pps = root; pps; pps = pps->next) {
dbLockSetMerge(pps->set.precord, pps->rdbk.precord);
for (poffset = pps->offsets; poffset; poffset = poffset->next) {
dbLockSetMerge(pps->rdbk.precord, poffset->set);
if (!poffset->set) {
errlogPrintf("devSoftPs (init/1) no setpoint record for %s\n", poffset->name);
status = -1;
}
}
}
done = TRUE;
return status;
}
#endif
static long report(int level)
{
struct ps *pps;
struct offset *poffset;
long status = 0;
/* check the whole list */
for (pps = root; pps; pps = pps->next) {
printf("ps: set=%s, rdbk=%s\n",pps->set.precord->name,pps->rdbk.precord->name);
if (level > 1) {
printf(" set_val=%f, abs_set_val=%f\n",pps->set_val, pps->abs_set_val);
}
if (level > 0)
for (poffset = pps->offsets; poffset; poffset = poffset->next) {
printf(" offset: rdbk=%s, set=%s\n",poffset->rdbk->name,poffset->set->name);
if (level > 1) {
printf(" set_val=%f, abs_set_val=%f\n",poffset->set_val, poffset->abs_set_val);
}
if (!poffset->set) {
printf("devSoftPs (report) no setpoint record for %s\n", poffset->name);
status = -1;
}
}
}
return status;
}
device(ai, INST_IO, devAiSoftPs, "Soft PS")
device(ao, INST_IO, devAoSoftPs, "Soft PS")
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment