J
Hello,
here's the first installment of ``better living through documentation''.
Please ask questions...
The plc_set() function sets a point to a particular value. Usage:
plc_set(data_point, value);
Where:
data_point is the handle to the point, and
value is an unsigned value (0-32 bits depending on the point).
As in a PLC, the value is buffered (in `private map') and doesn't appear to the outside world (or the rest of the lPLC) until plc_update() is called.
The function will only use as many bits of value as fit into the data_point, the rest will be ignored.
So, assuming we have point handles foo, bar and baz, we can write:
/* turn foo on */
plc_set(foo, 1);
/* invert bar */
plc_set(bar, ~plc_get(bar));
/*
* LD BAR
* AND BAZ
* OUT FOO
*/
plc_set(foo, plc_get(bar) & plc_get(baz));
Since we have the buffering, we can also do:
plc_set(foo, 0);
if (...)
plc_set(foo, 1);
if (...)
plc_set(foo, 1);
This won't cause any glitches, because the 0 doesn't actually appear to anything until the end of our cycle (when we call plc_update()).
If we have a handle xyzzy which is 8-bit, we can do:
/* increment (wraps around at 256) */
plc_set(xyzzy, plc_get(xyzzy)+1);
Note that this trick cannot be used with 32-bit words. With 32-bit words we have to:
/* increment with wrap-around */
if (~plc_get(plugh))
plc_set(plugh, plc_get(plugh)+1);
else
plc_set(plugh, 0);
Any other mathematical expressions as usual:
/* scaled decaying average */
plc_set(plugh, (9*plc_get(plugh) + scaling*plc_get(xyzzy) + 5)/10);
If you are writing a library, remember that the user might pass in any size handle - even zero-bit. Normally you should cope with this by keeping any important information in C variables, like this:
/* decaying average */
plugh_val = (9*plugh_val + scaling*plc_get(xyzzy) + 5)/10;
plc_set(plugh, plugh_val);
/* ... other code that uses plugh_val ... */
You could also check the size of the handle, if it absolutely doesn't make sense to pass a zero-bit handle (or 1-bit handle etc).
The data_point must be a valid point handle. If it is invalid, the program will exit with an error message (this needs fixing - there should be
provision for an error callback/return - so it may change).
It is permissible to write any point, even read-only ones. Such changes will persist until the next plc_update(), at which point they are discarded and a new value is fetched. Using this is a bad programming practice.
How it works: (lib/gmm/gmm.c lines 629-637)
This is basically a two-liner function. The first line calls a macro to check whether the data_point p is valid.
The second line changes the particular bits in the private map, by combining those bits of the map that shouldn't be changed (~pp.mask) and
the given value, shifted appropriately and masked.
That is:
word of private map =
word of private map & bits that shouldn't be changed
plus shifted value & bits that should be changed
The macro "pp" expands to "p", typecast to the private point-handle type.
Jiri
--
Jiri Baum <[email protected]>
What we do Every Night! Take Over the World!
_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc
here's the first installment of ``better living through documentation''.
Please ask questions...
The plc_set() function sets a point to a particular value. Usage:
plc_set(data_point, value);
Where:
data_point is the handle to the point, and
value is an unsigned value (0-32 bits depending on the point).
As in a PLC, the value is buffered (in `private map') and doesn't appear to the outside world (or the rest of the lPLC) until plc_update() is called.
The function will only use as many bits of value as fit into the data_point, the rest will be ignored.
So, assuming we have point handles foo, bar and baz, we can write:
/* turn foo on */
plc_set(foo, 1);
/* invert bar */
plc_set(bar, ~plc_get(bar));
/*
* LD BAR
* AND BAZ
* OUT FOO
*/
plc_set(foo, plc_get(bar) & plc_get(baz));
Since we have the buffering, we can also do:
plc_set(foo, 0);
if (...)
plc_set(foo, 1);
if (...)
plc_set(foo, 1);
This won't cause any glitches, because the 0 doesn't actually appear to anything until the end of our cycle (when we call plc_update()).
If we have a handle xyzzy which is 8-bit, we can do:
/* increment (wraps around at 256) */
plc_set(xyzzy, plc_get(xyzzy)+1);
Note that this trick cannot be used with 32-bit words. With 32-bit words we have to:
/* increment with wrap-around */
if (~plc_get(plugh))
plc_set(plugh, plc_get(plugh)+1);
else
plc_set(plugh, 0);
Any other mathematical expressions as usual:
/* scaled decaying average */
plc_set(plugh, (9*plc_get(plugh) + scaling*plc_get(xyzzy) + 5)/10);
If you are writing a library, remember that the user might pass in any size handle - even zero-bit. Normally you should cope with this by keeping any important information in C variables, like this:
/* decaying average */
plugh_val = (9*plugh_val + scaling*plc_get(xyzzy) + 5)/10;
plc_set(plugh, plugh_val);
/* ... other code that uses plugh_val ... */
You could also check the size of the handle, if it absolutely doesn't make sense to pass a zero-bit handle (or 1-bit handle etc).
The data_point must be a valid point handle. If it is invalid, the program will exit with an error message (this needs fixing - there should be
provision for an error callback/return - so it may change).
It is permissible to write any point, even read-only ones. Such changes will persist until the next plc_update(), at which point they are discarded and a new value is fetched. Using this is a bad programming practice.
How it works: (lib/gmm/gmm.c lines 629-637)
This is basically a two-liner function. The first line calls a macro to check whether the data_point p is valid.
The second line changes the particular bits in the private map, by combining those bits of the map that shouldn't be changed (~pp.mask) and
the given value, shifted appropriately and masked.
That is:
word of private map =
word of private map & bits that shouldn't be changed
plus shifted value & bits that should be changed
The macro "pp" expands to "p", typecast to the private point-handle type.
Jiri
--
Jiri Baum <[email protected]>
What we do Every Night! Take Over the World!
_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc