#include <asm/io.h>
#include "rtapi.h"
#include "rtapi_app.h"
#include "hal.h"
#include "hal_stg.h"
MODULE_AUTHOR("Alex Joni");
MODULE_DESCRIPTION("Driver for Servo-to-Go Model I & II for EMC HAL");
MODULE_LICENSE("GPL");
static int base = 0x00;
RTAPI_MP_INT(base, "board base address, don't use for autodetect");
static int model = 0;
RTAPI_MP_INT(model, "board model, use with caution. it overrides the detected model");
static int num_chan = MAX_CHANS;
RTAPI_MP_INT(num_chan, "number of channels");
static char *dio = "IIOO";
RTAPI_MP_STRING(dio, "dio config string - expects something like IIOO");
#define EPSILON 1e-20
typedef struct {
hal_bit_t *data;
union {
hal_bit_t *not;
hal_bit_t invert;
} io;
} io_pin;
typedef struct {
hal_s32_t *count[MAX_CHANS];
hal_s32_t offset[MAX_CHANS];
hal_float_t *pos[MAX_CHANS];
hal_float_t pos_scale[MAX_CHANS];
hal_bit_t *index_enable[MAX_CHANS];
hal_bit_t *index_latch[MAX_CHANS];
hal_bit_t *index_polarity[MAX_CHANS];
hal_float_t *dac_value[MAX_CHANS];
hal_float_t dac_offset[MAX_CHANS];
hal_float_t dac_gain[MAX_CHANS];
hal_float_t *adc_value[MAX_CHANS];
hal_float_t adc_offset[MAX_CHANS];
hal_float_t adc_gain[MAX_CHANS];
int adc_current_chan;
io_pin port[4][8];
unsigned char dir_bits;
unsigned char model;
} stg_struct;
static stg_struct *stg_driver;
static int comp_id;
static int outpinnum=0, inputpinnum=0;
const int STG_MSG_LEVEL = RTAPI_MSG_INFO;
#define DATA(x) (base + (2 * x) - (x % 2))
#define CTRL(x) (base + (2 * (x+1)) - (x % 2))
static int export_counter(int num, stg_struct * addr);
static int export_dac(int num, stg_struct * addr);
static int export_adc(int num, stg_struct * addr);
static int export_pins(int num, int dir, stg_struct * addr);
static int export_input_pin(int pinnum, io_pin * pin);
static int export_output_pin(int pinnum, io_pin * pin);
static int stg_init_card(void);
static int stg_set_interrupt(short interrupt);
static unsigned short stg_autodetect(void);
static int stg_counter_init(int ch);
static long stg_counter_read(int i);
static void stg_counter_latch(int i);
static void stg1_select_index_axis(void *arg, unsigned int chan);
static void stg1_reset_index_latch(void *arg, unsigned int chan);
static unsigned short stg1_get_index_pulse_latch(void *arg, unsigned int chan);
static void stg2_reset_all_index_latches( void *arg );
static void stg2_select_index_axes( void *arg, unsigned char mask );
static unsigned char stg2_get_all_index_pulse_latches( void *arg );
static int stg_dac_init(int ch);
static int stg_dac_write(int ch, short value);
static int stg_adc_init(int ch);
static int stg_adc_start(void *arg, unsigned short wAxis);
static short stg_adc_read(void *arg, int ch);
static int stg_dio_init(void);
static void stg_adcs_read(void *arg, long period); static void stg_dacs_write(void *arg, long period); static void stg_counter_capture(void *arg, long period); static void stg_di_read(void *arg, long period); static void stg_do_write(void *arg, long period);
#define MAX_CHAN 8
int rtapi_app_main(void)
{
int n, retval, mask, m;
unsigned char dir_bits;
int msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
if ((num_chan <= 0) || (num_chan > MAX_CHAN)) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: invalid num_chan: %d\n", num_chan);
return -1;
}
if ((dio == 0) || (dio[0] == '\0')) {
rtapi_print_msg(RTAPI_MSG_ERR, "STG: ERROR: no dio config string\n");
return -1;
}
comp_id = hal_init("hal_stg");
if (comp_id < 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "STG: ERROR: hal_init() failed\n");
return -1;
}
stg_driver = hal_malloc(num_chan * sizeof(stg_struct));
if (stg_driver == 0) {
rtapi_print_msg(RTAPI_MSG_ERR, "STG: ERROR: hal_malloc() failed\n");
hal_exit(comp_id);
return -1;
}
if ((retval=stg_init_card()) != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: stg_init_card() failed\n");
hal_exit(comp_id);
return retval;
}
dir_bits = 0;
mask = 0x01;
for ( m = 0 ; m < 4 ; m++ ) {
if ((dio[m] == 'i') || (dio[m] == 'I')) {
dir_bits &= ~mask;
} else if ((dio[m] == 'o') || (dio[m] == 'O')) {
dir_bits |= mask;
} else {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: bad config info for port %d\n", m);
return -1;
}
mask <<= 1;
}
mask = 0x01;
for ( m = 0 ; m < 4 ; m++ ) {
export_pins(m, (dir_bits & mask), stg_driver);
mask <<= 1;
}
stg_driver->dir_bits = dir_bits;
stg_dio_init();
for (n = 0; n < num_chan; n++) {
retval = export_counter(n, stg_driver);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: counter %d var export failed\n", n + 1);
hal_exit(comp_id);
return -1;
}
*(stg_driver->count[n]) = 0;
stg_driver->offset[n] = 0;
*(stg_driver->pos[n]) = 0.0;
*(stg_driver->index_enable[n]) = 0;
if( stg_driver->model == 1 )
{
*(stg_driver->index_polarity[n]) = 1;
}
*(stg_driver->index_latch[n]) = 0;
stg_driver->pos_scale[n] = 1.0;
stg_counter_init(n);
retval = export_dac(n, stg_driver);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: dac %d var export failed\n", n + 1);
hal_exit(comp_id);
return -1;
}
*(stg_driver->dac_value[n]) = 0;
stg_driver->dac_offset[n] = 0.0;
stg_driver->dac_gain[n] = 1.0;
stg_dac_init(n);
retval = export_adc(n, stg_driver);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: adc %d var export failed\n", n + 1);
hal_exit(comp_id);
return -1;
}
*(stg_driver->adc_value[n]) = 0;
stg_driver->adc_offset[n] = 0.0;
stg_driver->adc_gain[n] = 1.0;
stg_driver->adc_current_chan = -1;
stg_adc_init(n);
}
retval = hal_export_funct("stg.capture-position", stg_counter_capture,
stg_driver, 1, 0, comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: stg.counter-capture funct export failed\n");
hal_exit(comp_id);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO,
"STG: installed %d encoder counters\n", num_chan);
retval = hal_export_funct("stg.write-dacs", stg_dacs_write,
stg_driver, 1, 0, comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: stg.write-dacs funct export failed\n");
hal_exit(comp_id);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO,
"STG: installed %d dacs\n", num_chan);
retval = hal_export_funct("stg.read-adcs", stg_adcs_read,
stg_driver, 1, 0, comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: stg.read-adcs funct export failed\n");
hal_exit(comp_id);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO,
"STG: installed %d adcs\n", num_chan);
retval = hal_export_funct("stg.di-read", stg_di_read,
stg_driver, 0, 0, comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: stg.di-read funct export failed\n");
hal_exit(comp_id);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO,
"STG: installed %d digital inputs\n", inputpinnum);
retval = hal_export_funct("stg.do-write", stg_do_write,
stg_driver, 0, 0, comp_id);
if (retval != 0) {
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: ERROR: stg.do-write funct export failed\n");
hal_exit(comp_id);
return -1;
}
rtapi_print_msg(RTAPI_MSG_INFO,
"STG: installed %d digital outputs\n", outpinnum);
hal_ready(comp_id);
rtapi_set_msg_level(msg);
return 0;
}
void rtapi_app_exit(void)
{
hal_exit(comp_id);
return;
}
static void stg_counter_capture(void *arg, long period)
{
stg_struct *stg = arg;
int n;
unsigned char mask;
unsigned char index_pulse_latches;
if( stg->model == 1 )
{
for( n = 0; n < num_chan; n++ )
{
stg1_select_index_axis(arg, n);
if (stg1_get_index_pulse_latch(arg, n))
{
*(stg->index_latch[n]) = 1;
if ( *(stg->index_enable[n]) == 1 )
{
stg->offset[n] = stg_counter_read(n);
*(stg->index_enable[n]) = 0;
} else {
}
} else {
*(stg->index_latch[n]) = 0;
}
}
} else if( stg->model == 2 )
{
for( mask = 0, n = 0; n < num_chan; n++ )
{
if( *(stg->index_enable[n]) == 1 )
{
mask |= ( 1<<n );
}
}
stg2_select_index_axes( arg, mask );
index_pulse_latches = stg2_get_all_index_pulse_latches( arg );
for( n = 0; n < num_chan; n++ )
{
if( index_pulse_latches & (1<<n) )
{
*(stg->index_latch[n]) = 1;
if ( *(stg->index_enable[n]) == 1 )
{
stg->offset[n] = stg_counter_read(n);
*(stg->index_enable[n]) = 0;
} else {
}
} else {
*(stg->index_latch[n]) = 0;
}
}
stg2_reset_all_index_latches( arg );
} else {
}
for (n = 0; n < num_chan; n++)
{
stg_counter_latch(n);
*(stg->count[n]) = stg_counter_read(n) - stg->offset[n];
if (stg->pos_scale[n] < 0.0) {
if (stg->pos_scale[n] > -EPSILON)
stg->pos_scale[n] = -1.0;
} else {
if (stg->pos_scale[n] < EPSILON)
stg->pos_scale[n] = 1.0;
}
*(stg->pos[n]) = *(stg->count[n]) / stg->pos_scale[n];
}
return;
}
static void stg_dacs_write(void *arg, long period)
{
stg_struct *stg;
double volts;
short ncounts, i;
stg=arg;
for (i=0;i < num_chan; i++) {
volts = (*(stg->dac_value[i]) - stg->dac_offset[i]) * stg->dac_gain[i];
if (volts < -10.0)
volts = -10.0;
if (volts > 10.0)
volts = 10.0;
ncounts = (short) ((((-10.0 - volts) * 0x1FFF) / 20.0) - 1 );
stg_dac_write(i, ncounts);
}
return;
}
static void stg_adcs_read(void *arg, long period)
{
stg_struct *stg;
double volts;
short ncounts;
int i;
stg = arg;
i = stg->adc_current_chan;
if ((i >= 0) && (i < num_chan)) {
ncounts = stg_adc_read(stg,i);
volts = ncounts * 10.0 / 4096;
*(stg->adc_value[i]) = volts * stg->adc_gain[i] - stg->adc_offset[i];
}
if (stg->adc_current_chan++ >= num_chan)
stg->adc_current_chan=0;
stg_adc_start(stg,stg->adc_current_chan);
return;
}
static void split_input(unsigned char data, io_pin *dest, int num)
{
int b;
unsigned char mask;
mask = 0x01;
for (b = 0 ; b < num ; b++ ) {
if ( data & mask ) {
*(dest->data) = 0;
*(dest->io.not) = 1;
} else {
*(dest->data) = 1;
*(dest->io.not) = 0;
}
mask <<= 1;
dest++;
}
return;
}
unsigned char build_output(io_pin *src, int num)
{
int b;
unsigned char data, mask;
data = 0x00;
mask = 0x01;
for (b = 0; b < num; b++) {
if ( *(src->data) ) {
if ( !(src->io.invert) ) {
data |= mask;
}
} else {
if ( (src->io.invert) ) {
data |= mask;
}
}
mask <<= 1;
src++;
}
return data;
}
static void stg_di_read(void *arg, long period) {
stg_struct *stg;
unsigned char val;
stg=arg;
if ( (stg->dir_bits & 0x01) == 0) { if (stg->model == 1)
val = inb(base + DIO_A);
else
val = inb(base + PORT_A);
split_input(val, &(stg->port[0][0]), 8);
}
if ( (stg->dir_bits & 0x02) == 0) { if (stg->model == 1)
val = inb(base + DIO_B);
else
val = inb(base + PORT_B);
split_input(val, &(stg->port[1][0]), 8);
}
if ( (stg->dir_bits & 0x04) == 0) { if (stg->model == 1)
val = inb(base + DIO_C);
else
val = inb(base + PORT_C);
split_input(val, &(stg->port[2][0]), 8);
}
if ( (stg->dir_bits & 0x08) == 0) { if (stg->model == 1)
val = inb(base + DIO_D);
else
val = inb(base + PORT_D);
split_input(val, &(stg->port[3][0]), 8);
}
}
static void stg_do_write(void *arg, long period) {
stg_struct *stg;
unsigned char val;
stg=arg;
if ( (stg->dir_bits & 0x01) != 0) { val = build_output(&(stg->port[0][0]), 8);
if (stg->model == 1)
outb(val, base + DIO_A);
else
outb(val, base + PORT_A);
}
if ( (stg->dir_bits & 0x02) != 0) { val = build_output(&(stg->port[1][0]), 8);
if (stg->model == 1)
outb(val, base + DIO_B);
else
outb(val, base + PORT_B);
}
if ( (stg->dir_bits & 0x04) != 0) { val = build_output(&(stg->port[2][0]), 8);
if (stg->model == 1)
outb(val, base + DIO_C);
else
outb(val, base + PORT_C);
}
if ( (stg->dir_bits & 0x08) != 0) { val = build_output(&(stg->port[3][0]), 8);
if (stg->model == 1)
outb(val, base + DIO_D);
else
outb(val, base + PORT_D);
}
}
static int stg_counter_init(int ch)
{
outb(0x23, CTRL(ch));
outb(0x68, CTRL(ch));
outb(0x80, CTRL(ch));
outb(0xC3, CTRL(ch));
return 0;
}
static int stg_dac_init(int ch)
{
int i;
for (i=0; i < num_chan; i++) {
stg_dac_write(i, 0x1000); }
return 0;
}
static int stg_adc_init(int ch)
{
if (stg_driver->model == 1)
outb(0x0f, base + MIO_2); return 0;
}
static int stg_dio_init(void)
{
unsigned char control, tempINTC, tempIMR, tempCtrl0, tempCtrl1;
control = 0x80; if ( (stg_driver->dir_bits & 0x01) == 0) control |= 0x10;
if ( (stg_driver->dir_bits & 0x02) == 0) control |= 0x02;
if ( (stg_driver->dir_bits & 0x04) == 0) control |= 0x09;
if (stg_driver->model == 1) {
outb(control, base+MIO_1);
} else { outb(control, base+ABC_DIR);
}
tempINTC = inb(base + INTC);
if (stg_driver->model == 1) {
control = 0x82;
if ( (stg_driver->dir_bits & 0x08) == 0) control = 0x92;
tempIMR = inb(base + IMR);
outb(0xff, base + OCW1);
outb(control, base+MIO_2);
outb(tempINTC, base + INTC);
outb(tempIMR, base+ OCW1);
} else {
tempCtrl0 = inb(base+CNTRL0);
tempCtrl1 = inb(base+CNTRL1);
control = 0x82;
if ( (stg_driver->dir_bits & 0x08) == 0) control = 0x8b;
outb(0xff, base + CNTRL1);
outb(control, base + D_DIR);
outb(tempCtrl0, base + CNTRL0);
outb( (tempCtrl1 & 0x0f) | 0xf0, base + CNTRL1);
}
return 0;
}
static void stg_counter_latch(int i)
{
outb(0x03, CTRL(i));
}
static long stg_counter_read(int i)
{
union pos_tag {
long l;
struct byte_tag {
char b0;
char b1;
char b2;
char b3;
} byte;
} pos;
pos.byte.b0 = inb(DATA(i));
pos.byte.b1 = inb(DATA(i));
pos.byte.b2 = inb(DATA(i));
if (pos.byte.b2 < 0) {
pos.byte.b3 = -1;
} else {
pos.byte.b3 = 0;
}
return pos.l;
}
static void stg1_select_index_axis(void *arg, unsigned int channel)
{
stg_struct *stg = arg;
unsigned char byIntc,byAxis;
unsigned char byPol = 1;
if (stg->model == 1)
{
if( *(stg->index_polarity[channel]) == 0 )
{
byPol = 0;
}
stg1_reset_index_latch(arg, channel);
byAxis = channel;
byAxis &= 0x6; byAxis <<= 3; byIntc = inb(base + INTC); byIntc &= ~(IXLVL | IXS1 | IXS0); byIntc |= byAxis; if (byPol != 0) byIntc |= IXLVL;
outb(byIntc, base + INTC);
}
}
static void stg2_select_index_axes( void *arg, unsigned char mask )
{
outb( mask, base + IDLEN );
return;
}
static void stg1_reset_index_latch(void *arg, unsigned int channel)
{
stg_struct *stg = arg;
if (stg->model == 1)
{ inb(base + ODDRST); inb(base + BRDTST); }
return;
}
static void stg2_reset_all_index_latches( void *arg )
{
stg_struct *stg = arg;
if( stg->model == 2 )
{
outb( 0x00, base + IDL);
}
return;
}
unsigned char stg1_get_current_IRR(void)
{
outb(base + OCW3, 0x0a); return inb(base + IRR);
}
static unsigned short stg1_get_index_pulse_latch(void *arg, unsigned int chan)
{
stg_struct *stg = arg;
unsigned char byIRR, byAxisMask;
if (stg->model == 1){ byIRR = stg1_get_current_IRR();
byAxisMask = (chan & 1) ? LIXODD : LIXEVN; if (byIRR & byAxisMask) return 1;
return 0;
} else if (stg->model == 2) {
return 0;
}
return 0;
}
static unsigned char stg2_get_all_index_pulse_latches( void *arg )
{
stg_struct *stg = arg;
unsigned char indexRegister = 0;
if( stg-> model == 2 )
indexRegister = inb( base + IDL );
return indexRegister;
}
static int stg_dac_write(int ch, short value)
{
outw(value, base + DAC_0 + (ch << 1));
return 0;
}
int stg_adc_start(void *arg, unsigned short wAxis)
{
stg_struct *stg;
unsigned char tempCtrl0;
stg = arg;
if (stg->model == 1) {
inw(base + ADC_0 + (wAxis << 1));
outb(0, 0x80);
outb(0, 0x80);
outb(0, 0x80);
outb(0, 0x80);
outw(0, base + ADC_0 + (wAxis << 1));
} else {
tempCtrl0 = inb(base+CNTRL0) & 0x07; tempCtrl0 |= (wAxis << 4) | 0x88; outb(tempCtrl0, base + CNTRL0);
outb(0, 0x80);
outb(0, 0x80);
outb(0, 0x80);
outb(0, 0x80);
outw(0, base + ADC_0);
}
return 0;
};
static short stg_adc_read(void *arg, int axis)
{
short j;
stg_struct *stg;
stg = arg;
if (stg->model == 1) {
for (j = 0; !(inb(base + IRR) & 0x08) && (j < 1000); j++);
j = inw(base + ADC_0 + (axis << 1));
} else {
for (j = 0; (inb(base + BRDTST) & 0x08) && (j < 1000); j++);
j = inw(base + ADC_0 + (axis << 1));
}
if (j & 0x1000)
j |= 0xf000;
else
j &= 0xfff;
return j;
};
static int stg_set_interrupt(short interrupt)
{
unsigned char tempINTC;
if (stg_driver->model == 1)
tempINTC=0x80;
else
tempINTC=0x88;
switch (interrupt) {
case 3: break;
case 5: tempINTC |= 4;break;
case 7: tempINTC |= 2;break;
case 9: tempINTC |= 6;break;
case 10: tempINTC |= 5;break;
case 11: tempINTC |= 7;break;
case 12: tempINTC |= 3;break;
case 15: tempINTC |= 1;break;
default: tempINTC |= 4;break;
}
if (stg_driver->model == 1)
outb(tempINTC, base + INTC);
else
outb(tempINTC, base + CNTRL0);
return 0;
}
static int stg_init_card()
{
int msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
if ( (model != 0) && (base != 0) )
{
stg_driver->model = model;
} else {
base = stg_autodetect();
}
if ( (base == 0x00) || (stg_driver->model == 0) )
{
rtapi_print_msg(RTAPI_MSG_ERR, "STG: ERROR: no stg1 or stg2 card could be initialised\n");
return -ENODEV;
}
if (stg_driver->model == 1) {
outb(0x92, base + MIO_2);
stg_set_interrupt(5);
outb(0x1a, base + ICW1); outb(0x00, base + ICW2); outb(0xff, base + OCW1); rtapi_print_msg(RTAPI_MSG_INFO,
"STG: Initialised stg%1d card at address %x\n", stg_driver->model, base);
} else if (stg_driver->model == 2 ) {
outb(0x8b, base + D_DIR);
outb( 0x00, base + IDLEN );
outb( 0x00, base + SELDI );
stg_set_interrupt(5); rtapi_print_msg(RTAPI_MSG_INFO,
"STG: Initialised stg%1d card at address %x\n", stg_driver->model, base);
} else {
rtapi_print_msg(RTAPI_MSG_ERR, "STG: ERROR: The model stg%1d is not correct\n", stg_driver->model );
return -ENODEV;
}
rtapi_set_msg_level(msg);
return 0;
}
unsigned short stg_autodetect()
{
short i, j, k, ofs;
unsigned short address;
unsigned short retval = 0;
int msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
for (i = 15; i >= 0; i--) {
address = i * 0x20 + 0x200;
k = 0; for (j = 0; j < 8; j++) {
ofs = (inb(address + BRDTST) >> 4);
if (ofs & 8) {
ofs = ofs & 7;
k += (1 << ofs);
}
}
if (k == 0x75) {
rtapi_print_msg(RTAPI_MSG_INFO,
"STG: Autodetected stg1 card at address %x\n", address);
stg_driver->model=1;
retval = address;
break;
}
if (k == 0x74) {
rtapi_print_msg(RTAPI_MSG_INFO,
"STG: Autodetected stg2 card at address %x\n", address);
stg_driver->model=2;
retval = address;
break;
}
}
if ( ( retval == 0 ) || ( stg_driver->model == 0 ) )
{
rtapi_print_msg(RTAPI_MSG_ERR,
"STG: stg_autodetect() did not find any stg1 or stg2 card\n");
}
rtapi_set_msg_level(msg);
return retval;
}
static int export_counter(int num, stg_struct *addr)
{
int retval, msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
retval = hal_pin_s32_newf(HAL_OUT, &addr->count[num],
comp_id, "stg.%d.counts", num);
if (retval != 0) {
return retval;
}
retval = hal_pin_float_newf(HAL_OUT, &addr->pos[num],
comp_id, "stg.%d.position", num);
if (retval != 0) {
return retval;
}
retval = hal_param_float_newf(HAL_RW, &addr->pos_scale[num],
comp_id, "stg.%d.position-scale", num);
if (retval != 0) {
return retval;
}
retval = hal_pin_bit_newf(HAL_IO, &addr->index_enable[num],
comp_id, "stg.%d.index-enable", num);
if (retval != 0) {
return retval;
}
retval = hal_pin_bit_newf(HAL_OUT, &addr->index_latch[num],
comp_id, "stg.%d.index-latch", num);
if (retval != 0) {
return retval;
}
if( addr->model == 1 )
{
retval = hal_pin_bit_newf(HAL_IN, &addr->index_polarity[num],
comp_id, "stg.%d.index-polarity", num);
if (retval != 0)
{
return retval;
}
}
rtapi_set_msg_level(msg);
return 0;
}
static int export_dac(int num, stg_struct *addr)
{
int retval, msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
retval = hal_pin_float_newf(HAL_IN, &addr->dac_value[num],
comp_id, "stg.%d.dac-value", num);
if (retval != 0) {
return retval;
}
retval = hal_param_float_newf(HAL_RW, &addr->dac_offset[num],
comp_id, "stg.%d.dac-offset", num);
if (retval != 0) {
return retval;
}
retval = hal_param_float_newf(HAL_RW, &addr->dac_gain[num],
comp_id, "stg.%d.dac-gain", num);
if (retval != 0) {
return retval;
}
rtapi_set_msg_level(msg);
return 0;
}
static int export_adc(int num, stg_struct *addr)
{
int retval, msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
retval = hal_pin_float_newf(HAL_OUT, &addr->adc_value[num],
comp_id, "stg.%d.adc-value", num);
if (retval != 0) {
return retval;
}
retval = hal_param_float_newf(HAL_RW, &addr->adc_offset[num],
comp_id, "stg.%d.adc-offset", num);
if (retval != 0) {
return retval;
}
retval = hal_param_float_newf(HAL_RW, &addr->adc_gain[num],
comp_id, "stg.%d.adc-gain", num);
if (retval != 0) {
return retval;
}
rtapi_set_msg_level(msg);
return 0;
}
static int export_pins(int num, int dir, stg_struct *addr)
{
int retval, msg, i;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
for (i=0; i<8; i++) {
if (dir != 0)
retval=export_output_pin(outpinnum++, &(addr->port[num][i]) );
else
retval=export_input_pin(inputpinnum++, &(addr->port[num][i]) );
if (retval != 0) {
return retval;
}
}
rtapi_set_msg_level(msg);
return 0;
}
static int export_input_pin(int pinnum, io_pin * pin)
{
int retval;
int msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
retval = hal_pin_bit_newf(HAL_OUT, &(pin->data), comp_id,
"stg.in-%02d", pinnum);
if (retval != 0) {
return retval;
}
retval = hal_pin_bit_newf(HAL_OUT, &(pin->io.not), comp_id,
"stg.in-%02d-not", pinnum);
*(pin->data) = 0;
*(pin->io.not) = 1;
rtapi_set_msg_level(msg);
return retval;
}
static int export_output_pin(int pinnum, io_pin * pin)
{
int retval;
int msg;
msg = rtapi_get_msg_level();
rtapi_set_msg_level( STG_MSG_LEVEL );
retval = hal_pin_bit_newf(HAL_IN, &(pin->data),
comp_id, "stg.out-%02d", pinnum);
if (retval != 0) {
return retval;
}
retval = hal_param_bit_newf(HAL_RW, &(pin->io.invert),
comp_id, "stg.out-%02d-invert", pinnum);
*(pin->data) = 0;
pin->io.invert = 0;
rtapi_set_msg_level(msg);
return retval;
}