📄 hal_vti.c
字号:
static void vti_dacs_write(void *arg, long period){ vti_struct *vti; float volts; unsigned short ncounts, i; vti = arg; for (i = 0; i < num_chan; i++) { /* scale the voltage to be written based on offset and gain */ volts = (*(vti->dac_value[i]) - vti->dac_offset[i]) * vti->dac_gain[i]; /* compute the value for the DAC, the extra - in there is vti specific */ ncounts = ((volts / 10) * 0x7fff) + 0x8000; /* write it to the card */ vti_dac_write(i, ncounts); }}/* The VTI board has no ADCs. Procedure is retained only as a stub, should it be called from elsewhere in the application. */ static void vti_adcs_read(void *arg, long period){ return;}// helper function to extract the data out of a char and place it into HAL data// written by JMKstatic void split_input(unsigned char data, io_pin * dest, int num){ int b; unsigned char mask; /* splits a byte into 'num' HAL pins (and their NOTs) */ mask = 0x01; for (b = 0; b < num; b++) { if (data & mask) { /* input high, which means FALSE (active low) */ *(dest->data) = 0; *(dest->io.not) = 1; } else { /* input low, which means TRUE */ *(dest->data) = 1; *(dest->io.not) = 0; } mask <<= 1; dest++; }}// helper function to extract the data out of HAL and place it into a char// written by JMKunsigned char build_output(io_pin * src, int num){ int b; unsigned char data, mask; data = 0x00; mask = 0x01; /* assemble output byte for data port from 'num' source variables */ for (b = 0; b < num; b++) { /* get the data, add to output byte */ if (*(src->data)) { if (!(src->io.invert)) { data |= mask; } } else { if ((src->io.invert)) { data |= mask; } } mask <<= 1; src++; } return data;}static void vti_di_read(void *arg, long period) //reads digital inputs from the vti{ vti_struct *vti; int i; char latchedVal; vti = arg; if (diocount == 0) return; // No DIO enabled /* Get ENCDAC onboard inputs */ latchedVal = encoder->DIO; if (vti->dir_bits[0] == 0) split_input(latchedVal, &(vti->port[0][0]), 4); if (vti->dir_bits[1] == 0) split_input(latchedVal, &(vti->port[0][4]), 4); /* Get Extended I/O inputs */ if (diocount <= 8) return; // No extended I/O enabled for (i = 1; i < (diocount / 8); i++) { latchedVal = dac->DIO[i - 1]; if (vti->dir_bits[i * 2] == 0) split_input(latchedVal, &(vti->port[i][0]), 4); if (vti->dir_bits[i * 2 + 1] == 0) split_input(latchedVal, &(vti->port[i][4]), 4); }}static void vti_do_write(void *arg, long period) //writes digital outputs to the vti{ vti_struct *vti; int i; vti = arg; /* Write ENCDAC onboard outputs */ if (diocount == 0) return; // No DIO encoder->DIO = build_output(&(vti->port[0][0]), 8); if (diocount <= 8) return; // No extended I/O /* Write Extended I/O outputs */ for (i = 1; i < diocount / 8; i++) { dac->DIO[i - 1] = build_output(&(vti->port[i][0]), 8); } }/************************************************************************ BOARD SPECIFIC FUNCTIONS ** execute board related things (write/read to/from the vti) *************************************************************************//************************************************************************ INIT FUNCTIONS *************************************************************************//* vti_counter_init() - Initializes the channel works the same for both cards (vti & STG2)*/static int vti_counter_init(int counters){ int i, retval=0; /* export all the variables for each counter, dac */ for (i = 0; i < counters; i++) { /* export all vars */ retval = export_counter(i, vti_driver); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: counter %d var export failed\n", i + 1); hal_exit(comp_id); return -1; } /* init counter */ *(vti_driver->count[i]) = 0; *(vti_driver->pos[i]) = 0.0; vti_driver->pos_scale[i] = 1.0; } return 0;}/* vti_dac_init() - Initializes the dac channel works the same for both cards (vti & STG2)*/static int vti_dac_init(int channels){ int retval, i; encoder->DAC = DAC_IND_MODE; // Enable DACs for output indpendent of watchdog for (i = 0; i < channels; i++) { retval = export_dac(i, vti_driver); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: dac %d var export failed\n", i + 1); hal_exit(comp_id); return -1; } /* init counter */ *(vti_driver->dac_value[i]) = 0; vti_driver->dac_offset[i] = 0.0; vti_driver->dac_gain[i] = 1.0; vti_dac_write(i, DAC_ZERO_VOLTS); } return 0;}/* vti_adc_init() - Initializes the adc channel *//* VTI card has no ADCs. */static int vti_adc_init(int channels){ return 0;}static int vti_dio_init(int nibbles){ unsigned int mask; int i; /* we will select the directions of each port */ /* First initialize the 8 on board I/O points */ if (diocount == 0) return 0; // No DIO encoder->DIO = 0; // Turn all inputs / outputs off mask = encoder->Interrupt; mask &= 0xfffffcff; // Mask off direction bits if (vti_driver->dir_bits[0] == 1) mask |= 0x00000100; // Set mask for bits 0-3 if (vti_driver->dir_bits[1] == 1) mask |= 0x00000200; // Set mask for bits 4-7 encoder->Interrupt = mask; /* Now initialize all extended I/O */ if (diocount <= 8) return 0; // No extended I/O for (i = 0; i < (diocount - 8) / 8; i++) { dac->DIO[i] = 0; // Turn all extended I/O off } mask = 0; for (i = 0; i < 8; i++) { // Set direction for extended I/O points 0..63 if (vti_driver->dir_bits[(i * 2) + 2] == 1) mask |= (1 << i); } dac->config0 = mask; mask = 0; for (i = 0; i < 8; i++) { // Set direction for extended I/O points 64..127 if (vti_driver->dir_bits[(i * 2) + 18] == 1) mask |= (1 << i); } dac->config1 = mask; return 0;}/************************************************************************ ACTION FUNCTIONS ** these do the actual data exchange with the board *************************************************************************//* vti_counter_read() - reads one channel FIXME - todo, extend to 32 bits in software works the same for both cards (vti & STG2)*/static long vti_counter_read(int axis){ unsigned int status; unsigned int count; Longword EncData; static long int lastCount;// static unsigned short lastdac; if ((axis > MAX_CHANS) || (axis < 0)) { return 0x80000000; // Return encoder error value } lastCount = enc_counts[axis]; status = encoder->Status; // latch status from vti board count = encoder->Counter[axis]; // latch count from vti board EncData.Long = (long int)enc_counts[axis]; if (status & (1 << axis)) { if (status & (1 << (axis + 4))) { EncData.Word[1] += 1; } else { EncData.Word[1] -= 1; } } EncData.Word[0] = count;// Filter out spurious roll overs / roll unders if ((EncData.Long - lastCount) > 0x7fff) EncData.Word[1] -= 1; else if ((lastCount - EncData.Long) > 0x7fff) EncData.Word[1] += 1; enc_counts[axis] = EncData.Long; return EncData.Long;}/* vti_dac_write() - writes a dac channel*/static int vti_dac_write(int axis, short value){ short junk; /* write the DAC */ if ((axis > MAX_CHANS) || (axis < 0)) { return -1; } junk = dac->mode; // Read from mode to trigger update dac immediately dac->dac[axis] = value; // Write dac value return 0;}/* int vti_adc_start(void *arg, unsigned short wAxis){ return 0; // VTI card has do ADCs} *//* static short vti_adc_read(void *arg, int axis){ return 0; // VTI card has no ADCs} *//************************************************************************ BOARD INIT FUNCTIONS ** functions for autodetec, irq init *************************************************************************//*static int vti_set_interrupt(short interrupt){ return 0; // No interrupts necessary for VTI board}*/static int vti_init_card(){ int retval=vti_autodetect(); if (retval == 0) { encoder = (volatile struct encoder *) ioremap(pci_resource_start(dev, 2), sizeof(encoder)); dac = (volatile struct dac *) ioremap(pci_resource_start(dev, 4), sizeof(dac)); timer = (volatile struct timer *) ioremap(pci_resource_start(dev, 3), sizeof(timer)); ip = (volatile struct ip *) ioremap(pci_resource_start(dev, 5), sizeof(ip)); } else { return (retval); } rtapi_print_msg(RTAPI_MSG_INFO, "VTI: Encoders mapped to : %x2\n", (int) encoder); rtapi_print_msg(RTAPI_MSG_INFO, "VTI: DACs mapped to : %x2\n", (int) dac); rtapi_print_msg(RTAPI_MSG_INFO, "VTI: Timers mapped to : %x2\n", (int) timer); rtapi_print_msg(RTAPI_MSG_INFO, "VTI: Industry pack mapped to : %x2\n", (int) ip); encoder->Status = 0; encoder->Reset = 0; // all ok return 0;}/* scans possible addresses for vti cards */static int vti_autodetect(){ dev = pci_find_device(VENDOR, DEVICE, dev); if (dev) { rtapi_print_msg(RTAPI_MSG_INFO, "VTI: Card detected in slot: %2x\n", PCI_SLOT(dev->devfn)); return (0); } else { rtapi_print_msg(RTAPI_MSG_INFO, "VTI: Exiting with auto detect failed\n"); return (-ENODEV); }}/************************************************************************ LOCAL FUNCTION DEFINITIONS ** these are functions used for exporting various HAL pins/prams *************************************************************************/static int export_counter(int num, vti_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, "vti.%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, "vti.%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, "vti.%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, vti_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, "vti.%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, "vti.%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, "vti.%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, vti_struct * addr){ return 0; // No ADCs to export} */static int export_dio_pins(int io_points){ int i, msg, retval=0; /* 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 */ if (io_points == 0) return 0; msg = rtapi_get_msg_level(); rtapi_set_msg_level(RTAPI_MSG_WARN); for (i = 0; i < io_points; i++) { /* point, direction, driver */ retval |= export_pin(i, vti_driver->dir_bits[i / 4], vti_driver); } /* restore saved message level */ rtapi_set_msg_level(msg); return retval;}static int export_pin(int num, int dir, vti_struct * addr){ int retval; if (dir != 0) retval = export_output_pin(outpinnum++, &(addr->port[num / 8][num % 8])); else retval = export_input_pin(inputpinnum++, &(addr->port[num / 8][num % 8])); if (retval != 0) return retval; 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, "vti.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, "vti.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, "vti.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, "vti.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 + -