📄 hal_stg.c
字号:
* ACTION FUNCTIONS ** these do the actual data exchange with the board *************************************************************************//* stg_counter_read() - reads one channel FIXME - todo, extend to 32 bits in software works the same for both cards (STG & STG2)*/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; outb(0x03, CTRL(i)); 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;}/* stg_dac_write() - writes a dac channel works the same for both cards (STG & STG2)*/static int stg_dac_write(int ch, short value){ /* write the DAC */ 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) { /* do a dummy read from the ADC, just to set the input multiplexer to the right channel */ inw(base + ADC_0 + (wAxis << 1)); /* wait 4 uS for settling time on the multiplexer and ADC. You probably shouldn't really have a delay in a driver */ outb(0, 0x80); outb(0, 0x80); outb(0, 0x80); outb(0, 0x80); /* now start conversion */ outw(0, base + ADC_0 + (wAxis << 1)); } else { //model STG2 tempCtrl0 = inb(base+CNTRL0) & 0x07; // save IRQ tempCtrl0 |= (wAxis << 4) | 0x88; //autozero & cal cycle outb(tempCtrl0, CNTRL0); // select channel /* wait 4 uS for settling time on the multiplexer and ADC. You probably shouldn't really have a delay in a driver */ outb(0, 0x80); outb(0, 0x80); outb(0, 0x80); outb(0, 0x80); /* now start conversion */ outw(0, base + ADC_0); } return 0;};static short stg_adc_read(void *arg, int axis){ short j; stg_struct *stg; stg = arg; /* there must have been a delay between stg_adc_start() and stg_adc_read(), of 19 usec if autozeroing (we are), 4 usecs otherwise. In code that calls this, make sure you split these calls up with some intervening code */ if (stg->model == 1) { /* make sure conversion is done, assume polling delay is done. EOC (End Of Conversion) is bit 0x08 in IIR (Interrupt Request Register) of Interrupt Controller. Don't wait forever though bail out eventually. */ for (j = 0; !(inb(base + IRR) & 0x08) && (j < 1000); j++); j = inw(base + ADC_0 + (axis << 1)); } else { //model 2 for (j = 0; (inb(base + BRDTST) & 0x08) && (j < 1000); j++); j = inw(base + ADC_0); } if (j & 0x1000) /* is sign bit negative? */ j |= 0xf000; /* sign extend */ else j &= 0xfff; /* make sure high order bits are zero. */ return j;};/************************************************************************ BOARD INIT FUNCTIONS ** functions for autodetec, irq init *************************************************************************/static int stg_set_interrupt(short interrupt){ unsigned char tempINTC; if (stg_driver->model == 1) tempINTC=0x80; else tempINTC=0x88;//also CAL low, don|t want ADC to calibrate 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(){ if (base == 0x00) { base = stg_autodetect(); } if (model != 0) { stg_driver->model = model; //overrides any detected model, use with caution } if (base == 0x00) { rtapi_print_msg(RTAPI_MSG_ERR, "STG: ERROR: no STG or STG2 card found\n"); return -ENODEV; } if (stg_driver->model == 1) { // initialize INTC as output outb(0x92, base + MIO_2); stg_set_interrupt(5); // initialize it to smthg, we won't use it anyways outb(0x1a, base + ICW1); // initialize the 82C59 as single chip (STG docs say so:) outb(0x00, base + ICW2); // ICW2 not used, must init it to 0 outb(0xff, base + OCW1); // mask off all interrupts } else { //model 2 outb(0x8b, base + D_DIR); // initialize CONTRL0 output, BRDTST input stg_set_interrupt(5); // initialize it to smthg, we won't use it anyways } // all ok return 0;}/* scans possible addresses for STG cards */unsigned short stg_autodetect(){ short i, j, k, ofs; unsigned short address; /* search all possible addresses */ for (i = 15; i >= 0; i--) { address = i * 0x20 + 0x200; /* does jumper = i? */ //if ((inb(address + BRDTST) & 0x0f) == i) { // by Xuecheng, not necessary k = 0; // var for getting the serial for (j = 0; j < 8; j++) { ofs = (inb(address + BRDTST) >> 4); if (ofs & 8) { /* is SER set? */ ofs = ofs & 7; /* mask for Q2,Q1,Q0 */ k += (1 << ofs); /* shift bit into position specified by Q2, Q1, Q0 */ } } if (k == 0x75) { rtapi_print_msg(RTAPI_MSG_INFO, "STG: found version 1 card at address %x\n", address); stg_driver->model=1; return address; /* SER sequence is 01110101 */ } if (k == 0x74) { rtapi_print_msg(RTAPI_MSG_INFO, "STG: found version 2 card at address %x\n", address); stg_driver->model=2; return address; } //} } return (0);}/************************************************************************ LOCAL FUNCTION DEFINITIONS ** these are functions used for exporting various HAL pins/prams *************************************************************************/static int export_counter(int num, stg_struct *addr){ int retval, msg; char buf[HAL_NAME_LEN + 2]; /* This function exports a lot of stuff, which results in a lot of logging if msg_level is at INFO or ALL. So we save the current value of msg_level and restore it later. If you actually need to log this function's actions, change the second line below */ msg = rtapi_get_msg_level(); rtapi_set_msg_level(RTAPI_MSG_WARN); /* export pin for counts captured by update() */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.counts", num); retval = hal_pin_s32_new(buf, HAL_WR, &addr->count[num], comp_id); if (retval != 0) { return retval; } /* export pin for scaled position captured by update() */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.position", num); retval = hal_pin_float_new(buf, HAL_WR, &addr->pos[num], comp_id); if (retval != 0) { return retval; } /* export parameter for scaling */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.position-scale", num); retval = hal_param_float_new(buf, HAL_WR, &addr->pos_scale[num], comp_id); if (retval != 0) { return retval; } /* restore saved message level */ rtapi_set_msg_level(msg); return 0;}static int export_dac(int num, stg_struct *addr){ int retval, msg; char buf[HAL_NAME_LEN + 2]; /* This function exports a lot of stuff, which results in a lot of logging if msg_level is at INFO or ALL. So we save the current value of msg_level and restore it later. If you actually need to log this function's actions, change the second line below */ msg = rtapi_get_msg_level(); rtapi_set_msg_level(RTAPI_MSG_WARN); /* export pin for voltage received by the board() */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.dac-value", num); retval = hal_pin_float_new(buf, HAL_RD, &addr->dac_value[num], comp_id); if (retval != 0) { return retval; } /* export parameter for offset */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.dac-offset", num); retval = hal_param_float_new(buf, HAL_WR, &addr->dac_offset[num], comp_id); if (retval != 0) { return retval; } /* export parameter for gain */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.dac-gain", num); retval = hal_param_float_new(buf, HAL_WR, &addr->dac_gain[num], comp_id); if (retval != 0) { return retval; } /* restore saved message level */ rtapi_set_msg_level(msg); return 0;}static int export_adc(int num, stg_struct *addr){ int retval, msg; char buf[HAL_NAME_LEN + 2]; /* This function exports a lot of stuff, which results in a lot of logging if msg_level is at INFO or ALL. So we save the current value of msg_level and restore it later. If you actually need to log this function's actions, change the second line below */ msg = rtapi_get_msg_level(); rtapi_set_msg_level(RTAPI_MSG_WARN); /* export pin for voltage received by the board() */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.adc-value", num); retval = hal_pin_float_new(buf, HAL_WR, &addr->adc_value[num], comp_id); if (retval != 0) { return retval; } /* export parameter for offset */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.adc-offset", num); retval = hal_param_float_new(buf, HAL_WR, &addr->adc_offset[num], comp_id); if (retval != 0) { return retval; } /* export parameter for gain */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.%d.adc-gain", num); retval = hal_param_float_new(buf, HAL_WR, &addr->adc_gain[num], comp_id); if (retval != 0) { return retval; } /* restore saved message level */ rtapi_set_msg_level(msg); return 0;}static int export_pins(int num, int dir, stg_struct *addr){ int retval, msg, i; /* This function exports a lot of stuff, which results in a lot of logging if msg_level is at INFO or ALL. So we save the current value of msg_level and restore it later. If you actually need to log this function's actions, change the second line below */ msg = rtapi_get_msg_level(); rtapi_set_msg_level(RTAPI_MSG_WARN); 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; } } /* restore saved message level */ rtapi_set_msg_level(msg); return 0;}static int export_input_pin(int pinnum, io_pin * pin){ char buf[HAL_NAME_LEN + 2]; int retval; /* export read only HAL pin for input data */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.in-%02d", pinnum); retval = hal_pin_bit_new(buf, HAL_WR, &(pin->data), comp_id); if (retval != 0) { return retval; } /* export additional pin for inverted input data */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.in-%02d-not", pinnum); retval = hal_pin_bit_new(buf, HAL_WR, &(pin->io.not), comp_id); /* initialize HAL pins */ *(pin->data) = 0; *(pin->io.not) = 1; return retval;}static int export_output_pin(int pinnum, io_pin * pin){ char buf[HAL_NAME_LEN + 2]; int retval; /* export read only HAL pin for output data */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.out-%02d", pinnum); retval = hal_pin_bit_new(buf, HAL_RD, &(pin->data), comp_id); if (retval != 0) { return retval; } /* export parameter for polarity */ rtapi_snprintf(buf, HAL_NAME_LEN, "stg.out-%02d-invert", pinnum); retval = hal_param_bit_new(buf, HAL_WR, &(pin->io.invert), comp_id); /* initialize HAL pin and param */ *(pin->data) = 0; pin->io.invert = 0; return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -