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