Support for Vendors
User Configuration
Code examples
Analysing tools
Support for BiDiB
CONFIGX
BiDiB uses configurable ports. Depending on the port type, there are various adjustable parameters. These parameter are passed in a list (either from the node to the host or vice versa). These adjustable parameters are available in protocol version 0.6 or higher. Following is a sample implementation in a node that uses the type-based port model.
MSG_LC_CONFIGX_GET
Within the message parser, after decoding the message type, the next two bytes are interpreted as a port index (BiDiB port type) for the query:
case MSG_LC_CONFIGX_GET:
// *(msg_type+1) = Typ
// *(msg_type+2) = Port
bidib_send_port_configx((t_bidib_port_idx*) (msg_type+1));
break;
The routine bidib_send_port_configx() extracts the requested port parameters from the configuration memory and builds a response message (type MSG_LC_CONFIGX), exemplified below for a light port:
static void bidib_send_port_configx(t_bidib_port_idx* port)
{
t_node_message18 message;
switch(port->type)
{
case BIDIB_PORTTYPE_SWITCH: // standard port
....
break;
case BIDIB_PORTTYPE_LIGHT: // light port
if (port->portnum >= NUM_OF_LIGHTS)
{
bidib_send_port_na(port);
return; // out of range
}
else
{
uint8_t i = 0;
message.header.node_addr = 0;
message.header.index = get_tx_num();
message.header.msg_type = MSG_LC_CONFIGX;
message.data[i++] = port->type;
message.data[i++] = port->portnum;
message.data[i++] = BIDIB_PCFG_DIMM_DOWN_8_8; // Dimmgeschwindigkeit down
message.data[i++] = LOW8(CVram.light_cfg[port->portnum].dimm_off);
message.data[i++] = HIGH8(CVram.light_cfg[port->portnum].dimm_off);
message.data[i++] = BIDIB_PCFG_DIMM_UP_8_8;
message.data[i++] = LOW8(CVram.light_cfg[port->portnum].dimm_on);
message.data[i++] = HIGH8(CVram.light_cfg[port->portnum].dimm_on);
message.data[i++] = BIDIB_PCFG_LEVEL_PORT_OFF;
message.data[i++] = CVram.light_cfg[port->portnum].brightness_off;
message.data[i++] = BIDIB_PCFG_LEVEL_PORT_ON;
message.data[i++] = CVram.light_cfg[port->portnum].brightness_on;
message.header.size = sizeof(t_node_message_header)-1 +i;
send_bidib_message((unsigned char *)&message);
return;
}
break;
.....
If a port has no parameters, so the node responds:
static void bidib_send_configx_error(t_bidib_port_idx* port)
{
t_node_message10 message;
message.header.node_addr = 0;
message.header.index = get_tx_num();
message.header.msg_type = MSG_LC_CONFIGX;
message.data[0] = port->type;
message.data[1] = port->portnum;
message.data[2] = BIDIB_PCFG_NONE; // Error / None
message.data[3] = 0;
message.header.size = 3+4; // 3= sizeof(t_node_message_header)-1
send_bidib_message((unsigned char *)&message);
}
MSG_LC_CONFIGX_SET
To set these parameters the same list is used. Below is an example of the evaluation of the parameters of a light port:
// Parameter: msg: points to a list of: type, portnum, [P_ENUM, P_VALUE]
// length: number of bytes in list
// return: 0: port does not exist
// 1…x: wrong P_ENUM
// 255 if success
unsigned char configx_light(unsigned char *msg, signed char length)
{
msg++; // skip type
unsigned char myport = *msg++; // get portnum
if (myport >= NUM_OF_LIGHTS) return(0); // out of range
length -= 2;
while (length > 0)
{
switch(*msg++)
{
default:
return(*--msg); // return wrong Enum
case BIDIB_PCFG_LEVEL_PORT_OFF:
save_cv(offsetof(t_cv_record, light_cfg[myport].brightness_off), *msg);
msg++;
length -= 2;
break;
case BIDIB_PCFG_LEVEL_PORT_ON:
save_cv(offsetof(t_cv_record, light_cfg[myport].brightness_on), *msg);
msg++;
length -= 2;
break;
case BIDIB_PCFG_DIMM_UP_8_8:
save_cv_int(offsetof(t_cv_record, light_cfg[myport].dimm_on), *(uint16_t *)msg);
msg++;
msg++;
length -= 3;
break;
case BIDIB_PCFG_DIMM_DOWN_8_8:
save_cv_int(offsetof(t_cv_record, light_cfg[myport].dimm_off), *(uint16_t *)msg);
msg++;
msg++;
length -= 3;
break;
}
}
return(255);
}
MSG_LC_CONFIGX_GET_ALL
In order to achieve a very fast reading of the entire configuration of a node, there is a message to query a complete range. By means of MSG_LC_CONFIGX_GETALL the node will be asked to send a whole range of port parameters. The node should use as much as possible of spare bandwitdh.
Inside the type parser the range is checked and the configx responder is activated:
static t_bidib_port_idx bidib_cfgx2send; // start / counter for configx_get_all
static t_bidib_port_idx bidib_cfgx2last; // end for configx_get_all
case MSG_LC_CONFIGX_GET_ALL:
if (rest == 1) // no para, get all
{
bidib_cfgx2send.type = 0;
bidib_cfgx2send.portnum = 0;
bidib_cfgx2last.type = 0xFF;
bidib_cfgx2last.portnum = 0xFF;
}
else
{
bidib_cfgx2send.type = *(msg_type+1);
bidib_cfgx2send.portnum = *(msg_type+2);
bidib_cfgx2last.type = *(msg_type+3);
bidib_cfgx2last.portnum = *(msg_type+4);
}
bidib_send_configx_all(); // send a first answer
break;
As long as bidib_cfgx2send is smaller than bidib_cfgx2last, the node tries to send a configx-message to the host.
if (is_bidib_spontan_enabled())
{
if (bidib_send_configx_all()) return(0); // come back asap
}
// return: 1 if something is still to be transmitted, 0: all done
unsigned char bidib_send_configx_all(void)
{
if (port_type_in_range())
{
if (bidib_tx_fifo_okay()) // check if there is enough space in tx-fifo left
{
if (port_exits(&bidib_cfgx2send)) bidib_send_port_configx(&bidib_cfgx2send);
increment_port_idx(&bidib_cfgx2send);
if (port_type_in_range()) return(1);
return(0);
}
return(1);
}
return(0);
}