⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal_vti.c

📁 Source code for an Numeric Cmputer
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************* 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 + -