001package jmri.jmrix.xpa;
002
003import jmri.Turnout;
004import jmri.implementation.AbstractTurnout;
005import org.slf4j.Logger;
006import org.slf4j.LoggerFactory;
007import javax.annotation.concurrent.GuardedBy;
008
009/**
010 * Xpa+Modem implementation of the Turnout interface.
011 * <p>
012 * Based on XNetTurnout.java
013 *
014 * @author Paul Bender Copyright (C) 2004
015 */
016public class XpaTurnout extends AbstractTurnout {
017
018    // Private data member to keep track of what turnout we control
019    private final int _number;
020    private final XpaTrafficController tc;
021
022    @GuardedBy("this")
023    protected int _mThrown = Turnout.THROWN;
024    @GuardedBy("this")
025    protected int _mClosed = Turnout.CLOSED;
026
027    /**
028     * Xpa turnouts use any address allowed as an accessory decoder address on
029     * the particular command station.
030     *
031     * @param number turnout number
032     * @param m      connection turnout is associated with
033     */
034    public XpaTurnout(int number, XpaSystemConnectionMemo m) {
035        super(m.getSystemPrefix() + "T" + number);
036        _number = number;
037        tc = m.getXpaTrafficController();
038    }
039
040    public int getNumber() {
041        return _number;
042    }
043
044    /**
045     * {@inheritDoc}
046     */
047    @Override
048    synchronized protected void forwardCommandChangeToLayout(int newState) {
049        XpaMessage m;
050        // sort out states
051        if ((newState & _mClosed) != 0) {
052            // first look for the double case, which we can't handle
053            if ((newState & _mThrown ) != 0) {
054                // this is the disaster case!
055                log.error("Cannot command both CLOSED and THROWN {}", newState);
056                return;
057            } else {
058                // send a CLOSED command
059                m = XpaMessage.getSwitchNormalMsg(_number);
060            }
061        } else {
062            // send a THROWN command (or CLOSED if inverted)
063            m = XpaMessage.getSwitchReverseMsg(_number);
064        }
065        tc.sendXpaMessage(m, null);
066    }
067
068    @Override
069    protected void turnoutPushbuttonLockout(boolean _pushButtonLockout) {
070        log.debug("Send command to {} Pushbutton PT{}", (_pushButtonLockout ? "Lock" : "Unlock"), _number);
071    }
072
073    /**
074     * {@inheritDoc}
075     */
076    @Override
077    synchronized public void setInverted(boolean inverted) {
078        log.debug("Inverting Turnout State for turnout {}", getSystemName() );
079        if (inverted) {
080            _mThrown = Turnout.CLOSED;
081            _mClosed = Turnout.THROWN;
082        } else {
083            _mThrown = Turnout.THROWN;
084            _mClosed = Turnout.CLOSED;
085        }
086        super.setInverted(inverted);
087    }
088
089    @Override
090    public boolean canInvert() {
091        return true;
092    }
093
094    private final static Logger log = LoggerFactory.getLogger(XpaTurnout.class);
095
096}