/ src / hal / drivers / hal_evoreg.c
hal_evoreg.c
  1  /********************************************************************
  2  * Description:  hal_evoreg.c
  3  *               This file, 'hal_evoreg.c', is a HAL component that 
  4  *               provides a driver for the Siemens EVOREG motion 
  5  *               control board.
  6  *
  7  * Author: Martin Kuhnle, John Kasunich
  8  * License: GPL Version 2
  9  *    
 10  * Copyright (c) 2003 All rights reserved.
 11  *
 12  * Last change: 
 13  ********************************************************************/
 14  
 15  /** This file, 'hal_evoreg.c', is a HAL component that provides a
 16      driver for the Siemens EVOREG motion control board.
 17      This board privides three 16bit DAC's, three encoder inputs,
 18      46 digital inputs and 21 digital outputs
 19  
 20      Fixme: error messages are not proper up to now
 21      ToDo: better error messages
 22            make inverted bits available
 23            posibility to read back outputs
 24            check dac values for limits
 25            scale for every dacs
 26            scale for every encoder
 27            check if the dacs are updated all at the same time
 28            enable Interrupts
 29            check for wire break
 30            watchdog
 31  
 32  
 33  
 34   Copyright (C) 2003 Martin Kuhnle
 35                         <mkuhnle AT users DOT sourceforge DOT net>
 36                  John Kasunich
 37                         <jmkasunich AT users DOT sourceforge DOT net>
 38                         
 39  */
 40  
 41  /** This program is free software; you can redistribute it and/or
 42      modify it under the terms of version 2 of the GNU General
 43      Public License as published by the Free Software Foundation.
 44      This library is distributed in the hope that it will be useful,
 45      but WITHOUT ANY WARRANTY; without even the implied warranty of
 46      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 47      GNU General Public License for more details.
 48  
 49      You should have received a copy of the GNU General Public
 50      License along with this library; if not, write to the Free Software
 51      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 52  
 53      THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR
 54      ANY HARM OR LOSS RESULTING FROM ITS USE.  IT IS _EXTREMELY_ UNWISE
 55      TO RELY ON SOFTWARE ALONE FOR SAFETY.  Any machinery capable of
 56      harming persons must have provisions for completely removing power
 57      from all motors, etc, before persons enter any danger area.  All
 58      machinery must be designed to comply with local and national safety
 59      codes, and the authors of this software can not, and do not, take
 60      any responsibility for such compliance.
 61  
 62      This code was written as part of the EMC HAL project.  For more
 63      information, go to www.linuxcnc.org.
 64  */
 65  
 66  #include "rtapi_ctype.h"	/* isspace() */
 67  #include "rtapi.h"		/* RTAPI realtime OS API */
 68  #include "rtapi_app.h"		/* RTAPI realtime module decls */
 69  #include "hal.h"		/* HAL public API decls */
 70  
 71  /* If FASTIO is defined, uses outb() and inb() from <asm.io>,
 72     instead of rtapi_outb() and rtapi_inb() - the <asm.io> ones
 73     are inlined, and save a microsecond or two (on my 233MHz box)
 74  */
 75  #define FASTIO
 76  
 77  #ifdef FASTIO
 78  #define rtapi_inb inb
 79  #define rtapi_outb outb
 80  #include <asm/io.h>
 81  #endif
 82  
 83  /* module information */
 84  MODULE_AUTHOR("Martin Kuhnle");
 85  MODULE_DESCRIPTION("SIEMENS-EVOREG Driver for EMC HAL");
 86  MODULE_LICENSE("GPL");
 87  /* static char *cfg = 0; */
 88  /* config string
 89  RTAPI_MP_STRING(cfg, "config string"); */
 90  
 91  /***********************************************************************
 92  *                STRUCTURES AND GLOBAL VARIABLES                       *
 93  ************************************************************************/
 94  
 95  /* this structure contains the runtime data needed by the
 96     driver for a single port/channel
 97  */
 98  
 99  typedef struct {
100  	void *io_base;
101          hal_float_t *dac_out[3];  /* ptrs for dac output */
102  	hal_float_t *position[3];	   /* ptrs for encoder input */
103  	hal_bit_t *digital_in[47];    /* ptrs for digital input pins 0 - 45 */
104          hal_bit_t *digital_out[25];    /* ptrs for digital output pins 0 - 20 */
105          __u16 raw_counts_old[3];
106          __s32 counts[3];
107          hal_float_t pos_scale;         /*! \todo scale for position command FIXME schould be one per axis */
108  } evoreg_t;
109  
110  /* pointer to array of evoreg_t structs in shared memory, 1 per port */
111  static evoreg_t *port_data_array;
112  
113  /* other globals */
114  static int comp_id;		/* component ID */
115  static int num_ports;		/* number of ports configured */
116  
117  /***********************************************************************
118  *                  LOCAL FUNCTION DECLARATIONS                         *
119  ************************************************************************/
120  /* These is the functions that actually do the I/O
121     everything else is just init code
122  */
123  static void update_port(void *arg, long period);
124  
125  /***********************************************************************
126  *                       INIT AND EXIT CODE                             *
127  ************************************************************************/
128  
129  #define MAX_PORTS 8
130  #define MAX_DAC 3               /* number of DACs per card */
131  #define MAX_ENC 3               /* number of Encoders per card */
132  
133  #define MAX_TOK ((MAX_PORTS*2)+3)
134  
135  int rtapi_app_main(void)
136  {
137      char name[HAL_NAME_LEN + 1];
138      int n,i , retval, num_dac, num_enc;
139  
140      unsigned int base=0x300;
141  
142      /* only one port at the moment */
143      num_ports = 1;
144      n = 0;
145  
146      #define ISA_BASE    0xC9000
147      #define ISA_MAX    0x100000  /* allgemeiner Speicherzugriff */
148  
149      
150      /* STEP 1: initialise the driver */
151      comp_id = hal_init("hal_evoreg");
152      if (comp_id < 0) {
153  	rtapi_print_msg(RTAPI_MSG_ERR,
154  	    "EVOREG: ERROR: hal_init() failed\n");
155  	return -1;
156      }
157  
158      /* STEP 2: allocate shared memory for EVOREG data */
159      port_data_array = hal_malloc(num_ports * sizeof(evoreg_t));
160      if (port_data_array == 0) {
161  	rtapi_print_msg(RTAPI_MSG_ERR,
162  	    "EVOREG: ERROR: hal_malloc() failed\n");
163  	hal_exit(comp_id);
164  	return -1;
165      }
166  
167      /*! \todo FIXME: Test memory area and setup the card */
168      port_data_array->io_base = ioremap(ISA_BASE, ISA_MAX - ISA_BASE);
169      rtapi_print_msg(RTAPI_MSG_ERR,"EVOREG: io_base: %p \n", port_data_array->io_base);
170      outw(0x82c9,base); /* set indexregister */
171  
172      /* Set all outputs to zero */
173      writew(0, port_data_array->io_base + 0x20); /* digital out 0-15  */
174      writew(0, port_data_array->io_base + 0x40); /* digital out 16-23 */
175      writew(0, port_data_array->io_base + 0x60); /* DAC 1 */
176      writew(0, port_data_array->io_base + 0x80); /* DAC 2 */
177      writew(0, port_data_array->io_base + 0xa0); /* DAC 3 */
178      /* Reset Encoder's */
179      writew(0, port_data_array->io_base + 0x02); /* ENCODER 1 */
180      writew(0, port_data_array->io_base + 0x0a); /* ENCODER 2 */
181      writew(0, port_data_array->io_base + 0x12); /* ENCODER 3 */
182      
183      /* STEP 3: export the pin(s) */
184  
185      /* Export DAC pin's */
186      for ( num_dac=1; num_dac<=MAX_DAC; num_dac++) {
187        retval = hal_pin_float_newf(HAL_IN, &(port_data_array->dac_out[num_dac-1]),
188  				  comp_id, "evoreg.%d.dac-%02d-out", 1, num_dac);
189        if (retval < 0) {
190  	  rtapi_print_msg(RTAPI_MSG_ERR,
191  	    "EVOREG: ERROR: port %d var export failed with err=%i\n", n + 1,
192  	    retval);
193  	hal_exit(comp_id);
194  	return -1;
195        }
196      }
197  
198      /* Export Encoder pin's */
199      for ( num_enc=1; num_enc<=MAX_ENC; num_enc++) {
200        retval = hal_pin_float_newf(HAL_OUT, &(port_data_array->position[num_enc - 1]),
201  				  comp_id, "evoreg.%d.position-%02d-in", 1, num_enc);
202        if (retval < 0) {
203  	  rtapi_print_msg(RTAPI_MSG_ERR,
204  	      "EVOREG: ERROR: port %d var export failed with err=%i\n", n + 1,
205  	      retval);
206    	  hal_exit(comp_id);
207    	  return -1;
208        }
209      }
210  
211      /* Export IO pin's */
212  
213      /* export write only HAL pin's for the input bit */
214      for ( i=0; i<=45;i++) {
215        retval += hal_pin_bit_newf(HAL_OUT, &(port_data_array->digital_in[i]),
216  				 comp_id, "evoreg.%d.pin-%02d-in", 1, i);
217  
218        /* export another write only HAL pin for the same bit inverted */
219        /*
220        retval += hal_pin_bit_newf(HAL_OUT, &(port_data_array->digital_in[(2*i)+1]),
221  				 comp_id, "evoreg.%d.pin-%02d-in-not", 1, i); */
222        if (retval < 0) {
223  	  rtapi_print_msg(RTAPI_MSG_ERR,
224  	      "EVOREG: ERROR: port %d var export failed with err=%i\n", n + 1,
225  	      retval);
226    	  hal_exit(comp_id);
227    	  return -1;
228        }
229      }
230  
231      /* export read only HAL pin's for the output bit */
232      for ( i=0; i<=23;i++) {
233        retval += hal_pin_bit_newf(HAL_IN, &(port_data_array->digital_out[i]),
234  				 comp_id, "evoreg.%d.pin-%02d-out", 1, i);
235  
236        /* export another read only HAL pin for the same bit inverted */
237        /*
238        retval += hal_pin_bit_newf(HAL_IN, &(port_data_array->digital_out[(2*i)+1]),
239  				 comp_id, "evoreg.%d.pin-%02d-out-not", 1, i));  */
240        if (retval < 0) {
241  	  rtapi_print_msg(RTAPI_MSG_ERR,
242  	      "EVOREG: ERROR: port %d var export failed with err=%i\n", n + 1,
243  	      retval);
244    	  hal_exit(comp_id);
245    	  return -1;
246        }
247      }
248  
249      /* export parameter for scaling */
250      retval = hal_param_float_newf(HAL_RW, &(port_data_array->pos_scale),
251  				  comp_id, "evoreg.%d.position-scale", 1);
252      if (retval != 0) {
253  	return retval;
254      }
255  
256  
257      /* STEP 4: export function */
258      rtapi_snprintf(name, sizeof(name), "evoreg.%d.update", n + 1);
259      retval = hal_export_funct(name, update_port, &(port_data_array[n]), 1, 0,
260  	comp_id);
261      if (retval < 0) {
262  	rtapi_print_msg(RTAPI_MSG_ERR,
263  	    "EVOREG: ERROR: port %d write funct export failed\n", n + 1);
264  	hal_exit(comp_id);
265  	return -1;
266      }
267  
268      rtapi_print_msg(RTAPI_MSG_INFO,
269  	"EVOREG: installed driver for %d card(s)\n", num_ports);
270      hal_ready(comp_id);
271      return 0;
272  }
273  
274  void rtapi_app_exit(void)
275  {
276      outw(0x0,0x300);
277      hal_exit(comp_id);
278  }
279  
280  /**************************************************************
281  * REALTIME PORT WRITE FUNCTION                                *
282  **************************************************************/
283  
284  static void update_port(void *arg, long period)
285  {
286      evoreg_t *port;
287      int pin;
288      unsigned char tmp, mask;
289      __u16 raw_counts[3];
290  
291      port = arg;
292  
293  /* write DAC's */
294      writew((*(port->dac_out[0])/10 * 0x7fff), port->io_base + 0x60);
295      writew((*(port->dac_out[1])/10 * 0x7fff), port->io_base + 0x80);
296      writew((*(port->dac_out[2])/10 * 0x7fff), port->io_base + 0xa0);
297  
298  /* Read Encoders, improve the 16bit hardware counters to 32bit and scale the values */
299      raw_counts[0] = (__u16) readw(port->io_base);
300      raw_counts[1] = (__u16) readw(port->io_base + 0x08 );
301      raw_counts[2] = (__u16) readw(port->io_base + 0x10 );
302  
303      port->counts[0] += (__s16) (raw_counts[0] - port->raw_counts_old[0]);
304      port->raw_counts_old[0] = raw_counts[0];
305  
306      port->counts[1] += (__s16) (raw_counts[1] - port->raw_counts_old[1]);
307      port->raw_counts_old[1] = raw_counts[1];
308  
309      port->counts[2] += (__s16) (raw_counts[2] - port->raw_counts_old[2]);
310      port->raw_counts_old[2] = raw_counts[2];
311  
312      *port->position[0] = port->counts[0] * port->pos_scale;
313      *port->position[1] = port->counts[1] * port->pos_scale;
314      *port->position[2] = port->counts[2] * port->pos_scale;
315  
316  
317  /* read digital inputs */
318       tmp = readw(port->io_base + 0x20);       /* digital input 0-15 */
319        mask = 0x01;
320  	for (pin=0 ; pin < 16 ; pin++) {
321  	*port->digital_in[pin] = (tmp & mask) ? 1:0 ;
322  	mask <<= 1;
323  	}
324       tmp = readw(port->io_base + 0x40);       /* digital input 16-31 */
325        mask = 0x01;
326  	for (pin=16 ; pin < 32 ; pin++) {
327  	*port->digital_in[pin] = (tmp & mask) ? 1:0 ;
328  	mask <<= 1;
329  	}
330  
331       tmp = readw(port->io_base + 0x60);       /* digital input 32-45 */
332        mask = 0x01;
333  	for (pin=32 ; pin < 46 ; pin++) {
334  	*port->digital_in[pin] = (tmp & mask) ? 1:0 ;
335  	mask <<= 1;
336  	}
337  
338  
339  /* write digital outputs */
340       tmp = 0x0;
341       mask = 0x01;
342       for (pin=0; pin < 16; pin++) {
343          if (port->digital_out[pin]) {
344          tmp |= mask;
345          mask <<= 1;
346          }
347       }
348       writew( tmp, port->io_base + 0x20);  /* digital output 0-15 */
349  
350  
351       tmp = 0x0;
352       mask = 0x01;
353       for (pin=16; pin < 24; pin++) {
354          if (port->digital_out[pin]) {
355          tmp |= mask;
356          mask <<= 1;
357          }
358       }
359       writew( tmp, port->io_base + 0x40);  /* digital output 16-23 */
360  
361  }