Experimental Physics and Industrial Control System
Hi Abdalla
First the question of format: Are your structure fields in big endian or little
endian byte order? Are there any gaps in the structure for alignment?
In case of big endian unaligned fields you can for example use:
MaxInput = 10;
command1 {
out 0x00 0x00 0x00 0x01 0x00 0x0a 0x00 0x00 0x00 0x00;
in "%(\$1:STATUS)02r" 0x00 0x01 0x00 0x0a "%04r";
}
field(INP, "@$(PROTOCOLFILE) command1($(DEVICE)) $(PORT)")
This will send a fixed request, wait for the reply, put status into the *:STATUS
record and keep data for itself.
Assuming you use addresses up to 0xff only, you can pass the address low byte as
argument 2 and use a fixed 0x00 high byte:
command1 {
out 0x00 0x00 0x00 0x01 0x00 $2 0x00 0x00 0x00 0x00;
in "%(\$1:STATUS)02r" 0x00 0x01 0x00 $2 "%04r";
}
field(INP, "@$(PROTOCOLFILE) command1($(DEVICE),0xa) $(PORT)")
Unfortunately you cannot format protocol arguments at the moment. So if for
example you wanted to pass a 16 bit address like 0x1234 and format it with %.2r
like this: "%(\$2).2r", that will not work. It would try to find a record with
the name "0x1234" to take the value from. I may change that in the future,
assuming that record names and field names never start with digits.
BTW: If you want to invalidate your record if status is not 0000, you can use
this:
command1 {
out 0x00 0x00 0x00 0x01 0x00 $2 0x00 0x00 0x00 0x00;
in 0x00 0x00 0x00 0x01 0x00 $2 "%04r";
@mismatch {
in "%(\$1:STATUS)02r" 0x00 0x01 0x00 $2 "%04r";
}
}
The normal 'in' will fail if status is not 0x0000, which will set SEVR to
INVALID and STAT to CALC. But then it will execute @mismatch, re-parse the input
and store the status in the other record and read the (invalid) data for itself.
Thus you will end up with either the record containing a valid value and
unfortunately the STATUS record unchanged or with the record in INVALID/CALC
alarm state (but still containing the received value) and the STATUS record
updated.
Dirk
On Thu, 2024-09-05 at 09:27 +0000, Abdalla Ahmad wrote:
> Hello Dirk
>
> Thank you very much that was helpful. As an example let’s assume we want to read the value of address 10, we send a packet with the following:
> Status = 0x0
> Command = 0x1
> Address = 0xa
> Data = 0x0
>
> And we receive the same packet but with status filled by the device and the actual data is in the data field. So all the packets’ fields are constants and need not to be passed as a protocol argument. How to do it in this way? Also, if I want to use protocol arguments, is it possible to format the argument?
>
> Best Regards,
> Abdalla.
>
> From: Zimoch Dirk <dirk.zimoch at psi.ch>
> Sent: Thursday, September 5, 2024 11:59 AM
> To: Abdalla Ahmad <Abdalla.Ahmad at sesame.org.jo>
> Cc: tech-talk at aps.anl.gov
> Subject: Re: Asyn or Stream device interface for struct data
>
> Hello Abdalla
>
> Yes, you can do this using the %r format together with redirection in order to split the values into 4 records or combing the data from them. As your communication does not use terminators but has a fixed data size, use MaxInput.
> You need to know how the exact struct layout will look like on the network, in particular what the byte order is and if there will be "gaps" due to alignment. The compiler will probably add 2 bytes gap before u32 data when mapping this structure to memory in order to align the u32.
>
> Without any gaps:
>
> MaxInput = 10; # total struct size
> read {
> in "%(\$1:STATUS)02r%(\$1:COMAND)02r%(\$1:ADDRESS)%04r";
> }
> The 0 prefix in %()02r handles the value as unsigned, so that e.g. 0xf000 is not expanded to a negative record value.
> I assume here that the data is in big endian byte order. If you have little endian byte order, use the # modifier: %()#02r.
> The "\$1" is the first argument to the protocol. Pass the "basename" of your records like this:
>
> record (longin, "$(DEVICE):DATA") {
> field(DTYP, "stream")
> field(INP, "@$(PROTOCOLFILE) read($(DEVICE)) $(PORT)")
> }
>
> record(longin "$(DEVICE):STATUS) {
> # the 'status' field will be put here by the read protocol
> }
>
> Maybe you want to use a constant address instead of having it in a record. Pass it as a second parameter:
> field(INP, "@$(PROTOCOLFILE) read($(DEVICE),$(ADDRESS)) $(PORT)")
> and then reference it as $2 You need to pass the 16 byte address as 2 bytes like "00 01" (or maybe only use 1 byte and have a for example fixed 00 upper byte):
> in "%(\$1:STATUS)02r%(\$1:COMAND)02r" $2 "%04r";
>
> Also the command may be fixed. Either pass it as a third argument or have different protocols for different commands:
>
> commandABCD {
> in "%(\$1:STATUS)02r" AB CD $2 "%04r";
> }
>
> This way multiple input records may wait for input with "I/O Intr" scanning and select the matching command (if the device sends on it own without being asked). Or if you have the send a request first and use the command (and address) in both, the out and the in command, the in command will check that it actually gets the correct address.
>
> I am speculating a lot how your protocol actually works. Give me more details if you need a detailed advice.
>
> Dirk
>
>
>
> > On 5 Sep 2024, at 09:33, Abdalla Ahmad via Tech-talk <Tech-talk at aps.anl.gov> wrote:
> >
> > Hi
> >
> > We have a device that I am working on a device support for using asynPortDriver, but its interface is very simple, it is basically a simple C struct used for both TX and RX. Something like this:
> >
> > typedef struct {
> > u16 status,
> > u16 command,
> > u16 address,
> > u32 data
> > } packet_t;
> >
> > I send this packet and I receive the same packet in the response with the corresponding data. Can such a communication interface be achieved using stream device or asyn support?
> >
> > Best Regards,
> > Abdalla.
>
>
- References:
- Asyn or Stream device interface for struct data Abdalla Ahmad via Tech-talk
- Re: Asyn or Stream device interface for struct data Zimoch Dirk via Tech-talk
- RE: Asyn or Stream device interface for struct data Abdalla Ahmad via Tech-talk
- Navigate by Date:
- Prev:
Re: iSeghal queue overflow Florian Feldbauer via Tech-talk
- Next:
Re: areaDetector Overlay problem Mark Rivers via Tech-talk
- 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>
2025
- Navigate by Thread:
- Prev:
RE: Asyn or Stream device interface for struct data Abdalla Ahmad via Tech-talk
- Next:
iSeghal queue overflow Marco Filho via Tech-talk
- 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>
2025