Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/src/hal/comp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,10 @@ When implementing your own `rtapi_app_main()`, call the function `int export(cha
If specified, call the function defined by 'EXTRA_CLEANUP' from the automatically defined 'rtapi_app_exit' or,
in case of a detected error, in the automatically defined 'rtapi_app_main'.

* 'option post_export yes' - (default: no) +
If specified, call the function defined by 'POST_EXPORT' for each instance.
If using the automatically defined 'rtapi_app_main', 'extra_arg' is the number of this instance.

* 'option userspace yes' - (default: no) +
If specified, this file describes a non-realtime (formerly known as "userspace") component, rather than a regular (i.e., realtime) one.
A non-realtime component may not have functions defined by the 'function' directive.
Expand Down Expand Up @@ -434,6 +438,7 @@ Variable and function names that can not be used or are likely to cause problems
* 'rtapi_app_exit'
* 'extra_setup'
* 'extra_cleanup'
* 'post_export'

== Convenience Macros

Expand All @@ -449,6 +454,12 @@ The details of `struct __comp_state` and these macros may change from one versio
* `EXTRA_CLEANUP()` - Use this macro to begin the definition of the function called to perform extra cleanup of the component.
Note that this function must clean up all instances of the component, not just one.
The "pin_name", "parameter_name", and "data" macros may not be used here.
* `POST_EXPORT()` - Use this macro to begin the definition of the function called to perform extra setup _after_ all pins and parameters have been created for this instance.
This function is called just before the export() function returns.
You can use the POST_EXPORT() function to preset parameter values you otherwise would not be able to set.
Return a negative UNIX 'errno' value to indicate failure, or 0 to indicate success. +
Note: POST_EXPORT() should not change 'personality'.
If you need to adapt 'personality', then you must do so in EXTRA_SETUP(), which runs before pins and parameters are created.

* 'pin_name' or 'parameter_name' - For each pin 'pin_name' or param 'parameter_name'
there is a macro which allows the name to be used on its own to refer to the pin or parameter.
Expand Down
31 changes: 20 additions & 11 deletions src/hal/components/multiswitch.comp
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,20 @@ don't connect the extra pin.

component multiswitch """This component toggles between a specified number of output bits.""";

pin in bit up = false "Receives signal to toggle up";
pin in bit down = false "Receives signal to toggle down";
pin in bool up = false "Receives signal to toggle up";
pin in bool down = false "Receives signal to toggle down";

param rw unsigned top-position "Number of positions";
param rw signed position "Current state (may be set in the HAL)";
param rw ui32 top-position "Number of positions";
param rw si32 position "Current state (may be set in the HAL)";

pin out bit bit-##[32:personality] = false "Output bits";
pin out bool bit-##[32:personality] = false "Output bits";

modparam dummy cfg """cfg should be a comma-separated list of sizes, for example cfg=2,4,6 would create 3 instances of 2, 4 and 6 bits respectively.
Ignore the "personality" parameter, that is auto-generated.""";

function _ ;
option extra_setup yes;
option post_export yes;
option count_function yes;
option period no;

Expand All @@ -53,24 +54,32 @@ FUNCTION(_) {
int i;

// debounce
if (up && !old_up) { position++; }
if (down && !old_down) { position--;}
if (up && !old_up) { position_set(position + 1); }
if (down && !old_down) { position_set(position - 1);}
old_up = up;
old_down = down;

if (position < 0) position = top_position;
if ((unsigned)position > top_position) position = 0;
if (position < 0) position_set(top_position);
if ((unsigned)position > top_position) position_set(0);

for (i = 0 ; i < personality; i++){
bit(i) = (i == position);
bit_set(i, i == position);
}

}

EXTRA_SETUP(){
(void)prefix;
// This sets the instance's personality and the number of pins to export.
personality = cfg[extra_arg];
top_position = personality - 1;
return 0;
}

POST_EXPORT(){
(void)prefix;
(void)extra_arg;
// This can only be set after the parameter is created.
top_position_set(personality - 1);
return 0;
}

Expand Down
9 changes: 8 additions & 1 deletion src/hal/utils/halcompile.g
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ mp_decl_map = {'int': 'RTAPI_MP_INT', 'dummy': None}
# names. That includes not only global variables and functions, but also
# HAL pins & parameters, because comp adds #defines with the names of HAL
# pins & params.
reserved_names = [ 'comp_id', 'fperiod', 'rtapi_app_main', 'rtapi_app_exit', 'extra_setup', 'extra_cleanup' ]
reserved_names = [ 'comp_id', 'fperiod', 'rtapi_app_main', 'rtapi_app_exit', 'extra_setup', 'extra_cleanup', 'post_export' ]

def _parse(rule, text, filename=None):
global P, S
Expand Down Expand Up @@ -401,6 +401,8 @@ static int comp_id;
print("static int extra_setup(struct __comp_state *__comp_inst, char *prefix, long extra_arg);", file=f)
if options.get("extra_cleanup"):
print("static void extra_cleanup(void);", file=f)
if options.get("post_export"):
print("static int post_export(struct __comp_state *__comp_inst, char *prefix, long extra_arg);", file=f)

if not options.get("no_convenience_defines"):
print("#undef TRUE", file=f)
Expand Down Expand Up @@ -538,6 +540,9 @@ static int comp_id;
print(" if(__comp_last_inst) __comp_last_inst->_next = inst;", file=f)
print(" __comp_last_inst = inst;", file=f)
print(" if(!__comp_first_inst) __comp_first_inst = inst;", file=f)
if options.get("post_export"):
print(" r = post_export(inst, prefix, extra_arg);", file=f)
print(" if(r != 0) return r;", file=f)
print(" return 0;", file=f)
print("}", file=f)

Expand Down Expand Up @@ -776,6 +781,8 @@ int __comp_parse_names(int *argc, char **argv) {
print("#define EXTRA_SETUP() static int extra_setup(struct __comp_state *__comp_inst, char *prefix, long extra_arg)", file=f)
print("#undef EXTRA_CLEANUP", file=f)
print("#define EXTRA_CLEANUP() static void extra_cleanup(void)", file=f)
print("#undef POST_EXPORT", file=f)
print("#define POST_EXPORT() static int post_export(struct __comp_state *__comp_inst, char *prefix, long extra_arg)", file=f)
if options.get("period"):
print("#undef fperiod", file=f)
print("#define fperiod (period * 1e-9)", file=f)
Expand Down
Loading