001package jmri.jmrix.zimo;
002
003import java.util.ArrayList;
004import java.util.List;
005
006import javax.annotation.Nonnull;
007
008import jmri.*;
009
010import org.slf4j.Logger;
011import org.slf4j.LoggerFactory;
012
013/**
014 * Programmer support for Zimo MXULF operations mode.  
015 * Provide an Ops Mode Programmer via a wrapper that works with the
016 * MX1Programmer object.
017 * <p>
018 * Functionally, this just creates packets to send via the MXULF.
019 *
020 * @see jmri.Programmer
021 * @author Bob Jacobsen Copyright (c) 2002
022 *
023 * Adapted by
024 * @author Alger Pike Copyright (c) 2022
025 * for use with zimo MXULF
026 *
027 */
028public class Mx1OpsModeProgrammer extends Mx1Programmer implements AddressedProgrammer {
029
030    int mAddress;
031    boolean mLongAddr;
032
033     public Mx1OpsModeProgrammer(int pAddress, boolean pLongAddr, Mx1TrafficController tc) {
034        super(tc);
035        mAddress = pAddress;
036        mLongAddr = pLongAddr;
037    }
038
039    /**
040     * {@inheritDoc}
041     *
042     * Types implemented here.
043     */
044    @Override
045    @Nonnull
046    public List<ProgrammingMode> getSupportedModes() {
047        List<ProgrammingMode> ret = new ArrayList<ProgrammingMode>();
048        ret.add(ProgrammingMode.OPSBYTEMODE);
049        return ret;
050    }
051
052    /**
053     * {@inheritDoc}
054     */
055    @Override
056    synchronized public void writeCV(String CVname, int val, jmri.ProgListener p) throws jmri.ProgrammerException {
057        final int CV = Integer.parseInt(CVname);
058        if (log.isDebugEnabled()) {
059            log.debug("writeCV {} listens {}", CV, p);
060        }
061        useProgrammer(p);
062        _progRead = false;
063        // set new state & save values
064        progState = INQUIRESENT;
065        _val = val;
066        _cv = CV;
067        // start the error timer
068        startShortTimer();
069        // format and send message to go to program mode
070        if (getMode() == ProgrammingMode.OPSBYTEMODE) {
071            if (tc.getProtocol() == Mx1Packetizer.ASCII) {
072                // Not supporting ASCII protocol for now.
073                throw new ProgrammerException();
074            } else {
075                tc.sendMx1Message(Mx1Message.getDecProgCmd(mAddress, _cv, val, true), this);
076            }
077        }
078    }
079
080    /**
081     * {@inheritDoc}
082     */
083    @Override
084    synchronized public void readCV(String CVname, jmri.ProgListener p) throws jmri.ProgrammerException {
085        final int CV = Integer.parseInt(CVname);
086
087        // The MXULF still can't read
088        if (tc.getAdapterMemo().getConnectionType() != Mx1SystemConnectionMemo.KLUG) {
089            log.debug("confirm CV={}", CV);
090            log.error("confirmCV not available in this protocol");
091            throw new ProgrammerException();
092        }
093
094        if (log.isDebugEnabled()) {
095            log.debug("readCV {} listens {}", CV, p);
096        }
097        useProgrammer(p);
098        _progRead = true;
099        // set new state & save values
100        progState = INQUIRESENT;
101        _val = -1; // Read
102        _cv = CV;
103        // start the error timer
104        startShortTimer();
105        // format and send message to go to program mode
106        if (getMode() == ProgrammingMode.OPSBYTEMODE) {
107            if (tc.getProtocol() == Mx1Packetizer.ASCII) {
108                // Not supporting ASCII protocol for now.
109                throw new ProgrammerException();
110            } else {
111                tc.sendMx1Message(Mx1Message.getDecProgCmd(mAddress, _cv, _val, true), this);
112            }
113        }
114    }
115
116    /** 
117     * {@inheritDoc}
118     */
119    @Override
120    public synchronized void confirmCV(String CV, int val, ProgListener p) throws ProgrammerException {
121        log.debug("confirm CV={}", CV);
122        log.error("confirmCV not available in this protocol");
123        throw new ProgrammerException();
124    }
125    
126    /** 
127     * {@inheritDoc}
128     *
129     * Can this ops-mode programmer read back values? The KLUG yes, the MXULF is WIP, so no
130     *
131     * @return true in case of KLUG, otherwise false
132     */
133    @Override
134    public boolean getCanRead() {
135        return tc.getAdapterMemo().getConnectionType() == Mx1SystemConnectionMemo.KLUG;
136    }
137
138    /** 
139     * {@inheritDoc}
140     */
141    @Override
142    public boolean getLongAddress() {
143        return mLongAddr;
144    }
145
146    /** 
147     * {@inheritDoc}
148     */
149    @Override
150    public int getAddressNumber() {
151        return mAddress;
152    }
153
154    /** 
155     * {@inheritDoc}
156     */
157    @Override
158    public String getAddress() {
159        return "" + getAddressNumber() + " " + getLongAddress();
160    }
161
162    private final static Logger log = LoggerFactory.getLogger(Mx1OpsModeProgrammer.class);
163
164}