Added more objects to BDK port, and connected AI to ADC7, and BI0..BI4 to PINB0..PINB4. Fixed up some other objects and object API (header files).

This commit is contained in:
skarg
2009-06-18 03:58:54 +00:00
parent 6e6cdf2bc0
commit e70dd3c7ba
18 changed files with 814 additions and 29 deletions
+27 -2
View File
@@ -33,7 +33,11 @@
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#ifndef MAX_ANALOG_INPUTS
#define MAX_ANALOG_INPUTS 7
#endif
static float Present_Value[MAX_ANALOG_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Input_Properties_Required[] = {
@@ -104,6 +108,27 @@ uint32_t Analog_Input_Index_To_Instance(
return index;
}
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;
}
void Analog_Input_Present_Value_Set(
uint32_t object_instance,
float value)
{
if (object_instance < MAX_ANALOG_INPUTS) {
Present_Value[object_instance] = value;
}
}
char *Analog_Input_Name(
uint32_t object_instance)
{
@@ -130,7 +155,6 @@ int Analog_Input_Encode_Property_APDU(
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float value = 3.14159F;
(void) array_index;
switch (property) {
@@ -151,7 +175,8 @@ int Analog_Input_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0], value);
apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
+7
View File
@@ -52,6 +52,13 @@ extern "C" {
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
float Analog_Input_Present_Value(
uint32_t object_instance);
void Analog_Input_Present_Value_Set(
uint32_t object_instance,
float value);
void Analog_Input_Init(
void);
#ifdef TEST
#include "ctest.h"
+3 -1
View File
@@ -70,7 +70,9 @@ extern "C" {
uint8_t priority);
float Analog_Value_Present_Value(
uint32_t object_instance);
void Analog_Value_Init(
void);
#ifdef TEST
#include "ctest.h"
+8
View File
@@ -67,6 +67,14 @@ extern "C" {
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
void Binary_Input_Init(
void);
BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance);
bool Binary_Input_Present_Value_Set(
uint32_t object_instance,
bool value);
#ifdef TEST
#include "ctest.h"
+11 -2
View File
@@ -39,7 +39,7 @@
#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 */
@@ -80,7 +80,7 @@ char *Analog_Input_Name(
return NULL;
}
static float Analog_Input_Present_Value(
float Analog_Input_Present_Value(
uint32_t object_instance)
{
float value = 0.0;
@@ -91,6 +91,15 @@ static float Analog_Input_Present_Value(
return value;
}
void Analog_Input_Present_Value_Set(
uint32_t object_instance,
float value)
{
if (object_instance < MAX_ANALOG_INPUTS) {
Present_Value[object_instance] = value;
}
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(
@@ -42,6 +42,7 @@ BACNET_DEMO = ../../demo
CSRC = main.c \
init.c \
stack.c \
adc.c \
input.c \
serial.c \
rs485.c \
@@ -56,6 +57,7 @@ CSRC = main.c \
h_rd.c \
device.c \
ai.c \
av.c \
bi.c \
bo.c
+94
View File
@@ -0,0 +1,94 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "hardware.h"
/* prescale select bits */
#if (F_CPU >> 1) < 1000000
#define ADPS_8BIT (1)
#define ADPS_10BIT (3)
#elif (F_CPU >> 2) < 1000000
#define ADPS_8BIT (2)
#define ADPS_10BIT (4)
#elif (F_CPU >> 3) < 1000000
#define ADPS_8BIT (3)
#define ADPS_10BIT (5)
#elif (F_CPU >> 4) < 1000000
#define ADPS_8BIT (4)
#define ADPS_10BIT (6)
#elif (F_CPU >> 5) < 1000000
#define ADPS_8BIT (5)
#define ADPS_10BIT (7)
#else
#error "ADC: F_CPU too large for accuracy."
#endif
/* we could have array of ADC results */
static volatile uint8_t Sample_Result;
ISR(ADC_vect)
{
/* since we configured as ADLAR=1, get value from ADCH */
Sample_Result = ADCH;
}
uint8_t adc_result(
uint8_t channel) /* 0..7 = ADC0..ADC7, respectively */
{
return Sample_Result;
}
void adc_init(void)
{
/* set prescaler */
ADCSRA |= ADPS_8BIT;
/* Initial channel selection */
/* ADLAR = Left Adjust Result
REFSx = hardware setup: cap on AREF
*/
ADMUX = 7 /* channel */ | (1 << ADLAR) | (0 << REFS1) | (1 << REFS0);
/* ADEN = Enable
ADSC = Start conversion
ADIF = Interrupt Flag
ADIE = Interrupt Enable
ADATE = Auto Trigger Enable
*/
ADCSRA |= (1 << ADEN) | (1 << ADIE) | (1 << ADIF) | (1 << ADATE);
/* trigger selection bits
0 0 0 Free Running mode
0 0 1 Analog Comparator
0 1 0 External Interrupt Request 0
0 1 1 Timer/Counter0 Compare Match
1 0 0 Timer/Counter0 Overflow
1 0 1 Timer/Counter1 Compare Match B
1 1 0 Timer/Counter1 Overflow
1 1 1 Timer/Counter1 Capture Event
*/
ADCSRB |= (0 << ADTS2) | (0 << ADTS1) | (0 << ADTS0);
/* start the conversions */
ADCSRA |= (1 << ADSC);
/* Clear the Power Reduction bit */
BIT_CLEAR(PRR, PRADC);
}
+40
View File
@@ -0,0 +1,40 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*********************************************************************/
#ifndef ADC_H
#define ADC_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
uint8_t adc_result(uint8_t channel);
void adc_init(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+19 -3
View File
@@ -39,6 +39,8 @@
#error Modify the Analog_Input_Name to handle multiple digits
#endif
static uint8_t Present_Value[MAX_ANALOG_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -76,7 +78,11 @@ void Analog_Input_Property_Lists(
return;
}
static uint8_t Present_Value[MAX_ANALOG_INPUTS];
void Analog_Input_Init(
void)
{
return;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
@@ -117,17 +123,27 @@ char *Analog_Input_Name(
return NULL;
}
static float Analog_Input_Present_Value(
float Analog_Input_Present_Value(
uint32_t object_instance)
{
float value = 0.0;
if (object_instance < MAX_ANALOG_INPUTS)
if (object_instance < MAX_ANALOG_INPUTS) {
value = Present_Value[object_instance];
}
return value;
}
void Analog_Input_Present_Value_Set(
uint32_t object_instance,
float value)
{
if (object_instance < MAX_ANALOG_INPUTS) {
Present_Value[object_instance] = value;
}
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(
+452
View File
@@ -0,0 +1,452 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Analog Value Objects - customize for your use */
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h> /* for NAN */
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "wp.h"
#ifndef MAX_ANALOG_VALUES
#define MAX_ANALOG_VALUES 4
#endif
static float Present_Value[MAX_ANALOG_VALUES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
static const int Analog_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Analog_Value_Properties_Proprietary[] = {
-1
};
void Analog_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Analog_Value_Properties_Required;
if (pOptional)
*pOptional = Analog_Value_Properties_Optional;
if (pProprietary)
*pProprietary = Analog_Value_Properties_Proprietary;
return;
}
void Analog_Value_Init(
void)
{
return;
}
/* 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)
{
if (object_instance < MAX_ANALOG_VALUES)
return true;
return false;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Value_Count(
void)
{
return MAX_ANALOG_VALUES;
}
/* 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)
{
return 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 index = MAX_ANALOG_VALUES;
if (object_instance < MAX_ANALOG_VALUES)
index = object_instance;
return index;
}
float Analog_Value_Present_Value(
uint32_t object_instance)
{
float value = NAN;
unsigned index = 0;
index = Analog_Value_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_VALUES) {
value = Present_Value[index];
}
return value;
}
bool Analog_Value_Present_Value_Set(
uint32_t object_instance,
float value,
uint8_t priority)
{
unsigned index = 0;
bool status = false;
priority = priority;
index = Analog_Value_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_VALUES) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value >= 0.0) && (value <= 100.0)) {
Present_Value[index] = value;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
}
}
return status;
}
/* note: the object name must be unique within this device */
char *Analog_Value_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
unsigned index = 0;
index = Analog_Value_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_VALUES) {
sprintf(text_string, "AV-%lu", object_instance);
return text_string;
}
return NULL;
}
/* return apdu len, or -1 on error */
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)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = 1.414F;
#if 0
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
#endif
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:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
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:
#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Present_Value[object_index][i] == ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Present_Value[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Present_Value[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Present_Value[object_index][array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
#endif
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 status = false; /* return value */
#if 0
unsigned int object_index = 0;
unsigned int priority = 0;
#endif
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Analog_Value_Valid_Instance(wp_data->object_instance)) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* 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) {
if (Analog_Value_Present_Value_Set(
wp_data->object_instance,
value.type.Real,
wp_data->priority)) {
status = true;
} else if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
if (Analog_Value_Present_Value_Set(
wp_data->object_instance,
NAN,
wp_data->priority)) {
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testAnalog_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_VALUE;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
len =
Analog_Value_Encode_Property_APDU(&apdu[0], instance,
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);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_VALUE);
ct_test(pTest, decoded_instance == instance);
return;
}
#ifdef TEST_ANALOG_VALUE
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Analog Value", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testAnalog_Value);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
+23 -10
View File
@@ -80,17 +80,13 @@ void Binary_Input_Property_Lists(
return;
}
static void Binary_Input_Initialize(
void Binary_Input_Init(
void)
{
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
}
@@ -132,13 +128,12 @@ unsigned Binary_Input_Instance_To_Index(
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(
BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
Binary_Input_Initialize();
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
value = Present_Value[index];
@@ -147,6 +142,25 @@ static BACNET_BINARY_PV Binary_Input_Present_Value(
return value;
}
bool Binary_Input_Present_Value_Set(
uint32_t object_instance,
bool value)
{
unsigned index = 0;
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
if (value) {
Present_Value[index] = BINARY_ACTIVE;
} else {
Present_Value[index] = BINARY_INACTIVE;
}
return true;
}
return false;
}
char *Binary_Input_Name(
uint32_t object_instance)
{
@@ -178,7 +192,6 @@ int Binary_Input_Encode_Property_APDU(
(void) array_index;
Binary_Input_Initialize();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
@@ -39,6 +39,7 @@
/* objects */
#include "device.h"
#include "ai.h"
#include "av.h"
#include "bi.h"
#include "bo.h"
@@ -229,6 +230,7 @@ unsigned Device_Object_List_Count(
count += Binary_Input_Count();
count += Binary_Output_Count();
count += Analog_Input_Count();
count += Analog_Value_Count();
return count;
}
@@ -290,6 +292,17 @@ bool Device_Object_List_Identifier(
status = true;
}
}
/* analog value objects */
if (!status) {
/* array index starts at 1, and 1 for the device object */
object_index -= object_count;
object_count = Analog_Value_Count();
if (object_index < object_count) {
*object_type = OBJECT_ANALOG_VALUE;
*instance = Analog_Value_Index_To_Instance(object_index);
status = true;
}
}
return status;
}
@@ -398,6 +411,7 @@ int Device_Encode_Property_APDU(
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_OUTPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
+9
View File
@@ -39,6 +39,7 @@
/* demo objects */
#include "device.h"
#include "ai.h"
#include "av.h"
#include "bi.h"
#include "bo.h"
@@ -77,6 +78,14 @@ int Encode_Property_APDU(
error_code);
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(object_instance)) {
apdu_len =
Analog_Value_Encode_Property_APDU(&apdu[0],
object_instance, property, array_index, error_class,
error_code);
}
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(object_instance)) {
apdu_len =
+14
View File
@@ -39,6 +39,7 @@
/* demo objects */
#include "device.h"
#include "ai.h"
#include "av.h"
#include "bi.h"
#include "bo.h"
@@ -117,6 +118,19 @@ void handler_write_property(
error_class, error_code);
}
break;
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],
+61 -10
View File
@@ -22,22 +22,36 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "hardware.h"
static uint8_t Address_Switch;
static uint8_t Buttons;
/* debounce the inputs */
void input_task(
void)
{
uint8_t value;
static uint8_t old_value = 0;
static uint8_t old_address = 0;
static uint8_t old_buttons = 0;
value = BITMASK_CHECK(PINA, 0x7F);
if (value != old_value) {
old_value = value;
if (value != old_address) {
old_address = value;
} else {
if (old_value != Address_Switch) {
Address_Switch = old_value;
if (old_address != Address_Switch) {
Address_Switch = old_address;
}
}
/* pins used are PB4, PB3, PB2, PB1, PB0 */
value = BITMASK_CHECK(PINB, 0x1F);
if (value != old_buttons) {
old_buttons = value;
} else {
if (old_buttons != Buttons) {
Buttons = old_buttons;
}
}
}
@@ -48,12 +62,49 @@ uint8_t input_address(
return Address_Switch;
}
bool input_button_value(
uint8_t index)
{
bool value = false;
switch (index) {
case 0:
value = BIT_CHECK(Buttons, 0);
break;
case 1:
value = BIT_CHECK(Buttons, 1);
break;
case 2:
value = BIT_CHECK(Buttons, 2);
break;
case 3:
value = BIT_CHECK(Buttons, 3);
break;
case 4:
value = BIT_CHECK(Buttons, 4);
break;
default:
break;
}
return value;
}
void input_init(
void)
{
/* configure the port pins */
BITMASK_CLEAR(DDRA,
_BV(DDA0) | _BV(DDA1) | _BV(DDA2) | _BV(DDA3) | _BV(DDA4) | _BV(DDA5) |
_BV(DDA6)
);
/* configure the port pins for the switch */
BIT_CLEAR(DDRA, DDA0);
BIT_CLEAR(DDRA, DDA1);
BIT_CLEAR(DDRA, DDA2);
BIT_CLEAR(DDRA, DDA3);
BIT_CLEAR(DDRA, DDA4);
BIT_CLEAR(DDRA, DDA5);
BIT_CLEAR(DDRA, DDA6);
/* configure the port pins for binary inputs */
BIT_CLEAR(DDRB, DDB1);
BIT_CLEAR(DDRB, DDB2);
BIT_CLEAR(DDRB, DDB3);
BIT_CLEAR(DDRB, DDB4);
}
@@ -36,6 +36,8 @@ extern "C" {
void);
uint8_t input_address(
void);
bool input_button_value(
uint8_t index);
#ifdef __cplusplus
}
+18
View File
@@ -31,6 +31,7 @@
#include "timer.h"
#include "input.h"
#include "led.h"
#include "adc.h"
#include "nvdata.h"
#include "timer.h"
#include "dcc.h"
@@ -44,6 +45,7 @@
#include "iam.h"
#include "device.h"
#include "ai.h"
#include "av.h"
#include "bi.h"
#include "bo.h"
@@ -128,6 +130,9 @@ static void bacnet_init(
/* initialize objects */
Device_Init();
Binary_Output_Init();
Analog_Input_Init();
Binary_Input_Init();
Analog_Value_Init();
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
@@ -155,6 +160,9 @@ static void bacnet_task(
uint8_t mstp_mac_address = 0;
uint16_t pdu_len = 0;
BACNET_ADDRESS src; /* source address */
uint8_t value = 0;
bool button_value = false;
uint8_t i = 0;
mstp_mac_address = input_address();
if (MSTP_MAC_Address != mstp_mac_address) {
@@ -162,9 +170,18 @@ static void bacnet_task(
dlmstp_set_mac_address(MSTP_MAC_Address);
Send_I_Am(&Handler_Transmit_Buffer[0]);
}
/* handle the inputs */
value = adc_result(7);
Analog_Input_Present_Value_Set(0, value);
for (i = 0; i < 5; i++) {
button_value = input_button_value(i);
Binary_Input_Present_Value_Set(i, button_value);
}
/* handle the communication timer */
if (timer_elapsed_seconds(TIMER_DCC, 1)) {
dcc_timer_seconds(1);
}
/* handle the messaging */
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
if (pdu_len) {
npdu_handler(&src, &PDUBuffer[0], pdu_len);
@@ -198,6 +215,7 @@ int main(
void)
{
init();
adc_init();
led_init();
input_init();
timer_init();
+10 -1
View File
@@ -77,7 +77,7 @@ char *Analog_Input_Name(
return NULL;
}
static float Analog_Input_Present_Value(
float Analog_Input_Present_Value(
uint32_t object_instance)
{
float value = 0.0;
@@ -88,6 +88,15 @@ static float Analog_Input_Present_Value(
return value;
}
void Analog_Input_Present_Value_Set(
uint32_t object_instance,
float value)
{
if (object_instance < MAX_ANALOG_INPUTS) {
Present_Value[object_instance] = value;
}
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(