divers/vmeio.c

Go to the documentation of this file.
00001 /*-----------------------------------------------------------------------------
00002  *  Copyright (c) 1996      TRIUMF Data Acquistion Group
00003  *  Please leave this header in any reproduction of that distribution
00004  * 
00005  *  TRIUMF Data Acquisition Group, 4004 Wesbrook Mall, Vancouver, B.C. V6T 2A3
00006  *  Email: online@triumf.ca           Tel: (604) 222-1047  Fax: (604) 222-1074
00007  *         amaudruz@triumf.ca
00008  * -----------------------------------------------------------------------------
00009  *  
00010  *  Description : Support function library for the vmeIO board developed at TRIUMF
00011  *                by Mr. T. ambardar & P.A. Amaudruz
00012  *  Requires      : 
00013  *  Application : VME
00014  *  Author      :  Pierre-Andre Amaudruz Data Acquisition Group
00015  *  Revision 1.0:  1998/Mar/20 Pierre      Inline function
00016   $Id: vmeio.c 2753 2005-10-07 14:55:31Z ritt $
00017  *
00018  *---------------------------------------------------------------------------*/
00019 
00020 #include "stdio.h"
00021 #include "string.h"
00022 
00023 #include "vmeio.h"
00024 
00025 void myStub(void)
00026 {
00027 #ifdef OS_VXWORKS
00028    logMsg("myStub\n", 0, 0, 0, 0, 0, 0);
00029 #endif
00030 }
00031 
00032 /************ INLINE function for General command ***********/
00033 INLINE void vmeio_intsync_set(DWORD base_adr, DWORD pattern)
00034 /**************************************************************\
00035  Purpose: Set VMEIO interrupt source to be sync mode.
00036           Each bit refers to an input (0:7)
00037           If not set the interrupt source is Async
00038  Input:
00039   DWORD * base_addr     : base address of the VMEIO
00040   DWORD pattern         : data to be applied to board
00041  Output:
00042     none
00043  Function value:
00044     none
00045 \**************************************************************/
00046 {
00047    volatile DWORD *spec_adr;
00048 
00049    spec_adr = (DWORD *) (A32D24 + base_adr) + (SET_INT_SYNC);
00050    *spec_adr = (pattern & 0xf);
00051 }
00052 
00053 /************ INLINE function for General command **********/
00054 INLINE void vmeio_pulse_set(const DWORD base_adr, DWORD pattern)
00055 /**************************************************************\
00056  Purpose: Set VMEIO output channel pattern to be pulse mode
00057           Each bit refers to an output (0:23)
00058           If not set the output is latch mode
00059  Input:
00060   DWORD * base_addr     : base address of the VMEIO
00061   DWORD pattern         : data to be applied to board
00062  Output:
00063     none
00064  Function value:
00065     none
00066 \**************************************************************/
00067 {
00068    volatile DWORD *spec_adr;
00069 
00070    spec_adr = (DWORD *) (A32D24 + base_adr) + (SET_PULSE);
00071    *spec_adr = (pattern & 0xffffff);
00072 }
00073 
00074 /************ INLINE function for General command **********/
00075 INLINE void vmeio_sync_read(const DWORD base_adr, DWORD * data)
00076 /**************************************************************\
00077  Purpose: read VMEIO sync input data if gate received
00078  Input:
00079   DWORD * base_addr       : base address of the VMEIO
00080   DWORD * data            : data to be read
00081  Output:
00082     none
00083  Function value:
00084     none
00085 \**************************************************************/
00086 {
00087    volatile DWORD *spec_adr;
00088    DWORD status;
00089 
00090    /* status : Check first if trigger has been received */
00091    spec_adr = (DWORD *) (A32D24 + base_adr) + (READ_STATUS);
00092    status = *spec_adr;
00093    status &= 0xf;
00094    if (status != 0) {
00095       spec_adr = (DWORD *) (A32D24 + base_adr) + (READ_SYNC);
00096       *data = (*spec_adr & 0xffffff);
00097    } else
00098       *data = 0x80000000;
00099 }
00100 
00101 /************ INLINE function for General command **********/
00102 INLINE void vmeio_async_read(const DWORD base_adr, DWORD * data)
00103 /**************************************************************\
00104  Purpose: read VMEIO async input data
00105  Input:
00106   DWORD * base_addr       : base address of the VMEIO
00107   DWORD * data            : data to be read
00108  Output:
00109     none
00110  Function value:
00111     none
00112 \**************************************************************/
00113 {
00114    volatile DWORD *spec_adr;
00115 
00116    spec_adr = (DWORD *) (A32D24 + base_adr) + (READ_ASYNC);
00117    *data = (*spec_adr & 0xffffff);
00118 }
00119 
00120 /************ INLINE function for General command **********/
00121 INLINE void vmeio_pulse_write(const DWORD base_adr, DWORD data)
00122 /**************************************************************\
00123  Purpose: write to VMEIO pulse output.
00124           only the pulse enable channels will be affected
00125           Each bit correspond to a output (0:23)
00126  Input:
00127   DWORD * base_addr       : base address of the VMEIO
00128   DWORD data              : data to write
00129  Output:
00130     none
00131  Function value:
00132     none
00133 \**************************************************************/
00134 {
00135    DWORD *spec_adr;
00136 
00137    /* status : Check first if trigger has been received */
00138    spec_adr = (DWORD *) (A32D24 | base_adr) + (WRITE_PULSE);
00139    *spec_adr = (data & 0xffffff);
00140 }
00141 
00142 /************ INLINE function for General command **********/
00143 INLINE void vmeio_latch_write(const DWORD base_adr, DWORD data)
00144 /**************************************************************\
00145  Purpose: write to VMEIO latch output.
00146           only the latch enable channels will be affected
00147           Each bit correspond to a output (0:23)
00148  Input:
00149   DWORD * base_addr       : base address of the VMEIO
00150   DWORD data              : data to write
00151  Output:
00152     none
00153  Function value:
00154     none
00155 \**************************************************************/
00156 {
00157    volatile DWORD *spec_adr;
00158 
00159    /* status : Check first if trigger has been received */
00160    spec_adr = (DWORD *) (A32D24 + base_adr) + (WRITE_LATCH);
00161    *spec_adr = (data & 0xffffff);
00162 }
00163 
00164 /************ INLINE function for General command **********/
00165 INLINE void vmeio_clear(const DWORD base_adr)
00166 /**************************************************************\
00167  Purpose: clear the status reg (strobe)
00168  Input:
00169   DWORD * base_addr       : base address of the VMEIO
00170  Output:
00171     none
00172  Function value:
00173     none
00174 \**************************************************************/
00175 {
00176    volatile DWORD *spec_adr;
00177 
00178    /* status : Check first if trigger has been received */
00179    spec_adr = (DWORD *) (A32D24 + base_adr) + (CLEAR_VMEIO);
00180    *spec_adr = 0x0;
00181 }
00182 
00183 /************ INLINE function for General command **********/
00184 INLINE void vmeio_status_read(const DWORD base_adr, DWORD * data)
00185 /**************************************************************\
00186  Purpose: read the status register.
00187           contains the strobe bit (0x1), the interrupt level (0x70)
00188  Input:
00189   DWORD * base_addr       : base address of the VMEIO
00190   DWORD * data            : status
00191  Output:
00192     none
00193  Function value:
00194     none
00195 \**************************************************************/
00196 {
00197    volatile DWORD *spec_adr;
00198 
00199    spec_adr = (DWORD *) (A32D24 + base_adr) + (READ_STATUS);
00200    *data = (*spec_adr & 0xff);
00201 }
00202 
00203 /************ INLINE function for Interrupt handling **********/
00204 INLINE void vmeio_int_clear(const DWORD base_adr)
00205 {
00206    volatile DWORD *spec_adr;
00207 
00208    /* status : Check first if trigger has been received */
00209    spec_adr = (DWORD *) (A32D24 + base_adr) + (CLEAR_VMEIO);
00210    *spec_adr = 0x0;
00211 }
00212 
00213 INLINE void vmeio_int_enable(const DWORD base_adr, int intnum)
00214 /**************************************************************\
00215  Purpose: Enable the interrupt for the bitwise input intnum (0xff).
00216           The interrupt vector is then the VECTOR_BASE+intnum
00217  Input:
00218   DWORD * base_addr       : base address of the VMEIO
00219   DWORD * intnum          : interrupt number (input 0:7)
00220  Output:
00221     none
00222  Function value:
00223     none
00224 \**************************************************************/
00225 {
00226    volatile DWORD *spec_adr;
00227 
00228    spec_adr = (DWORD *) (A32D24 + base_adr) + (ENABLE_INT);
00229    *spec_adr = (intnum & 0xff);
00230 #ifdef OS_VXWORKS
00231    sysIntEnable(7);             /* interrupt level 7 */
00232 #endif
00233 }
00234 
00235 INLINE void vmeio_int_disable(const DWORD base_adr, int intnum)
00236 /**************************************************************\
00237  Purpose: Disable the interrupt for the bitwise input intnum (0xff).
00238           The interrupt vector is then the VECTOR_BASE+intnum
00239  Input:
00240   DWORD * base_addr       : base address of the VMEIO
00241   DWORD * intnum          : interrupt number (input 0:7)
00242  Output:
00243     none
00244  Function value:
00245     none
00246 \**************************************************************/
00247 {
00248    volatile DWORD *spec_adr;
00249 
00250 #ifdef OS_VXWORKS
00251    sysIntDisable(7);            /* interrupt level 7 */
00252 #endif
00253    spec_adr = (DWORD *) (A32D24 + base_adr) + (ENABLE_INT);
00254    *spec_adr = ~(intnum & 0xff);
00255 }
00256 
00257 INLINE void vmeio_int_attach(const DWORD base_adr, DWORD base_vect, int intnum,
00258                              void (*isr) (void))
00259 /**************************************************************\
00260  Purpose: Book an ISR for a bitwise set of interrupt input (0xff).
00261           The interrupt vector is then the VECTOR_BASE+intnum
00262  Input:
00263   DWORD * base_addr      : base address of the VMEIO
00264   DWORD base_vect        : base vector of the module
00265   DWORD intnum           : interrupt number (0:7)
00266   DWORD isr_routine      : interrupt routine pointer
00267  Output:
00268     none
00269  Function value:
00270     none
00271 \**************************************************************/
00272 {
00273    vmeio_int_clear(base_adr);   /* clear any pending front panel interrupts */
00274    vmeio_int_disable(base_adr, intnum); /* bitwise input */
00275 #ifdef OS_VXWORKS
00276    if (intnum < 8)
00277       intConnect(INUM_TO_IVEC(base_vect + intnum), (VOIDFUNCPTR) isr, intnum);
00278 #else
00279    printf("vector : 0x%x\n", base_vect + intnum);
00280 #endif
00281    vmeio_int_enable(base_adr, intnum);  /* bitwise input */
00282 }
00283 
00284 INLINE void vmeio_int_detach(const DWORD base_adr, DWORD base_vect, int intnum)
00285 /**************************************************************\
00286  Purpose: Unbook an ISR for a bitwise set of interrupt input (0xff).
00287           The interrupt vector is then the VECTOR_BASE+intnum
00288  Input:
00289   DWORD * base_addr       : base address of the VMEIO
00290   DWORD base_vect        : base vector of the module
00291   DWORD intnum           : interrupt number (0:7)
00292  Output:
00293     none
00294  Function value:
00295     none
00296 \**************************************************************/
00297 {
00298    vmeio_int_clear(base_adr);   /* clear any pending front panel interrupts */
00299    vmeio_int_disable(base_adr, intnum); /* mask off external interrupt x */
00300 #ifdef OS_VXWORKS
00301    if (intnum < 8)
00302       intConnect(INUM_TO_IVEC(base_vect + intnum), (VOIDFUNCPTR) myStub, intnum);
00303 #else
00304    printf("vector : 0x%x\n", base_vect + intnum);
00305 #endif
00306 }
00307 
00308 /*-Tests---------------------------------------------------------*/
00309 void vmeio(void)
00310 {
00311    printf("\n---> vmeIO Triumf board 24bit in/out latch/pulse + 8 interrupts <---\n");
00312    printf("Inline: vmeio_intsync_set (base, pattern)  : set interrupt source\n");
00313    printf("Inline: vmeio_pulse_set   (base, pattern)  : set output pulse\n");
00314    printf("Inline: vmeio_sync_read   (base, *data)    : read sync input\n");
00315    printf("Inline: vmeio_async_read  (base, *data)    : read Async input\n");
00316    printf("Inline: vmeio_pulse_write (base, data)     : write pulse output\n");
00317    printf("Inline: vmeio_latch_write (base, data)     : write latch output\n");
00318    printf("Inline: vmeio_clear       (base)           : clear strobe\n");
00319    printf("Inline: vmeio_status_read (base, *status)  : read status register\n");
00320    printf("Inline: vmeio_int_clear   (base)           : clear interrupts\n");
00321    printf("Inline: vmeio_int_enable  (base, int#)     : enable interrupt (0:7)\n");
00322    printf("Inline: vmeio_int_disable (base, int#)     : disable interrupt (0:7)\n");
00323    printf("Inline: vmeio_int_enable  (base, int#)     : enable interrupt (0:7)\n");
00324    printf("Inline: vmeio_int_attach  (base, vec, int#, isr) : interrupt (0:7)\n");
00325    printf("Inline: vmeio_int_detach  (base, vect, int#) : interrupt (0:7)\n");
00326    printf("Test  : vmeio_Status_read (0x780000)       : display status\n");
00327    printf("Test  : vmeio_Async_read  (0x780000)       : read Async\n");
00328    printf("Test  : vmeio_Sync_read   (0x780000)       : read sync\n");
00329    printf("Test  : vmeio_Pulse_write (0x780000,       : write pulse\n");
00330    printf("Test  : vmeio_Latch_write (0x780000,       : write latch\n");
00331    printf("Test  : vmeio_Clear       (0x780000)       : clear VMEIO\n");
00332    printf("Test  : Interrupt : VMEIO_BASE: 0x780000, VMEIO_VECT_BASE: 0x7F\n");
00333    printf("Test  : The interrupt test is based on the following configuration:\n");
00334    printf("        Output 0 -> strobe\n");
00335    printf("        Output 1 -> Input 0\n");
00336    printf("        Output 2 -> Input 1\n");
00337    printf("        Output 3 -> Input 2\n");
00338    printf("        vmeio_attach_async_interrupt(1)  will enable I1\n");
00339    printf("        vmeio_gen_async(1)               will generate int in I1\n");
00340    printf("  or    vmeio_attach_sync_interrupt(1)   will enable I1\n");
00341    printf("        vmeio_gen_sync(1)                will generate int in I1\n");
00342    printf("Test  : vmeio_attach_async_interrupt( x...): attach, enable Int#\n");
00343    printf("Test  : vmeio_attach_sync_interrupt( x...) : attach, enable Int#\n");
00344    printf("Test  : vmeio_detach_interrupt( x...)      : detach, enable Int#\n");
00345    printf("Test  : vmeio_gen_async( x)                : generate a Async int\n");
00346    printf("Test  : vmeio_gen_sync( x)                 : generate a sync int\n");
00347 }
00348 
00349 #define VMEIO_BASE  0x780000    /* VMEIO base address */
00350 #define VMEIO_VECT_BASE 0x7f
00351 
00352 void vmeio_Status_read(DWORD base)
00353 {
00354    char str[5];
00355    DWORD status, pattern;
00356    vmeio_status_read(base, &status);
00357    printf("vmeio status :0x%x\n", status);
00358    pattern = status & 0xff;
00359    printf("Status vmeio ==> intsrc:%s / Strobe:%1.1x\n",
00360           (((pattern & 0xf0) >> 4) == 0 ? strcpy(str, "ASync") : strcpy(str, "Sync"))
00361           , (pattern & 0x1));
00362 }
00363 
00364 void vmeio_Async_read(DWORD base)
00365 {
00366    DWORD status;
00367    vmeio_async_read(base, &status);
00368    printf("vmeio Async data :0x%x\n", status);
00369 }
00370 
00371 void vmeio_Sync_read(DWORD base)
00372 {
00373    DWORD status;
00374    vmeio_sync_read(base, &status);
00375    printf("vmeio Sync data :0x%x\n", status);
00376 }
00377 
00378 void vmeio_Pulse_write(DWORD base, DWORD pat)
00379 {
00380    vmeio_pulse_write(base, pat);
00381 }
00382 
00383 void vmeio_Latch_write(DWORD base, DWORD pat)
00384 {
00385    vmeio_latch_write(base, pat);
00386 }
00387 
00388 void vmeio_Clear(DWORD base)
00389 {
00390    vmeio_clear(base);
00391 }
00392 
00393 /* the interrupt test is based on the following configuration:
00394    O0 -> strobe
00395    O1 -> I0
00396    O2 -> I1
00397    O3 -> I2
00398    
00399    vmeio_attach_async_interrupt(1)
00400              will enable I1
00401    vmeio_gen_async(1)
00402              will generate int in I1
00403 
00404    vmeio_attach_sync_interrupt(1)
00405              will enable I1
00406    vmeio_gen_async(1)
00407              will generate int in I1
00408 */
00409 
00410 
00411 void vmeiotint(void)
00412 {
00413    static int vmeio_private_counter = 0;
00414 #ifdef OS_VXWORKS
00415    logMsg("%vmeiotint external interrupt #%i received and served\n",
00416           vmeio_private_counter++, 0, 0, 0, 0, 0);
00417 #endif
00418 }
00419 
00420 void vmeio_attach_async_interrupt(DWORD vmeioint)
00421 {
00422    vmeio_int_disable(VMEIO_BASE, vmeioint);
00423    vmeio_intsync_set(VMEIO_BASE, 0x0);
00424    vmeio_pulse_set(VMEIO_BASE, 0x0);
00425    vmeio_int_attach(VMEIO_BASE, VMEIO_VECT_BASE, vmeioint, vmeiotint);
00426    vmeio_int_enable(VMEIO_BASE, vmeioint);
00427    printf("Please generate an interrupt on line %d\n", vmeioint);
00428 }
00429 
00430 void vmeio_gen_async(DWORD intnum)
00431 {
00432    vmeio_Latch_write(VMEIO_BASE, (intnum << 1));
00433    vmeio_Latch_write(VMEIO_BASE, 0);
00434    vmeio_intsync_set(VMEIO_BASE, 0x0);  /* reset interrupt */
00435 }
00436 
00437 void vmeio_gen_sync(DWORD intnum)
00438 {
00439    vmeio_Pulse_write(VMEIO_BASE, (0x1 | (intnum << 1)));
00440    vmeio_clear(VMEIO_BASE);     /* reset interrupt */
00441 }
00442 
00443 void vmeio_attach_sync_interrupt(DWORD vmeioint)
00444 {
00445    vmeio_intsync_set(VMEIO_BASE, (0x1 | (vmeioint << 1)));
00446    vmeio_pulse_set(VMEIO_BASE, (0x1 | (vmeioint << 1)));        /* strobe done by intput 0 */
00447    vmeio_int_disable(VMEIO_BASE, vmeioint);
00448    vmeio_int_attach(VMEIO_BASE, VMEIO_VECT_BASE, vmeioint, vmeiotint);
00449    vmeio_int_enable(VMEIO_BASE, vmeioint);
00450    printf("Please generate an interrupt on line %d\n", vmeioint);
00451 }
00452 
00453 void vmeio_detach_interrupt(DWORD vmeioint)
00454 {
00455    vmeio_int_disable(VMEIO_BASE, vmeioint);
00456    vmeio_int_detach(VMEIO_BASE, VMEIO_VECT_BASE, vmeioint);
00457    printf("Interrupt on line %d detached \n", vmeioint);
00458 }

Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk