001package jmri.jmrix.loconet.usb_dcs210Plus;
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;
010
011/**
012 * Update the code in jmri.jmrix.loconet.locobuffer so that it refers to the
013 * option settings for the Digitrax DCS210Plus's USB interface
014 * <p>
015 * Based on PR3Adapter.java
016 *
017 * @author Bob Jacobsen Copyright (C) 2004, 2005, 2006, 2008
018 * @author B. Milhaupt Copyright (C) 2019
019 */
020public class UsbDcs210PlusAdapter extends LocoBufferAdapter {
021
022    public UsbDcs210PlusAdapter() {
023        super(new UsbDcs210PlusSystemConnectionMemo());
024
025        options.remove(option2Name);
026        options.put(option2Name, new Option(Bundle.getMessage("CommandStationTypeLabel"), commandStationOptions(), false));
027
028    }
029
030    @Override
031    protected void reportOpen(String portName) {
032        log.info("Connecting USB DCS210Plus via {} {}", portName, currentSerialPort);
033    }
034
035    /**
036     * Set up all of the other objects to operate with a DCS210Plus USB interface connected to this
037     * port. This overrides the version in loconet.locobuffer, but it has to
038     * duplicate much of the functionality there, so the code is basically
039     * copied.
040     */
041    @Override
042    public void configure() {
043        setCommandStationType(getOptionState(option2Name));
044        setTurnoutHandling(getOptionState(option3Name));
045        if (commandStationType == LnCommandStationType.COMMAND_STATION_USB_DCS210Plus_ALONE) {
046            // DCS210Plus USB in standalone programmer case:
047            // connect to a packetizing traffic controller
048            // that does echoing
049            //
050            // Note - already created a LocoNetSystemConnectionMemo, so re-use
051            // it when creating a PR2 Packetizer.  (If create a new one, will
052            // end up with two "LocoNet" menus...)
053            jmri.jmrix.loconet.pr2.LnPr2Packetizer packets =
054                    new jmri.jmrix.loconet.pr2.LnPr2Packetizer(this.getSystemConnectionMemo());
055            packets.setLoconetUpdateSlotOnMessageCreation(Bundle.getMessage("ButtonYes").equals(getOptionState("LoconetUpdateSlotOnMessageCreation")));
056            packets.connectPort(this);
057
058            // set traffic controller and configure command station and mangers
059            this.getSystemConnectionMemo().setLnTrafficController(packets);
060            // do the common manager config
061            this.getSystemConnectionMemo().configureCommandStation(commandStationType,
062                    mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable, mInterrogateAtStart, mLoconetProtocolAutoDetect);  // never transponding!
063            this.getSystemConnectionMemo().configureManagersPR2();
064            this.getSystemConnectionMemo().getSlotManager().serviceModeReplyDelay = 500;
065
066            // start operation
067            packets.startThreads();
068
069            // set mode
070            LocoNetMessage msg = new LocoNetMessage(6);
071            msg.setOpCode(0xD3);
072            msg.setElement(1, 0x10);
073            msg.setElement(2, 1);  // set PR2
074            msg.setElement(3, 0);
075            msg.setElement(4, 0);
076            packets.sendLocoNetMessage(msg);
077
078        } else {
079            // MS100 modes - connecting to a separate command station
080            // get transponding option
081            setTranspondingAvailable(getOptionState("TranspondingPresent"));
082            setInterrogateOnStart(getOptionState("InterrogateOnStart"));
083            setLoconetProtocolAutoDetect(getOptionState("LoconetProtocolAutoDetect"));
084            // connect to a packetizing traffic controller
085            LnPacketizer packets = getPacketizer(getOptionState(option4Name));
086            packets.setLoconetUpdateSlotOnMessageCreation(Bundle.getMessage("ButtonYes").equals(getOptionState("LoconetUpdateSlotOnMessageCreation")));
087            packets.connectPort(this);
088
089            // set traffic controller and configure command station and mangers
090            this.getSystemConnectionMemo().setLnTrafficController(packets);
091            // do the common manager config
092            this.getSystemConnectionMemo().configureCommandStation(commandStationType,
093                    mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable, mInterrogateAtStart, mLoconetProtocolAutoDetect);
094
095            this.getSystemConnectionMemo().configureManagersMS100();
096            this.getSystemConnectionMemo().getSlotManager().serviceModeReplyDelay = 500;
097
098            // start operation
099            packets.startThreads();
100
101            // set mode
102            LocoNetMessage msg = new LocoNetMessage(6);
103            msg.setOpCode(0xD3);
104            msg.setElement(1, 0x10);
105            msg.setElement(2, 0);  // set MS100, no power
106            msg.setElement(3, 0);
107            msg.setElement(4, 0);
108            packets.sendLocoNetMessage(msg);
109        }
110    }
111
112    /**
113     * {@inheritDoc}
114     *
115     * @return String[] containing the single valid baud rate, "57,600".
116     */
117    @Override
118    public String[] validBaudRates() {
119        return new String[]{"57,600 baud"}; // NOI18N
120    }
121
122    /**
123     * {@inheritDoc}
124     *
125     * @return int[] containing the single valid baud rate, 57600.
126     */
127    @Override
128    public int[] validBaudNumbers() {
129        return new int[]{57600};
130    }
131
132    @Override
133    public int defaultBaudIndex() {
134        return 0;
135    }
136
137    // Option 1 does flow control, inherited from LocoBufferAdapter
138
139    /**
140     * The DCS210Plus USB interface can be used as a "Standalone Programmer", or with various LocoNet
141     * command stations, or as an interface to a "Standalone LocoNet".  Provide those
142     * options.
143     *
144     * @return an array of strings containing the various command station names and
145     *      name(s) of modes without command stations
146     */
147    public String[] commandStationOptions() {
148        String[] retval = new String[commandStationNames.length + 1];
149        retval[0] = LnCommandStationType.COMMAND_STATION_DCS210PLUS.getName();
150        retval[1] = LnCommandStationType.COMMAND_STATION_USB_DCS210Plus_ALONE.getName();
151        int count = 2;
152        for (String commandStationName : commandStationNames) {
153            if (!commandStationName.equals(LnCommandStationType.COMMAND_STATION_DCS210PLUS.getName())) {
154            // include all but COMMAND_STATION_DCS210Plus, which was forced  to
155            // the front of the list (above)
156                retval[count++] = commandStationName;
157        }
158    }
159        // Note: Standalone loconet does not make sense for DCS210Plus USB interface.
160        return retval;
161    }
162
163    @Override
164    public UsbDcs210PlusSystemConnectionMemo getSystemConnectionMemo() {
165        LocoNetSystemConnectionMemo m = super.getSystemConnectionMemo();
166        if (m instanceof UsbDcs210PlusSystemConnectionMemo) {
167            return (UsbDcs210PlusSystemConnectionMemo) m;
168        }
169        log.error("Cannot cast the system connection memo to a UsbDcs210PlusSystemConnection Memo.");
170        return null;
171    }
172
173    private static final Logger log = LoggerFactory.getLogger(UsbDcs210PlusAdapter.class);
174}