Support for BiDiB

Node login at the BiDiBus

Nodes have to sign in on the bus at the beginning of a new session. For this, the node will be prompted to log in, this is done from the interface with the message BIDIBUS_LOGON. The node attempt to log on (MSG_LOGON). When two or more nodes trying to register simultaneously, the messages collide and a process for separating the nodes is following until a node is identified and this address is assigned to the session.

Logon from the node view

A node has four internal states:

DISCONNECTED no connection. The node attempts to log in to the system.
APPLIED The node has tried to log on and waits for confirmation.
CONNECTED The node is connected and sends/receives messages
REJECTED The node was rejected by the interface. It stops attempts to log in and displays an error code.

Between these states, there are now the following transitions:

  • The node is always DISCONNECTED:
    • after Power-Up
    • when a bus reset has been received
    • when a login attempt fails
    • if he gets no poll from the interface over a certain time.
  • The node enters the state APPLIED:
    • after he sends a logon message.
  • The node enters the state CONNECTED:
    • after receiving a positive acknowledgement to its logon message.
  • The node enters the state REJECTED:
    • after receiving a negative acknowledgement (at any time). It may leave this state only after a user interaction (ie. power cycle)(see note)

To achieve the required separation during the login process, there are rules that must be followed during login:

Backoff:

At the start and after an unsuccessful login attempt, the node have to ignore a random number of logon messages from the master. (='backoff'). This gives other nodes the chance to perform a successful logon. If the next login attempt occurs in a collision error again (node will be not logged in), the node must wait a random time again. This random time is calculated from the previous number plus a new random number, i.e. the 'back-off' is extended.

The random number at the beginning should be located in a range of 1…64 and it should be also calculated by using the Unique-ID of the node. Then the first login attempt from different nodes are already temporally equalized.

A test of logon is made by the receive routine and log-in will be sended occasionally:


if (received_message == BIDIBUS_LOGON)
  {
    if (my_bidib_connect == BIDIB_DISCONNECTED)
      {
        if (bidib_backoff)
          {
            bidib_backoff--;
          }
        else
          {
            send_logon_message();
            my_bidib_connect = BIDIB_APPLIED;
          }
     }
   else if (my_bidib_connect == BIDIB_APPLIED)
    {
       // logon attempt failed, no ack received
       bidib_backoff = calculate_new_backoff();
    }
   else
    {
       // other processing
    }
    

The new backoff is calculated as follows:


unsigned char calculate_new_backoff(void)
  {
    unsigned char new_backoff;
    new_backoff = prbs8() & 0xF;
    new_backoff += previous_backoff;
    new_backoff &= 0x1F;     // modulo 32 and limit
    previous_backoff = new_backoff;
    return(new_backoff);
  }
    

As a random process, an LSFR (PRBS) of length 8 is used.

This can be done in C with a few shift commands and XOR's.


unsigned char seed = 0xAA;   // this should be loaded by serial no.
static unsigned char prbs8(void)
  {
    unsigned char new_rnd,temp;

    new_rnd = seed;                // copy bit 1
    new_rnd = new_rnd << 1;
    new_rnd = new_rnd ^ seed;      // xor bit 2
    new_rnd = new_rnd << 1;
    new_rnd = new_rnd ^ seed;      // xor bit 3
    new_rnd = new_rnd << 4;
    new_rnd = new_rnd ^ seed;      // xor bit 7
    new_rnd = new_rnd >> 7;  // now put this bit to seed's lsb
    temp = seed << 1;
    seed = new_rnd + temp;
    return(seed);
  }
    
Collision Avoidance:

If the node has received a login, he must wait a certain time with his attempt and watch the bus:


if (received == BIDIBUS_LOGON_par)
  {
    if (bidib_connect == BIDIB_DISCONNECTED)
      {
        if (bidib_backoff) bidib_backoff--;
        else
          { // backoff timeout, go ahead
            // collision avoidance comes first:
            // The node waits for a specific period (0…31us),
            // while the RX line is observed
            // and occasionally _not_ transmitted!
            unsigned char i;
            for (i=0; i<bidib_collision_avoidance_time; i++)
              {
                if (HARDWARE_GET_RX == 0) return;
                _delay_us(1);
              }
            ...
            // now here the login message is sent.
    

This reduces the possibility of an collision and also accelerates the login of all nodes.

Note: It may happen (ie due to a short interruption in the power supply) that the node restarts, but the interface has still logged this node in. In this case the node may received a 'REJECTED', since the interface sees a double login. Therefore the node should sleep for a timeout period of 2 seconds, then try to logon again. If this new logon is rejected again, the node should not try to logon again.

Logon from the interfaces view

... this text is missing ... drop a mail if you are interested.