001package jmri.jmrix.tmcc.serialmon;
002
003import jmri.jmrix.tmcc.SerialListener;
004import jmri.jmrix.tmcc.SerialMessage;
005import jmri.jmrix.tmcc.SerialReply;
006import jmri.jmrix.tmcc.TmccSystemConnectionMemo;
007
008/**
009 * Frame displaying (and logging) TMCC serial command messages.
010 *
011 * @author Bob Jacobsen Copyright (C) 2001, 2006
012 */
013public class SerialMonFrame extends jmri.jmrix.AbstractMonFrame implements SerialListener {
014
015    private TmccSystemConnectionMemo _memo = null;
016
017    public SerialMonFrame(TmccSystemConnectionMemo memo) {
018        super();
019        _memo = memo;
020    }
021
022    @Override
023    protected String title() {
024        return Bundle.getMessage("MonitorXTitle", "TMCC");
025    }
026
027    @Override
028    protected void init() {
029        // connect to TrafficController
030        _memo.getTrafficController().addSerialListener(this);
031    }
032
033    @Override
034    public void dispose() {
035        _memo.getTrafficController().removeSerialListener(this);
036        super.dispose();
037    }
038
039    @Override
040    public synchronized void message(SerialMessage l) { // receive a message and log it
041        // check for valid length
042        if (l.getNumDataElements() < 3) {
043            nextLine("Truncated message of length " + l.getNumDataElements() + "\n",
044                    l.toString());
045        } else {
046            nextLine("Cmd: " + parse(l.getOpCode(), l.getAsWord()) + "\n", l.toString());
047        }
048    }
049
050    @Override
051    public synchronized void reply(SerialReply l) { // receive a reply message and log it
052        // check for valid length
053        if (l.getNumDataElements() < 2) {
054            nextLine("Truncated reply of length " + l.getNumDataElements() + ": \"" + l.toString() + "\"\n",
055                    l.toString());
056        } else {
057            nextLine("Rep: " + parse(l.getOpCode(), l.getAsWord()) + "\n", l.toString());
058        }
059    }
060
061    String parse(int opCode, int val) {
062        // TMCC 2 parsing
063        if (opCode != 0xFE) {
064            // TMCC2 Engine Commands
065            int A = (val / 512) & 0x7F;
066            int C = (val / 32) & 0x03;
067            int D = val & 0x1F;
068            if ((val & 0x0100) == 0x0100) {
069                switch (C) {
070                    case 0:
071                    
072                        switch (D) {
073                            case 0:
074                                return "Engine " + A + " - Forward Direction";
075                            case 1:
076                                return "Engine " + A + " - Toggle Direction";
077                            case 2:
078                                
079                            case 3:
080                                return "Engine " + A + " - Reverse Direction";
081                            case 4:
082                                return "Engine " + A + " - Boost";
083                            case 5:
084                                return "Engine " + A + " - Open Front Coupler";
085                            case 6:
086                                return "Engine " + A + " - Open Rear Coupler";
087                            case 7:
088                                return "Engine " + A + " - Brake";
089                            case 8:
090                                return "Engine " + A + " - AUX1 Off";
091                            case 9:
092                                return "Engine " + A + " - AUX1 Option 1 (CAB AUX1 button)";
093                            case 10:
094                                return "Engine " + A + " - AUX1 Option 2";
095                            case 11:
096                                return "Engine " + A + " - AUX1 On";
097                            case 12:
098                                return "Engine " + A + " - AUX2 Off";
099                            case 13:
100                                return "Engine " + A + " - AUX2 Option 1 (CAB AUX2 button) Headlight On/Off";
101                            case 14:
102                                return "Engine " + A + " - AUX2 Option 2";
103                            case 15:
104                                return "Engine " + A + " - AUX2 On";
105                            case 16:
106                                return "Engine " + A + " - Num 0 - Engine Reset (Needed to toggle ERR 100 Speed Steps)";
107                            case 17:
108                                return "Engine " + A + " - Num 1 - Sound Volume Increase";
109                            case 18:
110                                return "Engine " + A + " - Num 2 - Crew Talk";
111                            case 19:
112                                return "Engine " + A + " - Num 3 - Sound On w/Start-Up Sequence";
113                            case 20:
114                                return "Engine " + A + " - Num 4 - Sound Volume Decrease";
115                            case 21:
116                                return "Engine " + A + " - Num 5 - Sound Off w/Shut-Down Sequence";
117                            case 22:
118                                return "Engine " + A + " - Num 6 - Steam Release/RPM Decrease";
119                            case 23:
120                                return "Engine " + A + " - Num 7 - Tower Com Announcement";
121                            case 24:
122                                return "Engine " + A + " - Num 8 - Feature Off (Smoke/Aux Lighting)";
123                            case 25:
124                                return "Engine " + A + " - Num 9 - Feature On (Smoke/Aux Lighting)";
125                            case 26:
126                                
127                            case 27:
128                                
129                            case 28:
130                                return "Engine " + A + " - Blow Whistle/Horn 1";
131                            case 29:
132                                return "Engine " + A + " - Ring Bell";
133                            case 30:
134                                return "Engine " + A + " - Letoff Sound";
135                            case 31:
136                                return "Engine " + A + " - Blow Horn 2";
137                            default:
138                                return "Engine " + A + " - action command D=" + D;
139                        }
140
141                    case 1:
142                        //return "Engine " + A + " - extended command (C=1) with D=" + D;
143                        if ((D & 0x17) == 0) {
144                            return "Engine " + A + " - Momentum Low";
145                        }
146                        if ((D & 0x17) == 1) {
147                            return "Engine " + A + " - Momentum Medium";
148                        }
149                        if ((D & 0x17) == 2) {
150                            return "Engine " + A + " - Momentum High";
151                        }
152                        if ((D & 0x17) == 3) {
153                            return "Engine " + A + " - Set";
154                        }
155                        if ((D & 0x17) == 6) {
156                            return "Engine " + A + " - Unassigned FnKey";
157                        }
158                    
159                        //$FALL-THROUGH$
160                    case 2:
161                        return "Engine " + A + " - Change Speed (Relative) by " + (D - 5);
162                    case 3:
163                    default:    // to let the compiler know there are only 3 cases
164                        return "Engine " + A + " - Speed (Absolute) = " + D;
165                }
166            } else {
167                return "Engine " + A + " - Speed (Absolute) = " + (val & 0x00FF);
168            }
169        }
170
171        // TMCC 1 parsing
172        if ((val & 0xC000) == 0x4000) {
173            // TMCC1 Switch Commands
174            int A = (val / 128) & 0x7F;
175            int C = (val / 32) & 0x03;
176            int D = val & 0x1F;
177            if ((C == 0) && (D == 0)) {
178                return "Throw switch " + A + " THROUGH";
179            } else if ((C == 0) && (D == 0x1F)) {
180                return "Throw switch " + A + " OUT";
181            } else if ((C == 1) && (D == 0x09)) {
182                return "Switch " + A + " set address";
183            } else if (C == 2) {
184                return "Assign switch " + A + " to route " + D + " THROUGH";
185            } else if (C == 3) {
186                return "Assign switch " + A + " to route " + D + " OUT";
187            } else {
188                return "unrecognized switch command with A=" + A + " C=" + C + " D=" + D;
189            }
190        } else if ((val & 0xF000) == 0xD000) {
191            // TMCC1 Route Commands
192            int A = (val / 128) & 0x1F;
193            int C = (val / 32) & 0x03;
194            int D = val & 0x1F;
195            return "route command with A=" + A + " C=" + C + " D=" + D;
196        } else if ((val & 0xC000) == 0x0000) {
197            // TMCC1 Engine Commands
198            int A = (val / 128) & 0x7F;
199            int C = (val / 32) & 0x03;
200            int D = val & 0x1F;
201            switch (C) {
202                case 0:
203                    
204                    switch (D) {
205                        case 0:
206                            return "Engine " + A + " - Forward Direction";
207                        case 1:
208                            return "Engine " + A + " - Toggle Direction";
209                        case 2:
210                            
211                        case 3:
212                            return "Engine " + A + " - Reverse Direction";
213                        case 4:
214                            return "Engine " + A + " - Boost";
215                        case 5:
216                            return "Engine " + A + " - Open Front Coupler";
217                        case 6:
218                            return "Engine " + A + " - Open Rear Coupler";
219                        case 7:
220                            return "Engine " + A + " - Brake";
221                        case 8:
222                            
223                        case 9:
224                            return "Engine " + A + " - AUX1 Option 1 (CAB AUX1 button)";
225                        case 10:
226                            
227                        case 11:
228                            
229                        case 12:
230                            
231                        case 13:
232                            return "Engine " + A + " - AUX2 Option 1 (CAB AUX2 button) Headlight On/Off";
233                        case 14:
234                            
235                        case 15:
236                            
237                        case 16:
238                            return "Engine " + A + " - Num 0 - Engine Reset (Needed to toggle ERR 100 Speed Steps)";
239                        case 17:
240                            return "Engine " + A + " - Num 1 - Sound Volume Increase";
241                        case 18:
242                            return "Engine " + A + " - Num 2 - Crew Talk";
243                        case 19:
244                            return "Engine " + A + " - Num 3 - Sound On w/Start-Up Sequence";
245                        case 20:
246                            return "Engine " + A + " - Num 4 - Sound Volume Decrease";
247                        case 21:
248                            return "Engine " + A + " - Num 5 - Sound Off w/Shut-Down Sequence";
249                        case 22:
250                            return "Engine " + A + " - Num 6 - Steam Release/RPM Decrease";
251                        case 23:
252                            return "Engine " + A + " - Num 7 - Tower Com Announcement";
253                        case 24:
254                            return "Engine " + A + " - Num 8 - Feature Off (Smoke/Aux Lighting)";
255                        case 25:
256                            return "Engine " + A + " - Num 9 - Feature On (Smoke/Aux Lighting)";
257                        case 26:
258                            
259                        case 27:
260                            
261                        case 28:
262                            return "Engine " + A + " - Blow Whistle/Horn 1";
263                        case 29:
264                            return "Engine " + A + " - Ring Bell";
265                        case 30:
266                            return "Engine " + A + " - Letoff Sound";
267                        case 31:
268                            return "Engine " + A + " - Blow Horn 2";
269                        default:
270                            return "Engine " + A + " - action command D=" + D;
271                    }
272
273                case 1:
274                    //return "Engine " + A + " - extended command (C=1) with D=" + D;
275                    if ((D & 0x17) == 0) {
276                        return "Engine " + A + " - Momentum Low";
277                    }
278                    if ((D & 0x17) == 1) {
279                        return "Engine " + A + " - Momentum Medium";
280                    }
281                    if ((D & 0x17) == 2) {
282                        return "Engine " + A + " - Momentum High";
283                    }
284                    if ((D & 0x17) == 3) {
285                        return "Engine " + A + " - Set";
286                    }
287                    if ((D & 0x17) == 6) {
288                        return "Engine " + A + " - Unassigned FnKey";
289                    }
290                    
291                    //$FALL-THROUGH$
292                case 2:
293                    return "Engine " + A + " - Change Speed (Relative) by " + (D - 5);
294                case 3:
295                default:    // to let the compiler know there are only 3 cases
296                    return "Engine " + A + " - Speed (Absolute) = " + D;
297            }
298
299        } else if ((val & 0xF800) == 0xC800) {
300            // TMCC1 Train Commands
301            int A = (val / 128) & 0x0F;
302            int C = (val / 32) & 0x03;
303            int D = val & 0x1F;
304            return "train command with A=" + A + " C=" + C + " D=" + D;
305        } else if ((val & 0xC000) == 0x8000) {
306            // TMCC1 Accessory Commands
307            int A = (val / 128) & 0x7F;
308            int C = (val / 32) & 0x03;
309            int D = val & 0x1F;
310            return "accessory command with A=" + A + " C=" + C + " D=" + D;
311        } else if ((val & 0xF800) == 0xC000) {
312            // TMCC1 Group Commands
313            int A = (val / 128) & 0x0F;
314            int C = (val / 32) & 0x03;
315            int D = val & 0x1F;
316            return "group command with A=" + A + " C=" + C + " D=" + D;
317        } else {
318            return "unexpected command " + Integer.toHexString(val & 0xFF);
319        }
320    }
321
322}