001package jmri.jmrix.loconet;
002
003import jmri.ThrottleManager;
004import jmri.jmrix.loconet.SlotMapEntry.SlotType;
005
006import java.util.ArrayList;
007import java.util.Arrays;
008import java.util.List;
009
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013/**
014 * Enum to carry command-station specific information for LocoNet
015 * implementations.
016 * <p>
017 * Because you can't inherit and extend enums, this will accumulate information
018 * from subtypes. We use reflection to deal with that.
019 * <p>
020 * This is (slowly) centralizing all of the command-station-specific
021 * dependencies for startup. It does _not_ handle the connection-specific
022 * dependencies for e.g. the connections via networks and Uhlenbrock serial/USB;
023 * those are still done via port adapters, special packetizers et al.
024 * <hr>
025 * This file is part of JMRI.
026 * <p>
027 * JMRI is free software; you can redistribute it and/or modify it under the
028 * terms of version 2 of the GNU General Public License as published by the Free
029 * Software Foundation. See the "COPYING" file for a copy of this license.
030 * <p>
031 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY
032 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
033 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
034 *
035 * @author Bob Jacobsen Copyright (C) 2014
036 * @author B. Milhaupt Copyright (C) 2018
037 */
038@javax.annotation.concurrent.Immutable
039public enum LnCommandStationType {
040
041    //  enum value(name, canRead, progEndOp, ThrottleManager, SlotManager, supportsIdle, supportsMultimeter, Clock time type
042    COMMAND_STATION_DCS100("DCS100 (Chief)",  // NOI18N
043            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
044            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
045            "LnThrottleManager", "SlotManager",  // NOI18N
046            IdleSupport.SUPPORTS_OPC_IDLE,
047            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
048            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
049            CommandStationClockFracType.CLOCK13BIT,
050            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
051                    new SlotMapEntry(1,120,SlotType.LOCO),
052                    new SlotMapEntry(121,127,SlotType.SYSTEM),
053                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
054                    new SlotMapEntry(248,256,SlotType.SYSTEM),   // potential stat slots
055                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
056                    new SlotMapEntry(376,384,SlotType.SYSTEM),
057                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
058            ),
059    COMMAND_STATION_DCS240("DCS240 (Advanced Command Station)",  // NOI18N
060            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
061            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
062            "LnThrottleManager", "SlotManager",  // NOI18N
063            IdleSupport.SUPPORTS_OPC_IDLE,
064            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
065            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
066            CommandStationClockFracType.CLOCK15BIT,
067            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
068                    new SlotMapEntry(1,120,SlotType.LOCO),
069                    new SlotMapEntry(121,128,SlotType.SYSTEM),
070                    new SlotMapEntry(129,247,SlotType.LOCO),
071                    new SlotMapEntry(248,256,SlotType.SYSTEM),
072                    new SlotMapEntry(257,375,SlotType.LOCO),
073                    new SlotMapEntry(376,384,SlotType.SYSTEM),
074                    new SlotMapEntry(385,432,SlotType.LOCO))
075            ),
076    COMMAND_STATION_DCS240PLUS("DCS240+ (Advanced Command Station)",  // NOI18N
077            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
078            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
079            "LnThrottleManager", "SlotManager",  // NOI18N
080            IdleSupport.SUPPORTS_OPC_IDLE,
081            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
082            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
083            CommandStationClockFracType.CLOCK15BIT,
084            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
085                    new SlotMapEntry(1,120,SlotType.LOCO),
086                    new SlotMapEntry(121,128,SlotType.SYSTEM),
087                    new SlotMapEntry(129,247,SlotType.LOCO),
088                    new SlotMapEntry(248,256,SlotType.SYSTEM),
089                    new SlotMapEntry(257,375,SlotType.LOCO),
090                    new SlotMapEntry(376,384,SlotType.SYSTEM),
091                    new SlotMapEntry(385,432,SlotType.LOCO))
092            ),
093
094    COMMAND_STATION_DCS210PLUS("DCS210+ (Advanced Command Station)",  // NOI18N
095            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
096            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
097            "LnThrottleManager", "SlotManager",  // NOI18N
098            IdleSupport.SUPPORTS_OPC_IDLE,
099            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
100            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
101            CommandStationClockFracType.CLOCK15BIT,
102            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
103                    new SlotMapEntry(1,100,SlotType.LOCO),
104                    new SlotMapEntry(101,120,SlotType.UNKNOWN),
105                    new SlotMapEntry(121,127,SlotType.SYSTEM),
106                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
107                    new SlotMapEntry(248,256,SlotType.SYSTEM),
108                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
109                    new SlotMapEntry(376,384,SlotType.SYSTEM),
110                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
111            ),
112    COMMAND_STATION_DCS210("DCS210 (Evolution Command Station)",  // NOI18N
113            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
114            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
115            "LnThrottleManager", "SlotManager",  // NOI18N
116            IdleSupport.SUPPORTS_OPC_IDLE,
117            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
118            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
119            CommandStationClockFracType.CLOCK15BIT,
120            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
121                    new SlotMapEntry(1,100,SlotType.LOCO),
122                    new SlotMapEntry(101,120,SlotType.UNKNOWN),
123                    new SlotMapEntry(121,127,SlotType.SYSTEM),
124                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
125                    new SlotMapEntry(248,256,SlotType.SYSTEM),
126                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
127                    new SlotMapEntry(376,384,SlotType.SYSTEM),
128                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
129            ),
130    COMMAND_STATION_DCS200("DCS200",  // NOI18N
131            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
132            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
133            "LnThrottleManager", "SlotManager",  // NOI18N
134            IdleSupport.SUPPORTS_OPC_IDLE,
135            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
136            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
137            CommandStationClockFracType.CLOCK13BIT,
138            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
139                    new SlotMapEntry(1,120,SlotType.LOCO),
140                    new SlotMapEntry(121,127,SlotType.SYSTEM),
141                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
142                    new SlotMapEntry(248,256,SlotType.SYSTEM),
143                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
144                    new SlotMapEntry(376,384,SlotType.SYSTEM),
145                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
146            ),
147    COMMAND_STATION_DCS050("DCS50 (Zephyr)",  // NOI18N
148            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
149            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
150            "LnThrottleManager", "SlotManager",  // NOI18N
151            IdleSupport.NO_OPC_IDLE_SUPPORT,
152            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
153            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
154            CommandStationClockFracType.CLOCK13BIT,
155            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
156                    new SlotMapEntry(1,12,SlotType.LOCO),
157                    new SlotMapEntry(13,120,SlotType.UNKNOWN),
158                    new SlotMapEntry(121,127,SlotType.SYSTEM),
159                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
160                    new SlotMapEntry(248,256,SlotType.SYSTEM),
161                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
162                    new SlotMapEntry(376,384,SlotType.SYSTEM),
163                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
164            ),
165    COMMAND_STATION_DCS051("DCS51 (Zephyr Xtra)",  // NOI18N
166            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
167            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
168            "LnThrottleManager", "SlotManager",  // NOI18N
169            IdleSupport.NO_OPC_IDLE_SUPPORT,
170            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
171            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
172            CommandStationClockFracType.CLOCK13BIT,
173            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
174                    new SlotMapEntry(1,19,SlotType.LOCO),
175                    new SlotMapEntry(20,120,SlotType.UNKNOWN),
176                    new SlotMapEntry(121,127,SlotType.SYSTEM),
177                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
178                    new SlotMapEntry(248,256,SlotType.SYSTEM),
179                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
180                    new SlotMapEntry(376,384,SlotType.SYSTEM),
181                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
182            ),
183    COMMAND_STATION_DCS052("DCS52 (Zephyr Express)", // NOI18N
184            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
185            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
186            "LnThrottleManager", "SlotManager",  // NOI18N
187            IdleSupport.NO_OPC_IDLE_SUPPORT,
188            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
189            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
190            CommandStationClockFracType.CLOCK15BIT,
191            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
192                    new SlotMapEntry(1,20,SlotType.LOCO),
193                    new SlotMapEntry(21,120,SlotType.UNKNOWN),
194                    new SlotMapEntry(121,127,SlotType.SYSTEM),
195                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
196                    new SlotMapEntry(248,256,SlotType.SYSTEM),
197                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
198                    new SlotMapEntry(376,384,SlotType.SYSTEM),
199                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
200            ),
201    COMMAND_STATION_DB150("DB150 (Empire Builder)", // NOI18N
202            ReadsFromServiceModeTrack.NO_SVC_MODE_READS,
203            ProgDepowersTrack.TRACK_TURNEDOFF_BY_PROGRAMMING,
204            "LnThrottleManager", "SlotManager",  // NOI18N
205            IdleSupport.SUPPORTS_OPC_IDLE,
206            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
207            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
208            CommandStationClockFracType.CLOCK13BIT,
209            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
210                    new SlotMapEntry(1,120,SlotType.LOCO),
211                    new SlotMapEntry(121,127,SlotType.SYSTEM),
212                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
213                    new SlotMapEntry(248,256,SlotType.SYSTEM),
214                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
215                    new SlotMapEntry(376,384,SlotType.SYSTEM),
216                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
217            ),
218    // the following command stations are assumed to not support "OPC_IDLE"
219    COMMAND_STATION_LBPS("LocoBuffer (PS)",  // NOI18N
220            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
221            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
222            "LnThrottleManager", "SlotManager",  // NOI18N
223            IdleSupport.NO_OPC_IDLE_SUPPORT,
224            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
225            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
226            CommandStationClockFracType.CLOCK13BIT,
227            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
228                    new SlotMapEntry(1,120,SlotType.LOCO),
229                    new SlotMapEntry(121,127,SlotType.SYSTEM),
230                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
231                    new SlotMapEntry(248,256,SlotType.SYSTEM),
232                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
233                    new SlotMapEntry(376,384,SlotType.SYSTEM),
234                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
235            ),
236    COMMAND_STATION_MM("Mix-Master",  // NOI18N
237            ReadsFromServiceModeTrack.NO_SVC_MODE_READS,
238            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
239            "LnThrottleManager", "SlotManager",  // NOI18N
240            IdleSupport.NO_OPC_IDLE_SUPPORT,
241            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
242            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
243            CommandStationClockFracType.CLOCK13BIT,
244            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
245                    new SlotMapEntry(1,120,SlotType.LOCO),
246                    new SlotMapEntry(121,127,SlotType.SYSTEM),
247                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
248                    new SlotMapEntry(248,256,SlotType.SYSTEM),
249                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
250                    new SlotMapEntry(376,384,SlotType.SYSTEM),
251                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
252            ),
253    COMMAND_STATION_IBX_TYPE_1("Intellibox-I",  // NOI18N
254            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
255            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
256            "Ib1ThrottleManager", "SlotManager",  // NOI18N
257            IdleSupport.NO_OPC_IDLE_SUPPORT,
258            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
259            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
260            CommandStationClockFracType.CLOCK13BIT,
261            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
262                    new SlotMapEntry(1,120,SlotType.LOCO),
263                    new SlotMapEntry(121,127,SlotType.SYSTEM),
264                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
265                    new SlotMapEntry(248,256,SlotType.SYSTEM),
266                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
267                    new SlotMapEntry(376,384,SlotType.SYSTEM),
268                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
269            ),
270    COMMAND_STATION_IBX_TYPE_2("Intellibox-II",  // NOI18N
271            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
272            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
273            "Ib2ThrottleManager", "UhlenbrockSlotManager",  // NOI18N
274            IdleSupport.NO_OPC_IDLE_SUPPORT,
275            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
276            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
277            CommandStationClockFracType.CLOCK13BIT,
278            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
279                    new SlotMapEntry(1,120,SlotType.LOCO),
280                    new SlotMapEntry(121,127,SlotType.SYSTEM),
281                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
282                    new SlotMapEntry(248,256,SlotType.SYSTEM),
283                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
284                    new SlotMapEntry(376,384,SlotType.SYSTEM),
285                    new SlotMapEntry(385,432,SlotType.UNKNOWN))
286            ),
287    // the following command stations are known to not support "OPC_IDLE"
288    COMMAND_STATION_PR3_ALONE("PR3 standalone programmer",  // NOI18N
289            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
290            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
291            "LnThrottleManager", "SlotManager",  // NOI18N
292            IdleSupport.NO_OPC_IDLE_SUPPORT,
293            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
294            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
295            CommandStationClockFracType.CLOCK13BIT,
296            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
297                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
298                    new SlotMapEntry(121,127,SlotType.SYSTEM),
299                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
300            ),
301    COMMAND_STATION_PR2_ALONE("PR2 standalone programmer",  // NOI18N
302            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
303            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
304            "LnThrottleManager", "SlotManager",  // NOI18N
305            IdleSupport.NO_OPC_IDLE_SUPPORT,
306            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
307            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
308            CommandStationClockFracType.CLOCK13BIT,
309            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
310                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
311                    new SlotMapEntry(121,127,SlotType.SYSTEM),
312                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
313            ),
314    COMMAND_STATION_STANDALONE("Stand-alone LocoNet",  // NOI18N
315            ReadsFromServiceModeTrack.NO_SVC_MODE_READS,
316            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
317            "LnThrottleManager", "SlotManager",  // NOI18N
318            IdleSupport.NO_OPC_IDLE_SUPPORT,
319            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
320            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
321            CommandStationClockFracType.CLOCK13BIT,
322            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
323                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
324                    new SlotMapEntry(121,127,SlotType.SYSTEM),
325                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
326            ),
327    COMMAND_STATION_PR4_ALONE("PR4 standalone programmer",  // NOI18N
328            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
329            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
330            "LnThrottleManager", "SlotManager",  // NOI18N
331            IdleSupport.NO_OPC_IDLE_SUPPORT,
332            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
333            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
334            CommandStationClockFracType.CLOCK13BIT,
335            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
336                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
337                    new SlotMapEntry(121,127,SlotType.SYSTEM),
338                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
339            ),
340    COMMAND_STATION_USB_DCS240_ALONE("DCS240 USB interface as standalone programmer", // NOI18N
341            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
342            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
343            "LnThrottleManager", "SlotManager",  // NOI18N
344            IdleSupport.NO_OPC_IDLE_SUPPORT,
345            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
346            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
347            CommandStationClockFracType.CLOCK15BIT,
348            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
349                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
350                    new SlotMapEntry(121,127,SlotType.SYSTEM),
351                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
352            ),
353    COMMAND_STATION_USB_DCS240PLUS_ALONE("DCS240+ USB interface as standalone programmer", // NOI18N
354            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
355            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
356            "LnThrottleManager", "SlotManager",  // NOI18N
357            IdleSupport.NO_OPC_IDLE_SUPPORT,
358            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
359            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
360            CommandStationClockFracType.CLOCK15BIT,
361            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
362                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
363                    new SlotMapEntry(121,127,SlotType.SYSTEM),
364                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
365            ),
366    COMMAND_STATION_USB_DCS210Plus_ALONE("DCS210+ USB interface as standalone programmer", // NOI18N
367            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
368            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
369            "LnThrottleManager", "SlotManager",  // NOI18N
370            IdleSupport.NO_OPC_IDLE_SUPPORT,
371            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
372            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
373            CommandStationClockFracType.CLOCK15BIT,
374            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
375                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
376                    new SlotMapEntry(121,127,SlotType.SYSTEM),
377                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
378            ),
379    COMMAND_STATION_USB_DCS52_ALONE("DCS52 USB interface as standalone programmer",  // NOI18N
380            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
381            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
382            "LnThrottleManager", "SlotManager",
383            IdleSupport.NO_OPC_IDLE_SUPPORT, // NOI18N
384            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
385            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
386            CommandStationClockFracType.CLOCK15BIT,
387            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
388                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
389                    new SlotMapEntry(121,127,SlotType.SYSTEM),
390                    new SlotMapEntry(128,432,SlotType.UNKNOWN))
391            );
392    // Note that the convention is that the first word (space-separated token) of the name is the
393    // name of a configuration file for loconet.cmdstnconfig
394    LnCommandStationType(String name, ReadsFromServiceModeTrack canRead,
395            ProgDepowersTrack progEndOp,
396            String throttleClassName, String slotManagerClassName,
397            IdleSupport supportsIdle, MultiMeterSupport supportMultiMeter,
398            LocoResetSupport supportsLocoReset, CommandStationClockFracType csClockFracType,
399            List<SlotMapEntry> slotMap) {
400        this.name = name;
401        this.canRead = canRead;
402        this.progEndOp = progEndOp;
403        this.throttleClassName = throttleClassName;
404        this.slotManagerClassName = slotManagerClassName;
405        this.supportsIdle = supportsIdle;
406        this.supportsMultiMeter = supportMultiMeter;
407        this.supportsLocoReset = supportsLocoReset;
408        this.csClockFracType = csClockFracType;
409        this.slotMap = slotMap;
410    }
411
412    final String name;
413    final ReadsFromServiceModeTrack canRead;
414    final ProgDepowersTrack progEndOp;
415    final String throttleClassName;
416    final String slotManagerClassName;
417    final IdleSupport supportsIdle;
418    final MultiMeterSupport supportsMultiMeter;
419    final LocoResetSupport supportsLocoReset;
420    final CommandStationClockFracType csClockFracType;
421    final List<SlotMapEntry> slotMap;
422
423    public String getName() {
424        return name;
425    }
426
427    /**
428     * Can this command station read back from decoders?
429     * @return whether the command station can perform CV reads
430     */
431    public boolean getCanRead() {
432        return canRead == ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK;
433    }
434
435    @Override
436    public String toString() {
437        return name;
438    }
439
440    /**
441     * Does a programming operation turn track power off?
442     * @return whether the programming operation turns track power off
443     */
444    public boolean getProgPowersOff() {
445        return progEndOp == ProgDepowersTrack.TRACK_TURNEDOFF_BY_PROGRAMMING;
446    }
447
448    static public LnCommandStationType getByName(String name) {
449        for (LnCommandStationType p : LnCommandStationType.values()) {
450            if (p.name.equals(name)) {
451                return p;
452            }
453        }
454        throw new java.lang.IllegalArgumentException("argument value [" + name + "] not valid"); // NOI18N
455    }
456
457    /**
458     * Get a new ThrottleManager of the right type for this command station.
459     *
460     * @param memo the LocoNetSystemConnectionMemo object which hosts throttles
461     * @return the ThrottleManager object for the connection and the command station
462     */
463    public ThrottleManager getThrottleManager(LocoNetSystemConnectionMemo memo) {
464        try {
465            // uses reflection
466            String className = "jmri.jmrix.loconet." + throttleClassName; // NOI18N
467            log.debug("attempting to create {}", className); // NOI18N
468            Class<?> c = Class.forName(className);
469            java.lang.reflect.Constructor<?>[] allConstructors = c.getDeclaredConstructors();
470            for (java.lang.reflect.Constructor<?> ctor : allConstructors) {
471                Class<?>[] pType = ctor.getParameterTypes();
472                if (pType.length == 1 && pType[0].equals(LocoNetSystemConnectionMemo.class)) {
473                    // this is the right ctor
474                    return (ThrottleManager) ctor.newInstance(memo);
475                }
476            }
477            log.error("Did not find a throttle ctor for {}", name);
478        } catch (ClassNotFoundException e1) {
479            log.error("Could not find class for throttle manager from type {} in enum element {}", throttleClassName, name);
480        } catch (InstantiationException e2) {
481            log.error("Could not create throttle manager object from type {} in enum element {}", throttleClassName, name, e2);
482        } catch (IllegalAccessException e3) {
483            log.error("Access error creating throttle manager object from type {} in enum element {}", throttleClassName, name, e3);
484        } catch (java.lang.reflect.InvocationTargetException e4) {
485            log.error("Invocation error while creating throttle manager object from type {} in enum element {}", throttleClassName, name, e4);
486        }
487        return null;
488    }
489
490    /**
491     * Get a new SlotManager of the right type for this command station.
492     *
493     * @param tc the LnTrafficController object which hosts the slot manager
494     * @return the SlogManager object for the connection and the command station
495     */
496    public SlotManager getSlotManager(LnTrafficController tc) {
497        try {
498            // uses reflection
499            String className = "jmri.jmrix.loconet." + slotManagerClassName; // NOI18N
500            log.debug("attempting to create {}", className);
501            Class<?> c = Class.forName(className);
502            java.lang.reflect.Constructor<?>[] allConstructors = c.getDeclaredConstructors();
503            for (java.lang.reflect.Constructor<?> ctor : allConstructors) {
504                Class<?>[] pType = ctor.getParameterTypes();
505                if (pType.length == 1 && pType[0].equals(LnTrafficController.class)) {
506                    // this is the correct ctor
507                    return (SlotManager) ctor.newInstance(tc);
508                }
509            }
510            log.error("Did not find a slotmanager ctor for {}", name);
511        } catch (ClassNotFoundException e1) {
512            log.error("Could not find class for slotmanager from type {} in enum element {}", slotManagerClassName, name);
513        } catch (InstantiationException e2) {
514            log.error("Could not create slotmanager object from type {} in enum element {}", slotManagerClassName, name, e2);
515        } catch (IllegalAccessException e3) {
516            log.error("Access error creating slotmanager object from type {} in enum element {}", slotManagerClassName, name, e3);
517        } catch (java.lang.reflect.InvocationTargetException e4) {
518            log.error("Invocation error while creating slotmanager object from type {} in enum element {}", slotManagerClassName, name, e4);
519        }
520        return null;
521    }
522
523    /**
524     * Returns command station's support for OPC_IDLE
525     *
526     * @return true if OPC_IDLE forces broadcast of "stop", else false
527     */
528    public boolean getImplementsIdle() {
529        return supportsIdle == IdleSupport.SUPPORTS_OPC_IDLE;
530    }
531
532    /**
533     * Returns whether CS supports a multimeter
534     * @return true is Multimeter support
535     */
536    public boolean getSupportsMultimeter() {
537        return supportsMultiMeter == MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION;
538    }
539
540    /**
541     * Returns whether CS supports a Loco Reset feature.
542     *
543     * For this purpose "supports" means that the command station will send
544     * OPC_RE_LOCO_RESET when it clears all slots.
545     *
546     * @return true if command station supports OPC_RE_LOCO_RESET message
547     */
548    public boolean getSupportsLocoReset() {
549
550        return supportsLocoReset == LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION;
551    }
552
553    /**
554     * Returns CS Slot Map.
555     *
556     * @return true if command station supports OPC_RE_LOCO_RESET message
557     */
558    public List<SlotMapEntry> getSlotMap() {
559
560        return slotMap;
561    }
562
563    /**
564     * Returns CS Clock fraction Type
565     *
566     * @return the FracType
567     */
568    public CommandStationClockFracType getCsClockFracType() {
569
570        return csClockFracType;
571    }
572
573    protected enum ReadsFromServiceModeTrack {
574        NO_SVC_MODE_READS, CAN_READ_ON_SVC_TRACK
575    }
576
577    protected enum ProgDepowersTrack {
578        TRACK_TURNEDOFF_BY_PROGRAMMING, TRACK_UNCHANGED_BY_PROGRAMMING
579    }
580
581    protected enum IdleSupport {
582        NO_OPC_IDLE_SUPPORT, SUPPORTS_OPC_IDLE
583    }
584
585    protected enum MultiMeterSupport {
586        NO_MULTIMETER_SUPPORT, SUPPORTS_MULTIMETER_FUNCTION
587    }
588
589    protected enum LocoResetSupport {
590        NO_LOCO_RESET_SUPPORT, SUPPORTS_LOCO_RESET_FUNCTION
591    }
592
593    public enum CommandStationClockFracType {
594        CLOCKNONE,
595        CLOCK13BIT,
596        CLOCK15BIT
597    }
598
599    private final static Logger log = LoggerFactory.getLogger(LnCommandStationType.class);
600}