001package jmri.jmrix.direct;
002
003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
004import javax.annotation.Nonnull;
005import jmri.ProgrammingMode;
006import org.slf4j.Logger;
007import org.slf4j.LoggerFactory;
008
009/**
010 * Encodes a message for Direct DCC.
011 *
012 * @author Bob Jacobsen Copyright (C) 2004
013 */
014public class Message extends jmri.jmrix.AbstractMRMessage {
015
016    // create a new one
017    public Message(int i) {
018        if (i < 1) {
019            log.error("invalid length in call to ctor");
020        }
021        _nDataChars = i;
022        _dataChars = new int[i];
023    }
024
025    // copy one
026    public Message(@Nonnull Message m) {
027        _nDataChars = m._nDataChars;
028        _dataChars = new int[_nDataChars];
029        System.arraycopy(m._dataChars, 0, _dataChars, 0, _nDataChars);
030    }
031
032    @Override
033    public void setOpCode(int i) {
034        _dataChars[0] = i;
035    }
036
037    @Override
038    public int getOpCode() {
039        return _dataChars[0];
040    }
041
042    @Override
043    public String getOpCodeHex() {
044        return "0x" + Integer.toHexString(getOpCode());
045    }
046
047    // accessors to the bulk data
048    @Override
049    public int getNumDataElements() {
050        return _nDataChars;
051    }
052
053    @Override
054    public int getElement(int n) {
055        return _dataChars[n];
056    }
057
058    @Override
059    public void setElement(int n, int v) {
060        _dataChars[n] = v & 0x7F;
061    }
062
063    @Override
064    public String toString() {
065        StringBuilder s = new StringBuilder("");
066        for (int i = 0; i < _nDataChars; i++) {
067            s.append((char) _dataChars[i]);
068        }
069        return s.toString();
070    }
071
072    // diagnose format
073    public boolean isKillMain() {
074        return getOpCode() == '-';
075    }
076
077    public boolean isEnableMain() {
078        return getOpCode() == '+';
079    }
080
081    // static methods to return a formatted message
082
083    static public Message getEnableMain() {
084        log.error("getEnableMain doesn't have a reasonable implementation yet");
085        return null;
086    }
087
088    static public Message getKillMain() {
089        log.error("getKillMain doesn't have a reasonable implementation yet");
090        return null;
091    }
092
093    static public Message getProgMode() {
094        log.error("getProgMode doesn't have a reasonable implementation yet");
095        return null;
096    }
097
098    static public Message getExitProgMode() {
099        log.error("getExitProgMode doesn't have a reasonable implementation yet");
100        return null;
101    }
102
103    static public Message getReadCV(int cv, ProgrammingMode mode) {
104        Message m = new Message(5);
105        if (mode.equals(ProgrammingMode.PAGEMODE)) {
106            m.setOpCode('V');
107        } else { // Bit direct mode
108            m.setOpCode('C');
109        }
110        addSpace(m, 1);
111        addIntAsThree(cv, m, 2);
112        return m;
113    }
114
115    static public Message getWriteCV(int cv, int val, ProgrammingMode mode) {
116        Message m = new Message(9);
117        if (mode.equals(ProgrammingMode.PAGEMODE)) {
118            m.setOpCode('V');
119        } else { // Bit direct mode
120            m.setOpCode('C');
121        }
122        addSpace(m, 1);
123        addIntAsThree(cv, m, 2);
124        addSpace(m, 5);
125        addIntAsThree(val, m, 6);
126        return m;
127    }
128
129    static public Message getReadRegister(int reg) { //Vx
130        return null;
131    }
132
133    static public Message getWriteRegister(int reg, int val) { //Sx xx
134        return null;
135    }
136
137    private static String addSpace(Message m, int offset) {
138        String s = " ";
139        m.setElement(offset, ' ');
140        return s;
141    }
142
143    @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification="was previously marked with @SuppressWarnings, reason unknown")
144    private static String addIntAsTwo(int val, Message m, int offset) {
145        String s = "" + val;
146        if (s.length() != 2) {
147            s = "0" + s;  // handle <10
148        }
149        m.setElement(offset, s.charAt(0));
150        m.setElement(offset + 1, s.charAt(1));
151        return s;
152    }
153
154    private static String addIntAsThree(int val, Message m, int offset) {
155        String s = "" + val;
156        if (s.length() != 3) {
157            s = "0" + s;  // handle <10
158        }
159        if (s.length() != 3) {
160            s = "0" + s;  // handle <100
161        }
162        m.setElement(offset, s.charAt(0));
163        m.setElement(offset + 1, s.charAt(1));
164        m.setElement(offset + 2, s.charAt(2));
165        return s;
166    }
167
168    // static methods to recognize a message
169
170    public int getAddr() {
171        return getElement(0) & 0x7F;
172    }
173
174    private final static Logger log = LoggerFactory.getLogger(Message.class);
175
176}