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            ),
060    COMMAND_STATION_DCS240("DCS240 (Advanced Command Station)",  // NOI18N
061            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
062            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
063            "LnThrottleManager", "SlotManager",  // NOI18N
064            IdleSupport.SUPPORTS_OPC_IDLE,
065            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
066            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
067            CommandStationClockFracType.CLOCK15BIT,
068            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
069                    new SlotMapEntry(1,120,SlotType.LOCO),
070                    new SlotMapEntry(121,128,SlotType.SYSTEM),
071                    new SlotMapEntry(129,247,SlotType.LOCO),
072                    new SlotMapEntry(248,256,SlotType.SYSTEM),
073                    new SlotMapEntry(257,375,SlotType.LOCO),
074                    new SlotMapEntry(376,384,SlotType.SYSTEM),
075                    new SlotMapEntry(385,432,SlotType.LOCO)),
076            SupportsSlot250.SLOT250_AVAILABLE
077            ),
078    COMMAND_STATION_DCS240PLUS("DCS240+ (Advanced Command Station)",  // NOI18N
079            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
080            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
081            "LnThrottleManager", "SlotManager",  // NOI18N
082            IdleSupport.SUPPORTS_OPC_IDLE,
083            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
084            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
085            CommandStationClockFracType.CLOCK15BIT,
086            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
087                    new SlotMapEntry(1,120,SlotType.LOCO),
088                    new SlotMapEntry(121,128,SlotType.SYSTEM),
089                    new SlotMapEntry(129,247,SlotType.LOCO),
090                    new SlotMapEntry(248,256,SlotType.SYSTEM),
091                    new SlotMapEntry(257,375,SlotType.LOCO),
092                    new SlotMapEntry(376,384,SlotType.SYSTEM),
093                    new SlotMapEntry(385,432,SlotType.LOCO)),
094            SupportsSlot250.SLOT250_AVAILABLE
095            ),
096
097    COMMAND_STATION_DCS210PLUS("DCS210+ (Advanced Command Station)",  // NOI18N
098            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
099            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
100            "LnThrottleManager", "SlotManager",  // NOI18N
101            IdleSupport.SUPPORTS_OPC_IDLE,
102            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
103            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
104            CommandStationClockFracType.CLOCK15BIT,
105            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
106                    new SlotMapEntry(1,100,SlotType.LOCO),
107                    new SlotMapEntry(101,120,SlotType.UNKNOWN),
108                    new SlotMapEntry(121,127,SlotType.SYSTEM),
109                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
110                    new SlotMapEntry(248,256,SlotType.SYSTEM),
111                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
112                    new SlotMapEntry(376,384,SlotType.SYSTEM),
113                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
114            SupportsSlot250.SLOT250_AVAILABLE
115            ),
116    COMMAND_STATION_DCS210("DCS210 (Evolution Command Station)",  // NOI18N
117            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
118            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
119            "LnThrottleManager", "SlotManager",  // NOI18N
120            IdleSupport.SUPPORTS_OPC_IDLE,
121            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
122            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
123            CommandStationClockFracType.CLOCK15BIT,
124            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
125                    new SlotMapEntry(1,100,SlotType.LOCO),
126                    new SlotMapEntry(101,120,SlotType.UNKNOWN),
127                    new SlotMapEntry(121,127,SlotType.SYSTEM),
128                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
129                    new SlotMapEntry(248,256,SlotType.SYSTEM),
130                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
131                    new SlotMapEntry(376,384,SlotType.SYSTEM),
132                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
133            SupportsSlot250.SLOT250_AVAILABLE
134            ),
135    COMMAND_STATION_DCS200("DCS200",  // NOI18N
136            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
137            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
138            "LnThrottleManager", "SlotManager",  // NOI18N
139            IdleSupport.SUPPORTS_OPC_IDLE,
140            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
141            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
142            CommandStationClockFracType.CLOCK13BIT,
143            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
144                    new SlotMapEntry(1,120,SlotType.LOCO),
145                    new SlotMapEntry(121,127,SlotType.SYSTEM),
146                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
147                    new SlotMapEntry(248,256,SlotType.SYSTEM),
148                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
149                    new SlotMapEntry(376,384,SlotType.SYSTEM),
150                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
151            SupportsSlot250.SLOT250_UNAVAILABLE
152            ),
153    COMMAND_STATION_DCS050("DCS50 (Zephyr)",  // NOI18N
154            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
155            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
156            "LnThrottleManager", "SlotManager",  // NOI18N
157            IdleSupport.NO_OPC_IDLE_SUPPORT,
158            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
159            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
160            CommandStationClockFracType.CLOCK13BIT,
161            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
162                    new SlotMapEntry(1,12,SlotType.LOCO),
163                    new SlotMapEntry(13,120,SlotType.UNKNOWN),
164                    new SlotMapEntry(121,127,SlotType.SYSTEM),
165                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
166                    new SlotMapEntry(248,256,SlotType.SYSTEM),
167                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
168                    new SlotMapEntry(376,384,SlotType.SYSTEM),
169                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
170            SupportsSlot250.SLOT250_UNAVAILABLE
171            ),
172    COMMAND_STATION_DCS051("DCS51 (Zephyr Xtra)",  // NOI18N
173            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
174            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
175            "LnThrottleManager", "SlotManager",  // NOI18N
176            IdleSupport.NO_OPC_IDLE_SUPPORT,
177            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
178            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
179            CommandStationClockFracType.CLOCK13BIT,
180            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
181                    new SlotMapEntry(1,19,SlotType.LOCO),
182                    new SlotMapEntry(20,120,SlotType.UNKNOWN),
183                    new SlotMapEntry(121,127,SlotType.SYSTEM),
184                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
185                    new SlotMapEntry(248,256,SlotType.SYSTEM),
186                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
187                    new SlotMapEntry(376,384,SlotType.SYSTEM),
188                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
189            SupportsSlot250.SLOT250_UNAVAILABLE
190            ),
191    COMMAND_STATION_DCS052("DCS52 (Zephyr Express)", // NOI18N
192            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
193            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
194            "LnThrottleManager", "SlotManager",  // NOI18N
195            IdleSupport.NO_OPC_IDLE_SUPPORT,
196            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
197            LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION,
198            CommandStationClockFracType.CLOCK15BIT,
199            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
200                    new SlotMapEntry(1,20,SlotType.LOCO),
201                    new SlotMapEntry(21,120,SlotType.UNKNOWN),
202                    new SlotMapEntry(121,127,SlotType.SYSTEM),
203                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
204                    new SlotMapEntry(248,256,SlotType.SYSTEM),
205                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
206                    new SlotMapEntry(376,384,SlotType.SYSTEM),
207                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
208            SupportsSlot250.SLOT250_AVAILABLE
209            ),
210    COMMAND_STATION_DB150("DB150 (Empire Builder)", // NOI18N
211            ReadsFromServiceModeTrack.NO_SVC_MODE_READS,
212            ProgDepowersTrack.TRACK_TURNEDOFF_BY_PROGRAMMING,
213            "LnThrottleManager", "SlotManager",  // NOI18N
214            IdleSupport.SUPPORTS_OPC_IDLE,
215            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
216            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
217            CommandStationClockFracType.CLOCK13BIT,
218            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
219                    new SlotMapEntry(1,120,SlotType.LOCO),
220                    new SlotMapEntry(121,127,SlotType.SYSTEM),
221                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
222                    new SlotMapEntry(248,256,SlotType.SYSTEM),
223                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
224                    new SlotMapEntry(376,384,SlotType.SYSTEM),
225                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
226            SupportsSlot250.SLOT250_UNAVAILABLE
227            ),
228    // the following command stations are assumed to not support "OPC_IDLE"
229    COMMAND_STATION_LBPS("LocoBuffer (PS)",  // NOI18N
230            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
231            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
232            "LnThrottleManager", "SlotManager",  // NOI18N
233            IdleSupport.NO_OPC_IDLE_SUPPORT,
234            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
235            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
236            CommandStationClockFracType.CLOCK13BIT,
237            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
238                    new SlotMapEntry(1,120,SlotType.LOCO),
239                    new SlotMapEntry(121,127,SlotType.SYSTEM),
240                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
241                    new SlotMapEntry(248,256,SlotType.SYSTEM),
242                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
243                    new SlotMapEntry(376,384,SlotType.SYSTEM),
244                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
245            SupportsSlot250.SLOT250_UNAVAILABLE
246            ),
247    COMMAND_STATION_MM("Mix-Master",  // NOI18N
248            ReadsFromServiceModeTrack.NO_SVC_MODE_READS,
249            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
250            "LnThrottleManager", "SlotManager",  // NOI18N
251            IdleSupport.NO_OPC_IDLE_SUPPORT,
252            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
253            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
254            CommandStationClockFracType.CLOCK13BIT,
255            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
256                    new SlotMapEntry(1,120,SlotType.LOCO),
257                    new SlotMapEntry(121,127,SlotType.SYSTEM),
258                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
259                    new SlotMapEntry(248,256,SlotType.SYSTEM),
260                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
261                    new SlotMapEntry(376,384,SlotType.SYSTEM),
262                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
263            SupportsSlot250.SLOT250_UNAVAILABLE
264            ),
265    COMMAND_STATION_IBX_TYPE_1("Intellibox-I",  // NOI18N
266            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
267            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
268            "Ib1ThrottleManager", "SlotManager",  // NOI18N
269            IdleSupport.NO_OPC_IDLE_SUPPORT,
270            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
271            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
272            CommandStationClockFracType.CLOCK13BIT,
273            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
274                    new SlotMapEntry(1,120,SlotType.LOCO),
275                    new SlotMapEntry(121,127,SlotType.SYSTEM),
276                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
277                    new SlotMapEntry(248,256,SlotType.SYSTEM),
278                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
279                    new SlotMapEntry(376,384,SlotType.SYSTEM),
280                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
281            SupportsSlot250.SLOT250_UNAVAILABLE
282            ),
283    COMMAND_STATION_IBX_TYPE_2("Intellibox-II",  // NOI18N
284            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
285            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
286            "Ib2ThrottleManager", "UhlenbrockSlotManager",  // NOI18N
287            IdleSupport.NO_OPC_IDLE_SUPPORT,
288            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
289            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
290            CommandStationClockFracType.CLOCK13BIT,
291            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
292                    new SlotMapEntry(1,120,SlotType.LOCO),
293                    new SlotMapEntry(121,127,SlotType.SYSTEM),
294                    new SlotMapEntry(128,247,SlotType.UNKNOWN),
295                    new SlotMapEntry(248,256,SlotType.SYSTEM),
296                    new SlotMapEntry(257,375,SlotType.UNKNOWN),
297                    new SlotMapEntry(376,384,SlotType.SYSTEM),
298                    new SlotMapEntry(385,432,SlotType.UNKNOWN)),
299            SupportsSlot250.SLOT250_UNAVAILABLE
300            ),
301    // the following command stations are known to not support "OPC_IDLE"
302    COMMAND_STATION_PR3_ALONE("PR3 standalone programmer",  // NOI18N
303            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
304            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
305            "LnThrottleManager", "SlotManager",  // NOI18N
306            IdleSupport.NO_OPC_IDLE_SUPPORT,
307            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
308            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
309            CommandStationClockFracType.CLOCK13BIT,
310            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
311                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
312                    new SlotMapEntry(121,127,SlotType.SYSTEM),
313                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
314            SupportsSlot250.SLOT250_UNAVAILABLE
315            ),
316    COMMAND_STATION_PR2_ALONE("PR2 standalone programmer",  // NOI18N
317            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
318            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
319            "LnThrottleManager", "SlotManager",  // NOI18N
320            IdleSupport.NO_OPC_IDLE_SUPPORT,
321            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
322            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
323            CommandStationClockFracType.CLOCK13BIT,
324            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
325                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
326                    new SlotMapEntry(121,127,SlotType.SYSTEM),
327                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
328            SupportsSlot250.SLOT250_UNAVAILABLE
329            ),
330    COMMAND_STATION_STANDALONE("Stand-alone LocoNet",  // NOI18N
331            ReadsFromServiceModeTrack.NO_SVC_MODE_READS,
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            ),
344    COMMAND_STATION_STANDALONE_EXT_TERM("Stand-alone LocoNet (using external LocoNet Data Termination!)",  // NOI18N
345            ReadsFromServiceModeTrack.NO_SVC_MODE_READS,
346            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
347            "LnThrottleManager", "SlotManager",  // NOI18N
348            IdleSupport.NO_OPC_IDLE_SUPPORT,
349            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
350            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
351            CommandStationClockFracType.CLOCK13BIT,
352            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
353                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
354                    new SlotMapEntry(121,127,SlotType.SYSTEM),
355                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
356            SupportsSlot250.SLOT250_UNAVAILABLE
357            ),
358    COMMAND_STATION_PR4_ALONE("PR4 standalone programmer",  // NOI18N
359            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
360            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
361            "LnThrottleManager", "SlotManager",  // NOI18N
362            IdleSupport.NO_OPC_IDLE_SUPPORT,
363            MultiMeterSupport.NO_MULTIMETER_SUPPORT,
364            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
365            CommandStationClockFracType.CLOCK13BIT,
366            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
367                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
368                    new SlotMapEntry(121,127,SlotType.SYSTEM),
369                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
370            SupportsSlot250.SLOT250_UNAVAILABLE
371            ),
372    COMMAND_STATION_USB_DCS240_ALONE("DCS240 USB interface as standalone programmer", // NOI18N
373            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
374            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
375            "LnThrottleManager", "SlotManager",  // NOI18N
376            IdleSupport.NO_OPC_IDLE_SUPPORT,
377            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
378            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
379            CommandStationClockFracType.CLOCK15BIT,
380            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
381                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
382                    new SlotMapEntry(121,127,SlotType.SYSTEM),
383                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
384            SupportsSlot250.SLOT250_UNAVAILABLE
385            ),
386    COMMAND_STATION_USB_DCS240PLUS_ALONE("DCS240+ USB interface as standalone programmer", // NOI18N
387            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
388            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
389            "LnThrottleManager", "SlotManager",  // NOI18N
390            IdleSupport.NO_OPC_IDLE_SUPPORT,
391            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
392            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
393            CommandStationClockFracType.CLOCK15BIT,
394            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
395                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
396                    new SlotMapEntry(121,127,SlotType.SYSTEM),
397                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
398            SupportsSlot250.SLOT250_UNAVAILABLE
399            ),
400    COMMAND_STATION_USB_DCS210Plus_ALONE("DCS210+ USB interface as standalone programmer", // NOI18N
401            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
402            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
403            "LnThrottleManager", "SlotManager",  // NOI18N
404            IdleSupport.NO_OPC_IDLE_SUPPORT,
405            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
406            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
407            CommandStationClockFracType.CLOCK15BIT,
408            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
409                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
410                    new SlotMapEntry(121,127,SlotType.SYSTEM),
411                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
412            SupportsSlot250.SLOT250_UNAVAILABLE
413            ),
414    COMMAND_STATION_USB_DCS52_ALONE("DCS52 USB interface as standalone programmer",  // NOI18N
415            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
416            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
417            "LnThrottleManager", "SlotManager",
418            IdleSupport.NO_OPC_IDLE_SUPPORT, // NOI18N
419            MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION,
420            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
421            CommandStationClockFracType.CLOCK15BIT,
422            Arrays.asList(new SlotMapEntry(0,0,SlotType.SYSTEM),
423                    new SlotMapEntry(1,120,SlotType.UNKNOWN),
424                    new SlotMapEntry(121,127,SlotType.SYSTEM),
425                    new SlotMapEntry(128,432,SlotType.UNKNOWN)),
426            SupportsSlot250.SLOT250_UNAVAILABLE
427            );
428    // Note that the convention is that the first word (space-separated token) of the name is the
429    // name of a configuration file for loconet.cmdstnconfig
430    LnCommandStationType(String name, ReadsFromServiceModeTrack canRead,
431            ProgDepowersTrack progEndOp,
432            String throttleClassName, String slotManagerClassName,
433            IdleSupport supportsIdle, MultiMeterSupport supportMultiMeter,
434            LocoResetSupport supportsLocoReset, CommandStationClockFracType csClockFracType,
435            List<SlotMapEntry> slotMap, SupportsSlot250 supportsSlot250) {
436        this.name = name;
437        this.canRead = canRead;
438        this.progEndOp = progEndOp;
439        this.throttleClassName = throttleClassName;
440        this.slotManagerClassName = slotManagerClassName;
441        this.supportsIdle = supportsIdle;
442        this.supportsMultiMeter = supportMultiMeter;
443        this.supportsLocoReset = supportsLocoReset;
444        this.csClockFracType = csClockFracType;
445        this.slotMap = slotMap;
446        this.supportsSlot250 = supportsSlot250;
447    }
448
449    final String name;
450    final ReadsFromServiceModeTrack canRead;
451    final ProgDepowersTrack progEndOp;
452    final String throttleClassName;
453    final String slotManagerClassName;
454    final IdleSupport supportsIdle;
455    final MultiMeterSupport supportsMultiMeter;
456    final LocoResetSupport supportsLocoReset;
457    final CommandStationClockFracType csClockFracType;
458    final List<SlotMapEntry> slotMap;
459    final SupportsSlot250 supportsSlot250;
460
461    public String getName() {
462        return name;
463    }
464
465    /**
466     * Can this command station read back from decoders?
467     * @return whether the command station can perform CV reads
468     */
469    public boolean getCanRead() {
470        return canRead == ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK;
471    }
472
473    @Override
474    public String toString() {
475        return name;
476    }
477
478    /**
479     * Does a programming operation turn track power off?
480     * @return whether the programming operation turns track power off
481     */
482    public boolean getProgPowersOff() {
483        return progEndOp == ProgDepowersTrack.TRACK_TURNEDOFF_BY_PROGRAMMING;
484    }
485
486    /**
487     * Does CS report slot availability in slot 250 ?
488     * @return true if it does
489     */
490    public boolean getSupportsSlot250() {
491        return supportsSlot250 == SupportsSlot250.SLOT250_AVAILABLE;
492    }
493
494    static public LnCommandStationType getByName(String name) {
495        for (LnCommandStationType p : LnCommandStationType.values()) {
496            if (p.name.equals(name)) {
497                return p;
498            }
499        }
500        throw new java.lang.IllegalArgumentException("argument value [" + name + "] not valid"); // NOI18N
501    }
502
503    /**
504     * Get a new ThrottleManager of the right type for this command station.
505     *
506     * @param memo the LocoNetSystemConnectionMemo object which hosts throttles
507     * @return the ThrottleManager object for the connection and the command station
508     */
509    public ThrottleManager getThrottleManager(LocoNetSystemConnectionMemo memo) {
510        try {
511            // uses reflection
512            String className = "jmri.jmrix.loconet." + throttleClassName; // NOI18N
513            log.debug("attempting to create {}", className); // NOI18N
514            Class<?> c = Class.forName(className);
515            java.lang.reflect.Constructor<?>[] allConstructors = c.getDeclaredConstructors();
516            for (java.lang.reflect.Constructor<?> ctor : allConstructors) {
517                Class<?>[] pType = ctor.getParameterTypes();
518                if (pType.length == 1 && pType[0].equals(LocoNetSystemConnectionMemo.class)) {
519                    // this is the right ctor
520                    return (ThrottleManager) ctor.newInstance(memo);
521                }
522            }
523            log.error("Did not find a throttle ctor for {}", name);
524        } catch (ClassNotFoundException e1) {
525            log.error("Could not find class for throttle manager from type {} in enum element {}", throttleClassName, name);
526        } catch (InstantiationException e2) {
527            log.error("Could not create throttle manager object from type {} in enum element {}", throttleClassName, name, e2);
528        } catch (IllegalAccessException e3) {
529            log.error("Access error creating throttle manager object from type {} in enum element {}", throttleClassName, name, e3);
530        } catch (java.lang.reflect.InvocationTargetException e4) {
531            log.error("Invocation error while creating throttle manager object from type {} in enum element {}", throttleClassName, name, e4);
532        }
533        return null;
534    }
535
536    /**
537     * Get a new SlotManager of the right type for this command station.
538     *
539     * @param tc the LnTrafficController object which hosts the slot manager
540     * @return the SlogManager object for the connection and the command station
541     */
542    public SlotManager getSlotManager(LnTrafficController tc) {
543        try {
544            // uses reflection
545            String className = "jmri.jmrix.loconet." + slotManagerClassName; // NOI18N
546            log.debug("attempting to create {}", className);
547            Class<?> c = Class.forName(className);
548            java.lang.reflect.Constructor<?>[] allConstructors = c.getDeclaredConstructors();
549            for (java.lang.reflect.Constructor<?> ctor : allConstructors) {
550                Class<?>[] pType = ctor.getParameterTypes();
551                if (pType.length == 1 && pType[0].equals(LnTrafficController.class)) {
552                    // this is the correct ctor
553                    return (SlotManager) ctor.newInstance(tc);
554                }
555            }
556            log.error("Did not find a slotmanager ctor for {}", name);
557        } catch (ClassNotFoundException e1) {
558            log.error("Could not find class for slotmanager from type {} in enum element {}", slotManagerClassName, name);
559        } catch (InstantiationException e2) {
560            log.error("Could not create slotmanager object from type {} in enum element {}", slotManagerClassName, name, e2);
561        } catch (IllegalAccessException e3) {
562            log.error("Access error creating slotmanager object from type {} in enum element {}", slotManagerClassName, name, e3);
563        } catch (java.lang.reflect.InvocationTargetException e4) {
564            log.error("Invocation error while creating slotmanager object from type {} in enum element {}", slotManagerClassName, name, e4);
565        }
566        return null;
567    }
568
569    /**
570     * Returns command station's support for OPC_IDLE
571     *
572     * @return true if OPC_IDLE forces broadcast of "stop", else false
573     */
574    public boolean getImplementsIdle() {
575        return supportsIdle == IdleSupport.SUPPORTS_OPC_IDLE;
576    }
577
578    /**
579     * Returns whether CS supports a multimeter
580     * @return true is Multimeter support
581     */
582    public boolean getSupportsMultimeter() {
583        return supportsMultiMeter == MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION;
584    }
585
586    /**
587     * Returns whether CS supports a Loco Reset feature.
588     *
589     * For this purpose "supports" means that the command station will send
590     * OPC_RE_LOCO_RESET when it clears all slots.
591     *
592     * @return true if command station supports OPC_RE_LOCO_RESET message
593     */
594    public boolean getSupportsLocoReset() {
595
596        return supportsLocoReset == LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION;
597    }
598
599    /**
600     * Returns CS Slot Map.
601     *
602     * @return true if command station supports OPC_RE_LOCO_RESET message
603     */
604    public List<SlotMapEntry> getSlotMap() {
605
606        return slotMap;
607    }
608
609    /**
610     * Returns CS Clock fraction Type
611     *
612     * @return the FracType
613     */
614    public CommandStationClockFracType getCsClockFracType() {
615
616        return csClockFracType;
617    }
618    
619    public SupportsSlot250 commandStationSupportSlot250() {
620        return supportsSlot250;
621    }
622
623    protected enum ReadsFromServiceModeTrack {
624        NO_SVC_MODE_READS, CAN_READ_ON_SVC_TRACK
625    }
626
627    protected enum ProgDepowersTrack {
628        TRACK_TURNEDOFF_BY_PROGRAMMING, TRACK_UNCHANGED_BY_PROGRAMMING
629    }
630
631    protected enum IdleSupport {
632        NO_OPC_IDLE_SUPPORT, SUPPORTS_OPC_IDLE
633    }
634
635    protected enum MultiMeterSupport {
636        NO_MULTIMETER_SUPPORT, SUPPORTS_MULTIMETER_FUNCTION
637    }
638
639    protected enum LocoResetSupport {
640        NO_LOCO_RESET_SUPPORT, SUPPORTS_LOCO_RESET_FUNCTION
641    }
642
643    public enum CommandStationClockFracType {
644        CLOCKNONE,
645        CLOCK13BIT,
646        CLOCK15BIT
647    }
648    
649    public enum SupportsSlot250 {
650        SLOT250_AVAILABLE,
651        SLOT250_UNAVAILABLE
652    }
653
654    private final static Logger log = LoggerFactory.getLogger(LnCommandStationType.class);
655}