Support for Vendors
User Configuration
Code examples
Analysing tools
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_LOCAL_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…63 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 &= 0x3F; // modulo 64 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.
- Example Data BIDIBUS_LOGON:
-
The message for LOGON is handled in the same manner as every other message on BiDiBus: formed as bus paket and protected with a crc:
0x00B = Paket size 0x00A = Message size 0x000 = Adressstack (this message is from this node itself) 0x000 = Message Num (here 0) 0x0F0 = Code BIDIBUS_LOGON 0x000 = Unique, Class 0x000 = Unique, ClassX 0x00D = Unique, VendorID 0x075 = Unique, ProductID 0x000 = Unique, ProductID 0x073 = Unique, Serial 0x0F0 = Unique, Serial 0x0EB = CRC8
Logon from the interfaces view
... this text is missing ... drop a mail if you are interested.