epics-modules / asyn

EPICS module for driver and device support
http://epics-modules.github.io/asyn/
Other
37 stars 72 forks source link

Shift parameter in asynMask #166

Open tynanford opened 1 year ago

tynanford commented 1 year ago

Hello,

I am using asynPortDriver for an EPICS UDP driver and I can say it has been working really well and I enjoy working with it.

My use case is a driver that works with 32 bit registers which can be broken up into several different PVs. I've run across almost the exact same issue outlined in this tech talk post from 4 years ago:

https://epics.anl.gov/tech-talk/2018/msg00963.php

I can't find any github issues on shifting so I am just bringing the topic back up to see if there were any further discussions on this. Thanks.

MarkRivers commented 1 year ago

@tynanford what record types do you want to use this for? Is your driver "generic" so that it should be responsibility of device support to break up the registers, or is it specific to a particular device, and so the driver itself should know how to select the appropriate bits? Can you explain the driver and the registers in question?

tynanford commented 1 year ago

I am currently using asynUInt32Digital and longin/longout PVs for this. I think I would call it generic but I am not totally sure. Basically the driver works like this. A CSV file containing a mapping of register bits -> PV is parsed at compile time and an EPICS database file is generated

For instance:

RegisterAddress, Bitmask, PVName
0x00000001, 0xFFFF0000, PV1
0x00000001, 0x0000FF00, PV2
0x00000001, 0x000000FF, PV3

Becomes something like this:

record(longin, "PV1") {
    field(DTYP, "asynUInt32Digital")
    field(INP, "@asynMask( PORT, ADDR, 0xFFFF0000, 1)PARAM_00000001")
}
record(longin, "PV2") {
    field(DTYP, "asynUInt32Digital")
    field(INP, "@asynMask( PORT, ADDR, 0x0000FF00, 1)PARAM_00000001")
}
record(longin, "PV3") {
    field(DTYP, "asynUInt32Digital")
    field(INP, "@asynMask( PORT, ADDR, 0x000000FF, 1)PARAM_00000001")
}

So the asynPortDriver simply reads UDP packets, loops through the register address/value pairs, and puts the register value into the appropriate ASYN parameter ("PARAM_00000001" in this case). Then the device support layer takes care of updating PV1, PV2, and PV3 with the right bits masked.

In this case, I add an extra CALC record for both PV1 and PV2 to do the shifting down (i.e. PV1 >> 16). I could also do the shifting in the driver but I like keeping the driver simple. Something like an asynShiftMask option in the INP field would mean the CALC record isn't needed. Not a big deal but just wanted to raise the topic.

MarkRivers commented 1 year ago

This seems like a useful addition to the devAsynUInt32Digital device support for the longin and longout records. I am adding it to the to-do list.

tynanford commented 1 year ago

Thanks! I am happy to help with any testing needed