Tuned the ATmega168 port demo project that runs a Device Object and 9 Analog Inputs, and uses ReadProperty service. Uses 16158 bytes of flash, 624 bytes of RAM with an APDU of 128.
This commit is contained in:
@@ -91,7 +91,7 @@ OPTIMIZATION = -Os -mcall-prologues
|
||||
|
||||
## Compile options common for all C compilation units.
|
||||
BFLAGS = -DBACDL_MSTP
|
||||
BFLAGS += -DMAX_APDU=50
|
||||
BFLAGS += -DMAX_APDU=128
|
||||
BFLAGS += -DBIG_ENDIAN=0
|
||||
BFLAGS += -DMAX_TSM_TRANSACTIONS=0
|
||||
#BFLAGS += -DCRC_USE_TABLE
|
||||
|
||||
@@ -34,12 +34,12 @@
|
||||
#include "config.h"
|
||||
|
||||
/* Analog Input = Photocell */
|
||||
#define MAX_ANALOG_INPUTS 2
|
||||
#define MAX_ANALOG_INPUTS 9
|
||||
#if (MAX_ANALOG_INPUTS > 9)
|
||||
#error Modify the Analog_Input_Name to handle multiple digits
|
||||
#endif
|
||||
|
||||
static uint8_t Present_Value[MAX_ANALOG_INPUTS];
|
||||
static float Present_Value[MAX_ANALOG_INPUTS];
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
@@ -76,16 +76,6 @@ char *Analog_Input_Name(uint32_t object_instance)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static float Analog_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = 0.0;
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
value = Present_Value[object_instance];
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object has already exists */
|
||||
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
|
||||
@@ -105,7 +95,8 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
|
||||
object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
You could make Description writable and different */
|
||||
You could make Description writable and different.
|
||||
Note that Object-Name must be unique in this device */
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
@@ -118,7 +109,7 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
apdu_len = encode_application_real(&apdu[0],
|
||||
Analog_Input_Present_Value(object_instance));
|
||||
Present_Value[object_instance]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -49,8 +49,8 @@
|
||||
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 = 12345;
|
||||
static char Object_Name[32] = "ATmega Device";
|
||||
static uint32_t Object_Instance_Number = 260001;
|
||||
static char Object_Name[32] = "ATmega168 Device";
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
|
||||
void Device_Init(void)
|
||||
@@ -203,8 +203,6 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
unsigned count = 0;
|
||||
BACNET_TIME local_time;
|
||||
BACNET_DATE local_date;
|
||||
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
@@ -213,16 +211,13 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string, Object_Name);
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string, "BACnet Demo");
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], System_Status);
|
||||
@@ -247,21 +242,11 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
characterstring_init_ansi(&char_string, "1.0");
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_LOCATION:
|
||||
characterstring_init_ansi(&char_string, "USA");
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], 1);
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], 5);
|
||||
break;
|
||||
/* BACnet Legacy Support */
|
||||
case PROP_PROTOCOL_CONFORMANCE_CLASS:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 1);
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 5);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
@@ -277,11 +262,6 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
/* 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++) {
|
||||
/* FIXME: if ReadProperty used an array of Functions... */
|
||||
/* 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);
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
|
||||
@@ -367,30 +347,6 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||
break;
|
||||
case PROP_LOCAL_TIME:
|
||||
/* FIXME: if you support time */
|
||||
local_time.hour = 0;
|
||||
local_time.min = 0;
|
||||
local_time.sec = 0;
|
||||
local_time.hundredths = 0;
|
||||
apdu_len = encode_application_time(&apdu[0], &local_time);
|
||||
break;
|
||||
case PROP_UTC_OFFSET:
|
||||
/* Note: BACnet Time Zone is inverse of everybody else */
|
||||
apdu_len = encode_application_signed(&apdu[0], 5 /* EST */ );
|
||||
break;
|
||||
case PROP_LOCAL_DATE:
|
||||
/* FIXME: if you support date */
|
||||
local_date.year = 2006; /* AD */
|
||||
local_date.month = 4; /* Jan=1..Dec=12 */
|
||||
local_date.day = 11; /* 1..31 */
|
||||
local_date.wday = 0; /* 1=Mon..7=Sun */
|
||||
apdu_len = encode_application_date(&apdu[0], &local_date);
|
||||
break;
|
||||
case PROP_DAYLIGHT_SAVINGS_STATUS:
|
||||
/* FIXME: if you support time/date */
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case 9600:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
|
||||
break;
|
||||
@@ -519,4 +475,4 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -402,7 +402,8 @@ static void MSTP_Send_Frame(
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
uint8_t buffer[8]; /* stores the header and data crc */
|
||||
uint8_t buffer[8]; /* stores the header and crc */
|
||||
uint8_t datacrc[2]; /* stores the data crc */
|
||||
uint16_t i = 0; /* used to calculate CRC for data */
|
||||
|
||||
/* create the MS/TP header */
|
||||
@@ -419,10 +420,6 @@ static void MSTP_Send_Frame(
|
||||
buffer[6] = data_len % 256;
|
||||
crc8 = CRC_Calc_Header(buffer[6], crc8);
|
||||
buffer[7] = ~crc8;
|
||||
RS485_Turnaround_Delay();
|
||||
RS485_Transmitter_Enable(true);
|
||||
RS485_Send_Data(buffer,8);
|
||||
/* send any data */
|
||||
if (data_len) {
|
||||
/* calculate CRC for any data */
|
||||
for (i = 0; i < data_len; i++)
|
||||
@@ -430,10 +427,17 @@ static void MSTP_Send_Frame(
|
||||
crc16 = CRC_Calc_Data(data[i], crc16);
|
||||
}
|
||||
crc16 = ~crc16;
|
||||
buffer[0] = (crc16 & 0x00FF);
|
||||
buffer[1] = ((crc16 & 0xFF00) >> 8);
|
||||
datacrc[0] = (crc16 & 0x00FF);
|
||||
datacrc[1] = ((crc16 & 0xFF00) >> 8);
|
||||
}
|
||||
/* now transmit the frame */
|
||||
RS485_Turnaround_Delay();
|
||||
RS485_Transmitter_Enable(true);
|
||||
RS485_Send_Data(buffer,8);
|
||||
/* send any data */
|
||||
if (data_len) {
|
||||
RS485_Send_Data(data, data_len);
|
||||
RS485_Send_Data(buffer, 2);
|
||||
RS485_Send_Data(datacrc, 2);
|
||||
}
|
||||
RS485_Transmitter_Enable(false);
|
||||
}
|
||||
|
||||
@@ -45,16 +45,18 @@ void handler_who_is(uint8_t * service_request,
|
||||
int len = 0;
|
||||
int32_t low_limit = 0;
|
||||
int32_t high_limit = 0;
|
||||
int32_t target_device;
|
||||
|
||||
(void) src;
|
||||
len = whois_decode_service_request(service_request,
|
||||
service_len, &low_limit, &high_limit);
|
||||
if (len == 0)
|
||||
iam_send(&Handler_Transmit_Buffer[0]);
|
||||
else if (len != -1) {
|
||||
if (len == 0) {
|
||||
Send_I_Am = true;
|
||||
} else if (len != -1) {
|
||||
/* is my device id within the limits? */
|
||||
if (((Device_Object_Instance_Number() >= (uint32_t) low_limit) &&
|
||||
(Device_Object_Instance_Number() <= (uint32_t) high_limit))
|
||||
target_device = Device_Object_Instance_Number();
|
||||
if (((target_device >= low_limit) &&
|
||||
(target_device <= high_limit))
|
||||
||
|
||||
/* BACnet wildcard is the max instance number - everyone responds */
|
||||
((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) &&
|
||||
|
||||
@@ -152,23 +152,23 @@ int main(void)
|
||||
|
||||
init();
|
||||
#if defined(BACDL_MSTP)
|
||||
//RS485_Set_Baud_Rate(38400);
|
||||
RS485_Set_Baud_Rate(38400);
|
||||
dlmstp_set_max_master(127);
|
||||
dlmstp_set_max_info_frames(1);
|
||||
#endif
|
||||
datalink_init(NULL);
|
||||
for (;;) {
|
||||
if (Send_I_Am)
|
||||
if (Send_I_Am) {
|
||||
Send_I_Am = false;
|
||||
iam_send(&Handler_Transmit_Buffer[0]);
|
||||
}
|
||||
input_switch_read();
|
||||
task_milliseconds();
|
||||
/* other tasks */
|
||||
/* BACnet handling */
|
||||
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
|
||||
if (pdu_len) {
|
||||
#if !defined(TEST_MSTP)
|
||||
npdu_handler(&src, &PDUBuffer[0], pdu_len);
|
||||
#endif
|
||||
NPDU_LED_On();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user