All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gnu.io.RS485 Maven / Gradle / Ivy

/*-------------------------------------------------------------------------
|   RXTX License v 2.1 - LGPL v 2.1 + Linking Over Controlled Interface.
|   RXTX is a native interface to serial ports in java.
|   Copyright 1997-2007 by Trent Jarvi [email protected] and others who
|   actually wrote it.  See individual source files for more information.
|
|   A copy of the LGPL v 2.1 may be found at
|   http://www.gnu.org/licenses/lgpl.txt on March 4th 2007.  A copy is
|   here for your convenience.
|
|   This library is free software; you can redistribute it and/or
|   modify it under the terms of the GNU Lesser General Public
|   License as published by the Free Software Foundation; either
|   version 2.1 of the License, or (at your option) any later version.
|
|   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
|   Lesser General Public License for more details.
|
|   An executable that contains no derivative of any portion of RXTX, but
|   is designed to work with RXTX by being dynamically linked with it,
|   is considered a "work that uses the Library" subject to the terms and
|   conditions of the GNU Lesser General Public License.
|
|   The following has been added to the RXTX License to remove
|   any confusion about linking to RXTX.   We want to allow in part what
|   section 5, paragraph 2 of the LGPL does not permit in the special
|   case of linking over a controlled interface.  The intent is to add a
|   Java Specification Request or standards body defined interface in the 
|   future as another exception but one is not currently available.
|
|   http://www.fsf.org/licenses/gpl-faq.html#LinkingOverControlledInterface
|
|   As a special exception, the copyright holders of RXTX give you
|   permission to link RXTX with independent modules that communicate with
|   RXTX solely through the Sun Microsytems CommAPI interface version 2,
|   regardless of the license terms of these independent modules, and to copy
|   and distribute the resulting combined work under terms of your choice,
|   provided that every copy of the combined work is accompanied by a complete
|   copy of the source code of RXTX (the version of RXTX used to produce the
|   combined work), being distributed under the terms of the GNU Lesser General
|   Public License plus this exception.  An independent module is a
|   module which is not derived from or based on RXTX.
|
|   Note that people who make modified versions of RXTX are not obligated
|   to grant this special exception for their modified versions; it is
|   their choice whether to do so.  The GNU Lesser General Public License
|   gives permission to release a modified version without this exception; this
|   exception also makes it possible to release a modified version which
|   carries forward this exception.
|
|   You should have received a copy of the GNU Lesser General Public
|   License along with this library; if not, write to the Free
|   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
|   All trademarks belong to their respective owners.
--------------------------------------------------------------------------*/
package gnu.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.TooManyListenersException;


/**
 * @author Trent Jarvi
 * @version %I%, %G%
 * @since JDK1.0
 */

final class RS485 extends RS485Port {

    static {
        System.loadLibrary("rxtxRS485");
        Initialize();
    }


    /**
     * Initialize the native library
     */
    private native static void Initialize();


    /** Actual RS485Port wrapper class */


    /**
     * Open the named port
     */
    public RS485(String name) throws PortInUseException {
        fd = open(name);
    }

    private native int open(String name) throws PortInUseException;


    /**
     * File descriptor
     */
    private int fd;

    /**
     * DSR flag
     **/
    static boolean dsrFlag = false;

    /**
     * Output stream
     */
    private final RS485OutputStream out = new RS485OutputStream();

    public OutputStream getOutputStream() {
        return out;
    }


    /**
     * Input stream
     */
    private final RS485InputStream in = new RS485InputStream();

    public InputStream getInputStream() {
        return in;
    }


    /**
     * Set the RS485Port parameters
     */
    public void setRS485PortParams(int b, int d, int s, int p)
            throws UnsupportedCommOperationException {
        nativeSetRS485PortParams(b, d, s, p);
        speed = b;
        dataBits = d;
        stopBits = s;
        parity = p;
    }

    /**
     * Set the native RS485 port parameters
     */
    private native void nativeSetRS485PortParams(int speed, int dataBits,
                                                 int stopBits, int parity) throws UnsupportedCommOperationException;

    /**
     * Line speed in bits-per-second
     */
    private int speed = 9600;

    public int getBaudRate() {
        return speed;
    }

    /**
     * Data bits port parameter
     */
    private int dataBits = DATABITS_8;

    public int getDataBits() {
        return dataBits;
    }

    /**
     * Stop bits port parameter
     */
    private int stopBits = RS485Port.STOPBITS_1;

    public int getStopBits() {
        return stopBits;
    }

    /**
     * Parity port parameter
     */
    private int parity = RS485Port.PARITY_NONE;

    public int getParity() {
        return parity;
    }


    /**
     * Flow control
     */
    private int flowmode = RS485Port.FLOWCONTROL_NONE;

    public void setFlowControlMode(int flowcontrol) {
        try {
            setflowcontrol(flowcontrol);
        } catch (IOException e) {
            e.printStackTrace();
            return;
        }
        flowmode = flowcontrol;
    }

    public int getFlowControlMode() {
        return flowmode;
    }

    native void setflowcontrol(int flowcontrol) throws IOException;


	/*
    linux/drivers/char/n_hdlc.c? FIXME
		[email protected]
	*/

    /**
     * Receive framing control
     */
    public void enableReceiveFraming(int f)
            throws UnsupportedCommOperationException {
        throw new UnsupportedCommOperationException("Not supported");
    }

    public void disableReceiveFraming() {
    }

    public boolean isReceiveFramingEnabled() {
        return false;
    }

    public int getReceiveFramingByte() {
        return 0;
    }


    /**
     * Receive timeout control
     */
    private int timeout = 0;

    public native int NativegetReceiveTimeout();

    public native boolean NativeisReceiveTimeoutEnabled();

    public native void NativeEnableReceiveTimeoutThreshold(int time, int threshold, int InputBuffer);

    public void disableReceiveTimeout() {
        enableReceiveTimeout(0);
    }

    public void enableReceiveTimeout(int time) {
        if (time >= 0) {
            timeout = time;
            NativeEnableReceiveTimeoutThreshold(time, threshold, InputBuffer);
        } else {
            System.out.println("Invalid timeout");
        }
    }

    public boolean isReceiveTimeoutEnabled() {
        return (NativeisReceiveTimeoutEnabled());
    }

    public int getReceiveTimeout() {
        return (NativegetReceiveTimeout());
    }

    /**
     * Receive threshold control
     */

    private int threshold = 0;

    public void enableReceiveThreshold(int thresh) {
        if (thresh >= 0) {
            threshold = thresh;
            NativeEnableReceiveTimeoutThreshold(timeout, threshold, InputBuffer);
        } else /* invalid thresh */ {
            System.out.println("Invalid Threshold");
        }
    }

    public void disableReceiveThreshold() {
        enableReceiveThreshold(0);
    }

    public int getReceiveThreshold() {
        return threshold;
    }

    public boolean isReceiveThresholdEnabled() {
        return (threshold > 0);
    }

