Merge lp:~dirk.zimoch/epics-base/fix-aai-and-aao into lp:~epics-core/epics-base/3.14

Proposed by Dirk Zimoch
Status: Merged
Approved by: Andrew Johnson
Approved revision: 12079
Merge reported by: Andrew Johnson
Merged at revision: not available
Proposed branch: lp:~dirk.zimoch/epics-base/fix-aai-and-aao
Merge into: lp:~epics-core/epics-base/3.14
Diff against target: 895 lines (+434/-101)
10 files modified
documentation/RELEASE_NOTES.html (+7/-0)
src/dev/softDev/Makefile (+2/-0)
src/dev/softDev/devAaiSoft.c (+87/-0)
src/dev/softDev/devAaoSoft.c (+79/-0)
src/dev/softDev/devSoft.dbd (+2/-0)
src/misc/base.dbd (+2/-0)
src/rec/aaiRecord.c (+103/-52)
src/rec/aaiRecord.dbd (+25/-0)
src/rec/aaoRecord.c (+102/-49)
src/rec/aaoRecord.dbd (+25/-0)
To merge this branch: bzr merge lp:~dirk.zimoch/epics-base/fix-aai-and-aao
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Review via email: mp+26195@code.launchpad.net

This proposal supersedes a proposal from 2010-05-27.

Description of the change

* Bugfix: writing to aai/aao via db link crashed ioc. Memory allocation / device support init_record moved to pass 0.
* Soft device support for aai and aao added.
* Simulation mode fixed. SIOL link added. (sim handling is done in devsup!)
* Bugfix: writing to aai/aao modified NELM. Modify NORD instead.
* Hashing added to minimize monitor updates (like in waveform record)

Discussion:
Add features like RVAL->VAL conversion, scaling, smoothing, alarm limits?

To post a comment you must log in.
12076. By Dirk Zimoch <dirk@ubuntu>

release notes updated

12077. By Dirk Zimoch <dirk@ubuntu>

Merged with 3.14

Revision history for this message
Ralph Lange (ralph-lange) wrote : Posted in a previous version of this proposal

Looked at the code - the changes look fine to me.

As I never used the aai/aao records, I don't see me being the right person for testing and proper evaluation of the changes in behaviour, though.

Revision history for this message
Andrew Johnson (anj) wrote :

Hi Dirk,

When SIMM=YES, the aai record is put into alarm using the SIMS field for the severity. The aao record always goes to INVALID_ALARM in simulation mode.

Do you know under what circumstances a device support might want to set BPTR itself? The comment about calling the pdset->init_record() in pass 0 implies that run-time changes of the device address wouldn't be possible in that case (which is in the device support's power to allow if it uses devExtend(), but prevented if it doesn't).

Have you ever seen any written documentation for the aai/aao record types? There are no chapters for them in the Record Reference wiki yet.

I haven't started actually testing this code yet (that's my next task), but so far I think this work should be merged into R3.14.12.

- Andrew

Revision history for this message
Ben Franksen (bfrk) wrote :

On Freitag, 2. Juli 2010, Andrew Johnson wrote:
> Do you know under what circumstances a device support might want to set
> BPTR itself?

