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