001package jmri.jmrix.dccpp;
002
003/**
004 * Abstract base for classes representing a DCC++ communications port.
005 * Based on XNetSerialPortController by Bob Jacobsen and Paul Bender.
006 *
007 * @author Bob Jacobsen Copyright (C) 2001, 2008
008 * @author Paul Bender Copyright (C) 2004,2010
009 * @author Mark Underwood Copyright (C) 2015
010 */
011public abstract class DCCppSerialPortController extends jmri.jmrix.AbstractSerialPortController implements DCCppPortController {
012
013    private boolean outputBufferEmpty = true;
014
015    public DCCppSerialPortController() {
016        super(new DCCppSystemConnectionMemo());
017        //option2Name = "Buffer";
018        //options.put(option2Name, new Option("Check Buffer : ", validOption2));
019    }
020
021    /**
022     * Check that this object is ready to operate. This is a question of
023     * configuration, not transient hardware status.
024     */
025    @Override
026    public abstract boolean status();
027
028    /**
029     * Can the port accept additional characters? The state of CTS determines
030     * this, as there seems to be no way to check the number of queued bytes and
031     * buffer length. This might go false for short intervals, but it might also
032     * stick off if something goes wrong.
033     */
034    @Override
035    public boolean okToSend() {
036        if (getFlowControl(currentSerialPort) == FlowControl.RTSCTS) {
037            if (checkBuffer) {
038                log.debug("CTS: {} Buffer Empty: {}", currentSerialPort.getCTS(), outputBufferEmpty);
039                return (currentSerialPort.getCTS() && outputBufferEmpty);
040            } else {
041                log.debug("CTS: {}", currentSerialPort.getCTS());
042                return (currentSerialPort.getCTS());
043            }
044        } else {
045            if (checkBuffer) {
046                log.debug("Buffer Empty: {}", outputBufferEmpty);
047                return (outputBufferEmpty);
048            } else {
049                log.debug("No Flow Control or Buffer Check");
050                return (true);
051            }
052        }
053    }
054    
055    /**
056     * Say if the output buffer is empty or full.
057     * This should only be set to false by external processes.
058     */
059    @Override
060    synchronized public void setOutputBufferEmpty(boolean s) {
061        outputBufferEmpty = s;
062    }
063    
064    
065    /* Option 2 is not currently used with RxTx 2.0.  In the past, it
066       was used for the "check buffer status when sending" If this is still set
067       in a configuration file, we need to handle it, but we are not writing it
068       to new configuration files. */
069    /*public String getCurrentOption2Setting() {
070      if(getOptionState(option2Name)==null) return("no");
071     else return getOptionState(option2Name);
072     }*/
073
074    protected String[] validOption2 = new String[]{"yes", "no"};
075    private boolean checkBuffer = false;
076
077    /**
078     * Allow derived classes to set the private checkBuffer value.
079     * @param b Buffer to be held and used from now on.
080     */
081    protected void setCheckBuffer(boolean b) {
082        checkBuffer = b;
083    }
084    
085    @Override
086    public DCCppSystemConnectionMemo getSystemConnectionMemo() {
087        return (DCCppSystemConnectionMemo) super.getSystemConnectionMemo();
088    }
089
090    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DCCppSerialPortController.class);
091
092}