Subject: |
Conversion problem from double to 32 bit unsigned int (in ao) |
From: |
Dirk Zimoch <[email protected]> |
To: |
EPICS <[email protected]> |
Date: |
Wed, 10 Apr 2013 10:20:34 +0200 |
Hi folks,
Today I found a strange problem. I have a device that has 32 bit
unsigned int output registers. I want to scale an analog value (e.g.
-10.0 .. +10.0) to the raw range 0x00000000 ... 0xffffffff. The
special_linconv() function of the ao record sets ESLO and EOFF correctly
(ESLO=20/4294967295=4.65661287416E-09, EOFF=-10.0). All negative values
work but any positive value gives wrong results. Even worse, the results
are different on different machines: 0x80000000 on linux-x86, 0x7fffffff
on vxworks-ppc604 for all positive values.
What happens? In the convert() function the analog (double) value is
converted to epicsInt32 (type of the RVAL field). However if the double
value is too large for the integer, strange and obviously implementation
dependent things happen. I cannot find anything about this case in K&R.
Strictly speaking one can argue that it is illegal to convert a double
to an int if it is too large. But there is hardware that wants 32 bit
unsigned integer raw values.
I suggest to modify the convert function as follows:
diff -u -r1.1.1.1 aoRecord.c
--- src/rec/aoRecord.c 29 Nov 2010 10:38:07 -0000 1.1.1.1
+++ src/rec/aoRecord.c 10 Apr 2013 07:30:08 -0000
@@ -469,7 +469,7 @@
value -= prec->aoff;
if (prec->aslo != 0) value /= prec->aslo;
if (value >= 0.0)
- prec->rval = (epicsInt32)(value + 0.5) - prec->roff;
+ prec->rval = (epicsUInt32)(value + 0.5) - prec->roff;
else
prec->rval = (epicsInt32)(value - 0.5) - prec->roff;
}
I.e using unsigned integer conversion for positive values. This changes
nothing for any values < 0x7fffffff and gives a useful result for
positive values >= 0x80000000.
The same thing can happen at other locations, too.
Example:
record (mbbo, "DZ:mbbo") {
field (FLNK, "DZ:calcout")
}
record (calcout, "DZ:calcout") {
field (INPA, "DZ:mbbo")
field (CALC, "A*65536")
field (OUT, "DZ:longout PP")
}
record (longout, "DZ:longout") {
}
Writing 0xffff to the mbbo results in 0x8000000 on my 32 bit Linux PC.
field (CALC, "A<<16") on the other hand gives the expected result
0xffff0000.
The ai record is more tricky because 0x80000000 may mean a positive
unsigned or a negative signed value. I am not sure how to deal with this
(and the initialization of the ao record).
Dirk
- Replies:
- Re: Conversion problem from double to 32 bit unsigned int (in ao) Benjamin Franksen
- Re: Conversion problem from double to 32 bit unsigned int (in ao) Andrew Johnson
- Navigate by Date:
- Prev:
RE: linux file search from Asyn nick.rees
- Next:
Re: macLib: macro PORT is undefined Alan Greer
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
<2013>
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: macLib: macro PORT is undefined Alan Greer
- Next:
Re: Conversion problem from double to 32 bit unsigned int (in ao) Benjamin Franksen
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
<2013>
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
|