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.setLoconetUpdateSlotOnMessageCreation(Bundle.getMessage("ButtonYes").equals(getOptionState("LoconetUpdateSlotOnMessageCreation")));
059            packets.connectPort(this);
060
061            // set traffic controller and configure command station and mangers
062            this.getSystemConnectionMemo().setLnTrafficController(packets);
063            // do the common manager config
064            this.getSystemConnectionMemo().configureCommandStation(commandStationType,
065                    mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable, mInterrogateAtStart, mLoconetProtocolAutoDetect);  // never transponding!
066            this.getSystemConnectionMemo().configureManagersPR2();
067
068            // start operation
069            packets.startThreads();
070
071            // set mode
072            LocoNetMessage msg = new LocoNetMessage(6);
073            msg.setOpCode(0xD3);
074            msg.setElement(1, 0x10);
075            msg.setElement(2, 1);  // set PR2
076            msg.setElement(3, 0);
077            msg.setElement(4, 0);
078            packets.sendLocoNetMessage(msg);
079
080        } else {
081            // MS100 modes - connecting to a separate command station
082            // get transponding option
083            setTranspondingAvailable(getOptionState("TranspondingPresent"));
084            setInterrogateOnStart(getOptionState("InterrogateOnStart"));
085            setLoconetProtocolAutoDetect(getOptionState("LoconetProtocolAutoDetect"));
086            // connect to a packetizing traffic controller
087            LnPacketizer packets = getPacketizer(getOptionState(option4Name));
088            packets.setLoconetUpdateSlotOnMessageCreation(Bundle.getMessage("ButtonYes").equals(getOptionState("LoconetUpdateSlotOnMessageCreation")));
089            packets.connectPort(this);
090
091            // set traffic controller and configure command station and mangers
092            this.getSystemConnectionMemo().setLnTrafficController(packets);
093            // do the common manager config
094            this.getSystemConnectionMemo().configureCommandStation(commandStationType,
095                    mTurnoutNoRetry, mTurnoutExtraSpace, mTranspondingAvailable, mInterrogateAtStart, mLoconetProtocolAutoDetect);
096
097            this.getSystemConnectionMemo().configureManagersMS100();
098
099            // start operation
100            packets.startThreads();
101
102            // set mode
103            LocoNetMessage msg = new LocoNetMessage(6);
104            msg.setOpCode(0xD3);
105            msg.setElement(1, 0x10);
106            msg.setElement(2, 0);  // set MS100, no power
107            msg.setElement(3, 0);
108            msg.setElement(4, 0);
109            packets.sendLocoNetMessage(msg);
110        }
111    }
112
113    /**
114     * {@inheritDoc}
115     *
116     * @return String[] containing the single valid baud rate, "57,600".
117     */
118    @Override
119    public String[] validBaudRates() {
120        return new String[]{"57,600 baud"}; // NOI18N
121    }
122
123    /**
124     * {@inheritDoc}
125     *
126     * @return int[] containing the single valid baud rate, 57600.
127     */
128    @Override
129    public int[] validBaudNumbers() {
130        return new int[]{57600};
131    }
132
133    @Override
134    public int defaultBaudIndex() {
135        return 0;
136    }
137
138    // Option 1 does flow control, inherited from LocoBufferAdapter
139
140    /**
141     * The PR4 can be used as a "Standalone Programmer", or with various LocoNet
142     * command stations.  The PR4 does not support "LocoNet Data signal termination",
143     * so that is not added as a valid option (as it would be for the PR3).
144     *
145     * @return an array of strings containing the various command station names and
146     *      name(s) of modes without command stations
147     */
148    public String[] commandStationOptions() {
149        String[] retval = new String[commandStationNames.length + 2];
150        retval[0] = LnCommandStationType.COMMAND_STATION_PR4_ALONE.getName();
151        for (int i = 0; i < commandStationNames.length; i++) {
152            retval[i + 1] = commandStationNames[i];
153        }
154        // Add "Standalone LocoNet" option
155        // Note: PR4 does not provide "LocoNet Data Termination" and _requires_
156        // some external source of that feature.
157        retval[retval.length - 1] = LnCommandStationType.COMMAND_STATION_STANDALONE_EXT_TERM.getName(); // NOI18N
158        return retval;
159    }
160
161    @Override
162    public PR4SystemConnectionMemo getSystemConnectionMemo() {
163        LocoNetSystemConnectionMemo m = super.getSystemConnectionMemo();
164        if (m instanceof PR4SystemConnectionMemo) {
165            return (PR4SystemConnectionMemo) m;
166        }
167        log.error("Cannot cast the system connection memo to a PR4SystemConnection Memo.");
168        return null;
169    }
170
171    private static final Logger log = LoggerFactory.getLogger(PR4Adapter.class);
172}