From f70e80f146ff0722912288c7a32c0ded3e3a8e04 Mon Sep 17 00:00:00 2001 From: skarg Date: Tue, 16 Oct 2007 01:22:12 +0000 Subject: [PATCH] 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. --- bacnet-stack/ports/atmega168/Makefile | 2 +- bacnet-stack/ports/atmega168/ai.c | 19 +++------ bacnet-stack/ports/atmega168/bacnet.aps | 2 +- bacnet-stack/ports/atmega168/device.c | 56 +++---------------------- bacnet-stack/ports/atmega168/dlmstp.c | 20 +++++---- bacnet-stack/ports/atmega168/h_whois.c | 12 +++--- bacnet-stack/ports/atmega168/main.c | 8 ++-- 7 files changed, 36 insertions(+), 83 deletions(-) diff --git a/bacnet-stack/ports/atmega168/Makefile b/bacnet-stack/ports/atmega168/Makefile index f25fa713..44f2bbb8 100644 --- a/bacnet-stack/ports/atmega168/Makefile +++ b/bacnet-stack/ports/atmega168/Makefile @@ -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 diff --git a/bacnet-stack/ports/atmega168/ai.c b/bacnet-stack/ports/atmega168/ai.c index 5600ddaa..3acb2ebd 100644 --- a/bacnet-stack/ports/atmega168/ai.c +++ b/bacnet-stack/ports/atmega168/ai.c @@ -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); diff --git a/bacnet-stack/ports/atmega168/bacnet.aps b/bacnet-stack/ports/atmega168/bacnet.aps index 1abd57cf..b2544391 100644 --- a/bacnet-stack/ports/atmega168/bacnet.aps +++ b/bacnet-stack/ports/atmega168/bacnet.aps @@ -1 +1 @@ -13-Aug-2007 15:08:2728-Sep-2007 16:15:28013-Aug-2007 15:08:2744, 13, 0, 528AVR GCC241bacnet13-Aug-2007 15:11:0713-Aug-2007 15:11:07241013-Aug-2007 15:11:0744, 13, 0, 528AVR GCCbacnet.elfC:\code\bacnet-stack\ports\atmega168\ATmega168falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31AVR DragonAVR SimulatorATmega168.xmlAuto000main.crs485.ctimer.cdlmstp.cC:\code\bacnet-stack\crc.cC:\code\bacnet-stack\demo\handler\txbuf.cC:\code\bacnet-stack\iam.cC:\code\bacnet-stack\npdu.cdevice.cavr035.hhardware.hrs485.htimer.hC:\code\bacnet-stack\crc.hC:\code\bacnet-stack\dlmstp.hC:\code\bacnet-stack\demo\handler\txbuf.hC:\code\bacnet-stack\iam.hC:\code\bacnet-stack\npdu.hMakefiledefaultYESMakefileatmega168100bacnet.elfdefault\1..\..\demo\handler\.\..\..\..\..\demo\object\-Wall -gdwarf-2 -DMAX_APDU=50 -DBACDL_MSTP -DBIG_ENDIAN=0 -DF_CPU=7372800UL -O0 -fsigned-chardefault1C:\WinAVR-20070525\bin\avr-gcc.exeC:\WinAVR-20070525\utils\bin\make.exe0282161937372800011000001920010000000001011main100000C:\WinAVR-20070525\avr\include\avr\eeprom.h100001C:\WinAVR-20070525\avr\include\avr\iomx8.h100002C:\WinAVR-20070525\examples\stdiodemo\uart.c100003main.c25900004C:\WinAVR-20070525\avr\include\avr\interrupt.h100005C:\WinAVR-20070525\avr\include\avr\io.h100006C:\code\bacnet-stack\mstp.c200007rs485.c25900008dlmstp.c25800009avr035.h100010C:\code\bacnet-stack\crc.c25800011timer.c258840 433 1000 4570 0527 608 687 6320 0362 582 522 6060 0291 141 1093 565158 0746 382 906 4090 0360 611 520 6350 0354 196 1030 578140 14269 717 429 7410 0 +13-Aug-2007 15:08:2715-Oct-2007 19:39:56013-Aug-2007 15:08:2744, 13, 0, 528AVR GCC241bacnet13-Aug-2007 15:11:0713-Aug-2007 15:11:07241013-Aug-2007 15:11:0744, 13, 0, 528AVR GCCbacnet.elfC:\code\bacnet-stack\ports\atmega168\ATmega168falseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31AVR DragonAVR SimulatorATmega168.xmlAuto000main.crs485.ctimer.cdlmstp.cC:\code\bacnet-stack\demo\handler\txbuf.cdevice.cC:\code\bacnet-stack\src\crc.cC:\code\bacnet-stack\src\iam\iam_server.cC:\code\bacnet-stack\src\npdu.cai.capdu.ch_rp.cavr035.hhardware.hrs485.htimer.hC:\code\bacnet-stack\include\crc.hC:\code\bacnet-stack\include\dlmstp.hC:\code\bacnet-stack\include\iam.hC:\code\bacnet-stack\include\npdu.hC:\code\bacnet-stack\include\txbuf.hMakefiledefaultYESMakefileatmega168100bacnet.elfdefault\1..\..\demo\handler\.\..\..\..\..\demo\object\-Wall -gdwarf-2 -DMAX_APDU=50 -DBACDL_MSTP -DBIG_ENDIAN=0 -DF_CPU=7372800UL -O0 -fsigned-chardefault1C:\WinAVR-20070525\bin\avr-gcc.exeC:\WinAVR-20070525\utils\bin\make.exe0282161937372800011000001920010000000001011main100000C:\WinAVR-20070525\avr\include\avr\eeprom.h100001C:\WinAVR-20070525\avr\include\avr\iomx8.h100002C:\WinAVR-20070525\examples\stdiodemo\uart.c100003main.c25900004C:\WinAVR-20070525\avr\include\avr\interrupt.h100005C:\WinAVR-20070525\avr\include\avr\io.h100006rs485.c25900007dlmstp.c25900008timer.c25900009device.c25700010ai.c25700011C:\code\bacnet-stack\src\npdu.c25700012apdu.c25700013h_rp.c259269 845 429 8690 0524 608 684 6350 0359 582 519 6090 0288 141 1090 565148 0743 382 903 4090 0357 611 517 6380 0401 229 1451 7590 0511 339 1509 8691129 32335 163 1333 6930 0467 295 1465 8250 0489 317 1539 8470 0269 97 1267 6270 0291 119 1289 6490 0313 141 1311 6710 0 diff --git a/bacnet-stack/ports/atmega168/device.c b/bacnet-stack/ports/atmega168/device.c index 347faa37..608977cb 100644 --- a/bacnet-stack/ports/atmega168/device.c +++ b/bacnet-stack/ports/atmega168/device.c @@ -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 \ No newline at end of file +#endif diff --git a/bacnet-stack/ports/atmega168/dlmstp.c b/bacnet-stack/ports/atmega168/dlmstp.c index 0b5b4a64..ae017bd1 100644 --- a/bacnet-stack/ports/atmega168/dlmstp.c +++ b/bacnet-stack/ports/atmega168/dlmstp.c @@ -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); } diff --git a/bacnet-stack/ports/atmega168/h_whois.c b/bacnet-stack/ports/atmega168/h_whois.c index 4c6d033d..ad21077c 100644 --- a/bacnet-stack/ports/atmega168/h_whois.c +++ b/bacnet-stack/ports/atmega168/h_whois.c @@ -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) && diff --git a/bacnet-stack/ports/atmega168/main.c b/bacnet-stack/ports/atmega168/main.c index ec77227f..f92957e7 100644 --- a/bacnet-stack/ports/atmega168/main.c +++ b/bacnet-stack/ports/atmega168/main.c @@ -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(); } }