Had need for an or component with more than two inputs and therefore
spent most of the day implement one with configurable number of inputs
for instances.
Attached is source .c file and .gif picture of example how to use it.
Default with no extra config argument is a two input or component named
or.0 if it work as supposed to. Argument config= is comma separated lit
used to specify number of inputs for the or gates. Adding a text after
the number then this is used instead of number.
With name config argument look a lit bittle ugly and an improvement
would be to allow space after number before name for pin.
If someone want to include into the source it would be great?
Otherwise I will sooner or later make a pull request?
It should be simple to modify this into and and xor variant and will
probably also make this at the same time if I make a pull request.
Ideas for or improvement how parameters for configuration is entered is
appreciated.
Have only done a very fast test but it seems to work supposed to. If
anybody want to try it there is a need to make changes in the files
srd/Makefil and src/Makefile.inc.in
Regards Nicklas Karlsson
// Copyright (C) 2013 Andy Pugh, 2026 Hans Unzner, 2026 Nicklas SB Karlsson
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
// A generic or component with configurable number of inputs
#include <stdlib.h>
#include <rtapi.h>
#include <rtapi_app.h>
#include <hal.h>
/* module information */
MODULE_AUTHOR("Nicklas SB Karlsson"); // Derived from demux_generic.c author: Hans Unzner
MODULE_DESCRIPTION("Generic or component with configurable number of inputs");
MODULE_LICENSE("GPL");
#define MAX_CHAN 100
typedef struct {
hal_bit_t **inputs;
hal_bit_t *output;
int size;
} or_inst_t;
typedef struct {
or_inst_t *insts;
int num_insts;
} or_t;
static int comp_id;
static or_t *or;
static void update(void *arg, long period);
char *config[MAX_CHAN];
RTAPI_MP_ARRAY_STRING(config, MAX_CHAN, "Number or inputs specifier, default is two");
int rtapi_app_main(void){
int retval;
comp_id = hal_init("or");
if (comp_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "or: ERROR: hal_init() failed\n");
return -1;
}
/* allocate shared memory for the base structure. */
or = hal_malloc(sizeof(or_t));
if (or == 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"or component: Out of Memory\n");
hal_exit(comp_id);
return -1;
}
/* Number of instances. */
for (or->num_insts = 0; config[or->num_insts];or->num_insts++) {} // Count number of instances
if (0 == or->num_insts) { // Number of instances not given?
or->num_insts = 1; // Default to one
}
or->insts = hal_malloc(or->num_insts * sizeof(or_inst_t)); // Allocate memory for instances
if (or->insts == NULL) {
rtapi_print_msg(RTAPI_MSG_ERR,
"or component: Out of Memory\n");
hal_exit(comp_id);
return -1;
}
/* Parse the configuration string. */
for (int i = 0; i < or->num_insts; i++) { // For all instances
or_inst_t *inst = &or->insts[i]; // Shorthand access to this instance, place below in separate function will reduce risk to access wrong instance and may be an improvement
char* instance_name = NULL; // Instance name are not used outside this block so make local
/* Code may become somewhat cleaner if found number is converted to
* array of characters and instance name point to converted value.
* As maximum number of digits is limited there should be no need
* to malloc(...) space for this, fixed size good enough.
*/
{
unsigned int n_chars; // Counted number of chars used for configuration for this instance
if (0 == config[0]) { // Number of instances not given?
inst->size = 2; // Use default
n_chars = 0;
}
else{ // Number of instances given?
for (n_chars = 0; config[i][n_chars]; n_chars++) {} // Count number of characters for this instance
}
if(0 == n_chars) { // Number of inputs not given?
inst->size = 2; // Use default
}
else { // Parse number of inputs for this instance
char *endptr; // Pointer to character there parse stopped
errno = 0; // Man page comment: "To distinguish success/failure after call"
inst->size = strtol(&config[i][0], &endptr, 10); // Parse as number
if (errno == ERANGE || inst->size < 0 || inst->size > MAX_CHAN){// Range is valid?
rtapi_print_msg(RTAPI_MSG_ERR, // Error message
"or component: Number of inputs invalid value\n"); // Text used for this message
hal_exit(comp_id); // Exit component
return -1; // Return with an error
}
#if 1 // This method allow name for instance, prefer this
else if (endptr[0] != '\0') { // There is a pin name after number of inputs?
instance_name = &endptr[0]; // Assume extra characters is instance name
}
#else // Wit this method names are not allowed
else if (*endptr != '\0') { // Parsed all characters for this instance?
rtapi_print_msg(RTAPI_MSG_ERR, // Error message
"or component: Further characters after number: \"%s\"\n", endptr); // Text used for this message
hal_exit(comp_id); // Exit component
return -1; // Return with an error
}
#endif
else if (endptr == &config[i][0]) { // Any digit found?
rtapi_print_msg(RTAPI_MSG_ERR, // Error message
"or component: No digits for number of inputs found\n");// Text used for this message
hal_exit(comp_id); // Exit component
return -1; // Return with an error
}
}
}
/* allocate shared memory for the inputs for this instance. */
inst->inputs = hal_malloc(inst->size*sizeof(*inst->inputs));
if (NULL == inst->inputs) {
rtapi_print_msg(RTAPI_MSG_ERR,
"or component: Out of Memory\n");
hal_exit(comp_id);
return -1;
}
/* Input pins for this instance. */
for (int pin = 0; pin < inst->size; pin++) { // For all pins for this instance
if(NULL == instance_name) { // Did not find any name for this instance?
retval = hal_pin_bit_newf(HAL_IN, &inst->inputs[pin], comp_id, // Initialize pin
"or.%i.in%i", i, pin); // with default instance name
}
else{ // Fount name for this instance?
retval = hal_pin_bit_newf(HAL_IN, &inst->inputs[pin], comp_id, // Initialize pin
"%s.in%i", instance_name, pin); // with instance name
}
if (retval != 0) {
goto fail0;
}
}
/* Output pin for this instance. */
if(NULL == instance_name) { // Did not find any name for this instance?
retval = hal_pin_bit_newf(HAL_OUT, &inst->output, comp_id, // Initialize pin
"or.%i.out", i); // with default instance name
}
else{
retval = hal_pin_bit_newf(HAL_OUT, &inst->output, comp_id, // Initialize pin
"%s.out", instance_name); // with default instance name
}
if (retval != 0) {
goto fail0;
}
/* Export update function for this instance. */
if(NULL == instance_name) { // Did not find any name for this instance?
retval = hal_export_functf(update, inst, 1, 0, comp_id, "or.%i", i);// Initialize pin with default name
}
else{
retval = hal_export_functf(update, inst, 1, 0, comp_id, // Initialize pin
"%s", instance_name); // with default instance name
}
if (retval < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "or: ERROR: export of update(...) function failed\n");
goto fail0;
}
}
hal_ready(comp_id);
return 0;
fail0:
hal_exit(comp_id);
return -1;
}
/* This function is called to update outputs. */
void update(void *arg, long period) {
or_inst_t *inst = arg;
hal_bit_t output = false; // Output from component
output = 0;
(void)period; // Intentionally do not care about period and want to ignore warning about this
for(int pin = 0; pin < inst->size; pin++) { // For all pins
output = output || *inst->inputs[pin]; // Or together inputs
}
*inst->output = output; // Update output for this instance
}
void rtapi_app_exit(void){
/* Everything is hal_malloc-ed which saves a lot of cleanup here. */
hal_exit(comp_id);
}
_______________________________________________
Emc-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/emc-developers