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}