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 == 0xF8 || opCode == 0xF9 || opCode == 0xFB) {
064            // TMCC2 Engine Commands
065            int A = (val / 512) & 0x7F; // A is TMCC Adddress Code
066            int C = (val / 32) & 0x03; // C is TMCC Command Code
067            int D = val & 0x1F; // D is TMCC Data Code
068            if ((val & 0x0100) == 0x0100) {
069                switch (C) {
070                    case 0: // If C (TMCC Command Code) == 0                    
071                        switch (D) {
072                            case 0:
073                                return "TMCC2 - Engine " + A + " - Forward Direction";
074                            case 1:
075                                return "TMCC2 - Engine " + A + " - Toggle Direction";
076                            case 2:
077                                
078                            case 3:
079                                return "TMCC2 - Engine " + A + " - Reverse Direction";
080                            case 4:
081                                return "TMCC2 - Engine " + A + " - Boost";
082                            case 5:
083                                return "TMCC2 - Engine " + A + " - Open Front Coupler";
084                            case 6:
085                                return "TMCC2 - Engine " + A + " - Open Rear Coupler";
086                            case 7:
087                                return "TMCC2 - Engine " + A + " - Brake";
088                            case 8:
089                                return "TMCC2 - Engine " + A + " - AUX1 Off";
090                            case 9:
091                                return "TMCC2 - Engine " + A + " - AUX1 Option 1 (CAB AUX1 button)";
092                            case 10:
093                                return "TMCC2 - Engine " + A + " - AUX1 Option 2";
094                            case 11:
095                                return "TMCC2 - Engine " + A + " - AUX1 On";
096                            case 12:
097                                return "TMCC2 - Engine " + A + " - AUX2 Off";
098                            case 13:
099                                return "TMCC2 - Engine " + A + " - AUX2 Option 1 (CAB AUX2 button) Headlight On/Off";
100                            case 14:
101                                return "TMCC2 - Engine " + A + " - AUX2 Option 2";
102                            case 15:
103                                return "TMCC2 - Engine " + A + " - AUX2 On";
104                            case 16:
105                                return "TMCC2 - Engine " + A + " - Num 0 - Engine Reset - Needed to toggle ERR 100 Speed Steps - TMCC2 Feature Type 0 ";
106                            case 17:
107                                return "TMCC2 - Engine " + A + " - Num 1 - Sound Volume Increase - TMCC2 Feature Type 1";
108                            case 18:
109                                return "TMCC2 - Engine " + A + " - Num 2 - Crew Talk - TMCC2 Feature Type 2";
110                            case 19:
111                                return "TMCC2 - Engine " + A + " - Num 3 - Sound On w/Start-Up Sequence/RPM Increase";
112                            case 20:
113                                return "TMCC2 - Engine " + A + " - Num 4 - Sound Volume Decrease";
114                            case 21:
115                                return "TMCC2 - Engine " + A + " - Num 5 - Sound Off w/Shut-Down Sequence";
116                            case 22:
117                                return "TMCC2 - Engine " + A + " - Num 6 - Steam Release/RPM Decrease";
118                            case 23:
119                                return "TMCC2 - Engine " + A + " - Num 7 - Tower Com Announcement";
120                            case 24:
121                                return "TMCC2 - Engine " + A + " - Num 8 - Feature Off (Smoke/Aux Lighting)";
122                            case 25:
123                                return "TMCC2 - Engine " + A + " - Num 9 - Feature On (Smoke/Aux Lighting)";
124                            case 26:
125                                
126                            case 27:
127                                
128                            case 28:
129                                return "TMCC2 - Engine " + A + " - Blow Whistle/Horn 1";
130                            case 29:
131                                return "TMCC2 - Engine " + A + " - Ring Bell";
132                            case 30:
133                                return "TMCC2 - Engine " + A + " - Letoff Sound";
134                            case 31:
135                                return "TMCC2 - Engine " + A + " - Blow Horn 2";
136                            default:
137                                return "TMCC2 - Engine " + A + " - action command D=" + D;
138                        }
139
140                    case 1: // If C (TMCC Command Code) == 1
141                        if ((D & 0x17) == 0) {
142                            return "TMCC2 - Engine " + A + " - Momentum Low";
143                        }
144                        if ((D & 0x17) == 1) {
145                            return "TMCC2 - Engine " + A + " - Momentum Medium";
146                        }
147                        if ((D & 0x17) == 2) {
148                            return "TMCC2 - Engine " + A + " - Momentum High";
149                        }
150                        if ((D & 0x17) == 3) {
151                            return "TMCC2 - Engine ID " + A + " - Set";
152                        }
153                        if ((D & 0x17) == 6) {
154                            return "TMCC2 - Engine " + A + " - Unassigned FnKey 111";
155                        }
156                    
157                        //$FALL-THROUGH$
158                    case 2: // If C (TMCC Command Code) == 2
159                        return "TMCC2 - Engine " + A + " - Change Speed (Relative) by +" + (D - 5);
160                        
161                    case 3: // If C (TMCC Command Code) == 3
162                    default:    // to let the compiler know there are only 3 cases
163                        return "TMCC2 (32 Speed Steps) - Engine " + A + " - Speed (Absolute) = " + D;
164                }
165            }
166
167            return "TMCC2 (200 Speed Steps) - Engine " + A + " - Speed (Absolute) = " + (val & 0xFF);
168        }
169        
170        
171        // TMCC 1 parsing
172        if (opCode == 0xFE) {
173            if ((val & 0xC000) == 0x4000) {
174                // TMCC1 Switch Commands
175                int A = (val / 128) & 0x7F; // A is TMCC Adddress Code
176                int C = (val / 32) & 0x03; // C is TMCC Command Code
177                int D = val & 0x1F; // D is TMCC Data Code
178                if ((C == 0) && (D == 0)) {
179                    return "Throw switch " + A + " - THROUGH";
180                } else if ((C == 0) && (D == 0x1F)) {
181                    return "Throw switch " + A + " - OUT";
182                } else if ((C == 1) && (D == 0x0B)) {
183                    return "Switch ID " + A + " - Set";                
184                } else if (C == 2) {
185                    return "Assign switch " + A + " to route " + D + " - THROUGH";
186                } else if (C == 3) {
187                    return "Assign switch " + A + " to route " + D + " - OUT";
188                } else {
189                    return "unrecognized switch command with A=" + A + " C=" + C + " D=" + D;
190                }
191            } else if ((val & 0xF000) == 0xD000) {
192                // TMCC1 Route Commands
193                int A = (val / 128) & 0x1F; // A is TMCC Adddress Code
194                int C = (val / 32) & 0x03; // C is TMCC Command Code
195                int D = val & 0x1F; // D is TMCC Data Code
196                if ((C == 0) && (D == 0x1F)) {
197                    return "Route " + A + " - THROW";
198                } else if ((C == 1) && (D == 0x0C)) {
199                    return "Route " + A + " - CLEAR";
200                } else {
201                      return "unrecognized route command with A=" + A + " C=" + C + " D=" + D;
202                }
203            } else if ((val & 0xC000) == 0x0000) {
204                // TMCC1 Engine Commands
205                int A = (val / 128) & 0x7F; // A is TMCC Adddress Code
206                int C = (val / 32) & 0x03; // C is TMCC Command Code
207                int D = val & 0x1F; // D is TMCC Data Code
208                switch (C) {
209                    case 0: // If C (TMCC Command Code) == 0                    
210                        switch (D) {
211                            case 0:
212                                return "TMCC1 - Engine " + A + " - Forward Direction";
213                            case 1:
214                                return "TMCC1 - Engine " + A + " - Toggle Direction";
215                            case 2:
216                            
217                            case 3:
218                                return "TMCC1 - Engine " + A + " - Reverse Direction";
219                            case 4:
220                                return "TMCC1 - Engine " + A + " - Boost";
221                            case 5:
222                                return "TMCC1 - Engine " + A + " - Open Front Coupler";
223                            case 6:
224                                return "TMCC1 - Engine " + A + " - Open Rear Coupler";
225                            case 7:
226                                return "TMCC1 - Engine " + A + " - Brake";
227                            case 8:
228                            
229                            case 9:
230                                return "TMCC1 - Engine " + A + " - AUX1 Option 1 (CAB AUX1 button)";
231                            case 10:
232                            
233                            case 11:
234                            
235                            case 12:
236                            
237                            case 13:
238                                return "TMCC1 - Engine " + A + " - AUX2 Option 1 (CAB AUX2 button) Headlight On/Off";
239                            case 14:
240                            
241                            case 15:
242                            
243                            case 16:
244                                return "TMCC1 - Engine " + A + " - Num 0 - Engine Reset (Needed to toggle ERR 100 Speed Steps)";
245                            case 17:
246                                return "TMCC1 - Engine " + A + " - Num 1 - Sound Volume Increase";
247                            case 18:
248                                return "TMCC1 - Engine " + A + " - Num 2 - Crew Talk";
249                            case 19:
250                                return "TMCC1 - Engine " + A + " - Num 3 - Sound On w/Start-Up Sequence";
251                            case 20:
252                                return "TMCC1 - Engine " + A + " - Num 4 - Sound Volume Decrease - TMCC1 Feature Type 4";
253                            case 21:
254                                return "TMCC1 - Engine " + A + " - Num 5 - Sound Off w/Shut-Down Sequence - TMCC1 Feature Type 5";
255                            case 22:
256                                return "TMCC1 - Engine " + A + " - Num 6 - Steam Release/RPM Decrease - TMCC1 Feature Type 6";
257                            case 23:
258                                return "TMCC1 - Engine " + A + " - Num 7 - Tower Com Announcement";
259                            case 24:
260                                return "TMCC1 - Engine " + A + " - Num 8 - Feature Off (Smoke/Aux Lighting) - TMCC1 Feature Type 8";
261                            case 25:
262                                return "TMCC1 - Engine " + A + " - Num 9 - Feature On (Smoke/Aux Lighting)";
263                            case 26:
264                            
265                            case 27:
266                            
267                            case 28:
268                                return "TMCC1 - Engine " + A + " - Blow Whistle/Horn 1";
269                            case 29:
270                                return "TMCC1 - Engine " + A + " - Ring Bell";
271                            case 30:
272                                return "TMCC1 - Engine " + A + " - Letoff Sound";
273                            case 31:
274                                return "TMCC1 - Engine " + A + " - Blow Horn 2";
275                            default:
276                                return "TMCC1 - Engine " + A + " - action command D=" + D;
277                        }
278
279                    case 1: // If C (TMCC Command Code) == 1
280                        if ((D & 0x17) == 0) {
281                            return "TMCC1 - Engine " + A + " - Momentum Low";
282                        }
283                        if ((D & 0x17) == 1) {
284                            return "TMCC1 - Engine " + A + " - Momentum Medium";
285                        }
286                        if ((D & 0x17) == 2) {
287                            return "TMCC1 - Engine " + A + " - Momentum High";
288                        }
289                        if ((D & 0x17) == 3) {
290                            return "TMCC1 - Engine ID " + A + " - Set";
291                        }
292                        if ((D & 0x17) == 6) {
293                            return "TMCC1 - Engine " + A + " - Unassigned FnKey 222";
294                        }
295                    
296                    //$FALL-THROUGH$
297                    case 2: // If C (TMCC Command Code) == 2
298                        return "TMCC1 - Engine " + A + " - Change Speed (Relative) by " + (D - 5);
299
300                    case 3: // If C (TMCC Command Code) == 3
301                    default:    // to let the compiler know there are only 3 cases
302                        return "TMCC1 (32 Speed Steps) - Engine " + A + " - Speed (Absolute) = " + D;
303                }
304
305            } else if ((val & 0xF800) == 0xC800) {
306                // TMCC1 Train Commands
307                int A = (val / 128) & 0x0F; // A is TMCC Adddress Code
308                int C = (val / 32) & 0x03; // C is TMCC Command Code
309                int D = val & 0x1F; // D is TMCC Data Code
310                return "unrecognized train command with A=" + A + " C=" + C + " D=" + D;
311            } else if ((val & 0xC000) == 0x8000) {
312                // TMCC1 Accessory Commands
313                int A = (val / 128) & 0x7F; // A is TMCC Adddress Code
314                int C = (val / 32) & 0x03; // C is TMCC Command Code
315                int D = val & 0x1F; // D is TMCC Data Code
316                if ((C == 0) && (D == 0x08)) {
317                    return "Aux 1 - ACC " + A + " - OFF";
318                } else if ((C == 0) && (D == 0x09)) {
319                    return "Aux 1 - ACC " + A + " - OPTION 1";
320                } else if ((C == 0) && (D == 0x0A)) {
321                    return "Aux 1 - ACC " + A + " - OPTION 2";
322                } else if ((C == 0) && (D == 0x0B)) {
323                    return "Aux 1 - ACC " + A + " - ON";
324                } else if ((C == 0) && (D == 0x0C)) {
325                    return "Aux 2 - ACC " + A + " - OFF";
326                } else if ((C == 0) && (D == 0x0D)) {
327                    return "Aux 2 - ACC " + A + " - OPTION 1";
328                } else if ((C == 0) && (D == 0x0E)) {
329                    return "Aux 2 - ACC " + A + " - OPTION 2";
330                } else if ((C == 0) && (D == 0x0F)) {
331                    return "Aux 2 - ACC " + A + " - ON";
332//                } else if ((C == 0) && (D == 0x??)) {
333//                    return "Numeric Command - ACC " + A + " - 0-9";
334                } else if ((C == 1) && (D == 0x00)) {
335                    return "ALL ACC OFF";
336                } else if ((C == 1) && (D == 0x1F)) {
337                    return "ALL ACC ON";
338                } else if ((C == 1) && (D == 0x0B)) {
339                    return "Accessory ID " + A + " - Set";
340//                } else if ((C == 1) && (D == 0x??)) {
341//                    return "Assign Aux 1 to Group D " + A + " - 0-9";
342//                } else if ((C == 1) && (D == 0x??)) {
343//                    return "Assign Aux 2 to Group D " + A + " - 0-9"";
344                } else {
345                    return "unrecognized accessory command with A=" + A + " C=" + C + " D=" + D;
346                }
347            } else if ((val & 0xF800) == 0xC000) {
348                // TMCC1 Group Commands
349                int A = (val / 128) & 0x0F; // A is TMCC Adddress Code
350                int C = (val / 32) & 0x03; // C is TMCC Command Code
351                int D = val & 0x1F; // D is TMCC Data Code
352                if ((C == 0) && (D == 0x08)) {
353                    return "GROUP - ACC " + A + " - OFF";
354                } else if ((C == 0) && (D == 0x09)) {
355                    return "GROUP - ACC " + A + " - OPTION 1";
356                } else if ((C == 0) && (D == 0x0A)) {
357                    return "GROUP - ACC " + A + " - OPTION 2";
358                } else if ((C == 0) && (D == 0x0B)) {
359                    return "GROUP - ACC " + A + " - ON";
360                } else if ((C == 1) && (D == 0x0C)) {
361                    return "GROUP - ACC " + A + " - CLEAR";
362                } else {
363                    return "unrecognized group command with A=" + A + " C=" + C + " D=" + D;
364                }
365            }            
366        }
367
368
369        // TMCC Error parsing
370        if (opCode == 0x00) {
371//            int A = (val / 128) & 0x7F; // A is TMCC Adddress Code
372            int C = (val / 32) & 0x03; // C is TMCC Command Code
373            int D = val & 0x1F; // D is TMCC Data Code
374            if ((C == 0) && (D == 0)) {
375                return "Address Must be Between 1-98 for TMCC";
376            } else if ((C == 0) && (D == 0x01)) {
377                return "CV Must Equal 1 for Programming TMCC Loco/Engine, Switch, Accessory ID#s";
378            } else if ((C == 0) && (D == 0x02)) {
379                return "CV Must Equal 2 for Programming TMCC Feature Type";
380            } else if ((C == 0) && (D == 0x03)) {
381                return "Value Entered is Not a TMCC1 Feature Type";
382            } else if ((C == 0) && (D == 0x04)) {
383                return "Value Entered is Not a TMCC2 Feature Type";                
384            }
385        }
386        
387        return "TMCC - CV#, Loco ID#/Address/Feature Value - Out of Range";
388
389    }
390}
391