001package jmri.jmrix.loconet.usb_dcs52;
002
003import jmri.jmrix.loconet.LnCommandStationType;
004import jmri.jmrix.loconet.LnPacketizer;
005import jmri.jmrix.loconet.LocoNetMessage;
006import jmri.jmrix.loconet.LocoNetSystemConnectionMemo;
007import jmri.jmrix.loconet.locobuffer.LocoBufferAdapter;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010import purejavacomm.SerialPort;
011import purejavacomm.UnsupportedCommOperationException;
012
013/**
014 * Update the code in jmri.jmrix.loconet.locobuffer so that it refers to the
015 * option settings for the Digitrax DCS52's USB interface
016 * <p>
017 * Based on PR3Adapter.java
018 *
019 * @author Bob Jacobsen Copyright (C) 2004, 2005, 2006, 2008
020 * @author B. Milhaupt Copyright (C) 2019
021 */
022public class UsbDcs52Adapter extends LocoBufferAdapter {
023
024    public UsbDcs52Adapter() {
025        super(new UsbDcs52SystemConnectionMemo());
026
027        options.remove(option2Name);
028        options.put(option2Name, new Option(Bundle.getMessage("CommandStationTypeLabel"), commandStationOptions(), false));
029
030    }
031
032    /**
033     * Sets up the serial port characteristics.  Always uses flow control, which is
034     * not considered a user-settable option.  Sets the DCS52 USB interface for the appropriate
035     * operating mode, based on the selected "command station type".
036     *
037     * @param activeSerialPort  the port to be configured
038     */
039    @Override
040    protected void setSerialPort(SerialPort activeSerialPort) throws UnsupportedCommOperationException {
041        // find the baud rate value, configure comm options
042        int baud = currentBaudNumber(mBaudRate);
043        activeSerialPort.setSerialPortParams(baud, SerialPort.DATABITS_8,
044                SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
045
046        // configure flow control to always on
047        int flow = SerialPort.FLOWCONTROL_RTSCTS_OUT;
048        if (getOptionState(option1Name).equals(validOption1[1])) {
049            flow = SerialPort.FLOWCONTROL_NONE;
050        }
051        configureLeadsAndFlowControl(activeSerialPort, flow);
052
053        log.info("USB DCS52 adapter{}{} RTSCTS_OUT=" + SerialPort.FLOWCONTROL_RTSCTS_OUT + " RTSCTS_IN=" + SerialPort.FLOWCONTROL_RTSCTS_IN, activeSerialPort.getFlowControlMode() == SerialPort.FLOWCONTROL_RTSCTS_OUT ? " set hardware flow control, mode=" : " set no flow control, mode=", activeSerialPort.getFlowControlMode());
054    }
055
056    /**
057     * Set up all of the other objects to operate with a DCS52 USB interface connected to this
058     * port. This overrides the version in loconet.locobuffer, but it has to
059     * duplicate much of the functionality there, so the code is basically
060     * copied.
061     */
062    @Override
063    public void configure() {
064        setCommandStationType(getOptionState(option2Name));
065        setTurnoutHandling(getOptionState(option3Name));
066        if (commandStationType == LnCommandStationType.COMMAND_STATION_USB_DCS52_ALONE) {
067            // DCS52 USB in standalone programmer case:
068            // connect to a packetizing traffic controller
069            // that does echoing
070            //
071            // Note - already created a LocoNetSystemConnectionMemo, so re-use 
072            // it when creating a PR2 Packetizer.  (If create a new one, will
073            // end up with two "LocoNet" menus...)
074            jmri.jmrix.loconet.pr2.LnPr2Packetizer packets = 
075                    new jmri.jmrix.loconet.pr2.LnPr2Packetizer(this.getSystemConnectionMemo());
076            packets.connectPort(this);
077
078            // set traffic controller and configure command station and mangers
079            this.getSystemConnectionMemo().setLnTrafficController(packets);
080            // do the common manager config
081            this.getSystemConnectionMemo().configureCommandStation(commandStationType,
082                    mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable);  // never transponding!
083            this.getSystemConnectionMemo().configureManagersPR2();
084
085            // start operation
086            packets.startThreads();
087
088            // set mode
089            LocoNetMessage msg = new LocoNetMessage(6);
090            msg.setOpCode(0xD3);
091            msg.setElement(1, 0x10);
092            msg.setElement(2, 1);  // set PR2
093            msg.setElement(3, 0);
094            msg.setElement(4, 0);
095            packets.sendLocoNetMessage(msg);
096
097        } else {
098            // MS100 modes - connecting to a separate command station
099            // get transponding option
100            setTranspondingAvailable(getOptionState("TranspondingPresent"));
101            // connect to a packetizing traffic controller
102            LnPacketizer packets = getPacketizer(getOptionState(option4Name));
103            packets.connectPort(this);
104
105            // set traffic controller and configure command station and mangers
106            this.getSystemConnectionMemo().setLnTrafficController(packets);
107            // do the common manager config
108            this.getSystemConnectionMemo().configureCommandStation(commandStationType,
109                    mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable);
110
111            this.getSystemConnectionMemo().configureManagersMS100();
112
113            // start operation
114            packets.startThreads();
115
116            // set mode
117            LocoNetMessage msg = new LocoNetMessage(6);
118            msg.setOpCode(0xD3);
119            msg.setElement(1, 0x10);
120            msg.setElement(2, 0);  // set MS100, no power
121            msg.setElement(3, 0);
122            msg.setElement(4, 0);
123            packets.sendLocoNetMessage(msg);
124        }
125    }
126
127    /**
128     * {@inheritDoc}
129     *
130     * @return String[] containing the single valid baud rate, "57,600".
131     */
132    @Override
133    public String[] validBaudRates() {
134        return new String[]{"57,600 baud"}; // TODO I18N
135    }
136
137    /**
138     * {@inheritDoc}
139     *
140     * @return int[] containing the single valid baud rate, 57600.
141     */
142    @Override
143    public int[] validBaudNumbers() {
144        return new int[]{57600};
145    }
146
147    @Override
148    public int defaultBaudIndex() {
149        return 0;
150    }
151
152    // Option 1 does flow control, inherited from LocoBufferAdapter
153
154    /**
155     * The DCS52 USB interface can be used as a "Standalone Programmer", or with various LocoNet
156     * command stations, or as an interface to a "Standalone LocoNet".  Provide those
157     * options.
158     *
159     * @return an array of strings containing the various command station names and
160     *      name(s) of modes without command stations
161     */
162    public String[] commandStationOptions() {
163        String[] retval = new String[commandStationNames.length + 1];
164        retval[0] = LnCommandStationType.COMMAND_STATION_USB_DCS52_ALONE.getName();
165        retval[1] = LnCommandStationType.COMMAND_STATION_DCS052.getName();
166        int count = 2;
167        for (String commandStationName : commandStationNames) {
168            if (!commandStationName.equals(LnCommandStationType.COMMAND_STATION_DCS052.getName())) {
169                // include all but COMMAND_STATION_DCS052, which was forced  to 
170                // the front of the list (above)
171                retval[count++] = commandStationName;
172            }
173        }
174        // Note: Standalone loconet does not make sense for DCS240 USB interface.
175        return retval;
176    }
177
178    @Override
179    public UsbDcs52SystemConnectionMemo getSystemConnectionMemo() {
180        LocoNetSystemConnectionMemo m = super.getSystemConnectionMemo();
181        if (m instanceof UsbDcs52SystemConnectionMemo) {
182            return (UsbDcs52SystemConnectionMemo) m;
183        }
184        log.error("Cannot cast the system connection memo to a UsbDcs52SystemConnection Memo.");
185        return null;
186    }
187
188    private final static Logger log = LoggerFactory.getLogger(UsbDcs52Adapter.class);
189
190}