001package jmri.jmrix.direct; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004import jmri.CommandStation; 005import jmri.DccLocoAddress; 006import jmri.LocoAddress; 007import jmri.SystemConnectionMemo; 008import jmri.jmrix.AbstractThrottle; 009 010/** 011 * An implementation of DccThrottle with code specific to a Direct serial 012 * connection. 013 * 014 * @author Bob Jacobsen Copyright (C) 2004 015 */ 016public class Throttle extends AbstractThrottle { 017 018 private final CommandStation tcl; 019 020 /** 021 * Constructor. 022 * @param address loco address. 023 * @param tc system connection traffic controller. 024 * @param memo the system connection. 025 */ 026 public Throttle(DccLocoAddress address, CommandStation tc, SystemConnectionMemo memo) { 027 super(memo); 028 tcl = tc; 029 030 // cache settings. 031 synchronized(this) { 032 this.speedSetting = 0; 033 } 034 // Functions default to false 035 this.address = address; 036 this.isForward = true; 037 } 038 039 @Deprecated (since="5.13.3", forRemoval=true) 040 public Throttle(DccLocoAddress address, CommandStation tc) { 041 this(address, tc, jmri.InstanceManager.getDefault(SystemConnectionMemo.class)); 042 } 043 044 DccLocoAddress address; 045 046 @Override 047 public LocoAddress getLocoAddress() { 048 return address; 049 } 050 051 /** 052 * Send the message to set the state of functions F0, F1, F2, F3, F4. 053 */ 054 @Override 055 protected void sendFunctionGroup1() { 056 byte[] result = jmri.NmraPacket.function0Through4Packet(address.getNumber(), address.isLongAddress(), 057 getFunction(0), getFunction(1), getFunction(2), getFunction(3), getFunction(4)); 058 059 tcl.sendPacket(result, 1); 060 } 061 062 /** 063 * Send the message to set the state of functions F5, F6, F7, F8. 064 */ 065 @Override 066 protected void sendFunctionGroup2() { 067 068 byte[] result = jmri.NmraPacket.function5Through8Packet(address.getNumber(), address.isLongAddress(), 069 getFunction(5), getFunction(6), getFunction(7), getFunction(8)); 070 071 tcl.sendPacket(result, 1); 072 } 073 074 /** 075 * Send the message to set the state of functions F9, F10, F11, F12. 076 */ 077 @Override 078 protected void sendFunctionGroup3() { 079 080 byte[] result = jmri.NmraPacket.function9Through12Packet(address.getNumber(), address.isLongAddress(), 081 getFunction(9), getFunction(10), getFunction(11), getFunction(12)); 082 083 tcl.sendPacket(result, 1); 084 } 085 086 /** 087 * Set the speed and direction. 088 * <p> 089 * This intentionally skips the emergency stop value of 1. 090 * 091 * @param speed Number from 0 to 1; less than zero is emergency stop 092 */ 093 @SuppressFBWarnings(value = "FE_FLOATING_POINT_EQUALITY") // OK to compare floating point 094 @Override 095 public synchronized void setSpeedSetting(float speed) { 096 float oldSpeed = this.speedSetting; 097 this.speedSetting = speed; 098 int value = (int) ((127 - 1) * speed); // -1 for rescale to avoid estop 099 if (value > 0) { 100 value = value + 1; // skip estop 101 } 102 if (value > 127) { 103 value = 127; // max possible speed 104 } 105 if (value < 0) { 106 value = 1; // emergency stop 107 } 108 String step = "" + value; 109 110 Message m = new Message(1 + step.length()); 111 int i = 0; // message index counter 112 if (isForward) { 113 m.setElement(i++, '>'); 114 } else { 115 m.setElement(i++, '<'); 116 } 117 118 for (int j = 0; j < step.length(); j++) { 119 m.setElement(i++, step.charAt(j)); 120 } 121 firePropertyChange(SPEEDSETTING, oldSpeed, this.speedSetting); 122 record(speed); 123 // tcl.sendMessage(m, null); 124 } 125 126 @Override 127 public void setIsForward(boolean forward) { 128 boolean old = isForward; 129 isForward = forward; 130 synchronized(this) { 131 setSpeedSetting(speedSetting); // send the command 132 } 133 firePropertyChange(ISFORWARD, old, isForward); 134 } 135 136 @Override 137 public void throttleDispose() { 138 finishRecord(); 139 } 140 141 // initialize logging 142 // private final static Logger log = LoggerFactory.getLogger(Throttle.class); 143 144}