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