📄 dlmstp.c
字号:
/* Some other node exists at a lower address. */
/* Enter the IDLE state to receive and
process the incoming frame. */
Master_State = MSTP_MASTER_STATE_IDLE;
transition_now = true;
}
} else {
ns_timeout = Tno_token + (Tslot * (This_Station + 1));
if (Timer_Silence() < ns_timeout) {
/* GenerateToken */
/* Assume that this node is the lowest numerical address */
/* on the network and is empowered to create a token. */
Poll_Station = next_this_station;
/* Transmit a Poll For Master frame to PS. */
MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER, Poll_Station,
This_Station, NULL, 0);
/* indicate that the next station is unknown */
Next_Station = This_Station;
RetryCount = 0;
TokenCount = 0;
/* EventCount = 0; removed Addendum 135-2004d-8 */
/* enter the POLL_FOR_MASTER state
to find a new successor to TS. */
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
}
}
break;
/* In the POLL_FOR_MASTER state, the node listens for a reply to */
/* a previously sent Poll For Master frame in order to find */
/* a successor node. */
case MSTP_MASTER_STATE_POLL_FOR_MASTER:
if (MSTP_Flag.ReceivedValidFrame == true) {
if ((DestinationAddress == This_Station)
&& (FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
/* ReceivedReplyToPFM */
MSTP_Flag.SoleMaster = false;
Next_Station = SourceAddress;
EventCount = 0;
/* Transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
Poll_Station = This_Station;
TokenCount = 0;
RetryCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
} else {
/* ReceivedUnexpectedFrame */
/* An unexpected frame was received. */
/* This may indicate the presence of multiple tokens. */
/* enter the IDLE state to synchronize with the network. */
/* This action drops the token. */
Master_State = MSTP_MASTER_STATE_IDLE;
transition_now = true;
}
MSTP_Flag.ReceivedValidFrame = false;
} else if ((Timer_Silence() > Tusage_timeout) ||
(MSTP_Flag.ReceivedInvalidFrame == true)) {
if (MSTP_Flag.SoleMaster == true) {
/* SoleMaster */
/* There was no valid reply to the periodic poll */
/* by the sole known master for other masters. */
FrameCount = 0;
/* TokenCount++; removed in 2004 */
Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;
} else {
if (Next_Station != This_Station) {
/* DoneWithPFM */
/* There was no valid reply to the maintenance */
/* poll for a master at address PS. */
EventCount = 0;
/* transmit a Token frame to NS */
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
This_Station, NULL, 0);
RetryCount = 0;
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
} else {
if (next_poll_station != This_Station) {
/* SendNextPFM */
Poll_Station = next_poll_station;
/* Transmit a Poll For Master frame to PS. */
MSTP_Send_Frame(FRAME_TYPE_POLL_FOR_MASTER,
Poll_Station, This_Station, NULL, 0);
RetryCount = 0;
/* Re-enter the current state. */
} else {
/* DeclareSoleMaster */
/* to indicate that this station
is the only master */
MSTP_Flag.SoleMaster = true;
FrameCount = 0;
Master_State = MSTP_MASTER_STATE_USE_TOKEN;
transition_now = true;
}
}
}
MSTP_Flag.ReceivedInvalidFrame = false;
}
break;
/* The ANSWER_DATA_REQUEST state is entered when a */
/* BACnet Data Expecting Reply, a Test_Request, or */
/* a proprietary frame that expects a reply is received. */
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
/* Note: we could wait for up to Treply_delay */
if (MSTP_Flag.TransmitPacketPending) {
matched =
dlmstp_compare_data_expecting_reply(&InputBuffer[0],
DataLength, SourceAddress, &TransmitPacket[0],
TransmitPacketLen, TransmitPacketDest);
}
if (MSTP_Flag.TransmitPacketPending && matched) {
/* Reply */
/* If a reply is available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame */
/* (the mechanism used to determine this is a local matter), */
/* then call MSTP_Send_Frame to transmit the reply frame */
/* and enter the IDLE state to wait for the next frame. */
uint8_t frame_type;
if (MSTP_Flag.TransmitPacketDER) {
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
} else {
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
}
MSTP_Send_Frame(frame_type, TransmitPacketDest, This_Station,
(uint8_t *) & TransmitPacket[0], TransmitPacketLen);
MSTP_Flag.TransmitPacketPending = false;
Master_State = MSTP_MASTER_STATE_IDLE;
} else {
/* DeferredReply */
/* If no reply will be available from the higher layers */
/* within Treply_delay after the reception of the */
/* final octet of the requesting frame (the mechanism */
/* used to determine this is a local matter), */
/* then an immediate reply is not possible. */
/* Any reply shall wait until this node receives the token. */
/* Call MSTP_Send_Frame to transmit a Reply Postponed frame, */
/* and enter the IDLE state. */
MSTP_Send_Frame(FRAME_TYPE_REPLY_POSTPONED, SourceAddress,
This_Station, NULL, 0);
Master_State = MSTP_MASTER_STATE_IDLE;
}
/* clear our flag we were holding for comparison */
MSTP_Flag.ReceivedValidFrame = false;
break;
default:
Master_State = MSTP_MASTER_STATE_IDLE;
break;
}
return transition_now;
}
/* returns number of bytes sent on success, zero on failure */
int dlmstp_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
int bytes_sent = 0;
if (MSTP_Flag.TransmitPacketPending == false) {
MSTP_Flag.TransmitPacketDER = npdu_data->data_expecting_reply;
TransmitPacket = pdu;
TransmitPacketLen = pdu_len;
bytes_sent = pdu_len;
TransmitPacketDest = dest->mac[0];
MSTP_Flag.TransmitPacketPending = true;
}
return bytes_sent;
}
/* Return the length of the packet */
uint16_t dlmstp_receive(
BACNET_ADDRESS * src, /* source address */
uint8_t * pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
unsigned timeout)
{ /* milliseconds to wait for a packet */
uint16_t pdu_len = 0; /* return value */
/* set the input buffer to the same data storage for zero copy */
if (!InputBuffer) {
InputBuffer = pdu;
InputBufferSize = max_pdu;
}
/* only do receive state machine while we don't have a frame */
if ((MSTP_Flag.ReceivedValidFrame == false) &&
(MSTP_Flag.ReceivedInvalidFrame == false)) {
for (;;) {
MSTP_Receive_Frame_FSM();
if (MSTP_Flag.ReceivedValidFrame || MSTP_Flag.ReceivedInvalidFrame)
break;
/* if we are not idle, then we are
receiving a frame or timing out */
if (Receive_State == MSTP_RECEIVE_STATE_IDLE)
break;
}
}
/* only do master state machine while rx is idle */
if (Receive_State == MSTP_RECEIVE_STATE_IDLE) {
while (MSTP_Master_Node_FSM()) {
/* do nothing while some states fast transition */
};
}
/* if there is a packet that needs processed, do it now. */
if (MSTP_Flag.ReceivePacketPending) {
MSTP_Flag.ReceivePacketPending = false;
pdu_len = DataLength;
src->mac_len = 1;
src->mac[0] = SourceAddress;
/* data is already in the pdu pointer */
}
return pdu_len;
}
void dlmstp_set_mac_address(
uint8_t mac_address)
{
/* Master Nodes can only have address 0-127 */
if (mac_address <= 127) {
This_Station = mac_address;
/* FIXME: implement your data storage */
/* I2C_Write_Byte(
EEPROM_DEVICE_ADDRESS,
mac_address,
EEPROM_MSTP_MAC_ADDR); */
if (mac_address > Nmax_master)
dlmstp_set_max_master(mac_address);
}
return;
}
uint8_t dlmstp_mac_address(
void)
{
return This_Station;
}
/* This parameter represents the value of the Max_Info_Frames property of */
/* the node's Device object. The value of Max_Info_Frames specifies the */
/* maximum number of information frames the node may send before it must */
/* pass the token. Max_Info_Frames may have different values on different */
/* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */
void dlmstp_set_max_info_frames(
uint8_t max_info_frames)
{
if (max_info_frames >= 1) {
Nmax_info_frames = max_info_frames;
/* FIXME: implement your data storage */
/* I2C_Write_Byte(
EEPROM_DEVICE_ADDRESS,
(uint8_t)max_info_frames,
EEPROM_MSTP_MAX_INFO_FRAMES_ADDR); */
}
return;
}
uint8_t dlmstp_max_info_frames(
void)
{
return Nmax_info_frames;
}
/* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */
/* allowable address for master nodes. The value of Max_Master shall be */
/* less than or equal to 127. If Max_Master is not writable in a node, */
/* its value shall be 127. */
void dlmstp_set_max_master(
uint8_t max_master)
{
if (max_master <= 127) {
if (This_Station <= max_master) {
Nmax_master = max_master;
/* FIXME: implement your data storage */
/* I2C_Write_Byte(
EEPROM_DEVICE_ADDRESS,
max_master,
EEPROM_MSTP_MAX_MASTER_ADDR); */
}
}
return;
}
uint8_t dlmstp_max_master(
void)
{
return Nmax_master;
}
void dlmstp_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0; /* counter */
my_address->mac_len = 1;
my_address->mac[0] = This_Station;
my_address->net = 0; /* local only, no routing */
my_address->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
my_address->adr[i] = 0;
}
return;
}
void dlmstp_get_broadcast_address(
BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
dest->mac_len = 1;
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* always zero when DNET is broadcast */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -