001package jmri.jmrix.can.cbus; 002 003import jmri.ProgrammingMode; 004import jmri.jmrix.AbstractMessage; 005import jmri.jmrix.can.CanFrame; 006import jmri.jmrix.can.CanMessage; 007import jmri.jmrix.can.CanMutableFrame; 008import jmri.jmrix.can.CanReply; 009 010 011/** 012 * Class to allow use of CBUS concepts to access the underlying can message. 013 * <p> 014 * Methods that take a CanMessage or CanReply as argument: 015 * <ul> 016 * <li>CanMessage - Can Frame being sent by JMRI 017 * <li>CanReply - Can Frame being received by JMRI 018 * </ul> 019 * https://github.com/MERG-DEV/CBUSlib. 020 * 021 * @author Andrew Crosland Copyright (C) 2008 022 * @author Steve Young (C) 2018 023 */ 024public class CbusMessage { 025 026 /** 027 * Return a CanReply for use in sensors, turnouts + light 028 * If a response event, set to normal event 029 * In future, this may also translate extended messages down to normal messages. 030 * 031 * @param original CanReply to be coverted to normal opc 032 * @return new CanReply perhaps converted from response OPC to normal OPC. 033 */ 034 public static CanReply opcRangeToStl(CanReply original){ 035 CanReply msg = new CanReply(original); 036 int opc = getOpcode(msg); 037 // log.debug(" about to check opc {} ",opc); 038 switch (opc) { 039 case CbusConstants.CBUS_ARON: 040 msg.setElement(0, CbusConstants.CBUS_ACON); 041 break; 042 case CbusConstants.CBUS_AROF: 043 msg.setElement(0, CbusConstants.CBUS_ACOF); 044 break; 045 case CbusConstants.CBUS_ARSON: 046 msg.setElement(0, CbusConstants.CBUS_ASON); 047 break; 048 case CbusConstants.CBUS_ARSOF: 049 msg.setElement(0, CbusConstants.CBUS_ASOF); 050 break; 051 default: 052 break; 053 } 054 return msg; 055 } 056 057 058 /** 059 * Get the Op Code from the CanMessage 060 * 061 * @param am CanMessage or CanReply 062 * @return OPC of the message 063 */ 064 public static int getOpcode(AbstractMessage am) { 065 return am.getElement(0); 066 } 067 068 /** 069 * Get the Data Length from the CanMessage 070 * 071 * @param am CanMessage or CanReply 072 * @return the message data length 073 */ 074 public static int getDataLength(AbstractMessage am) { 075 return am.getElement(0) >> 5; 076 } 077 078 /** 079 * Get the Node Number from a CanFrame Event 080 * 081 * @param am CanMessage or CanReply 082 * @return the node number if not a short event 083 */ 084 public static int getNodeNumber(AbstractMessage am) { 085 if (isEvent(am) && !isShort(am) ) { 086 return am.getElement(1) * 256 + am.getElement(2); 087 } else { 088 return 0; 089 } 090 } 091 092 /** 093 * Get the Event Number from a CBUS Event 094 * 095 * @param m CanMessage or CanReply 096 * @return the message event ( device ) number, else -1 if not an event. 097 */ 098 public static int getEvent(AbstractMessage m) { 099 if (isEvent(m)) { 100 return m.getElement(3) * 256 + m.getElement(4); 101 } else { 102 return -1; 103 } 104 } 105 106 /** 107 * Get the Event Type ( on or off ) from a CanFrame 108 * 109 * @param am CanFrame or CanReply 110 * @return CbusConstant EVENT_ON or EVENT_OFF 111 */ 112 public static int getEventType(AbstractMessage am) { 113 if ( CbusOpCodes.isOnEvent(am.getElement(0))) { 114 return CbusConstants.EVENT_ON; 115 } else { 116 return CbusConstants.EVENT_OFF; 117 } 118 } 119 120 /** 121 * Tests if a CanMessage or CanReply is an Event. 122 * Performs Extended and RTR check. 123 * Adheres to cbus spec, ie on off responses to an AREQ are events. 124 * 125 * @param am CanMessage or CanReply 126 * @return True if event, else False. 127 */ 128 public static boolean isEvent(AbstractMessage am) { 129 if ( am instanceof CanFrame && ((CanFrame)am).extendedOrRtr()){ 130 return false; 131 } 132 return CbusOpCodes.isEvent(am.getElement(0)); 133 } 134 135 /** 136 * Tests if CanFrame is a short event 137 * 138 * @param am CanReply or CanMessage 139 * @return true if Short Event, else false 140 */ 141 public static boolean isShort(AbstractMessage am) { 142 return CbusOpCodes.isShortEvent(am.getElement(0)); 143 } 144 145 /** 146 * Set the CAN ID within a CanMessage or CanReply Header 147 * 148 * @param am CanMessage or CanReply 149 * @param id CAN ID 150 */ 151 public static void setId(AbstractMessage am, int id) throws IllegalArgumentException { 152 if (am instanceof CanMutableFrame){ 153 CanMutableFrame m = (CanMutableFrame) am; 154 int update = m.getHeader(); 155 if (m.isExtended()) { 156 throw new IllegalArgumentException("No CAN ID Concept on Extended CBUS CAN Frame."); 157 } else { 158 if ((id & ~0x7f) != 0) { 159 throw new IllegalArgumentException("invalid standard ID value: " + id); 160 } 161 m.setHeader((update & ~0x07f) | id); 162 } 163 } 164 else { 165 throw new IllegalArgumentException(am + " is Not a CanMutableFrame"); 166 } 167 } 168 169 /** 170 * Set the priority within a CanMessage or CanReply Header. 171 * 172 * @param am CanMessage or CanReply 173 * @param pri Priority 174 */ 175 public static void setPri(AbstractMessage am, int pri) throws IllegalArgumentException { 176 if (am instanceof CanMutableFrame){ 177 CanMutableFrame m = (CanMutableFrame) am; 178 if ((pri & ~0x0F) != 0) { 179 throw new IllegalArgumentException("Invalid CBUS Priority value: " + pri); 180 } 181 if (m.isExtended()) { 182 throw new IllegalArgumentException("Extended CBUS CAN Frames do not have a priority concept."); 183 } else { 184 m.setHeader((m.getHeader() & ~0x780) | (pri << 7)); 185 } 186 } 187 else { 188 throw new IllegalArgumentException(am + " is Not a CanMutableFrame"); 189 } 190 } 191 192 /** 193 * Returns string form of a CanMessage ( a Can Frame sent by JMRI ) 194 * Short / Long events converted to Sensor / Turnout / Light hardware address 195 * message priority not indicated 196 * @param m CanReply or CanMessage 197 * @return String of hardware address form 198 */ 199 public static String toAddress(AbstractMessage m) { 200 switch (m.getElement(0)) { 201 case CbusConstants.CBUS_ACON: 202 // + form 203 return "+n" + (m.getElement(1) * 256 + m.getElement(2)) + "e" + (m.getElement(3) * 256 + m.getElement(4)); 204 case CbusConstants.CBUS_ACOF: 205 // - form 206 return "-n" + (m.getElement(1) * 256 + m.getElement(2)) + "e" + (m.getElement(3) * 256 + m.getElement(4)); 207 case CbusConstants.CBUS_ASON: 208 // + short form 209 return "+" + (m.getElement(3) * 256 + m.getElement(4)); 210 case CbusConstants.CBUS_ASOF: 211 // - short form 212 return "-" + (m.getElement(3) * 256 + m.getElement(4)); 213 default: 214 // hex form 215 String tmp = m.toString().replaceAll("\\s*\\[[^\\]]*\\]\\s*", ""); // remove the [header] 216 return "X" + tmp.replaceAll(" ", ""); 217 } 218 } 219 220 /** 221 * Checks if a CanMessage is requesting Track Power Off 222 * 223 * @param m Can Frame Message 224 * @return boolean 225 */ 226 public static boolean isRequestTrackOff(CanMessage m) { 227 return m.getOpCode() == CbusConstants.CBUS_RTOF; 228 } 229 230 /** 231 * Checks if a CanMessage is requesting Track Power On 232 * 233 * @param m Can Frame Message 234 * @return True if outgoing track power on request 235 */ 236 public static boolean isRequestTrackOn(CanMessage m) { 237 return m.getOpCode() == CbusConstants.CBUS_RTON; 238 } 239 240 /** 241 * Get the CAN ID within a CanReply or CanMessage Header 242 * 243 * @param f CanReply or CanMessage 244 * @return CAN ID of the outgoing message 245 */ 246 public static int getId(AbstractMessage f) throws IllegalArgumentException { 247 if (f instanceof CanFrame){ 248 CanFrame cfMsg = (CanFrame) f; 249 if (cfMsg.isExtended()) { 250 return cfMsg.getHeader() & 0x1FFFFF; 251 } else { 252 return cfMsg.getHeader() & 0x7f; 253 } 254 } 255 else { 256 throw new IllegalArgumentException(f + " is Not a CanFrame"); 257 } 258 } 259 260 /** 261 * Get the priority from within the CanReply or CanMessage Header 262 * 263 * @param r CanReply or CanMessage 264 * @return Priority of the outgoing message 265 */ 266 public static int getPri(AbstractMessage r) throws IllegalArgumentException { 267 if (r instanceof CanFrame){ 268 CanFrame cfMsg = (CanFrame) r; 269 if (cfMsg.isExtended()) { 270 return (cfMsg.getHeader() >> 25) & 0x0F; 271 } else { 272 return (cfMsg.getHeader() >> 7) & 0x0F; 273 } 274 } 275 else { 276 throw new IllegalArgumentException(r + " is Not a CanFrame"); 277 } 278 } 279 280 /** 281 * Tests if CanReply is confirming Track Power Off. 282 * 283 * @param m CanReply 284 * @return True if is a Track Off notification 285 */ 286 public static boolean isTrackOff(CanReply m) { 287 return m.getOpCode() == CbusConstants.CBUS_TOF; 288 } 289 290 /** 291 * Tests if CanReply is confirming Track Power On. 292 * 293 * @param m CanReply 294 * @return True if is a Track On notification 295 */ 296 public static boolean isTrackOn(CanReply m) { 297 return m.getOpCode() == CbusConstants.CBUS_TON; 298 } 299 300 /** 301 * Tests if CanReply is a System Reset 302 * 303 * @param m CanReply 304 * @return True if emergency Stop 305 */ 306 public static boolean isArst(CanReply m) { 307 return m.getOpCode() == CbusConstants.CBUS_ARST; 308 } 309 310 /** 311 * CBUS programmer commands 312 * @param cv CV to read 313 * @param mode Programming Mode 314 * @param header CAN ID 315 * @return CanMessage ready to send 316 */ 317 static public CanMessage getReadCV(int cv, ProgrammingMode mode, int header) { 318 CanMessage m = new CanMessage(5, header); 319 m.setElement(0, CbusConstants.CBUS_QCVS); 320 m.setElement(1, CbusConstants.SERVICE_HANDLE); 321 m.setElement(2, (cv / 256) & 0xff); 322 m.setElement(3, cv & 0xff); 323 if (mode.equals(ProgrammingMode.PAGEMODE)) { 324 m.setElement(4, CbusConstants.CBUS_PROG_PAGED); 325 } else if (mode.equals(ProgrammingMode.DIRECTBITMODE)) { 326 m.setElement(4, CbusConstants.CBUS_PROG_DIRECT_BIT); 327 } else if (mode.equals(ProgrammingMode.DIRECTBYTEMODE)) { 328 m.setElement(4, CbusConstants.CBUS_PROG_DIRECT_BYTE); 329 } else { 330 m.setElement(4, CbusConstants.CBUS_PROG_REGISTER); 331 } 332 setPri(m, 0xb); 333 return m; 334 } 335 336 /** 337 * CBUS programmer commands 338 * 339 * CBUS VCVS works like a QCVS read but the programmer will first check if 340 * the CV contents are equal to the startVal. This can speed up CV reads by 341 * skipping reading of other values. 342 * 343 * @param cv CV to read 344 * @param mode Programming Mode 345 * @param startVal Hint of current CV value 346 * @param header CAN ID 347 * @return CanMessage ready to send 348 */ 349 static public CanMessage getVerifyCV(int cv, ProgrammingMode mode, int startVal, int header) { 350 CanMessage m = new CanMessage(6, header); 351 m.setElement(0, CbusConstants.CBUS_VCVS); 352 m.setElement(1, CbusConstants.SERVICE_HANDLE); 353 m.setElement(2, (cv / 256) & 0xff); 354 m.setElement(3, cv & 0xff); 355 if (mode.equals(ProgrammingMode.PAGEMODE)) { 356 m.setElement(4, CbusConstants.CBUS_PROG_PAGED); 357 } else if (mode.equals(ProgrammingMode.DIRECTBITMODE)) { 358 m.setElement(4, CbusConstants.CBUS_PROG_DIRECT_BIT); 359 } else if (mode.equals(ProgrammingMode.DIRECTBYTEMODE)) { 360 m.setElement(4, CbusConstants.CBUS_PROG_DIRECT_BYTE); 361 } else { 362 m.setElement(4, CbusConstants.CBUS_PROG_REGISTER); 363 } 364 m.setElement(5, startVal & 0xff); 365 setPri(m, 0xb); 366 return m; 367 } 368 369 /** 370 * Get a CanMessage to write a CV. 371 * @param cv Which CV, 0-65534 372 * @param val New CV value, 0-255 373 * @param mode Programming Mode 374 * @param header CAN ID 375 * @return ready to send CanMessage 376 */ 377 static public CanMessage getWriteCV(int cv, int val, ProgrammingMode mode, int header) { 378 CanMessage m = new CanMessage(6, header); 379 m.setElement(0, CbusConstants.CBUS_WCVS); 380 m.setElement(1, CbusConstants.SERVICE_HANDLE); 381 m.setElement(2, (cv / 256) & 0xff); 382 m.setElement(3, cv & 0xff); 383 if (mode.equals(ProgrammingMode.PAGEMODE)) { 384 m.setElement(4, CbusConstants.CBUS_PROG_PAGED); 385 } else if (mode.equals(ProgrammingMode.DIRECTBITMODE)) { 386 m.setElement(4, CbusConstants.CBUS_PROG_DIRECT_BIT); 387 } else if (mode.equals(ProgrammingMode.DIRECTBYTEMODE)) { 388 m.setElement(4, CbusConstants.CBUS_PROG_DIRECT_BYTE); 389 } else { 390 m.setElement(4, CbusConstants.CBUS_PROG_REGISTER); 391 } 392 m.setElement(5, val); 393 setPri(m, 0xb); 394 return m; 395 } 396 397 /** 398 * CBUS Ops mode programmer commands 399 * @param mAddress Loco Address, non-DCC format 400 * @param mLongAddr If Loco Address is a long address 401 * @param header CAN ID 402 * @param val New CV value 403 * @param cv Which CV, 0-65534 404 * @return ready to send CanMessage 405 */ 406 static public CanMessage getOpsModeWriteCV(int mAddress, boolean mLongAddr, int cv, int val, int header) { 407 CanMessage m = new CanMessage(7, header); 408 int address = mAddress; 409 m.setElement(0, CbusConstants.CBUS_WCVOA); 410 if (mLongAddr) { 411 address = address | 0xc000; 412 } 413 m.setElement(1, address / 256); 414 m.setElement(2, address & 0xff); 415 m.setElement(3, (cv / 256) & 0xff); 416 m.setElement(4, cv & 0xff); 417 m.setElement(5, CbusConstants.CBUS_OPS_BYTE); 418 m.setElement(6, val); 419 setPri(m, 0xb); 420 return m; 421 } 422 423 /** 424 * Get a CanMessage to send track power on 425 * 426 * @param header for connection CAN ID 427 * @return the CanMessage to send to request track power on 428 */ 429 static public CanMessage getRequestTrackOn(int header) { 430 CanMessage m = new CanMessage(1, header); 431 m.setElement(0, CbusConstants.CBUS_RTON); 432 setPri(m, 0xb); 433 return m; 434 } 435 436 /** 437 * Get a CanMessage to send track power off 438 * 439 * @param header for connection CAN ID 440 * @return the CanMessage to send to request track power off 441 */ 442 static public CanMessage getRequestTrackOff(int header) { 443 CanMessage m = new CanMessage(1, header); 444 m.setElement(0, CbusConstants.CBUS_RTOF); 445 setPri(m, 0xb); 446 return m; 447 } 448 449 450 // CBUS bootloader commands 451 452 /** 453 * This is a strict CBUS message to put a node into boot mode. 454 * @param nn Node Number 1-65534 455 * @param header CAN ID 456 * @return ready to send CanMessage 457 */ 458 static public CanMessage getBootEntry(int nn, int header) { 459 CanMessage m = new CanMessage(3, header); 460 m.setElement(0, CbusConstants.CBUS_BOOTM); 461 m.setElement(1, (nn / 256) & 0xFF); 462 m.setElement(2, nn & 0xFF); 463 setPri(m, 0xb); 464 return m; 465 } 466 467 /** 468 * Microchip AN247 format NOP message to set address. 469 * <p> 470 * The CBUS bootloader uses extended ID frames 471 * 472 * @param a address 473 * @param header CAN ID - overridden by call to setHeader 474 * @return ready to send CanMessage 475 */ 476 static public CanMessage getBootNop(int a, int header) { 477 CanMessage m = new CanMessage(8, header); 478 m.setExtended(true); 479 m.setHeader(0x4); 480 m.setElement(0, a & 0xFF); 481 m.setElement(1, (a / 256) & 0xFF); 482 m.setElement(2, (a / 65536) & 0xFF); 483 m.setElement(3, 0); 484 m.setElement(4, 0x0D); 485 m.setElement(5, CbusConstants.CBUS_BOOT_NOP); 486 m.setElement(6, 0); 487 m.setElement(7, 0); 488 return m; 489 } 490 491 /** 492 * Microchip AN247 format message to reset and enter normal mode. 493 * 494 * @param header CAN ID - overridden by call to setHeader 495 * @return ready to send CanMessage 496 */ 497 static public CanMessage getBootReset(int header) { 498 CanMessage m = new CanMessage(8, header); 499 m.setExtended(true); 500 m.setHeader(0x4); 501 m.setElement(0, 0); 502 m.setElement(1, 0); 503 m.setElement(2, 0); 504 m.setElement(3, 0); 505 m.setElement(4, 0x0D); 506 m.setElement(5, CbusConstants.CBUS_BOOT_RESET); 507 m.setElement(6, 0); 508 m.setElement(7, 0); 509 return m; 510 } 511 512 /** 513 * Microchip AN247 format message to initialise the bootloader and set the 514 * start address. 515 * 516 * @param a start address 517 * @param header CAN ID - overridden by call to setHeader 518 * @return ready to send CanMessage 519 */ 520 static public CanMessage getBootInitialise(int a, int header) { 521 CanMessage m = new CanMessage(8, header); 522 m.setExtended(true); 523 m.setHeader(0x4); 524 m.setElement(0, a & 0xFF); 525 m.setElement(1, (a / 256) & 0xFF); 526 m.setElement(2, (a / 65536) & 0xFF); 527 m.setElement(3, 0); 528 m.setElement(4, 0x0D); 529 m.setElement(5, CbusConstants.CBUS_BOOT_INIT); 530 m.setElement(6, 0); 531 m.setElement(7, 0); 532 return m; 533 } 534 535 /** 536 * Microchip AN247 format message to send the checksum for comparison. 537 * 538 * At time of writing [6th Feb '20] The MERG bootloader doc is incorrect and 539 * shows the checksum as being byte swapped. 540 * 541 * @param c 0-65535 2's complement of sum of all program bytes sent 542 * @param header CAN ID - overridden by call to setHeader 543 * @return ready to send CanMessage 544 */ 545 static public CanMessage getBootCheck(int c, int header) { 546 CanMessage m = new CanMessage(8, header); 547 m.setExtended(true); 548 m.setHeader(0x4); 549 m.setElement(0, 0); 550 m.setElement(1, 0); 551 m.setElement(2, 0); 552 m.setElement(3, 0); 553 m.setElement(4, 0x0D); 554 m.setElement(5, CbusConstants.CBUS_BOOT_CHECK); 555 m.setElement(6, c & 0xff); 556 m.setElement(7, (c >> 8) & 0xff); 557 return m; 558 } 559 560 /** 561 * Microchip AN247 format message to check if a module is in boot mode. 562 * 563 * @param header CAN ID - overridden by call to setHeader 564 * @return ready to send CanMessage 565 */ 566 static public CanMessage getBootTest(int header) { 567 CanMessage m = new CanMessage(8, header); 568 m.setExtended(true); 569 m.setHeader(0x4); 570 m.setElement(0, 0); 571 m.setElement(1, 0); 572 m.setElement(2, 0); 573 m.setElement(3, 0); 574 m.setElement(4, 0x0D); 575 m.setElement(5, CbusConstants.CBUS_BOOT_TEST); 576 m.setElement(6, 0); 577 m.setElement(7, 0); 578 return m; 579 } 580 581 /** 582 * CBUS bootloader v1.0 format message to request device ID. 583 * 584 * @param header CAN ID - overridden by call to setHeader 585 * @return ready to send CanMessage 586 */ 587 static public CanMessage getBootDevId(int header) { 588 CanMessage m = new CanMessage(8, header); 589 m.setExtended(true); 590 m.setHeader(0x4); 591 m.setElement(0, 0); 592 m.setElement(1, 0); 593 m.setElement(2, 0); 594 m.setElement(3, 0); 595 m.setElement(4, 0x0D); 596 m.setElement(5, CbusConstants.CBUS_BOOT_DEVID); 597 m.setElement(6, 0); 598 m.setElement(7, 0); 599 return m; 600 } 601 602 /** 603 * CBUS bootloader v1.0 format message to request bootloader ID. 604 * 605 * @param header CAN ID - overridden by call to setHeader 606 * @return ready to send CanMessage 607 */ 608 static public CanMessage getBootId(int header) { 609 CanMessage m = new CanMessage(8, header); 610 m.setExtended(true); 611 m.setHeader(0x4); 612 m.setElement(0, 0); 613 m.setElement(1, 0); 614 m.setElement(2, 0); 615 m.setElement(3, 0); 616 m.setElement(4, 0x0D); 617 m.setElement(5, CbusConstants.CBUS_BOOT_BOOTID); 618 m.setElement(6, 0); 619 m.setElement(7, 0); 620 return m; 621 } 622 623 /** 624 * CBUS bootloader v1.0 format message to set memory region write enables 625 * 626 * @param enables enable bits for memory regions 627 * @param header CAN ID - overridden by call to setHeader 628 * @return ready to send CanMessage 629 */ 630 static public CanMessage getBootEnables(int enables, int header) { 631 CanMessage m = new CanMessage(8, header); 632 m.setExtended(true); 633 m.setHeader(0x4); 634 m.setElement(0, 0); 635 m.setElement(1, 0); 636 m.setElement(2, 0); 637 m.setElement(3, 0); 638 m.setElement(4, 0x0D); 639 m.setElement(5, CbusConstants.CBUS_BOOT_ENABLES); 640 m.setElement(6, enables & 0xFF); 641 m.setElement(7, 0); 642 return m; 643 } 644 645 /** 646 * Microchip AN247 format message to write 8 bytes of data 647 * 648 * @param d data array, 8 length, values 0-255 649 * @param header CAN ID - overridden by call to setHeader 650 * @return ready to send CanMessage 651 */ 652 static public CanMessage getBootWriteData(int[] d, int header) { 653 CanMessage m = new CanMessage(d.length, header); 654 m.setExtended(true); 655 m.setHeader(0x5); 656 for (int i = 0; i < d.length; i++) { 657 m.setElement(i, d[i] & 0xff); 658 } 659 return m; 660 } 661 662 /** 663 * Microchip AN247 format message to write up to 8 bytes of data 664 * 665 * @param d data array, values 0-255 666 * @param header CAN ID - overridden by call to setHeader 667 * @return ready to send CanMessage 668 */ 669 static public CanMessage getBootWriteData(byte[] d, int header) { 670 CanMessage m = new CanMessage(d.length, header); 671 m.setExtended(true); 672 m.setHeader(0x5); 673 for (int i = 0; i < d.length; i++) { 674 m.setElement(i, d[i] & 0xff); 675 } 676 return m; 677 } 678 679 /** 680 * Tests if a message is a bootloader data write 681 * 682 * @param m message 683 * @return true if the message is a bootloader data write 684 */ 685 public static boolean isBootWriteData(CanMessage m) { 686 if (m.isExtended() && (m.getHeader() == 0x5)) { 687 return (true); 688 } 689 return (false); 690 } 691 692 /** 693 * Tests if incoming CanReply is a Boot Command Error. 694 * 695 * @param r CanReply 696 * @return True if is a Boot Command Error 697 */ 698 public static boolean isBootError(CanReply r) { 699 if (r.isExtended() && (r.getHeader() == 0x10000004) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOT_ERROR) 700 && (r.getNumDataElements() == 1)) { 701 return (true); 702 } 703 return (false); 704 } 705 706 /** 707 * Tests if incoming CanReply is a Boot Data Error. 708 * 709 * @param r CanReply 710 * @return True if is a Boot Data Error 711 */ 712 public static boolean isBootDataError(CanReply r) { 713 if (r.isExtended() && (r.getHeader() == 0x10000005) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOT_ERROR) 714 && (r.getNumDataElements() == 1)) { 715 return (true); 716 } 717 return (false); 718 } 719 720 /** 721 * Tests if incoming CanReply is a Boot Command OK. 722 * 723 * @param r CanReply 724 * @return True if is a Boot COmmand OK 725 */ 726 public static boolean isBootOK(CanReply r) { 727 if (r.isExtended() && (r.getHeader() == 0x10000004) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOT_OK) 728 && (r.getNumDataElements() == 1)) { 729 return (true); 730 } 731 return (false); 732 } 733 734 /** 735 * Tests if incoming CanReply is a Boot Data OK. 736 * 737 * @param r CanReply 738 * @return True if is a Boot Data OK 739 */ 740 public static boolean isBootDataOK(CanReply r) { 741 if (r.isExtended() && (r.getHeader() == 0x10000005) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOT_OK) 742 && (r.getNumDataElements() == 1)) { 743 return (true); 744 } 745 return (false); 746 } 747 748 /** 749 * Tests if incoming CanReply is a Boot Out of Range 750 * 751 * @param r CanReply 752 * @return True if is a Boot Data OK 753 */ 754 public static boolean isBootOutOfRange(CanReply r) { 755 if (r.isExtended() && (r.getHeader() == 0x10000004) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOT_OUT_OF_RANGE) 756 && (r.getNumDataElements() == 1)) { 757 return (true); 758 } 759 return (false); 760 } 761 762 /** 763 * Tests if incoming CanReply is a Boot Out of Range 764 * 765 * @param r CanReply 766 * @return True if is a Boot Data OK 767 */ 768 public static boolean isBootDataOutOfRange(CanReply r) { 769 if (r.isExtended() && (r.getHeader() == 0x10000005) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOT_OUT_OF_RANGE) 770 && (r.getNumDataElements() == 1)) { 771 return (true); 772 } 773 return (false); 774 } 775 776 /** 777 * Tests if incoming CanReply is a Boot Confirm. 778 * 779 * @param r CanReply 780 * @return True if is a Boot Confirm 781 */ 782 public static boolean isBootConfirm(CanReply r) { 783 if (r.isExtended() && (r.getHeader() == 0x10000004) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOTC) 784 && (r.getNumDataElements() == 1)) { 785 return (true); 786 } 787 return (false); 788 } 789 790 /** 791 * Tests if incoming CanReply is a device ID reply. 792 * 793 * @param r CanReply 794 * @return True if is a Boot Confirm 795 */ 796 public static boolean isBootDevId(CanReply r) { 797 if (r.isExtended() && (r.getHeader() == 0x10000004) && (r.getElement(0) == CbusConstants.CBUS_EXT_DEVID) 798 && (r.getNumDataElements() == 7)) { 799 return (true); 800 } 801 return (false); 802 } 803 804 /** 805 * Tests if incoming CanReply is a bootloader ID reply. 806 * 807 * @param r CanReply 808 * @return True if is a Boot Confirm 809 */ 810 public static boolean isBootId(CanReply r) { 811 if (r.isExtended() && (r.getHeader() == 0x10000004) && (r.getElement(0) == CbusConstants.CBUS_EXT_BOOTID) 812 && (r.getNumDataElements() == 5)) { 813 return (true); 814 } 815 return (false); 816 } 817 818// private final static Logger log = LoggerFactory.getLogger(CbusMessage.class); 819}