001package jmri.jmrix.lenz;
002
003/**
004 * Abstract base for classes representing an XNet communications port
005 *
006 * @author Bob Jacobsen Copyright (C) 2001, 2008
007 * @author Paul Bender Copyright (C) 2004,2010
008 */
009public abstract class XNetSerialPortController extends jmri.jmrix.AbstractSerialPortController implements XNetPortController {
010
011    private boolean outputBufferEmpty = true;
012
013    private boolean timeSlot = true;
014
015    public XNetSerialPortController() {
016        super(new XNetSystemConnectionMemo());
017    }
018
019    public XNetSerialPortController(XNetSystemConnectionMemo memo) {
020        super(memo);
021    }
022
023    /**
024     * Can the port accept additional characters? The state of CTS determines
025     * this, as there seems to be no way to check the number of queued bytes and
026     * buffer length. This might go false for short intervals, but it might also
027     * stick off if something goes wrong.
028     */
029    @Override
030    public boolean okToSend() {
031        if (getFlowControl(currentSerialPort) == FlowControl.RTSCTS) {
032            if (checkBuffer) {
033                log.debug("CTS: {} Buffer Empty {}",currentSerialPort.getCTS(),outputBufferEmpty);
034                return (currentSerialPort.getCTS() && outputBufferEmpty);
035            } else {
036                log.debug("CTS: {}",currentSerialPort.getCTS());
037                return (currentSerialPort.getCTS());
038            }
039        } else {
040            if (checkBuffer) {
041                log.debug("Buffer Empty: {}", outputBufferEmpty);
042                return (outputBufferEmpty && hasTimeSlot() );
043            } else {
044                log.debug("No Flow Control or Buffer Check");
045                return (hasTimeSlot());
046            }
047        }
048    }
049
050    /**
051     * Indicate whether the Command Station is currently providing a timeslot to this
052     * port controller.
053     *
054     * @return true if the command station is currently providing a timeslot.
055     */
056    @Override
057    public boolean hasTimeSlot(){
058        return timeSlot;
059    }
060    
061    /**
062     * Set a variable indicating whether or not the command station is
063     * providing a timeslot.
064     * <p>
065     * This method should be called with the paramter set to false if
066     * a "Command Station No Longer Providing a timeslot for communications"
067     * (01 05 04) is received.
068     * <p>
069     * This method should be called with the parameter set to true if
070     * a "Command Station is providing a timeslot for communications again."
071     * (01 07 06) is received.
072     *
073     * @param timeslot true if a timeslot is being sent, false otherwise.
074     */
075    @Override
076    public void setTimeSlot(boolean timeslot){
077       timeSlot = timeslot;
078    }    
079
080
081    /**
082     * We need a way to say if the output buffer is empty or full.
083     * <p>
084     * This should only be set to false by external processes.
085     */
086    @Override
087    public synchronized void setOutputBufferEmpty(boolean s) {
088        outputBufferEmpty = s;
089    }
090
091
092    /* Option 2 is not currenddtly used with RxTx 2.0.  In the past, it
093     was used for the "check buffer status when sending" If this is still set
094     in a configuration file, we need to handle it, but we are not writing it
095     to new configuration files. */
096    protected String[] validOption2 = new String[]{"yes", "no"};
097    private boolean checkBuffer = false;
098
099    /**
100     * Allow derived classes to set the private checkBuffer value.
101     * @param b new checkBuffer value
102     */
103    protected void setCheckBuffer(boolean b) {
104        checkBuffer = b;
105    }
106
107    @Override
108    public XNetSystemConnectionMemo getSystemConnectionMemo() {
109        return (XNetSystemConnectionMemo) super.getSystemConnectionMemo();
110    }
111
112    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(XNetSerialPortController.class);
113
114}