    /** Input/output buffers */
    /**
     * FIXME I think this refers to
     * FOPEN(3)/SETBUF(3)/FREAD(3)/FCLOSE(3)
     * [email protected]
     * 

* These are native stubs... */ private int InputBuffer = 0; private int OutputBuffer = 0; public void setInputBufferSize(int size) { InputBuffer = size; } public int getInputBufferSize() { return (InputBuffer); } public void setOutputBufferSize(int size) { OutputBuffer = size; } public int getOutputBufferSize() { return (OutputBuffer); } /** * Line status methods */ public native boolean isDTR(); public native void setDTR(boolean state); public native void setRTS(boolean state); private native void setDSR(boolean state); public native boolean isCTS(); public native boolean isDSR(); public native boolean isCD(); public native boolean isRI(); public native boolean isRTS(); /** * Write to the port */ public native void sendBreak(int duration); private native void writeByte(int b) throws IOException; private native void writeArray(byte b[], int off, int len) throws IOException; private native void drain() throws IOException; /** * RS485 read methods */ private native int nativeavailable() throws IOException; private native int readByte() throws IOException; private native int readArray(byte b[], int off, int len) throws IOException; /** * RS485 Port Event listener */ private RS485PortEventListener SPEventListener; /** * Thread to monitor data */ private MonitorThread monThread; /** * Process RS485PortEvents */ native void eventLoop(); private int dataAvailable = 0; public void sendEvent(int event, boolean state) { switch (event) { case RS485PortEvent.DATA_AVAILABLE: dataAvailable = 1; if (monThread.Data) break; return; case RS485PortEvent.OUTPUT_BUFFER_EMPTY: if (monThread.Output) break; return; /* if( monThread.DSR ) break; return; if (isDSR()) { if (!dsrFlag) { dsrFlag = true; RS485PortEvent e = new RS485PortEvent(this, RS485PortEvent.DSR, !dsrFlag, dsrFlag ); } } else if (dsrFlag) { dsrFlag = false; RS485PortEvent e = new RS485PortEvent(this, RS485PortEvent.DSR, !dsrFlag, dsrFlag ); } */ case RS485PortEvent.CTS: if (monThread.CTS) break; return; case RS485PortEvent.DSR: if (monThread.DSR) break; return; case RS485PortEvent.RI: if (monThread.RI) break; return; case RS485PortEvent.CD: if (monThread.CD) break; return; case RS485PortEvent.OE: if (monThread.OE) break; return; case RS485PortEvent.PE: if (monThread.PE) break; return; case RS485PortEvent.FE: if (monThread.FE) break; return; case RS485PortEvent.BI: if (monThread.BI) break; return; default: System.err.println("unknown event:" + event); return; } RS485PortEvent e = new RS485PortEvent(this, event, !state, state); if (SPEventListener != null) SPEventListener.RS485Event(e); } /** * Add an event listener */ public void addEventListener(RS485PortEventListener lsnr) throws TooManyListenersException { if (SPEventListener != null) throw new TooManyListenersException(); SPEventListener = lsnr; monThread = new MonitorThread(); monThread.start(); } /** * Remove the RS485 port event listener */ public void removeEventListener() { SPEventListener = null; if (monThread != null) { monThread.interrupt(); monThread = null; } } public void notifyOnDataAvailable(boolean enable) { monThread.Data = enable; } public void notifyOnOutputEmpty(boolean enable) { monThread.Output = enable; } public void notifyOnCTS(boolean enable) { monThread.CTS = enable; } public void notifyOnDSR(boolean enable) { monThread.DSR = enable; } public void notifyOnRingIndicator(boolean enable) { monThread.RI = enable; } public void notifyOnCarrierDetect(boolean enable) { monThread.CD = enable; } public void notifyOnOverrunError(boolean enable) { monThread.OE = enable; } public void notifyOnParityError(boolean enable) { monThread.PE = enable; } public void notifyOnFramingError(boolean enable) { monThread.FE = enable; } public void notifyOnBreakInterrupt(boolean enable) { monThread.BI = enable; } /** * Close the port */ private native void nativeClose(); public void close() { setDTR(false); setDSR(false); nativeClose(); super.close(); fd = 0; } /** * Finalize the port */ protected void finalize() { if (fd > 0) close(); } /** * Inner class for RS485OutputStream */ class RS485OutputStream extends OutputStream { public void write(int b) throws IOException { writeByte(b); } public void write(byte b[]) throws IOException { writeArray(b, 0, b.length); } public void write(byte b[], int off, int len) throws IOException { writeArray(b, off, len); } public void flush() throws IOException { drain(); } } /** * Inner class for RS485InputStream */ class RS485InputStream extends InputStream { public int read() throws IOException { dataAvailable = 0; return readByte(); } public int read(byte b[]) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int len) throws IOException { dataAvailable = 0; int i = 0, Minimum = 0; int intArray[] = { b.length, InputBuffer, len }; /* find the lowest nonzero value timeout and threshold are handled on the native side see NativeEnableReceiveTimeoutThreshold in RS485Imp.c */ while (intArray[i] == 0 && i < intArray.length) i++; Minimum = intArray[i]; while (i < intArray.length) { if (intArray[i] > 0) { Minimum = Math.min(Minimum, intArray[i]); } i++; } Minimum = Math.min(Minimum, threshold); if (Minimum == 0) Minimum = 1; int Available = available(); int Ret = readArray(b, off, Minimum); return Ret; } public int available() throws IOException { return nativeavailable(); } } class MonitorThread extends Thread { /** * Note: these have to be separate boolean flags because the * RS485PortEvent constants are NOT bit-flags, they are just * defined as integers from 1 to 10 -DPL */ private boolean CTS = false; private boolean DSR = false; private boolean RI = false; private boolean CD = false; private boolean OE = false; private boolean PE = false; private boolean FE = false; private boolean BI = false; private boolean Data = false; private boolean Output = false; MonitorThread() { } public void run() { eventLoop(); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy