001package jmri.jmrix.easydcc;
002
003import jmri.DccLocoAddress;
004import org.slf4j.Logger;
005import org.slf4j.LoggerFactory;
006
007/**
008 * Encodes a message to an EasyDCC command station.
009 * <p>
010 * The {@link EasyDccReply} class handles the response from the command station.
011 *
012 * @author Bob Jacobsen Copyright (C) 2001, 2004
013 */
014public class EasyDccMessage extends jmri.jmrix.AbstractMRMessage {
015
016    public EasyDccMessage() {
017        super();
018    }
019
020    // create a new one
021    public EasyDccMessage(int i) {
022        super(i);
023    }
024
025    // copy one
026    public EasyDccMessage(EasyDccMessage m) {
027        super(m);
028    }
029
030    // from String
031    public EasyDccMessage(String s) {
032        super(s);
033    }
034
035    // diagnose format
036    public boolean isKillMain() {
037        return getOpCode() == 'K';
038    }
039
040    public boolean isEnableMain() {
041        return getOpCode() == 'E';
042    }
043
044    // static methods to return a formatted message
045    static public EasyDccMessage getEnableMain() {
046        EasyDccMessage m = new EasyDccMessage(1);
047        m.setBinary(false);
048        m.setOpCode('E');
049        return m;
050    }
051
052    static public EasyDccMessage getKillMain() {
053        EasyDccMessage m = new EasyDccMessage(1);
054        m.setBinary(false);
055        m.setOpCode('K');
056        return m;
057    }
058
059    /**
060     * Get a static message to add a locomotive to a Standard Consist
061     * in the normal direction.
062     *
063     * @param ConsistAddress  a consist address in the range 1-255
064     * @param LocoAddress  a jmri.DccLocoAddress object representing the 
065     * locomotive to add
066     * @return an EasyDccMessage of the form GN cc llll 
067     */
068    static public EasyDccMessage getAddConsistNormal(int ConsistAddress, DccLocoAddress LocoAddress) {
069        EasyDccMessage m = new EasyDccMessage(10);
070        m.setBinary(false);
071        m.setOpCode('G');
072        m.setElement(1, 'N');
073        m.setElement(2, ' ');
074        m.addIntAsTwoHex(ConsistAddress, 3);
075        m.setElement(5, ' ');
076        m.addIntAsFourHex(LocoAddress.getNumber(), 6);
077        return m;
078    }
079
080    /**
081     * Get a static message to add a locomotive to a Standard Consist in
082     * the reverse direction.
083     *
084     * @param ConsistAddress  a consist address in the range 1-255
085     * @param LocoAddress  a jmri.DccLocoAddress object representing the 
086     * locomotive to add
087     * @return an EasyDccMessage of the form GS cc llll 
088     */
089    static public EasyDccMessage getAddConsistReverse(int ConsistAddress, DccLocoAddress LocoAddress) {
090        EasyDccMessage m = new EasyDccMessage(10);
091        m.setBinary(false);
092        m.setOpCode('G');
093        m.setElement(1, 'R');
094        m.setElement(2, ' ');
095        m.addIntAsTwoHex(ConsistAddress, 3);
096        m.setElement(5, ' ');
097        m.addIntAsFourHex(LocoAddress.getNumber(), 6);
098        return m;
099    }
100
101    /**
102     * Get a static message to subtract a locomotive from a Standard Consist.
103     *
104     * @param ConsistAddress  a consist address in the range 1-255
105     * @param LocoAddress  a jmri.DccLocoAddress object representing the 
106     * locomotive to remove
107     * @return an EasyDccMessage of the form GS cc llll 
108     */
109    static public EasyDccMessage getSubtractConsist(int ConsistAddress, DccLocoAddress LocoAddress) {
110        EasyDccMessage m = new EasyDccMessage(10);
111        m.setBinary(false);
112        m.setOpCode('G');
113        m.setElement(1, 'S');
114        m.setElement(2, ' ');
115        m.addIntAsTwoHex(ConsistAddress, 3);
116        m.setElement(5, ' ');
117        m.addIntAsFourHex(LocoAddress.getNumber(), 6);
118        return m;
119    }
120
121    /**
122     * Get a static message to delete a Standard Consist.
123     *
124     * @param ConsistAddress  a consist address in the range 1-255
125     * @return an EasyDccMessage of the form GK cc 
126     */
127    static public EasyDccMessage getKillConsist(int ConsistAddress) {
128        EasyDccMessage m = new EasyDccMessage(5);
129        m.setBinary(false);
130        m.setOpCode('G');
131        m.setElement(1, 'K');
132        m.setElement(2, ' ');
133        m.addIntAsTwoHex(ConsistAddress, 3);
134        return m;
135    }
136
137    /**
138     * Get a static message to display a Standard Consist.
139     *
140     * @param ConsistAddress  a consist address in the range 1-255
141     * @return an EasyDccMessage of the form GD cc 
142     */
143    static public EasyDccMessage getDisplayConsist(int ConsistAddress) {
144        EasyDccMessage m = new EasyDccMessage(5);
145        m.setBinary(false);
146        m.setOpCode('G');
147        m.setElement(1, 'D');
148        m.setElement(2, ' ');
149        m.addIntAsTwoHex(ConsistAddress, 3);
150        return m;
151    }
152
153    static public EasyDccMessage getProgMode() {
154        EasyDccMessage m = new EasyDccMessage(1);
155        m.setBinary(false);
156        m.setOpCode('M');
157        return m;
158    }
159
160    static public EasyDccMessage getExitProgMode() {
161        EasyDccMessage m = new EasyDccMessage(1);
162        m.setBinary(false);
163        m.setOpCode('X');
164        return m;
165    }
166
167    static public EasyDccMessage getReadPagedCV(int cv) { //R xxx
168        EasyDccMessage m = new EasyDccMessage(5);
169        m.setBinary(false);
170        m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE);
171        m.setTimeout(LONG_TIMEOUT);
172        m.setOpCode('R');
173        m.setElement(1, ' ');
174        m.addIntAsThreeHex(cv, 2);
175        return m;
176    }
177
178    static public EasyDccMessage getWritePagedCV(int cv, int val) { //P xxx xx
179        EasyDccMessage m = new EasyDccMessage(8);
180        m.setBinary(false);
181        m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE);
182        m.setTimeout(LONG_TIMEOUT);
183        m.setOpCode('P');
184        m.setElement(1, ' ');
185        m.addIntAsThreeHex(cv, 2);
186        m.setElement(5, ' ');
187        m.addIntAsTwoHex(val, 6);
188        return m;
189    }
190
191    static public EasyDccMessage getReadRegister(int reg) { //Vx
192        if (reg > 8) {
193            log.error("register number too large: {}", reg);
194        }
195        EasyDccMessage m = new EasyDccMessage(2);
196        m.setBinary(false);
197        m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE);
198        m.setTimeout(LONG_TIMEOUT);
199        m.setOpCode('V');
200        String s = "" + reg;
201        m.setElement(1, s.charAt(s.length() - 1));
202        return m;
203    }
204
205    static public EasyDccMessage getWriteRegister(int reg, int val) { //Sx xx
206        if (reg > 8) {
207            log.error("register number too large: {}", reg);
208        }
209        EasyDccMessage m = new EasyDccMessage(5);
210        m.setBinary(false);
211        m.setNeededMode(jmri.jmrix.AbstractMRTrafficController.PROGRAMINGMODE);
212        m.setTimeout(LONG_TIMEOUT);
213        m.setOpCode('S');
214        String s = "" + reg;
215        m.setElement(1, s.charAt(s.length() - 1));
216        m.setElement(2, ' ');
217        m.addIntAsTwoHex(val, 3);
218        return m;
219    }
220
221    static protected final int LONG_TIMEOUT = 180000; // e.g. for programming options
222
223    private final static Logger log = LoggerFactory.getLogger(EasyDccMessage.class);
224
225}