Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shift parameter in asynMask #166

Open
tynanford opened this issue Dec 16, 2022 · 4 comments
Open

Shift parameter in asynMask #166

tynanford opened this issue Dec 16, 2022 · 4 comments

Comments

@tynanford
Copy link

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
Copy link
Member

@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
Copy link
Author

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
Copy link
Member

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
Copy link
Author

Thanks! I am happy to help with any testing needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants