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

📄 hal_motenc.c

📁 CNC 的开放码,EMC2 V2.2.8版
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** * * Copyright (C) 2005 Peter G. Vavaroutsos <pete AT vavaroutsos DOT com> * License: GPL Version 2 * * $RCSfile: hal_motenc.c,v $ * $Author: jmkasunich $ * $Locker:  $ * $Revision: 1.23 $ * $State: Exp $ * $Date: 2007/06/13 02:05:25 $ * * This is the driver for the Vital Systems MOTENC-100 board. * The board includes 8 quadrature decoders, 8 analog inputs, * 8 analog outputs, 68 digital inputs, 32 digital outputs, * programable timer interrupts, a watch dog timer, and a hardware * E-STOP circuit. * * Installation of the driver (realtime only): * * insmod hal_motenc * * * The following items are exported to the HAL. <boardId> is read * from the jumper settings on the MOTENC-100 board and is formated * as "%d". <channel> is formated as "%02d". * * Encoders: *   Parameters: *	float	motenc.<boardId>.enc-<channel>-scale * *   Pins: *	s32	motenc.<boardId>.enc-<channel>-count *	float	motenc.<boardId>.enc-<channel>-position *	bit	motenc.<boardId>.enc-<channel>-index *	bit	motenc.<boardId>.enc-<channel>-index-enable *	bit	motenc.<boardId>.enc-<channel>-reset * *   Functions: *	void    motenc.<boardId>.encoder-read * * * DACs: *   Parameters: *	float	motenc.<boardId>.dac-<channel>-offset *	float	motenc.<boardId>.dac-<channel>-gain * *   Pins: *	float	motenc.<boardId>.dac-<channel>-value * *   Functions: *	void    motenc.<boardId>.dac-write * * * ADC: *   Parameters: *	float	motenc.<boardId>.adc-<channel>-offset *	float	motenc.<boardId>.adc-<channel>-gain * *   Pins: *	float	motenc.<boardId>.adc-<channel>-value * *   Functions: *	void    motenc.<boardId>.adc-read * * * Digital In: *   Pins: *	bit	motenc.<boardId>.pin-<channel>-in *	bit	motenc.<boardId>.pin-<channel>-in-not * *   Functions: *	void    motenc.<boardId>.digital-in-read * * * Digital Out: *   Parameters: *	bit	motenc.<boardId>.pin-<channel>-out-invert * *   Pins: *	bit	motenc.<boardId>.pin-<channel>-out * *   Functions: *	void    motenc.<boardId>.digital-out-write * * * Miscellaneous: *   Parameters: *	u32	motenc.<boardId>.watchdog-control *		    MOTENC_WATCHDOG_CTL_8MS	    0x00000000 *		    MOTENC_WATCHDOG_CTL_16MS	    0x00000001 *		    MOTENC_WATCHDOG_CTL_ENABLE	    0x00000004 *		    MOTENC_WATCHDOG_CTL_AUTO_RESET  0x00000010 // Reset by DAC writes. * *   Pins: *	bit	motenc.<boardId>.estop-in *	bit	motenc.<boardId>.estop-in-not *	bit	motenc.<boardId>.watchdog-reset * *   Functions: *	void    motenc.<boardId>.misc-update * ****************************************************************************** * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 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 <linux/pci.h>#include "rtapi.h"			// RTAPI realtime OS API.#include "rtapi_app.h"			// RTAPI realtime module decls.#include "hal.h"			// HAL public API decls.#include "motenc.h"			// Hardware dependent defines.#ifndef MODULE#define MODULE#endif#ifdef MODULE// Module information.MODULE_AUTHOR("Pete Vavaroutsos");MODULE_DESCRIPTION("Driver for Vital Systems MOTENC-100 for EMC HAL");MODULE_LICENSE("GPL");#endif // MODULE/****************************************************************************** * DEVICE OBJECT * * This object contains all the data for one card. A device object is * dynamically allocated in shmem for each card during initialization. * ******************************************************************************/typedef struct {    // Pins.    hal_s32_t				*pCount;	// Captured binary count value.    hal_float_t				*pPosition;	// Scaled position (floating point).    hal_bit_t				*pIndex;	// Current state of index.    hal_bit_t				*pIndexEnable;	// Setting this pin causes the count							// to be cleared on the next index pulse.							// Use this feature at your own risk as the PID loop							// may get upset. This pin is self clearing.    hal_bit_t				*pReset;	// Setting this pin causes Count to be reset.    // Parameters.    hal_float_t				scale;		// Scaling factor for position.    // Private data.    float				oldScale;	// Stored scale value.    double				scaleRecip;	// Reciprocal value used for scaling.} EncoderPinsParams;typedef struct {    // Pins.    hal_float_t				*pValue;	// Desired value.    // Parameters.    hal_float_t				offset;    hal_float_t				gain;} DacPinsParams;typedef struct {    // Pins.    hal_float_t				*pValue;	// Converted value.    // Parameters.    hal_float_t				offset;    hal_float_t				gain;} AdcPinsParams;typedef struct {    // Pins.    hal_bit_t				*pValue;    hal_bit_t				*pValueNot;} DigitalInPinsParams;typedef struct {    // Pins.    hal_bit_t				*pValue;    // Parameters.    hal_bit_t				invert;} DigitalOutPinsParams;typedef struct {    // Pins.    hal_bit_t				*pEstopIn;    hal_bit_t				*pEstopInNot;    hal_bit_t				*pWatchdogReset;// This pin is self clearing.    // Parameters.    hal_u32_t				watchdogControl;} MiscPinsParams;typedef struct {    // Private data.    MotencRegMap			*pCard;    int					boardType;    char				*pTypeName;    int					boardID;    int					numFpga;    int					adcState;    hal_u32_t				watchdogControl;// Shadow HW register.    // Exported to HAL.    EncoderPinsParams			encoder[MOTENC_NUM_ENCODER_CHANNELS];    DacPinsParams			dac[MOTENC_NUM_DAC_CHANNELS];    AdcPinsParams			adc[MOTENC_NUM_ADC_CHANNELS];    DigitalInPinsParams			in[MOTENC_NUM_DIGITAL_INPUTS];    DigitalOutPinsParams		out[MOTENC_NUM_DIGITAL_OUTPUTS];    MiscPinsParams			misc;} Device;// These methods are used for initialization.static int Device_Init(Device *this, MotencRegMap *pCard);static int Device_ExportPinsParametersFunctions(Device *this, int componentId);static int Device_ExportEncoderPinsParametersFunctions(Device *this, int componentId, int boardId);static int Device_ExportDacPinsParametersFunctions(Device *this, int componentId, int boardId);static int Device_ExportAdcPinsParametersFunctions(Device *this, int componentId, int boardId);static int Device_ExportDigitalInPinsParametersFunctions(Device *this, int componentId, int boardId);static int Device_ExportDigitalOutPinsParametersFunctions(Device *this, int componentId, int boardId);static int Device_ExportMiscPinsParametersFunctions(Device *this, int componentId, int boardId);// These methods are exported to the HAL.static void Device_EncoderRead(void *this, long period);static void Device_DacWrite(void *this, long period);static void Device_AdcRead(void *this, long period);static void Device_DigitalInRead(void *this, long period);static void Device_DigitalOutWrite(void *this, long period);static void Device_MiscUpdate(void *this, long period);// Private helper methods.static int Device_AdcRead4(Device *this, int startChannel);/****************************************************************************** * DRIVER OBJECT * * This object contains all the data for this HAL component. * ******************************************************************************/#define MAX_DEVICES			4		// Since there are 2 board id bits.typedef struct {    int					componentId;	// HAL component ID.    Device				*deviceTable[MAX_DEVICES];    unsigned char			idPresent[MAX_DEVICES];} Driver;static Driver				driver;/****************************************************************************** * INIT AND EXIT CODE ******************************************************************************/intrtapi_app_main(void){    int					i, j;    struct pci_dev			*pDev = NULL;    MotencRegMap			*pCard = NULL;    Device				*pDevice;    // Connect to the HAL.    driver.componentId = hal_init("hal_motenc");    if (driver.componentId < 0) {	rtapi_print_msg(RTAPI_MSG_ERR, "MOTENC: ERROR: hal_init() failed\n");	return(-EINVAL);    }    for(i = 0; i < MAX_DEVICES; i++){	driver.deviceTable[i] = NULL;	driver.idPresent[i] = 0;    }    i = 0;    // Find a MOTENC card.    while((i < MAX_DEVICES) && ((pDev = pci_find_device(MOTENC_VENDOR_ID, MOTENC_DEVICE_ID, pDev)) != NULL)){	// Allocate memory for device object.	pDevice = hal_malloc(sizeof(Device));	if (pDevice == 0) {	    rtapi_print_msg(RTAPI_MSG_ERR, "MOTENC: ERROR: hal_malloc() failed\n");	    hal_exit(driver.componentId);	    return(-ENOMEM);	}	// Save pointer to device object.	driver.deviceTable[i++] = pDevice;		// Map card into memory.	pCard = (MotencRegMap *)ioremap_nocache(pci_resource_start(pDev, 2), pci_resource_len(pDev, 2));	rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card detected in slot %2x\n", PCI_SLOT(pDev->devfn));	rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card address @ %p, Len = %d\n", pCard, (int)pci_resource_len(pDev, 2));	// Initialize device.	Device_Init(pDevice, pCard);	rtapi_print_msg(RTAPI_MSG_INFO, "MOTENC: Card is %s, ID: %d\n", pDevice->pTypeName, pDevice->boardID);        if ( pDevice->boardType == 0 ) {	    rtapi_print_msg(RTAPI_MSG_ERR, "MOTENC: ERROR, unknown card detected\n");	    hal_exit(driver.componentId);	    return(-ENODEV);	}		if ( driver.idPresent[pDevice->boardID] != 0 ) {	    // duplicate ID... a strict driver would bail out, but	    // we are nice, we try to find an unused ID	    j = 0;	    while ( driver.idPresent[j] != 0 ) {		j++;	        if ( j >= MAX_DEVICES ) {		    rtapi_print_msg(RTAPI_MSG_ERR, "MOTENC: ERROR, duplicate ID, can't remap\n");		    hal_exit(driver.componentId);		    return(-EINVAL);		}	    }	    pDevice->boardID = j;	    rtapi_print_msg(RTAPI_MSG_WARN, "MOTENC: WARNING, duplicate ID, remapped to %d\n", j);	}	driver.idPresent[pDevice->boardID] = 1;		// Export pins, parameters, and functions.	if(Device_ExportPinsParametersFunctions(pDevice, driver.componentId)){	    hal_exit(driver.componentId);	    return(-EINVAL);	}    }    if(pCard == NULL){	// No card present.	rtapi_print_msg(RTAPI_MSG_WARN, "MOTENC: **** No MOTENC card detected ****\n");	hal_exit(driver.componentId);	return -ENODEV;    }    hal_ready(driver.componentId);    return(0);}voidrtapi_app_exit(void){    int					i, j;    Device				*pDevice;    hal_exit(driver.componentId);    for(i = 0; i < MAX_DEVICES; i++){	if((pDevice = driver.deviceTable[i]) != NULL){	    // turn off digital outputs	    for(j = 0; j < pDevice->numFpga; j++){		pDevice->pCard->fpga[i].digitalIo = MOTENC_DIGITAL_OUT;	    }	    // set DAC outputs to zero volts	    for(i = 0; i < MOTENC_NUM_DAC_CHANNELS; i++){		pDevice->pCard->dac[i] = MOTENC_DAC_COUNT_ZERO;	    }	    	    // Unmap card.	    iounmap((void *)(pDevice->pCard));	    // TODO: Free device object when HAL supports free.//	    hal_free(pDevice);	}    }}/****************************************************************************** * DEVICE OBJECT FUNCTION DEFINITIONS ******************************************************************************//* * LOCAL FUNCTIONS */static intDevice_Init(Device *this, MotencRegMap *pCard){    int i, status;    this->pCard = pCard;    this->adcState = 0;    this->watchdogControl = 0;    // Identify type of board.    status = pCard->fpga[0].boardVersion;    if ( status == 0 ) {	// MOTENC-100.	this->boardType = 1;	this->pTypeName = "MOTENC-100";	this->numFpga = 2;    } else if ( status == 1 ) {	// MOTENC-Lite.	this->boardType = 2;	this->pTypeName = "MOTENC-Lite";	this->numFpga = 1;    } else {	// No idea what it is.	this->boardType = 0;	this->pTypeName = "unknown";	this->numFpga = 0;	return -1;    }    // Extract board id from first FPGA. The user sets this via jumpers on the card.    status = pCard->fpga[0].statusControl;    this->boardID = (status & MOTENC_STATUS_BOARD_ID) >> MOTENC_STATUS_BOARD_ID_SHFT;        // Initialize hardware.    for(i = 0; i < this->numFpga; i++){	pCard->fpga[i].digitalIo = MOTENC_DIGITAL_OUT;	pCard->fpga[i].statusControl = MOTENC_CONTROL_ENCODER_RESET;    }    for(i = 0; i < MOTENC_NUM_DAC_CHANNELS; i++){	pCard->dac[i] = MOTENC_DAC_COUNT_ZERO;    }    pCard->timerIrqDisable = 1;    pCard->watchdogControl = this->watchdogControl;    return(0);}static intDevice_ExportPinsParametersFunctions(Device *this, int componentId){    int					msgLevel, boardId, error;    // 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.    msgLevel = rtapi_get_msg_level();    rtapi_set_msg_level(RTAPI_MSG_WARN);    boardId = this->boardID;        // Export encoders.    error = Device_ExportEncoderPinsParametersFunctions(this, componentId, boardId);    // Export DACs.    if(!error) error = Device_ExportDacPinsParametersFunctions(this, componentId, boardId);    // Export ADCs.    if(!error) error = Device_ExportAdcPinsParametersFunctions(this, componentId, boardId);    // Export digital I/O.    if(!error) error = Device_ExportDigitalInPinsParametersFunctions(this, componentId, boardId);    if(!error) error = Device_ExportDigitalOutPinsParametersFunctions(this, componentId, boardId);    // Export miscellaneous.    if(!error) error = Device_ExportMiscPinsParametersFunctions(this, componentId, boardId);    // Restore saved message level.    rtapi_set_msg_level(msgLevel);    return(error);}static intDevice_ExportEncoderPinsParametersFunctions(Device *this, int componentId, int boardId){    int					halError, channel;    char				name[HAL_NAME_LEN + 2];    // Export pins and parameters.    halError = 0;    for(channel = 0; channel < this->numFpga * MOTENC_FPGA_NUM_ENCODER_CHANNELS; channel++){	// Pins.	rtapi_snprintf(name, HAL_NAME_LEN, "motenc.%d.enc-%02d-count", boardId, channel);	if((halError = hal_pin_s32_new(name, HAL_OUT, &(this->encoder[channel].pCount), componentId)) != 0)	    break;	rtapi_snprintf(name, HAL_NAME_LEN, "motenc.%d.enc-%02d-position", boardId, channel);	if((halError = hal_pin_float_new(name, HAL_OUT, &(this->encoder[channel].pPosition), componentId)) != 0)	    break;	rtapi_snprintf(name, HAL_NAME_LEN, "motenc.%d.enc-%02d-index", boardId, channel);	if((halError = hal_pin_bit_new(name, HAL_OUT, &(this->encoder[channel].pIndex), componentId)) != 0)	    break;	rtapi_snprintf(name, HAL_NAME_LEN, "motenc.%d.enc-%02d-index-enable", boardId, channel);	if((halError = hal_pin_bit_new(name, HAL_IO, &(this->encoder[channel].pIndexEnable), componentId)) != 0)	    break;	rtapi_snprintf(name, HAL_NAME_LEN, "motenc.%d.enc-%02d-reset", boardId, channel);	if((halError = hal_pin_bit_new(name, HAL_IN, &(this->encoder[channel].pReset), componentId)) != 0)	    break;	// Parameters.	rtapi_snprintf(name, HAL_NAME_LEN, "motenc.%d.enc-%02d-scale", boardId, channel);	if((halError = hal_param_float_new(name, HAL_RW, &(this->encoder[channel].scale), componentId)) != 0)	    break;	// Init encoder.

⌨️ 快捷键说明

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