001package jmri.jmrit.roster;
002
003import org.slf4j.Logger;
004import org.slf4j.LoggerFactory;
005
006/**
007 * Interact with a programmer to identify the
008 * {@link jmri.jmrit.roster.RosterEntry} for a loco on the programming track.
009 * <p>
010 * This is a class (instead of a {@link jmri.jmrit.roster.Roster} member
011 * function) to simplify use of ProgListener callbacks. It is abstract as we
012 * expect that local classes will define the message and done members.
013 *
014 * @author Bob Jacobsen Copyright (C) 2001, 2015
015 * @see jmri.jmrit.symbolicprog.CombinedLocoSelPane
016 * @see jmri.jmrit.symbolicprog.NewLocoSelPane
017 */
018abstract public class IdentifyLoco extends jmri.jmrit.AbstractIdentify {
019
020    public IdentifyLoco(jmri.Programmer programmer) {
021        super(programmer);
022    }
023
024    protected boolean shortAddr;
025    private int cv17val;
026    private int cv18val;
027    protected int cv7val;
028    protected int cv8val;
029    int address = -1;
030
031    // steps of the identification state machine
032    @Override
033    public boolean test1() {
034        // request contents of CV 29
035        statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("READ CV 29"));
036        readCV("29");
037        return false;
038    }
039
040    @Override
041    public boolean test2(int value) {
042        // check for long address vs short address
043        if ((value & 0x20) != 0) {
044            // long address needed
045            shortAddr = false;
046            statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("LONG ADDRESS - READ CV 17"));
047            readCV("17");
048        } else {
049            // short - read address
050            shortAddr = true;
051            statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("SHORT ADDRESS - READ CV 1"));
052            readCV("1");
053        }
054        return false;
055    }
056
057    @Override
058    public boolean test3(int value) {
059        // check if we're reading short or long
060        if (shortAddr) {
061            // short - this is the address
062            address = value;
063            statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("READMFG"));
064            readCV("7");
065            return false;
066        } else {
067            // long - need CV18 also
068            cv17val = value;
069            statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("LONG ADDRESS - READ CV 18"));
070            readCV("18");
071            return false;
072        }
073    }
074
075    @Override
076    public boolean test4(int value) {
077        // only for long address
078        if (shortAddr) {
079            cv7val = value;
080            statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("READMFGVER"));
081            readCV("8");
082            return false;
083        }
084
085        // value is CV18, calculate address
086        cv18val = value;
087        address = (cv17val & 0x3f) * 256 + cv18val;
088        statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("READMFG"));
089        readCV("7");
090        return false;
091    }
092
093    @Override
094    public boolean test5(int value) {
095        if (shortAddr) {
096            cv8val = value;
097            //We have read manufacturer and decoder version details
098            return true;
099        }
100        statusUpdate(java.util.ResourceBundle.getBundle("jmri/jmrit/roster/JmritRosterBundle").getString("READMFGVER"));
101        readCV("8");
102        cv7val = value;
103        return false;
104    }
105
106    @Override
107    public boolean test6(int value) {
108        if (shortAddr) {
109            log.error("test4 routine reached in short address mode");
110            return true;
111        }
112        cv8val = value;
113        return true;
114    }
115
116    @Override
117    public boolean test7(int value) {
118        log.error("unexpected step 7 reached with value: {}", value);
119        return true;
120    }
121
122    @Override
123    public boolean test8(int value) {
124        log.error("unexpected step 8 reached with value: {}", value);
125        return true;
126    }
127    @Override
128    public boolean test9(int value) {
129        log.error("unexpected step 9 reached with value: {}", value);
130        return true;
131    }
132
133    @Override
134    protected void statusUpdate(String s) {
135        message(s);
136        if (s.equals("Done")) {
137            done(address);
138        } else if (log.isDebugEnabled()) {
139            log.debug("received status: {}", s);
140        }
141    }
142
143    abstract protected void done(int address);
144
145    abstract protected void message(String m);
146
147    // initialize logging
148    private final static Logger log = LoggerFactory.getLogger(IdentifyLoco.class);
149
150}