Slightly off-topic, but I suggest removing BPTR and use VAL field instead.
VAL is not used for anything at the moment, AFAIR, and is also
DBF_NOACCESS, so this is even compatible (but not for device support, maybe
this is the reason this hasn't been done before?).

Same for waveform record, BTW.

Cheers
Ben

Revision history for this message
Andrew Johnson (anj) wrote :

Hi Ben,

Interesting point, although not relevant to the review of this particular branch. Making that change to the records would require a corresponding modification to all device supports, so it's not something I'd want to do for 3.14.12. I guess removing the BPTR fields completely would cause any unmodified code to fail at compile-time (which is what we'd want), so it's not an impossible idea for 3.15.

Thanks,

- Andrew

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

Andrew,

> The aao record always goes to INVALID_ALARM in simulation mode.
I missed that. It should use the SIMS field as well. As soon as I get bazaar installed on this computer, I will fix that.

I have never seen documentation on the aai/aao records, but I guess that the intention was to set BPTR directly to memory mapped register space to save the time for copying data. But this has several disadvantages:
* BPTR must be set early enough (fixed now)
* BPTR must not change at run time (e.g. no double buffering). I have to check what devExtend() does to solve this problem.
* As a result, BPTR may contain inconsistent data if the hardware modifies the buffer while it is being read (e.g. by a CA read or monitor)

I kept the memory allocation model to stay compatible to old device supports. Additionally I allow for new device supports not to set BPTR. Also to stay compatible, I do not want to switch from BPTR to VAL.

Basically the aai is the same as the waveform record except that it does not have a RARM field. The aao is the only record that is intended to write arrays. (The waveform can write through its INP if the device support allows. But if we do so, why do we need ai/ao, mbbi/mbbo, etc. pairs?)

Revision history for this message
Andrew Johnson (anj) wrote :

On Monday 05 July 2010 03:02:23 Dirk Zimoch wrote:
>
> * BPTR must not change at run time (e.g. no double buffering). I have to
> check what devExtend() does to solve this problem.

Sorry, devExtend() is the way that a device support tells the iocCore code
that it can accept address changes at runtime; it doesn't solve that problem.
The devExtend() routine must be called from a dset->init() routine and points
to a dsxt structure with the add_record() and del_record() routines that
support those runtime changes for this device support. My point was merely
that if BPTR can't be changed after rset->init_record(0) returns [presumably
because this somehow stops DB links from working] that it's not going to be
possible to have extended device support that sets BPTR. Not a major issue,
and there are no incompatibilities here.

> I kept the memory allocation model to stay compatible to old device
> supports. Additionally I allow for new device supports not to set BPTR.
> Also to stay compatible, I do not want to switch from BPTR to VAL.

I agree that this is the best solution for now.

Thanks,

- Andrew
--
The best FOSS code is written to be read by other humans -- Harald Welte

Revision history for this message
Dirk Zimoch (dirk.zimoch) wrote :

What we really need to make this work as intended, i.e. modify BPTR at run-time to point to the current data, is a way to tell a link, a CA connection, and maybe other EPICS components that the address of the data has changed. But this is a completely different problem.

12078. By Dirk Zimoch <dirk@ubuntu>

Bugfix: use SIMS for simulation severity

12079. By Dirk Zimoch <dirk@ubuntu>

Merged with mirror-3.14

Revision history for this message
Andrew Johnson (anj) wrote :

Asynchronous processing doesn't work because of the line
    if (pact) return 0;
in the process() routines of both record types.

With those lines removed I'm happy with the result, so I will merge the code.

Thanks,

- Andrew

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'documentation/RELEASE_NOTES.html'
--- documentation/RELEASE_NOTES.html 2010-07-01 16:59:22 +0000
+++ documentation/RELEASE_NOTES.html 2010-07-07 17:48:44 +0000
@@ -11,6 +11,13 @@
1111
12<h2 align="center">Changes between 3.14.11 and 3.14.12</h2>12<h2 align="center">Changes between 3.14.11 and 3.14.12</h2>
13<!-- Insert new items immediately below here ... -->13<!-- Insert new items immediately below here ... -->
14<h4>Record Types aai and aao</h4>
15<p>Fixed bug in memory allocation that caused crashes when linking other records
16to aai or aao.
17Fixed bug where NELM was modified instead of NORD.
18Added Soft Channel device support.
19Added SIOL link and proper simulation mode for Soft Channel support.
20Added MPST, APST and HASH fields for monitor on change support like in waveform record.
1421
1522
16<h4>devLib cleanup</h4>23<h4>devLib cleanup</h4>
1724
=== modified file 'src/dev/softDev/Makefile'
--- src/dev/softDev/Makefile 2008-09-24 22:40:37 +0000
+++ src/dev/softDev/Makefile 2010-07-07 17:48:44 +0000
@@ -12,6 +12,8 @@
1212
13DBD += devSoft.dbd13DBD += devSoft.dbd
1414
15LIBSRCS += devAaiSoft.c
16LIBSRCS += devAaoSoft.c
15LIBSRCS += devAiSoft.c17LIBSRCS += devAiSoft.c
16LIBSRCS += devAiSoftRaw.c18LIBSRCS += devAiSoftRaw.c
17LIBSRCS += devAoSoft.c19LIBSRCS += devAoSoft.c
1820
=== added file 'src/dev/softDev/devAaiSoft.c'
--- src/dev/softDev/devAaiSoft.c 1970-01-01 00:00:00 +0000
+++ src/dev/softDev/devAaiSoft.c 2010-07-07 17:48:44 +0000
@@ -0,0 +1,87 @@
1/*************************************************************************\
2* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.
6* EPICS BASE is distributed subject to a Software License Agreement found
7* in file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/* $Id$
11 * devAaiSoft.c - Device Support Routines for soft Waveform Records
12 *
13 * Original Author: Bob Dalesio
14 * Current Author: Dirk Zimoch
15 * Date: 27-MAY-2010
16 */
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21
22#include "alarm.h"
23#include "dbDefs.h"
24#include "dbAccess.h"
25#include "recGbl.h"
26#include "devSup.h"
27#include "cantProceed.h"
28#include "menuYesNo.h"
29#include "aaiRecord.h"
30#include "epicsExport.h"
31
32/* Create the dset for devAaiSoft */
33static long init_record();
34static long read_aai();
35
36struct {
37 long number;
38 DEVSUPFUN report;
39 DEVSUPFUN init;
40 DEVSUPFUN init_record;
41 DEVSUPFUN get_ioint_info;
42 DEVSUPFUN read_aai;
43} devAaiSoft = {
44 5,
45 NULL,
46 NULL,
47 init_record,
48 NULL,
49 read_aai
50};
51epicsExportAddress(dset,devAaiSoft);
52
53static long init_record(aaiRecord *prec)
54{
55 /* INP must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/
56 switch (prec->inp.type) {
57 case CONSTANT:
58 prec->nord = 0;
59 break;
60 case PV_LINK:
61 case DB_LINK:
62 case CA_LINK:
63 break;
64 default :
65 recGblRecordError(S_db_badField, (void *)prec,
66 "devAaiSoft (init_record) Illegal INP field");
67 return(S_db_badField);
68 }
69 return 0;
70}
71
72static long read_aai(aaiRecord *prec)
73{
74 long nRequest = prec->nelm;
75
76 dbGetLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->inp,
77 prec->ftvl, prec->bptr, 0, &nRequest);
78 if (nRequest > 0) {
79 prec->nord = nRequest;
80 prec->udf=FALSE;
81 if (prec->tsel.type == CONSTANT &&
82 prec->tse == epicsTimeEventDeviceTime)
83 dbGetTimeStamp(&prec->inp, &prec->time);
84 }
85
86 return 0;
87}
088
=== added file 'src/dev/softDev/devAaoSoft.c'
--- src/dev/softDev/devAaoSoft.c 1970-01-01 00:00:00 +0000
+++ src/dev/softDev/devAaoSoft.c 2010-07-07 17:48:44 +0000
@@ -0,0 +1,79 @@
1/*************************************************************************\
2* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
3* National Laboratory.
4* Copyright (c) 2002 The Regents of the University of California, as
5* Operator of Los Alamos National Laboratory.
6* EPICS BASE is distributed subject to a Software License Agreement found
7* in file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/* $Id$
11 * devAaoSoft.c - Device Support Routines for soft Waveform Records
12 *
13 * Original Author: Bob Dalesio
14 * Current Author: Dirk Zimoch
15 * Date: 27-MAY-2010
16 */
17
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21
22#include "alarm.h"
23#include "dbDefs.h"
24#include "dbAccess.h"
25#include "recGbl.h"
26#include "devSup.h"
27#include "cantProceed.h"
28#include "menuYesNo.h"
29#include "aaoRecord.h"
30#include "epicsExport.h"
31
32/* Create the dset for devAaoSoft */
33static long init_record();
34static long write_aao();
35
36struct {
37 long number;
38 DEVSUPFUN report;
39 DEVSUPFUN init;
40 DEVSUPFUN init_record;
41 DEVSUPFUN get_ioint_info;
42 DEVSUPFUN read_aao;
43} devAaoSoft = {
44 5,
45 NULL,
46 NULL,
47 init_record,
48 NULL,
49 write_aao
50};
51epicsExportAddress(dset,devAaoSoft);
52
53static long init_record(aaoRecord *prec)
54{
55 /* OUT must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/
56 switch (prec->out.type) {
57 case CONSTANT:
58 prec->nord = 0;
59 break;
60 case PV_LINK:
61 case DB_LINK:
62 case CA_LINK:
63 break;
64 default :
65 recGblRecordError(S_db_badField, prec,
66 "devAaoSoft (init_record) Illegal OUT field");
67 return(S_db_badField);
68 }
69 return 0;
70}
71
72static long write_aao(aaoRecord *prec)
73{
74 long nRequest = prec->nord;
75 dbPutLink(prec->simm == menuYesNoYES ? &prec->siol : &prec->out,
76 prec->ftvl, prec->bptr, nRequest);
77
78 return 0;
79}
080
=== modified file 'src/dev/softDev/devSoft.dbd'
--- src/dev/softDev/devSoft.dbd 2008-09-24 22:40:37 +0000
+++ src/dev/softDev/devSoft.dbd 2010-07-07 17:48:44 +0000
@@ -1,3 +1,5 @@
1device(aai,CONSTANT,devAaiSoft,"Soft Channel")
2device(aao,CONSTANT,devAaoSoft,"Soft Channel")
1device(ai,CONSTANT,devAiSoft,"Soft Channel")3device(ai,CONSTANT,devAiSoft,"Soft Channel")
2device(ao,CONSTANT,devAoSoft,"Soft Channel")4device(ao,CONSTANT,devAoSoft,"Soft Channel")
3device(bi,CONSTANT,devBiSoft,"Soft Channel")5device(bi,CONSTANT,devBiSoft,"Soft Channel")
46
=== modified file 'src/misc/base.dbd'
--- src/misc/base.dbd 2008-08-14 20:41:05 +0000
+++ src/misc/base.dbd 2010-07-07 17:48:44 +0000
@@ -8,6 +8,8 @@
8include "menuConvert.dbd"8include "menuConvert.dbd"
99
10# Record types10# Record types
11include "aaiRecord.dbd"
12include "aaoRecord.dbd"
11include "aiRecord.dbd"13include "aiRecord.dbd"
12include "aoRecord.dbd"14include "aoRecord.dbd"
13include "aSubRecord.dbd"15include "aSubRecord.dbd"
1416
=== modified file 'src/rec/aaiRecord.c'
--- src/rec/aaiRecord.c 2009-07-08 18:14:11 +0000
+++ src/rec/aaiRecord.c 2010-07-07 17:48:44 +0000
@@ -9,7 +9,6 @@
9/* recAai.c - Record Support Routines for Array Analog In records */9/* recAai.c - Record Support Routines for Array Analog In records */
10/*10/*
11 * Original Author: Dave Barker11 * Original Author: Dave Barker
12 * Date: 10/24/93
13 *12 *
14 * C E B A F13 * C E B A F
15 * 14 *
@@ -18,6 +17,8 @@
18 *17 *
19 * Copyright SURA CEBAF 1993.18 * Copyright SURA CEBAF 1993.
20 *19 *
20 * Current Author: Dirk Zimoch <dirk.zimoch@psi.ch>
21 * Date: 27-MAY-2010
21 */22 */
2223
23#include <stddef.h>24#include <stddef.h>
@@ -28,14 +29,17 @@
2829
29#include "dbDefs.h"30#include "dbDefs.h"
30#include "epicsPrint.h"31#include "epicsPrint.h"
32#include "epicsString.h"
31#include "alarm.h"33#include "alarm.h"
32#include "dbAccess.h"34#include "dbAccess.h"
35#include "dbEvent.h"
36#include "dbFldTypes.h"
33#include "dbScan.h"37#include "dbScan.h"
34#include "dbEvent.h"
35#include "devSup.h"38#include "devSup.h"
36#include "errMdef.h"39#include "errMdef.h"
37#include "recSup.h"40#include "recSup.h"
38#include "recGbl.h"41#include "recGbl.h"
42#include "cantProceed.h"
39#include "menuYesNo.h"43#include "menuYesNo.h"
40#define GEN_SIZE_OFFSET44#define GEN_SIZE_OFFSET
41#include "aaiRecord.h"45#include "aaiRecord.h"
@@ -48,7 +52,7 @@
48static long init_record(aaiRecord *, int);52static long init_record(aaiRecord *, int);
49static long process(aaiRecord *);53static long process(aaiRecord *);
50#define special NULL54#define special NULL
51static long get_value(aaiRecord *, struct valueDes *);55#define get_value NULL
52static long cvt_dbaddr(DBADDR *);56static long cvt_dbaddr(DBADDR *);
53static long get_array_info(DBADDR *, long *, long *);57static long get_array_info(DBADDR *, long *, long *);
54static long put_array_info(DBADDR *, long);58static long put_array_info(DBADDR *, long);
@@ -84,43 +88,67 @@
84epicsExportAddress(rset,aaiRSET);88epicsExportAddress(rset,aaiRSET);
8589
86struct aaidset { /* aai dset */90struct aaidset { /* aai dset */
87 long number;91 long number;
88 DEVSUPFUN dev_report;92 DEVSUPFUN dev_report;
89 DEVSUPFUN init;93 DEVSUPFUN init;
90 DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/94 DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
91 DEVSUPFUN get_ioint_info;95 DEVSUPFUN get_ioint_info;
92 DEVSUPFUN read_aai; /*returns: (-1,0)=>(failure,success)*/96 DEVSUPFUN read_aai; /*returns: (-1,0)=>(failure,success)*/
93};97};
9498
95static void monitor(aaiRecord *);99static void monitor(aaiRecord *);
96static long readValue(aaiRecord *);100static long readValue(aaiRecord *);
97101
98
99static long init_record(aaiRecord *prec, int pass)102static long init_record(aaiRecord *prec, int pass)
100{103{
101 struct aaidset *pdset;
102 long status;104 long status;
105 struct aaidset *pdset = (struct aaidset *)(prec->dset);
103106
107 /* must have dset defined */
108 if (!pdset) {
109 recGblRecordError(S_dev_noDSET, prec, "aai: init_record");
110 return S_dev_noDSET;
111 }
112
104 if (pass == 0) {113 if (pass == 0) {
105 if (prec->nelm <= 0) prec->nelm = 1;114 if (prec->nelm <= 0)
115 prec->nelm = 1;
116 if (prec->ftvl > DBF_ENUM)
117 prec->ftvl = DBF_UCHAR;
118 if (prec->nelm == 1) {
119 prec->nord = 1;
120 } else {
121 prec->nord = 0;
122 }
123
124 /* we must call pdset->init_record in pass 0
125 because it may set prec->bptr which must
126 not change after links are established before pass 1
127 */
128
129 if (pdset->init_record) {
130 /* init_record may set the bptr to point to the data */
131 if ((status = pdset->init_record(prec)))
132 return status;
133 }
134 if (!prec->bptr) {
135 /* device support did not allocate memory so we must do it */
136 prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl),
137 "aai: buffer calloc failed");
138 }
106 return 0;139 return 0;
107 }140 }
108 recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);141
109 /* must have dset defined */142 /* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */
110 if (!(pdset = (struct aaidset *)(prec->dset))) {143 if (prec->siml.type == CONSTANT) {
111 recGblRecordError(S_dev_noDSET, (void *)prec, "aai: init_record");144 recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
112 return S_dev_noDSET;
113 }145 }
146
114 /* must have read_aai function defined */147 /* must have read_aai function defined */
115 if (pdset->number < 5 || pdset->read_aai == NULL) {148 if (pdset->number < 5 || pdset->read_aai == NULL) {
116 recGblRecordError(S_dev_missingSup, (void *)prec, "aai: init_record");149 recGblRecordError(S_dev_missingSup, prec, "aai: init_record");
117 return S_dev_missingSup;150 return S_dev_missingSup;
118 }151 }
119 if (pdset->init_record) {
120 /* init_record sets the bptr to point to the data */
121 if ((status = pdset->init_record(prec)))
122 return status;
123 }
124 return 0;152 return 0;
125}153}
126154
@@ -132,14 +160,13 @@
132160
133 if (pdset == NULL || pdset->read_aai == NULL) {161 if (pdset == NULL || pdset->read_aai == NULL) {
134 prec->pact = TRUE;162 prec->pact = TRUE;
135 recGblRecordError(S_dev_missingSup, (void *)prec, "read_aai");163 recGblRecordError(S_dev_missingSup, prec, "read_aai");
136 return S_dev_missingSup;164 return S_dev_missingSup;
137 }165 }
138166
139 if (pact) return 0;167 if (pact) return 0;
140168
141 status = readValue(prec); /* read the new value */169 status = readValue(prec); /* read the new value */
142 /* check if device support set pact */
143 if (!pact && prec->pact) return 0;170 if (!pact && prec->pact) return 0;
144 prec->pact = TRUE;171 prec->pact = TRUE;
145172
@@ -151,22 +178,14 @@
151 recGblFwdLink(prec);178 recGblFwdLink(prec);
152179
153 prec->pact = FALSE;180 prec->pact = FALSE;
154 return 0;181 return status;
155}
156
157static long get_value(aaiRecord *prec, struct valueDes *pvdes)
158{
159 pvdes->no_elements = prec->nelm;
160 pvdes->pvalue = prec->bptr;
161 pvdes->field_type = prec->ftvl;
162 return 0;
163}182}
164183
165static long cvt_dbaddr(DBADDR *paddr)184static long cvt_dbaddr(DBADDR *paddr)
166{185{
167 aaiRecord *prec = (aaiRecord *)paddr->precord;186 aaiRecord *prec = (aaiRecord *)paddr->precord;
168187
169 paddr->pfield = (void *)(prec->bptr);188 paddr->pfield = prec->bptr;
170 paddr->no_elements = prec->nelm;189 paddr->no_elements = prec->nelm;
171 paddr->field_type = prec->ftvl;190 paddr->field_type = prec->ftvl;
172 paddr->field_size = dbValueSize(prec->ftvl);191 paddr->field_size = dbValueSize(prec->ftvl);
@@ -178,7 +197,7 @@
178{197{
179 aaiRecord *prec = (aaiRecord *)paddr->precord;198 aaiRecord *prec = (aaiRecord *)paddr->precord;
180199
181 *no_elements = prec->nelm;200 *no_elements = prec->nord;
182 *offset = 0;201 *offset = 0;
183 return 0;202 return 0;
184}203}
@@ -187,7 +206,9 @@
187{206{
188 aaiRecord *prec = (aaiRecord *)paddr->precord;207 aaiRecord *prec = (aaiRecord *)paddr->precord;
189208
190 prec->nelm = nNew;209 prec->nord = nNew;
210 if (prec->nord > prec->nelm)
211 prec->nord = prec->nelm;
191 return 0;212 return 0;
192}213}
193214
@@ -204,7 +225,7 @@
204 aaiRecord *prec = (aaiRecord *)paddr->precord;225 aaiRecord *prec = (aaiRecord *)paddr->precord;
205226
206 *precision = prec->prec;227 *precision = prec->prec;
207 if (paddr->pfield == (void *)prec->bptr) return 0;228 if (paddr->pfield == prec->bptr) return 0;
208 recGblGetPrec(paddr, precision);229 recGblGetPrec(paddr, precision);
209 return 0;230 return 0;
210}231}
@@ -213,7 +234,7 @@
213{234{
214 aaiRecord *prec = (aaiRecord *)paddr->precord;235 aaiRecord *prec = (aaiRecord *)paddr->precord;
215236
216 if (paddr->pfield == (void *)prec->bptr) {237 if (paddr->pfield == prec->bptr) {
217 pgd->upper_disp_limit = prec->hopr;238 pgd->upper_disp_limit = prec->hopr;
218 pgd->lower_disp_limit = prec->lopr;239 pgd->lower_disp_limit = prec->lopr;
219 } else recGblGetGraphicDouble(paddr, pgd);240 } else recGblGetGraphicDouble(paddr, pgd);
@@ -224,7 +245,7 @@
224{245{
225 aaiRecord *prec = (aaiRecord *)paddr->precord;246 aaiRecord *prec = (aaiRecord *)paddr->precord;
226247
227 if (paddr->pfield == (void *)prec->bptr) {248 if (paddr->pfield == prec->bptr) {
228 pcd->upper_ctrl_limit = prec->hopr;249 pcd->upper_ctrl_limit = prec->hopr;
229 pcd->lower_ctrl_limit = prec->lopr;250 pcd->lower_ctrl_limit = prec->lopr;
230 } else recGblGetControlDouble(paddr, pcd);251 } else recGblGetControlDouble(paddr, pcd);
@@ -234,9 +255,35 @@
234static void monitor(aaiRecord *prec)255static void monitor(aaiRecord *prec)
235{256{
236 unsigned short monitor_mask;257 unsigned short monitor_mask;
258 unsigned int hash = 0;
237259
238 monitor_mask = recGblResetAlarms(prec);260 monitor_mask = recGblResetAlarms(prec);
239 monitor_mask |= (DBE_LOG | DBE_VALUE);261
262 if (prec->mpst == aaiPOST_Always)
263 monitor_mask |= DBE_VALUE;
264 if (prec->apst == aaiPOST_Always)
265 monitor_mask |= DBE_LOG;
266
267 /* Calculate hash if we are interested in OnChange events. */
268 if ((prec->mpst == aaiPOST_OnChange) ||
269 (prec->apst == aaiPOST_OnChange)) {
270 hash = epicsMemHash(prec->bptr,
271 prec->nord * dbValueSize(prec->ftvl), 0);
272
273 /* Only post OnChange values if the hash is different. */
274 if (hash != prec->hash) {
275 if (prec->mpst == aaiPOST_OnChange)
276 monitor_mask |= DBE_VALUE;
277 if (prec->apst == aaiPOST_OnChange)
278 monitor_mask |= DBE_LOG;
279
280 /* Store hash for next process. */
281 prec->hash = hash;
282 /* Post HASH. */
283 db_post_events(prec, &prec->hash, DBE_VALUE);
284 }
285 }
286
240 if (monitor_mask)287 if (monitor_mask)
241 db_post_events(prec, prec->bptr, monitor_mask);288 db_post_events(prec, prec->bptr, monitor_mask);
242}289}
@@ -253,21 +300,25 @@
253300
254 status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);301 status = dbGetLink(&prec->siml, DBR_ENUM, &prec->simm, 0, 0);
255 if (status)302 if (status)
256 return(status);303 return status;
257304
258 if (prec->simm == menuYesNoNO){305 if (prec->simm == menuYesNoNO){
259 /* Call dev support */306 return pdset->read_aai(prec);
260 status = pdset->read_aai(prec);
261 return status;
262 }307 }
308
263 if (prec->simm == menuYesNoYES){309 if (prec->simm == menuYesNoYES){
264 /* Simm processing split performed in devSup */310 /* Device suport is responsible for buffer
265 /* Call dev support */311 which might be read-only so we may not be
266 status = pdset->read_aai(prec);312 allowed to call dbGetLink on it.
267 return status;313 Maybe also device support has an advanced
314 simulation mode.
315 Thus call device now.
316 */
317 recGblSetSevr(prec, SIMM_ALARM, prec->sims);
318 return pdset->read_aai(prec);
268 }319 }
269 status = -1;320
270 recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM);321 recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
271 return status;322 return -1;
272}323}
273324
274325
=== modified file 'src/rec/aaiRecord.dbd'
--- src/rec/aaiRecord.dbd 2002-07-12 21:35:43 +0000
+++ src/rec/aaiRecord.dbd 2010-07-07 17:48:44 +0000
@@ -7,6 +7,10 @@
7# and higher are distributed subject to a Software License Agreement found7# and higher are distributed subject to a Software License Agreement found
8# in file LICENSE that is included with this distribution. 8# in file LICENSE that is included with this distribution.
9#*************************************************************************9#*************************************************************************
10menu(aaiPOST) {
11 choice(aaiPOST_Always,"Always")
12 choice(aaiPOST_OnChange,"On Change")
13}
10recordtype(aai) {14recordtype(aai) {
11 include "dbCommon.dbd" 15 include "dbCommon.dbd"
12 field(VAL,DBF_NOACCESS) {16 field(VAL,DBF_NOACCESS) {
@@ -82,4 +86,25 @@
82 interest(2)86 interest(2)
83 menu(menuAlarmSevr)87 menu(menuAlarmSevr)
84 }88 }
89 field(SIOL,DBF_INLINK) {
90 prompt("Sim Input Specifctn")
91 promptgroup(GUI_INPUTS)
92 interest(1)
93 }
94 field(MPST,DBF_MENU) {
95 prompt("Post Value Monitors")
96 promptgroup(GUI_DISPLAY)
97 interest(1)
98 menu(aaiPOST)
99 }
100 field(APST,DBF_MENU) {
101 prompt("Post Archive Monitors")
102 promptgroup(GUI_DISPLAY)
103 interest(1)
104 menu(aaiPOST)
105 }
106 field(HASH,DBF_ULONG) {
107 prompt("Hash of OnChange data.")
108 interest(3)
109 }
85}110}
86111
=== modified file 'src/rec/aaoRecord.c'
--- src/rec/aaoRecord.c 2009-07-08 18:14:11 +0000
+++ src/rec/aaoRecord.c 2010-07-07 17:48:44 +0000
@@ -9,7 +9,6 @@
9/* recAao.c - Record Support Routines for Array Analog Out records */9/* recAao.c - Record Support Routines for Array Analog Out records */
10/*10/*
11 * Original Author: Dave Barker11 * Original Author: Dave Barker
12 * Date: 10/28/93
13 *12 *
14 * C E B A F13 * C E B A F
15 * 14 *
@@ -18,6 +17,8 @@
18 *17 *
19 * Copyright SURA CEBAF 1993.18 * Copyright SURA CEBAF 1993.
20 *19 *
20 * Current Author: Dirk Zimoch <dirk.zimoch@psi.ch>
21 * Date: 27-MAY-2010
21 */22 */
2223
23#include <stddef.h>24#include <stddef.h>
@@ -28,14 +29,17 @@
2829
29#include "dbDefs.h"30#include "dbDefs.h"
30#include "epicsPrint.h"31#include "epicsPrint.h"
32#include "epicsString.h"
31#include "alarm.h"33#include "alarm.h"
32#include "dbAccess.h"34#include "dbAccess.h"
35#include "dbEvent.h"
33#include "dbFldTypes.h"36#include "dbFldTypes.h"
34#include "dbScan.h"37#include "dbScan.h"
35#include "dbEvent.h"
36#include "devSup.h"38#include "devSup.h"
39#include "errMdef.h"
37#include "recSup.h"40#include "recSup.h"
38#include "recGbl.h"41#include "recGbl.h"
42#include "cantProceed.h"
39#include "menuYesNo.h"43#include "menuYesNo.h"
40#define GEN_SIZE_OFFSET44#define GEN_SIZE_OFFSET
41#include "aaoRecord.h"45#include "aaoRecord.h"
@@ -48,7 +52,7 @@
48static long init_record(aaoRecord *, int);52static long init_record(aaoRecord *, int);
49static long process(aaoRecord *);53static long process(aaoRecord *);
50#define special NULL54#define special NULL
51static long get_value(aaoRecord *, struct valueDes *);55#define get_value NULL
52static long cvt_dbaddr(DBADDR *);56static long cvt_dbaddr(DBADDR *);
53static long get_array_info(DBADDR *, long *, long *);57static long get_array_info(DBADDR *, long *, long *);
54static long put_array_info(DBADDR *, long);58static long put_array_info(DBADDR *, long);
@@ -84,43 +88,67 @@
84epicsExportAddress(rset,aaoRSET);88epicsExportAddress(rset,aaoRSET);
8589
86struct aaodset { /* aao dset */90struct aaodset { /* aao dset */
87 long number;91 long number;
88 DEVSUPFUN dev_report;92 DEVSUPFUN dev_report;
89 DEVSUPFUN init;93 DEVSUPFUN init;
90 DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/94 DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
91 DEVSUPFUN get_ioint_info;95 DEVSUPFUN get_ioint_info;
92 DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/96 DEVSUPFUN write_aao; /*returns: (-1,0)=>(failure,success)*/
93};97};
9498
95static void monitor(aaoRecord *);99static void monitor(aaoRecord *);
96static long writeValue(aaoRecord *);100static long writeValue(aaoRecord *);
97101
98
99static long init_record(aaoRecord *prec, int pass)102static long init_record(aaoRecord *prec, int pass)
100{103{
101 struct aaodset *pdset;
102 long status;104 long status;
105 struct aaodset *pdset = (struct aaodset *)(prec->dset);
103106
104 if (pass == 0) {
105 if (prec->nelm <= 0) prec->nelm = 1;
106 return 0;
107 }
108 recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm);
109 /* must have dset defined */107 /* must have dset defined */
110 if (!(pdset = (struct aaodset *)(prec->dset))) {108 if (!pdset) {
111 recGblRecordError(S_dev_noDSET, (void *)prec, "aao: init_record");109 recGblRecordError(S_dev_noDSET, prec, "aao: init_record");
112 return S_dev_noDSET;110 return S_dev_noDSET;
113 }111 }
112
113 if (pass == 0) {
114 if (prec->nelm <= 0)
115 prec->nelm = 1;
116 if (prec->ftvl > DBF_ENUM)
117 prec->ftvl = DBF_UCHAR;
118 if (prec->nelm == 1) {
119 prec->nord = 1;
120 } else {
121 prec->nord = 0;
122 }
123
124 /* we must call pdset->init_record in pass 0
125 because it may set prec->bptr which must
126 not change after links are established before pass 1
127 */
128
129 if (pdset->init_record) {
130 /* init_record may set the bptr to point to the data */
131 if ((status = pdset->init_record(prec)))
132 return status;
133 }
134 if (!prec->bptr) {
135 /* device support did not allocate memory so we must do it */
136 prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl),
137 "aao: buffer calloc failed");
138 }
139 return 0;
140 }
141
142 /* SIML must be a CONSTANT or a PV_LINK or a DB_LINK */
143 if (prec->siml.type == CONSTANT) {
144 recGblInitConstantLink(&prec->siml,DBF_USHORT,&prec->simm);
145 }
146
114 /* must have write_aao function defined */147 /* must have write_aao function defined */
115 if (pdset->number < 5 || pdset->write_aao == NULL) {148 if (pdset->number < 5 || pdset->write_aao == NULL) {
116 recGblRecordError(S_dev_missingSup, (void *)prec, "aao: init_record");149 recGblRecordError(S_dev_missingSup, prec, "aao: init_record");
117 return S_dev_missingSup;150 return S_dev_missingSup;
118 }151 }
119 if (pdset->init_record) {
120 /* init records sets the bptr to point to the data */
121 if ((status = pdset->init_record(prec)))
122 return status;
123 }
124 return 0;152 return 0;
125}153}
126154
@@ -132,13 +160,15 @@
132160
133 if (pdset == NULL || pdset->write_aao == NULL) {161 if (pdset == NULL || pdset->write_aao == NULL) {
134 prec->pact = TRUE;162 prec->pact = TRUE;
135 recGblRecordError(S_dev_missingSup, (void *)prec, "write_aao");163 recGblRecordError(S_dev_missingSup, prec, "write_aao");
136 return S_dev_missingSup;164 return S_dev_missingSup;
137 }165 }
138166
139 if (pact) return 0;167 if (pact) return 0;
140168
141 status = writeValue(prec); /* write the data */169 status = writeValue(prec); /* write the data */
170 if (!pact && prec->pact) return 0;
171 prec->pact = TRUE;
142172
143 prec->udf = FALSE;173 prec->udf = FALSE;
144 recGblGetTimeStamp(prec);174 recGblGetTimeStamp(prec);
@@ -148,22 +178,14 @@
148 recGblFwdLink(prec);178 recGblFwdLink(prec);
149179
150 prec->pact = FALSE;180 prec->pact = FALSE;
151 return 0;181 return status;
152}
153
154static long get_value(aaoRecord *prec, struct valueDes *pvdes)
155{
156 pvdes->no_elements = prec->nelm;
157 pvdes->pvalue = prec->bptr;
158 pvdes->field_type = prec->ftvl;
159 return 0;
160}182}
161183
162static long cvt_dbaddr(DBADDR *paddr)184static long cvt_dbaddr(DBADDR *paddr)
163{185{
164 aaoRecord *prec = (aaoRecord *)paddr->precord;186 aaoRecord *prec = (aaoRecord *)paddr->precord;
165187
166 paddr->pfield = (void *)(prec->bptr);188 paddr->pfield = prec->bptr;
167 paddr->no_elements = prec->nelm;189 paddr->no_elements = prec->nelm;
168 paddr->field_type = prec->ftvl;190 paddr->field_type = prec->ftvl;
169 paddr->field_size = dbValueSize(prec->ftvl);191 paddr->field_size = dbValueSize(prec->ftvl);
@@ -175,7 +197,7 @@
175{197{
176 aaoRecord *prec = (aaoRecord *)paddr->precord;198 aaoRecord *prec = (aaoRecord *)paddr->precord;
177199
178 *no_elements = prec->nelm;200 *no_elements = prec->nord;
179 *offset = 0;201 *offset = 0;
180 return 0;202 return 0;
181}203}
@@ -184,7 +206,9 @@
184{206{
185 aaoRecord *prec = (aaoRecord *)paddr->precord;207 aaoRecord *prec = (aaoRecord *)paddr->precord;
186208
187 prec->nelm = nNew;209 prec->nord = nNew;
210 if (prec->nord > prec->nelm)
211 prec->nord = prec->nelm;
188 return 0;212 return 0;
189}213}
190214
@@ -210,7 +234,7 @@
210{234{
211 aaoRecord *prec = (aaoRecord *)paddr->precord;235 aaoRecord *prec = (aaoRecord *)paddr->precord;
212236
213 if (paddr->pfield == (void *)prec->bptr) {237 if (paddr->pfield == prec->bptr) {
214 pgd->upper_disp_limit = prec->hopr;238 pgd->upper_disp_limit = prec->hopr;
215 pgd->lower_disp_limit = prec->lopr;239 pgd->lower_disp_limit = prec->lopr;
216 } else recGblGetGraphicDouble(paddr,pgd);240 } else recGblGetGraphicDouble(paddr,pgd);
@@ -221,7 +245,7 @@
221{245{
222 aaoRecord *prec = (aaoRecord *)paddr->precord;246 aaoRecord *prec = (aaoRecord *)paddr->precord;
223247
224 if(paddr->pfield==(void *)prec->bptr){248 if(paddr->pfield == prec->bptr){
225 pcd->upper_ctrl_limit = prec->hopr;249 pcd->upper_ctrl_limit = prec->hopr;
226 pcd->lower_ctrl_limit = prec->lopr;250 pcd->lower_ctrl_limit = prec->lopr;
227 } else recGblGetControlDouble(paddr,pcd);251 } else recGblGetControlDouble(paddr,pcd);
@@ -231,9 +255,35 @@
231static void monitor(aaoRecord *prec)255static void monitor(aaoRecord *prec)
232{256{
233 unsigned short monitor_mask;257 unsigned short monitor_mask;
258 unsigned int hash = 0;
234259
235 monitor_mask = recGblResetAlarms(prec);260 monitor_mask = recGblResetAlarms(prec);
236 monitor_mask |= (DBE_LOG | DBE_VALUE);261
262 if (prec->mpst == aaoPOST_Always)
263 monitor_mask |= DBE_VALUE;
264 if (prec->apst == aaoPOST_Always)
265 monitor_mask |= DBE_LOG;
266
267 /* Calculate hash if we are interested in OnChange events. */
268 if ((prec->mpst == aaoPOST_OnChange) ||
269 (prec->apst == aaoPOST_OnChange)) {
270 hash = epicsMemHash(prec->bptr,
271 prec->nord * dbValueSize(prec->ftvl), 0);
272
273 /* Only post OnChange values if the hash is different. */
274 if (hash != prec->hash) {
275 if (prec->mpst == aaoPOST_OnChange)
276 monitor_mask |= DBE_VALUE;
277 if (prec->apst == aaoPOST_OnChange)
278 monitor_mask |= DBE_LOG;
279
280 /* Store hash for next process. */
281 prec->hash = hash;
282 /* Post HASH. */
283 db_post_events(prec, &prec->hash, DBE_VALUE);
284 }
285 }
286
237 if (monitor_mask)287 if (monitor_mask)
238 db_post_events(prec, prec->bptr, monitor_mask);288 db_post_events(prec, prec->bptr, monitor_mask);
239}289}
@@ -253,17 +303,20 @@
253 return status;303 return status;
254304
255 if (prec->simm == menuYesNoNO) {305 if (prec->simm == menuYesNoNO) {
256 /* Call dev support */306 return pdset->write_aao(prec);
257 status = pdset->write_aao(prec);
258 return status;
259 }307 }
260 if (prec->simm == menuYesNoYES) {308 if (prec->simm == menuYesNoYES) {
261 /* Call dev support */309 /* Device suport is responsible for buffer
262 status = pdset->write_aao(prec);310 which might be write-only so we may not be
263 return status;311 allowed to call dbPutLink on it.
312 Maybe also device support has an advanced
313 simulation mode.
314 Thus call device now.
315 */
316 recGblSetSevr(prec, SIMM_ALARM, prec->sims);
317 return pdset->write_aao(prec);
264 }318 }
265 status = -1;319 recGblSetSevr(prec, SOFT_ALARM, INVALID_ALARM);
266 recGblSetSevr(prec, SIMM_ALARM, INVALID_ALARM);320 return -1;
267 return status;
268}321}
269322
270323
=== modified file 'src/rec/aaoRecord.dbd'
--- src/rec/aaoRecord.dbd 2002-07-12 21:35:43 +0000
+++ src/rec/aaoRecord.dbd 2010-07-07 17:48:44 +0000
@@ -7,6 +7,10 @@
7# and higher are distributed subject to a Software License Agreement found7# and higher are distributed subject to a Software License Agreement found
8# in file LICENSE that is included with this distribution. 8# in file LICENSE that is included with this distribution.
9#*************************************************************************9#*************************************************************************
10menu(aaoPOST) {
11 choice(aaoPOST_Always,"Always")
12 choice(aaoPOST_OnChange,"On Change")
13}
10recordtype(aao) {14recordtype(aao) {
11 include "dbCommon.dbd" 15 include "dbCommon.dbd"
12 field(VAL,DBF_NOACCESS) {16 field(VAL,DBF_NOACCESS) {
@@ -82,4 +86,25 @@
82 interest(2)86 interest(2)
83 menu(menuAlarmSevr)87 menu(menuAlarmSevr)
84 }88 }
89 field(SIOL,DBF_OUTLINK) {
90 prompt("Sim Output Specifctn")
91 promptgroup(GUI_INPUTS)
92 interest(1)
93 }
94 field(MPST,DBF_MENU) {
95 prompt("Post Value Monitors")
96 promptgroup(GUI_DISPLAY)
97 interest(1)
98 menu(aaoPOST)
99 }
100 field(APST,DBF_MENU) {
101 prompt("Post Archive Monitors")
102 promptgroup(GUI_DISPLAY)
103 interest(1)
104 menu(aaoPOST)
105 }
106 field(HASH,DBF_ULONG) {
107 prompt("Hash of OnChange data.")
108 interest(3)
109 }
85}110}

Subscribers

People subscribed via source and target branches