001package jmri.jmrix.sprog; 002 003import jmri.DccLocoAddress; 004import jmri.LocoAddress; 005import jmri.SpeedStepMode; 006import jmri.jmrix.AbstractThrottle; 007 008import org.slf4j.Logger; 009import org.slf4j.LoggerFactory; 010 011/** 012 * An implementation of DccThrottle with code specific to a SPROG Command 013 * Station connection. 014 * <p> 015 * Updated by Andrew Crosland February 2012 to enable 28 step speed packets 016 * 017 * @author Andrew Crosland Copyright (C) 2006, 2012 018 */ 019public class SprogCSThrottle extends AbstractThrottle { 020 021 /** 022 * Constructor. 023 * @param memo system connection. 024 * @param address Loco Address. 025 */ 026 public SprogCSThrottle(SprogSystemConnectionMemo memo, LocoAddress address) { 027 super(memo, SprogConstants.MAX_FUNCTIONS); 028 029 if (address instanceof DccLocoAddress) { 030 this.address = ((DccLocoAddress) address); 031 } 032 else { 033 log.error("{} is not a DccLocoAddress",address); 034 } 035 036 // cache settings. 037 synchronized(this) { 038 this.speedSetting = 0; 039 } 040 // Functions default to false 041 this.isForward = true; 042 this.speedStepMode = SpeedStepMode.NMRA_DCC_128; 043 044 045 //@TODO - this needs a little work. Current implementation looks like it 046 //should support other modes, but doesn't in practice. 047 //@see AbstractThrottleManager.supportedSpeedModes() 048 // Find our command station 049 if ((memo != null) && (memo.get(jmri.CommandStation.class) != null)) { 050 commandStation = (SprogCommandStation) memo.get(jmri.CommandStation.class); 051 } else { 052 commandStation = (SprogCommandStation) jmri.InstanceManager.getNullableDefault(jmri.CommandStation.class); 053 } 054 055 } 056 057 private final SprogCommandStation commandStation; 058 059 DccLocoAddress address; 060 061 @Override 062 public LocoAddress getLocoAddress() { 063 return address; 064 } 065 066 /** 067 * Send the message to set the state of functions F0, F1, F2, F3, F4 by 068 * adding it to the S queue 069 */ 070 @Override 071 protected void sendFunctionGroup1() { 072 commandStation.function0Through4Packet(address, 073 getFunction(0), getFunctionMomentary(0), 074 getFunction(1), getFunctionMomentary(1), 075 getFunction(2), getFunctionMomentary(2), 076 getFunction(3), getFunctionMomentary(3), 077 getFunction(4), getFunctionMomentary(4)); 078 079 } 080 081 /** 082 * Send the message to set the state of functions F5, F6, F7, F8 by# adding 083 * it to the S queue 084 */ 085 @Override 086 protected void sendFunctionGroup2() { 087 commandStation.function5Through8Packet(address, 088 getFunction(5), getFunctionMomentary(5), 089 getFunction(6), getFunctionMomentary(6), 090 getFunction(7), getFunctionMomentary(7), 091 getFunction(8), getFunctionMomentary(8)); 092 } 093 094 /** 095 * Send the message to set the state of functions F9, F10, F11, F12 by 096 * adding it to the S queue 097 */ 098 @Override 099 protected void sendFunctionGroup3() { 100 commandStation.function9Through12Packet(address, 101 getFunction(9), getFunctionMomentary(9), 102 getFunction(10), getFunctionMomentary(10), 103 getFunction(11), getFunctionMomentary(11), 104 getFunction(12), getFunctionMomentary(12)); 105 } 106 107 /** 108 * Send the message to set the state of functions F13 - F20 109 * adding it to the S queue 110 */ 111 @Override 112 protected void sendFunctionGroup4() { 113 commandStation.function13Through20Packet(address, 114 getFunction(13), getFunctionMomentary(13), 115 getFunction(14), getFunctionMomentary(14), 116 getFunction(15), getFunctionMomentary(15), 117 getFunction(16), getFunctionMomentary(16), 118 getFunction(17), getFunctionMomentary(17), 119 getFunction(18), getFunctionMomentary(18), 120 getFunction(19), getFunctionMomentary(19), 121 getFunction(20), getFunctionMomentary(20)); 122 } 123 124 /** 125 * Send the message to set the state of functions F21 - F28 126 * adding it to the S queue 127 */ 128 @Override 129 protected void sendFunctionGroup5() { 130 commandStation.function21Through28Packet(address, 131 getFunction(21), getFunctionMomentary(21), 132 getFunction(22), getFunctionMomentary(22), 133 getFunction(23), getFunctionMomentary(23), 134 getFunction(24), getFunctionMomentary(24), 135 getFunction(25), getFunctionMomentary(25), 136 getFunction(26), getFunctionMomentary(26), 137 getFunction(27), getFunctionMomentary(27), 138 getFunction(28), getFunctionMomentary(28)); 139 } 140 141 /** 142 * Send the message to set the state of functions F29 - F36 143 * adding it to the S queue 144 */ 145 @Override 146 protected void sendFunctionGroup6() { 147 commandStation.function29Through36Packet(address, 148 getFunctionNoWarn(29), getFunctionMomentaryNoWarn(29), 149 getFunctionNoWarn(30), getFunctionMomentaryNoWarn(30), 150 getFunctionNoWarn(31), getFunctionMomentaryNoWarn(32), 151 getFunctionNoWarn(32), getFunctionMomentaryNoWarn(32), 152 getFunctionNoWarn(33), getFunctionMomentaryNoWarn(33), 153 getFunctionNoWarn(34), getFunctionMomentaryNoWarn(34), 154 getFunctionNoWarn(35), getFunctionMomentaryNoWarn(35), 155 getFunctionNoWarn(36), getFunctionMomentaryNoWarn(36)); 156 } 157 158 /** 159 * Send the message to set the state of functions F37 - F44 160 * adding it to the S queue 161 */ 162 @Override 163 protected void sendFunctionGroup7() { 164 commandStation.function37Through44Packet(address, 165 getFunctionNoWarn(37), getFunctionMomentaryNoWarn(37), 166 getFunctionNoWarn(38), getFunctionMomentaryNoWarn(38), 167 getFunctionNoWarn(39), getFunctionMomentaryNoWarn(39), 168 getFunctionNoWarn(40), getFunctionMomentaryNoWarn(40), 169 getFunctionNoWarn(41), getFunctionMomentaryNoWarn(41), 170 getFunctionNoWarn(42), getFunctionMomentaryNoWarn(42), 171 getFunctionNoWarn(43), getFunctionMomentaryNoWarn(43), 172 getFunctionNoWarn(44), getFunctionMomentaryNoWarn(44)); 173 } 174 175 /** 176 * Send the message to set the state of functions F45 - F52 177 * adding it to the S queue 178 */ 179 @Override 180 protected void sendFunctionGroup8() { 181 commandStation.function45Through52Packet(address, 182 getFunctionNoWarn(45), getFunctionMomentaryNoWarn(45), 183 getFunctionNoWarn(46), getFunctionMomentaryNoWarn(46), 184 getFunctionNoWarn(47), getFunctionMomentaryNoWarn(47), 185 getFunctionNoWarn(48), getFunctionMomentaryNoWarn(48), 186 getFunctionNoWarn(49), getFunctionMomentaryNoWarn(49), 187 getFunctionNoWarn(50), getFunctionMomentaryNoWarn(50), 188 getFunctionNoWarn(51), getFunctionMomentaryNoWarn(51), 189 getFunctionNoWarn(52), getFunctionMomentaryNoWarn(52)); 190 } 191 192 /** 193 * Send the message to set the state of functions F53 - F60 194 * adding it to the S queue 195 */ 196 @Override 197 protected void sendFunctionGroup9() { 198 commandStation.function53Through60Packet(address, 199 getFunctionNoWarn(53), getFunctionMomentaryNoWarn(53), 200 getFunctionNoWarn(54), getFunctionMomentaryNoWarn(54), 201 getFunctionNoWarn(55), getFunctionMomentaryNoWarn(55), 202 getFunctionNoWarn(56), getFunctionMomentaryNoWarn(56), 203 getFunctionNoWarn(57), getFunctionMomentaryNoWarn(57), 204 getFunctionNoWarn(58), getFunctionMomentaryNoWarn(58), 205 getFunctionNoWarn(59), getFunctionMomentaryNoWarn(59), 206 getFunctionNoWarn(60), getFunctionMomentaryNoWarn(60)); 207 } 208 209 /** 210 * Send the message to set the state of functions F61 - F68 211 * adding it to the S queue 212 */ 213 @Override 214 protected void sendFunctionGroup10() { 215 commandStation.function61Through68Packet(address, 216 getFunctionNoWarn(61), getFunctionMomentaryNoWarn(61), 217 getFunctionNoWarn(62), getFunctionMomentaryNoWarn(62), 218 getFunctionNoWarn(63), getFunctionMomentaryNoWarn(63), 219 getFunctionNoWarn(64), getFunctionMomentaryNoWarn(64), 220 getFunctionNoWarn(65), getFunctionMomentaryNoWarn(65), 221 getFunctionNoWarn(66), getFunctionMomentaryNoWarn(66), 222 getFunctionNoWarn(67), getFunctionMomentaryNoWarn(67), 223 getFunctionNoWarn(68), getFunctionMomentaryNoWarn(68)); 224 } 225 226 /** 227 * Set the speed and direction. 228 * <p> 229 * This intentionally skips the emergency stop value of 1 in 128 step mode 230 * and the stop and estop values 1-3 in 28 step mode. 231 * 232 * @param speed Number from 0 to 1; less than zero is emergency stop 233 */ 234 @Override 235 public synchronized void setSpeedSetting(float speed) { 236 SpeedStepMode mode = getSpeedStepMode(); 237 if (mode == SpeedStepMode.NMRA_DCC_28) { 238 // 28 step mode speed commands are 239 // stop, estop, stop, estop, 4, 5, ..., 31 240 float oldSpeed = this.speedSetting; 241 this.speedSetting = speed; 242 int value = Math.round((31 - 3) * speed); // -3 for rescale to avoid estopx2 and stop 243 if (this.speedSetting > 0 && value == 0) { 244 value = 1; // ensure non-zero input results in non-zero output 245 } 246 if (value > 0) { 247 value = value + 3; // skip estopx2 and stop 248 } 249 if (value > 31) { 250 value = 31; // max possible speed 251 } 252 if (value < 0) { 253 value = 1; // emergency stop 254 } 255 commandStation.setSpeed(SpeedStepMode.NMRA_DCC_28, address, value, isForward); 256 firePropertyChange(SPEEDSETTING, oldSpeed, this.speedSetting); 257 } else { 258 // 128 step mode speed commands are 259 // stop, estop, 2, 3, ..., 127 260 float oldSpeed = this.speedSetting; 261 this.speedSetting = speed; 262 int value = Math.round((127 - 1) * speed); // -1 for rescale to avoid estop 263 if (this.speedSetting > 0 && value == 0) { 264 value = 1; // ensure non-zero input results in non-zero output 265 } 266 if (value > 0) { 267 value = value + 1; // skip estop 268 } 269 if (value > 127) { 270 value = 127; // max possible speed 271 } 272 if (value < 0) { 273 value = 1; // emergency stop 274 } 275 commandStation.setSpeed(SpeedStepMode.NMRA_DCC_128, address, value, isForward); 276 firePropertyChange(SPEEDSETTING, oldSpeed, this.speedSetting); 277 } 278 record(speed); 279 } 280 281 @Override 282 public void setIsForward(boolean forward) { 283 boolean old = isForward; 284 isForward = forward; 285 synchronized(this) { 286 setSpeedSetting(speedSetting); // Update the speed setting 287 } 288 firePropertyChange(ISFORWARD, old, isForward); 289 } 290 291 @Override 292 public void throttleDispose() { 293 active = false; 294 commandStation.release(address); 295 finishRecord(); 296 } 297 298 private final static Logger log = LoggerFactory.getLogger(SprogCSThrottle.class); 299 300}