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