Indented.
This commit is contained in:
@@ -36,7 +36,7 @@
|
||||
/* Analog Input = Photocell */
|
||||
#define 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
|
||||
|
||||
float Present_Value[MAX_ANALOG_INPUTS];
|
||||
@@ -44,7 +44,8 @@ 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 */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(uint32_t object_instance)
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
@@ -53,30 +54,34 @@ bool Analog_Input_Valid_Instance(uint32_t object_instance)
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(void)
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Instance_To_Index(uint32_t object_instance)
|
||||
unsigned Analog_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
|
||||
char *Analog_Input_Name(uint32_t object_instance)
|
||||
char *Analog_Input_Name(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AI-0"; /* okay for single thread */
|
||||
static char text_string[5] = "AI-0"; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
return text_string;
|
||||
}
|
||||
|
||||
@@ -85,13 +90,15 @@ char *Analog_Input_Name(uint32_t object_instance)
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object has already exists */
|
||||
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
|
||||
int Analog_Input_Encode_Property_APDU(
|
||||
uint8_t * apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
int32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
@@ -99,50 +106,53 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
|
||||
|
||||
(void) array_index;
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
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,
|
||||
Analog_Input_Name(object_instance));
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0],
|
||||
OBJECT_ANALOG_INPUT);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Input_Instance_To_Index(object_instance);
|
||||
apdu_len = encode_application_real(&apdu[0],
|
||||
Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
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,
|
||||
Analog_Input_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0],
|
||||
OBJECT_ANALOG_INPUT);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Input_Instance_To_Index(object_instance);
|
||||
apdu_len = encode_application_real(&apdu[0],
|
||||
Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
#include "bacenum.h"
|
||||
#include "handlers.h"
|
||||
|
||||
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
|
||||
bool apdu_service_supported(
|
||||
BACNET_SERVICES_SUPPORTED service_supported)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -57,13 +58,15 @@ bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_decode_confirmed_service_request(
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_len,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||
uint8_t * service_choice,
|
||||
uint8_t ** service_request, uint16_t * service_request_len)
|
||||
uint8_t ** service_request,
|
||||
uint16_t * service_request_len)
|
||||
{
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
service_data->segmented_message = (apdu[0] & BIT3) ? true : false;
|
||||
service_data->more_follows = (apdu[0] & BIT2) ? true : false;
|
||||
@@ -84,55 +87,56 @@ uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
|
||||
return len;
|
||||
}
|
||||
|
||||
void apdu_handler(BACNET_ADDRESS * src, uint8_t * apdu, /* APDU data */
|
||||
void apdu_handler(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_len)
|
||||
{
|
||||
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
|
||||
uint8_t service_choice = 0;
|
||||
uint8_t *service_request = NULL;
|
||||
uint16_t service_request_len = 0;
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
if (apdu) {
|
||||
/* PDU Type */
|
||||
switch (apdu[0] & 0xF0) {
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
apdu_len,
|
||||
&service_data,
|
||||
&service_choice, &service_request, &service_request_len);
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
handler_read_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
#if 0
|
||||
else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
|
||||
handler_write_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
apdu_len,
|
||||
&service_data,
|
||||
&service_choice, &service_request, &service_request_len);
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
handler_read_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
#if 0
|
||||
else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
|
||||
handler_write_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
handler_unrecognized_service(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
break;
|
||||
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
|
||||
service_choice = apdu[1];
|
||||
service_request = &apdu[2];
|
||||
service_request_len = apdu_len - 2;
|
||||
if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
|
||||
handler_who_is(service_request,
|
||||
service_request_len, src);
|
||||
}
|
||||
break;
|
||||
case PDU_TYPE_SIMPLE_ACK:
|
||||
case PDU_TYPE_COMPLEX_ACK:
|
||||
case PDU_TYPE_SEGMENT_ACK:
|
||||
case PDU_TYPE_ERROR:
|
||||
case PDU_TYPE_REJECT:
|
||||
case PDU_TYPE_ABORT:
|
||||
default:
|
||||
break;
|
||||
else {
|
||||
handler_unrecognized_service(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
break;
|
||||
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
|
||||
service_choice = apdu[1];
|
||||
service_request = &apdu[2];
|
||||
service_request_len = apdu_len - 2;
|
||||
if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
|
||||
handler_who_is(service_request, service_request_len, src);
|
||||
}
|
||||
break;
|
||||
case PDU_TYPE_SIMPLE_ACK:
|
||||
case PDU_TYPE_COMPLEX_ACK:
|
||||
case PDU_TYPE_SEGMENT_ACK:
|
||||
case PDU_TYPE_ERROR:
|
||||
case PDU_TYPE_REJECT:
|
||||
case PDU_TYPE_ABORT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "bacapp.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "wp.h"
|
||||
|
||||
#define MAX_ANALOG_VALUES 9
|
||||
#if (MAX_ANALOG_VALUES > 9)
|
||||
#error Modify the Analog_Value_Name to handle multiple digits
|
||||
#error Modify the Analog_Value_Name to handle multiple digits
|
||||
#endif
|
||||
|
||||
float Present_Value[MAX_ANALOG_VALUES];
|
||||
@@ -44,7 +44,8 @@ float Present_Value[MAX_ANALOG_VALUES];
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
||||
bool Analog_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
return true;
|
||||
@@ -54,7 +55,8 @@ bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(void)
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
{
|
||||
return MAX_ANALOG_VALUES;
|
||||
}
|
||||
@@ -62,7 +64,8 @@ unsigned Analog_Value_Count(void)
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(unsigned index)
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -70,18 +73,20 @@ uint32_t Analog_Value_Index_To_Instance(unsigned index)
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Analog_Value_Name(uint32_t object_instance)
|
||||
char *Analog_Value_Name(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AV-0"; /* okay for single thread */
|
||||
static char text_string[5] = "AV-0"; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_VALUES) {
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
return text_string;
|
||||
}
|
||||
|
||||
@@ -89,65 +94,74 @@ char *Analog_Value_Name(uint32_t object_instance)
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
|
||||
int Analog_Value_Encode_Property_APDU(
|
||||
uint8_t * apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
int32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
|
||||
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Value_Name(object_instance));
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Value_Instance_To_Index(object_instance);
|
||||
apdu_len = encode_application_real(&apdu[0], Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Value_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Value_Instance_To_Index(object_instance);
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0], Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
@@ -166,22 +180,21 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
/* FIXME: len == 0: unable to decode? */
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_PRESENT_VALUE:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index(wp_data->
|
||||
object_instance);
|
||||
Present_Value[object_index] = value.type.Real;
|
||||
status = true;
|
||||
} else {
|
||||
case PROP_PRESENT_VALUE:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index(wp_data->object_instance);
|
||||
Present_Value[object_index] = value.type.Real;
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -192,7 +205,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testAnalog_Value(Test * pTest)
|
||||
void testAnalog_Value(
|
||||
Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 0;
|
||||
@@ -207,8 +221,7 @@ void testAnalog_Value(Test * pTest)
|
||||
|
||||
len = Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||
instance,
|
||||
PROP_OBJECT_IDENTIFIER,
|
||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||
ct_test(pTest, len != 0);
|
||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||
@@ -221,7 +234,8 @@ void testAnalog_Value(Test * pTest)
|
||||
}
|
||||
|
||||
#ifdef TEST_ANALOG_VALUE
|
||||
int main(void)
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
@@ -238,5 +252,5 @@ int main(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TEST_ANALOG_VALUE */
|
||||
#endif /* TEST */
|
||||
#endif /* TEST_ANALOG_VALUE */
|
||||
#endif /* TEST */
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
#define BITMASK_FLIP(x,y) ((x) ^= (y))
|
||||
#define BITMASK_CHECK(x,y) ((x) & (y))
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -53,7 +53,8 @@ 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)
|
||||
void Device_Init(
|
||||
void)
|
||||
{
|
||||
/* Reinitialize_State = REINITIALIZED_STATE_IDLE; */
|
||||
/* dcc_set_status_duration(COMMUNICATION_ENABLE, 0); */
|
||||
@@ -65,14 +66,16 @@ void Device_Init(void)
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE) {
|
||||
Object_Instance_Number = object_id;
|
||||
@@ -88,21 +91,24 @@ bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
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));
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
unsigned Device_Object_List_Count(void)
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
/* FIXME: add objects as needed */
|
||||
#if 0
|
||||
@@ -115,8 +121,10 @@ unsigned Device_Object_List_Count(void)
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(unsigned array_index,
|
||||
int *object_type, uint32_t * instance)
|
||||
bool Device_Object_List_Identifier(
|
||||
unsigned array_index,
|
||||
int *object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned object_index = 0;
|
||||
@@ -185,18 +193,20 @@ bool Device_Object_List_Identifier(unsigned array_index,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error */
|
||||
int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
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)
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
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;
|
||||
@@ -206,168 +216,175 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
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_SYSTEM_STATUS:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], System_Status);
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, BACnet_Version);
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, "1.0");
|
||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 5);
|
||||
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_application_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);
|
||||
/* must have the bit string as big as it can be */
|
||||
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);
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
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_SYSTEM_STATUS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, BACnet_Version);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, "1.0");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 5);
|
||||
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_application_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);
|
||||
/* must have the bit string as big as it can be */
|
||||
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);
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
|
||||
#if 0
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
|
||||
#endif
|
||||
apdu_len = encode_application_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 == 0)
|
||||
apdu_len = encode_application_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_application_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 = encode_application_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 == 0)
|
||||
apdu_len = encode_application_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_application_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) {
|
||||
*error_class = ERROR_CLASS_SERVICES;
|
||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* error: internal error? */
|
||||
*error_class = ERROR_CLASS_SERVICES;
|
||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||
*error_code = ERROR_CODE_OTHER;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* error: internal error? */
|
||||
*error_class = ERROR_CLASS_SERVICES;
|
||||
*error_code = ERROR_CODE_OTHER;
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_application_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_application_unsigned(&apdu[0],
|
||||
MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len = encode_application_enumerated(&apdu[0],
|
||||
SEGMENTATION_NONE);
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 60000);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||
break;
|
||||
case 9600:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len = encode_application_enumerated(&apdu[0],
|
||||
SEGMENTATION_NONE);
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 60000);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||
break;
|
||||
case 9600:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
||||
bool Device_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
@@ -384,98 +401,98 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
/* FIXME: len == 0: unable to decode? */
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.
|
||||
Object_Id.instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*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) {
|
||||
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
if ((value.type.Unsigned_Int > 0) &&
|
||||
(value.type.Unsigned_Int <= 127)) {
|
||||
dlmstp_set_max_master(value.type.Unsigned_Int);
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
uint8_t encoding;
|
||||
size_t len;
|
||||
|
||||
encoding =
|
||||
characterstring_encoding(&value.type.Character_String);
|
||||
len = characterstring_length(&value.type.Character_String);
|
||||
if (encoding == CHARACTER_ANSI_X34) {
|
||||
if (len <= 20) {
|
||||
/* FIXME: set the name */
|
||||
/* Display_Set_Name(
|
||||
characterstring_value(&value.type.Character_String)); */
|
||||
/* FIXME: All the object names in a device must be unique.
|
||||
Disallow setting the Device Object Name to any objects in
|
||||
the device. */
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.
|
||||
Object_Id.instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
if (value.type.Unsigned_Int <= 255) {
|
||||
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
if ((value.type.Unsigned_Int > 0) &&
|
||||
(value.type.Unsigned_Int <= 127)) {
|
||||
dlmstp_set_max_master(value.type.Unsigned_Int);
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
uint8_t encoding;
|
||||
size_t len;
|
||||
|
||||
encoding =
|
||||
characterstring_encoding(&value.type.Character_String);
|
||||
len = characterstring_length(&value.type.Character_String);
|
||||
if (encoding == CHARACTER_ANSI_X34) {
|
||||
if (len <= 20) {
|
||||
/* FIXME: set the name */
|
||||
/* Display_Set_Name(
|
||||
characterstring_value(&value.type.Character_String)); */
|
||||
/* FIXME: All the object names in a device must be unique.
|
||||
Disallow setting the Device Object Name to any objects in
|
||||
the device. */
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
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 {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -64,24 +64,18 @@ int Encode_Property_APDU(
|
||||
*error_class = ERROR_CLASS_OBJECT;
|
||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
/* handle each object type */
|
||||
switch(object_type) {
|
||||
switch (object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Valid_Object_Instance_Number(object_instance)) {
|
||||
apdu_len = Device_Encode_Property_APDU(
|
||||
&apdu[0],
|
||||
property,
|
||||
array_index,
|
||||
error_class, error_code);
|
||||
apdu_len = Device_Encode_Property_APDU(&apdu[0],
|
||||
property, array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Valid_Instance(object_instance)) {
|
||||
apdu_len = Analog_Value_Encode_Property_APDU(
|
||||
&apdu[0],
|
||||
apdu_len = Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||
object_instance,
|
||||
property,
|
||||
array_index,
|
||||
error_class, error_code);
|
||||
property, array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -93,9 +87,11 @@ int Encode_Property_APDU(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
void handler_read_property(uint8_t * service_request,
|
||||
void handler_read_property(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
{
|
||||
BACNET_READ_PROPERTY_DATA data;
|
||||
int len = 0;
|
||||
@@ -125,13 +121,10 @@ void handler_read_property(uint8_t * service_request,
|
||||
} else {
|
||||
/* most cases will be error */
|
||||
error = true;
|
||||
len = Encode_Property_APDU(
|
||||
&Temp_Buf[0],
|
||||
len = Encode_Property_APDU(&Temp_Buf[0],
|
||||
data.object_type,
|
||||
data.object_instance,
|
||||
data.object_property,
|
||||
data.array_index,
|
||||
&error_class, &error_code);
|
||||
data.object_property, data.array_index, &error_class, &error_code);
|
||||
if (len >= 0) {
|
||||
/* encode the APDU portion of the packet */
|
||||
data.application_data = &Temp_Buf[0];
|
||||
@@ -145,18 +138,18 @@ 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;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
pdu_len += len;
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
|
||||
bool Send_I_Am = true;
|
||||
|
||||
void handler_who_is(uint8_t * service_request,
|
||||
uint16_t service_len, BACNET_ADDRESS * src)
|
||||
void handler_who_is(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src)
|
||||
{
|
||||
int len = 0;
|
||||
int32_t low_limit = 0;
|
||||
@@ -55,8 +57,7 @@ void handler_who_is(uint8_t * service_request,
|
||||
} else if (len != -1) {
|
||||
/* is my device id within the limits? */
|
||||
target_device = Device_Object_Instance_Number();
|
||||
if (((target_device >= low_limit) &&
|
||||
(target_device <= high_limit))
|
||||
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) &&
|
||||
|
||||
@@ -48,9 +48,11 @@
|
||||
/* too big to reside on stack frame for PIC */
|
||||
static BACNET_WRITE_PROPERTY_DATA wp_data;
|
||||
|
||||
void handler_write_property(uint8_t * service_request,
|
||||
void handler_write_property(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
@@ -61,8 +63,7 @@ void handler_write_property(uint8_t * service_request,
|
||||
BACNET_ADDRESS my_address;
|
||||
|
||||
/* decode the service request only */
|
||||
len = wp_decode_service_request(service_request,
|
||||
service_len, &wp_data);
|
||||
len = wp_decode_service_request(service_request, service_len, &wp_data);
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
@@ -79,66 +80,66 @@ void handler_write_property(uint8_t * service_request,
|
||||
} else {
|
||||
switch (wp_data.object_type) {
|
||||
#if 0
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_INPUT:
|
||||
case OBJECT_BINARY_INPUT:
|
||||
error_class = ERROR_CLASS_PROPERTY;
|
||||
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_INPUT:
|
||||
case OBJECT_BINARY_INPUT:
|
||||
error_class = ERROR_CLASS_PROPERTY;
|
||||
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pdu_len += len;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define HARDWARE_H
|
||||
|
||||
/* The processor clock frequency */
|
||||
#define F_CPU (7372800)
|
||||
#define F_CPU (7372800)
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
@@ -39,11 +39,14 @@
|
||||
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
|
||||
|
||||
/* dummy function */
|
||||
bool dcc_communication_enabled(void) {
|
||||
bool dcc_communication_enabled(
|
||||
void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void init(void)
|
||||
void init(
|
||||
void)
|
||||
{
|
||||
/* Initialize the Clock Prescaler for ATmega48/88/168 */
|
||||
/* The default CLKPSx bits are factory set to 0011 */
|
||||
@@ -51,17 +54,17 @@ void init(void)
|
||||
CLKPR = _BV(CLKPCE);
|
||||
/* CLKPS3 CLKPS2 CLKPS1 CLKPS0 Clock Division Factor
|
||||
------ ------ ------ ------ ---------------------
|
||||
0 0 0 0 1
|
||||
0 0 0 1 2
|
||||
0 0 1 0 4
|
||||
0 0 1 1 8
|
||||
0 1 0 0 16
|
||||
0 1 0 1 32
|
||||
0 1 1 0 64
|
||||
0 1 1 1 128
|
||||
1 0 0 0 256
|
||||
1 x x x Reserved
|
||||
*/
|
||||
0 0 0 0 1
|
||||
0 0 0 1 2
|
||||
0 0 1 0 4
|
||||
0 0 1 1 8
|
||||
0 1 0 0 16
|
||||
0 1 0 1 32
|
||||
0 1 1 0 64
|
||||
0 1 1 1 128
|
||||
1 0 0 0 256
|
||||
1 x x x Reserved
|
||||
*/
|
||||
/* Set the CLKPS3..0 bits to Prescaler of 1 */
|
||||
CLKPR = 0;
|
||||
/* Initialize I/O ports */
|
||||
@@ -75,7 +78,7 @@ void init(void)
|
||||
PORTD = 0;
|
||||
|
||||
/* Configure the watchdog timer - Disabled for testing */
|
||||
BIT_CLEAR(MCUSR,WDRF);
|
||||
BIT_CLEAR(MCUSR, WDRF);
|
||||
WDTCSR = 0;
|
||||
|
||||
/* Configure USART */
|
||||
@@ -85,11 +88,11 @@ void init(void)
|
||||
Timer_Initialize();
|
||||
|
||||
/* Set the LED ports OFF */
|
||||
BIT_SET(PORTD,PD4);
|
||||
BIT_SET(PORTD,PD5);
|
||||
BIT_SET(PORTD, PD4);
|
||||
BIT_SET(PORTD, PD5);
|
||||
/* Configure the LED ports as outputs */
|
||||
BIT_SET(DDRD,DDD4);
|
||||
BIT_SET(DDRD,DDD5);
|
||||
BIT_SET(DDRD, DDD4);
|
||||
BIT_SET(DDRD, DDD5);
|
||||
|
||||
/* Enable global interrupts */
|
||||
sei();
|
||||
@@ -97,23 +100,26 @@ void init(void)
|
||||
|
||||
static uint8_t NPDU_Timer;
|
||||
|
||||
static void NDPU_Timers(void)
|
||||
static void NDPU_Timers(
|
||||
void)
|
||||
{
|
||||
if (NPDU_Timer) {
|
||||
NPDU_Timer--;
|
||||
if (NPDU_Timer == 0) {
|
||||
BIT_SET(PORTD,PD5);
|
||||
BIT_SET(PORTD, PD5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void NPDU_LED_On(void)
|
||||
static void NPDU_LED_On(
|
||||
void)
|
||||
{
|
||||
BIT_CLEAR(PORTD,PD5);
|
||||
BIT_CLEAR(PORTD, PD5);
|
||||
NPDU_Timer = 20;
|
||||
}
|
||||
|
||||
void task_milliseconds(void)
|
||||
void task_milliseconds(
|
||||
void)
|
||||
{
|
||||
while (Timer_Milliseconds) {
|
||||
Timer_Milliseconds--;
|
||||
@@ -125,31 +131,33 @@ void task_milliseconds(void)
|
||||
|
||||
static uint8_t Address_Switch;
|
||||
|
||||
void input_switch_read(void)
|
||||
void input_switch_read(
|
||||
void)
|
||||
{
|
||||
uint8_t value;
|
||||
static uint8_t old_value = 0;
|
||||
|
||||
value = BITMASK_CHECK(PINC,0x0F) | (BITMASK_CHECK(PINB,0x07)<<4);
|
||||
value = BITMASK_CHECK(PINC, 0x0F) | (BITMASK_CHECK(PINB, 0x07) << 4);
|
||||
if (value != old_value) {
|
||||
old_value = value;
|
||||
} else {
|
||||
if (old_value != Address_Switch) {
|
||||
Address_Switch = old_value;
|
||||
Address_Switch = old_value;
|
||||
#if defined(BACDL_MSTP)
|
||||
dlmstp_set_mac_address(Address_Switch);
|
||||
dlmstp_set_mac_address(Address_Switch);
|
||||
#endif
|
||||
Device_Set_Object_Instance_Number(86000 + Address_Switch);
|
||||
Device_Set_Object_Instance_Number(86000 + Address_Switch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t PDUBuffer[MAX_MPDU];
|
||||
int main(void)
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src; /* source address */
|
||||
|
||||
|
||||
init();
|
||||
#if defined(BACDL_MSTP)
|
||||
RS485_Set_Baud_Rate(38400);
|
||||
|
||||
@@ -70,10 +70,11 @@ static uint32_t RS485_Baud = 9600;
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(void)
|
||||
void RS485_Initialize(
|
||||
void)
|
||||
{
|
||||
/* enable Transmit and Receive */
|
||||
UCSR0B = _BV(TXEN0) | _BV(RXEN0);
|
||||
UCSR0B = _BV(TXEN0) | _BV(RXEN0);
|
||||
|
||||
/* Set USART Control and Status Register n C */
|
||||
/* Asynchronous USART 8-bit data, No parity, 1 stop */
|
||||
@@ -84,16 +85,16 @@ void RS485_Initialize(void)
|
||||
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
|
||||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
|
||||
/* Clear Power Reduction USART0 */
|
||||
BIT_CLEAR(PRR,PRUSART0);
|
||||
BIT_CLEAR(PRR, PRUSART0);
|
||||
/* Use port PD2 for RTS - enable and disable of Transceiver Tx/Rx */
|
||||
/* Set port bit as Output - initially receiving */
|
||||
BIT_CLEAR(PORTD,PD2);
|
||||
BIT_SET(DDRD,DDD2);
|
||||
BIT_CLEAR(PORTD, PD2);
|
||||
BIT_SET(DDRD, DDD2);
|
||||
/* Configure Transmit and Receive LEDs - initially off */
|
||||
BIT_SET(PORTD,PD6);
|
||||
BIT_SET(PORTD,PD7);
|
||||
BIT_SET(DDRD,DDD6);
|
||||
BIT_SET(DDRD,DDD7);
|
||||
BIT_SET(PORTD, PD6);
|
||||
BIT_SET(PORTD, PD7);
|
||||
BIT_SET(DDRD, DDD6);
|
||||
BIT_SET(DDRD, DDD7);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -104,7 +105,8 @@ void RS485_Initialize(void)
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(void)
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void)
|
||||
{
|
||||
return RS485_Baud;
|
||||
}
|
||||
@@ -115,7 +117,8 @@ uint32_t RS485_Get_Baud_Rate(void)
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
@@ -128,7 +131,7 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
case 115200:
|
||||
RS485_Baud = baud;
|
||||
/* 2x speed mode */
|
||||
BIT_SET(UCSR0A,U2X0);
|
||||
BIT_SET(UCSR0A, U2X0);
|
||||
/* configure baud rate */
|
||||
UBRR0 = (F_CPU / (8UL * RS485_Baud)) - 1;
|
||||
/* FIXME: store the baud rate */
|
||||
@@ -147,14 +150,15 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(void)
|
||||
void RS485_Turnaround_Delay(
|
||||
void)
|
||||
{
|
||||
uint16_t turnaround_time;
|
||||
|
||||
|
||||
/* delay after reception before trasmitting - per MS/TP spec */
|
||||
/* wait a minimum 40 bit times since reception */
|
||||
/* at least 1 ms for errors: rounding, clock tick */
|
||||
turnaround_time = 1 + ((Tturnaround*1000UL)/RS485_Baud);
|
||||
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud);
|
||||
while (Timer_Silence() < turnaround_time) {
|
||||
/* do nothing - wait for timer to increment */
|
||||
};
|
||||
@@ -166,18 +170,19 @@ void RS485_Turnaround_Delay(void)
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(bool enable)
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
BIT_SET(PORTD,PD2);
|
||||
BIT_SET(PORTD, PD2);
|
||||
} else {
|
||||
#if Tpostdrive1
|
||||
_delay_us(Tpostdrive1/RS485_Baud);
|
||||
#endif
|
||||
#if Tpostdrive2
|
||||
_delay_us(Tpostdrive2/RS485_Baud);
|
||||
#endif
|
||||
BIT_CLEAR(PORTD,PD2);
|
||||
#if Tpostdrive1
|
||||
_delay_us(Tpostdrive1 / RS485_Baud);
|
||||
#endif
|
||||
#if Tpostdrive2
|
||||
_delay_us(Tpostdrive2 / RS485_Baud);
|
||||
#endif
|
||||
BIT_CLEAR(PORTD, PD2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,18 +192,19 @@ void RS485_Transmitter_Enable(bool enable)
|
||||
* ALGORITHM: none
|
||||
* NOTES: expected to be called once a millisecond
|
||||
*****************************************************************************/
|
||||
void RS485_LED_Timers(void)
|
||||
void RS485_LED_Timers(
|
||||
void)
|
||||
{
|
||||
if (LED1_Off_Timer) {
|
||||
LED1_Off_Timer--;
|
||||
if (LED1_Off_Timer == 0) {
|
||||
BIT_SET(PORTD,PD6);
|
||||
BIT_SET(PORTD, PD6);
|
||||
}
|
||||
}
|
||||
if (LED3_Off_Timer) {
|
||||
LED3_Off_Timer--;
|
||||
if (LED3_Off_Timer == 0) {
|
||||
BIT_SET(PORTD,PD7);
|
||||
BIT_SET(PORTD, PD7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,9 +215,10 @@ void RS485_LED_Timers(void)
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void RS485_LED1_On(void)
|
||||
static void RS485_LED1_On(
|
||||
void)
|
||||
{
|
||||
BIT_CLEAR(PORTD,PD6);
|
||||
BIT_CLEAR(PORTD, PD6);
|
||||
LED1_Off_Timer = 20;
|
||||
}
|
||||
|
||||
@@ -221,9 +228,10 @@ static void RS485_LED1_On(void)
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void RS485_LED3_On(void)
|
||||
static void RS485_LED3_On(
|
||||
void)
|
||||
{
|
||||
BIT_CLEAR(PORTD,PD7);
|
||||
BIT_CLEAR(PORTD, PD7);
|
||||
LED3_Off_Timer = 20;
|
||||
}
|
||||
|
||||
@@ -234,27 +242,27 @@ static void RS485_LED3_On(void)
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes) /* number of bytes of data */
|
||||
{
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
RS485_LED3_On();
|
||||
while (nbytes) {
|
||||
while (!BIT_CHECK(UCSR0A,UDRE0)) {
|
||||
while (!BIT_CHECK(UCSR0A, UDRE0)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
}
|
||||
UDR0 = *buffer;
|
||||
buffer++;
|
||||
nbytes--;
|
||||
}
|
||||
while (!BIT_CHECK(UCSR0A,UDRE0)) {
|
||||
while (!BIT_CHECK(UCSR0A, UDRE0)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
}
|
||||
/* is the frame sent? */
|
||||
while (!BIT_CHECK(UCSR0A,TXC0)) {
|
||||
while (!BIT_CHECK(UCSR0A, TXC0)) {
|
||||
/* do nothing - wait until the entire frame in the
|
||||
Transmit Shift Register has been shifted out */
|
||||
}
|
||||
BIT_CLEAR(UCSR0A,TXC0);
|
||||
BIT_CLEAR(UCSR0A, TXC0);
|
||||
/* per MSTP spec, sort of */
|
||||
Timer_Silence_Reset();
|
||||
}
|
||||
@@ -266,31 +274,32 @@ void RS485_Send_Data(
|
||||
* ALGORITHM: autobaud - if there are a lot of errors, switch baud rate
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(void)
|
||||
bool RS485_ReceiveError(
|
||||
void)
|
||||
{
|
||||
bool ReceiveError = false;
|
||||
uint8_t dummy_data;
|
||||
|
||||
/* check for framing error */
|
||||
#if 0
|
||||
if (BIT_CHECK(UCSR0A,FE0)) {
|
||||
#if 0
|
||||
if (BIT_CHECK(UCSR0A, FE0)) {
|
||||
/* FIXME: how do I clear the error flags? */
|
||||
BITMASK_CLEAR(UCSR0A,(_BV(FE0) | _BV(DOR0) | _BV(UPE0)));
|
||||
BITMASK_CLEAR(UCSR0A, (_BV(FE0) | _BV(DOR0) | _BV(UPE0)));
|
||||
ReceiveError = true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* check for overrun error */
|
||||
if (BIT_CHECK(UCSR0A,DOR0)) {
|
||||
if (BIT_CHECK(UCSR0A, DOR0)) {
|
||||
/* flush the receive buffer */
|
||||
do {
|
||||
dummy_data = UDR0;
|
||||
} while (BIT_CHECK(UCSR0A,RXC0));
|
||||
} while (BIT_CHECK(UCSR0A, RXC0));
|
||||
ReceiveError = true;
|
||||
}
|
||||
if (ReceiveError) {
|
||||
RS485_LED1_On();
|
||||
}
|
||||
|
||||
|
||||
return ReceiveError;
|
||||
}
|
||||
|
||||
@@ -300,12 +309,13 @@ bool RS485_ReceiveError(void)
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(uint8_t *data)
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * data)
|
||||
{
|
||||
bool DataAvailable = false;
|
||||
|
||||
/* check for data */
|
||||
if (BIT_CHECK(UCSR0A,RXC0)) {
|
||||
if (BIT_CHECK(UCSR0A, RXC0)) {
|
||||
*data = UDR0;
|
||||
DataAvailable = true;
|
||||
RS485_LED1_On();
|
||||
@@ -315,7 +325,8 @@ bool RS485_DataAvailable(uint8_t *data)
|
||||
}
|
||||
|
||||
#ifdef TEST_RS485
|
||||
int main(void)
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
unsigned i = 0;
|
||||
uint8_t DataRegister;
|
||||
@@ -325,11 +336,10 @@ int main(void)
|
||||
/* receive task */
|
||||
for (;;) {
|
||||
if (RS485_ReceiveError()) {
|
||||
fprintf(stderr,"ERROR ");
|
||||
fprintf(stderr, "ERROR ");
|
||||
} else if (RS485_DataAvailable(&DataRegister)) {
|
||||
fprintf(stderr,"%02X ",DataRegister);
|
||||
fprintf(stderr, "%02X ", DataRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TEST_RS485 */
|
||||
|
||||
#endif /* TEST_RS485 */
|
||||
|
||||
@@ -40,26 +40,34 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void RS485_Initialize(void);
|
||||
void RS485_Initialize(
|
||||
void);
|
||||
|
||||
void RS485_Transmitter_Enable(bool enable);
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable);
|
||||
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes); /* number of bytes of data */
|
||||
|
||||
bool RS485_ReceiveError(void);
|
||||
bool RS485_DataAvailable(uint8_t *data);
|
||||
bool RS485_ReceiveError(
|
||||
void);
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * data);
|
||||
|
||||
void RS485_Turnaround_Delay(void);
|
||||
uint32_t RS485_Get_Baud_Rate(void);
|
||||
bool RS485_Set_Baud_Rate(uint32_t baud);
|
||||
void RS485_Turnaround_Delay(
|
||||
void);
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void);
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud);
|
||||
|
||||
void RS485_LED_Timers(void);
|
||||
void RS485_LED_Timers(
|
||||
void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
@@ -41,30 +41,31 @@ volatile uint8_t Timer_Milliseconds = 0;
|
||||
static volatile uint16_t SilenceTime;
|
||||
|
||||
/* Configure the Timer */
|
||||
void Timer_Initialize(void)
|
||||
void Timer_Initialize(
|
||||
void)
|
||||
{
|
||||
/* Normal Operation */
|
||||
TCCR1A = 0;
|
||||
/* CSn2 CSn1 CSn0 Description
|
||||
---- ---- ---- -----------
|
||||
0 0 0 No Clock Source
|
||||
0 0 1 No prescaling
|
||||
0 1 0 CLKio/8
|
||||
0 1 1 CLKio/64
|
||||
1 0 0 CLKio/256
|
||||
1 0 1 CLKio/1024
|
||||
1 1 0 Falling Edge of T0 (external)
|
||||
1 1 1 Rising Edge of T0 (external)
|
||||
*/
|
||||
0 0 0 No Clock Source
|
||||
0 0 1 No prescaling
|
||||
0 1 0 CLKio/8
|
||||
0 1 1 CLKio/64
|
||||
1 0 0 CLKio/256
|
||||
1 0 1 CLKio/1024
|
||||
1 1 0 Falling Edge of T0 (external)
|
||||
1 1 1 Rising Edge of T0 (external)
|
||||
*/
|
||||
TCCR0B = _BV(CS01) | _BV(CS00);
|
||||
/* Clear any TOV1 Flag set when the timer overflowed */
|
||||
BIT_CLEAR(TIFR0,TOV0);
|
||||
BIT_CLEAR(TIFR0, TOV0);
|
||||
/* Initial value */
|
||||
TCNT0 = TIMER_COUNT;
|
||||
/* Enable the overflow interrupt */
|
||||
BIT_SET(TIMSK0,TOIE0);
|
||||
BIT_SET(TIMSK0, TOIE0);
|
||||
/* Clear the Power Reduction Timer/Counter0 */
|
||||
BIT_CLEAR(PRR,PRTIM0);
|
||||
BIT_CLEAR(PRR, PRTIM0);
|
||||
}
|
||||
|
||||
/* Timer interupt */
|
||||
@@ -77,13 +78,14 @@ ISR(TIMER0_OVF_vect)
|
||||
/* Overflow Flag is automatically cleared */
|
||||
/* Update the global timer */
|
||||
if (Timer_Milliseconds < 0xFF)
|
||||
Timer_Milliseconds++;
|
||||
Timer_Milliseconds++;
|
||||
if (SilenceTime < 0xFFFF)
|
||||
SilenceTime++;
|
||||
}
|
||||
|
||||
/* Public access to the Silence Timer */
|
||||
uint16_t Timer_Silence(void)
|
||||
uint16_t Timer_Silence(
|
||||
void)
|
||||
{
|
||||
uint16_t timer;
|
||||
uint8_t sreg;
|
||||
@@ -97,7 +99,8 @@ uint16_t Timer_Silence(void)
|
||||
}
|
||||
|
||||
/* Public reset of the Silence Timer */
|
||||
void Timer_Silence_Reset(void)
|
||||
void Timer_Silence_Reset(
|
||||
void)
|
||||
{
|
||||
uint8_t sreg;
|
||||
|
||||
|
||||
@@ -29,14 +29,16 @@ extern volatile uint8_t Timer_Milliseconds;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void Timer_Initialize(void);
|
||||
uint16_t Timer_Silence(void);
|
||||
void Timer_Silence_Reset(void);
|
||||
void Timer_Initialize(
|
||||
void);
|
||||
uint16_t Timer_Silence(
|
||||
void);
|
||||
void Timer_Silence_Reset(
|
||||
void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user