📄 hal_vti.c
字号:
/********************************************************************* Description: hal_vti.c* This is the driver for the Vigilant Technologies* PCI-ENCDAC 4 channel controller.** Author: Eric H. Johnson from template by Alex Joni and EMC1 driver* by Paul C.* License: GPL Version 2** Copyright (c) 2006 All rights reserved.* see below for additional notes** Last change:* $Revision: 1.5 $* $Author: alex_joni $* $Date: 2006/03/28 17:34:13 $********************************************************************//** This is the driver for Vigilant Technologies (VTI) ENCDAC controller. The board includes 4 channels of quadrature encoder input, 4 channels of analog input and output, 8 bits digital I/O plus up to 128 bits digital I/O on digital expander module, and three timers with interrupt. Installation of the driver only realtime: insmod hal_vti num_chan=4 dio="IOiooi" BNF -> dio="*nI|O|ii|io|oi|oo" where n=number of enabled I/O ports - autodetects the address or insmod hal_vti base=0x200 num_chan=4 dio="I|O|ii|io|oi|oo..." Check your Hardware manual for your base address (ISA bus only). The digital inputs/outputs configuration is determined by a config string passed to insmod when loading the module. The format consists of a character string that sets the direction of each group of pins. Each character or character pair of the direction string is one of "I", "O", "ii", "io", "oi" or "oo". The individual and character pair formats may be used interchangably in the same string, however the lower case format must always appear in pairs. The representatiom of each character or character pair is as follows: I: 8 (0..7) Inputs O: 8 (0..7) Outputs ii: 4 (0..3) Inputs / 4 (4..7) Inputs io: 4 (0..3) Inputs / 4 (4..7) Outputs oi: 4 (0..3) Outputs / 4 (4..7) Inputs oo: 4 (0..3) Outputs / 4 (4..7) Outputs There are characters or character pairs equal to the number of I/O ports (sets of 8 DIO) configured on the ENCDAC board and the expanded I/O module, where the first port is for the I/O on the ENCDAC board itself. The following items are exported to the HAL. Encoders: Parameters: float vti.<channel>.position-scale Pins: s32 vti.<channel>.counts float vti.<channel>.position/todo bit vti.<channel>.enc-index/todo bit vti.<channel>.enc-idx-latch/todo bit vti.<channel>.enc-latch-index/todo bit vti.<channel>.enc-reset-count Functions: void vti.<channel>.capture_position DACs: Parameters: float vti.<channel>.dac-offset float vti.<channel>.dac-gain Pins: float vti.<channel>.dac-value Functions: void vti.<channel>.dac-write ADC: Parameters:/totest float vti.<channel>.adc-offset/totest float vti.<channel>.adc-gain Pins:/totest float vti.<channel>.adc-value Functions:/totest void vti.<channel>.adc-read Digital In: Pins: bit vti.in-<pinnum> bit vti.in-<pinnum>-not Functions: void vti.digital-in-read Digital Out: Parameters: bit vti.out-<pinnum>-invert Pins: bit vti.out-<pinnum> Functions: void vti.digital-out-write*//** Copyright (C) 2006 Eric Johnson <ejohnson AT aaainc DOT com>*//** Copyright (C) 2004 Alex Joni <alex DOT joni AT robcon DOT ro>*//** Copyright (C) 2003 John Kasunich <jmkasunich AT users DOT sourceforge DOT net>*//* Also relates to the EMC1 code (very similar to STGMEMBS.CPP) work done by Fred Proctor, Will Shackleford *//** This program is free software; you can redistribute it and/or modify it under the terms of version 2.1 of the GNU General Public License as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR ANY HARM OR LOSS RESULTING FROM ITS USE. IT IS _EXTREMELY_ UNWISE TO RELY ON SOFTWARE ALONE FOR SAFETY. Any machinery capable of harming persons must have provisions for completely removing power from all motors, etc, before persons enter any danger area. All machinery must be designed to comply with local and national safety codes, and the authors of this software can not, and do not, take any responsibility for such compliance. This code was written as part of the EMC HAL project. For more information, go to www.linuxcnc.org.*/#ifndef RTAPI#error This is a realtime component only!#endif#include <asm/io.h>#include "rtapi.h" /* RTAPI realtime OS API */#include "rtapi_app.h" /* RTAPI realtime module decls */#include <linux/pci.h>#include "hal.h" /* HAL public API decls */#include "hal_vti.h" /* VTI related defines */#ifndef MODULE#define MODULE#endif#ifdef MODULE/* module information */MODULE_AUTHOR("Eric Johnson");MODULE_DESCRIPTION ("Driver for Vigilant Technologies ENCDAC 4 channel controller");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif /* MODULE_LICENSE */static int num_chan = MAX_CHANS; /* number of channels - default = 8 */MODULE_PARM(num_chan, "i");MODULE_PARM_DESC(num_chan, "number of channels");static long period = 0; /* thread period - default = no thread */MODULE_PARM(period, "l");MODULE_PARM_DESC(period, "thread period (nsecs)");static char *dio = "ii"; /* dio config - default = port A&B inputs, port C&D outputs */MODULE_PARM(dio, "s");MODULE_PARM_DESC(dio, "dio config string - expects something like IOiooi");#endif /* MODULE *//*********************************************************************** * STRUCTURES AND GLOBAL VARIABLES *************************************************************************/typedef struct { hal_bit_t *data; /* basic pin for input or output */ union { hal_bit_t *not; /* pin for inverted data (input only) */ hal_bit_t invert; /* param for inversion (output only) */ } io;} io_pin;typedef struct {/* counter data */ hal_s32_t *count[MAX_CHANS]; /* captured binary count value */ hal_float_t *pos[MAX_CHANS]; /* scaled position (floating point) */ hal_float_t pos_scale[MAX_CHANS]; /* parameter: scaling factor for pos *//* dac data */ hal_float_t *dac_value[MAX_CHANS]; /* value to be written to dac */ hal_float_t dac_offset[MAX_CHANS]; /* offset value for DAC */ hal_float_t dac_gain[MAX_CHANS]; /* gain to be applied *//* adc data */ hal_float_t *adc_value[MAX_CHANS]; /* value to be read from adc */ hal_float_t adc_offset[MAX_CHANS]; /* offset value for ADC */ hal_float_t adc_gain[MAX_CHANS]; /* gain to be applied */ int adc_current_chan; /* holds the currently converting channel *//* dio data */ io_pin port[MAX_IO_PORTS][PINS_PER_PORT]; /* Holds MAX_IO_PORTS X PINS_PER_PORT number of discreet I/O points */ unsigned char dir_bits[MAX_IO_PORTS * 2]; /* remembers config (which port is input which is output) */ unsigned char model;} vti_struct;static vti_struct *vti_driver;struct pci_dev *dev = NULL;struct pci_access *device;volatile struct encoder *encoder = NULL;volatile struct timer *timer = NULL;volatile struct dac *dac = NULL;volatile struct ip *ip = NULL;/* other globals */static int comp_id; /* component ID */static int outpinnum = 0, inputpinnum = 0;static int diocount = 0;static hal_s32_t enc_counts[MAX_CHANS];/************************************************************************ LOCAL FUNCTION DECLARATIONS *************************************************************************//* helper functions, to export HAL pins & co. */static int export_counter(int num, vti_struct * addr);static int export_dac(int num, vti_struct * addr);// static int export_adc(int num, vti_struct * addr);static int export_dio_pins(int io_points);static int export_pin(int num, int dir, vti_struct * addr);static int export_input_pin(int pinnum, io_pin * pin);static int export_output_pin(int pinnum, io_pin * pin);/* Board specific functions *//* initializes the vti, takes care of autodetection, all initialisations */static int vti_init_card(void);/* sets up interrupt to be used - unused for now*//*static int vti_set_interrupt(short interrupt);*//* scans possible addresses for vti cards */static int vti_autodetect(void);/* counter related functions */static int vti_counter_init(int channels);static long vti_counter_read(int i);/* dac related functions */static int vti_dac_init(int channels);static int vti_dac_write(int ch, short value);/* adc related functions */static int vti_adc_init(int channels);// static int vti_adc_start(void *arg, unsigned short wAxis);// static short vti_adc_read(void *arg, int ch);/* dio related functions */static int vti_dio_init(int nibbles);static int vti_parse_dio(void);/* periodic functions registered to HAL */static void vti_adcs_read(void *arg, long period); //reads adc data from the board, check long description at the beginning of the functionstatic void vti_dacs_write(void *arg, long period); //writes dac's to the vtistatic void vti_counter_capture(void *arg, long period); //captures encoder countersstatic void vti_di_read(void *arg, long period); //reads digital inputs from the vtistatic void vti_do_write(void *arg, long period); //writes digital outputs to the vti/************************************************************************ INIT AND EXIT CODE *************************************************************************/#define MAX_CHAN 8int rtapi_app_main(void){ int retval; /* test for number of channels */ if ((num_chan <= 0) || (num_chan > MAX_CHAN)) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: invalid num_chan: %d\n", num_chan); return -1; } /* test for config string */ if ((dio == 0) || (dio[0] == '\0')) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: no dio config string\n"); return -1; } /* have good config info, connect to the HAL */ comp_id = hal_init("hal_vti"); if (comp_id < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: hal_init() failed\n"); return -1; } /* allocate shared memory for vti data */ vti_driver = hal_malloc(num_chan * sizeof(vti_struct)); if (vti_driver == 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: hal_malloc() failed\n"); hal_exit(comp_id); return -1; } /* takes care of all initialisations, also autodetection and model if necessary */ if ((retval=vti_init_card()) != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti_init_card() failed\n"); hal_exit(comp_id); return retval; } diocount = vti_parse_dio(); if (diocount == -1) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: bad config info for port.\n"); return -1; } export_dio_pins(diocount); vti_dio_init(diocount / 4); /* init counter chip */ if (vti_counter_init(num_chan) == -1) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: bad config info counter.\n"); return -1; } /* init dac chip */ vti_dac_init(num_chan); /* init adc chip */ vti_adc_init(0); // VTI controller has no ADCs /* export functions */ retval = hal_export_funct("vti.capture-position", vti_counter_capture, vti_driver, 1, 0, comp_id); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.counter-capture funct export failed\n"); hal_exit(comp_id); return -1; } rtapi_print_msg(RTAPI_MSG_INFO, "VTI: installed %d encoder counters\n", num_chan); retval = hal_export_funct("vti.write-dacs", vti_dacs_write, vti_driver, 1, 0, comp_id); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.write-dacs funct export failed\n"); hal_exit(comp_id); return -1; } rtapi_print_msg(RTAPI_MSG_INFO, "VTI: installed %d dacs\n", num_chan); retval = hal_export_funct("vti.read-adcs", vti_adcs_read, vti_driver, 1, 0, comp_id); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.read-adcs funct export failed\n"); hal_exit(comp_id); return -1; } rtapi_print_msg(RTAPI_MSG_INFO, "VTI: installed %d adcs\n", 0); retval = hal_export_funct("vti.di-read", vti_di_read, vti_driver, 0, 0, comp_id); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.di-read funct export failed\n"); hal_exit(comp_id); return -1; } rtapi_print_msg(RTAPI_MSG_INFO, "VTI: installed %d digital inputs\n", inputpinnum); retval = hal_export_funct("vti.do-write", vti_do_write, vti_driver, 0, 0, comp_id); if (retval != 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: vti.do-write funct export failed\n"); hal_exit(comp_id); return -1; } rtapi_print_msg(RTAPI_MSG_INFO, "VTI: installed %d digital outputs\n", outpinnum); /* was 'period' specified in the insmod command? */ if (period > 0) { /* create a thread */ retval = hal_create_thread("vti.thread", period, 0); if (retval < 0) { rtapi_print_msg(RTAPI_MSG_ERR, "VTI: ERROR: could not create thread\n"); hal_exit(comp_id); return -1; } else { rtapi_print_msg(RTAPI_MSG_INFO, "VTI: created %d uS thread\n", period / 1000); } } return 0;}static int vti_parse_dio(void){ int i = 0, nibble = 0; if (strlen(dio) == 0) return 0; while (i < strlen(dio)) { switch (dio[i]) { case 'I': vti_driver->dir_bits[nibble] = 0; vti_driver->dir_bits[nibble + 1] = 0; break; case 'O': vti_driver->dir_bits[nibble] = 1; vti_driver->dir_bits[nibble + 1] = 1; break; case 'i': vti_driver->dir_bits[nibble] = 0; i++; if (dio[i] == 'i') vti_driver->dir_bits[nibble + 1] = 0; else if (dio[i] == 'o') vti_driver->dir_bits[nibble + 1] = 1; else return -1; break; case 'o': vti_driver->dir_bits[nibble] = 1; i++; if (dio[i] == 'i') vti_driver->dir_bits[nibble + 1] = 0; else if (dio[i] == 'o') vti_driver->dir_bits[nibble + 1] = 1; else return -1; break; default: return -1; } nibble += 2; i++; } return nibble * 4; // Number of IO points defined}void rtapi_app_exit(void){ hal_exit(comp_id);}/************************************************************************ REALTIME ENCODER COUNTING AND UPDATE FUNCTIONS *************************************************************************/static void vti_counter_capture(void *arg, long period){ vti_struct *vti; int i; vti = arg; for (i = 0; i < num_chan; i++) { /* capture raw counts to latches */ *(vti->count[i]) = vti_counter_read(i); /* scale count to make floating point position */ if (vti->pos_scale[i] < 0.0) { if (vti->pos_scale[i] > -EPSILON) vti->pos_scale[i] = -1.0;} else { if (vti->pos_scale[i] < EPSILON) vti->pos_scale[i] = 1.0; } *(vti->pos[i]) = *(vti->count[i]) / vti->pos_scale[i]; } /* done */}/* vti_dacs_write() - writes all dac's to the board - calls vti_dac_write() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -