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_PR4_ALONE("PR4 standalone programmer",  // NOI18N
345            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
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_USB_DCS240_ALONE("DCS240 USB interface as 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.SUPPORTS_MULTIMETER_FUNCTION,
364            LocoResetSupport.NO_LOCO_RESET_SUPPORT,
365            CommandStationClockFracType.CLOCK15BIT,
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_DCS240PLUS_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_DCS210Plus_ALONE("DCS210+ 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_DCS52_ALONE("DCS52 USB interface as standalone programmer",  // NOI18N
401            ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK,
402            ProgDepowersTrack.TRACK_UNCHANGED_BY_PROGRAMMING,
403            "LnThrottleManager", "SlotManager",
404            IdleSupport.NO_OPC_IDLE_SUPPORT, // NOI18N
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    // Note that the convention is that the first word (space-separated token) of the name is the
415    // name of a configuration file for loconet.cmdstnconfig
416    LnCommandStationType(String name, ReadsFromServiceModeTrack canRead,
417            ProgDepowersTrack progEndOp,
418            String throttleClassName, String slotManagerClassName,
419            IdleSupport supportsIdle, MultiMeterSupport supportMultiMeter,
420            LocoResetSupport supportsLocoReset, CommandStationClockFracType csClockFracType,
421            List<SlotMapEntry> slotMap, SupportsSlot250 supportsSlot250) {
422        this.name = name;
423        this.canRead = canRead;
424        this.progEndOp = progEndOp;
425        this.throttleClassName = throttleClassName;
426        this.slotManagerClassName = slotManagerClassName;
427        this.supportsIdle = supportsIdle;
428        this.supportsMultiMeter = supportMultiMeter;
429        this.supportsLocoReset = supportsLocoReset;
430        this.csClockFracType = csClockFracType;
431        this.slotMap = slotMap;
432        this.supportsSlot250 = supportsSlot250;
433    }
434
435    final String name;
436    final ReadsFromServiceModeTrack canRead;
437    final ProgDepowersTrack progEndOp;
438    final String throttleClassName;
439    final String slotManagerClassName;
440    final IdleSupport supportsIdle;
441    final MultiMeterSupport supportsMultiMeter;
442    final LocoResetSupport supportsLocoReset;
443    final CommandStationClockFracType csClockFracType;
444    final List<SlotMapEntry> slotMap;
445    final SupportsSlot250 supportsSlot250;
446
447    public String getName() {
448        return name;
449    }
450
451    /**
452     * Can this command station read back from decoders?
453     * @return whether the command station can perform CV reads
454     */
455    public boolean getCanRead() {
456        return canRead == ReadsFromServiceModeTrack.CAN_READ_ON_SVC_TRACK;
457    }
458
459    @Override
460    public String toString() {
461        return name;
462    }
463
464    /**
465     * Does a programming operation turn track power off?
466     * @return whether the programming operation turns track power off
467     */
468    public boolean getProgPowersOff() {
469        return progEndOp == ProgDepowersTrack.TRACK_TURNEDOFF_BY_PROGRAMMING;
470    }
471
472    /**
473     * Does CS report slot availability in slot 250 ?
474     * @return true if it does
475     */
476    public boolean getSupportsSlot250() {
477        return supportsSlot250 == SupportsSlot250.SLOT250_AVAILABLE;
478    }
479
480    static public LnCommandStationType getByName(String name) {
481        for (LnCommandStationType p : LnCommandStationType.values()) {
482            if (p.name.equals(name)) {
483                return p;
484            }
485        }
486        throw new java.lang.IllegalArgumentException("argument value [" + name + "] not valid"); // NOI18N
487    }
488
489    /**
490     * Get a new ThrottleManager of the right type for this command station.
491     *
492     * @param memo the LocoNetSystemConnectionMemo object which hosts throttles
493     * @return the ThrottleManager object for the connection and the command station
494     */
495    public ThrottleManager getThrottleManager(LocoNetSystemConnectionMemo memo) {
496        try {
497            // uses reflection
498            String className = "jmri.jmrix.loconet." + throttleClassName; // NOI18N
499            log.debug("attempting to create {}", className); // NOI18N
500            Class<?> c = Class.forName(className);
501            java.lang.reflect.Constructor<?>[] allConstructors = c.getDeclaredConstructors();
502            for (java.lang.reflect.Constructor<?> ctor : allConstructors) {
503                Class<?>[] pType = ctor.getParameterTypes();
504                if (pType.length == 1 && pType[0].equals(LocoNetSystemConnectionMemo.class)) {
505                    // this is the right ctor
506                    return (ThrottleManager) ctor.newInstance(memo);
507                }
508            }
509            log.error("Did not find a throttle ctor for {}", name);
510        } catch (ClassNotFoundException e1) {
511            log.error("Could not find class for throttle manager from type {} in enum element {}", throttleClassName, name);
512        } catch (InstantiationException e2) {
513            log.error("Could not create throttle manager object from type {} in enum element {}", throttleClassName, name, e2);
514        } catch (IllegalAccessException e3) {
515            log.error("Access error creating throttle manager object from type {} in enum element {}", throttleClassName, name, e3);
516        } catch (java.lang.reflect.InvocationTargetException e4) {
517            log.error("Invocation error while creating throttle manager object from type {} in enum element {}", throttleClassName, name, e4);
518        }
519        return null;
520    }
521
522    /**
523     * Get a new SlotManager of the right type for this command station.
524     *
525     * @param tc the LnTrafficController object which hosts the slot manager
526     * @return the SlogManager object for the connection and the command station
527     */
528    public SlotManager getSlotManager(LnTrafficController tc) {
529        try {
530            // uses reflection
531            String className = "jmri.jmrix.loconet." + slotManagerClassName; // NOI18N
532            log.debug("attempting to create {}", className);
533            Class<?> c = Class.forName(className);
534            java.lang.reflect.Constructor<?>[] allConstructors = c.getDeclaredConstructors();
535            for (java.lang.reflect.Constructor<?> ctor : allConstructors) {
536                Class<?>[] pType = ctor.getParameterTypes();
537                if (pType.length == 1 && pType[0].equals(LnTrafficController.class)) {
538                    // this is the correct ctor
539                    return (SlotManager) ctor.newInstance(tc);
540                }
541            }
542            log.error("Did not find a slotmanager ctor for {}", name);
543        } catch (ClassNotFoundException e1) {
544            log.error("Could not find class for slotmanager from type {} in enum element {}", slotManagerClassName, name);
545        } catch (InstantiationException e2) {
546            log.error("Could not create slotmanager object from type {} in enum element {}", slotManagerClassName, name, e2);
547        } catch (IllegalAccessException e3) {
548            log.error("Access error creating slotmanager object from type {} in enum element {}", slotManagerClassName, name, e3);
549        } catch (java.lang.reflect.InvocationTargetException e4) {
550            log.error("Invocation error while creating slotmanager object from type {} in enum element {}", slotManagerClassName, name, e4);
551        }
552        return null;
553    }
554
555    /**
556     * Returns command station's support for OPC_IDLE
557     *
558     * @return true if OPC_IDLE forces broadcast of "stop", else false
559     */
560    public boolean getImplementsIdle() {
561        return supportsIdle == IdleSupport.SUPPORTS_OPC_IDLE;
562    }
563
564    /**
565     * Returns whether CS supports a multimeter
566     * @return true is Multimeter support
567     */
568    public boolean getSupportsMultimeter() {
569        return supportsMultiMeter == MultiMeterSupport.SUPPORTS_MULTIMETER_FUNCTION;
570    }
571
572    /**
573     * Returns whether CS supports a Loco Reset feature.
574     *
575     * For this purpose "supports" means that the command station will send
576     * OPC_RE_LOCO_RESET when it clears all slots.
577     *
578     * @return true if command station supports OPC_RE_LOCO_RESET message
579     */
580    public boolean getSupportsLocoReset() {
581
582        return supportsLocoReset == LocoResetSupport.SUPPORTS_LOCO_RESET_FUNCTION;
583    }
584
585    /**
586     * Returns CS Slot Map.
587     *
588     * @return true if command station supports OPC_RE_LOCO_RESET message
589     */
590    public List<SlotMapEntry> getSlotMap() {
591
592        return slotMap;
593    }
594
595    /**
596     * Returns CS Clock fraction Type
597     *
598     * @return the FracType
599     */
600    public CommandStationClockFracType getCsClockFracType() {
601
602        return csClockFracType;
603    }
604    
605    public SupportsSlot250 commandStationSupportSlot250() {
606        return supportsSlot250;
607    }
608
609    protected enum ReadsFromServiceModeTrack {
610        NO_SVC_MODE_READS, CAN_READ_ON_SVC_TRACK
611    }
612
613    protected enum ProgDepowersTrack {
614        TRACK_TURNEDOFF_BY_PROGRAMMING, TRACK_UNCHANGED_BY_PROGRAMMING
615    }
616
617    protected enum IdleSupport {
618        NO_OPC_IDLE_SUPPORT, SUPPORTS_OPC_IDLE
619    }
620
621    protected enum MultiMeterSupport {
622        NO_MULTIMETER_SUPPORT, SUPPORTS_MULTIMETER_FUNCTION
623    }
624
625    protected enum LocoResetSupport {
626        NO_LOCO_RESET_SUPPORT, SUPPORTS_LOCO_RESET_FUNCTION
627    }
628
629    public enum CommandStationClockFracType {
630        CLOCKNONE,
631        CLOCK13BIT,
632        CLOCK15BIT
633    }
634    
635    public enum SupportsSlot250 {
636        SLOT250_AVAILABLE,
637        SLOT250_UNAVAILABLE
638    }
639
640    private final static Logger log = LoggerFactory.getLogger(LnCommandStationType.class);
641}