001package jmri.jmrix.easydcc;
002
003import java.util.ArrayList;
004import java.util.List;
005import javax.annotation.Nonnull;
006
007import jmri.AddressedProgrammer;
008import jmri.NmraPacket;
009import jmri.ProgListener;
010import jmri.ProgrammerException;
011import jmri.ProgrammingMode;
012
013/**
014 * Provide an Ops Mode Programmer via a wrapper that works with the
015 * EasyDccCommandStation 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 */
022public class EasyDccOpsModeProgrammer extends EasyDccProgrammer implements AddressedProgrammer {
023
024    int mAddress;
025    boolean mLongAddr;
026
027    public EasyDccOpsModeProgrammer(int pAddress, boolean pLongAddr, EasyDccSystemConnectionMemo memo) {
028        super(memo);
029        mAddress = pAddress;
030        mLongAddr = pLongAddr;
031    }
032
033    /** 
034     * {@inheritDoc}
035     *
036     * Forward a write request to an ops-mode write operation.
037     */
038    @Override
039    public synchronized void writeCV(String CVname, int val, ProgListener p) throws ProgrammerException {
040        final int CV = Integer.parseInt(CVname);
041        log.debug("write CV={} val={}", CV, val);
042        // create the message and fill it,
043        byte[] contents = NmraPacket.opsCvWriteByte(mAddress, mLongAddr, CV, val);
044        EasyDccMessage msg = new EasyDccMessage(4 + 3 * contents.length);
045        msg.setOpCode('S');
046        msg.setElement(1, ' ');
047        msg.setElement(2, '0');
048        msg.setElement(3, '5');
049        int j = 4;
050        for (int i = 0; i < contents.length; i++) {
051            msg.setElement(j++, ' ');
052            msg.addIntAsTwoHex(contents[i] & 0xFF, j);
053            j = j + 2;
054        }
055
056        // record state.  COMMANDSENT is just waiting for a reply...
057        useProgrammer(p);
058        _progRead = false;
059        progState = COMMANDSENT;
060        _val = val;
061        _cv = CV;
062
063        // start the error timer
064        startShortTimer();
065
066        // send it
067        tc.sendEasyDccMessage(msg, this);
068    }
069
070    /** 
071     * {@inheritDoc}
072     */
073    @Override
074    public synchronized void readCV(String CVname, ProgListener p) throws ProgrammerException {
075        final int CV = Integer.parseInt(CVname);
076        log.debug("read CV={}", CV);
077        log.error("readCV not available in this protocol");
078        throw new ProgrammerException();
079    }
080
081    /** 
082     * {@inheritDoc}
083     */
084    @Override
085    public synchronized void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException {
086        log.debug("confirm CV={}", CV);
087        log.error("confirmCV not available in this protocol");
088        throw new ProgrammerException();
089    }
090
091    /** 
092     * {@inheritDoc}
093     */
094    @Override
095    @Nonnull
096    public List<ProgrammingMode> getSupportedModes() {
097        List<ProgrammingMode> ret = new ArrayList<ProgrammingMode>();
098        ret.add(ProgrammingMode.OPSBYTEMODE);
099        return ret;
100    }
101
102    /** 
103     * {@inheritDoc}
104     *
105     * Can this ops-mode programmer read back values? For now, no, but maybe
106     * later.
107     *
108     * @return always false for now
109     */
110    @Override
111    public boolean getCanRead() {
112        return false;
113    }
114
115    /** 
116     * {@inheritDoc}
117     */
118    @Override
119    public boolean getLongAddress() {
120        return mLongAddr;
121    }
122
123    /** 
124     * {@inheritDoc}
125     */
126    @Override
127    public int getAddressNumber() {
128        return mAddress;
129    }
130
131    /** 
132     * {@inheritDoc}
133     */
134    @Override
135    public String getAddress() {
136        return "" + getAddressNumber() + " " + getLongAddress();
137    }
138
139    /** 
140     * {@inheritDoc}
141     *
142     * Ops-mode programming doesn't put the command station in programming mode,
143     * so we don't have to send an exit-programming command at end. Therefore,
144     * this routine does nothing except to replace the parent routine that does
145     * something.
146     */
147    @Override
148    void cleanup() {
149    }
150
151    // initialize logging
152    private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EasyDccOpsModeProgrammer.class);
153
154}