001package jmri.jmrix.xpa.serialdriver;
002
003import java.io.IOException;
004
005import jmri.InstanceManager;
006import jmri.jmrix.xpa.XpaPortController;
007import jmri.jmrix.xpa.XpaSystemConnectionMemo;
008import jmri.jmrix.xpa.XpaTrafficController;
009
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013import purejavacomm.CommPortIdentifier;
014import purejavacomm.NoSuchPortException;
015import purejavacomm.PortInUseException;
016import purejavacomm.SerialPort;
017import purejavacomm.UnsupportedCommOperationException;
018
019/**
020 * Implements SerialPortAdapter for a modem connected to an XPA.
021 * <p>
022 * This connects an XPA+Modem connected to an XpressNet based command station
023 * via a serial com port. Normally controlled by the SerialDriverFrame class.
024 * <p>
025 * The current implementation only handles the 9,600 baud rate. It uses the
026 * first configuraiont variable for the modem initialization string.
027 *
028 * @author Paul Bender Copyright (C) 2004
029 */
030public class SerialDriverAdapter extends XpaPortController {
031
032    public SerialDriverAdapter() {
033
034        super(new XpaSystemConnectionMemo());
035        ((XpaSystemConnectionMemo)getSystemConnectionMemo()).setXpaTrafficController(new XpaTrafficController());
036
037
038        option1Name = "ModemInitString"; // NOI18N
039        options.put(option1Name, new Option(Bundle.getMessage("ModemInitStringLabel"), new String[]{"ATX0E0"}));
040        this.manufacturerName = jmri.jmrix.lenz.LenzConnectionTypeList.LENZ;
041    }
042
043    SerialPort activeSerialPort = null;
044
045    @Override
046    public String openPort(String portName, String appName) {
047        // open the port, check ability to set moderators
048        try {
049            // get and open the primary port
050            CommPortIdentifier portID = CommPortIdentifier.getPortIdentifier(portName);
051            try {
052                activeSerialPort = (SerialPort) portID.open(appName, 2000);  // name of program, msec to wait
053            } catch (PortInUseException p) {
054                return handlePortBusy(p, portName, log);
055            }
056
057            // try to set it for communication via SerialDriver
058            try {
059                activeSerialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
060            } catch (UnsupportedCommOperationException e) {
061                log.error("Cannot set serial parameters on port {}: {}", portName, e.getMessage());
062                return "Cannot set serial parameters on port " + portName + ": " + e.getMessage();
063            }
064
065            // disable flow control; hardware lines used for signaling, XON/XOFF might appear in data
066            configureLeadsAndFlowControl(activeSerialPort, 0);
067
068            // set timeout
069            // activeSerialPort.enableReceiveTimeout(1000);
070            log.debug("Serial timeout was observed as: {} {}", activeSerialPort.getReceiveTimeout(), activeSerialPort.isReceiveTimeoutEnabled());
071
072            // purge contents, if any
073            purgeStream(activeSerialPort.getInputStream());
074
075            // report status?
076            if (log.isInfoEnabled()) {
077                log.info("{} port opened at {} baud, sees  DTR: {} RTS: {} DSR: {} CTS: {}  CD: {}", portName, activeSerialPort.getBaudRate(), activeSerialPort.isDTR(), activeSerialPort.isRTS(), activeSerialPort.isDSR(), activeSerialPort.isCTS(), activeSerialPort.isCD());
078            }
079
080            opened = true;
081
082        } catch (NoSuchPortException p) {
083            return handlePortNotFound(p, portName, log);
084        } catch (IOException ex) {
085            log.error("Unexpected exception while opening port {}", portName, ex);
086            return "IO Exception while opening port " + portName + ": " + ex;
087        }
088
089        return null; // indicates OK return
090
091    }
092
093    /**
094     * set up all of the other objects to operate with an XPA+Modem Connected to
095     * an XpressNet based command station connected to this port
096     */
097    @Override
098    public void configure() {
099
100        // connect to the traffic controller
101        XpaSystemConnectionMemo memo = ((XpaSystemConnectionMemo)getSystemConnectionMemo());
102        XpaTrafficController tc = memo.getXpaTrafficController();
103        tc.connectPort(this);
104
105        InstanceManager.store(memo.getPowerManager(), jmri.PowerManager.class);
106        InstanceManager.store(memo.getTurnoutManager(),jmri.TurnoutManager.class);
107        InstanceManager.store(memo.getThrottleManager(),jmri.ThrottleManager.class);
108        memo.register();
109
110        // start operation
111        tc.startTransmitThread();
112        sinkThread = new Thread(tc);
113        sinkThread.start();
114    }
115
116    private Thread sinkThread;
117
118    @Override
119    public boolean status() {
120        return opened;
121    }
122
123    /**
124     * {@inheritDoc}
125     * Currently only 9,600 bps
126     */
127    @Override
128    public String[] validBaudRates() {
129        return new String[]{"9,600 bps"};
130    }
131
132    /**
133     * {@inheritDoc}
134     */
135    @Override
136    public int[] validBaudNumbers() {
137        return new int[]{9600};
138    }
139
140    @Override
141    public int defaultBaudIndex() {
142        return 0;
143    }
144
145    private final static Logger log = LoggerFactory.getLogger(SerialDriverAdapter.class);
146
147}