/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: GPIB.java * Written by Eric Kim and Tom O'Neill, Sun Microsystems. * * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * * Electric(tm) is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */ package com.sun.electric.tool.simulation.test; /** * Driver for National Instruments NI-488.2M GPIB controller, includes the JNI * native method signatures and Java convenience wrapper methods. This class * provides low-level control, but the API methods are provided by the * friendlier {@link Equipment} class. * <p> * Native command documentation including error codes can be found in <a * href="http://www.ni.com/pdf/manuals/370963a.pdf"> the NI-488.2M Software * Reference Manual </a> and in <a href="../../../../../ugpib.h"> * <tt>ugpib.h</tt> </a>. */ class GPIB { /** * The return values from the native GPIB routines will have bit 15 set if * an error has occured. */ private static final int ERR_BIT = 0x8000; /** Whether catchError() is in progress */ private static boolean errorPending = false; /** String identifying unused status bit or error code */ public static final String UNUSED = "unused"; /** Meaning of the various bits in the ibsta status word */ public static final String[] STATUS_BITS = { "DCAS: device clear state (brd)", "DTAS: device trigger state (brd)", "LACS: Listener (brd)", "TACS: Talker (brd)", "ATN: Attention is asserted", "CIC: Controller-In-Charge", "REM: Remote state", "LOK: Lockout state", "CMPL: I/O completed", UNUSED, UNUSED, "RQS: Device requesting service", "SRQI: SRQ interrupt received", "END: END or EOS detected", "TIMO: Time limit exceeded", "ERR: GPIB error" }; /** Meaning of the possible decimal values of the iberr error code */ public static final String[] ERROR_CODES = { "EDVR: UNIX error (code in ibcnt, which we currently don't return)", "ECIC: Function requires GPIB board to be CIC", "ENOL: Write handshake error (e.g., no Listener)", "EADR: GPIB board not addressed correctly", "EARG: Invalid argument to function call", "ESAC: GPIB board not System Controller as required", "EABO: I/O operation aborted (timeout)", "ENEB: Non-existent GPIB board", "EDMA: DMA hardware problem", "EBTO: DMA hardware bus timeout", UNUSED, "ECAP: No capability for operation", "EFSO: File system error", UNUSED, "EBUS: GPIB bus error", "ESTB: Serial Poll status byte queue overflow", "ESRQ: SRQ stuck in ON position", UNUSED, UNUSED, UNUSED, "ETAB: Table Problem" }; /** Suppress default constructor to make class non-instantiable */ private GPIB() { } /* * helper utilities */ /** * Open GPIB device with the given name and return its unit descriptor. * * @param name * Name of the device to find, from <tt>ibconf</tt> * @return unit descriptor of the device */ public static int findDevice(String name) { name = name + '\0'; //add EOS to be safe int[] istat_ierr = new int[2]; int ud = GPIB.ibfind(name.getBytes(), istat_ierr); String function = "ibfind(" + name + ") when initializing GPIB"; catchError(function, ud, name, istat_ierr[0], istat_ierr[1]); if (ud < 0) { Infrastructure.fatal("Cannot find device " + name + " on GPIB."); } return ud; } /** * Write data to a GPIB device * * @param ud * unit descriptor of the device * @param name * name of the device * @param data * data to write */ public static void ibWrite(int ud, String name, String data) { data = data + '\n'; byte[] bytes = data.getBytes(); int length = bytes.length; int[] ierr = new int[1]; int status = GPIB.ibwrt(ud, bytes, length, ierr); String function = "ibwrt(ud=" + ud + ", data=" + data + ", length=" + length + ") during write to"; catchError(function, ud, name, status, ierr[0]); } /** * Read data from a GPIB device * * @param ud * unit descriptor of the device * @param name * name of the device * @param length * maximum number of bytes to read */ public static String ibRead(int ud, String name, int length) { byte[] bytes = new byte[length]; int[] ierr = new int[1]; int status = GPIB.ibrd(ud, bytes, length, ierr); String output = new String(bytes); String function = "ibrd(ud=" + ud + ", bytes, length=" + length + ") during read from"; catchError(function, ud, name, status, ierr[0]); return output; } /** * Return information about the GPIB software configuration parameters. * Valid <code>option</code> values can be found in the <tt>ibconf</tt> * and <tt>ibask</tt> constants section in <a * href="../../../../../ugpib.h"> <tt>ugpib.h</tt> </a>. Currently * {@link Equipment#CONTROLLER_ID_NUMBER} is provided for convenience * in specifying <code>option</code>. * * @param ud * unit descriptor of the device * @param name * name of the device * @param option * constant identifying which configuration parameter to return * @return value of the requested configuration parameter */ public static int ibAsk(int ud, String name, int option) { int[] value = new int[1]; int[] ierr = new int[1]; int status = GPIB.ibask(ud, option, value, ierr); String function = "ibask(ud=" + ud + ", option=" + option + ", value) during query of"; catchError(function, ud, name, status, ierr[0]); return value[0]; } /** * Clear internal or device functions of the specified device. * * @param ud * unit descriptor identifying device to clear * @param name * name of the device */ public static void ibClr(int ud, String name) { int[] ierr = new int[1]; int status = GPIB.ibclr(ud, ierr); String function = "ibclr(ud=" + ud + ") during clear of"; catchError(function, ud, name, status, ierr[0]); } /** * Send GPIB interface messages to the device. The commands are listed in * Appendix A of <a href="../../../../../manuals/NI-488.2M_sw.pdf">NI-488.2M * Software Reference Manual </a> * * @param ud * unit descriptor identifying device to send command to * @param name * name of the device * @param command * string containing characters to send over GPIB */ public static void ibCmd(int ud, String name, String command) { int[] ierr = new int[1]; command = command + '\n'; byte[] bytes = command.getBytes(); int length = bytes.length; int status = ibcmd(ud, bytes, length, ierr); String function = "ibcmd(ud=" + ud + ", cmd=" + bytes + ", cnt=" + length + ") while sending interface message to"; catchError(function, ud, name, status, ierr[0]); } /** * Issues fatal error on error from a GPIB native command function. * * @param function * description of native GPIB function being checked * @param ud * unit descriptor identifying device function was used on * @param name * name of the device * @param status * NI-488.2M <code>ibsta</code> status word * @param iberr * NI-488.2M <code>iberr</code> status word for the command */ private static void catchError(String function, int ud, String name, int status, int iberr) { if ((status & ERR_BIT) != 0) { Infrastructure.nonfatal("Bad return value ibsta=" + status + " (0x" + Integer.toHexString(status) + ") from native method\nGPIB." + function + "\ndevice " + name + ". Error is iberr=" + iberr + "."); reportStatus(status); reportError(iberr); System.err.println("Find descriptions of these error conditions\n" + "in Chapter 3 of ${TEST_ROOT}/manuals/NI-488.2M_sw.pdf."); if (errorPending == false) { errorPending = true; System.err.println("\nNow querying device " + name + " itself about the error..."); ibWrite(ud, name, "SYST:ERR?"); String error = ibRead(ud, name, 200); System.err.println("Device " + name + " reports error: " + error); } /* * Try to leave the device in a good state. To prevent infinite * loop, don't call this.ibClr() */ int[] ierr = new int[1]; status = GPIB.ibclr(ud, ierr); System.exit(0); } } private static void reportStatus(int status) { System.err .println("The following bits are set in the ibsta status word:"); for (int bit = 0; bit < STATUS_BITS.length; bit++) { int value = (1 << bit); if ((status & value) != 0) { System.err.println(" Bit " + bit + " (0x" + Integer.toHexString(value) + ") means '" + STATUS_BITS[bit] + "'"); if (STATUS_BITS[bit].equals(UNUSED)) { System.err .println("*** This status bit should not occur ***"); } } } } private static void reportError(int iberr) { if (iberr < 0 || iberr >= ERROR_CODES.length || ERROR_CODES[iberr].equals(UNUSED)) { System.err.println("Unknown error code iberr=" + iberr); } else { System.err.println("The error code iberr=" + iberr + " means '" + ERROR_CODES[iberr] + "'"); } } private static void printCodes() { for (int bit = 0; bit < STATUS_BITS.length; bit++) { System.out.println(bit + " (0x" + Integer.toHexString(1 << bit) + "): " + STATUS_BITS[bit]); } for (int err = 0; err < ERROR_CODES.length; err++) { System.out.println(err + ": " + ERROR_CODES[err]); } } /*---------------------------------------------------------------------- * GPIB JNI interface. usually helper utility are preferred than these low * level native call byte in java = 8bits char in c = 8bits * -------------------------------------------------------------------- */ // Load the native C library static { System.loadLibrary("teste"); } public native static int ibwrt(int ud, byte[] data, int length, int[] ierr); public native static int ibrd(int ud, byte[] data, int length, int[] ierr); /** * Open device and return the unit descriptor associated with the given * name. Note <code>istat_ierr[0]</code> is the NI-488M <code>ibsta</code> * status word and <code>istat_ierr[1]</code> is the <code>iberr</code> * error code. * * @param name * device name from <tt>ibconf</tt> * @param istat_ierr * <code>ibsta</code> and <code>iberr</code> status words in * array * @return number used by NI-488M native functions to identify the device */ public native static int ibfind(byte[] name, int[] istat_ierr); /** * Return information about the GPIB software configuration parameters. * * @param ud * unit descriptor identifying device to clear * @param ierr * NI-488.2M <code>iberr</code> status word * @return NI-488.2M <code>ibsta</code> status word */ public native static int ibask(int ud, int option, int[] value, int[] ierr); /** * Clear specified device. * * @param ud * unit descriptor identifying device to clear * @param ierr * NI-488.2M <code>iberr</code> status word * @return NI-488.2M <code>ibsta</code> status word */ public native static int ibclr(int ud, int[] ierr); /** * Send GPIB interface messages to the device. The commands are listed in * Appendix A of <a href="../../../../../manuals/NI-488.2M_sw.pdf">NI-488.2M * Software Reference Manual </a> * * @param ud * unit descriptor identifying device to send command to * @param cmd * characters to be sent over GPIB * @param cnt * requested transfer count (maximum bytes to send) * @param ierr * NI-488.2M <code>iberr</code> status word * @return NI-488.2M <code>ibsta</code> status word */ public native static int ibcmd(int ud, byte[] cmd, long cnt, int[] ierr); public static void main(String[] args) { printCodes(); int ista; do { String string = Infrastructure.readln("Enter ista in hex:"); ista = Integer.parseInt(string, 16); reportStatus(ista); } while (ista != -999); } }