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