#include "rtapi.h"
#include "rtapi_app.h"
#include "hal.h"
#include <float.h>
#include <rtapi_math.h>
#include <rtapi_string.h>
MODULE_AUTHOR("John Kasunich");
MODULE_DESCRIPTION("Signal Generator Component for EMC HAL");
MODULE_LICENSE("GPL");
static int num_chan;
static int default_num_chan = 1;
static int howmany;
RTAPI_MP_INT(num_chan, "number of channels");
#define MAX_CHAN 16
static char *names[MAX_CHAN] = {0,};
RTAPI_MP_ARRAY_STRING(names, MAX_CHAN, "names of siggen");
typedef struct {
hal_float_t *square;
hal_float_t *sawtooth;
hal_float_t *triangle;
hal_float_t *sine;
hal_float_t *cosine;
hal_bit_t *clock;
hal_float_t *frequency;
hal_float_t *amplitude;
hal_float_t *offset;
hal_bit_t *reset;
double index;
} hal_siggen_t;
static hal_siggen_t *siggen_array;
static int comp_id;
static int export_siggen(int num, hal_siggen_t * addr,char* prefix);
static void calc_siggen(void *arg, long period);
int rtapi_app_main(void)
{
int n, retval, i;
if(num_chan && names[0]) {
rtapi_print_msg(RTAPI_MSG_ERR,"num_chan= and names= are mutually exclusive\n");
return -EINVAL;
}
if(!num_chan && !names[0]) num_chan = default_num_chan;
if(num_chan) {
howmany = num_chan;
} else {
howmany = 0;
for (i = 0; i < MAX_CHAN; i++) {
if ( (names[i] == NULL) || (*names[i] == 0) ){
break;
}
howmany = i + 1;
}
}
if ((howmany <= 0) || (howmany > MAX_CHAN)) {
rtapi_print_msg(RTAPI_MSG_ERR,
"SIGGEN: ERROR: invalid number of channels: %d\n", howmany);
return -1;
}
comp_id = hal_init("siggen");
if (comp_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "SIGGEN: ERROR: hal_init() failed\n");
return -1;
}
siggen_array = hal_malloc(howmany * sizeof(hal_siggen_t));
if (siggen_array == 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"SIGGEN: ERROR: hal_malloc() failed\n");
hal_exit(comp_id);
return -1;
}
i = 0; for (n = 0; n < howmany; n++) {
if(num_chan) {
char buf[HAL_NAME_LEN + 1];
rtapi_snprintf(buf, sizeof(buf), "siggen.%d", n);
retval = export_siggen(n, &(siggen_array[n]),buf);
} else {
retval = export_siggen(n, &(siggen_array[n]),names[i++]);
}
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"SIGGEN: ERROR: siggen %d var export failed\n", n);
hal_exit(comp_id);
return -1;
}
}
rtapi_print_msg(RTAPI_MSG_INFO,
"SIGGEN: installed %d signal generators\n", howmany);
hal_ready(comp_id);
return 0;
}
void rtapi_app_exit(void)
{
hal_exit(comp_id);
}
static void calc_siggen(void *arg, long period)
{
hal_siggen_t *siggen;
double tmp1, tmp2;
siggen = arg;
tmp1 = period * 0.000000001;
tmp2 = *(siggen->frequency) * tmp1;
if ( tmp2 > 0.5 ) {
*(siggen->frequency) = 0.5 / tmp1;
tmp2 = 0.5;
}
if ( *(siggen->reset) ) {
siggen->index = 0.5;
} else {
siggen->index += tmp2;
}
if ( siggen->index >= 1.0 ) {
siggen->index -= 1.0;
}
if ( siggen->index > 0.5 ) {
tmp1 = 1.0;
*(siggen->clock) = 1;
} else {
tmp1 = -1.0;
*(siggen->clock) = 0;
}
*(siggen->square) = (tmp1 * *(siggen->amplitude)) + *(siggen->offset);
tmp2 = (siggen->index * 2.0) - 1.0;
*(siggen->sawtooth) = (tmp2 * *(siggen->amplitude)) + *(siggen->offset);
tmp2 *= 2.0;
tmp2 = (tmp2 * tmp1) - 1.0;
*(siggen->triangle) = (tmp2 * *(siggen->amplitude)) + *(siggen->offset);
tmp1 = siggen->index * (2.0 * 3.1415927);
*(siggen->sine) = (sin(tmp1) * *(siggen->amplitude)) + *(siggen->offset);
*(siggen->cosine) = (cos(tmp1) * *(siggen->amplitude)) + *(siggen->offset);
}
static int export_siggen(int num, hal_siggen_t * addr,char* prefix)
{
int retval;
char buf[HAL_NAME_LEN + 1];
retval = hal_pin_float_newf(HAL_OUT, &(addr->square), comp_id,
"%s.square", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_OUT, &(addr->sawtooth), comp_id,
"%s.sawtooth", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_OUT, &(addr->triangle), comp_id,
"%s.triangle", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_OUT, &(addr->sine), comp_id,
"%s.sine", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_OUT, &(addr->cosine), comp_id,
"%s.cosine", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_bit_newf(HAL_OUT, &(addr->clock), comp_id,
"%s.clock", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_IN, &(addr->frequency), comp_id,
"%s.frequency", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_IN, &(addr->amplitude), comp_id,
"%s.amplitude", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_IN, &(addr->offset), comp_id,
"%s.offset", prefix);
if (retval != 0) {
return retval;
}
retval = hal_pin_bit_newf(HAL_IN, &(addr->reset), comp_id,
"%s.reset", prefix);
if (retval != 0) {
return retval;
}
*(addr->square) = 0.0;
*(addr->sawtooth) = 0.0;
*(addr->triangle) = 0.0;
*(addr->sine) = 0.0;
*(addr->cosine) = 0.0;
*(addr->clock) = 0;
*(addr->frequency) = 1.0;
*(addr->amplitude) = 1.0;
*(addr->offset) = 0.0;
addr->index = 0.0;
rtapi_snprintf(buf, sizeof(buf), "%s.update", prefix);
retval =
hal_export_funct(buf, calc_siggen, &(siggen_array[num]), 1, 0,
comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"SIGGEN: ERROR: update funct export failed\n");
hal_exit(comp_id);
return -1;
}
return 0;
}