Converted to standard indent style.
This commit is contained in:
@@ -103,9 +103,7 @@ int abort_decode_apdu(uint8_t * apdu,
|
||||
}
|
||||
|
||||
void testAbortAPDU(Test * pTest,
|
||||
uint8_t invoke_id,
|
||||
uint8_t abort_reason,
|
||||
bool server)
|
||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
||||
{
|
||||
uint8_t apdu[480] = { 0 };
|
||||
int len = 0;
|
||||
@@ -144,8 +142,7 @@ void testAbort(Test * pTest)
|
||||
ct_test(pTest, len != 0);
|
||||
apdu_len = len;
|
||||
len = abort_decode_apdu(&apdu[0],
|
||||
apdu_len, &test_invoke_id, &test_abort_reason,
|
||||
&test_server);
|
||||
apdu_len, &test_invoke_id, &test_abort_reason, &test_server);
|
||||
ct_test(pTest, len != -1);
|
||||
ct_test(pTest, test_invoke_id == invoke_id);
|
||||
ct_test(pTest, test_abort_reason == abort_reason);
|
||||
@@ -170,8 +167,8 @@ void testAbort(Test * pTest)
|
||||
/* check them all... */
|
||||
for (invoke_id = 0; invoke_id < 255; invoke_id++) {
|
||||
for (abort_reason = 0; abort_reason < 255; abort_reason++) {
|
||||
testAbortAPDU(pTest, invoke_id, abort_reason, false);
|
||||
testAbortAPDU(pTest, invoke_id, abort_reason, true);
|
||||
testAbortAPDU(pTest, invoke_id, abort_reason, false);
|
||||
testAbortAPDU(pTest, invoke_id, abort_reason, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,13 +1042,12 @@ int encode_tagged_octet_string(uint8_t * apdu,
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_context_octet_string(uint8_t * apdu,
|
||||
int tag_number,
|
||||
BACNET_OCTET_STRING * octet_string)
|
||||
int tag_number, BACNET_OCTET_STRING * octet_string)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
|
||||
if (apdu && octet_string) {
|
||||
apdu_len = encode_tag(&apdu[0], (uint8_t) tag_number,
|
||||
apdu_len = encode_tag(&apdu[0], (uint8_t) tag_number,
|
||||
true, octetstring_length(octet_string));
|
||||
if ((apdu_len + octetstring_length(octet_string)) < MAX_APDU)
|
||||
apdu_len += encode_octet_string(&apdu[apdu_len], octet_string);
|
||||
|
||||
@@ -109,8 +109,7 @@ extern "C" {
|
||||
int encode_tagged_octet_string(uint8_t * apdu,
|
||||
BACNET_OCTET_STRING * octet_string);
|
||||
int encode_context_octet_string(uint8_t * apdu,
|
||||
int tag_number,
|
||||
BACNET_OCTET_STRING * octet_string);
|
||||
int tag_number, BACNET_OCTET_STRING * octet_string);
|
||||
int decode_octet_string(uint8_t * apdu, uint32_t len_value,
|
||||
BACNET_OCTET_STRING * octet_string);
|
||||
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
int mtu_len = 0;
|
||||
int bytes_sent = 0;
|
||||
|
||||
(void)npdu_data;
|
||||
(void) npdu_data;
|
||||
/* assumes that the driver has already been initialized */
|
||||
if (BIP_Socket < 0)
|
||||
return BIP_Socket;
|
||||
|
||||
+4
-5
@@ -356,15 +356,14 @@ int ucov_notify_decode_apdu(uint8_t * apdu,
|
||||
|
||||
/* dummy function stubs */
|
||||
int npdu_encode_pdu(uint8_t * npdu,
|
||||
BACNET_ADDRESS * dest,
|
||||
BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data)
|
||||
BACNET_ADDRESS * dest,
|
||||
BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void npdu_encode_npdu_data(BACNET_NPDU_DATA * npdu,
|
||||
bool data_expecting_reply,
|
||||
BACNET_MESSAGE_PRIORITY priority)
|
||||
bool data_expecting_reply, BACNET_MESSAGE_PRIORITY priority)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ void handler_atomic_read_file(uint8_t * service_request,
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
&my_address, &npdu_data);
|
||||
/* bad decoding - send an abort */
|
||||
if (len < 0) {
|
||||
@@ -132,14 +132,13 @@ void handler_atomic_read_file(uint8_t * service_request,
|
||||
} else if (data.object_type == OBJECT_FILE) {
|
||||
if (!bacfile_valid_instance(data.object_instance)) {
|
||||
error = true;
|
||||
}
|
||||
else if (data.access == FILE_STREAM_ACCESS) {
|
||||
} else if (data.access == FILE_STREAM_ACCESS) {
|
||||
if (data.type.stream.requestedOctetCount <
|
||||
octetstring_capacity(&data.fileData)) {
|
||||
if (bacfile_read_data(&data)) {
|
||||
len =
|
||||
arf_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
arf_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
} else {
|
||||
error = true;
|
||||
error_class = ERROR_CLASS_OBJECT;
|
||||
@@ -167,12 +166,11 @@ void handler_atomic_read_file(uint8_t * service_request,
|
||||
error_class = ERROR_CLASS_SERVICES;
|
||||
error_code = ERROR_CODE_FILE_ACCESS_DENIED;
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
|
||||
if (error) {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
|
||||
}
|
||||
pdu_len += len;
|
||||
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
||||
|
||||
@@ -59,7 +59,7 @@ void handler_device_communication_control(uint8_t * service_request,
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
&my_address, &npdu_data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "DeviceCommunicationControl!\n");
|
||||
|
||||
@@ -59,7 +59,7 @@ void handler_reinitialize_device(uint8_t * service_request,
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
&my_address, &npdu_data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "ReinitializeDevice!\n");
|
||||
|
||||
@@ -69,7 +69,7 @@ void handler_read_property(uint8_t * service_request,
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
&my_address, &npdu_data);
|
||||
#if PRINT_ENABLED
|
||||
if (len <= 0)
|
||||
@@ -105,8 +105,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"Sending Read Property Ack for Device!\n");
|
||||
@@ -127,8 +127,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Sending Read Property Ack for AI!\n");
|
||||
#endif
|
||||
@@ -148,8 +148,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Sending Read Property Ack for BI!\n");
|
||||
#endif
|
||||
@@ -169,8 +169,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Sending Read Property Ack for BO!\n");
|
||||
#endif
|
||||
@@ -190,8 +190,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Sending Read Property Ack for BV!\n");
|
||||
#endif
|
||||
@@ -211,8 +211,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Sending Read Property Ack for AO!\n");
|
||||
#endif
|
||||
@@ -232,8 +232,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Sending Read Property Ack for AV!\n");
|
||||
#endif
|
||||
@@ -253,8 +253,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"Sending Read Property Ack for LSP!\n");
|
||||
@@ -275,8 +275,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"Sending Read Property Ack for MSO!\n");
|
||||
@@ -298,8 +298,8 @@ void handler_read_property(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"Sending Read Property Ack for File!\n");
|
||||
@@ -316,17 +316,17 @@ void handler_read_property(uint8_t * service_request,
|
||||
if (error) {
|
||||
switch (len) {
|
||||
/* BACnet APDU too small to fit data, so proper response is Abort */
|
||||
case -2:
|
||||
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||
break;
|
||||
case -1:
|
||||
default:
|
||||
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
|
||||
break;
|
||||
case -2:
|
||||
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||
break;
|
||||
case -1:
|
||||
default:
|
||||
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
|
||||
break;
|
||||
}
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Sending Read Property Error!\n");
|
||||
|
||||
@@ -68,7 +68,7 @@ void handler_write_property(uint8_t * service_request,
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
&my_address, &npdu_data);
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Received Write-Property Request!\n");
|
||||
|
||||
@@ -50,7 +50,7 @@ void handler_unrecognized_service(uint8_t * service_request,
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
&my_address, &npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
len = reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
|
||||
@@ -76,9 +76,11 @@ uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
|
||||
if (status) {
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
||||
&my_address, &npdu_data);
|
||||
npdu_encode_npdu_data(&npdu_data, true,
|
||||
MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
||||
&my_address, &npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
len = awf_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
invoke_id, &data);
|
||||
|
||||
@@ -70,7 +70,7 @@ uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t t
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
||||
&my_address, &npdu_data);
|
||||
&my_address, &npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
characterstring_init_ansi(&password_string, password);
|
||||
len = dcc_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
|
||||
@@ -70,7 +70,7 @@ uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
||||
&my_address, &npdu_data);
|
||||
&my_address, &npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
characterstring_init_ansi(&password_string, password);
|
||||
len = rd_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
|
||||
@@ -73,7 +73,7 @@ uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
||||
&my_address, &npdu_data);
|
||||
&my_address, &npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
data.object_type = object_type;
|
||||
data.object_instance = object_instance;
|
||||
|
||||
@@ -74,7 +74,7 @@ uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
||||
&my_address, &npdu_data);
|
||||
&my_address, &npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
data.object_type = object_type;
|
||||
data.object_instance = object_instance;
|
||||
|
||||
@@ -227,7 +227,7 @@ bool bacfile_write_property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* decode the some of the request */
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_ARCHIVE:
|
||||
@@ -313,7 +313,8 @@ uint32_t bacfile_instance_from_tsm(uint8_t invokeID)
|
||||
found = tsm_get_transaction_pdu(invokeID, &dest, &npdu_data, &apdu[0],
|
||||
&apdu_len);
|
||||
if (found) {
|
||||
if (!npdu_data.network_layer_message && npdu_data.data_expecting_reply
|
||||
if (!npdu_data.network_layer_message
|
||||
&& npdu_data.data_expecting_reply
|
||||
&& (apdu[0] == PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) {
|
||||
len =
|
||||
apdu_decode_confirmed_service_request(&apdu[0],
|
||||
|
||||
@@ -158,8 +158,8 @@ int main(int argc, char *argv[])
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
/* setup my info */
|
||||
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
||||
|
||||
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
|
||||
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
|
||||
Target_Device_Object_Instance, BACNET_MAX_INSTANCE+1);
|
||||
Target_Device_Object_Instance, BACNET_MAX_INSTANCE + 1);
|
||||
return 1;
|
||||
}
|
||||
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE) {
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
typedef struct dlmstp_packet {
|
||||
bool ready; /* true if ready to be sent or received */
|
||||
BACNET_ADDRESS address; /* source address */
|
||||
uint8_t frame_type; /* type of message */
|
||||
uint8_t frame_type; /* type of message */
|
||||
unsigned pdu_len; /* packet length */
|
||||
uint8_t pdu[MAX_MPDU]; /* packet */
|
||||
} DLMSTP_PACKET;
|
||||
|
||||
+2
-3
@@ -190,8 +190,7 @@ int npdu_encode_pdu(uint8_t * npdu,
|
||||
/* Configure the NPDU portion of the packet for an APDU */
|
||||
/* This function does not handle the network messages, just APDUs. */
|
||||
void npdu_encode_npdu_data(BACNET_NPDU_DATA * npdu_data,
|
||||
bool data_expecting_reply,
|
||||
BACNET_MESSAGE_PRIORITY priority)
|
||||
bool data_expecting_reply, BACNET_MESSAGE_PRIORITY priority)
|
||||
{
|
||||
if (npdu_data) {
|
||||
npdu_data->data_expecting_reply = data_expecting_reply;
|
||||
@@ -358,7 +357,7 @@ void testNPDU2(Test * pTest)
|
||||
BACNET_ADDRESS npdu_dest = { 0 };
|
||||
BACNET_ADDRESS npdu_src = { 0 };
|
||||
int len = 0;
|
||||
bool data_expecting_reply = true;
|
||||
bool data_expecting_reply = true;
|
||||
BACNET_MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL;
|
||||
BACNET_NPDU_DATA npdu_data = { 0 };
|
||||
int i = 0; /* counter */
|
||||
|
||||
+1
-2
@@ -63,8 +63,7 @@ extern "C" {
|
||||
BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data);
|
||||
|
||||
void npdu_encode_npdu_data(BACNET_NPDU_DATA * npdu,
|
||||
bool data_expecting_reply,
|
||||
BACNET_MESSAGE_PRIORITY priority);
|
||||
bool data_expecting_reply, BACNET_MESSAGE_PRIORITY priority);
|
||||
|
||||
void npdu_copy_data(BACNET_NPDU_DATA * dest, BACNET_NPDU_DATA * src);
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ int arcnet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
int mtu_len = 0;
|
||||
struct archdr *pkt = (struct archdr *) mtu;
|
||||
|
||||
(void)npdu_data;
|
||||
(void) npdu_data;
|
||||
src.mac[0] = ARCNET_MAC_Address;
|
||||
src.mac_len = 1;
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
uint8_t mtu[MAX_MPDU] = { 0 }; /* our buffer */
|
||||
int mtu_len = 0;
|
||||
|
||||
(void)npdu_data;
|
||||
(void) npdu_data;
|
||||
/* load the BACnet address for NPDU data */
|
||||
for (i = 0; i < 6; i++) {
|
||||
src.mac[i] = Ethernet_MAC_Address[i];
|
||||
|
||||
+408
-404
@@ -1,404 +1,408 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005,2006 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h> /* for memmove */
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "apdu.h"
|
||||
#include "device.h" /* me */
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
The properties that are constant can be hard coded
|
||||
into the read-property encoding. */
|
||||
static uint32_t Object_Instance_Number = 0;
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
static uint16_t APDU_Timeout = 3000;
|
||||
static uint8_t Number_Of_APDU_Retries = 3;
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE)
|
||||
Object_Instance_Number = object_id;
|
||||
else
|
||||
status = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return ((Object_Instance_Number == object_id) ||
|
||||
(object_id == BACNET_MAX_INSTANCE));
|
||||
}
|
||||
|
||||
BACNET_DEVICE_STATUS Device_System_Status(void)
|
||||
{
|
||||
return System_Status;
|
||||
}
|
||||
|
||||
void Device_Set_System_Status(BACNET_DEVICE_STATUS status)
|
||||
{
|
||||
/* FIXME: bounds check? */
|
||||
System_Status = status;
|
||||
}
|
||||
|
||||
/* FIXME: put your vendor ID here! */
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Version(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Revision(void)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
/* FIXME: MAX_APDU is defined in config.ini - set it! */
|
||||
uint16_t Device_Max_APDU_Length_Accepted(void)
|
||||
{
|
||||
return MAX_APDU;
|
||||
}
|
||||
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
|
||||
{
|
||||
return SEGMENTATION_NONE;
|
||||
}
|
||||
|
||||
uint16_t Device_APDU_Timeout(void)
|
||||
{
|
||||
return APDU_Timeout;
|
||||
}
|
||||
|
||||
/* in milliseconds */
|
||||
void Device_Set_APDU_Timeout(uint16_t timeout)
|
||||
{
|
||||
APDU_Timeout = timeout;
|
||||
}
|
||||
|
||||
uint8_t Device_Number_Of_APDU_Retries(void)
|
||||
{
|
||||
return Number_Of_APDU_Retries;
|
||||
}
|
||||
|
||||
void Device_Set_Number_Of_APDU_Retries(uint8_t retries)
|
||||
{
|
||||
Number_Of_APDU_Retries = retries;
|
||||
}
|
||||
|
||||
uint8_t Device_Database_Revision(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(unsigned array_index,
|
||||
int *object_type, uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned object_index = 0;
|
||||
unsigned object_count = 0;
|
||||
|
||||
/* device object */
|
||||
if (array_index == 1) {
|
||||
*object_type = OBJECT_DEVICE;
|
||||
*instance = Object_Instance_Number;
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error or
|
||||
-2 for abort */
|
||||
int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
BACNET_PROPERTY_ID property,
|
||||
int32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned i = 0;
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
unsigned count = 0;
|
||||
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, (char *)"TD");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string, (char *)"Tiny");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len = encode_tagged_enumerated(&apdu[0], Device_System_Status());
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, (char *)"ASHRAE");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, (char *)"GNU");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, (char *)"1.0");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, (char *)"1.0");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0], Device_Protocol_Version());
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0], Device_Protocol_Revision());
|
||||
break;
|
||||
/* BACnet Legacy Support */
|
||||
case PROP_PROTOCOL_CONFORMANCE_CLASS:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported(i));
|
||||
}
|
||||
apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
/* Note: this is the list of objects that can be in this device,
|
||||
not a list of objects that this device can access */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
count = Device_Object_List_Count();
|
||||
/* Array element zero is the number of objects in the list */
|
||||
if (array_index == BACNET_ARRAY_LENGTH_INDEX)
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], count);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. Note that more than likely you will have */
|
||||
/* to return an error if the number of encoded objects exceeds */
|
||||
/* your maximum APDU size. */
|
||||
else if (array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
if (Device_Object_List_Identifier(i, &object_type,
|
||||
&instance)) {
|
||||
len =
|
||||
encode_tagged_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
if ((apdu_len + len) >= MAX_APDU) {
|
||||
apdu_len = -2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* error: internal error? */
|
||||
*error_class = ERROR_CLASS_SERVICES;
|
||||
*error_code = ERROR_CODE_OTHER;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_tagged_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0],
|
||||
Device_Max_APDU_Length_Accepted());
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len = encode_tagged_enumerated(&apdu[0],
|
||||
Device_Segmentation_Supported());
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], APDU_Timeout);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0], Device_Number_Of_APDU_Retries());
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], Device_Database_Revision());
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testDevice(Test * pTest)
|
||||
{
|
||||
bool status = false;
|
||||
const char *name = "Patricia";
|
||||
|
||||
status = Device_Set_Object_Instance_Number(0);
|
||||
ct_test(pTest, Device_Object_Instance_Number() == 0);
|
||||
ct_test(pTest, status == true);
|
||||
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
||||
ct_test(pTest, Device_Object_Instance_Number() == BACNET_MAX_INSTANCE);
|
||||
ct_test(pTest, status == true);
|
||||
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE / 2);
|
||||
ct_test(pTest,
|
||||
Device_Object_Instance_Number() == (BACNET_MAX_INSTANCE / 2));
|
||||
ct_test(pTest, status == true);
|
||||
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE + 1);
|
||||
ct_test(pTest,
|
||||
Device_Object_Instance_Number() != (BACNET_MAX_INSTANCE + 1));
|
||||
ct_test(pTest, status == false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST_DEVICE
|
||||
/* stubs to dependencies to keep unit test simple */
|
||||
char *Analog_Input_Name(uint32_t object_instance)
|
||||
{
|
||||
(void) object_instance;
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned Analog_Input_Count(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
char *Analog_Output_Name(uint32_t object_instance)
|
||||
{
|
||||
(void) object_instance;
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned Analog_Output_Count(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Analog_Output_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Tiny Device", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testDevice);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TEST_DEVICE */
|
||||
#endif /* TEST */
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005,2006 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h> /* for memmove */
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "apdu.h"
|
||||
#include "device.h" /* me */
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
The properties that are constant can be hard coded
|
||||
into the read-property encoding. */
|
||||
static uint32_t Object_Instance_Number = 0;
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
static uint16_t APDU_Timeout = 3000;
|
||||
static uint8_t Number_Of_APDU_Retries = 3;
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE)
|
||||
Object_Instance_Number = object_id;
|
||||
else
|
||||
status = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return ((Object_Instance_Number == object_id) ||
|
||||
(object_id == BACNET_MAX_INSTANCE));
|
||||
}
|
||||
|
||||
BACNET_DEVICE_STATUS Device_System_Status(void)
|
||||
{
|
||||
return System_Status;
|
||||
}
|
||||
|
||||
void Device_Set_System_Status(BACNET_DEVICE_STATUS status)
|
||||
{
|
||||
/* FIXME: bounds check? */
|
||||
System_Status = status;
|
||||
}
|
||||
|
||||
/* FIXME: put your vendor ID here! */
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Version(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Revision(void)
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
/* FIXME: MAX_APDU is defined in config.ini - set it! */
|
||||
uint16_t Device_Max_APDU_Length_Accepted(void)
|
||||
{
|
||||
return MAX_APDU;
|
||||
}
|
||||
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
|
||||
{
|
||||
return SEGMENTATION_NONE;
|
||||
}
|
||||
|
||||
uint16_t Device_APDU_Timeout(void)
|
||||
{
|
||||
return APDU_Timeout;
|
||||
}
|
||||
|
||||
/* in milliseconds */
|
||||
void Device_Set_APDU_Timeout(uint16_t timeout)
|
||||
{
|
||||
APDU_Timeout = timeout;
|
||||
}
|
||||
|
||||
uint8_t Device_Number_Of_APDU_Retries(void)
|
||||
{
|
||||
return Number_Of_APDU_Retries;
|
||||
}
|
||||
|
||||
void Device_Set_Number_Of_APDU_Retries(uint8_t retries)
|
||||
{
|
||||
Number_Of_APDU_Retries = retries;
|
||||
}
|
||||
|
||||
uint8_t Device_Database_Revision(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(unsigned array_index,
|
||||
int *object_type, uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned object_index = 0;
|
||||
unsigned object_count = 0;
|
||||
|
||||
/* device object */
|
||||
if (array_index == 1) {
|
||||
*object_type = OBJECT_DEVICE;
|
||||
*instance = Object_Instance_Number;
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error or
|
||||
-2 for abort */
|
||||
int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
BACNET_PROPERTY_ID property,
|
||||
int32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned i = 0;
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
unsigned count = 0;
|
||||
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, (char *) "TD");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string, (char *) "Tiny");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len =
|
||||
encode_tagged_enumerated(&apdu[0], Device_System_Status());
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, (char *) "ASHRAE");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0], Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, (char *) "GNU");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, (char *) "1.0");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, (char *) "1.0");
|
||||
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0], Device_Protocol_Version());
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0], Device_Protocol_Revision());
|
||||
break;
|
||||
/* BACnet Legacy Support */
|
||||
case PROP_PROTOCOL_CONFORMANCE_CLASS:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported(i));
|
||||
}
|
||||
apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
/* Note: this is the list of objects that can be in this device,
|
||||
not a list of objects that this device can access */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
count = Device_Object_List_Count();
|
||||
/* Array element zero is the number of objects in the list */
|
||||
if (array_index == BACNET_ARRAY_LENGTH_INDEX)
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], count);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. Note that more than likely you will have */
|
||||
/* to return an error if the number of encoded objects exceeds */
|
||||
/* your maximum APDU size. */
|
||||
else if (array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
if (Device_Object_List_Identifier(i, &object_type,
|
||||
&instance)) {
|
||||
len =
|
||||
encode_tagged_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
if ((apdu_len + len) >= MAX_APDU) {
|
||||
apdu_len = -2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* error: internal error? */
|
||||
*error_class = ERROR_CLASS_SERVICES;
|
||||
*error_code = ERROR_CODE_OTHER;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_tagged_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0],
|
||||
Device_Max_APDU_Length_Accepted());
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len = encode_tagged_enumerated(&apdu[0],
|
||||
Device_Segmentation_Supported());
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_tagged_unsigned(&apdu[0], APDU_Timeout);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0],
|
||||
Device_Number_Of_APDU_Retries());
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len =
|
||||
encode_tagged_unsigned(&apdu[0], Device_Database_Revision());
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testDevice(Test * pTest)
|
||||
{
|
||||
bool status = false;
|
||||
const char *name = "Patricia";
|
||||
|
||||
status = Device_Set_Object_Instance_Number(0);
|
||||
ct_test(pTest, Device_Object_Instance_Number() == 0);
|
||||
ct_test(pTest, status == true);
|
||||
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
||||
ct_test(pTest, Device_Object_Instance_Number() == BACNET_MAX_INSTANCE);
|
||||
ct_test(pTest, status == true);
|
||||
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE / 2);
|
||||
ct_test(pTest,
|
||||
Device_Object_Instance_Number() == (BACNET_MAX_INSTANCE / 2));
|
||||
ct_test(pTest, status == true);
|
||||
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE + 1);
|
||||
ct_test(pTest,
|
||||
Device_Object_Instance_Number() != (BACNET_MAX_INSTANCE + 1));
|
||||
ct_test(pTest, status == false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST_DEVICE
|
||||
/* stubs to dependencies to keep unit test simple */
|
||||
char *Analog_Input_Name(uint32_t object_instance)
|
||||
{
|
||||
(void) object_instance;
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned Analog_Input_Count(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
char *Analog_Output_Name(uint32_t object_instance)
|
||||
{
|
||||
(void) object_instance;
|
||||
return "";
|
||||
}
|
||||
|
||||
unsigned Analog_Output_Count(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t Analog_Output_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Tiny Device", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testDevice);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TEST_DEVICE */
|
||||
#endif /* TEST */
|
||||
|
||||
+113
-126
@@ -33,105 +33,96 @@
|
||||
#include "mstp.h"
|
||||
#include "dlmstp.h"
|
||||
#include "rs485.h"
|
||||
#include "npdu.h"
|
||||
#include "npdu.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
|
||||
/* Number of MS/TP Packets Rx/Tx
|
||||
*/
|
||||
*/
|
||||
uint16_t MSTP_Packets = 0;
|
||||
|
||||
/* receive buffer */
|
||||
/* receive buffer */
|
||||
#pragma udata MSTP_RxData
|
||||
static DLMSTP_PACKET Receive_Buffer;
|
||||
/* temp buffer for NPDU insertion */
|
||||
/* local MS/TP port data - shared with RS-485 */
|
||||
/* local MS/TP port data - shared with RS-485 */
|
||||
#pragma udata MSTP_PortData
|
||||
volatile struct mstp_port_struct_t MSTP_Port;
|
||||
#pragma udata
|
||||
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
|
||||
volatile struct mstp_port_struct_t MSTP_Port;
|
||||
#pragma udata
|
||||
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
|
||||
|
||||
/* This defines the number of edit fields for this module
|
||||
*/
|
||||
#define MAX_EDIT_FIELD 1
|
||||
static uint8_t EditField = 0;
|
||||
/* *************************************************************************
|
||||
DESCRIPTION: This function handles incrementing or decrementing our
|
||||
EditField
|
||||
RETURN: none
|
||||
ALGORITHM: none
|
||||
NOTES: Pass a #>0 to increment #<0 to decrement
|
||||
*************************************************************************** */
|
||||
void dlmstp_SetEditField(
|
||||
signed char state) /* direction our editfield is moving */
|
||||
{
|
||||
if (state > 0)
|
||||
{
|
||||
if (++EditField > MAX_EDIT_FIELD)
|
||||
EditField = 0;
|
||||
}
|
||||
else if (state < 0)
|
||||
{
|
||||
if (EditField)
|
||||
EditField--;
|
||||
else
|
||||
EditField = MAX_EDIT_FIELD;
|
||||
}
|
||||
else
|
||||
EditField = 0;
|
||||
}
|
||||
|
||||
/* *************************************************************************
|
||||
DESCRIPTION: Gets the current edit field for this module
|
||||
RETURN: the current edit field
|
||||
ALGORITHM: none
|
||||
NOTES: none
|
||||
*************************************************************************** */
|
||||
uint8_t dlmstp_GetEditField(void)
|
||||
{
|
||||
return (EditField);
|
||||
}
|
||||
|
||||
void dlmstp_millisecond_timer(void)
|
||||
{
|
||||
INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer);
|
||||
}
|
||||
|
||||
void dlmstp_reinit(void)
|
||||
{
|
||||
/* This defines the number of edit fields for this module
|
||||
*/
|
||||
#define MAX_EDIT_FIELD 1
|
||||
static uint8_t EditField = 0;
|
||||
/* *************************************************************************
|
||||
DESCRIPTION: This function handles incrementing or decrementing our
|
||||
EditField
|
||||
RETURN: none
|
||||
ALGORITHM: none
|
||||
NOTES: Pass a #>0 to increment #<0 to decrement
|
||||
*************************************************************************** */
|
||||
void dlmstp_SetEditField(signed char state)
|
||||
{ /* direction our editfield is moving */
|
||||
if (state > 0) {
|
||||
if (++EditField > MAX_EDIT_FIELD)
|
||||
EditField = 0;
|
||||
} else if (state < 0) {
|
||||
if (EditField)
|
||||
EditField--;
|
||||
else
|
||||
EditField = MAX_EDIT_FIELD;
|
||||
} else
|
||||
EditField = 0;
|
||||
}
|
||||
|
||||
/* *************************************************************************
|
||||
DESCRIPTION: Gets the current edit field for this module
|
||||
RETURN: the current edit field
|
||||
ALGORITHM: none
|
||||
NOTES: none
|
||||
*************************************************************************** */
|
||||
uint8_t dlmstp_GetEditField(void)
|
||||
{
|
||||
return (EditField);
|
||||
}
|
||||
|
||||
void dlmstp_millisecond_timer(void)
|
||||
{
|
||||
INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer);
|
||||
}
|
||||
|
||||
void dlmstp_reinit(void)
|
||||
{
|
||||
RS485_Reinit();
|
||||
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
|
||||
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
|
||||
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
|
||||
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
||||
}
|
||||
|
||||
void dlmstp_init(void)
|
||||
{
|
||||
|
||||
void dlmstp_init(void)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
/* initialize buffer */
|
||||
Receive_Buffer.ready = false;
|
||||
Receive_Buffer.pdu_len = 0;
|
||||
/* initialize hardware */
|
||||
RS485_Initialize();
|
||||
MSTP_Port.InputBuffer = &Receive_Buffer.pdu[0];
|
||||
MSTP_Init(&MSTP_Port);
|
||||
data = I2C_Read_Byte(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
EEPROM_MSTP_MAC_ADDR);
|
||||
if (data <= 127)
|
||||
MSTP_Port.This_Station = data;
|
||||
else
|
||||
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
|
||||
data = I2C_Read_Byte(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
EEPROM_MSTP_MAX_MASTER_ADDR);
|
||||
if (data <= 127)
|
||||
MSTP_Port.Nmax_master = data;
|
||||
else
|
||||
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
||||
MSTP_Port.Nmax_info_frames =
|
||||
I2C_Read_Byte(
|
||||
Receive_Buffer.pdu_len = 0;
|
||||
/* initialize hardware */
|
||||
RS485_Initialize();
|
||||
MSTP_Port.InputBuffer = &Receive_Buffer.pdu[0];
|
||||
MSTP_Init(&MSTP_Port);
|
||||
data = I2C_Read_Byte(EEPROM_DEVICE_ADDRESS, EEPROM_MSTP_MAC_ADDR);
|
||||
if (data <= 127)
|
||||
MSTP_Port.This_Station = data;
|
||||
else
|
||||
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
|
||||
data = I2C_Read_Byte(EEPROM_DEVICE_ADDRESS,
|
||||
EEPROM_MSTP_MAX_MASTER_ADDR);
|
||||
if (data <= 127)
|
||||
MSTP_Port.Nmax_master = data;
|
||||
else
|
||||
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
||||
MSTP_Port.Nmax_info_frames =
|
||||
I2C_Read_Byte(EEPROM_DEVICE_ADDRESS,
|
||||
EEPROM_MSTP_MAX_INFO_FRAMES_ADDR);
|
||||
}
|
||||
@@ -149,8 +140,8 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
{ /* number of bytes of data */
|
||||
int bytes_sent = 0;
|
||||
unsigned npdu_len = 0;
|
||||
uint8_t frame_type = 0;
|
||||
uint8_t destination = 0; /* destination address */
|
||||
uint8_t frame_type = 0;
|
||||
uint8_t destination = 0; /* destination address */
|
||||
BACNET_ADDRESS src;
|
||||
unsigned i = 0; /* loop counter */
|
||||
|
||||
@@ -166,62 +157,59 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
destination = dest->mac[0];
|
||||
} else {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
dlmstp_get_my_address(&src);
|
||||
if ((8 /* header len */ + pdu_len) > MAX_MPDU) {
|
||||
return -4;
|
||||
}
|
||||
bytes_sent = MSTP_Create_Frame(
|
||||
(uint8_t *) & MSTP_Port.TxBuffer[0],
|
||||
sizeof(MSTP_Port.TxBuffer),
|
||||
MSTP_Port.TxFrameType,
|
||||
sizeof(MSTP_Port.TxBuffer),
|
||||
MSTP_Port.TxFrameType,
|
||||
destination, MSTP_Port.This_Station, pdu, pdu_len);
|
||||
MSTP_Port.TxLength = bytes_sent;
|
||||
MSTP_Port.TxLength = bytes_sent;
|
||||
MSTP_Port.TxReady = true;
|
||||
MSTP_Packets++;
|
||||
}
|
||||
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
void dlmstp_task(void)
|
||||
{
|
||||
uint8_t bytes_remaining;
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
void dlmstp_task(void)
|
||||
{
|
||||
uint8_t bytes_remaining;
|
||||
bool received_frame;
|
||||
|
||||
/* only do receive state machine while we don't have a frame */
|
||||
if ((MSTP_Port.ReceivedValidFrame == false) &&
|
||||
(MSTP_Port.ReceivedInvalidFrame == false))
|
||||
{
|
||||
do {
|
||||
bytes_remaining = RS485_Check_UART_Data(&MSTP_Port);
|
||||
MSTP_Receive_Frame_FSM(&MSTP_Port);
|
||||
received_frame = MSTP_Port.ReceivedValidFrame ||
|
||||
MSTP_Port.ReceivedInvalidFrame;
|
||||
if (received_frame)
|
||||
/* only do receive state machine while we don't have a frame */
|
||||
if ((MSTP_Port.ReceivedValidFrame == false) &&
|
||||
(MSTP_Port.ReceivedInvalidFrame == false)) {
|
||||
do {
|
||||
bytes_remaining = RS485_Check_UART_Data(&MSTP_Port);
|
||||
MSTP_Receive_Frame_FSM(&MSTP_Port);
|
||||
received_frame = MSTP_Port.ReceivedValidFrame ||
|
||||
MSTP_Port.ReceivedInvalidFrame;
|
||||
if (received_frame)
|
||||
break;
|
||||
} while (bytes_remaining);
|
||||
}
|
||||
/* only do master state machine while rx is idle */
|
||||
/* only do master state machine while rx is idle */
|
||||
if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) {
|
||||
while (MSTP_Master_Node_FSM(&MSTP_Port)) {
|
||||
while (MSTP_Master_Node_FSM(&MSTP_Port)) {};
|
||||
/*MSTP_Master_Node_FSM(&MSTP_Port);
|
||||
};
|
||||
/*MSTP_Master_Node_FSM(&MSTP_Port);
|
||||
*/
|
||||
}
|
||||
/* see if there is a packet available, and a place
|
||||
to put the reply (if necessary) and process it */
|
||||
if (Receive_Buffer.ready && !MSTP_Port.TxReady) {
|
||||
if (Receive_Buffer.pdu_len) {
|
||||
MSTP_Packets++;
|
||||
npdu_handler(
|
||||
&Receive_Buffer.address,
|
||||
/* see if there is a packet available, and a place
|
||||
to put the reply (if necessary) and process it */
|
||||
if (Receive_Buffer.ready && !MSTP_Port.TxReady) {
|
||||
if (Receive_Buffer.pdu_len) {
|
||||
MSTP_Packets++;
|
||||
npdu_handler(&Receive_Buffer.address,
|
||||
&Receive_Buffer.pdu[0], Receive_Buffer.pdu_len);
|
||||
}
|
||||
Receive_Buffer.ready = false;
|
||||
}
|
||||
Receive_Buffer.ready = false;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -246,12 +234,11 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_address)
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
src->adr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* for the MS/TP state machine to use for putting received data */
|
||||
uint16_t dlmstp_put_receive(
|
||||
uint8_t src, /* source MS/TP address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
}
|
||||
|
||||
/* for the MS/TP state machine to use for putting received data */
|
||||
uint16_t dlmstp_put_receive(uint8_t src, /* source MS/TP address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t pdu_len)
|
||||
{ /* amount of PDU data */
|
||||
/* PDU is already in the Receive_Buffer */
|
||||
@@ -259,13 +246,13 @@ uint16_t dlmstp_put_receive(
|
||||
Receive_Buffer.pdu_len = pdu_len;
|
||||
Receive_Buffer.ready = true;
|
||||
}
|
||||
|
||||
|
||||
void dlmstp_set_my_address(uint8_t mac_address)
|
||||
{
|
||||
/* Master Nodes can only have address 0-127 */
|
||||
if (mac_address <= 127)
|
||||
MSTP_Port.This_Station = mac_address;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -296,7 +283,7 @@ unsigned dlmstp_max_info_frames(void)
|
||||
/* 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, */
|
||||
/* 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)
|
||||
{
|
||||
|
||||
@@ -77,7 +77,7 @@ void My_Read_Property_Handler(uint8_t * service_request,
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
|
||||
&my_address, &npdu_data);
|
||||
/* bad decoding - send an abort */
|
||||
if (len < 0) {
|
||||
@@ -101,8 +101,8 @@ void My_Read_Property_Handler(uint8_t * service_request,
|
||||
data.application_data_len = len;
|
||||
/* FIXME: probably need a length limitation sent with encode */
|
||||
len =
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
rp_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||
[pdu_len], service_data->invoke_id, &data);
|
||||
} else
|
||||
error = true;
|
||||
} else
|
||||
|
||||
@@ -56,13 +56,13 @@
|
||||
|
||||
/* debug print statements */
|
||||
#if PRINT_ENABLED
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 1
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 1
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#else
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 0
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 0
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#endif
|
||||
|
||||
/* MS/TP Frame Format */
|
||||
@@ -450,7 +450,8 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
} else {
|
||||
if ((mstp_port->DestinationAddress == mstp_port->This_Station)
|
||||
if ((mstp_port->DestinationAddress ==
|
||||
mstp_port->This_Station)
|
||||
|| (mstp_port->DestinationAddress ==
|
||||
MSTP_BROADCAST_ADDRESS)) {
|
||||
/* FrameTooLong */
|
||||
@@ -459,21 +460,24 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
/* unacceptable data length has been received */
|
||||
mstp_port->ReceivedInvalidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
mstp_port->receive_state =
|
||||
MSTP_RECEIVE_STATE_IDLE;
|
||||
}
|
||||
/* NoData */
|
||||
else if (mstp_port->DataLength == 0) {
|
||||
/* indicate that a frame with no data has been received */
|
||||
mstp_port->ReceivedValidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
mstp_port->receive_state =
|
||||
MSTP_RECEIVE_STATE_IDLE;
|
||||
}
|
||||
/* Data */
|
||||
else {
|
||||
mstp_port->Index = 0;
|
||||
mstp_port->DataCRC = 0xFFFF;
|
||||
/* receive the data portion of the frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
|
||||
mstp_port->receive_state =
|
||||
MSTP_RECEIVE_STATE_DATA;
|
||||
}
|
||||
}
|
||||
/* NotForUs */
|
||||
@@ -482,8 +486,8 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/* not per MS/TP standard, but it is a case not covered */
|
||||
else {
|
||||
@@ -655,7 +659,7 @@ char *mstp_frame_type_text(int type)
|
||||
#endif
|
||||
|
||||
/* returns true if we need to transition immediately */
|
||||
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port)
|
||||
{
|
||||
int mtu_len = 0;
|
||||
int frame_type = 0;
|
||||
@@ -1217,11 +1221,11 @@ void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port)
|
||||
mstp_port->SoleMaster = false;
|
||||
mstp_port->SourceAddress = 0;
|
||||
mstp_port->TokenCount = 0;
|
||||
#if 0
|
||||
#if 0
|
||||
/* these are adjustable, so should already be set */
|
||||
mstp_port->Nmax_info_frames = DEFAULT_MAX_INFO_FRAMES;
|
||||
mstp_port->Nmax_master = DEFAULT_MAX_MASTER;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* An array of octets, used to store PDU octets prior to being transmitted. */
|
||||
/* This array is only used for APDU messages */
|
||||
|
||||
+191
-202
@@ -42,7 +42,7 @@ extern volatile struct mstp_port_struct_t MSTP_Port;
|
||||
uint32_t RS485_Baud_Rate = 9600;
|
||||
|
||||
/* the ISR and other use this for status and control */
|
||||
COMSTAT RS485_Comstat;
|
||||
COMSTAT RS485_Comstat;
|
||||
|
||||
/*#pragma udata MSTPPortData */
|
||||
/* the buffer for receiving characters */
|
||||
@@ -59,53 +59,55 @@ volatile uint8_t RS485_Tx_Buffer[MAX_MPDU];
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes) /* number of bytes of data (up to 501) */
|
||||
{
|
||||
uint16_t i = 0; /* loop counter */
|
||||
uint8_t turnaround_time;
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint16_t i = 0; /* loop counter */
|
||||
uint8_t turnaround_time;
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
/* bounds check */
|
||||
if (nbytes >= sizeof(RS485_Tx_Buffer))
|
||||
return;
|
||||
|
||||
/* buffer is full. Wait for ISR to transmit. */
|
||||
while (RS485_Comstat.Tx_Bytes) {
|
||||
};
|
||||
|
||||
/* wait 40 bit times since reception */
|
||||
if (RS485_Baud_Rate == 9600)
|
||||
turnaround_time = 4;
|
||||
else if (RS485_Baud_Rate == 19200)
|
||||
turnaround_time = 2;
|
||||
else
|
||||
turnaround_time = 1;
|
||||
|
||||
while (mstp_port->SilenceTimer < turnaround_time) {
|
||||
};
|
||||
|
||||
RS485_Comstat.TxHead = 0;
|
||||
memcpy((void *) &RS485_Tx_Buffer[0], (void *) buffer, nbytes);
|
||||
|
||||
/*for (i = 0; i < nbytes; i++) { */
|
||||
/* /* put the data into the buffer */ */
|
||||
/* RS485_Tx_Buffer[i] = *buffer; */
|
||||
/* buffer++; */
|
||||
/*} */
|
||||
RS485_Comstat.Tx_Bytes = nbytes;
|
||||
/* disable the receiver */
|
||||
PIE3bits.RC2IE = 0;
|
||||
RCSTA2bits.CREN = 0;
|
||||
/* enable the transceiver */
|
||||
RS485_TX_ENABLE = 1;
|
||||
RS485_RX_DISABLE = 1;
|
||||
/* enable the transmitter */
|
||||
TXSTA2bits.TXEN = 1;
|
||||
PIE3bits.TX2IE = 1;
|
||||
/* per MSTP spec, sort of */
|
||||
mstp_port->SilenceTimer = 0;
|
||||
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
/* bounds check */
|
||||
if (nbytes >= sizeof(RS485_Tx_Buffer))
|
||||
return;
|
||||
|
||||
/* buffer is full. Wait for ISR to transmit. */
|
||||
while (RS485_Comstat.Tx_Bytes) {};
|
||||
|
||||
/* wait 40 bit times since reception */
|
||||
if (RS485_Baud_Rate == 9600)
|
||||
turnaround_time = 4;
|
||||
else if (RS485_Baud_Rate == 19200)
|
||||
turnaround_time = 2;
|
||||
else
|
||||
turnaround_time = 1;
|
||||
|
||||
while (mstp_port->SilenceTimer < turnaround_time) {};
|
||||
|
||||
RS485_Comstat.TxHead = 0;
|
||||
memcpy((void *)&RS485_Tx_Buffer[0], (void *)buffer, nbytes);
|
||||
|
||||
/*for (i = 0; i < nbytes; i++) { */
|
||||
/* /* put the data into the buffer */ */
|
||||
/* RS485_Tx_Buffer[i] = *buffer; */
|
||||
/* buffer++; */
|
||||
/*} */
|
||||
RS485_Comstat.Tx_Bytes = nbytes;
|
||||
/* disable the receiver */
|
||||
PIE3bits.RC2IE = 0;
|
||||
RCSTA2bits.CREN = 0;
|
||||
/* enable the transceiver */
|
||||
RS485_TX_ENABLE = 1;
|
||||
RS485_RX_DISABLE = 1;
|
||||
/* enable the transmitter */
|
||||
TXSTA2bits.TXEN = 1;
|
||||
PIE3bits.TX2IE = 1;
|
||||
/* per MSTP spec, sort of */
|
||||
mstp_port->SilenceTimer = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -114,30 +116,30 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
|
||||
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *
|
||||
mstp_port)
|
||||
{
|
||||
/* check for data */
|
||||
if (RS485_Comstat.Rx_Bytes)
|
||||
{
|
||||
mstp_port->DataRegister = RS485_Rx_Buffer[RS485_Comstat.RxTail];
|
||||
if (RS485_Comstat.RxTail >= (sizeof(RS485_Rx_Buffer)-1))
|
||||
RS485_Comstat.RxTail = 0;
|
||||
else
|
||||
RS485_Comstat.RxTail++;
|
||||
RS485_Comstat.Rx_Bytes--;
|
||||
/* errors? let the state machine know */
|
||||
if (RS485_Comstat.Rx_Bufferoverrun)
|
||||
{
|
||||
RS485_Comstat.Rx_Bufferoverrun = FALSE;
|
||||
mstp_port->ReceiveError = TRUE;
|
||||
}
|
||||
/* We read a good byte */
|
||||
else
|
||||
mstp_port->DataAvailable = TRUE;
|
||||
if (RS485_Comstat.Rx_Bytes) {
|
||||
mstp_port->DataRegister = RS485_Rx_Buffer[RS485_Comstat.RxTail];
|
||||
if (RS485_Comstat.RxTail >= (sizeof(RS485_Rx_Buffer) - 1))
|
||||
RS485_Comstat.RxTail = 0;
|
||||
else
|
||||
RS485_Comstat.RxTail++;
|
||||
RS485_Comstat.Rx_Bytes--;
|
||||
/* errors? let the state machine know */
|
||||
if (RS485_Comstat.Rx_Bufferoverrun) {
|
||||
RS485_Comstat.Rx_Bufferoverrun = FALSE;
|
||||
mstp_port->ReceiveError = TRUE;
|
||||
}
|
||||
/* We read a good byte */
|
||||
else
|
||||
mstp_port->DataAvailable = TRUE;
|
||||
}
|
||||
|
||||
return RS485_Comstat.Rx_Bytes;
|
||||
return RS485_Comstat.Rx_Bytes;
|
||||
}
|
||||
|
||||
/* *************************************************************************
|
||||
DESCRIPTION: Receives RS485 data stream
|
||||
|
||||
@@ -149,31 +151,26 @@ uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
|
||||
*************************************************************************** */
|
||||
void RS485_Interrupt_Rx(void)
|
||||
{
|
||||
char dummy;
|
||||
char dummy;
|
||||
|
||||
if ((RCSTA2bits.FERR) || (RCSTA2bits.OERR))
|
||||
{
|
||||
/* Clear the error */
|
||||
RCSTA2bits.CREN = 0;
|
||||
RCSTA2bits.CREN = 1;
|
||||
RS485_Comstat.Rx_Bufferoverrun = TRUE;
|
||||
dummy = RCREG2;
|
||||
}
|
||||
else if (RS485_Comstat.Rx_Bytes < sizeof(RS485_Rx_Buffer))
|
||||
{
|
||||
RS485_Rx_Buffer[RS485_Comstat.RxHead] = RCREG2;
|
||||
if (RS485_Comstat.RxHead >= (sizeof(RS485_Rx_Buffer)-1))
|
||||
RS485_Comstat.RxHead = 0;
|
||||
else
|
||||
RS485_Comstat.RxHead++;
|
||||
RS485_Comstat.Rx_Bytes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
RS485_Comstat.Rx_Bufferoverrun = TRUE;
|
||||
dummy = RCREG2;
|
||||
(void)dummy;
|
||||
}
|
||||
if ((RCSTA2bits.FERR) || (RCSTA2bits.OERR)) {
|
||||
/* Clear the error */
|
||||
RCSTA2bits.CREN = 0;
|
||||
RCSTA2bits.CREN = 1;
|
||||
RS485_Comstat.Rx_Bufferoverrun = TRUE;
|
||||
dummy = RCREG2;
|
||||
} else if (RS485_Comstat.Rx_Bytes < sizeof(RS485_Rx_Buffer)) {
|
||||
RS485_Rx_Buffer[RS485_Comstat.RxHead] = RCREG2;
|
||||
if (RS485_Comstat.RxHead >= (sizeof(RS485_Rx_Buffer) - 1))
|
||||
RS485_Comstat.RxHead = 0;
|
||||
else
|
||||
RS485_Comstat.RxHead++;
|
||||
RS485_Comstat.Rx_Bytes++;
|
||||
} else {
|
||||
RS485_Comstat.Rx_Bufferoverrun = TRUE;
|
||||
dummy = RCREG2;
|
||||
(void) dummy;
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************************************
|
||||
@@ -187,28 +184,25 @@ void RS485_Interrupt_Rx(void)
|
||||
*************************************************************************** */
|
||||
void RS485_Interrupt_Tx(void)
|
||||
{
|
||||
if (RS485_Comstat.Tx_Bytes)
|
||||
{
|
||||
/* Get the data byte */
|
||||
TXREG2 = RS485_Tx_Buffer[RS485_Comstat.TxHead];
|
||||
/* point to the next byte */
|
||||
RS485_Comstat.TxHead++;
|
||||
/* reduce the buffer size */
|
||||
RS485_Comstat.Tx_Bytes--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* wait for the USART to be empty */
|
||||
while (!TXSTA2bits.TRMT);
|
||||
/* disable this interrupt */
|
||||
PIE3bits.TX2IE = 0;
|
||||
/* enable the receiver */
|
||||
RS485_TX_ENABLE = 0;
|
||||
RS485_RX_DISABLE = 0;
|
||||
/* FIXME: might not be necessary */
|
||||
PIE3bits.RC2IE = 1;
|
||||
RCSTA2bits.CREN = 1;
|
||||
}
|
||||
if (RS485_Comstat.Tx_Bytes) {
|
||||
/* Get the data byte */
|
||||
TXREG2 = RS485_Tx_Buffer[RS485_Comstat.TxHead];
|
||||
/* point to the next byte */
|
||||
RS485_Comstat.TxHead++;
|
||||
/* reduce the buffer size */
|
||||
RS485_Comstat.Tx_Bytes--;
|
||||
} else {
|
||||
/* wait for the USART to be empty */
|
||||
while (!TXSTA2bits.TRMT);
|
||||
/* disable this interrupt */
|
||||
PIE3bits.TX2IE = 0;
|
||||
/* enable the receiver */
|
||||
RS485_TX_ENABLE = 0;
|
||||
RS485_RX_DISABLE = 0;
|
||||
/* FIXME: might not be necessary */
|
||||
PIE3bits.RC2IE = 1;
|
||||
RCSTA2bits.CREN = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -243,11 +237,9 @@ void RS485_Set_Baud_Rate(uint32_t baud)
|
||||
else
|
||||
RS485_Baud_Rate = 115200;
|
||||
|
||||
I2C_Write_Block(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&RS485_Baud_Rate,
|
||||
sizeof(RS485_Baud_Rate),
|
||||
EEPROM_MSTP_BAUD_RATE_ADDR);
|
||||
I2C_Write_Block(EEPROM_DEVICE_ADDRESS,
|
||||
(char *) &RS485_Baud_Rate,
|
||||
sizeof(RS485_Baud_Rate), EEPROM_MSTP_BAUD_RATE_ADDR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -260,75 +252,74 @@ void RS485_Set_Baud_Rate(uint32_t baud)
|
||||
void RS485_Initialize_Port(void)
|
||||
{
|
||||
|
||||
/* Reset USART registers to POR state */
|
||||
TXSTA2 = 0;
|
||||
RCSTA2 = 0;
|
||||
/* configure USART for receiving */
|
||||
/* since the TX will handle setting up for transmit */
|
||||
RCSTA2bits.CREN = 1;
|
||||
/* Interrupt on receipt */
|
||||
PIE3bits.RC2IE = 1;
|
||||
/* enable the transmitter, disable its interrupt */
|
||||
TXSTA2bits.TXEN = 1;
|
||||
PIE3bits.TX2IE = 0;
|
||||
/* setup USART Baud Rate Generator */
|
||||
/* see BAUD RATES FOR ASYNCHRONOUS MODE in Data Book */
|
||||
/* Fosc=20MHz
|
||||
BRGH=1 BRGH=0
|
||||
Rate SPBRG Rate SPBRG
|
||||
------- ----- ------- -----
|
||||
9615 129 9469 32
|
||||
19230 64 19530 15
|
||||
37878 32 78130 3
|
||||
56818 21 104200 2
|
||||
113630 10 312500 0
|
||||
250000 4
|
||||
625000 1
|
||||
1250000 0
|
||||
*/
|
||||
switch (RS485_Baud_Rate)
|
||||
{
|
||||
case 19200:
|
||||
SPBRG2 = 64;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 38400:
|
||||
SPBRG2 = 32;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 57600:
|
||||
SPBRG2 = 21;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 76800:
|
||||
SPBRG2 = 3;
|
||||
TXSTA2bits.BRGH = 0;
|
||||
break;
|
||||
case 115200:
|
||||
SPBRG2 = 10;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 9600:
|
||||
SPBRG2 = 129;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
default:
|
||||
SPBRG2 = 129;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
RS485_Set_Baud_Rate(9600);
|
||||
break;
|
||||
}
|
||||
/* select async mode */
|
||||
TXSTA2bits.SYNC = 0;
|
||||
/* enable transmitter */
|
||||
TXSTA2bits.TXEN = 1;
|
||||
/* serial port enable */
|
||||
RCSTA2bits.SPEN = 1;
|
||||
/* since we are using RS485,
|
||||
we need to explicitly say
|
||||
transmit enable or not */
|
||||
RS485_RX_DISABLE = 0;
|
||||
RS485_TX_ENABLE = 0;
|
||||
/* Reset USART registers to POR state */
|
||||
TXSTA2 = 0;
|
||||
RCSTA2 = 0;
|
||||
/* configure USART for receiving */
|
||||
/* since the TX will handle setting up for transmit */
|
||||
RCSTA2bits.CREN = 1;
|
||||
/* Interrupt on receipt */
|
||||
PIE3bits.RC2IE = 1;
|
||||
/* enable the transmitter, disable its interrupt */
|
||||
TXSTA2bits.TXEN = 1;
|
||||
PIE3bits.TX2IE = 0;
|
||||
/* setup USART Baud Rate Generator */
|
||||
/* see BAUD RATES FOR ASYNCHRONOUS MODE in Data Book */
|
||||
/* Fosc=20MHz
|
||||
BRGH=1 BRGH=0
|
||||
Rate SPBRG Rate SPBRG
|
||||
------- ----- ------- -----
|
||||
9615 129 9469 32
|
||||
19230 64 19530 15
|
||||
37878 32 78130 3
|
||||
56818 21 104200 2
|
||||
113630 10 312500 0
|
||||
250000 4
|
||||
625000 1
|
||||
1250000 0
|
||||
*/
|
||||
switch (RS485_Baud_Rate) {
|
||||
case 19200:
|
||||
SPBRG2 = 64;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 38400:
|
||||
SPBRG2 = 32;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 57600:
|
||||
SPBRG2 = 21;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 76800:
|
||||
SPBRG2 = 3;
|
||||
TXSTA2bits.BRGH = 0;
|
||||
break;
|
||||
case 115200:
|
||||
SPBRG2 = 10;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
case 9600:
|
||||
SPBRG2 = 129;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
break;
|
||||
default:
|
||||
SPBRG2 = 129;
|
||||
TXSTA2bits.BRGH = 1;
|
||||
RS485_Set_Baud_Rate(9600);
|
||||
break;
|
||||
}
|
||||
/* select async mode */
|
||||
TXSTA2bits.SYNC = 0;
|
||||
/* enable transmitter */
|
||||
TXSTA2bits.TXEN = 1;
|
||||
/* serial port enable */
|
||||
RCSTA2bits.SPEN = 1;
|
||||
/* since we are using RS485,
|
||||
we need to explicitly say
|
||||
transmit enable or not */
|
||||
RS485_RX_DISABLE = 0;
|
||||
RS485_TX_ENABLE = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@@ -339,9 +330,9 @@ void RS485_Initialize_Port(void)
|
||||
*****************************************************************************/
|
||||
void RS485_Disable_Port(void)
|
||||
{
|
||||
RCSTA2 &= 0x4F; /* Disable the receiver */
|
||||
TXSTA2bits.TXEN = 0; /* and transmitter */
|
||||
PIE3 &= 0xCF; /* Disable both interrupts */
|
||||
RCSTA2 &= 0x4F; /* Disable the receiver */
|
||||
TXSTA2bits.TXEN = 0; /* and transmitter */
|
||||
PIE3 &= 0xCF; /* Disable both interrupts */
|
||||
}
|
||||
|
||||
void RS485_Reinit(void)
|
||||
@@ -357,20 +348,18 @@ void RS485_Reinit(void)
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(void)
|
||||
{
|
||||
/* Init the Rs485 buffers */
|
||||
RS485_Comstat.RxHead = 0;
|
||||
RS485_Comstat.RxTail = 0;
|
||||
RS485_Comstat.Rx_Bytes = 0;
|
||||
RS485_Comstat.Rx_Bufferoverrun = FALSE;
|
||||
RS485_Comstat.TxHead = 0;
|
||||
RS485_Comstat.TxTail = 0;
|
||||
RS485_Comstat.Tx_Bytes = 0;
|
||||
/* Init the Rs485 buffers */
|
||||
RS485_Comstat.RxHead = 0;
|
||||
RS485_Comstat.RxTail = 0;
|
||||
RS485_Comstat.Rx_Bytes = 0;
|
||||
RS485_Comstat.Rx_Bufferoverrun = FALSE;
|
||||
RS485_Comstat.TxHead = 0;
|
||||
RS485_Comstat.TxTail = 0;
|
||||
RS485_Comstat.Tx_Bytes = 0;
|
||||
|
||||
I2C_Read_Block(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&RS485_Baud_Rate,
|
||||
sizeof(RS485_Baud_Rate),
|
||||
EEPROM_MSTP_BAUD_RATE_ADDR);
|
||||
I2C_Read_Block(EEPROM_DEVICE_ADDRESS,
|
||||
(char *) &RS485_Baud_Rate,
|
||||
sizeof(RS485_Baud_Rate), EEPROM_MSTP_BAUD_RATE_ADDR);
|
||||
|
||||
RS485_Initialize_Port();
|
||||
RS485_Initialize_Port();
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ extern "C" {
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes); /* number of bytes of data (up to 501) */
|
||||
|
||||
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
|
||||
|
||||
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
|
||||
|
||||
void RS485_Interrupt_Rx(void);
|
||||
|
||||
void RS485_Interrupt_Tx(void);
|
||||
|
||||
@@ -66,7 +66,7 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
int bytes_sent = 0;
|
||||
uint8_t frame_type = 0;
|
||||
uint8_t destination = 0; /* destination address */
|
||||
BACNET_ADDRESS src;
|
||||
BACNET_ADDRESS src;
|
||||
unsigned mtu_len = 0;
|
||||
|
||||
if (MSTP_Port.TxReady == false) {
|
||||
@@ -84,23 +84,22 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
fprintf(stderr, "mstp: invalid destination MAC address!\n");
|
||||
#endif
|
||||
return -2;
|
||||
}
|
||||
/* header len */
|
||||
}
|
||||
/* header len */
|
||||
mtu_len = 8;
|
||||
if ((mtu_len + pdu_len) > MAX_MPDU) {
|
||||
if ((mtu_len + pdu_len) > MAX_MPDU) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "mstp: PDU is too big to send!\n");
|
||||
#endif
|
||||
return -4;
|
||||
}
|
||||
memmove(&PDU_Buffer[mtu_len], pdu, pdu_len);
|
||||
}
|
||||
memmove(&PDU_Buffer[mtu_len], pdu, pdu_len);
|
||||
mtu_len += pdu_len;
|
||||
bytes_sent = MSTP_Create_Frame(
|
||||
(uint8_t *) & MSTP_Port.TxBuffer[0],
|
||||
sizeof(MSTP_Port.TxBuffer),
|
||||
MSTP_Port.TxFrameType,
|
||||
destination,
|
||||
MSTP_Port.This_Station, &PDU_Buffer[0], mtu_len);
|
||||
destination, MSTP_Port.This_Station, &PDU_Buffer[0], mtu_len);
|
||||
MSTP_Port.TxLength = bytes_sent;
|
||||
MSTP_Port.TxReady = true;
|
||||
}
|
||||
@@ -123,7 +122,7 @@ uint16_t dlmstp_receive(BACNET_ADDRESS * src, /* source address */
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
|
||||
(void) timeout;
|
||||
(void) timeout;
|
||||
/* only do receive state machine while we don't have a frame */
|
||||
if ((MSTP_Port.ReceivedValidFrame == false) &&
|
||||
(MSTP_Port.ReceivedInvalidFrame == false)) {
|
||||
@@ -132,7 +131,8 @@ uint16_t dlmstp_receive(BACNET_ADDRESS * src, /* source address */
|
||||
}
|
||||
/* only do master state machine while rx is idle */
|
||||
if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) {
|
||||
while (MSTP_Master_Node_FSM(&MSTP_Port)) {};
|
||||
while (MSTP_Master_Node_FSM(&MSTP_Port)) {
|
||||
};
|
||||
}
|
||||
/* see if there is a packet available */
|
||||
if (Receive_Buffer.ready) {
|
||||
|
||||
@@ -96,7 +96,7 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
|
||||
int mtu_len = 0;
|
||||
int i = 0;
|
||||
|
||||
(void)npdu_data;
|
||||
(void) npdu_data;
|
||||
/* don't waste time if the socket is not valid */
|
||||
if (Ethernet_Socket < 0) {
|
||||
fprintf(stderr, "ethernet: 802.2 socket is invalid!\n");
|
||||
|
||||
@@ -93,7 +93,7 @@ void RTOS_Initialize(void)
|
||||
RTKernelInit(5); /* get the kernel going */
|
||||
RTKeybrdInit();
|
||||
/*(void)CPUMoniInit(); /* not needed - just monitor idle task */ */
|
||||
RTComInit();
|
||||
RTComInit();
|
||||
ITimerInit();
|
||||
|
||||
if (RTCallDebugger(RT_DBG_MONITOR, 0, 0) != -1) {
|
||||
|
||||
@@ -56,13 +56,13 @@
|
||||
|
||||
/* debug print statements */
|
||||
#if PRINT_ENABLED
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 1
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 1
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#else
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 0
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#define PRINT_ENABLED_RECEIVE 0
|
||||
#define PRINT_ENABLED_RECEIVE_DATA 0
|
||||
#define PRINT_ENABLED_MASTER 0
|
||||
#endif
|
||||
|
||||
/* MS/TP Frame Format */
|
||||
@@ -458,7 +458,8 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
} else {
|
||||
if ((mstp_port->DestinationAddress == mstp_port->This_Station)
|
||||
if ((mstp_port->DestinationAddress ==
|
||||
mstp_port->This_Station)
|
||||
|| (mstp_port->DestinationAddress ==
|
||||
MSTP_BROADCAST_ADDRESS)) {
|
||||
/* FrameTooLong */
|
||||
@@ -467,39 +468,42 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
/* unacceptable data length has been received */
|
||||
mstp_port->ReceivedInvalidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
mstp_port->receive_state =
|
||||
MSTP_RECEIVE_STATE_IDLE;
|
||||
}
|
||||
/* NoData */
|
||||
else if (mstp_port->DataLength == 0) {
|
||||
/* CHEAT: it is very difficult to respond to
|
||||
poll for master in the Master Node state machine
|
||||
before Tusage_timeout, so we will do it here. */
|
||||
if ((mstp_port->FrameType == FRAME_TYPE_POLL_FOR_MASTER) &&
|
||||
(mstp_port->DestinationAddress == mstp_port->This_Station) &&
|
||||
(mstp_port->master_state == MSTP_MASTER_STATE_IDLE))
|
||||
{
|
||||
if ((mstp_port->FrameType ==
|
||||
FRAME_TYPE_POLL_FOR_MASTER)
|
||||
&& (mstp_port->DestinationAddress ==
|
||||
mstp_port->This_Station)
|
||||
&& (mstp_port->master_state ==
|
||||
MSTP_MASTER_STATE_IDLE)) {
|
||||
MSTP_Create_And_Send_Frame(mstp_port,
|
||||
FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
|
||||
mstp_port->SourceAddress, mstp_port->This_Station,
|
||||
NULL, 0);
|
||||
mstp_port->SourceAddress,
|
||||
mstp_port->This_Station, NULL, 0);
|
||||
/* don't indicate that a frame has been received */
|
||||
mstp_port->ReceivedInvalidFrame = false;
|
||||
mstp_port->ReceivedValidFrame = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
/* indicate that a frame with no data has been received */
|
||||
mstp_port->ReceivedValidFrame = true;
|
||||
}
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
mstp_port->receive_state =
|
||||
MSTP_RECEIVE_STATE_IDLE;
|
||||
}
|
||||
/* Data */
|
||||
else {
|
||||
mstp_port->Index = 0;
|
||||
mstp_port->DataCRC = 0xFFFF;
|
||||
/* receive the data portion of the frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
|
||||
mstp_port->receive_state =
|
||||
MSTP_RECEIVE_STATE_DATA;
|
||||
}
|
||||
}
|
||||
/* NotForUs */
|
||||
@@ -508,8 +512,8 @@ void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/* not per MS/TP standard, but it is a case not covered */
|
||||
else {
|
||||
@@ -681,7 +685,7 @@ char *mstp_frame_type_text(int type)
|
||||
#endif
|
||||
|
||||
/* returns true if we need to transition immediately */
|
||||
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t * mstp_port)
|
||||
{
|
||||
int mtu_len = 0;
|
||||
int frame_type = 0;
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
*
|
||||
*********************************************************************/
|
||||
#if PRINT_ENABLED
|
||||
#define PRINT_ENABLED_RS485 1
|
||||
#define PRINT_ENABLED_RS485 1
|
||||
#else
|
||||
#define PRINT_ENABLED_RS485 0
|
||||
#define PRINT_ENABLED_RS485 0
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -57,27 +57,24 @@ static FineTime RS485_Debug_Transmit_Timer;
|
||||
#endif
|
||||
|
||||
#if PRINT_ENABLED_RS485
|
||||
void RS485_Print_Frame(int port,
|
||||
FineTime timer,
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
void RS485_Print_Frame(int port, FineTime timer, uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes)
|
||||
{
|
||||
uint16_t i; /* byte counter */
|
||||
unsigned long duration; /* measures the time from last output to this one */
|
||||
uint16_t i; /* byte counter */
|
||||
unsigned long duration; /* measures the time from last output to this one */
|
||||
unsigned long seconds;
|
||||
unsigned long milliseconds;
|
||||
|
||||
|
||||
duration = ElapsedMilliSecs(timer);
|
||||
seconds = duration / 1000U;
|
||||
milliseconds = duration - (seconds * 1000U);
|
||||
fprintf(stderr,"%0lu.%03lu: COM%d:",seconds,milliseconds,port+1);
|
||||
for (i = 0; i < nbytes; i++)
|
||||
{
|
||||
unsigned value;
|
||||
value = buffer[i];
|
||||
fprintf(stderr," %02X",value);
|
||||
fprintf(stderr, "%0lu.%03lu: COM%d:", seconds, milliseconds, port + 1);
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
unsigned value;
|
||||
value = buffer[i];
|
||||
fprintf(stderr, " %02X", value);
|
||||
}
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
@@ -179,10 +176,8 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
|
||||
octet is transmitted. */
|
||||
mstp_port->SilenceTimer = 0;
|
||||
#if PRINT_ENABLED_RS485
|
||||
RS485_Print_Frame(RS485_Port,
|
||||
RS485_Debug_Transmit_Timer,
|
||||
buffer, /* frame to send (up to 501 bytes of data) */
|
||||
nbytes);
|
||||
RS485_Print_Frame(RS485_Port, RS485_Debug_Transmit_Timer, buffer, /* frame to send (up to 501 bytes of data) */
|
||||
nbytes);
|
||||
MarkTime(&RS485_Debug_Transmit_Timer);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -430,8 +430,8 @@ void ethernet_debug_address(const char *info, BACNET_ADDRESS * dest)
|
||||
if (info) {
|
||||
sprintf(msgBuf, "%s", info);
|
||||
LogError(msgBuf);
|
||||
} /* if */
|
||||
|
||||
}
|
||||
/* if */
|
||||
if (dest) {
|
||||
sprintf(msgBuf,
|
||||
"Address:\n MAC Length=%d\n MAC Address=", dest->mac_len);
|
||||
@@ -449,7 +449,7 @@ void ethernet_debug_address(const char *info, BACNET_ADDRESS * dest)
|
||||
LogInfo(msgBuf);
|
||||
} /* for */
|
||||
LogInfo("\n");
|
||||
} /* if ( dest ) */
|
||||
|
||||
}
|
||||
/* if ( dest ) */
|
||||
return;
|
||||
}
|
||||
|
||||
+3
-2
@@ -43,7 +43,7 @@ int wp_encode_apdu(uint8_t * apdu,
|
||||
uint8_t invoke_id, BACNET_WRITE_PROPERTY_DATA * data)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
int len = 0; /* total length of the apdu, return value */
|
||||
int len = 0; /* total length of the apdu, return value */
|
||||
|
||||
if (apdu) {
|
||||
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
|
||||
@@ -67,7 +67,8 @@ int wp_encode_apdu(uint8_t * apdu,
|
||||
/* propertyValue */
|
||||
len = encode_opening_tag(&apdu[apdu_len], 3);
|
||||
apdu_len += len;
|
||||
len = bacapp_encode_application_data(&apdu[apdu_len], &data->value);
|
||||
len =
|
||||
bacapp_encode_application_data(&apdu[apdu_len], &data->value);
|
||||
apdu_len += len;
|
||||
len = encode_closing_tag(&apdu[apdu_len], 3);
|
||||
apdu_len += len;
|
||||
|
||||
Reference in New Issue
Block a user