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}