001package jmri.jmrix.roco.z21;
002
003/**
004 * Defines the standard/common routines used in multiple classes related to 
005 * a Roco z21 Command Station.
006 * <p>
007 * This class keeps track of the broadcast flags associated with the 
008 * currently connected Roco Z21 Command Station.
009 * <p>
010 * Brief descriptions of the flags are as follows (loosely
011 * translated from  section 2.16 of the manual from the German 
012 * with the aid of google translate).
013 * <ul>
014 * <li>0x00000001 send XpressNet related information (track
015 * power on/off, programming mode, short circuit, broadcast stop,
016 * locomotive information, turnout information).</li>
017 * <li>0x00000002 send data changes that occur on the RMBUS.</li>
018 * <li>0x00000004 (deprecated by Roco) send Railcom Data</li>
019 * <li>0x00000100 send changes in system state (such as track voltage)
020 * <li>0x00010000 send changes to locomotives on XpressNet (must also have
021 * 0x00000001 set.</li>
022 * <li>0x01000000 forward LocoNet data to the client.  Does not send
023 * Locomotive or turnout data.</li>
024 * <li>0x02000000 send Locomotive specific LocoNet data to the client.</li>
025 * <li>0x04000000 send Turnout specific LocoNet data to the client.</li>
026 * <li>0x08000000 send Occupancy information from LocoNet to the client</li>
027 * <li>0x00040000 Automatically send updates for Railcom data to the client</li>
028 * <li>0x00080000 send CAN detector messages to the client</li>
029 * <li>0x00020000 send CAN booster status messages to the client.</li>
030 * <li>0x00000010 send Fast Clock time messages to the client.</li>
031 * </ul>
032 *
033 * @author Bob Jacobsen Copyright (C) 2001 
034 * @author      Paul Bender Copyright (C) 2016,2025
035 */
036public class RocoZ21CommandStation extends jmri.jmrix.roco.RocoCommandStation {
037
038    private static final int XPressNetFlag = 0x00000001;
039    private static final int RMBusFlag = 0x00000002;
040    private static final int RailComFlag = 0x00000004;
041    private static final int SystemStateFlag = 0x00000100;
042    private static final int XPressNetLocomotiveFlag = 0x00010000;
043    private static final int LocoNetDataFlag = 0x01000000;
044    private static final int LocoNetLocomotiveFlag = 0x02000000;
045    private static final int LocoNetTurnoutFlag = 0x04000000;
046    private static final int LocoNetOccupancyFlag = 0x08000000;
047    private static final int AutoMaticRailComFlag = 0x00040000;
048    private static final int CANDetectorFlag = 0x00080000;
049    private static final int CANBoosterFlag = 0x00020000;
050    private static final int FastClockFlag = 0x00000010;
051    private int broadcast_flags = 0; // holds the value of the broadcast flags.
052    private int serial_number = 0; // holds the serial number of the Z21.
053    private float software_version = 0; // holds the software version of the Z21.
054    private int hardware_version = 0; // holds the hardware version of the Z21.
055
056   /**
057    * get the serial number.
058    * @return serial number of the connected Z21 command station
059    */
060   public int getSerialNumber(){
061      return serial_number;
062   }
063
064   /**
065    * set the serial number associated with this Z21 command station.
066    * @param sn serial number
067    */
068   public void setSerialNumber(int sn){
069      serial_number = sn;
070   }
071 
072  /**
073    * get the software version.
074    * @return software version of the connected Z21 command station
075    */
076   public float getSoftwareVersion(){
077      return software_version;
078   }
079
080   /**
081    * set the software version associated with this Z21 command station.
082    * @param sv software version
083    */
084   public void setSoftwareVersion(float sv){
085      software_version=sv;
086   }
087
088  /**
089    * get the hardware version.
090    * @return hardware version of the connected Z21 command station
091    */
092   public int getHardwareVersion(){
093      return hardware_version;
094   }
095
096   /**
097    * set the hardware version associated with this Z21 command station.
098    * @param hv software version
099    */
100   public void setHardwareVersion(int hv){
101      hardware_version=hv;
102   }
103
104   /**
105    * get the current value of the broadcast flags as an int
106    * @return value representing the broadcast flags. 
107    */
108   public int getZ21BroadcastFlags(){
109        return broadcast_flags;
110   }
111
112   /**
113    * set the current value of the broadcast flags as an int
114    * @param flags representing the broadcast flags. 
115    */
116   public void setZ21BroadcastFlags(int flags){
117        broadcast_flags = flags;
118   }
119
120   /**
121    * get the current value of the broadcast flags as a string
122    * @return string representing the broadcast flags.
123    */
124    public String getZ21BroadcastFlagsString() {
125        return getZ21BroadcastFlagsString(broadcast_flags);
126    }
127
128    /**
129     * Get the value of the specified broadcast flags as a string
130     *
131     * @param flags the flags to be interpreted
132     * @return string representing the broadcast flags.
133     */
134    static public String getZ21BroadcastFlagsString(int flags) {
135        StringBuilder flagStringBuilder = new StringBuilder();
136        if((flags & XPressNetFlag) == XPressNetFlag){
137            flagStringBuilder.append("XpressNet Messages");
138            flagStringBuilder.append("\n");
139        }
140        if((flags & RMBusFlag) == RMBusFlag){
141            flagStringBuilder.append("RMBus Messages");
142            flagStringBuilder.append("\n");
143        }
144        if((flags & RailComFlag) == RailComFlag){
145            flagStringBuilder.append("Railcom Messages");
146            flagStringBuilder.append("\n");
147        }
148        if((flags & SystemStateFlag) == SystemStateFlag){
149            flagStringBuilder.append("System State Messages");
150            flagStringBuilder.append("\n");
151        }
152        if((flags & XPressNetLocomotiveFlag) == XPressNetLocomotiveFlag){
153            flagStringBuilder.append("XpressNet Locomotive Messages");
154            flagStringBuilder.append("\n");
155        }
156        if((flags & LocoNetDataFlag) == LocoNetDataFlag){
157            flagStringBuilder.append("LocoNet Messages");
158            flagStringBuilder.append("\n");
159        }
160        if((flags & LocoNetLocomotiveFlag) == LocoNetLocomotiveFlag){
161            flagStringBuilder.append("LocoNet Locomotive Messages");
162            flagStringBuilder.append("\n");
163        }
164        if((flags & LocoNetTurnoutFlag) == LocoNetTurnoutFlag){
165            flagStringBuilder.append("LocoNet Turnout Messages");
166            flagStringBuilder.append("\n");
167        }
168        if((flags & LocoNetOccupancyFlag) == LocoNetOccupancyFlag){
169            flagStringBuilder.append("LocoNet Occupancy Messages");
170            flagStringBuilder.append("\n");
171        }
172        if ((flags & AutoMaticRailComFlag) == AutoMaticRailComFlag) {
173            flagStringBuilder.append("Railcom Automatic Messages");
174            flagStringBuilder.append("\n");
175        }
176        if ((flags & CANDetectorFlag) == CANDetectorFlag) {
177            flagStringBuilder.append("CAN Detector Messages");
178            flagStringBuilder.append("\n");
179        }
180
181        if((flags & CANBoosterFlag) == CANBoosterFlag){
182            flagStringBuilder.append("CAN Booster Status Messages");
183            flagStringBuilder.append("\n");
184        }
185        if((flags & FastClockFlag) == FastClockFlag){
186            flagStringBuilder.append("Fast Clock Messages");
187            flagStringBuilder.append("\n");
188        }
189
190        return flagStringBuilder.toString();
191    }
192
193    /**
194    * Is flag bit 0x00000001 which tells the command station to send 
195    * XpressNet related information (track power on/off, programming
196    * mode, short circuit, broadcast stop, locomotive information, 
197    * turnout information) set?
198    * @return true if flag is set.
199    */
200    public boolean getXPressNetMessagesFlag(){
201        return((broadcast_flags & XPressNetFlag) == XPressNetFlag);
202    }
203
204   /**
205    * Set flag bit 0x00000001 which tells the command station to send 
206    * XpressNet related information (track power on/off, programming
207    * mode, short circuit, broadcast stop, locomotive information, 
208    * turnout information).
209    * @param flag true if flag is to be set.
210    */
211    public void setXPressNetMessagesFlag(boolean flag){
212        if(flag) {
213           broadcast_flags = broadcast_flags | XPressNetFlag;
214        }
215        else {
216           broadcast_flags = broadcast_flags & (~XPressNetFlag);
217        }
218    }
219
220   /**
221    * Is flag bit 0x00000002 which tells the command station to send 
222    * data changes on the RMBus to the client set?
223    * @return true if flag is set.
224    */
225    public boolean getRMBusMessagesFlag(){
226        return((broadcast_flags & RMBusFlag) == RMBusFlag);
227    }
228
229   /**
230    * Set flag bit 0x00000002 which tells the command station to send 
231    * data changes on the RMBus to the client set?
232    * @param flag true if flag is to be set.
233    */
234    public void setRMBusMessagesFlag(boolean flag){
235        if(flag) {
236           broadcast_flags = broadcast_flags | RMBusFlag;
237        }
238        else {
239           broadcast_flags = broadcast_flags & (~RMBusFlag);
240        }
241    }
242
243   /**
244    * Is flag bit 0x00000004, which tells the command station to 
245    * send Railcom data to the client set (this flag may no longer
246    * be supported by Roco). 
247    * @return true if flag is set.
248    */
249    public boolean getRailComMessagesFlag(){
250        return((broadcast_flags & RailComFlag) == RailComFlag);
251    }
252
253   /**
254    * Set flag bit 0x00000004, which tells the command station to 
255    * send Railcom data to the client set (this flag may no longer
256    * be supported by Roco). 
257    * @param flag true if flag is to be set.
258    */
259    public void setRailComMessagesFlag(boolean flag){
260        if(flag) {
261           broadcast_flags = broadcast_flags | RailComFlag;
262        }
263        else {
264           broadcast_flags = broadcast_flags & (~RailComFlag);
265        }
266    }
267
268   /**
269    * Is flag bit 0x00040000, which tells the command station to 
270    * automatically send Railcom data to the client set. 
271    * @return true if flag is set.
272    */
273    public boolean getRailComAutomaticFlag(){
274        return((broadcast_flags & AutoMaticRailComFlag) == AutoMaticRailComFlag);
275    }
276
277   /**
278    * Set flag bit 0x00040000, which tells the command station to 
279    * automatically send Railcom data to the client set. 
280    * @param flag true if flag is to be set.
281    */
282    public void setRailComAutomaticFlag(boolean flag){
283        if(flag) {
284           broadcast_flags = broadcast_flags | AutoMaticRailComFlag;
285        }
286        else {
287           broadcast_flags = broadcast_flags & (~AutoMaticRailComFlag);
288        }
289    }
290
291   /**
292    * Is flag bit 0x00080000, which tells the command station to 
293    * send CAN detector data to the client set. 
294    * @return true if flag is set.
295    */
296    public boolean getCanDetectorFlag(){
297        return((broadcast_flags & CANDetectorFlag) == CANDetectorFlag);
298    }
299
300   /**
301    * Set flag bit 0x00080000, which tells the command station to 
302    * send CAN detector data to the client. 
303    * @param flag true if flag is to be set.
304    */
305    public void setCanDetectorFlag(boolean flag){
306        if(flag) {
307           broadcast_flags = broadcast_flags | CANDetectorFlag;
308        }
309        else {
310           broadcast_flags = broadcast_flags & (~CANDetectorFlag);
311        }
312    }
313
314    /**
315     * Is flag bit 0x00020000, which tells the command station to
316     * send CAN booster data to the client set.
317     * @return true if flag is set.
318     */
319    public boolean getCanBoosterFlag(){
320        return((broadcast_flags & CANBoosterFlag) == CANBoosterFlag);
321    }
322
323    /**
324     * Set flag bit 0x00020000, which tells the command station to
325     * send CAN detector data to the client.
326     * @param flag true if flag is to be set.
327     */
328    public void setCanBoosterFlag(boolean flag) {
329        if (flag) {
330            broadcast_flags = broadcast_flags | CANBoosterFlag;
331        } else {
332            broadcast_flags = broadcast_flags & (~CANBoosterFlag);
333        }
334    }
335
336
337   /**
338    * Is flag bit 0x00000100 which tells the command station to send 
339    * changes in system state (such as track voltage) set?
340    * @return true if flag is set.
341    */
342    public boolean getSystemStatusMessagesFlag(){
343        return((broadcast_flags & SystemStateFlag) == SystemStateFlag);
344    }
345
346   /**
347    * Set flag bit 0x00000100 which tells the command station to send 
348    * changes in system state (such as track voltage).
349    * @param flag true if flag is to be set.
350    */
351    public void setSystemStatusMessagesFlag(boolean flag){
352        if(flag) {
353           broadcast_flags = broadcast_flags | SystemStateFlag;
354        }
355        else {
356           broadcast_flags = broadcast_flags & (~SystemStateFlag);
357        }
358    }
359
360   /**
361    * Is flag bit 0x00010000 which tells the command station to send 
362    * XpressNet related locomoitve information to the client set?
363    *
364    * @return true if flag is set
365    */
366    public boolean getXPressNetLocomotiveMessagesFlag(){
367        return((broadcast_flags & XPressNetLocomotiveFlag) == XPressNetLocomotiveFlag);
368    }
369
370   /**
371    * Set flag bit 0x00010000 which tells the command station to send 
372    * XpressNet related locomoitve information to the client.
373    * @param flag true if flag is to be set.
374    */
375    public void setXPressNetLocomotiveMessagesFlag(boolean flag){
376        if(flag) {
377           broadcast_flags = broadcast_flags | XPressNetLocomotiveFlag;
378        }
379        else {
380           broadcast_flags = broadcast_flags & (~XPressNetLocomotiveFlag);
381        }
382    }
383
384   /**
385    * Is flag bit 0x01000000 which tells the command station to send 
386    * LocoNet data,except Locomotive and Turnout data, to the client set?
387    * @return true if flag is set.
388    */
389    public boolean getLocoNetMessagesFlag(){
390        return((broadcast_flags & LocoNetDataFlag) == LocoNetDataFlag);
391    }
392
393   /**
394    * Set flag bit 0x01000000 which tells the command station to send
395    * LocoNet data,except Locomotive and Turnout data, to the client.
396    * @param flag true if flag is to be set.
397    */
398    public void setLocoNetMessagesFlag(boolean flag){
399        if(flag) {
400           broadcast_flags = broadcast_flags | LocoNetDataFlag;
401        }
402        else {
403           broadcast_flags = broadcast_flags & (~LocoNetDataFlag);
404        }
405    }
406
407   /**
408    * Is flag bit 0x02000000 which tells the command station to send 
409    * Locomotive specific LocoNet data to the client set?
410    * @return true if flag is set.
411    */
412    public boolean getLocoNetLocomotiveMessagesFlag(){
413        return((broadcast_flags & LocoNetLocomotiveFlag) == LocoNetLocomotiveFlag);
414    }
415
416   /**
417    * Set flag bit 0x02000000 which tells the command station to send 
418    * Locomotive specific LocoNet data to the client.
419    * @param flag true if flag is to be set.
420    */
421    public void setLocoNetLocomotiveMessagesFlag(boolean flag){
422        if(flag) {
423           broadcast_flags = broadcast_flags | LocoNetLocomotiveFlag;
424        }
425        else {
426           broadcast_flags = broadcast_flags & (~LocoNetLocomotiveFlag);
427        }
428    }
429
430   /**
431    * Is flag bit 0x04000000 which tells the command station to send 
432    * Turnout specific LocoNet data to the client set?
433    * @return true if flag is set.
434    */
435    public boolean getLocoNetTurnoutMessagesFlag(){
436        return((broadcast_flags & LocoNetTurnoutFlag) == LocoNetTurnoutFlag);
437    }
438
439   /**
440    * Set flag bit 0x04000000 which tells the command station to send 
441    * Turnout specific LocoNet data to the client set?
442    * @param flag true if flag is to be set.
443    */
444    public void setLocoNetTurnoutMessagesFlag(boolean flag){
445        if(flag) {
446           broadcast_flags = broadcast_flags | LocoNetTurnoutFlag;
447        }
448        else {
449           broadcast_flags = broadcast_flags & (~LocoNetTurnoutFlag);
450        }
451    }
452
453   /**
454    * Is flag bit 0x08000000 which tells the command station to send 
455    * Occupancy information from LocoNet to the client set?
456    * @return true if flag is set.
457    */
458    public boolean getLocoNetOccupancyMessagesFlag(){
459        return((broadcast_flags & LocoNetOccupancyFlag) == LocoNetOccupancyFlag);
460    }
461
462   /**
463    * <p>
464    * Set flag bit 0x08000000 which tells the command station to send 
465    * Occupancy information from LocoNet to the client
466    * </p>
467    * <p>
468    * If this flag is set to true, the Z21 will format Transponding messages
469    * as described in section 9.5 of the Z21 Lan Protocol.  This message format
470    * is currentlyunsupported by JMRI.
471    * </p>
472    *
473    * @param flag true if flag is to be set.
474    */
475    public void setLocoNetOccupancyMessagesFlag(boolean flag){
476        if(flag) {
477           broadcast_flags = broadcast_flags | LocoNetOccupancyFlag;
478        }
479        else {
480           broadcast_flags = broadcast_flags & (~LocoNetOccupancyFlag);
481        }
482    }
483    //* <li>0x00000010 send Fast Clock time messages to the client.</li>
484    /**
485     * Is flag bit 0x00000100 which tells the command station to send
486     * changes in system state (such as track voltage) set?
487     * @return true if flag is set.
488     */
489    public boolean getFastClockFlag(){
490        return((broadcast_flags & FastClockFlag) == FastClockFlag);
491    }
492
493    /**
494     * Set flag bit 0x00000010 which tells the command station to send
495     * changes in the fast clock to.
496     * @param flag true if flag is to be set.
497     */
498    public void setFastClockFlag(boolean flag){
499        if(flag) {
500            broadcast_flags = broadcast_flags | FastClockFlag;
501        }
502        else {
503            broadcast_flags = broadcast_flags & (~FastClockFlag);
504        }
505    }
506
507}