diff --git a/ports/at91sam7s/Makefile b/ports/at91sam7s/Makefile
index 9a9c5cd3..c207e07d 100644
--- a/ports/at91sam7s/Makefile
+++ b/ports/at91sam7s/Makefile
@@ -61,6 +61,7 @@ DEMOSRC = ai.c \
bi.c \
bv.c \
device.c \
+ netport.c \
$(BACNET_BASIC)/tsm/tsm.c \
$(BACNET_BASIC)/sys/ringbuf.c \
$(BACNET_BASIC)/npdu/h_npdu.c \
diff --git a/ports/at91sam7s/bacnet.ewp b/ports/at91sam7s/bacnet.ewp
index 0bc6556b..1ff4a2a6 100644
--- a/ports/at91sam7s/bacnet.ewp
+++ b/ports/at91sam7s/bacnet.ewp
@@ -1108,6 +1108,9 @@
$PROJ_DIR$\device.c
+
+ $PROJ_DIR$\netport.c
+
$PROJ_DIR$\dlmstp.c
diff --git a/ports/at91sam7s/device.c b/ports/at91sam7s/device.c
index 26dc3fed..26200817 100644
--- a/ports/at91sam7s/device.c
+++ b/ports/at91sam7s/device.c
@@ -39,6 +39,9 @@
#include "bacnet/basic/services.h"
#include "bacnet/proplist.h"
/* objects */
+#if (BACNET_PROTOCOL_REVISION >= 17)
+#include "bacnet/basic/object/netport.h"
+#endif
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/ai.h"
#include "bacnet/basic/object/av.h"
@@ -64,11 +67,12 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
-} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
- Device_Count, Device_Index_To_Instance,
- Device_Valid_Object_Instance_Number,
- Device_Object_Name, Device_Read_Property_Local,
- Device_Write_Property_Local, Device_Property_Lists },
+} Object_Table[] = {
+ { OBJECT_DEVICE, NULL, /* don't init - recursive! */
+ Device_Count, Device_Index_To_Instance,
+ Device_Valid_Object_Instance_Number,
+ Device_Object_Name, Device_Read_Property_Local,
+ Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
@@ -85,6 +89,12 @@ static struct my_object_functions {
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
Binary_Value_Object_Name, Binary_Value_Read_Property,
Binary_Value_Write_Property, Binary_Value_Property_Lists },
+#if (BACNET_PROTOCOL_REVISION >= 17)
+ { OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
+ Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
+ Network_Port_Object_Name, Network_Port_Read_Property,
+ Network_Port_Write_Property, Network_Port_Property_Lists },
+#endif
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
/* note: you really only need to define variables for
@@ -769,7 +779,7 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
break;
case 9600:
apdu_len =
- encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
+ encode_application_unsigned(&apdu[0], rs485_baud_rate());
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -896,9 +906,9 @@ bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 115200) {
- RS485_Set_Baud_Rate(value.type.Unsigned_Int);
- status = true;
- } else {
+ status = rs485_baud_rate_set(value.type.Unsigned_Int);
+ }
+ if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
diff --git a/ports/at91sam7s/dlmstp.c b/ports/at91sam7s/dlmstp.c
index 8af419b6..f9a85aea 100644
--- a/ports/at91sam7s/dlmstp.c
+++ b/ports/at91sam7s/dlmstp.c
@@ -1396,3 +1396,13 @@ void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
return;
}
+
+uint8_t dlmstp_max_info_frames_limit(void)
+{
+ return MSTP_PDU_PACKET_COUNT;
+}
+
+uint8_t dlmstp_max_master_limit(void)
+{
+ return 127;
+}
diff --git a/ports/at91sam7s/init.c b/ports/at91sam7s/init.c
index b50aac11..0778ef3b 100644
--- a/ports/at91sam7s/init.c
+++ b/ports/at91sam7s/init.c
@@ -21,12 +21,32 @@
/* Include the board file description */
#include "board.h"
+#if defined(__ICCARM__)
+//------------------------------------------------------------------------------
+// Internal functions
+//------------------------------------------------------------------------------
+static void AT91F_Spurious_handler( void )
+{
+ while (1);
+}
+
+static void AT91F_Default_FIQ_handler( void )
+{
+ while (1);
+}
+
+static void AT91F_Default_IRQ_handler( void )
+{
+ while (1);
+}
+#else
/* The following functions must be write in ARM mode this function called
* directly */
/* by exception vector */
extern void AT91F_Spurious_handler(void);
extern void AT91F_Default_IRQ_handler(void);
extern void AT91F_Default_FIQ_handler(void);
+#endif
/**----------------------------------------------------------------------------
*/
diff --git a/ports/at91sam7s/isr.c b/ports/at91sam7s/isr.c
index 9781354a..cd882c67 100644
--- a/ports/at91sam7s/isr.c
+++ b/ports/at91sam7s/isr.c
@@ -23,6 +23,8 @@
#include "at91sam7s256.h"
#include "isr.h"
+#if defined(__GNUC__)
+/* GCC */
#define IRQ_MASK 0x00000080
#define FIQ_MASK 0x00000040
#define INT_MASK (IRQ_MASK | FIQ_MASK)
@@ -91,3 +93,4 @@ unsigned enableFIQ(void)
__set_cpsr(_cpsr & ~FIQ_MASK);
return _cpsr;
}
+#endif
diff --git a/ports/at91sam7s/isr.h b/ports/at91sam7s/isr.h
index b8d89dfb..554894a2 100644
--- a/ports/at91sam7s/isr.h
+++ b/ports/at91sam7s/isr.h
@@ -32,6 +32,8 @@
#include
#define isr_enable() __enable_interrupt()
#define isr_disable() __disable_interrupt()
+#define __get_cpsr __get_CPSR
+#define __set_cpsr __set_CPSR
#endif
#if defined(__GNUC__)
#define isr_enable() enableIRQ();enableFIQ();
diff --git a/ports/at91sam7s/main.c b/ports/at91sam7s/main.c
index 9b67ccf7..4da0b38c 100644
--- a/ports/at91sam7s/main.c
+++ b/ports/at91sam7s/main.c
@@ -133,7 +133,7 @@ static inline void bacnet_init(void)
#if defined(BACDL_MSTP)
uint8_t MAC_Address = 0x55;
- RS485_Set_Baud_Rate(38400);
+ rs485_baud_rate_set(38400);
dlmstp_set_mac_address(MAC_Address);
dlmstp_set_max_master(127);
dlmstp_set_max_info_frames(1);
diff --git a/ports/at91sam7s/netport.c b/ports/at91sam7s/netport.c
new file mode 100644
index 00000000..3a2899a6
--- /dev/null
+++ b/ports/at91sam7s/netport.c
@@ -0,0 +1,748 @@
+/**
+ * @file
+ * @author Steve Karg
+ * @date 2016
+ * @brief Network port objects, customize for your use
+ *
+ * @section DESCRIPTION
+ *
+ * The Network Port object provides access to the configuration
+ * and properties of network ports of a device.
+ *
+ * @section LICENSE
+ *
+ * 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
+#include
+#include
+#include
+#include
+#include
+#include "bacnet/config.h"
+#include "bacnet/basic/binding/address.h"
+#include "bacnet/bacdef.h"
+#include "bacnet/bacapp.h"
+#include "bacnet/bacdcode.h"
+#include "bacnet/npdu.h"
+#include "bacnet/apdu.h"
+#include "bacnet/basic/object/device.h"
+/* MS/TP specific */
+#include "bacnet/datalink/dlmstp.h"
+#include "rs485.h"
+//#include "nvdata.h"
+/* me */
+#include "bacnet/basic/object/netport.h"
+
+/* our local object data */
+struct object_data {
+ bool Changes_Pending : 1;
+ uint8_t MAC_Address[1];
+ uint8_t Max_Master;
+ uint8_t Max_Info_Frames;
+ float Link_Speed;
+};
+
+/* this object example only supports 1 instance */
+#define BACNET_NETWORK_PORTS_MAX 1
+struct object_data Object_List[BACNET_NETWORK_PORTS_MAX];
+/* instance number - can be overridden */
+#ifndef BACNET_NETWORK_PORT_INSTANCE
+#define BACNET_NETWORK_PORT_INSTANCE 1
+#endif
+
+/* These three arrays are used by the ReadPropertyMultiple handler */
+static const int Network_Port_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
+ PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_STATUS_FLAGS, PROP_RELIABILITY,
+ PROP_OUT_OF_SERVICE, PROP_NETWORK_TYPE, PROP_PROTOCOL_LEVEL,
+ PROP_NETWORK_NUMBER, PROP_NETWORK_NUMBER_QUALITY, PROP_CHANGES_PENDING,
+ PROP_APDU_LENGTH, PROP_LINK_SPEED, -1 };
+
+static const int Network_Port_Properties_Optional[] = { PROP_MAC_ADDRESS,
+ PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, -1 };
+
+static const int Network_Port_Properties_Proprietary[] = { -1 };
+
+/**
+ * Returns the list of required, optional, and proprietary properties.
+ * Used by ReadPropertyMultiple service.
+ *
+ * @param object_instance - object-instance number of the object
+ * @param pRequired - pointer to list of int terminated by -1, of
+ * BACnet required properties for this object.
+ * @param pOptional - pointer to list of int terminated by -1, of
+ * BACnet optkional properties for this object.
+ * @param pProprietary - pointer to list of int terminated by -1, of
+ * BACnet proprietary properties for this object.
+ */
+void Network_Port_Property_List(uint32_t object_instance,
+ const int **pRequired,
+ const int **pOptional,
+ const int **pProprietary)
+{
+ (void)object_instance;
+ if (pRequired) {
+ *pRequired = Network_Port_Properties_Required;
+ }
+ if (pOptional) {
+ *pOptional = Network_Port_Properties_Optional;
+ }
+ if (pProprietary) {
+ *pProprietary = Network_Port_Properties_Proprietary;
+ }
+
+ return;
+}
+
+/**
+ * Returns the list of required, optional, and proprietary properties.
+ * Used by ReadPropertyMultiple service.
+ *
+ * @param pRequired - pointer to list of int terminated by -1, of
+ * BACnet required properties for this object.
+ * @param pOptional - pointer to list of int terminated by -1, of
+ * BACnet optkional properties for this object.
+ * @param pProprietary - pointer to list of int terminated by -1, of
+ * BACnet proprietary properties for this object.
+ */
+void Network_Port_Property_Lists(
+ const int **pRequired, const int **pOptional, const int **pProprietary)
+{
+ Network_Port_Property_List(
+ BACNET_NETWORK_PORT_INSTANCE, pRequired, pOptional, pProprietary);
+}
+
+/**
+ * For a given object instance-number, loads the object-name into
+ * a characterstring. Note that the object name must be unique
+ * within this device.
+ *
+ * @param object_instance - object-instance number of the object
+ * @param object_name - holds the object-name retrieved
+ *
+ * @return true if object-name was retrieved
+ */
+bool Network_Port_Object_Name(
+ uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
+{
+ bool status = false;
+
+ if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
+ status = characterstring_init_ansi(object_name, "NP-1");
+ }
+
+ return status;
+}
+
+/**
+ * Determines if a given Network Port instance is valid
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return true if the instance is valid, and false if not
+ */
+bool Network_Port_Valid_Instance(uint32_t object_instance)
+{
+ if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Determines the number of Network Port objects
+ *
+ * @return Number of Network Port objects
+ */
+unsigned Network_Port_Count(void)
+{
+ return BACNET_NETWORK_PORTS_MAX;
+}
+
+/**
+ * Determines the object instance-number for a given 0..N index
+ * of Network Port objects where N is Network_Port_Count().
+ *
+ * @param index - 0..BACNET_NETWORK_PORTS_MAX value
+ *
+ * @return object instance-number for the given index, or BACNET_MAX_INSTANCE
+ * for an invalid index.
+ */
+uint32_t Network_Port_Index_To_Instance(unsigned index)
+{
+ if (index < BACNET_NETWORK_PORTS_MAX) {
+ return BACNET_NETWORK_PORT_INSTANCE;
+ }
+
+ return BACNET_MAX_INSTANCE;
+}
+
+/**
+ * For a given object instance-number, determines a 0..N index
+ * of Network Port objects where N is Network_Port_Count().
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return index for the given instance-number, or BACNET_NETWORK_PORTS_MAX
+ * if not valid.
+ */
+unsigned Network_Port_Instance_To_Index(uint32_t object_instance)
+{
+ if (object_instance == BACNET_NETWORK_PORT_INSTANCE) {
+ return 0;
+ }
+
+ return BACNET_NETWORK_PORTS_MAX;
+}
+
+/**
+ * For a given object instance-number, returns the out-of-service
+ * property value
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return out-of-service property value
+ */
+bool Network_Port_Out_Of_Service(uint32_t object_instance)
+{
+ (void)object_instance;
+ return false;
+}
+
+/**
+ * For a given object instance-number, gets the reliability.
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return reliability value
+ */
+BACNET_RELIABILITY Network_Port_Reliability(uint32_t object_instance)
+{
+ (void)object_instance;
+ return RELIABILITY_NO_FAULT_DETECTED;
+}
+
+/**
+ * For a given object instance-number, gets the BACnet Network Type.
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return BACnet network type value
+ */
+uint8_t Network_Port_Type(uint32_t object_instance)
+{
+ (void)object_instance;
+ return PORT_TYPE_MSTP;
+}
+
+/**
+ * For a given object instance-number, gets the BACnet Network Number.
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return BACnet network type value
+ */
+uint16_t Network_Port_Network_Number(uint32_t object_instance)
+{
+ (void)object_instance;
+ /* A Network_Number of 0 indicates that the Network_Number
+ is not known or cannot be determined. */
+ return 0;
+}
+
+/**
+ * For a given object instance-number, gets the quality property
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return quality property value
+ */
+BACNET_PORT_QUALITY Network_Port_Quality(uint32_t object_instance)
+{
+ (void)object_instance;
+ return PORT_QUALITY_CONFIGURED;
+}
+
+/**
+ * For a given object instance-number, loads the mac-address into
+ * an octet string.
+ *
+ * @param object_instance - object-instance number of the object
+ * @param mac_address - holds the mac-address retrieved
+ *
+ * @return true if mac-address was retrieved
+ */
+bool Network_Port_MAC_Address(
+ uint32_t object_instance, BACNET_OCTET_STRING *mac_address)
+{
+ (void)object_instance;
+ Object_List[0].MAC_Address[0] = dlmstp_mac_address();
+
+ return octetstring_init(mac_address, Object_List[0].MAC_Address, 1);
+}
+
+/**
+ * @brief For a given object instance-number, set the mac-address and length
+ * @param object_instance - object-instance number of the object
+ * @param mac_src - holds the MAC address to be written
+ * @param mac_len - number of bytes in the MAC address
+ * @return true if object-name was set
+ */
+bool Network_Port_MAC_Address_Set(
+ uint32_t object_instance, uint8_t *mac_src, uint8_t mac_len)
+{
+ if (mac_len == 1) {
+ Object_List[0].MAC_Address[0] = mac_src[0];
+ Object_List[0].Changes_Pending = true;
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * For a given object instance-number, gets the BACnet Network Number.
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return APDU length for this network port
+ */
+uint16_t Network_Port_APDU_Length(uint32_t object_instance)
+{
+ (void)object_instance;
+ return MAX_APDU;
+}
+
+/**
+ * For a given object instance-number, gets the network communication rate
+ * as the number of bits per second. A value of 0 indicates an unknown
+ * communication rate.
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return Link_Speed for this network port, or 0 if unknown
+ */
+float Network_Port_Link_Speed(uint32_t object_instance)
+{
+ (void)object_instance;
+ Object_List[0].Link_Speed = rs485_baud_rate();
+
+ return Object_List[0].Link_Speed;
+}
+
+/**
+ * @brief Set the device link speed (baud rate)
+ * @param object_instance The object instance number of the object
+ * @param value The new link speed value
+ * @return true if value was set
+ */
+bool Network_Port_Link_Speed_Set(uint32_t object_instance, float value)
+{
+ bool status = false;
+ uint32_t baud = (uint32_t)value;
+
+ switch (baud) {
+ case 9600:
+ case 19200:
+ case 38400:
+ case 57600:
+ case 76800:
+ case 115200:
+ Object_List[0].Link_Speed = value;
+ Object_List[0].Changes_Pending = true;
+ status = true;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * @brief For a given object instance-number, returns the changes-pending flag
+ * @param object_instance - object-instance number of the object
+ * @return changes-pending property value
+ */
+bool Network_Port_Changes_Pending(uint32_t object_instance)
+{
+ bool flag = false;
+ unsigned index = 0;
+
+ index = Network_Port_Instance_To_Index(object_instance);
+ if (index < BACNET_NETWORK_PORTS_MAX) {
+ flag = Object_List[index].Changes_Pending;
+ }
+
+ return flag;
+}
+
+/**
+ * @brief For a given object instance-number, sets the changes-pending flag
+ * @param object_instance - object-instance number of the object
+ * @param flag - true=changes pending, false=no changes pending
+ * @return true if flag was set
+ */
+bool Network_Port_Changes_Pending_Set(uint32_t instance, bool flag)
+{
+ unsigned index = 0;
+
+ index = Network_Port_Instance_To_Index(instance);
+ if (index < BACNET_NETWORK_PORTS_MAX) {
+ Object_List[index].Changes_Pending = flag;
+ } else
+ return false;
+
+ return true;
+}
+
+/**
+ * @brief For a given object instance-number, gets the MS/TP Max_Master value
+ * @param object_instance - object-instance number of the object
+ * @return MS/TP Max_Master value
+ */
+uint8_t Network_Port_MSTP_Max_Master(uint32_t object_instance)
+{
+ (void)object_instance;
+ Object_List[0].Max_Master = dlmstp_max_master();
+
+ return Object_List[0].Max_Master;
+}
+
+/**
+ * For a given object instance-number, sets the MS/TP Max_Master value
+ *
+ * @param object_instance - object-instance number of the object
+ * @param value - MS/TP Max_Master value 0..127
+ *
+ * @return true if values are within range and property is set.
+ */
+bool Network_Port_MSTP_Max_Master_Set(uint32_t object_instance, uint8_t value)
+{
+ bool status = false;
+
+ (void)object_instance;
+ if (value <= dlmstp_max_master_limit()) {
+ Object_List[0].Max_Master = value;
+ Object_List[0].Changes_Pending = true;
+ status = true;
+ }
+
+ return status;
+}
+
+/**
+ * For a given object instance-number, gets the MS/TP Max_Info_Frames value
+ *
+ * @param object_instance - object-instance number of the object
+ *
+ * @return MS/TP Max_Info_Frames value
+ */
+uint8_t Network_Port_MSTP_Max_Info_Frames(uint32_t object_instance)
+{
+ (void)object_instance;
+ Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
+
+ return Object_List[0].Max_Info_Frames;
+}
+
+/**
+ * For a given object instance-number, sets the MS/TP Max_Info_Frames value
+ *
+ * @param object_instance - object-instance number of the object
+ * @param value - MS/TP Max_Info_Frames value 0..255
+ *
+ * @return true if values are within range and property is set.
+ */
+bool Network_Port_MSTP_Max_Info_Frames_Set(
+ uint32_t object_instance, uint8_t value)
+{
+ bool status = false;
+
+ (void)object_instance;
+ if (value <= dlmstp_max_info_frames_limit()) {
+ Object_List[0].Max_Info_Frames = value;
+ Object_List[0].Changes_Pending = true;
+ status = true;
+ }
+
+ return status;
+}
+
+/**
+ * ReadProperty handler for this object. For the given ReadProperty
+ * data, the application_data is loaded or the error flags are set.
+ *
+ * @param rpdata - BACNET_READ_PROPERTY_DATA data, including
+ * requested data and space for the reply, or error response.
+ *
+ * @return number of APDU bytes in the response, or
+ * BACNET_STATUS_ERROR on error.
+ */
+int Network_Port_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
+{
+ int apdu_len = 0;
+ BACNET_BIT_STRING bit_string;
+ BACNET_OCTET_STRING octet_string;
+ BACNET_CHARACTER_STRING char_string;
+ uint8_t *apdu = NULL;
+
+ if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
+ (rpdata->application_data_len == 0)) {
+ return 0;
+ }
+ apdu = rpdata->application_data;
+ switch (rpdata->object_property) {
+ case PROP_OBJECT_IDENTIFIER:
+ apdu_len = encode_application_object_id(
+ &apdu[0], OBJECT_NETWORK_PORT, rpdata->object_instance);
+ break;
+ case PROP_OBJECT_NAME:
+ Network_Port_Object_Name(rpdata->object_instance, &char_string);
+ apdu_len =
+ encode_application_character_string(&apdu[0], &char_string);
+ break;
+ case PROP_OBJECT_TYPE:
+ apdu_len =
+ encode_application_enumerated(&apdu[0], OBJECT_NETWORK_PORT);
+ break;
+ case PROP_STATUS_FLAGS:
+ bitstring_init(&bit_string);
+ bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
+ if (Network_Port_Reliability(rpdata->object_instance) ==
+ RELIABILITY_NO_FAULT_DETECTED) {
+ bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
+ } else {
+ bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, true);
+ }
+ bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
+ if (Network_Port_Out_Of_Service(rpdata->object_instance)) {
+ bitstring_set_bit(
+ &bit_string, STATUS_FLAG_OUT_OF_SERVICE, true);
+ } else {
+ bitstring_set_bit(
+ &bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
+ }
+ apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
+ break;
+ case PROP_RELIABILITY:
+ apdu_len = encode_application_enumerated(
+ &apdu[0], Network_Port_Reliability(rpdata->object_instance));
+ break;
+ case PROP_OUT_OF_SERVICE:
+ apdu_len = encode_application_boolean(
+ &apdu[0], Network_Port_Out_Of_Service(rpdata->object_instance));
+ break;
+ case PROP_NETWORK_TYPE:
+ apdu_len = encode_application_enumerated(
+ &apdu[0], Network_Port_Type(rpdata->object_instance));
+ break;
+ case PROP_PROTOCOL_LEVEL:
+ apdu_len = encode_application_enumerated(
+ &apdu[0], BACNET_PROTOCOL_LEVEL_PHYSICAL);
+ break;
+ case PROP_NETWORK_NUMBER:
+ apdu_len = encode_application_unsigned(
+ &apdu[0], Network_Port_Network_Number(rpdata->object_instance));
+ break;
+ case PROP_NETWORK_NUMBER_QUALITY:
+ apdu_len = encode_application_enumerated(
+ &apdu[0], Network_Port_Quality(rpdata->object_instance));
+ break;
+ case PROP_MAC_ADDRESS:
+ Network_Port_MAC_Address(rpdata->object_instance, &octet_string);
+ apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
+ break;
+ case PROP_MAX_APDU_LENGTH_ACCEPTED:
+ apdu_len = encode_application_unsigned(
+ &apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
+ break;
+ case PROP_LINK_SPEED:
+ apdu_len = encode_application_real(
+ &apdu[0], Network_Port_Link_Speed(rpdata->object_instance));
+ break;
+ case PROP_CHANGES_PENDING:
+ apdu_len = encode_application_boolean(&apdu[0],
+ Network_Port_Changes_Pending(rpdata->object_instance));
+ break;
+ case PROP_APDU_LENGTH:
+ apdu_len = encode_application_unsigned(
+ &apdu[0], Network_Port_APDU_Length(rpdata->object_instance));
+ break;
+ case PROP_MAX_MASTER:
+ apdu_len = encode_application_unsigned(&apdu[0],
+ Network_Port_MSTP_Max_Master(rpdata->object_instance));
+ break;
+ case PROP_MAX_INFO_FRAMES:
+ apdu_len = encode_application_unsigned(&apdu[0],
+ Network_Port_MSTP_Max_Info_Frames(rpdata->object_instance));
+ break;
+ default:
+ rpdata->error_class = ERROR_CLASS_PROPERTY;
+ rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
+ apdu_len = BACNET_STATUS_ERROR;
+ break;
+ }
+
+ return apdu_len;
+}
+
+/**
+ * WriteProperty handler for this object. For the given WriteProperty
+ * data, the application_data is loaded or the error flags are set.
+ *
+ * @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including
+ * requested data and space for the reply, or error response.
+ *
+ * @return false if an error is loaded, true if no errors
+ */
+bool Network_Port_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
+{
+ bool status = false; /* return value */
+ int len = 0;
+ BACNET_APPLICATION_DATA_VALUE value;
+
+ if (!Network_Port_Valid_Instance(wp_data->object_instance)) {
+ wp_data->error_class = ERROR_CLASS_OBJECT;
+ wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
+ return false;
+ }
+ /* decode the some of the request */
+ len = bacapp_decode_application_data(
+ wp_data->application_data, wp_data->application_data_len, &value);
+ if (len < 0) {
+ /* error while decoding - a value larger than we can handle */
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ return false;
+ }
+ if ((wp_data->object_property != PROP_LINK_SPEEDS) &&
+ (wp_data->object_property != PROP_IP_DNS_SERVER) &&
+ (wp_data->object_property != PROP_IPV6_DNS_SERVER) &&
+ (wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS) &&
+ (wp_data->object_property != PROP_EVENT_MESSAGE_TEXTS_CONFIG) &&
+ (wp_data->object_property != PROP_TAGS) &&
+ (wp_data->array_index != BACNET_ARRAY_ALL)) {
+ /* only array properties can have array options */
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
+ return false;
+ }
+ /* FIXME: len < application_data_len: more data? */
+ switch (wp_data->object_property) {
+ case PROP_MAX_MASTER:
+ if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
+ if (value.type.Unsigned_Int <= 255) {
+ status = Network_Port_MSTP_Max_Master_Set(
+ wp_data->object_instance, value.type.Unsigned_Int);
+ if (!status) {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ } else {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ } else {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ case PROP_MAX_INFO_FRAMES:
+ if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
+ if (value.type.Unsigned_Int <= 255) {
+ status = Network_Port_MSTP_Max_Info_Frames_Set(
+ wp_data->object_instance, value.type.Unsigned_Int);
+ if (!status) {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ status = true;
+ } else {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ } else {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ case PROP_LINK_SPEED:
+ if (value.tag == BACNET_APPLICATION_TAG_REAL) {
+ if (!Network_Port_Link_Speed_Set(
+ wp_data->object_instance, value.type.Real)) {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ status = true;
+ } else {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ case PROP_MAC_ADDRESS:
+ if (value.tag == BACNET_APPLICATION_TAG_OCTET_STRING) {
+ if (!Network_Port_MAC_Address_Set(wp_data->object_instance,
+ value.type.Octet_String.value,
+ value.type.Octet_String.length)) {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
+ }
+ status = true;
+ } else {
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
+ }
+ break;
+ case PROP_OBJECT_IDENTIFIER:
+ case PROP_OBJECT_NAME:
+ case PROP_OBJECT_TYPE:
+ case PROP_STATUS_FLAGS:
+ case PROP_RELIABILITY:
+ case PROP_OUT_OF_SERVICE:
+ case PROP_NETWORK_TYPE:
+ case PROP_PROTOCOL_LEVEL:
+ case PROP_NETWORK_NUMBER:
+ case PROP_NETWORK_NUMBER_QUALITY:
+ case PROP_MAX_APDU_LENGTH_ACCEPTED:
+ case PROP_CHANGES_PENDING:
+ case PROP_APDU_LENGTH:
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
+ break;
+ default:
+ wp_data->error_class = ERROR_CLASS_PROPERTY;
+ wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * Initializes the Network Port object data
+ */
+void Network_Port_Init(void)
+{
+ Object_List[0].Changes_Pending = false;
+ Object_List[0].MAC_Address[0] = dlmstp_mac_address();
+ Object_List[0].Max_Master = dlmstp_max_master();
+ Object_List[0].Max_Info_Frames = dlmstp_max_info_frames();
+ Object_List[0].Link_Speed = rs485_baud_rate();
+}
diff --git a/ports/at91sam7s/rs485.c b/ports/at91sam7s/rs485.c
index b7d35063..9f37b621 100644
--- a/ports/at91sam7s/rs485.c
+++ b/ports/at91sam7s/rs485.c
@@ -118,7 +118,7 @@ void RS485_Cleanup(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
-uint32_t RS485_Get_Baud_Rate(void)
+uint32_t rs485_baud_rate(void)
{
return RS485_Baud;
}
@@ -129,7 +129,7 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
-bool RS485_Set_Baud_Rate(uint32_t baud)
+bool rs485_baud_rate_set(uint32_t baud)
{
bool valid = true;
@@ -266,7 +266,7 @@ int main(void)
unsigned i = 0;
uint8_t DataRegister;
- RS485_Set_Baud_Rate(38400);
+ rs485_baud_rate_set(38400);
RS485_Initialize();
/* receive task */
for (;;) {
diff --git a/ports/at91sam7s/rs485.h b/ports/at91sam7s/rs485.h
index ae622daa..a69b4e28 100644
--- a/ports/at91sam7s/rs485.h
+++ b/ports/at91sam7s/rs485.h
@@ -49,9 +49,9 @@ extern "C" {
void RS485_Turnaround_Delay(
void);
- uint32_t RS485_Get_Baud_Rate(
+ uint32_t rs485_baud_rate(
void);
- bool RS485_Set_Baud_Rate(
+ bool rs485_baud_rate_set(
uint32_t baud);
#ifdef __cplusplus
diff --git a/ports/bdk-atxx4-mstp/Makefile b/ports/bdk-atxx4-mstp/Makefile
index debf1628..33e1f505 100644
--- a/ports/bdk-atxx4-mstp/Makefile
+++ b/ports/bdk-atxx4-mstp/Makefile
@@ -91,6 +91,7 @@ HALSRC = main.c \
bacnet.c \
bname.c \
device.c \
+ netport.c \
ai.c \
av.c \
bi.c \
@@ -218,6 +219,7 @@ BFLAGS += -DBACAPP_OBJECT_ID
BFLAGS += -DBACAPP_UNSIGNED
BFLAGS += -DBACAPP_ENUMERATED
BFLAGS += -DBACAPP_CHARACTER_STRING
+BFLAGS += -DBACAPP_OCTET_STRING
BFLAGS += -DWRITE_PROPERTY
## Compile options for C files
diff --git a/ports/bdk-atxx4-mstp/bacnet.ewp b/ports/bdk-atxx4-mstp/bacnet.ewp
index 718ac496..19c85171 100644
--- a/ports/bdk-atxx4-mstp/bacnet.ewp
+++ b/ports/bdk-atxx4-mstp/bacnet.ewp
@@ -266,6 +266,7 @@
BACAPP_UNSIGNED
BACAPP_ENUMERATED
BACAPP_CHARACTER_STRING
+ BACAPP_OCTET_STRING
WRITE_PROPERTY