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 return; 046 } else { 047 nextLine("Cmd: " + parse(l.getAsWord()) + "\n", l.toString()); 048 } 049 } 050 051 @Override 052 public synchronized void reply(SerialReply l) { // receive a reply message and log it 053 // check for valid length 054 if (l.getNumDataElements() < 2) { 055 nextLine("Truncated reply of length " + l.getNumDataElements() + ": \"" + l.toString() + "\"\n", 056 l.toString()); 057 return; 058 } else { 059 nextLine("Rep: " + parse(l.getAsWord()) + "\n", l.toString()); 060 } 061 } 062 063 String parse(int val) { 064 if ((val & 0xC000) == 0x4000) { 065 // switch command 066 int A = (val / 128) & 0x7F; 067 int C = (val / 32) & 0x03; 068 int D = val & 0x1F; 069 if ((C == 0) && (D == 0)) { 070 return "Throw switch " + A + " THROUGH"; 071 } else if ((C == 0) && (D == 0x1F)) { 072 return "Throw switch " + A + " OUT"; 073 } else if ((C == 1) && (D == 0x09)) { 074 return "Switch " + A + " set address"; 075 } else if (C == 2) { 076 return "Assign switch " + A + " to route " + D + " THROUGH"; 077 } else if (C == 3) { 078 return "Assign switch " + A + " to route " + D + " OUT"; 079 } else { 080 return "unrecognized switch command with A=" + A + " C=" + C + " D=" + D; 081 } 082 } else if ((val & 0xF000) == 0xD000) { 083 // route command 084 int A = (val / 128) & 0x1F; 085 int C = (val / 32) & 0x03; 086 int D = val & 0x1F; 087 return "route command with A=" + A + " C=" + C + " D=" + D; 088 } else if ((val & 0xC000) == 0x0000) { 089 // engine command 090 int A = (val / 128) & 0x7F; 091 int C = (val / 32) & 0x03; 092 int D = val & 0x1F; 093 switch (C) { 094 case 0: 095 if (((D & 0x70) == 0x10) && ((D & 0x0F) < 10)) { 096 return "engine " + A + " numeric action command " + (D & 0x0F); 097 } 098 099 switch (D) { 100 case 0: 101 return "engine " + A + " forward direction"; 102 case 1: 103 return "engine " + A + " toggle direction"; 104 case 3: 105 return "engine " + A + " reverse direction"; 106 case 7: 107 return "engine " + A + " brake"; 108 case 4: 109 return "engine " + A + " boost"; 110 case 5: 111 return "engine " + A + " open front coupler"; 112 case 6: 113 return "engine " + A + " open rear coupler"; 114 case 28: 115 return "engine " + A + " blow horn 1"; 116 case 29: 117 return "engine " + A + " ring bell"; 118 case 30: 119 return "engine " + A + " letoff sound"; 120 case 31: 121 return "engine " + A + " blow horn 2"; 122 case 8: 123 return "engine " + A + " AUX1 off"; 124 case 9: 125 return "engine " + A + " AUX1 option 1 (CAB AUX1 button)"; 126 case 10: 127 return "engine " + A + " AUX1 option 2"; 128 case 11: 129 return "engine " + A + " AUX1 on"; 130 case 12: 131 return "engine " + A + " AUX2 off"; 132 case 13: 133 return "engine " + A + " AUX2 option 1 (CAB AUX2 button)"; 134 case 14: 135 return "engine " + A + " AUX2 option 2"; 136 case 15: 137 return "engine " + A + " AUX2 on"; 138 default: 139 return "engine " + A + " action command D=" + D; 140 } 141 142 case 1: 143 return "engine " + A + " extended command (C=1) with D=" + D; 144 case 2: 145 return "change engine " + A + " speed (relative) by " + (D - 5); 146 case 3: 147 default: // to let the compiler know there are only 3 cases 148 return "set engine " + A + " speed (absolute) to " + D; 149 } 150 } else if ((val & 0xF800) == 0xC800) { 151 // train command 152 int A = (val / 128) & 0x0F; 153 int C = (val / 32) & 0x03; 154 int D = val & 0x1F; 155 return "train command with A=" + A + " C=" + C + " D=" + D; 156 } else if ((val & 0xC000) == 0x8000) { 157 // accessory command 158 int A = (val / 128) & 0x7F; 159 int C = (val / 32) & 0x03; 160 int D = val & 0x1F; 161 return "accessory command with A=" + A + " C=" + C + " D=" + D; 162 } else if ((val & 0xF800) == 0xC000) { 163 // group command 164 int A = (val / 128) & 0x0F; 165 int C = (val / 32) & 0x03; 166 int D = val & 0x1F; 167 return "group command with A=" + A + " C=" + C + " D=" + D; 168 } else { 169 return "unexpected command " + Integer.toHexString(val & 0xFF); 170 } 171 } 172 173}