001package jmri.jmrix.mrc;
002
003import java.util.ArrayList;
004import java.util.List;
005import javax.annotation.Nonnull;
006
007import jmri.ProgListener;
008import jmri.ProgrammerException;
009import jmri.ProgrammingMode;
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013/**
014 * Provide an Ops Mode Programmer via a wrapper what works with the MRC command
015 * station object.
016 * <p>
017 * Functionally, this just creates packets to send via the command station.
018 *
019 * @see jmri.Programmer
020 * @author Bob Jacobsen Copyright (C) 2002
021 * @author Ken Cameron Copyright (C) 2014
022 * @author Kevin Dickerson Copyright (C) 2014
023 */
024public class MrcOpsModeProgrammer extends MrcProgrammer implements jmri.AddressedProgrammer {
025
026    int mAddress;
027    boolean mLongAddr;
028
029    public MrcOpsModeProgrammer(MrcSystemConnectionMemo memo, int pAddress, boolean pLongAddr) {
030        super(memo);
031        log.debug("MRC ops mode programmer {} {}", pAddress, pLongAddr); // NOI18N
032        if (pLongAddr) {
033            addressLo = pAddress;
034            addressHi = pAddress >> 8;
035            addressHi = addressHi + 0xc0; //We add 0xc0 to the high byte.
036        } else {
037            addressLo = pAddress;
038        }
039    }
040
041    int addressLo = 0x00;
042    int addressHi = 0x00;
043
044    /**
045     * {@inheritDoc}
046     *
047     * Forward a write request to an ops-mode write operation
048     */
049    @Override
050    public synchronized void writeCV(String CVname, int val, ProgListener p) throws ProgrammerException {
051        final int CV = Integer.parseInt(CVname);
052        log.debug("write CV={} val={}", CV, val); // NOI18N
053        MrcMessage msg = MrcMessage.getPOM(addressLo, addressHi, CV, val);
054
055        useProgrammer(p);
056        _progRead = false;
057        progState = POMCOMMANDSENT;
058        _val = val;
059        _cv = CV;
060
061        // start the error timer
062        startShortTimer();
063
064        memo.getMrcTrafficController().sendMrcMessage(msg);
065    }
066
067    /**
068     * {@inheritDoc}
069     */
070    @Override
071    public synchronized void readCV(String CVname, ProgListener p) throws ProgrammerException {
072        final int CV = Integer.parseInt(CVname);
073        log.debug("read CV={}", CV);
074        log.error("readCV not available in this protocol"); // NOI18N
075        throw new ProgrammerException();
076    }
077
078    /**
079     * {@inheritDoc}
080     */
081    @Override
082    public synchronized void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException {
083        log.debug("confirm CV={}", CV);
084        log.error("confirmCV not available in this protocol"); // NOI18N
085        throw new ProgrammerException();
086    }
087
088    /**
089     * {@inheritDoc}
090     */
091    // add 200mSec between commands, so MRC command station queue doesn't get overrun
092    @Override
093    protected void notifyProgListenerEnd(int value, int status) {
094        log.debug("MrcOpsModeProgrammer adds 200mSec delay to response"); // NOI18N
095        try {
096            wait(200);
097        } catch (InterruptedException e) {
098            log.debug("unexpected exception", e); // NOI18N
099        }
100        super.notifyProgListenerEnd(value, status);
101    }
102
103    /**
104     * {@inheritDoc}
105     *
106     * Types implemented here.
107     */
108    @Override
109    @Nonnull
110    public List<ProgrammingMode> getSupportedModes() {
111        List<ProgrammingMode> ret = new ArrayList<ProgrammingMode>();
112        ret.add(ProgrammingMode.OPSBYTEMODE);
113        return ret;
114    }
115
116    /**
117     * {@inheritDoc}
118     *
119     * Can this ops-mode programmer read back values? For now, no, but maybe
120     * later.
121     *
122     * @return always false for now
123     */
124    @Override
125    public boolean getCanRead() {
126        return false;
127    }
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public boolean getLongAddress() {
134        return mLongAddr;
135    }
136
137    /**
138     * {@inheritDoc}
139     */
140    @Override
141    public int getAddressNumber() {
142        return mAddress;
143    }
144
145    /**
146     * {@inheritDoc}
147     */
148    @Override
149    public String getAddress() {
150        return "" + getAddressNumber() + " " + getLongAddress();
151    }
152
153    /**
154     * {@inheritDoc}
155     *
156     * Ops-mode programming doesn't put the command station in programming mode,
157     * so we don't have to send an exit-programming command at end. Therefore,
158     * this routine does nothing except to replace the parent routine that does
159     * something.
160     */
161    @Override
162    void cleanup() {
163    }
164
165    // initialize logging
166    private final static Logger log = LoggerFactory.getLogger(MrcOpsModeProgrammer.class);
167
168}