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

📄 hal_ax5214h.c

📁 Source code for an Numeric Cmputer
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************* Description:  AX5214H.c*               This file, 'AX5214H.c', is a HAL component that *               provides a driver for the Axiom Measurement & Control *               AX5241H 48 channel digital I/O board.** Author: John Kasunich* License: GPL Version 2*    * Copyright (c) 2005 All rights reserved.** Last change: # $Revision: 1.5.4.1 $* $Author: jmkasunich $* $Date: 2006/05/02 01:56:19 $********************************************************************//** This file, 'AX5214H.c', is a HAL component that provides a    driver for the Axiom Measurement & Control AX5241H 48 channel    digital I/O board.    The configuration is determined by a config string passed to     insmod when loading the module.  The format consists of a base    address, followed by a eight character string that sets the    direction of each group of pins, repeated for each card (if     more than one card is used).   Each character of the direction    string is either "I" or "O".  The first character sets the    direction of port A on channel 1 (Port 1A), the next sets     port B on channel 1 (port 1B), the next sets the low nibble    of port C on channel 1 (port 1CL), and the fourth sets the     high nibble of port C on channel 1 (port 1CH).  The next four    characters do the same thing for channel 2 (ports 2A, 2B,     2CL, and 2CH).    example:    insmod AX5214.o cfg="0x220 IIIOIIOO"        The example above is for one card, with it's base address     set to hex 220, and with 36 channels of input (Ports 1A,     1B, 1CL, 2A, and 2B) and 12 channels of output (Ports 1CH,    2CL, and 2CH).    The driver creates HAL pins and parameters for each port pin    as follows:    Each physical output has a correspinding HAL pin, named    'ax5214.<boardnum>.out-<pinnum>', and a HAL parameter    'ax5214.<boardnum>.out-<pinnum>-invert'.    Each physical input has two corresponding HAL pins, named    'ax5214.<boardnum>.in-<pinnum>' and    'ax5214.<boardnum>.in-<pinnum>-not'.    <boardnum> is the board number, starting from zero.      <pinnum> is the pin number, from 0 to 47.        Note that the driver assumes active LOW signals.  This    is so that modules such as OPTO-22 will work correctly    (TRUE means output ON, or input energized).  If the     signals are being used directly without buffering or    isolation the inversion needs to be accounted for.    The driver exports two HAL functions for each board,     'ax5214.<boardnum>.read' and 'ax5214.<boardnum>.write'.*//** Copyright (C) 2005 John Kasunich                       <jmkasunich AT users DOT sourceforge DOT net>*//** 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.*/#if ( !defined RTAPI )#error This is a realtime driver, needs RTAPI#endif#include <linux/ctype.h>	/* isspace() */#include "rtapi.h"		/* RTAPI realtime OS API */#include "rtapi_app.h"		/* RTAPI realtime module decls */#include "hal.h"		/* HAL public API decls *//* If FASTIO is defined, uses outb() and inb() from <asm.io>,   instead of rtapi_outb() and rtapi_inb() - the <asm.io> ones   are inlined, and save a microsecond or two (on my 233MHz box)*/#define FASTIO#ifdef FASTIO#define rtapi_inb inb#define rtapi_outb outb#include <asm/io.h>#endif#ifdef MODULE/* module information */MODULE_AUTHOR("John Kasunich");MODULE_DESCRIPTION("Axiom AX5214H Driver for HAL");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif /* MODULE_LICENSE */static char *cfg = "";	/* config string, default no boards */RTAPI_MP_STRING(cfg, "config string");#endif /* MODULE *//************************************************************************                STRUCTURES AND GLOBAL VARIABLES                       *************************************************************************//* this structure contains the runtime data needed by the   driver for a single board*/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_t;typedef struct {    unsigned short base_addr;	/* base I/O address (0x220, etc.) */    unsigned char dir_bits;	/* LSB is port 1A, MSB is port 2CH, */				/*   1 means output, 0 means input */    unsigned char port1config;	/* config register value for port 1 */    unsigned char port2config;	/* config register value for port 1 */    io_pin_t port_1A[8];    io_pin_t port_1B[8];    io_pin_t port_1CL[4];    io_pin_t port_1CH[4];    io_pin_t port_2A[8];    io_pin_t port_2B[8];    io_pin_t port_2CL[4];    io_pin_t port_2CH[4];    hal_u8_t raw[8];		/* raw read data, for debug */} board_t;/* pointer to array of board_t structs in shared memory, 1 per board */static board_t *board_array;/* other globals */static int comp_id;		/* component ID */static int num_boards;		/* number of ports configured *//************************************************************************                  LOCAL FUNCTION DECLARATIONS                         *************************************************************************//* These are the functions that actually do the I/O   everything else is just init code*/static void read_board(void *arg, long period);static void write_board(void *arg, long period);/* 'pins_and_params()' does most of the work involved in setting up   the driver.  It parses the command line (argv[]), then if the   command line is OK, it calls hal_init(), allocates shared memory   for the parport_t data structure(s), and exports pins and parameters   It does not set up functions, since that is handled differently in   realtime and user space.*/static int pins_and_params(char *argv[]);static unsigned short parse_board_addr(char *cp);static int export_board(int boardnum, board_t * board);static int export_port(int boardnum, int pin_num, io_pin_t *pin, int num_pins, int dir);static int export_input_pin(int boardnum, int pinnum, io_pin_t *pin);static int export_output_pin(int boardnum, int pinnum, io_pin_t *pin);/************************************************************************                       INIT AND EXIT CODE                             *************************************************************************/#define MAX_BOARDS 8#define MAX_TOK ((MAX_BOARDS*2)+3)int rtapi_app_main(void){    char *cp;    char *argv[MAX_TOK];    char name[HAL_NAME_LEN + 2];    int n, retval;    /* test for config string */    if ((cfg == 0) || (cfg[0] == '\0')) {	rtapi_print_msg(RTAPI_MSG_ERR, "AX5214H: ERROR: no config string\n");	return -1;    }    /* as a RT module, we don't get a nice argc/argv command line, we only       get a single string... so we need to tokenize it ourselves */    /* and to make things worse, it seems that insmod under kernel 2.6       ends the config string at the first space, so I added the ability       to use '_' as a token separator.  What an ugly hack...  HAL needs       a better way to handle insmod time config data */    cp = cfg;    for (n = 0; n < MAX_TOK; n++) {	/* strip leading whitespace or token separators */	while ((*cp != '\0') && ( isspace(*cp) || ( *cp == '_') ))	    cp++;	/* mark beginning of token */	argv[n] = cp;	/* find end of token */	while ((*cp != '\0') && !( isspace(*cp) || ( *cp == '_') ))	    cp++;	/* mark end of this token, prepare to search for next one */	if (*cp != '\0') {	    *cp = '\0';	    cp++;	}    }    for (n = 0; n < MAX_TOK; n++) {	/* is token empty? */	if (argv[n][0] == '\0') {	    /* yes - make pointer NULL */	    argv[n] = NULL;	}    }    /* parse "command line", set up pins and parameters */    retval = pins_and_params(argv);    if (retval != 0) {	return retval;    }    /* export functions for each board */    for (n = 0; n < num_boards; n++) {	/* make read function name */	rtapi_snprintf(name, HAL_NAME_LEN, "ax5214h.%d.read", n);	/* export read function */	retval = hal_export_funct(name, read_board, &(board_array[n]),	    0, 0, comp_id);	if (retval != 0) {	    rtapi_print_msg(RTAPI_MSG_ERR,		"AX5214H: ERROR: port %d read funct export failed\n", n);	    hal_exit(comp_id);	    return -1;	}	/* make write function name */	rtapi_snprintf(name, HAL_NAME_LEN, "ax5214h.%d.write", n);	/* export write function */	retval = hal_export_funct(name, write_board, &(board_array[n]),	    0, 0, comp_id);	if (retval != 0) {	    rtapi_print_msg(RTAPI_MSG_ERR,		"AX5214H: ERROR: port %d write funct export failed\n", n);	    hal_exit(comp_id);	    return -1;	}    }    rtapi_print_msg(RTAPI_MSG_INFO,	"AX5214H: installed driver for %d boards\n", num_boards);    return 0;}void rtapi_app_exit(void){    int n;    board_t *board;        for ( n = 0 ; n < num_boards ; n++ ) {	board = &(board_array[n]);	/* reset all outputs to high/off */	outb(0xff, board->base_addr+0);	outb(0xff, board->base_addr+1);	outb(0xff, board->base_addr+2);	outb(0xff, board->base_addr+3);	outb(0xff, board->base_addr+4);	outb(0xff, board->base_addr+5);	outb(0xff, board->base_addr+6);	outb(0xff, board->base_addr+7);    }    hal_exit(comp_id);}/************************************************************************                  REALTIME PORT READ AND WRITE FUNCTIONS              *************************************************************************/static void split_input(unsigned char data, io_pin_t *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++;    }}    static void read_board(void *arg, long period){    board_t *board;    unsigned char indata;        board = arg;    if ( (board->dir_bits & 0x01) == 0 ) {	indata = rtapi_inb(board->base_addr+0);	split_input(indata, &(board->port_1A[0]), 8);    }    if ( (board->dir_bits & 0x02) == 0 ) {	indata = rtapi_inb(board->base_addr+1);	split_input(indata, &(board->port_1B[0]), 8);    }    if ( (board->dir_bits & 0x0A) != 0x0A ) {	indata = rtapi_inb(board->base_addr+2);	if ( (board->dir_bits & 0x04) == 0 ) {	    split_input(indata, &(board->port_1CL[0]), 4);	}	indata >>= 4;	if ( (board->dir_bits & 0x08) == 0 ) {	    split_input(indata, &(board->port_1CH[0]), 4);	}    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -