Class Dcc4PcBlockLocos

java.lang.Object
jmri.jmrix.dcc4pc.Dcc4PcBlockLocos

public class Dcc4PcBlockLocos extends Object
Works out which locomotives are in which block from Raw encoding packets.

Channel 1 is a broadcast: every decoder in a block sends its address in the same time slot, so with two locos the ADR_LOW halves collide into invalid codes. Channel 2 is only used by the decoder the DCC packet was addressed to, so a valid channel 2 reply on an input right after a packet to address X means X is in that block. A clean ADR_HIGH + ADR_LOW pair on channel 1 is also accepted, which covers a lone loco the command station isn't addressing.

A loco stays in a block until the block reads unoccupied, or until it has been seen in another block and not in this one for MOVE_MILLIS. There is no plain timeout: a stopped decoder can go many seconds without a channel 2 reply.

A loco that is still present and heard again is reported as a refresh, at most every REFRESH_MILLIS, so its "last seen" time keeps up without flooding the GUI.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static class 
    A loco added to or removed from a block, or heard again in it.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final long
    RailCom from a loco on an input proves the input is occupied, whatever the debounced state says.
    (package private) static final int
     
    static final int
    Added to an address to mark it as a long (14-bit) address.
    static final long
    How long a loco seen elsewhere keeps its old block, to allow for bridging a gap.
    static final long
    Shortest time between refreshes for a loco that stays in a block.
    (package private) static final int
    ACK, NACK or BUSY.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Dcc4PcBlockLocos(int[] inputs)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    (package private) static int
    address(int high, int low)
    Combine channel 1 ADR_HIGH and ADR_LOW payloads (RCN-217 5.2.1).
    apply(Dcc4PcRawDecoder.Packet p, int[] states, long now)
    Apply one decoded packet.
    void
    Forget everything, as after a resync: the next packets rebuild it.
    (package private) static int
    decode(int b)
     
    (package private) static boolean
    hasValidReply(int[] ch2)
    True if channel 2 holds at least one well-formed datagram or an ACK/NACK/BUSY.
    (package private) static String
    hex(int[] bytes)
     
    locos(int input)
     
    static int
    mobileAddress(int[] dcc)
    The locomotive address a DCC packet is sent to.
    static String
    name(int address)
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • MOVE_MILLIS

      public static final long MOVE_MILLIS
      How long a loco seen elsewhere keeps its old block, to allow for bridging a gap.
      See Also:
    • REFRESH_MILLIS

      public static final long REFRESH_MILLIS
      Shortest time between refreshes for a loco that stays in a block.
      See Also:
    • HEARD_PROVES_OCCUPIED_MILLIS

      public static final long HEARD_PROVES_OCCUPIED_MILLIS
      RailCom from a loco on an input proves the input is occupied, whatever the debounced state says. The debounced state lags the raw one (a block becomes occupied after 2 packets, and unoccupied only after 300 ms), so a loco entering a block can be heard before its block reads occupied. An unoccupied reading therefore only removes locos not heard on that input for this long, which matches the unoccupied hold in the sensor manager: a block that has really been empty that long has had no RailCom.
      See Also:
    • LONG

      public static final int LONG
      Added to an address to mark it as a long (14-bit) address.
      See Also:
    • INVALID

      static final int INVALID
      See Also:
    • SPECIAL

      static final int SPECIAL
      ACK, NACK or BUSY.
      See Also:
  • Constructor Details

    • Dcc4PcBlockLocos

      public Dcc4PcBlockLocos(int[] inputs)
      Parameters:
      inputs - the enabled inputs, numbered from 1, in the decoder's order
  • Method Details

    • locos

      public List<Integer> locos(int input)
      Parameters:
      input - input number, from 1
      Returns:
      the locos in that block, in the order they were first seen
    • clear

      public void clear()
      Forget everything, as after a resync: the next packets rebuild it.
    • apply

      public List<Dcc4PcBlockLocos.Change> apply(Dcc4PcRawDecoder.Packet p, int[] states, long now)
      Apply one decoded packet.
      Parameters:
      p - the packet
      states - the input states to use, debounced, in the decoder's order
      now - the time, in milliseconds
      Returns:
      what changed
    • name

      public static String name(int address)
      Parameters:
      address - an address as used here
      Returns:
      it as text, such as "9328(L)" or "3(S)"
    • mobileAddress

      public static int mobileAddress(int[] dcc)
      The locomotive address a DCC packet is sent to.
      Parameters:
      dcc - the packet bytes, without the error byte or with it
      Returns:
      the address, with LONG added for a long address, or -1 for a broadcast, idle, accessory or malformed packet
    • address

      static int address(int high, int low)
      Combine channel 1 ADR_HIGH and ADR_LOW payloads (RCN-217 5.2.1).
      Returns:
      the address, with LONG added for a long address, or -1 if ADR_HIGH isn't a valid address pattern
    • hasValidReply

      static boolean hasValidReply(int[] ch2)
      True if channel 2 holds at least one well-formed datagram or an ACK/NACK/BUSY.
    • hex

      static String hex(int[] bytes)
      Returns:
      the bytes as hex, for the log
    • decode

      static int decode(int b)
      Returns:
      the six-bit value of a 4-of-8 code, SPECIAL or INVALID