001package jmri.jmrix.can.cbus; 002 003import jmri.AddressedProgrammer; 004import jmri.Programmer; 005import jmri.jmrix.can.CanSystemConnectionMemo; 006import jmri.jmrix.can.ConfigurationManager; 007import jmri.jmrix.can.cbus.swing.modeswitcher.SprogCbusSprog3PlusModeSwitcherFrame; 008import jmri.managers.DefaultProgrammerManager; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013/** 014 * Extend DefaultProgrammerManager to provide programmers for CBUS systems 015 * 016 * Added methods to manipulate the programmer availability to support hardware 017 * that can redirect ops mode or service mode packets to a particular interface. 018 * 019 * @see jmri.managers.DefaultProgrammerManager 020 * @author Andrew crosland Copyright (C) 2009, 2020 021 */ 022public class CbusDccProgrammerManager extends DefaultProgrammerManager { 023 024 private boolean _isAddressedModePossible = true; 025 private boolean _isGlobalProgrammerAvailable = true; 026 027 private final CbusPreferences prefs; 028 029 public CbusDccProgrammerManager(Programmer serviceModeProgrammer, CanSystemConnectionMemo memo) { 030 super(serviceModeProgrammer, memo); 031 tc = memo.getTrafficController(); 032 prefs = memo.get(jmri.jmrix.can.cbus.CbusPreferences.class); 033 log.info("Preferences for programmers start as: global {} addressed {}", prefs.isGlobalProgrammerAvailable(), prefs.isAddressedModePossible()); 034 validateProgrammingModes(memo); 035 log.info("Preferences for programmers now: global {} addressed {}", prefs.isGlobalProgrammerAvailable(), prefs.isAddressedModePossible()); 036 log.info("ProgModeSwitch is {}", memo.getProgModeSwitch()); 037 } 038 039 jmri.jmrix.can.TrafficController tc; 040 041 /** 042 * Check that the programming mode preferences, which may be default values for a new connection 043 * or if they have never been set, are consistent with the programmer modes for 044 * the connected hardware 045 * 046 * @param memo CAN system connection emo 047 */ 048 protected final void validateProgrammingModes(CanSystemConnectionMemo memo) { 049 boolean igpa = prefs.isGlobalProgrammerAvailable(); 050 boolean iamp = prefs.isAddressedModePossible(); 051 int ptm = prefs.getProgTrackMode(); 052 ConfigurationManager.ProgModeSwitch pms = memo.getProgModeSwitch(); 053 switch (pms) { 054 default: 055 case NONE: 056 // Force both programmers available, e.g. for CANCMD that has no mode switching 057 igpa = true; 058 iamp = true; 059 break; 060 061 case EITHER: 062 if ((igpa && iamp) || (!igpa && !iamp)) { 063 // Default to global (service) mode if inconsistent prefs 064 igpa = true; 065 iamp = false; 066 } // else prefs are OK 067 break; 068 069 case SPROG3PLUS: 070 if (ptm == SprogCbusSprog3PlusModeSwitcherFrame.PROG_AR_MODE) { 071 // No global (service) mode if using auto-reverse 072 igpa = false; 073 iamp = true; 074 } else { 075 // Both modes are available global (service) mode 076 igpa = true; 077 iamp = true; 078 } 079 break; 080 } 081 prefs.setProgrammersAvailable(igpa, iamp); 082 mySetGlobalProgrammerAvailable(igpa); 083 mySetAddressedModePossible(iamp); 084 } 085 086 /** 087 * CBUS DCC Programmer has hardware support for ops mode 088 * 089 * @return true 090 */ 091 public boolean isAddressedModeHardwareAvailable() { 092 return true; 093 } 094 095 /** 096 * CBUS DCC Programmer has hardware support for service mode 097 * 098 * @return true if available 099 */ 100 public boolean isGlobalProgrammerHardwareAvailable() { 101 return true; 102 } 103 104 /** 105 * Does Programmer currently support ops mode 106 * 107 * @return true if possible 108 */ 109 @Override 110 public boolean isAddressedModePossible() { 111 return _isAddressedModePossible; 112 } 113 114 /** 115 * Set availability of addressed (ops mode) programmer. 116 * To avoid calling overridable method from constructor 117 * 118 * @param state true if possible 119 */ 120 public final void mySetAddressedModePossible(boolean state) { 121 boolean old = _isAddressedModePossible; 122 _isAddressedModePossible = state; 123 firePropertyChange("addressedModePossible", old, state); 124 } 125 126 /** 127 * Set availability of addressed (ops mode) programmer. 128 * 129 * @param state true if available 130 */ 131 public void setAddressedModePossible(boolean state) { 132 mySetAddressedModePossible(state); 133 } 134 135 /** 136 * Programmer currently support service mode 137 * 138 * @return true if available 139 */ 140 @Override 141 public boolean isGlobalProgrammerAvailable() { 142 return _isGlobalProgrammerAvailable; 143 } 144 145 /** 146 * Set availability of global (service mode) programmer. 147 * To avoid calling overridable method from constructor 148 * 149 * @param state true if available 150 */ 151 public final void mySetGlobalProgrammerAvailable(boolean state) { 152 boolean old = _isGlobalProgrammerAvailable; 153 _isGlobalProgrammerAvailable = state; 154 firePropertyChange("globalProgrammerAvailable", old, state); 155 } 156 157 /** 158 * Set availability of global (service mode) programmer. 159 * 160 * @param state true if available 161 */ 162 public void setGlobalProgrammerAvailable(boolean state) { 163 mySetGlobalProgrammerAvailable(state); 164 } 165 166 @Override 167 public AddressedProgrammer getAddressedProgrammer(boolean pLongAddress, int pAddress) { 168 return new CbusDccOpsModeProgrammer(pAddress, pLongAddress, tc); 169 } 170 171 @Override 172 public AddressedProgrammer reserveAddressedProgrammer(boolean pLongAddress, int pAddress) { 173 return null; 174 } 175 176 private final static Logger log = LoggerFactory.getLogger(CbusDccProgrammerManager.class); 177 178}