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:
skarg
2007-10-16 01:22:12 +00:00
parent cbefb47a05
commit f70e80f146
7 changed files with 36 additions and 83 deletions
+1 -1
View File
@@ -91,7 +91,7 @@ OPTIMIZATION = -Os -mcall-prologues
## Compile options common for all C compilation units. ## Compile options common for all C compilation units.
BFLAGS = -DBACDL_MSTP BFLAGS = -DBACDL_MSTP
BFLAGS += -DMAX_APDU=50 BFLAGS += -DMAX_APDU=128
BFLAGS += -DBIG_ENDIAN=0 BFLAGS += -DBIG_ENDIAN=0
BFLAGS += -DMAX_TSM_TRANSACTIONS=0 BFLAGS += -DMAX_TSM_TRANSACTIONS=0
#BFLAGS += -DCRC_USE_TABLE #BFLAGS += -DCRC_USE_TABLE
+5 -14
View File
@@ -34,12 +34,12 @@
#include "config.h" #include "config.h"
/* Analog Input = Photocell */ /* Analog Input = Photocell */
#define MAX_ANALOG_INPUTS 2 #define MAX_ANALOG_INPUTS 9
#if (MAX_ANALOG_INPUTS > 9) #if (MAX_ANALOG_INPUTS > 9)
#error Modify the Analog_Input_Name to handle multiple digits #error Modify the Analog_Input_Name to handle multiple digits
#endif #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 */ /* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */ /* more complex, and then you need validate that the */
@@ -76,16 +76,6 @@ char *Analog_Input_Name(uint32_t object_instance)
return NULL; 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 */ /* return apdu length, or -1 on error */
/* assumption - object has already exists */ /* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(uint8_t * apdu, int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
@@ -105,7 +95,8 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
object_instance); object_instance);
break; break;
/* note: Name and Description don't have to be the same. /* 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_OBJECT_NAME:
case PROP_DESCRIPTION: case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, characterstring_init_ansi(&char_string,
@@ -118,7 +109,7 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
break; break;
case PROP_PRESENT_VALUE: case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0], apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance)); Present_Value[object_instance]);
break; break;
case PROP_STATUS_FLAGS: case PROP_STATUS_FLAGS:
bitstring_init(&bit_string); bitstring_init(&bit_string);
File diff suppressed because one or more lines are too long
+6 -50
View File
@@ -49,8 +49,8 @@
properties that are writable or that may change. properties that are writable or that may change.
The properties that are constant can be hard coded The properties that are constant can be hard coded
into the read-property encoding. */ into the read-property encoding. */
static uint32_t Object_Instance_Number = 12345; static uint32_t Object_Instance_Number = 260001;
static char Object_Name[32] = "ATmega Device"; static char Object_Name[32] = "ATmega168 Device";
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL; static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
void Device_Init(void) void Device_Init(void)
@@ -203,8 +203,6 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
int object_type = 0; int object_type = 0;
uint32_t instance = 0; uint32_t instance = 0;
unsigned count = 0; unsigned count = 0;
BACNET_TIME local_time;
BACNET_DATE local_date;
/* FIXME: change the hardcoded names to suit your application */ /* FIXME: change the hardcoded names to suit your application */
switch (property) { switch (property) {
@@ -213,16 +211,13 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
Object_Instance_Number); Object_Instance_Number);
break; break;
case PROP_OBJECT_NAME: case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, Object_Name); characterstring_init_ansi(&char_string, Object_Name);
apdu_len = encode_application_character_string(&apdu[0], &char_string); apdu_len = encode_application_character_string(&apdu[0], &char_string);
break; break;
case PROP_OBJECT_TYPE: case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE); apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break; 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: case PROP_SYSTEM_STATUS:
apdu_len = apdu_len =
encode_application_enumerated(&apdu[0], System_Status); 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"); characterstring_init_ansi(&char_string, "1.0");
apdu_len = encode_application_character_string(&apdu[0], &char_string); apdu_len = encode_application_character_string(&apdu[0], &char_string);
break; 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: case PROP_PROTOCOL_VERSION:
apdu_len = apdu_len = encode_application_unsigned(&apdu[0], 1);
encode_application_unsigned(&apdu[0], 1);
break; break;
case PROP_PROTOCOL_REVISION: case PROP_PROTOCOL_REVISION:
apdu_len = apdu_len = encode_application_unsigned(&apdu[0], 5);
encode_application_unsigned(&apdu[0], 5);
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break; break;
case PROP_PROTOCOL_SERVICES_SUPPORTED: case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */ /* 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, /* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */ not a list of objects that this device can access */
bitstring_init(&bit_string); 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 */ /* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true); bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, 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: case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master()); apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master());
break; 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: case 9600:
apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate()); apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break; break;
@@ -519,4 +475,4 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
return status; return status;
} }
#endif #endif
+12 -8
View File
@@ -402,7 +402,8 @@ static void MSTP_Send_Frame(
{ /* number of bytes of data (up to 501) */ { /* number of bytes of data (up to 501) */
uint8_t crc8 = 0xFF; /* used to calculate the crc value */ uint8_t crc8 = 0xFF; /* used to calculate the crc value */
uint16_t crc16 = 0xFFFF; /* 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 */ uint16_t i = 0; /* used to calculate CRC for data */
/* create the MS/TP header */ /* create the MS/TP header */
@@ -419,10 +420,6 @@ static void MSTP_Send_Frame(
buffer[6] = data_len % 256; buffer[6] = data_len % 256;
crc8 = CRC_Calc_Header(buffer[6], crc8); crc8 = CRC_Calc_Header(buffer[6], crc8);
buffer[7] = ~crc8; buffer[7] = ~crc8;
RS485_Turnaround_Delay();
RS485_Transmitter_Enable(true);
RS485_Send_Data(buffer,8);
/* send any data */
if (data_len) { if (data_len) {
/* calculate CRC for any data */ /* calculate CRC for any data */
for (i = 0; i < data_len; i++) for (i = 0; i < data_len; i++)
@@ -430,10 +427,17 @@ static void MSTP_Send_Frame(
crc16 = CRC_Calc_Data(data[i], crc16); crc16 = CRC_Calc_Data(data[i], crc16);
} }
crc16 = ~crc16; crc16 = ~crc16;
buffer[0] = (crc16 & 0x00FF); datacrc[0] = (crc16 & 0x00FF);
buffer[1] = ((crc16 & 0xFF00) >> 8); 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(data, data_len);
RS485_Send_Data(buffer, 2); RS485_Send_Data(datacrc, 2);
} }
RS485_Transmitter_Enable(false); RS485_Transmitter_Enable(false);
} }
+7 -5
View File
@@ -45,16 +45,18 @@ void handler_who_is(uint8_t * service_request,
int len = 0; int len = 0;
int32_t low_limit = 0; int32_t low_limit = 0;
int32_t high_limit = 0; int32_t high_limit = 0;
int32_t target_device;
(void) src; (void) src;
len = whois_decode_service_request(service_request, len = whois_decode_service_request(service_request,
service_len, &low_limit, &high_limit); service_len, &low_limit, &high_limit);
if (len == 0) if (len == 0) {
iam_send(&Handler_Transmit_Buffer[0]); Send_I_Am = true;
else if (len != -1) { } else if (len != -1) {
/* is my device id within the limits? */ /* is my device id within the limits? */
if (((Device_Object_Instance_Number() >= (uint32_t) low_limit) && target_device = Device_Object_Instance_Number();
(Device_Object_Instance_Number() <= (uint32_t) high_limit)) if (((target_device >= low_limit) &&
(target_device <= high_limit))
|| ||
/* BACnet wildcard is the max instance number - everyone responds */ /* BACnet wildcard is the max instance number - everyone responds */
((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) && ((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) &&
+4 -4
View File
@@ -152,23 +152,23 @@ int main(void)
init(); init();
#if defined(BACDL_MSTP) #if defined(BACDL_MSTP)
//RS485_Set_Baud_Rate(38400); RS485_Set_Baud_Rate(38400);
dlmstp_set_max_master(127); dlmstp_set_max_master(127);
dlmstp_set_max_info_frames(1); dlmstp_set_max_info_frames(1);
#endif #endif
datalink_init(NULL); datalink_init(NULL);
for (;;) { for (;;) {
if (Send_I_Am) if (Send_I_Am) {
Send_I_Am = false;
iam_send(&Handler_Transmit_Buffer[0]); iam_send(&Handler_Transmit_Buffer[0]);
}
input_switch_read(); input_switch_read();
task_milliseconds(); task_milliseconds();
/* other tasks */ /* other tasks */
/* BACnet handling */ /* BACnet handling */
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0); pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) { if (pdu_len) {
#if !defined(TEST_MSTP)
npdu_handler(&src, &PDUBuffer[0], pdu_len); npdu_handler(&src, &PDUBuffer[0], pdu_len);
#endif
NPDU_LED_On(); NPDU_LED_On();
} }
} }