001package jmri.jmrix.marklin;
002
003/**
004 * Carries the reply to an MarklinMessage.
005 *
006 * @author Bob Jacobsen Copyright (C) 2001, 2008
007 * @author Kevin Dickerson Copyright (C) 2007
008 *
009 */
010public class MarklinReply extends jmri.jmrix.AbstractMRReply {
011
012    // create a new one
013    public MarklinReply() {
014        super();
015    }
016
017    public MarklinReply(String s) {
018        super(s);
019    }
020
021    public MarklinReply(MarklinReply l) {
022        super(l);
023    }
024
025    // create a new one from an array
026    public MarklinReply(int[] d) {
027        //this(header);
028        this();
029        _nDataChars = d.length;
030        System.arraycopy(d, 0, _dataChars, 0, d.length);
031    }
032
033    //Maximum size of a reply packet is 13 bytes.
034    @Override
035    public int maxSize() {
036        return 13;
037    }
038
039    // no need to do anything
040    @Override
041    protected int skipPrefix(int index) {
042        return index;
043    }
044
045    @Override
046    public int value() {
047        if (isBinary()) {
048            return getElement(0);
049        } else {
050            return super.value();
051        }
052    }
053
054    @Override  // avoid stupid sign extension
055    public int getElement(int n) {
056        return super.getElement(n) & 0xff;
057    }
058
059    //An event message is Unsolicited
060    @Override
061    public boolean isUnsolicited() {
062        return !isResponse();
063    }
064
065    /**
066     * {@inheritDoc}
067     */
068    @Override
069    public String toString(){
070        StringBuilder buf = new StringBuilder();
071        buf.append("0x").append(Integer.toHexString(_dataChars[0]));
072        for (int i = 1; i < _nDataChars; i++) {
073            buf.append(", 0x").append(Integer.toHexString(_dataChars[i]));
074        }
075        return buf.toString();
076    }
077
078    /**
079     * {@inheritDoc}
080     */
081    @Override
082    public String toMonitorString(){
083        // eventually, the MarklinMon class should probably be integrated here.
084        return jmri.jmrix.marklin.swing.monitor.MarklinMon.displayReply(this);
085    }
086
087    public boolean isResponse() {
088        return (getElement(1) & 0x01) == 0x01;
089    }
090
091    public int getCanDataLength() {
092        return getElement(4);
093    }
094
095    public int[] getCanData() {
096        int[] arr = new int[maxSize() - 5];
097        for (int i = 5; i < maxSize(); i++) {
098            arr[i - 5] = getElement(i);
099        }
100        return arr;
101    }
102
103    public int[] getCanAddress() {
104        int[] arr = new int[4];
105        for (int i = 5; i < 9; i++) {
106            arr[i - 5] = getElement(i);
107        }
108        return arr;
109    }
110
111    /**
112     * Get the 4-Byte Address.
113     * @return the value from CANADDRESSBYTE1 (hi) to CANADDRESSBYTE4 (low)
114     */
115    public long getAddress() {
116        long addr = (getElement(MarklinConstants.CANADDRESSBYTE1));
117        addr = (addr << 8) + (getElement(MarklinConstants.CANADDRESSBYTE2));
118        addr = (addr << 8) + (getElement(MarklinConstants.CANADDRESSBYTE3));
119        addr = (addr << 8) + (getElement(MarklinConstants.CANADDRESSBYTE4));
120        return addr;
121    }
122
123    /**
124     * Sets the 4-byte address by splitting an integer into four bytes.
125     * @param address the 32-bit integer representing the full address
126     */
127    public void setAddress(long address) {
128        setElement(MarklinConstants.CANADDRESSBYTE1, (byte) ((address >> 24) & 0xFF)); // hi
129        setElement(MarklinConstants.CANADDRESSBYTE2, (byte) ((address >> 16) & 0xFF));
130        setElement(MarklinConstants.CANADDRESSBYTE3, (byte) ((address >> 8) & 0xFF));
131        setElement(MarklinConstants.CANADDRESSBYTE4, (byte) (address & 0xFF)); // lo
132    }
133
134    public int getPriority() {
135        return (getElement(0) >> 4);
136    }
137
138    /**
139     * Get the Control Command.
140     * @return command, e.g. MarklinConstants.CMDHALTSYS
141     */
142    public int getCommand() {
143        int result = getElement(0) << 7;
144        result = result + getElement(1) >> 1;
145        return result;
146    }
147
148    /**
149     * Set the Command value.
150     * @param command new value.
151     */
152    public void setCommand(int command) {
153        // Update only the relevant bits in element0 (upper 7 bits)
154        int element0 = (getElement(0) & ~0x7F) | ((command >> 7) & 0x7F);
155
156        // Update only the relevant bits in element1 (lower 7 bits, shifted left)
157        int element1 = (getElement(1) & ~0xFE) | ((command & 0x7F) << 1);
158
159        // Set the updated elements
160        setElement(0, element0);
161        setElement(1, element1);
162    }
163
164    public int[] getHash() {
165        int[] arr = new int[2];
166        arr[0] = getElement(2);
167        arr[1] = getElement(3);
168        return arr;
169    }
170}