/** Node type: Wrapper around RSCAD CBuilder model * * @author Steffen Vogel * @copyright 2017, Steffen Vogel **********************************************************************************/ #include "node.h" #include "log.h" #include "plugin.h" #include "utils.h" #include "nodes/cbuilder.h" int cbuilder_parse(struct node *n, config_setting_t *cfg) { struct cbuilder *cb = n->_vd; config_setting_t *cfg_params; const char *model; if (!config_setting_lookup_float(cfg, "timestep", &cb->timestep)) cerror(cfg, "CBuilder model requires 'timestep' setting"); if (!config_setting_lookup_string(cfg, "model", &model)) cerror(cfg, "CBuilder model requires 'model' setting"); cb->model = (struct cbuilder_model *) plugin_lookup(PLUGIN_TYPE_MODEL_CBUILDER, model); if (!cb->model) cerror(cfg, "Unknown model '%s'", model); cfg_params = config_setting_get_member(cfg, "parameters"); if (cfg_params) { if (!config_setting_is_array(cfg_params)) cerror(cfg_params, "Model parameters must be an array of numbers!"); cb->paramlen = config_setting_length(cfg_params); cb->params = alloc(cb->paramlen * sizeof(double)); for (int i = 0; i < cb->paramlen; i++) cb->params[i] = config_setting_get_float_elem(cfg_params, i); } return 0; } int cbuilder_start(struct node *n) { int ret; struct cbuilder *cb = n->_vd; /* Initialize mutex and cv */ pthread_mutex_init(&cb->mtx, NULL); pthread_cond_init(&cb->cv, NULL); /* Currently only a single timestep per model / instance is supported */ cb->step = 0; cb->read = 0; ret = cb->model->init(cb); if (ret) error("Failed to intialize CBuilder model %s", node_name(n)); cb->model->ram(); return 0; } int cbuilder_stop(struct node *n) { struct cbuilder *cb = n->_vd; pthread_mutex_destroy(&cb->mtx); pthread_cond_destroy(&cb->cv); return 0; } int cbuilder_read(struct node *n, struct sample *smps[], unsigned cnt) { struct cbuilder *cb = n->_vd; struct sample *smp = smps[0]; /* Wait for completion of step */ pthread_mutex_lock(&cb->mtx); while (cb->read >= cb->step) pthread_cond_wait(&cb->cv, &cb->mtx); smp->length = cb->model->read(&smp->data[0].f, 16); smp->sequence = cb->step; cb->read = cb->step; pthread_mutex_unlock(&cb->mtx); return 1; } int cbuilder_write(struct node *n, struct sample *smps[], unsigned cnt) { struct cbuilder *cb = n->_vd; struct sample *smp = smps[0]; pthread_mutex_lock(&cb->mtx); cb->model->write(&smp->data[0].f, smp->length); cb->model->code(); cb->step++; pthread_cond_signal(&cb->cv); pthread_mutex_unlock(&cb->mtx); return 1; } static struct plugin p = { .name = "cbuilder", .description = "RTDS CBuilder model", .type = PLUGIN_TYPE_NODE, .node = { .vectorize = 1, .size = sizeof(struct cbuilder), .parse = cbuilder_parse, .start = cbuilder_start, .stop = cbuilder_stop, .read = cbuilder_read, .write = cbuilder_write, .instances = LIST_INIT() } }; REGISTER_PLUGIN(&p)