001package jmri.jmrix.marklin;
002
003
004/**
005 * Encodes a message to a Marklin command station.
006 * <p>
007 * The {@link MarklinReply} class handles the response from the command station.
008 *
009 * @author Kevin Dickerson Copyright (C) 2001, 2008
010 */
011/*Packages of length 13 are interpreted as can-bus packages: 4 bytes
012 Can-bus-ID (BigEndian or network order), 1-byte length and 8 bytes of data, if necessary with null bytes
013 to fill in are.*/
014
015/*The message ID is divided into the areas of lower priority (priority), command (command), response
016 and hash. The communication is based on the following format:
017 Prio - 2 +2bit
018 Command 8 bit
019 Resp - 1 bit
020 Hash - 16bit
021 DLC - 4bit (ie CAN message length)
022 CAN message 8 BYTES
023 Can Message Bytes 0 to 3 are the address bytes, with byte 0 High, byte 3 low
024 */
025public class MarklinMessage extends jmri.jmrix.AbstractMRMessage {
026
027    static int MY_UID = 0x12345678;
028
029    MarklinMessage() {
030        _dataChars = new int[13];
031        _nDataChars = 13;
032        setBinary(true);
033        for (int i = 0; i < 13; i++) {
034            _dataChars[i] = 0x00;
035        }
036    }
037
038    // create a new one from an array
039    public MarklinMessage(int[] d) {
040        this();
041        for (int i = 0; i < d.length; i++) {
042            _dataChars[i] = d[i];
043        }
044    }
045
046    // create a new one from a byte array, as a service
047    public MarklinMessage(byte[] d) {
048        this();
049        for (int i = 0; i < d.length; i++) {
050            _dataChars[i] = d[i] & 0xFF;
051        }
052    }
053
054    // create a new one
055    public MarklinMessage(int i) {
056        this();
057    }
058
059    // copy one
060    public MarklinMessage(MarklinMessage m) {
061        super(m);
062    }
063
064    // from String
065    /*public  MarklinMessage(String m) {
066     super(m);
067     }*/
068    // static methods to return a formatted message
069    static public MarklinMessage getEnableMain() {
070        MarklinMessage m = new MarklinMessage();
071        m.setElement(0, MarklinConstants.SYSCOMMANDSTART & 0xFF);
072        m.setElement(1, 0x00 & 0xFF);
073        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
074        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
075        m.setElement(4, 0x05 & 0xFF); //five bytes;
076        //5, 6, 7, 8 Address but this is a global command
077        m.setElement(9, MarklinConstants.CMDGOSYS & 0xFF); //Turn main on 0x01
078        return m;
079    }
080
081    static public MarklinMessage getKillMain() {
082        MarklinMessage m = new MarklinMessage();
083        m.setElement(0, MarklinConstants.SYSCOMMANDSTART & 0xFF);
084        m.setElement(1, 0x00 & 0xFF);
085        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
086        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
087        m.setElement(4, 0x05 & 0xFF); //five bytes;
088        //5, 6, 7, 8 Address but this is a global command
089        m.setElement(9, MarklinConstants.CMDSTOPSYS & 0xFF); //Turn main off 0x00
090        return m;
091    }
092
093    //static public MarklinMessage get
094    static public MarklinMessage getSetTurnout(int addr, int state, int power) {
095        MarklinMessage m = new MarklinMessage();
096        m.setElement(0, (MarklinConstants.ACCCOMMANDSTART >> 7) & 0xFF);
097        m.setElement(1, (MarklinConstants.ACCCOMMANDSTART << 1) & 0xFF);
098        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
099        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
100        m.setElement(4, 0x06 & 0xFF); //five bytes;
101        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
102        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
103        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
104        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
105        m.setElement(9, state & 0xff);
106        m.setElement(10, power & 0xff);
107        return m;
108    }
109
110    static public MarklinMessage getQryLocoSpeed(int addr) {
111        MarklinMessage m = new MarklinMessage();
112        m.setElement(0, (MarklinConstants.LOCOSPEED >> 7) & 0xFF);
113        m.setElement(1, (MarklinConstants.LOCOSPEED << 1) & 0xFF);
114        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
115        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
116        m.setElement(4, 0x04 & 0xFF);
117        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
118        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
119        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
120        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
121        return m;
122    }
123
124    static public MarklinMessage setLocoSpeed(int addr, int speed) {
125        MarklinMessage m = new MarklinMessage();
126        m.setElement(0, (MarklinConstants.LOCOSPEED >> 7) & 0xFF);
127        m.setElement(1, (MarklinConstants.LOCOSPEED << 1) & 0xFF);
128        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
129        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
130        m.setElement(4, 0x06 & 0xFF);
131        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
132        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
133        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
134        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
135        m.setElement(9, (speed >> 8) & 0xff);
136        m.setElement(10, speed & 0xff);
137        return m;
138    }
139
140    static public MarklinMessage setLocoEmergencyStop(int addr) {
141        MarklinMessage m = new MarklinMessage();
142        m.setElement(0, MarklinConstants.SYSCOMMANDSTART & 0xFF);
143        m.setElement(1, 0x00 & 0xFF);
144        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
145        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
146        m.setElement(4, 0x05 & 0xFF); //five bytes;
147        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
148        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
149        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
150        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
151        m.setElement(9, MarklinConstants.LOCOEMERGENCYSTOP & 0xFF);
152        return m;
153    }
154
155    static public MarklinMessage setLocoSpeedSteps(int addr, int step) {
156        MarklinMessage m = new MarklinMessage();
157        m.setElement(0, MarklinConstants.SYSCOMMANDSTART & 0xFF);
158        m.setElement(1, 0x00 & 0xFF);
159        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
160        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
161        m.setElement(4, 0x05 & 0xFF); //five bytes;
162        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
163        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
164        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
165        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
166        m.setElement(9, 0x05 & 0xFF);
167        m.setElement(10, step & 0xFF);
168        return m;
169    }
170
171    static public MarklinMessage getQryLocoDirection(int addr) {
172        MarklinMessage m = new MarklinMessage();
173        m.setElement(0, (MarklinConstants.LOCODIRECTION >> 7) & 0xFF);
174        m.setElement(1, (MarklinConstants.LOCODIRECTION << 1) & 0xFF);
175        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
176        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
177        m.setElement(4, 0x04 & 0xFF);
178        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
179        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
180        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
181        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
182        return m;
183    }
184
185    static public MarklinMessage setLocoDirection(int addr, int dir) {
186        MarklinMessage m = new MarklinMessage();
187        m.setElement(0, (MarklinConstants.LOCODIRECTION >> 7) & 0xFF);
188        m.setElement(1, (MarklinConstants.LOCODIRECTION << 1) & 0xFF);
189        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
190        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
191        m.setElement(4, 0x05 & 0xFF);
192        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
193        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
194        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
195        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
196        m.setElement(9, dir & 0xff);
197        return m;
198    }
199
200    static public MarklinMessage getQryLocoFunction(int addr, int funct) {
201        MarklinMessage m = new MarklinMessage();
202        m.setElement(0, (MarklinConstants.LOCOFUNCTION >> 7) & 0xFF);
203        m.setElement(1, (MarklinConstants.LOCOFUNCTION << 1) & 0xFF);
204        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
205        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
206        m.setElement(4, 0x05 & 0xFF);
207        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
208        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
209        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
210        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
211        m.setElement(9, (funct) & 0xFF);
212        return m;
213    }
214
215    static public MarklinMessage setLocoFunction(int addr, int funct, int state) {
216        MarklinMessage m = new MarklinMessage();
217        m.setElement(0, (MarklinConstants.LOCOFUNCTION >> 7) & 0xFF);
218        m.setElement(1, (MarklinConstants.LOCOFUNCTION << 1) & 0xFF);
219        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
220        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
221        m.setElement(4, 0x06 & 0xFF);
222        m.setElement(MarklinConstants.CANADDRESSBYTE1, (addr >> 24) & 0xFF);
223        m.setElement(MarklinConstants.CANADDRESSBYTE2, (addr >> 16) & 0xFF);
224        m.setElement(MarklinConstants.CANADDRESSBYTE3, (addr >> 8) & 0xFF);
225        m.setElement(MarklinConstants.CANADDRESSBYTE4, (addr) & 0xFF);
226        m.setElement(9, funct & 0xff);
227        m.setElement(10, state & 0xff);
228        m.getAddress();
229        return m;
230    }
231
232    static public MarklinMessage sensorPollMessage(int module) {
233        MarklinMessage m = new MarklinMessage();
234        m.setElement(0, (MarklinConstants.FEECOMMANDSTART >> 7) & 0xFF);
235        m.setElement(1, (MarklinConstants.FEECOMMANDSTART << 1) & 0xFF);
236        m.setElement(2, MarklinConstants.HASHBYTE1 & 0xFF);
237        m.setElement(3, MarklinConstants.HASHBYTE2 & 0xFF);
238        m.setElement(4, 0x05 & 0xFF); //five bytes;
239        m.setElement(MarklinConstants.CANADDRESSBYTE1, (MY_UID >> 24) & 0xFF);
240        m.setElement(MarklinConstants.CANADDRESSBYTE2, (MY_UID >> 16) & 0xFF);
241        m.setElement(MarklinConstants.CANADDRESSBYTE3, (MY_UID >> 8) & 0xFF);
242        m.setElement(MarklinConstants.CANADDRESSBYTE4, (MY_UID) & 0xFF);
243        m.setElement(9, module & 0xFF);
244        return m;
245    }
246
247    public long getAddress() {
248        long addr = getElement(MarklinConstants.CANADDRESSBYTE1);
249        addr = (addr << 8) + getElement(MarklinConstants.CANADDRESSBYTE2);
250        addr = (addr << 8) + getElement(MarklinConstants.CANADDRESSBYTE3);
251        addr = (addr << 8) + getElement(MarklinConstants.CANADDRESSBYTE4);
252
253        return addr;
254    }
255
256    static public MarklinMessage getProgMode() {
257        return new MarklinMessage();
258    }
259
260    static public MarklinMessage getExitProgMode() {
261        return new MarklinMessage();
262    }
263
264    static public MarklinMessage getReadPagedCV(int cv) { //Rxxx
265        return new MarklinMessage();
266    }
267
268    static public MarklinMessage getWritePagedCV(int cv, int val) { //Pxxx xxx
269        return new MarklinMessage();
270    }
271
272    static public MarklinMessage getReadRegister(int reg) { //Vx
273        return new MarklinMessage();
274    }
275
276    static public MarklinMessage getWriteRegister(int reg, int val) { //Sx xxx
277        return new MarklinMessage();
278    }
279
280    static public MarklinMessage getReadDirectCV(int cv) { //Rxxx
281        return new MarklinMessage();
282    }
283
284    static public MarklinMessage getWriteDirectCV(int cv, int val) { //Pxxx xxx
285        return new MarklinMessage();
286    }
287}