001package jmri.jmrix.cmri.serial.diagnostic; 002 003import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 004import java.awt.Container; 005import java.awt.Dimension; 006import java.awt.FlowLayout; 007import java.awt.event.ActionEvent; 008import java.awt.event.ActionListener; 009import javax.swing.BorderFactory; 010import javax.swing.BoxLayout; 011import javax.swing.JComboBox; 012import javax.swing.JLabel; 013import javax.swing.JPanel; 014import javax.swing.Timer; 015import javax.swing.border.Border; 016import jmri.util.StringUtil; 017 018import jmri.jmrix.cmri.CMRISystemConnectionMemo; 019import jmri.jmrix.cmri.serial.SerialMessage; 020import jmri.jmrix.cmri.serial.SerialNode; 021import jmri.jmrix.cmri.serial.SerialReply; 022import jmri.jmrix.cmri.serial.SerialTrafficController; 023 024/** 025 * Frame for running CMRI diagnostics 026 * 027 * @author Dave Duchamp Copyright (C) 2004 028 * @author Chuck Catania Copyright (C) 2018 029 */ 030public class DiagnosticFrame extends jmri.util.JmriJFrame implements jmri.jmrix.cmri.serial.SerialListener { 031 protected int numTestNodes = 0; 032 protected SerialNode[] testNodes = new SerialNode[128]; // Node control blocks 033 protected int[] testNodeAddresses = new int[128]; // ua's of loaded nodes 034 035 protected SerialNode testNode = null; // current node under test 036 public int testNodeAddr = 0; // Address (ua) of selected Node 037 protected String testNodeID = "x"; // text address of selected Node 038 protected int testNodeType = 0; // Test node type e.g SMINI 039 040 JComboBox<String> nodeSelBox = new JComboBox<>(); 041 JComboBox<String> testSelectBox = new JComboBox<>(); 042 043 // member declarations 044 public static final int testType_Outputs = 0, // Write bit pattern to ports 045 testType_Wraparound = 1, // Write bit pattern to port, read and compare bit pattern. Needs loopback cable 046 testType_SendCommand= 2, // Poll node to check for presence, read inputs 047 testType_WriteBytes = 3; // Transmit output byte pattern 048 049 protected int selTestType = testType_Outputs; // Current test suite 050 protected boolean outTest = true; 051 protected boolean wrapTest = false; 052 protected boolean isSMINI = false; 053 protected boolean isUSIC_SUSIC = true; 054 protected boolean isCPNODE = false; 055 protected boolean isESP32NODE = false; 056 // Here add other node types 057 protected int numOutputCards = 2; 058 protected int numInputCards = 1; 059 protected int numCards = 3; 060 protected int numIOXInputCards = 0; 061 protected int numIOXOutputCards= 0; 062 063// protected int ua = 0; // node address 064// protected SerialNode node; 065 protected int outCardNum = 0; 066 protected int obsDelay = 500; 067 protected int inCardNum = 2; 068 protected int filterDelay = 0; 069 // Test running variables 070 protected boolean testRunning = false; 071 protected boolean testSuspended = false; // true when Wraparound is suspended by error 072 protected byte[] outBytes = new byte[256]; 073 protected int curOutByte = 0; // current output byte in output test 074 protected int curOutBit = 0; // current on bit in current output byte in output test 075 protected short curOutValue = 0; // current ofoutput byte in wraparound test 076 protected int nOutBytes = 6; // number of output bytes for all cards of this node 077 protected int begOutByte = 0; // numbering from zero, subscript in outBytes 078 protected int endOutByte = 2; 079 protected int totalOutBytes= 0; 080 protected int portsPerCard = 0; 081 protected byte[] inBytes = new byte[256]; 082 protected byte[] wrapBytes = new byte[4]; 083 protected int nInBytes = 3; // number of input bytes for all cards of this node 084 protected int begInByte = 0; // numbering from zero, subscript in inBytes 085 protected int replyCount= 0; // number of bytes received from a poll 086 087 @SuppressFBWarnings(value = "IS2_INCONSISTENT_SYNC", justification = "unsync access only during initialization") 088 protected int endInByte = 2; 089 090 protected int numErrors = 0; 091 protected int numIterations = 0; 092 protected javax.swing.Timer outTimer; 093 protected javax.swing.Timer wrapTimer; 094 protected javax.swing.Timer pollTimer; 095 096 @SuppressFBWarnings(value = "IS2_INCONSISTENT_SYNC", justification = "unsync access only during initialization") 097 protected boolean waitingOnInput = false; 098 protected boolean waitingResponse = false; 099 100 protected boolean needInputTest = false; 101 protected int count = 20; 102 int debugCount = 0; 103 javax.swing.ButtonGroup testGroup = new javax.swing.ButtonGroup(); 104 javax.swing.JCheckBox invertOutButton = new javax.swing.JCheckBox(Bundle.getMessage("ButtonInvert"), false); 105 javax.swing.JCheckBox invertWrapButton = new javax.swing.JCheckBox(Bundle.getMessage("ButtonInvert"), false); 106 javax.swing.JCheckBox invertWriteButton = new javax.swing.JCheckBox(Bundle.getMessage("ButtonInvert"), false); 107 108 javax.swing.JButton initButton = new javax.swing.JButton(Bundle.getMessage("ButtonInitializeNode")); 109 javax.swing.JButton pollButton = new javax.swing.JButton(Bundle.getMessage("ButtonPollNode")); 110 javax.swing.JButton writeButton = new javax.swing.JButton(Bundle.getMessage("ButtonWriteBytes")); 111 javax.swing.JButton haltPollButton = new javax.swing.JButton("Halt Polling" ); 112 113 javax.swing.JTextField uaAddrField = new javax.swing.JTextField(3); 114 javax.swing.JTextField outCardField = new javax.swing.JTextField(3); 115 javax.swing.JTextField inCardField = new javax.swing.JTextField(3); 116 javax.swing.JTextField obsDelayField = new javax.swing.JTextField(5); 117 javax.swing.JTextField filterDelayField = new javax.swing.JTextField(5); 118 javax.swing.JTextField writeCardField = new javax.swing.JTextField(3); 119 javax.swing.JTextField writeBytesField = new javax.swing.JTextField(9); 120 121 javax.swing.JButton runButton = new javax.swing.JButton(Bundle.getMessage("ButtonRun")); 122 javax.swing.JButton stopButton = new javax.swing.JButton(Bundle.getMessage("ButtonStop")); 123 javax.swing.JButton continueButton = new javax.swing.JButton(Bundle.getMessage("ButtonContinue")); 124 125 javax.swing.JLabel nodeText1 = new javax.swing.JLabel(); 126 javax.swing.JLabel nodeText2 = new javax.swing.JLabel(); 127 javax.swing.JLabel testReqEquip = new javax.swing.JLabel(Bundle.getMessage("NeededEquipmentTitle")); 128 javax.swing.JLabel testEquip = new javax.swing.JLabel(); 129 javax.swing.JLabel nodeReplyLabel = new javax.swing.JLabel(Bundle.getMessage("NodeReplyLabel")); 130 javax.swing.JLabel nodeReplyText = new javax.swing.JLabel(); 131 javax.swing.JLabel writeCardLabel = new javax.swing.JLabel("Out Card:"); 132 javax.swing.JLabel writeBytesLabel = new javax.swing.JLabel("Output Bytes (Hex):"); 133 134 javax.swing.JLabel statusText1 = new javax.swing.JLabel(); 135 javax.swing.JLabel statusText2 = new javax.swing.JLabel(); 136 javax.swing.JLabel compareErr = new javax.swing.JLabel(); 137 138 DiagnosticFrame curFrame; 139 140 private CMRISystemConnectionMemo _memo = null; 141 142 public DiagnosticFrame(CMRISystemConnectionMemo memo) { 143 super(); 144 curFrame = this; 145 _memo=memo; 146 } 147 148 /** 149 * {@inheritDoc} 150 */ 151 @Override 152 public void initComponents() { 153 154 initializeNodes(); 155 nodeSelBox.setEditable(false); 156 if (numTestNodes > 0) { 157 nodeSelBox.addActionListener(new ActionListener() { 158 @Override 159 public void actionPerformed(ActionEvent event) { 160 displayNodeInfo((String) nodeSelBox.getSelectedItem()); 161 } 162 }); 163 } 164 165 // set the frame's initial state 166 setTitle(Bundle.getMessage("DiagnosticTitle") + Bundle.getMessage("WindowConnectionMemo") + _memo.getUserName()); // NOI18N 167 setSize(500, 200); 168 Container contentPane = getContentPane(); 169 contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS)); 170 171 // Test node information 172 //---------------------- 173 JPanel panelNode = new JPanel(); 174 panelNode.setLayout(new BoxLayout(panelNode, BoxLayout.Y_AXIS)); 175 JPanel panelNode1 = new JPanel(); 176 panelNode1.setLayout(new FlowLayout()); 177 panelNode1.add(new JLabel(Bundle.getMessage("LabelNodeAddress"))); 178 panelNode1.add(nodeSelBox); 179 nodeSelBox.setToolTipText(Bundle.getMessage("SelectNodeAddressTip")); 180 panelNode1.add(nodeText1); 181 nodeText1.setText("Node Type/Card Size"); 182 panelNode.add(panelNode1); 183 184 JPanel panelNode2 = new JPanel(); 185 panelNode2.setLayout(new FlowLayout()); 186 nodeText2.setText("Ins and Outs"); 187 panelNode2.add(nodeText2); 188 panelNode.add(panelNode2); 189 190 Border panelNodeBorder = BorderFactory.createEtchedBorder(); 191 Border panelNodeTitled = BorderFactory.createTitledBorder(panelNodeBorder, Bundle.getMessage("TestNodeTitle")); 192 panelNode.setBorder(panelNodeTitled); 193 contentPane.add(panelNode); 194 195 // Set up the test suite buttons 196 //------------------------------ 197 JPanel panelTest = new JPanel(); 198 panelTest.setLayout(new BoxLayout(panelTest, BoxLayout.Y_AXIS)); 199 JPanel panelTest1 = new JPanel(); 200 panelTest1.setLayout(new FlowLayout(FlowLayout.LEADING)); 201 testSelectBox.addItem(Bundle.getMessage("ButtonTestOutput")); 202 testSelectBox.addItem(Bundle.getMessage("ButtonTestLoopback")); 203 testSelectBox.addItem(Bundle.getMessage("ButtonTestSendCommands")); 204 panelTest1.add(testSelectBox); 205 testSelectBox.setToolTipText(Bundle.getMessage("TestTypeToolLabel")); 206 207 // -------------------------- 208 // Set up Halt Polling button 209 // -------------------------- 210 haltPollButton.setVisible(true); 211 haltPollButton.setToolTipText(Bundle.getMessage("HaltPollButtonTip")); 212 haltPollButton.addActionListener(new java.awt.event.ActionListener() { 213 @Override 214 public void actionPerformed(java.awt.event.ActionEvent e) { 215 haltpollButtonActionPerformed(); 216 } 217 }); 218 panelTest1.add(haltPollButton); 219 SerialTrafficController stc = _memo.getTrafficController(); 220 if (stc.getPollNetwork()) { 221 haltPollButton.setText(Bundle.getMessage("HaltPollButtonText")); 222 } else { 223 haltPollButton.setText(Bundle.getMessage("ResumePollButtonText")); 224 } 225 226 panelTest.add(panelTest1); 227 228 JPanel panel11 = new JPanel(); 229 panel11.setLayout(new FlowLayout(FlowLayout.LEFT)); 230 testReqEquip.setText(Bundle.getMessage("NeededEquipmentTitle")); 231 panel11.add(testReqEquip); 232 panel11.add(testEquip); 233 testEquip.setToolTipText(Bundle.getMessage("NeededTestEquipmentTip")); 234 panelTest.add(panel11); 235 236 Border panel1Border = BorderFactory.createEtchedBorder(); 237 Border panel1Titled = BorderFactory.createTitledBorder(panel1Border, Bundle.getMessage("TestTypeTitle")); 238 panelTest.setBorder(panel1Titled); 239 contentPane.add(panelTest); 240 241 // Set up the test setup panel 242 // There are multiple panes depending upon which test type is selected 243 //-------------------------------------------------------------------- 244 JPanel panel2 = new JPanel(); 245 panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS)); 246 247 // Panel for the Output test suite 248 JPanel panel21 = new JPanel(); 249 panel21.setLayout(new FlowLayout()); 250 panel21.add(new JLabel(" " + Bundle.getMessage("OutCardLabel"))); 251 panel21.add(outCardField); 252 outCardField.setToolTipText(Bundle.getMessage("OutCardToolTip")); 253 outCardField.setText("0"); 254 panel21.add(invertOutButton); 255 invertOutButton.setToolTipText(Bundle.getMessage("InvertToolTip")); 256 panel21.add(new JLabel(" " + Bundle.getMessage("ObservationDelayLabel"))); 257 panel21.add(obsDelayField); 258 obsDelayField.setToolTipText(Bundle.getMessage("ObservationDelayToolTip")); 259 obsDelayField.setText(Integer.toString(obsDelay)); 260 261 // Panel for the Loopback test 262 JPanel panel22 = new JPanel(); 263 panel22.setLayout(new FlowLayout()); 264 panel22.add(new JLabel(Bundle.getMessage("InCardToolLabel"))); 265 panel22.add(inCardField); 266 panel22.add(invertWrapButton); 267 invertWrapButton.setToolTipText(Bundle.getMessage("InvertToolTip")); 268 inCardField.setToolTipText(Bundle.getMessage("InCardToolTip")); 269 inCardField.setText("2"); 270 panel22.add(new JLabel(" " + Bundle.getMessage("FilteringDelayLabel"))); 271 panel22.add(filterDelayField); 272 filterDelayField.setToolTipText(Bundle.getMessage("FilteringDelayToolTip")); 273 filterDelayField.setText("0"); 274 275 // Panel for the Node command packets 276 JPanel panel23 = new JPanel(); 277 panel23.setLayout(new FlowLayout(FlowLayout.LEFT)); 278 panel23.add(initButton); 279 initButton.addActionListener(new java.awt.event.ActionListener() { 280 @Override 281 public void actionPerformed(java.awt.event.ActionEvent e) { 282 sendInitalizePacket(); 283 } 284 }); 285 pollButton.addActionListener(new java.awt.event.ActionListener() { 286 @Override 287 public void actionPerformed(java.awt.event.ActionEvent e) { 288 pollButtonActionPerformed(e); 289 } 290 }); 291 292 JPanel panel23a = new JPanel(); 293 panel23a.setLayout(new FlowLayout(FlowLayout.LEFT)); 294 panel23a.add(pollButton); 295 panel23a.add(nodeReplyLabel); 296 panel23a.add(nodeReplyText); 297 298 JPanel panel24 = new JPanel(); 299 panel24.setLayout(new FlowLayout(FlowLayout.LEFT)); 300 panel24.add(writeButton); 301 writeButton.addActionListener(new java.awt.event.ActionListener() { 302 @Override 303 public void actionPerformed(java.awt.event.ActionEvent e) { 304 sendButtonActionPerformed(e); 305 } 306 }); 307 panel24.add(writeCardLabel); 308 panel24.add(writeCardField); 309 writeCardField.setText("0"); 310 panel24.add(invertWriteButton); 311 panel24.add(writeBytesLabel); 312 panel24.add(writeBytesField); 313 writeBytesField.setText("0"); 314 315 // Panel for the Poll node with inputs display 316 JPanel panel25 = new JPanel(); 317 panel25.setLayout(new FlowLayout()); 318 319 panel2.add(panel21); 320 321 panel2.add(panel22); 322 panel22.setVisible(false); 323 324 panel2.add(panel23); 325 panel23.setVisible(false); 326 panel2.add(panel23a); 327 panel23a.setVisible(false); 328 panel2.add(panel24); 329 panel24.setVisible(false); 330 331 panel2.add(panel25); 332 panel25.setVisible(false); 333 334 Border panel2Border = BorderFactory.createEtchedBorder(); 335 Border panel2Titled = BorderFactory.createTitledBorder(panel2Border, Bundle.getMessage("TestSetUpTitle")); 336 panel2.setBorder(panel2Titled); 337 contentPane.add(panel2); 338 339 // Add the button listeners to display the appropriate test options 340 //----------------------------------------------------------------- 341 testSelectBox.addActionListener(new ActionListener() { 342 @Override 343 public void actionPerformed(ActionEvent event) { 344 selTestType = testSelectBox.getSelectedIndex(); 345 switch (selTestType) { 346 case testType_Outputs: 347 testEquip.setText(Bundle.getMessage("OutputTestEquipment")); 348 panel21.setVisible(true); 349 panel22.setVisible(false); 350 panel23.setVisible(false); 351 panel23a.setVisible(false); 352 panel24.setVisible(false); 353 panel25.setVisible(false); 354 runButton.setEnabled(true); 355 stopButton.setEnabled(true); 356 continueButton.setVisible(false); 357 displayNodeInfo(testNodeID); 358 break; 359 case testType_Wraparound: 360 testEquip.setText(Bundle.getMessage("WrapTestEquipment")); 361 panel21.setVisible(true); 362 panel22.setVisible(true); 363 panel23.setVisible(false); 364 panel23a.setVisible(false); 365 panel24.setVisible(false); 366 panel25.setVisible(false); 367 invertOutButton.setVisible(false); 368 runButton.setEnabled(true); 369 stopButton.setEnabled(true); 370 continueButton.setVisible(true); 371 invertWrapButton.setSelected(testNodeType == SerialNode.CPNODE); 372 displayNodeInfo(testNodeID); 373 break; 374 case testType_SendCommand: 375 testEquip.setText(Bundle.getMessage("SendCommandEquipment")); 376 panel21.setVisible(false); 377 panel22.setVisible(false); 378 panel23.setVisible(true); 379 panel23a.setVisible(true); 380 panel24.setVisible(true); 381 panel25.setVisible(false); 382 runButton.setEnabled(false); 383 stopButton.setEnabled(false); 384 continueButton.setVisible(false); 385 displayNodeInfo(testNodeID); 386 break; 387 case testType_WriteBytes: 388 testEquip.setText(Bundle.getMessage("WriteBytesEquipment")); 389 panel21.setVisible(false); 390 panel22.setVisible(false); 391 panel23.setVisible(false); 392 panel23a.setVisible(false); 393 panel24.setVisible(false); 394 panel25.setVisible(true); 395 displayNodeInfo(testNodeID); 396 break; 397 default: 398 log.debug("default case in testSelectBox switch"); 399 } 400 } 401 }); 402 403 // Set up the status panel 404 //------------------------ 405 JPanel panel3 = new JPanel(); 406 panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS)); 407 408 JPanel panel31 = new JPanel(); 409 panel31.setLayout(new FlowLayout()); 410 statusText1.setText(Bundle.getMessage("StatusLine1")); 411 statusText1.setVisible(true); 412 statusText1.setMaximumSize(new Dimension(statusText1.getMaximumSize().width, 413 statusText1.getPreferredSize().height)); 414 panel31.add(statusText1); 415 416 JPanel panel32 = new JPanel(); 417 panel32.setLayout(new FlowLayout()); 418 statusText2.setText(Bundle.getMessage("StatusLine2", Bundle.getMessage("ButtonRun"))); 419 statusText2.setVisible(true); 420 statusText2.setMaximumSize(new Dimension(statusText2.getMaximumSize().width, 421 statusText2.getPreferredSize().height)); 422 panel32.add(statusText2); 423 424 JPanel panel33 = new JPanel(); 425 panel33.setLayout(new FlowLayout()); 426 compareErr.setText(" "); //Bundle.getMessage("StatusLine1")); 427 compareErr.setVisible(true); 428 compareErr.setMaximumSize(new Dimension(compareErr.getMaximumSize().width, 429 compareErr.getPreferredSize().height)); 430 panel33.add(compareErr); 431 432 panel3.add(panel31); 433 panel3.add(panel32); 434 panel3.add(panel33); 435 436 Border panel3Border = BorderFactory.createEtchedBorder(); 437 Border panel3Titled = BorderFactory.createTitledBorder(panel3Border, Bundle.getMessage("StatusTitle")); 438 panel3.setBorder(panel3Titled); 439 contentPane.add(panel3); 440 441 // Set up Continue, Stop, Run buttons 442 //----------------------------------- 443 JPanel panel4 = new JPanel(); 444 panel4.setLayout(new FlowLayout()); 445 continueButton.setText(Bundle.getMessage("ButtonContinue")); 446 continueButton.setVisible(false); 447 continueButton.setToolTipText(Bundle.getMessage("ContinueTestToolTip")); 448 continueButton.addActionListener(new java.awt.event.ActionListener() { 449 @Override 450 public void actionPerformed(java.awt.event.ActionEvent e) { 451 continueButtonActionPerformed(e); 452 } 453 }); 454 panel4.add(continueButton); 455 stopButton.setText(Bundle.getMessage("ButtonStop")); 456 stopButton.setVisible(true); 457 stopButton.setToolTipText(Bundle.getMessage("StopToolTip")); 458 panel4.add(stopButton); 459 stopButton.addActionListener(new java.awt.event.ActionListener() { 460 @Override 461 public void actionPerformed(java.awt.event.ActionEvent e) { 462 stopButtonActionPerformed(e); 463 } 464 }); 465 runButton.setText(Bundle.getMessage("ButtonRun")); 466 runButton.setVisible(true); 467 runButton.setToolTipText(Bundle.getMessage("RunTestToolTip")); 468 panel4.add(runButton); 469 runButton.addActionListener(new java.awt.event.ActionListener() { 470 @Override 471 public void actionPerformed(java.awt.event.ActionEvent e) { 472 runButtonActionPerformed(e); 473 } 474 }); 475 contentPane.add(panel4); 476 477 if (numTestNodes > 0) { 478 // initialize for the first time 479 displayNodeInfo((String) nodeSelBox.getSelectedItem()); 480 } 481 testSelectBox.setSelectedIndex(selTestType); 482 addHelpMenu("package.jmri.jmrix.cmri.serial.diagnostic.DiagnosticFrame", true); 483 484 // pack for display 485 pack(); 486 } 487 488 /** 489 * Initialize configured nodes and set up the node select combo box. 490 */ 491 public void initializeNodes() { 492 String str = ""; 493 // clear the arrays 494 for (int i = 0; i < 128; i++) { 495 testNodeAddresses[i] = -1; 496 testNodes[i] = null; 497 } 498 // get all configured nodes 499 SerialNode node = (SerialNode) _memo.getTrafficController().getNode(0); 500 int index = 1; 501 while (node != null) 502 { 503 testNodes[numTestNodes] = node; 504 testNodeAddresses[numTestNodes] = node.getNodeAddress(); 505 str = Integer.toString(testNodeAddresses[numTestNodes]); 506 nodeSelBox.addItem(str); 507 if (index == 1) { 508 testNode = node; 509 testNodeAddr = testNodeAddresses[numTestNodes]; 510 testNodeID = "y"; // to force first time initialization 511 } 512 numTestNodes++; 513 // go to next node 514 node = (SerialNode) _memo.getTrafficController().getNode(index); 515 index++; 516 } 517 } 518 519 /** 520 * Method to handle selection of a Node for info display. 521 * @param nodeID Node ID. 522 */ 523 public void displayNodeInfo(String nodeID) { 524 if (!nodeID.equals(testNodeID)) { 525 // The selected node is changing - initialize it 526 int aTestNum = Integer.parseInt(nodeID); 527 SerialNode s = null; 528 for (int k = 0; k < numTestNodes; k++) { 529 if (aTestNum == testNodeAddresses[k]) { 530 s = testNodes[k]; 531 } 532 } 533 if (s == null) { 534 // serious trouble, log error and ignore 535 log.error("Cannot find Node {} in list of configured Nodes.", nodeID); 536 return; 537 } 538 // have node, initialize for new node 539 testNodeID = nodeID; 540 testNode = s; 541 testNodeAddr = aTestNum; 542 // prepare the information line 543 int bitsPerCard = testNode.getNumBitsPerCard(); 544// int numInputCards = testNode.numInputCards(); 545// int numOutputCards = testNode.numOutputCards(); 546// int numIOXInputCards = 0; 547// int numIOXOutputCards= 0; 548 549 testNodeType = testNode.getNodeType(); 550 String s1 = "", 551 s2 = ""; 552 switch (testNodeType) 553 { 554 case SerialNode.SMINI: 555 bitsPerCard = testNode.getNumBitsPerCard(); 556 numInputCards = testNode.numInputCards(); 557 numOutputCards = testNode.numOutputCards(); 558 numIOXInputCards = 0; 559 numIOXOutputCards= 0; 560 561 nodeText1.setText(" SMINI - " + bitsPerCard + " " + Bundle.getMessage("BitsPerCard")); 562 nodeText2.setText(numInputCards + " " + Bundle.getMessage("InputCard") + 563 ", " + numOutputCards + " " + Bundle.getMessage("OutputCard") + "s"); 564 break; 565 case SerialNode.USIC_SUSIC: 566 bitsPerCard = testNode.getNumBitsPerCard(); 567 numInputCards = testNode.numInputCards(); 568 numOutputCards = testNode.numOutputCards(); 569 numIOXInputCards = 0; 570 numIOXOutputCards= 0; 571 if(numInputCards > 1) s1 = "s"; 572 if(numOutputCards > 1) s2 = "s"; 573 nodeText1.setText(" USIC_SUSIC - " + bitsPerCard + " " + Bundle.getMessage("BitsPerCard")); 574 nodeText2.setText(numInputCards + " " + Bundle.getMessage("InputCard") + s1 + 575 ", " + numOutputCards + " " + Bundle.getMessage("OutputCard") + s2); 576 break; 577 case SerialNode.CPNODE: 578 bitsPerCard = testNode.getNumBitsPerCard(); 579 numInputCards = testNode.numInputCards(); //2; 580 numOutputCards = testNode.numOutputCards(); //2; 581 numIOXInputCards = testNode.numInputCards() - 2; 582 numIOXOutputCards= testNode.numOutputCards()- 2; 583 if(numInputCards > 1) s1 = "s"; 584 if(numOutputCards > 1) s2 = "s"; 585 nodeText1.setText(" CPNODE - " + bitsPerCard + " " +Bundle.getMessage("BitsPerCard")); 586 nodeText2.setText(numInputCards + " " + Bundle.getMessage("InputCard") + s1 + 587 ", " + numOutputCards + " " + Bundle.getMessage("OutputCard") + s2 + 588 " IOX: " + numIOXInputCards + " " + Bundle.getMessage("InputsTitle") + 589 ", " + numIOXOutputCards + " " + Bundle.getMessage("OutputsTitle")); 590 invertWrapButton.setSelected(testNodeType == SerialNode.CPNODE); 591 break; 592 case SerialNode.CPMEGA: 593 numIOXInputCards = 0; 594 numIOXOutputCards= 0; 595 nodeText1.setText("CPMEGA - " + bitsPerCard + " " + Bundle.getMessage("BitsPerCard")); 596 break; 597 case SerialNode.ESP32NODE: 598 // No onboard cards at all (unlike CPNODE's 2+2), so unlike CPNODE's 599 // "numOutputCards - 2" here, IOX counts equal the raw counts directly. 600 bitsPerCard = testNode.getNumBitsPerCard(); 601 numInputCards = testNode.numInputCards(); 602 numOutputCards = testNode.numOutputCards(); 603 numIOXInputCards = numInputCards; 604 numIOXOutputCards= numOutputCards; 605 if(numInputCards > 1) s1 = "s"; 606 if(numOutputCards > 1) s2 = "s"; 607 nodeText1.setText(" ESP32Node - " + bitsPerCard + " " +Bundle.getMessage("BitsPerCard")); 608 nodeText2.setText(numInputCards + " " + Bundle.getMessage("InputCard") + s1 + 609 ", " + numOutputCards + " " + Bundle.getMessage("OutputCard") + s2 + 610 " IOX: " + numIOXInputCards + " " + Bundle.getMessage("InputsTitle") + 611 ", " + numIOXOutputCards + " " + Bundle.getMessage("OutputsTitle")); 612 break; 613 default: 614 nodeText1.setText("Unknown Node Type "+testNodeType); 615 break; 616 } 617// here insert code for new types of C/MRI nodes 618 } 619 statusText1.setVisible(true); 620 statusText2.setVisible(true); 621 622 } 623 624 /** 625 * Handle run button in Diagnostic Frame. 626 * @param e unused. 627 */ 628 public void runButtonActionPerformed(java.awt.event.ActionEvent e) { 629 // Ignore button if test is already running 630 if (!testRunning) { 631 // Read the user entered data, and report any errors 632 if (readSetupData()) { 633 if (outTest) { 634 // Initialize output test 635 if (initializeOutputTest()) { 636 // Run output test 637 runOutputTest(); 638 } 639 } else if (wrapTest) { 640 // Initialize wraparound test 641 if (initializeWraparoundTest()) { 642 // Run wraparound test 643 runWraparoundTest(); 644 } 645 } 646 } 647 } 648 } 649 650 /** 651 * Read data in Diagnostic Frame, get node data, and test 652 * for consistency. 653 * If errors are found, the errors are noted in the status panel 654 * of the Diagnostic Frame. 655 * 656 * @return 'true' if no errors are found, 'false' if errors are found 657 */ 658 protected boolean readSetupData() { 659 // determine test type 660// outTest = outputButton.isSelected(); 661// wrapTest = wrapButton.isSelected(); 662 switch(selTestType) 663 { 664 case testType_Outputs: 665 outTest = true; 666 wrapTest= false; 667 break; 668 case testType_Wraparound: 669 outTest = false; 670 wrapTest= true; 671 break; 672 case testType_SendCommand: 673 case testType_WriteBytes: 674 outTest = false; 675 wrapTest= false; 676 break; 677 default: 678 log.debug("default case in testSelectBox switch"); 679 } 680 681 // get the SerialNode corresponding to this node address 682 testNode = (SerialNode) _memo.getTrafficController().getNodeFromAddress(testNodeAddr); 683 if (testNode == null) { 684 statusText1.setText(Bundle.getMessage("DiagnosticError3")); 685 statusText1.setVisible(true); 686 return (false); 687 } 688 // determine if node is SMINI, USIC_SUSIC, or 689 int type = testNode.getNodeType(); 690 isSMINI = (type == SerialNode.SMINI); 691 isUSIC_SUSIC = (type == SerialNode.USIC_SUSIC); 692 isCPNODE = (type == SerialNode.CPNODE); 693 isESP32NODE = (type == SerialNode.ESP32NODE); 694 // Here insert code for other type nodes 695 // initialize numInputCards, numOutputCards, and numCards 696 numOutputCards = testNode.numOutputCards(); 697 numInputCards = testNode.numInputCards(); 698 numCards = numOutputCards + numInputCards; 699 700 // read setup data - Out Card field 701 try { 702 outCardNum = Integer.parseInt(outCardField.getText()); 703 } catch (Exception e) { 704 statusText1.setText(Bundle.getMessage("DiagnosticError4")); 705 statusText1.setVisible(true); 706 return (false); 707 } 708 // Check for consistency with Node definition 709 if (isUSIC_SUSIC) { 710 if ((outCardNum < 0) || (outCardNum >= numCards)) { 711 statusText1.setText(Bundle.getMessage("DiagnosticError5", Integer.toString(numCards - 1))); 712 statusText1.setVisible(true); 713 return (false); 714 } 715 if (!testNode.isOutputCard(outCardNum)) { 716 statusText1.setText(Bundle.getMessage("DiagnosticError6")); 717 statusText1.setVisible(true); 718 return (false); 719 } 720 } 721 if (isSMINI && ((outCardNum < 0) || (outCardNum > 1))) { 722 statusText1.setText(Bundle.getMessage("DiagnosticError7")); 723 statusText1.setVisible(true); 724 return (false); 725 } 726 if (isCPNODE && (!testNode.isOutputCard(outCardNum+2))) { 727 statusText1.setText(Bundle.getMessage("DiagnosticError6")); 728 statusText1.setVisible(true); 729 return (false); 730 } 731 // ESP32Node's typed Out Card field is 1-based (Card 1 = the first real 732 // card, 0x20/A) to match its on-screen "Card N" label -- unlike 733 // CPNODE's field above, which is 0-based internally even though its 734 // label shows +2. So the typed number converts to a raw 735 // cardTypeLocation index via -1, not +2 or +1. Card 1 typed -> raw 736 // index 0. Guard against 0 or negative input first (raw index -1 737 // would be an ArrayIndexOutOfBoundsException, not just "not a card"). 738 if (isESP32NODE && (outCardNum < 1)) { 739 statusText1.setText(Bundle.getMessage("DiagnosticError6")); 740 statusText1.setVisible(true); 741 return (false); 742 } 743 if (isESP32NODE && (!testNode.isOutputCard(outCardNum-1))) { 744 statusText1.setText(Bundle.getMessage("DiagnosticError6")); 745 statusText1.setVisible(true); 746 return (false); 747 } 748 749 if (outTest) { 750 // read setup data - Observation Delay field 751 try { 752 obsDelay = Integer.parseInt(obsDelayField.getText()); 753 } catch (Exception e) { 754 statusText1.setText(Bundle.getMessage("DiagnosticError8")); 755 statusText1.setVisible(true); 756 return (false); 757 } 758 } 759 760 if (wrapTest) { 761 // read setup data - In Card field 762 try { 763 inCardNum = Integer.parseInt(inCardField.getText()); 764 } catch (Exception e) { 765 statusText1.setText(Bundle.getMessage("DiagnosticError9")); 766 statusText1.setVisible(true); 767 return (false); 768 } 769 // Check for consistency with Node definition 770 if (isUSIC_SUSIC) { 771 if ((inCardNum < 0) || (inCardNum >= numCards)) { 772 statusText1.setText(Bundle.getMessage("DiagnosticError10", Integer.toString(numCards - 1))); 773 statusText1.setVisible(true); 774 return (false); 775 } 776 if (!testNode.isInputCard(inCardNum)) { 777 statusText1.setText(Bundle.getMessage("DiagnosticError11")); 778 statusText1.setVisible(true); 779 return (false); 780 } 781 } 782 if (isSMINI && (inCardNum != 2)) { 783 statusText1.setText(Bundle.getMessage("DiagnosticError12")); 784 statusText1.setVisible(true); 785 return (false); 786 } 787 788 // read setup data - Filtering Delay field 789 try { 790 filterDelay = Integer.parseInt(filterDelayField.getText()); 791 } catch (Exception e) { 792 statusText1.setText(Bundle.getMessage("DiagnosticError13")); 793 statusText1.setVisible(true); 794 return (false); 795 } 796 } 797 798 // complete initialization of output card 799 portsPerCard = (testNode.getNumBitsPerCard()) / 8; 800 801 if (testNodeType == SerialNode.CPNODE) 802 begOutByte = (testNode.getOutputCardIndex(outCardNum+2)) * portsPerCard; 803 else if (testNodeType == SerialNode.ESP32NODE) 804 begOutByte = (testNode.getOutputCardIndex(outCardNum-1)) * portsPerCard; 805 else 806 begOutByte = (testNode.getOutputCardIndex(outCardNum)) * portsPerCard; 807 808 endOutByte = begOutByte + portsPerCard - 1; 809 nOutBytes = numOutputCards * portsPerCard; 810 811 // if wraparound test, complete initialization of the input card 812 if (wrapTest) { 813 begInByte = (testNode.getInputCardIndex(inCardNum)) * portsPerCard; 814 endInByte = begInByte + portsPerCard - 1; 815 nInBytes = numInputCards * portsPerCard; 816 } 817 return (true); 818 } 819 820 /** 821 * Handle continue button in Diagnostic Frame. 822 * @param e unused. 823 */ 824 public void continueButtonActionPerformed(java.awt.event.ActionEvent e) { 825 if (testRunning && testSuspended) { 826 testSuspended = false; 827 if (wrapTest) { 828 statusText1.setText(Bundle.getMessage("StatusRunningWraparoundTest")); 829 statusText1.setVisible(true); 830 } 831 } 832 } 833 834 /** 835 * Handle Stop button in Diagnostic Frame. 836 * @param e unused. 837 */ 838 public void stopButtonActionPerformed(java.awt.event.ActionEvent e) { 839 // Ignore button push if test is not running, else change flag 840 if (testRunning) { 841 if (outTest) { 842 stopOutputTest(); 843 } else if (wrapTest) { 844 stopWraparoundTest(); 845 } 846 testRunning = false; 847 } 848 } 849 850 /** 851 * Halt Poll button handler 852 * Polling should be halted when executing diagnostics so as not to 853 * interfere with the test sequences. 854 */ 855 public void haltpollButtonActionPerformed() { 856 SerialTrafficController stc = _memo.getTrafficController(); 857 stc.setPollNetwork(!stc.getPollNetwork()); 858 if (stc.getPollNetwork()) 859 haltPollButton.setText(Bundle.getMessage("HaltPollButtonText")); 860 else 861 haltPollButton.setText(Bundle.getMessage("ResumePollButtonText")); 862 } 863/** 864 * Initialize an Output Test. 865 * If errors are found, the errors are noted in the status panel of the Diagnostic Frame. 866 * 867 * @return 'true' if successfully initialized, 'false' if errors are found 868 * Added synchronized 869 */ 870 synchronized protected boolean initializeOutputTest() { 871 // clear all output bytes for this node 872 for (int i = 0; i < nOutBytes; i++) { 873 outBytes[i] = 0; 874 } 875 // check the entered delay--if too short an overrun could occur 876 // where the computer program is ahead of buffered serial output 877 if (obsDelay < 250) { 878 obsDelay = 250; 879 } 880 // Set up beginning LED on position 881 curOutByte = begOutByte; 882 curOutBit = 0; 883 // Send initialization message 884 _memo.getTrafficController().sendSerialMessage((SerialMessage) testNode.createInitPacket(), curFrame); 885 try { 886 // Wait for initialization to complete 887 wait(1000); 888 } catch (InterruptedException e) { 889 // means done 890 log.debug("interrupted"); 891 return false; 892 } 893 // Initialization was successful 894 numIterations = 0; 895 testRunning = true; 896 return true; 897 } 898 899 /** 900 * Run an Output Test. 901 */ 902 protected void runOutputTest() { 903 // Set up timer to update output pattern periodically 904 outTimer = new Timer(obsDelay, new ActionListener() { 905 @Override 906 public void actionPerformed(ActionEvent evnt) { 907 if (testRunning && outTest) { 908 int[] outBitPattern = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; 909 String[] portID = {"A", "B", "C", "D"}; 910 911 // set new pattern 912 // Invert bit polarity if selected (usefull for Common Anode LEDs) 913 if (invertOutButton.isSelected()) 914 for (int i=0; i<8; i++) { outBitPattern[i] = (~outBitPattern[i]); } 915 916 outBytes[curOutByte] = (byte) outBitPattern[curOutBit]; 917 // send new pattern 918 SerialMessage m = createOutPacket(); 919 m.setTimeout(50); 920 _memo.getTrafficController().sendSerialMessage(m, curFrame); 921 // update status panel to show bit that is on 922 statusText1.setText(Bundle.getMessage("StatusLine3", portID[curOutByte - begOutByte], Integer.toString(curOutBit))); 923 statusText1.setVisible(true); 924 StringBuilder st = new StringBuilder(); 925 for (int i = begOutByte; i <= endOutByte; i++) { 926 st.append(" "); 927 for (int j = 0; j < 8; j++) { 928 if ((i == curOutByte) && (j == curOutBit)) { 929 st.append("1 "); 930 } else { 931 st.append("0 "); 932 } 933 } 934 } 935 // Was st.reverse().toString() -- that reversed the WHOLE 936 // string char-by-char, which flipped bit order within 937 // each byte to MSB-left/LSB-right AND (for multi-byte 938 // cards) reversed the order the byte-groups themselves 939 // appeared in. As curOutBit climbed 0->7, the "1" in the 940 // reversed string moved right-to-left, not left-to-right. 941 // Dropping the reversal displays the string exactly as 942 // built above: bit0 leftmost within each byte (ascending, 943 // matching the convention used elsewhere in this project), 944 // byte begOutByte's group leftmost for multi-byte cards -- 945 // so the walking-bit test now visibly sweeps left to right. 946 statusText2.setText(st.toString()); //statusText2 947 statusText2.setVisible(true); 948 // update bit pattern for next entry 949 curOutBit++; 950 if (curOutBit > 7) { 951 // Move to the next byte 952 curOutBit = 0; 953 outBytes[curOutByte] = 0; 954 curOutByte++; 955 if (curOutByte > endOutByte) { 956 // Pattern complete, recycle to first byte 957 curOutByte = begOutByte; 958 numIterations++; 959 } 960 } 961 } 962 } 963 }); 964 965 // start timer 966 outTimer.start(); 967 } 968 969 /** 970 * Stop an Output Test. 971 */ 972 protected void stopOutputTest() { 973 if (testRunning && outTest) { 974 // Stop the timer 975 outTimer.stop(); 976 // Update the status 977 statusText1.setText(Bundle.getMessage("StatusLine4", Integer.toString(numIterations))); 978 statusText1.setVisible(true); 979 statusText2.setText(" "); 980 statusText2.setVisible(true); 981 } 982 } 983 984 /** 985 * Transmit an Initialize message to the test node. 986 * 987 * @return 'true' if message sent successfully 988 */ 989 synchronized protected boolean sendInitalizePacket() { 990 // Send initialization message 991 _memo.getTrafficController().sendSerialMessage((SerialMessage) testNode.createInitPacket(), curFrame); 992 try { 993 // Wait for initialization to complete 994 wait(1000); 995 } catch (InterruptedException e) { 996 log.debug("interrupted"); 997 return false; 998 } 999 1000 return true; 1001 } 1002 1003 /** 1004 * Initialize a Wraparound Test. 1005 * If errors are found, the errors are noted in the status panel of the Diagnostic 1006 * Frame. 1007 * 1008 * @return 'true' if successfully initialized, 'false' if errors are found 1009 */ 1010 synchronized protected boolean initializeWraparoundTest() { 1011 // clear all output bytes for this node 1012 for (int i = 0; i < nOutBytes; i++) { 1013 outBytes[i] = 0; 1014 } 1015 // Set up beginning output values 1016 curOutByte = begOutByte; 1017 curOutValue = 0; 1018 1019 if (!sendInitalizePacket()) 1020 return false; 1021 1022 // Clear error count 1023 numErrors = 0; 1024 numIterations = 0; 1025 // Initialize running flags 1026 testRunning = true; 1027 testSuspended = false; 1028 waitingOnInput = false; 1029 needInputTest = false; 1030 count = 50; 1031 compareErr.setText(" "); 1032 1033 return true; 1034 } 1035 1036 /** 1037 * Run a Wraparound Test. 1038 */ 1039 protected void runWraparoundTest() { 1040 // Display Status Message 1041 statusText1.setText(Bundle.getMessage("StatusRunningWraparoundTest")); 1042 statusText1.setVisible(true); 1043 1044 // Set up timer to update output pattern periodically 1045 wrapTimer = new Timer(100, new ActionListener() { 1046 @Override 1047 public void actionPerformed(ActionEvent evnt) { 1048 if (testRunning && !testSuspended) { 1049 if (waitingOnInput) { 1050 count--; 1051 if (count == 0) { 1052 statusText2.setText(Bundle.getMessage("StatusLine5")); 1053 statusText2.setVisible(true); 1054 } 1055 } else { 1056 // compare input with previous output if needed 1057 if (needInputTest) { 1058 needInputTest = false; 1059 boolean comparisonError = false; 1060 // compare input and output bytes 1061 int j = 0; 1062 for (int i = begInByte; i <= endInByte; i++, j++) 1063 { 1064 if (invertWrapButton.isSelected()) { inBytes[i] = (byte) ~inBytes[j]; 1065 } 1066 1067 if (inBytes[i] != wrapBytes[j]) { 1068 comparisonError = true; 1069 } 1070 } 1071 if (comparisonError) { 1072 // report error and suspend test 1073 statusText1.setText(Bundle.getMessage("StatusLine6", 1074 Bundle.getMessage("ButtonStop"), Bundle.getMessage("ButtonContinue"))); 1075 statusText1.setVisible(true); 1076 StringBuilder st = new StringBuilder(Bundle.getMessage("StatusLine7pt1")); 1077 for (int i = begOutByte; i <= endOutByte; i++) { 1078 st.append(" "); 1079 st.append(Integer.toHexString((outBytes[i]) & 0x000000ff).toUpperCase()); 1080 } 1081 st.append(" "); // spacer 1082 st.append(Bundle.getMessage("StatusLine7pt2")); 1083 for (int i = begInByte; i <= endInByte; i++) { 1084 st.append(" "); 1085 st.append(Integer.toHexString((inBytes[i]) & 0x000000ff).toUpperCase()); 1086 } 1087 compareErr.setText(st.toString()); //statusText2 1088 compareErr.setVisible(true); 1089 numErrors++; 1090 testSuspended = true; 1091 return; 1092 } 1093 } 1094 1095 // send next output pattern 1096 outBytes[curOutByte] = (byte) curOutValue; 1097 if (isSMINI) { 1098 // If SMINI, send same pattern to both output cards 1099 if (curOutByte > 2) { 1100 outBytes[curOutByte - 3] = (byte) curOutValue; 1101 } else { 1102 outBytes[curOutByte + 3] = (byte) curOutValue; 1103 } 1104 } 1105 SerialMessage m = createOutPacket(); 1106 // wait for signal to settle down if filter delay 1107 m.setTimeout(50 + filterDelay); 1108 _memo.getTrafficController().sendSerialMessage(m, curFrame); 1109 1110 // update Status area 1111 short[] outBitPattern = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; 1112 String[] portID = {"A", "B", "C", "D"}; 1113 StringBuilder st = new StringBuilder(Bundle.getMessage("PortLabel")); 1114 StringBuilder bp = new StringBuilder(" "); 1115 st.append(portID[curOutByte - begOutByte]); 1116 st.append(", "); 1117 st.append(Bundle.getMessage("PatternLabel")); 1118 for (int j = 0; j < 8; j++) { 1119 if ((curOutValue & outBitPattern[j]) != 0) { 1120 bp.append("1 "); 1121 } else { 1122 bp.append("0 "); 1123 } 1124 } 1125 // Reverse the displayed output string to put bit zero on the right 1126 //----------------------------------------------------------------- 1127 statusText2.setText(st.toString()+bp.reverse().toString()); //statusText2 1128 statusText2.setVisible(true); 1129 1130 // set up for testing input returned 1131 int k = 0; 1132 for (int i = begOutByte; i <= endOutByte; i++, k++) { 1133 wrapBytes[k] = outBytes[i]; 1134 } 1135 waitingOnInput = true; 1136 needInputTest = true; 1137 count = 50; 1138 // send poll 1139 _memo.getTrafficController().sendSerialMessage( 1140 SerialMessage.getPoll(testNodeAddr), curFrame); 1141 1142 // update output pattern for next entry 1143 curOutValue++; 1144 if (curOutValue > 255) { 1145 // Move to the next byte 1146 curOutValue = 0; 1147 outBytes[curOutByte] = 0; 1148 if (isSMINI) { 1149 // If SMINI, clear ports of both output cards 1150 if (curOutByte > 2) { 1151 outBytes[curOutByte - 3] = 0; 1152 } else { 1153 outBytes[curOutByte + 3] = 0; 1154 } 1155 } 1156 curOutByte++; 1157 if (curOutByte > endOutByte) { 1158 // Pattern complete, recycle to first port (byte) 1159 curOutByte = begOutByte; 1160 numIterations++; 1161 } 1162 } 1163 } 1164 } 1165 } 1166 }); 1167 1168 // start timer 1169 wrapTimer.start(); 1170 } 1171 1172 /** 1173 * Stop a Wraparound Test. 1174 */ 1175 protected void stopWraparoundTest() { 1176 if (testRunning && wrapTest) { 1177 // Stop the timer 1178 wrapTimer.stop(); 1179 // Update the status 1180 statusText1.setText(Bundle.getMessage("StatusLine8", Integer.toString(numErrors))); 1181 statusText1.setVisible(true); 1182 statusText2.setText(Bundle.getMessage("StatusLine9", Integer.toString(numIterations))); 1183 statusText2.setVisible(true); 1184 } 1185 } 1186 1187 /** 1188 * Create an Transmit packet (SerialMessage). 1189 * @return loaded packet to transmit 1190 */ 1191 SerialMessage createOutPacket() { 1192 // Count the number of DLE's to be inserted 1193 int nDLE = 0; 1194 for (int i = 0; i < nOutBytes; i++) { 1195 if ((outBytes[i] == 2) || (outBytes[i] == 3) || (outBytes[i] == 16)) { 1196 nDLE++; 1197 } 1198 } 1199 // Create a Serial message and add initial bytes 1200 SerialMessage m = new SerialMessage(nOutBytes + nDLE + 2); 1201 m.setElement(0, testNodeAddr + 65); // node address 1202 m.setElement(1, 84); // 'T' 1203 // Add output bytes 1204 int k = 2; 1205 for (int i = 0; i < nOutBytes; i++) { 1206 // perform C/MRI required DLE processing 1207 if ((outBytes[i] == 2) || (outBytes[i] == 3) || (outBytes[i] == 16)) { 1208 m.setElement(k, 16); // DLE 1209 k++; 1210 } 1211 // add output byte 1212 m.setElement(k, outBytes[i]); 1213 k++; 1214 } 1215 return m; 1216 } 1217 1218 /** 1219 * Handle poll node button in Diagnostic Frame. 1220 * @param e unused. 1221 */ 1222 public synchronized void pollButtonActionPerformed(java.awt.event.ActionEvent e) { 1223 portsPerCard = (testNode.getNumBitsPerCard()) / 8; 1224 begInByte = (testNode.getInputCardIndex(inCardNum)) * portsPerCard; 1225 endInByte = begInByte + portsPerCard; 1226 nInBytes = numInputCards * portsPerCard; 1227 1228 needInputTest = true; 1229 waitingOnInput = true; 1230 waitingResponse = false; 1231 count = 30; 1232 1233 // send poll 1234 _memo.getTrafficController().sendSerialMessage(SerialMessage.getPoll(testNodeAddr), curFrame); 1235 statusText2.setText(""); 1236 nodeReplyText.setText(""); 1237 1238 // display input data bytes or timeout 1239 pollNodeReadReply(); 1240 } 1241 1242 1243 /** 1244 * Run a Poll/Response Test. 1245 * Returns number of bytes read or a timeout 1246 */ 1247 protected synchronized void pollNodeReadReply() { 1248 // Set up timer to poll the node and report data or a timeout 1249 pollTimer = new Timer(100, new ActionListener() { 1250 @Override 1251 public void actionPerformed(ActionEvent evnt) { 1252 if (waitingOnInput) { 1253 count--; 1254 if (count == 0) { 1255 nodeReplyText.setText(Bundle.getMessage("PollTimeOut")); 1256 waitingOnInput = false; 1257 pollTimer.stop(); 1258 return; 1259 } 1260 } 1261 else 1262 { 1263 if (waitingResponse) 1264 { 1265 nodeReplyText.setText(Bundle.getMessage("InByteCount",replyCount)); 1266 nodeReplyText.setVisible(true); 1267 waitingOnInput = false; 1268 pollTimer.stop(); 1269 return; 1270 } 1271 } 1272 } 1273 }); 1274 1275 // start timer 1276 pollTimer.start(); 1277 waitingResponse = true; 1278 } 1279 1280 /** 1281 * Transmit bytes to selected output card starting with out card number 1282 * for number of bytes entered. 1283 * If inverted checked, data is flipped. 1284 * @param e unused. 1285 */ 1286 public synchronized void sendButtonActionPerformed(java.awt.event.ActionEvent e) { 1287 1288 portsPerCard = (testNode.getNumBitsPerCard()) / 8; 1289 byte b[] = StringUtil.bytesFromHexString(writeBytesField.getText()); 1290 totalOutBytes = (numOutputCards*portsPerCard); 1291 statusText1.setText(" "); 1292 1293 // Validate number of bytes entered 1294 if (b.length == 0) { 1295 statusText1.setText(Bundle.getMessage("WriteBytesError1")); 1296 return; 1297 } 1298 if (b.length > portsPerCard) { 1299 statusText1.setText(Bundle.getMessage("WriteBytesError2",portsPerCard)); 1300 return; 1301 } 1302 outCardNum = Integer.parseInt(writeCardField.getText()); 1303 1304 if (testNodeType == SerialNode.CPNODE) 1305 { 1306 if (!testNode.isOutputCard(outCardNum+2)) { 1307 statusText1.setText(Bundle.getMessage("DiagnosticError6")); 1308 return; 1309 } 1310 begOutByte = (testNode.getOutputCardIndex(outCardNum+2)) * portsPerCard; 1311 } 1312 else if (testNodeType == SerialNode.ESP32NODE) 1313 { 1314 if ((outCardNum < 1) || (!testNode.isOutputCard(outCardNum-1))) { 1315 statusText1.setText(Bundle.getMessage("DiagnosticError6")); 1316 return; 1317 } 1318 begOutByte = (testNode.getOutputCardIndex(outCardNum-1)) * portsPerCard; 1319 } 1320 else 1321 { 1322 if (!testNode.isOutputCard(outCardNum)) { 1323 statusText1.setText(Bundle.getMessage("DiagnosticError6")); 1324 return; 1325 } 1326 begOutByte = (testNode.getOutputCardIndex(outCardNum)) * portsPerCard; 1327 } 1328 // Zero the output buffer 1329 int zero = (invertWriteButton.isSelected()) ? -1:0; 1330 1331 for (int i=0; i<totalOutBytes; i++) 1332 { 1333 outBytes[i] = (byte) zero; 1334 } 1335 1336 int j=begOutByte; 1337 for (int i=0; i<portsPerCard; i++) 1338 { 1339 outBytes[j] = (invertWriteButton.isSelected()) ? (byte) ~b[i]: (byte) b[i]; 1340 j++; 1341 } 1342 nOutBytes = totalOutBytes; 1343 1344 SerialMessage m = createOutPacket(); 1345 m.setTimeout(50); 1346 _memo.getTrafficController().sendSerialMessage(m, curFrame); 1347 } 1348 1349 /** 1350 * {@inheritDoc} 1351 */ 1352 @Override 1353 public void message(SerialMessage m) { 1354 } // Ignore for now 1355 1356 /** 1357 * Reply notification implementing SerialListener interface 1358 */ 1359 @Override 1360 public synchronized void reply(SerialReply l) { 1361 // Test if waiting on this input 1362 if (waitingOnInput && (l.isRcv()) && (testNodeAddr == l.getUA())) { 1363 // This is a receive message for the node being tested 1364 for (int i = begInByte; i <= endInByte; i++) { 1365 // get data bytes, skipping over node address and 'R' 1366 inBytes[i] = (byte) l.getElement(i + 2); 1367 } 1368 replyCount = (l.getNumDataElements()-2); 1369 1370 waitingOnInput = false; 1371 } 1372 } 1373 1374 /** 1375 * Stop operation when window closing 1376 */ 1377 @Override 1378 public void windowClosing(java.awt.event.WindowEvent e) { 1379 if (testRunning) { 1380 if (outTest) { 1381 stopOutputTest(); 1382 } else if (wrapTest) { 1383 stopWraparoundTest(); 1384 } 1385 } 1386 super.windowClosing(e); 1387 } 1388 1389 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DiagnosticFrame.class); 1390}