LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Calculate and apply mask programatically

Hello everyone,

 

I'm looking for a way to programmatically apply a mask to specific bits in a register.

 

To explain this better, here's an example:

I have a variable called Value1.
This variable, along with others, is registered in a Modbus map that includes additional information about the variables.
This information is:
- Variable type: B, U2, U3, ..., S64, S16, S32, F32, etc.
- The register number where the variable is located
- The bit positions occupied by the variable
- The variable name

 

In this case, let’s say the variable shares the same register with other variables, so:

(hexAdd)[b]:(cs):(cbr) decAdd (msb..lsb) type varName
(0x9c40)[0]:(16):(15..0) 40000 (15..0) U16 GlobalVariable
(0x9c40)[0]:(16):(0..0) 40000 (0..0) B Value0
(0x9c40)[0]:(16):(8..1) 40000 (8..1) U7 Value1
(0x9c40)[0]:(16):(9..9) 40000 (9..9) B Value2
(0x9c40)[0]:(16):(15..10) 40000 (15..10) U6 Value3

 

Therefore, to modify only the value of Value1, I would have to apply a mask 0xFE01 = 0b1111111000000001 and then add the value I want to set, for example, 0x00012 = 0b0000000000010010.
This way, only Value1 would be modified. Value0, Value2, and Value3 would remain unchanged.

 

Right now, every time I want to apply a mask, I have to calculate it and write it manually. This isn’t difficult and isn't a problem to me.
But sometimes, depending on the Modbus map I’m using, the same variable occupies a different location inside the register.
Therefore, I would like the mask to be applied to be calculated automatically based on the information provided by the Modbus map.

 

I have attached the VIs I am using, as well as the VI I have been testing. I am a bit stuck and unsure how to continue, so I would appreciate any guidance.

 

If I haven't made myself clear, please let me know and I will answer any questions.

 

Thanks in advance.

using LV 2017 on Win11
0 Kudos
Message 1 of 2
(178 Views)

Well, I haven't looked at your code, but I figured it's a small fun challenge. I haven't done any real thinking and I wouldn't be surprised if others appear with cleaner solutions:

 

bitmask.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Some comments:

 

  1. In this example, I want to set the value 1101 starting at bit 10.
  2. When you do something like this, it help to take it one step at a time. That's what I did here with saying something like "I need a mask with N 1s (or 0s) in bit X. How do I get that?". Once I had that, I could keep going. In my example the number of bits corresponds to your variable type.
  3. If you can avoid it, I would suggest changing this structure. If the values in the registers are updated from more than one place, you have the potential for race conditions. Even if they're not, this tends to be harder to read. Unless you have real timing or space constraints, I would suggest separating the values in different registers (and have different blocks of registers for the different parties which can modify them).
  4. There is a Modbus function (22) which can modify only some bits in a register. It's not implemented by all devices or libraries, but if it works for you, it can remove the need to apply the mask yourself and mitigate the risk of race conditions (that depends on what the other side modifying the registers is doing, assuming of course there is something like that in the system).

___________________
Try to take over the world!
0 Kudos
Message 2 of 2
(79 Views)