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