001package jmri.jmrix.loconet.pr4;
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 * Override {@link jmri.jmrix.loconet.locobuffer.LocoBufferAdapter} so that it refers to the
013 * (switch) settings on the Digitrax PR4.
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 PR4Adapter extends LocoBufferAdapter {
021
022    public PR4Adapter() {
023        super(new PR4SystemConnectionMemo());
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 PR4 via {} {}", portName, currentSerialPort);
033    }
034
035    /**
036     * Set up all of the other objects to operate with a PR4 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     * Note that the PR4 does not support "LocoNet Data Signal termination" when
042     * in LocoNet interface mode (i.e. MS100 mode).
043     */
044    @Override
045    public void configure() {
046        setCommandStationType(getOptionState(option2Name));
047        setTurnoutHandling(getOptionState(option3Name));
048        if (commandStationType == LnCommandStationType.COMMAND_STATION_PR4_ALONE) {
049            // PR4 standalone case
050            // connect to a packetizing traffic controller
051            // that does echoing
052            //
053            // Note - already created a LocoNetSystemConnectionMemo, so re-use
054            // it when creating a PR2 Packetizer.  (If create a new one, will
055            // end up with two "LocoNet" menus...)
056            jmri.jmrix.loconet.pr2.LnPr2Packetizer packets =
057                    new jmri.jmrix.loconet.pr2.LnPr2Packetizer(this.getSystemConnectionMemo());
058            packets.connectPort(this);
059
060            // set traffic controller and configure command station and mangers
061            this.getSystemConnectionMemo().setLnTrafficController(packets);
062            // do the common manager config
063            this.getSystemConnectionMemo().configureCommandStation(commandStationType,
064                    mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable, mInterrogateAtStart, mLoconetProtocolAutoDetect);  // never transponding!
065            this.getSystemConnectionMemo().configureManagersPR2();
066
067            // start operation
068            packets.startThreads();
069
070            // set mode
071            LocoNetMessage msg = new LocoNetMessage(6);
072            msg.setOpCode(0xD3);
073            msg.setElement(1, 0x10);
074            msg.setElement(2, 1);  // set PR2
075            msg.setElement(3, 0);
076            msg.setElement(4, 0);
077            packets.sendLocoNetMessage(msg);
078
079        } else {
080            // MS100 modes - connecting to a separate command station
081            // get transponding option
082            setTranspondingAvailable(getOptionState("TranspondingPresent"));
083            setInterrogateOnStart(getOptionState("InterrogateOnStart"));
084            setLoconetProtocolAutoDetect(getOptionState("LoconetProtocolAutoDetect"));
085            // connect to a packetizing traffic controller
086            LnPacketizer packets = getPacketizer(getOptionState(option4Name));
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
097            // start operation
098            packets.startThreads();
099
100            // set mode
101            LocoNetMessage msg = new LocoNetMessage(6);
102            msg.setOpCode(0xD3);
103            msg.setElement(1, 0x10);
104            msg.setElement(2, 0);  // set MS100, no power
105            msg.setElement(3, 0);
106            msg.setElement(4, 0);
107            packets.sendLocoNetMessage(msg);
108        }
109    }
110
111    /**
112     * {@inheritDoc}
113     *
114     * @return String[] containing the single valid baud rate, "57,600".
115     */
116    @Override
117    public String[] validBaudRates() {
118        return new String[]{"57,600 baud"}; // NOI18N
119    }
120
121    /**
122     * {@inheritDoc}
123     *
124     * @return int[] containing the single valid baud rate, 57600.
125     */
126    @Override
127    public int[] validBaudNumbers() {
128        return new int[]{57600};
129    }
130
131    @Override
132    public int defaultBaudIndex() {
133        return 0;
134    }
135
136    // Option 1 does flow control, inherited from LocoBufferAdapter
137
138    /**
139     * The PR4 can be used as a "Standalone Programmer", or with various LocoNet
140     * command stations.  The PR4 does not support "LocoNet Data signal termination",
141     * so that is not added as a valid option (as it would be for the PR3).
142     *
143     * @return an array of strings containing the various command station names and
144     *      name(s) of modes without command stations
145     */
146    public String[] commandStationOptions() {
147        String[] retval = new String[commandStationNames.length + 2];
148        retval[0] = LnCommandStationType.COMMAND_STATION_PR4_ALONE.getName();
149        for (int i = 0; i < commandStationNames.length; i++) {
150            retval[i + 1] = commandStationNames[i];
151        }
152        // Add "Standalone LocoNet" option
153        // Note: PR4 does not provide "LocoNet Data Termination" and _requires_
154        // some external source of that feature.
155        retval[retval.length - 1] = LnCommandStationType.COMMAND_STATION_STANDALONE.getName() + " (using external LocoNet Data Termination!)"; // NOI18N
156        return retval;
157    }
158
159    @Override
160    public PR4SystemConnectionMemo getSystemConnectionMemo() {
161        LocoNetSystemConnectionMemo m = super.getSystemConnectionMemo();
162        if (m instanceof PR4SystemConnectionMemo) {
163            return (PR4SystemConnectionMemo) m;
164        }
165        log.error("Cannot cast the system connection memo to a PR4SystemConnection Memo.");
166        return null;
167    }
168
169    private final static Logger log = LoggerFactory.getLogger(PR4Adapter.class);
170}