In training class last week, someone asked about writing values to an I/O Unit from a variable, but not necessarily all of the values or I/O at once. He also wanted a “mask” so he could indicate/select which outputs to write to and which to skip for now. (This selection process might happen in a PAC Display screen, or perhaps from groov).
There’s already a built-in command called Set I/O Unit from MOMO Masks which does about what he described for DIGITAL points.
However, if you’re not a bit-head and tend to say no-no to the mo-mo (in this discussion I mention why you might do that), or you’re setting ANALOG outputs, then there are also the commands called: Move Numeric Table to I/O Unit (Ex) (you’d use the Ex version if you have modules with more than four points). But… those Move commands don’t give you an option to skip some of the points on that I/O Unit.
What to do? There are several ways to approach this problem. And since PAC Control will let you write your own command (a “subroutine”), once you solve it the way you like, you can easily use that code/subroutine in future projects!
Let’s explore a couple of different options here, starting with the simplest (no subroutines, no pointers or mysterious commands). Then we’ll ponder the pros/cons as I move into some of the fancier options—always lots of options with OptoStuff!
The quickest/dirtiest method…
…that pops into my head would use a few tables and a few move commands and one loop. It would look like this:
- Move the current values on my I/O Unit to a table I’ll call: [B]ftIOValues_Now[/B], using the command [B]Move I/O Unit to Numeric Table[/B]
- Loop through the mask table, which I’ll call: [B]ntIOActive_where_0_means_dont_send[/B], and the new values table which I’ll call: [B]ftIOValues_to_Write[/B], and if you see a non-zero value in [B]ntIOActive_where_0_means_dont_send[/B], then copy that table element in: [B]ftIOValues_to_Write[/B] to the corresponding table element in: [B]ftIOValues_Now[/B].
- Write the just-updated ftIO_Values_Now to the I/O Unit using [B]Move Numeric Table to I/O Unit[/B]
In OptoScript, it might look something like this:
Other options/additions/variations you might consider:
- You could make this code into your own command/subroutine, perhaps called: [B]Move [I]Masked[/I] Table to I/O Unit [/B]where you pass the I/O unit, mask table, and ftIOValues_to_Write.
- If all your modules only have 4 points or fewer… you could use a 64-bit integer for the mask instead of the table. (Besides the no-no to MOMO post I mentioned above, I’d also recommend using tables vs. an int64 since [I]groov[/I] doesn’t currently have an option for letting you access one bit in an integer used as a bitmask).
- If you care about how fast these outputs are changing and what changes on those outputs between the read and the write, we have the rarely discussed [B]Flag Lock[/B] and [B]Flag Unlock[/B] commands for just this sort of situation.
Why I’d use a Pointer Table…
However, knowing what I know about the system (very little), I’d be tempted to throw in a pointer table, and not just to annoy Ben. Because… for one thing, if we use a pointer table, this logic can be used for ALL your Analog Points, not just the ones on a particular I/O unit. Also avoids the need for the Flag/semaphore commands mentioned above. It’d look something like this:
Where those two OptoScript blocks will look like this:
In the loop with a delay:
Easy, yes? Other ideas? Comments? Questions? Do share!