Updated some ARM and AVR ports projects which needed changes to API for some BACnet objects. Compiled with IAR ARM and AVR compiler.
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
// The following functions must be written in ARM mode
|
||||||
|
// these functions are called directly by an exception vector
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Internal functions
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Default spurious interrupt handler. Infinite loop.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void AT91F_Spurious_handler( void )
|
||||||
|
{
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Default handler for fast interrupt requests. Infinite loop.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void AT91F_Default_FIQ_handler( void )
|
||||||
|
{
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Default handler for standard interrupt requests. Infinite loop.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void AT91F_Default_IRQ_handler( void )
|
||||||
|
{
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
@@ -1985,9 +1985,66 @@
|
|||||||
<data/>
|
<data/>
|
||||||
</settings>
|
</settings>
|
||||||
</configuration>
|
</configuration>
|
||||||
<file>
|
<group>
|
||||||
<name>$PROJ_DIR$\..\..\src\abort.c</name>
|
<name>BACnet-Core</name>
|
||||||
</file>
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\abort.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\bacapp.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\bacdcode.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\bacerror.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\bacint.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\bacreal.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\bacstr.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\crc.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\iam.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\npdu.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\reject.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\rp.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\whois.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\src\wp.c</name>
|
||||||
|
</file>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<name>BACnet-Handlers</name>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\demo\handler\h_npdu.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\demo\handler\noserv.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\demo\handler\s_iam.c</name>
|
||||||
|
</file>
|
||||||
|
<file>
|
||||||
|
<name>$PROJ_DIR$\..\..\demo\handler\txbuf.c</name>
|
||||||
|
</file>
|
||||||
|
</group>
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\apdu.c</name>
|
<name>$PROJ_DIR$\apdu.c</name>
|
||||||
</file>
|
</file>
|
||||||
@@ -1997,39 +2054,15 @@
|
|||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\avr035.h</name>
|
<name>$PROJ_DIR$\avr035.h</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\bacapp.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\bacdcode.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\bacerror.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\bacint.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\bacreal.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\bacstr.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\bv.c</name>
|
<name>$PROJ_DIR$\bv.c</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\crc.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\device.c</name>
|
<name>$PROJ_DIR$\device.c</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\dlmstp.c</name>
|
<name>$PROJ_DIR$\dlmstp.c</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\demo\handler\h_npdu.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\h_rp.c</name>
|
<name>$PROJ_DIR$\h_rp.c</name>
|
||||||
</file>
|
</file>
|
||||||
@@ -2042,36 +2075,18 @@
|
|||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\hardware.h</name>
|
<name>$PROJ_DIR$\hardware.h</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\iam.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\iar2gcc.h</name>
|
<name>$PROJ_DIR$\iar2gcc.h</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\main.c</name>
|
<name>$PROJ_DIR$\main.c</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\demo\handler\noserv.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\npdu.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\reject.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\rp.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\rs485.c</name>
|
<name>$PROJ_DIR$\rs485.c</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\rs485.h</name>
|
<name>$PROJ_DIR$\rs485.h</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\demo\handler\s_iam.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\stack.c</name>
|
<name>$PROJ_DIR$\stack.c</name>
|
||||||
</file>
|
</file>
|
||||||
@@ -2081,15 +2096,6 @@
|
|||||||
<file>
|
<file>
|
||||||
<name>$PROJ_DIR$\timer.h</name>
|
<name>$PROJ_DIR$\timer.h</name>
|
||||||
</file>
|
</file>
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\demo\handler\txbuf.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\whois.c</name>
|
|
||||||
</file>
|
|
||||||
<file>
|
|
||||||
<name>$PROJ_DIR$\..\..\src\wp.c</name>
|
|
||||||
</file>
|
|
||||||
</project>
|
</project>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,34 +19,35 @@ BACNET_INCLUDE = ../../include
|
|||||||
BACNET_DEMO = ../../demo
|
BACNET_DEMO = ../../demo
|
||||||
|
|
||||||
# local files for this project
|
# local files for this project
|
||||||
CSRC = main.c \
|
CSRC = apdu.c \
|
||||||
timer.c \
|
device.c \
|
||||||
rs485.c \
|
|
||||||
dlmstp.c \
|
dlmstp.c \
|
||||||
apdu.c \
|
main.c \
|
||||||
$(BACNET_CORE)/crc.c
|
rs485.c \
|
||||||
|
timer.c
|
||||||
|
|
||||||
# common demo files needed
|
# common demo files needed
|
||||||
DEMOSRC = h_rp.c \
|
DEMOSRC =
|
||||||
device.c \
|
$(BACNET_DEMO)/handler/h_rp.c \
|
||||||
$(BACNET_DEMO)/handler/txbuf.c \
|
$(BACNET_DEMO)/handler/txbuf.c \
|
||||||
$(BACNET_DEMO)/handler/h_npdu.c \
|
$(BACNET_DEMO)/handler/h_npdu.c \
|
||||||
$(BACNET_DEMO)/handler/noserv.c
|
$(BACNET_DEMO)/handler/noserv.c
|
||||||
|
|
||||||
# core BACnet stack files
|
# core BACnet stack files - place into library
|
||||||
CORESRC = \
|
CORESRC = \
|
||||||
|
$(BACNET_CORE)/crc.c \
|
||||||
|
$(BACNET_CORE)/abort.c \
|
||||||
$(BACNET_CORE)/apdu.c \
|
$(BACNET_CORE)/apdu.c \
|
||||||
$(BACNET_CORE)/npdu.c \
|
$(BACNET_CORE)/bacapp.c \
|
||||||
$(BACNET_CORE)/bacdcode.c \
|
$(BACNET_CORE)/bacdcode.c \
|
||||||
|
$(BACNET_CORE)/bacerror.c \
|
||||||
$(BACNET_CORE)/bacint.c \
|
$(BACNET_CORE)/bacint.c \
|
||||||
$(BACNET_CORE)/bacreal.c \
|
$(BACNET_CORE)/bacreal.c \
|
||||||
$(BACNET_CORE)/bacstr.c \
|
$(BACNET_CORE)/bacstr.c \
|
||||||
$(BACNET_CORE)/rp.c \
|
|
||||||
$(BACNET_CORE)/bacaddr.c \
|
$(BACNET_CORE)/bacaddr.c \
|
||||||
$(BACNET_CORE)/abort.c \
|
$(BACNET_CORE)/npdu.c \
|
||||||
$(BACNET_CORE)/reject.c \
|
$(BACNET_CORE)/reject.c \
|
||||||
$(BACNET_CORE)/bacerror.c \
|
$(BACNET_CORE)/rp.c
|
||||||
$(BACNET_CORE)/bacapp.c
|
|
||||||
|
|
||||||
# $(BACNET_CORE)/iam.c \
|
# $(BACNET_CORE)/iam.c \
|
||||||
# $(BACNET_CORE)/whois.c \
|
# $(BACNET_CORE)/whois.c \
|
||||||
|
|||||||
@@ -1,163 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 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 Input Objects customize for your use */
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "bacdef.h"
|
|
||||||
#include "bacdcode.h"
|
|
||||||
#include "bacenum.h"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
/* Analog Input = Photocell */
|
|
||||||
#define MAX_ANALOG_INPUTS 9
|
|
||||||
#if (MAX_ANALOG_INPUTS > 9)
|
|
||||||
#error Modify the Analog_Input_Name to handle multiple digits
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (object_instance < MAX_ANALOG_INPUTS)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we simply have 0-n object instances. */
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we simply have 0-n object instances. */
|
|
||||||
unsigned Analog_Input_Instance_To_Index(
|
|
||||||
uint32_t object_instance)
|
|
||||||
{
|
|
||||||
return object_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *Analog_Input_Name(
|
|
||||||
uint32_t object_instance)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
return text_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return apdu length, or -1 on error */
|
|
||||||
/* assumption - object has already exists */
|
|
||||||
int Analog_Input_Encode_Property_APDU(
|
|
||||||
uint8_t * apdu,
|
|
||||||
uint32_t object_instance,
|
|
||||||
BACNET_PROPERTY_ID property,
|
|
||||||
uint32_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;
|
|
||||||
unsigned object_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;
|
|
||||||
}
|
|
||||||
/* only array properties can have array options */
|
|
||||||
if ((apdu_len >= 0) && (array_index != BACNET_ARRAY_ALL)) {
|
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
|
||||||
apdu_len = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apdu_len;
|
|
||||||
}
|
|
||||||
@@ -1,264 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
*
|
|
||||||
* 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 "hardware.h"
|
|
||||||
#include "bacdef.h"
|
|
||||||
#include "bacdcode.h"
|
|
||||||
#include "bacenum.h"
|
|
||||||
#include "bacapp.h"
|
|
||||||
#include "config.h" /* the custom stuff */
|
|
||||||
#include "wp.h"
|
|
||||||
#include "av.h"
|
|
||||||
|
|
||||||
#if (MAX_ANALOG_VALUES > 10)
|
|
||||||
#error Modify the Analog_Value_Name to handle multiple digits
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float AV_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)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
return object_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* note: the object name must be unique within this device */
|
|
||||||
char *Analog_Value_Name(
|
|
||||||
uint32_t object_instance)
|
|
||||||
{
|
|
||||||
static char text_string[5] = "AV-"; /* okay for single thread */
|
|
||||||
|
|
||||||
text_string[3] = '0' + (uint8_t) object_instance;
|
|
||||||
|
|
||||||
return text_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return apdu len, or -1 on error */
|
|
||||||
int Analog_Value_Encode_Property_APDU(
|
|
||||||
uint8_t * apdu,
|
|
||||||
uint32_t object_instance,
|
|
||||||
BACNET_PROPERTY_ID property,
|
|
||||||
uint32_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;
|
|
||||||
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:
|
|
||||||
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],
|
|
||||||
AV_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;
|
|
||||||
}
|
|
||||||
/* only array properties can have array options */
|
|
||||||
if ((apdu_len >= 0) && (array_index != BACNET_ARRAY_ALL)) {
|
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
|
||||||
apdu_len = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
|
||||||
unsigned int object_index = 0;
|
|
||||||
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? */
|
|
||||||
if (len < 0) {
|
|
||||||
/* error while decoding - a value larger than we can handle */
|
|
||||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
AV_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_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 */
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
|
||||||
|
<workspace>
|
||||||
|
<project>
|
||||||
|
<path>$WS_DIR$\bacnet.ewp</path>
|
||||||
|
</project>
|
||||||
|
<batchBuild/>
|
||||||
|
</workspace>
|
||||||
|
|
||||||
|
|
||||||
@@ -1,313 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*********************************************************************/
|
|
||||||
|
|
||||||
/* Binary Value Objects - customize for your use */
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "hardware.h"
|
|
||||||
#include "bacdef.h"
|
|
||||||
#include "bacdcode.h"
|
|
||||||
#include "bacenum.h"
|
|
||||||
#include "config.h" /* the custom stuff */
|
|
||||||
#include "wp.h"
|
|
||||||
#include "bv.h"
|
|
||||||
|
|
||||||
#if (MAX_BINARY_VALUES > 10)
|
|
||||||
#error Modify the Binary_Value_Name to handle multiple digits
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_VALUES];
|
|
||||||
|
|
||||||
/* we simply have 0-n object instances. */
|
|
||||||
bool Binary_Value_Valid_Instance(
|
|
||||||
uint32_t object_instance)
|
|
||||||
{
|
|
||||||
if (object_instance < MAX_BINARY_VALUES)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we simply have 0-n object instances. */
|
|
||||||
unsigned Binary_Value_Count(
|
|
||||||
void)
|
|
||||||
{
|
|
||||||
return MAX_BINARY_VALUES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we simply have 0-n object instances. */
|
|
||||||
uint32_t Binary_Value_Index_To_Instance(
|
|
||||||
unsigned index)
|
|
||||||
{
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we simply have 0-n object instances. */
|
|
||||||
unsigned Binary_Value_Instance_To_Index(
|
|
||||||
uint32_t object_instance)
|
|
||||||
{
|
|
||||||
unsigned index = MAX_BINARY_VALUES;
|
|
||||||
|
|
||||||
if (object_instance < MAX_BINARY_VALUES)
|
|
||||||
index = object_instance;
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BACNET_BINARY_PV Binary_Value_Present_Value(
|
|
||||||
uint32_t object_instance)
|
|
||||||
{
|
|
||||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
|
||||||
|
|
||||||
if (object_instance < MAX_BINARY_VALUES) {
|
|
||||||
value = Present_Value[object_instance];
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* note: the object name must be unique within this device */
|
|
||||||
char *Binary_Value_Name(
|
|
||||||
uint32_t object_instance)
|
|
||||||
{
|
|
||||||
static char text_string[5] = "BV-0"; /* okay for single thread */
|
|
||||||
|
|
||||||
if (object_instance < MAX_BINARY_VALUES) {
|
|
||||||
text_string[3] = '0' + (uint8_t) object_instance;
|
|
||||||
return text_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return apdu len, or -1 on error */
|
|
||||||
int Binary_Value_Encode_Property_APDU(
|
|
||||||
uint8_t * apdu,
|
|
||||||
uint32_t object_instance,
|
|
||||||
BACNET_PROPERTY_ID property,
|
|
||||||
uint32_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;
|
|
||||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
|
||||||
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
|
||||||
|
|
||||||
switch (property) {
|
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
|
||||||
apdu_len =
|
|
||||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
|
|
||||||
object_instance);
|
|
||||||
break;
|
|
||||||
/* note: Name and Description don't have to be the same.
|
|
||||||
You could make Description writable and different */
|
|
||||||
case PROP_OBJECT_NAME:
|
|
||||||
characterstring_init_ansi(&char_string,
|
|
||||||
Binary_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_BINARY_VALUE);
|
|
||||||
break;
|
|
||||||
case PROP_PRESENT_VALUE:
|
|
||||||
present_value = Binary_Value_Present_Value(object_instance);
|
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
|
||||||
break;
|
|
||||||
case PROP_STATUS_FLAGS:
|
|
||||||
/* note: see the details in the standard on how to use these */
|
|
||||||
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:
|
|
||||||
/* note: see the details in the standard on how to use this */
|
|
||||||
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_POLARITY:
|
|
||||||
/* FIXME: figure out the polarity */
|
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], polarity);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
|
||||||
apdu_len = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* only array properties can have array options */
|
|
||||||
if ((apdu_len >= 0) && (array_index != BACNET_ARRAY_ALL)) {
|
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
|
||||||
apdu_len = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apdu_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* returns true if successful */
|
|
||||||
bool Binary_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;
|
|
||||||
int len = 0;
|
|
||||||
BACNET_APPLICATION_DATA_VALUE value;
|
|
||||||
|
|
||||||
if (!Binary_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? */
|
|
||||||
if (len < 0) {
|
|
||||||
/* error while decoding - a value larger than we can handle */
|
|
||||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch (wp_data->object_property) {
|
|
||||||
case PROP_PRESENT_VALUE:
|
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
|
|
||||||
if ((value.type.Enumerated == BINARY_ACTIVE) ||
|
|
||||||
(value.type.Enumerated == BINARY_INACTIVE)) {
|
|
||||||
object_index =
|
|
||||||
Binary_Value_Instance_To_Index
|
|
||||||
(wp_data->object_instance);
|
|
||||||
/* NOTE: this Binary value has no priority array */
|
|
||||||
Present_Value[object_index] =
|
|
||||||
(BACNET_BINARY_PV) value.type.Enumerated;
|
|
||||||
/* 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. */
|
|
||||||
if (Present_Value[0] == BINARY_ACTIVE) {
|
|
||||||
LED_GREEN_ON();
|
|
||||||
} else {
|
|
||||||
LED_GREEN_OFF();
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
#if 0
|
|
||||||
case PROP_OUT_OF_SERVICE:
|
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
|
||||||
object_index =
|
|
||||||
Binary_Value_Instance_To_Index(wp_data->object_instance);
|
|
||||||
Binary_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 testBinary_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_BINARY_VALUE;
|
|
||||||
uint32_t decoded_instance = 0;
|
|
||||||
uint32_t instance = 123;
|
|
||||||
BACNET_ERROR_CLASS error_class;
|
|
||||||
BACNET_ERROR_CODE error_code;
|
|
||||||
|
|
||||||
|
|
||||||
len =
|
|
||||||
Binary_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_BINARY_VALUE);
|
|
||||||
ct_test(pTest, decoded_instance == instance);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST_BINARY_VALUE
|
|
||||||
int main(
|
|
||||||
void)
|
|
||||||
{
|
|
||||||
Test *pTest;
|
|
||||||
bool rc;
|
|
||||||
|
|
||||||
pTest = ct_create("BACnet Binary_Value", NULL);
|
|
||||||
/* individual tests */
|
|
||||||
rc = ct_addTestFunction(pTest, testBinary_Value);
|
|
||||||
assert(rc);
|
|
||||||
|
|
||||||
ct_setStream(pTest, stdout);
|
|
||||||
ct_run(pTest);
|
|
||||||
(void) ct_report(pTest);
|
|
||||||
ct_destroy(pTest);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif /* TEST_BINARY_VALUE */
|
|
||||||
#endif /* TEST */
|
|
||||||
@@ -169,13 +169,8 @@ bool Device_Object_List_Identifier(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* return the length of the apdu encoded or -1 for error */
|
/* return the length of the apdu encoded or -1 for error */
|
||||||
int Device_Encode_Property_APDU(
|
int Device_Read_Property(
|
||||||
uint8_t * apdu,
|
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||||
uint32_t object_instance,
|
|
||||||
BACNET_PROPERTY_ID property,
|
|
||||||
uint32_t array_index,
|
|
||||||
BACNET_ERROR_CLASS * error_class,
|
|
||||||
BACNET_ERROR_CODE * error_code)
|
|
||||||
{
|
{
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
int len = 0; /* apdu len intermediate value */
|
int len = 0; /* apdu len intermediate value */
|
||||||
@@ -185,14 +180,19 @@ int Device_Encode_Property_APDU(
|
|||||||
int object_type = 0;
|
int object_type = 0;
|
||||||
uint32_t instance = 0;
|
uint32_t instance = 0;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
uint8_t *apdu = NULL;
|
||||||
|
|
||||||
object_instance = object_instance;
|
if ((rpdata->application_data == NULL) ||
|
||||||
|
(rpdata->application_data_len == 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
apdu = rpdata->application_data;
|
||||||
/* FIXME: change the hardcoded names to suit your application */
|
/* FIXME: change the hardcoded names to suit your application */
|
||||||
switch (property) {
|
switch ((int) rpdata->object_property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
case PROP_OBJECT_IDENTIFIER:
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
encode_application_object_id(&apdu[0], rpdata->object_type,
|
||||||
Object_Instance_Number);
|
rpdata->object_instance);
|
||||||
break;
|
break;
|
||||||
case PROP_OBJECT_NAME:
|
case PROP_OBJECT_NAME:
|
||||||
characterstring_init_ansi(&char_string, Object_Name);
|
characterstring_init_ansi(&char_string, Object_Name);
|
||||||
@@ -271,13 +271,13 @@ int Device_Encode_Property_APDU(
|
|||||||
case PROP_OBJECT_LIST:
|
case PROP_OBJECT_LIST:
|
||||||
count = Device_Object_List_Count();
|
count = Device_Object_List_Count();
|
||||||
/* Array element zero is the number of objects in the list */
|
/* Array element zero is the number of objects in the list */
|
||||||
if (array_index == 0)
|
if (rpdata->array_index == 0)
|
||||||
apdu_len = encode_application_unsigned(&apdu[0], count);
|
apdu_len = encode_application_unsigned(&apdu[0], count);
|
||||||
/* if no index was specified, then try to encode the entire list */
|
/* if no index was specified, then try to encode the entire list */
|
||||||
/* into one packet. Note that more than likely you will have */
|
/* into one packet. Note that more than likely you will have */
|
||||||
/* to return an error if the number of encoded objects exceeds */
|
/* to return an error if the number of encoded objects exceeds */
|
||||||
/* your maximum APDU size. */
|
/* your maximum APDU size. */
|
||||||
else if (array_index == BACNET_ARRAY_ALL) {
|
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||||
for (i = 1; i <= count; i++) {
|
for (i = 1; i <= count; i++) {
|
||||||
Device_Object_List_Identifier(i, &object_type, &instance);
|
Device_Object_List_Identifier(i, &object_type, &instance);
|
||||||
len =
|
len =
|
||||||
@@ -287,21 +287,22 @@ int Device_Encode_Property_APDU(
|
|||||||
/* assume next one is the same size as this one */
|
/* assume next one is the same size as this one */
|
||||||
/* can we all fit into the APDU? */
|
/* can we all fit into the APDU? */
|
||||||
if ((apdu_len + len) >= MAX_APDU) {
|
if ((apdu_len + len) >= MAX_APDU) {
|
||||||
*error_code =
|
rpdata->error_code =
|
||||||
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
|
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
|
||||||
apdu_len = BACNET_STATUS_ABORT;
|
apdu_len = BACNET_STATUS_ABORT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
if (Device_Object_List_Identifier(rpdata->array_index,
|
||||||
|
&object_type,
|
||||||
&instance))
|
&instance))
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_object_id(&apdu[0], object_type,
|
encode_application_object_id(&apdu[0], object_type,
|
||||||
instance);
|
instance);
|
||||||
else {
|
else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||||
apdu_len = BACNET_STATUS_ERROR;
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,16 +327,16 @@ int Device_Encode_Property_APDU(
|
|||||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
apdu_len = -1;
|
apdu_len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* only array properties can have array options */
|
/* only array properties can have array options */
|
||||||
if ((apdu_len >= 0) && (property != PROP_OBJECT_LIST) &&
|
if ((apdu_len >= 0) && (rpdata->object_property != PROP_OBJECT_LIST) &&
|
||||||
(array_index != BACNET_ARRAY_ALL)) {
|
(rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||||
apdu_len = BACNET_STATUS_ERROR;
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
|
#include "mstpdef.h"
|
||||||
#include "dlmstp.h"
|
#include "dlmstp.h"
|
||||||
#include "rs485.h"
|
#include "rs485.h"
|
||||||
#include "crc.h"
|
#include "crc.h"
|
||||||
@@ -44,6 +45,8 @@
|
|||||||
#include "bits.h"
|
#include "bits.h"
|
||||||
#include "bytes.h"
|
#include "bytes.h"
|
||||||
#include "bacaddr.h"
|
#include "bacaddr.h"
|
||||||
|
/* special optimization - I-Am response in this module */
|
||||||
|
#include "client.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* This file has been customized for use with small microprocessors */
|
/* This file has been customized for use with small microprocessors */
|
||||||
@@ -53,46 +56,16 @@
|
|||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
/* The value 255 is used to denote broadcast when used as a */
|
|
||||||
/* destination address but is not allowed as a value for a station. */
|
|
||||||
/* Station addresses for master nodes can be 0-127. */
|
|
||||||
/* Station addresses for slave nodes can be 127-254. */
|
|
||||||
#define MSTP_BROADCAST_ADDRESS 255
|
|
||||||
|
|
||||||
/* MS/TP Frame Type */
|
|
||||||
/* Frame Types 8 through 127 are reserved by ASHRAE. */
|
|
||||||
#define FRAME_TYPE_TOKEN 0
|
|
||||||
#define FRAME_TYPE_POLL_FOR_MASTER 1
|
|
||||||
#define FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER 2
|
|
||||||
#define FRAME_TYPE_TEST_REQUEST 3
|
|
||||||
#define FRAME_TYPE_TEST_RESPONSE 4
|
|
||||||
#define FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY 5
|
|
||||||
#define FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY 6
|
|
||||||
#define FRAME_TYPE_REPLY_POSTPONED 7
|
|
||||||
/* Frame Types 128 through 255: Proprietary Frames */
|
|
||||||
/* These frames are available to vendors as proprietary (non-BACnet) frames. */
|
|
||||||
/* The first two octets of the Data field shall specify the unique vendor */
|
|
||||||
/* identification code, most significant octet first, for the type of */
|
|
||||||
/* vendor-proprietary frame to be conveyed. The length of the data portion */
|
|
||||||
/* of a Proprietary frame shall be in the range of 2 to 501 octets. */
|
|
||||||
#define FRAME_TYPE_PROPRIETARY_MIN 128
|
|
||||||
#define FRAME_TYPE_PROPRIETARY_MAX 255
|
|
||||||
|
|
||||||
/* receive FSM states */
|
|
||||||
typedef enum {
|
|
||||||
MSTP_RECEIVE_STATE_IDLE = 0,
|
|
||||||
MSTP_RECEIVE_STATE_PREAMBLE = 1,
|
|
||||||
MSTP_RECEIVE_STATE_HEADER = 2,
|
|
||||||
MSTP_RECEIVE_STATE_DATA = 3
|
|
||||||
} MSTP_RECEIVE_STATE;
|
|
||||||
|
|
||||||
/* The state of the Receive State Machine */
|
/* The state of the Receive State Machine */
|
||||||
static MSTP_RECEIVE_STATE Receive_State;
|
static MSTP_RECEIVE_STATE Receive_State;
|
||||||
static struct mstp_flag_t {
|
static struct mstp_flag_t {
|
||||||
/* A Boolean flag set to TRUE by the Receive State Machine */
|
/* A Boolean flag set to TRUE by the Receive State Machine */
|
||||||
/* if an invalid or valid frame is received. */
|
/* if an invalid frame is received. */
|
||||||
/* Set to FALSE by the main state machine. */
|
/* Set to FALSE by the main state machine. */
|
||||||
unsigned ReceivedInvalidFrame:1;
|
unsigned ReceivedInvalidFrame:1;
|
||||||
|
/* A Boolean flag set to TRUE by the Receive State Machine */
|
||||||
|
/* if a valid frame is received. */
|
||||||
|
/* Set to FALSE by the main state machine. */
|
||||||
unsigned ReceivedValidFrame:1;
|
unsigned ReceivedValidFrame:1;
|
||||||
/* A Boolean flag set TRUE by the datalink transmit if a
|
/* A Boolean flag set TRUE by the datalink transmit if a
|
||||||
frame is pending */
|
frame is pending */
|
||||||
@@ -118,7 +91,7 @@ struct mstp_packet_info_t {
|
|||||||
uint8_t buffer_len; /* buffer to put the data */
|
uint8_t buffer_len; /* buffer to put the data */
|
||||||
uint8_t index; /* index into receive buffer */
|
uint8_t index; /* index into receive buffer */
|
||||||
};
|
};
|
||||||
static struct nitoo_packet_info_t MSTP_Receive_Packet;
|
static struct mstp_packet_info_t MSTP_Receive_Packet;
|
||||||
|
|
||||||
/* Used to store the data length of a received frame. */
|
/* Used to store the data length of a received frame. */
|
||||||
static uint16_t DataLength;
|
static uint16_t DataLength;
|
||||||
@@ -160,24 +133,11 @@ static uint8_t TransmitPacketDest;
|
|||||||
/* const uint16_t Tframe_abort = 1 + ((1000 * 60) / 9600); */
|
/* const uint16_t Tframe_abort = 1 + ((1000 * 60) / 9600); */
|
||||||
#define Tframe_abort 30
|
#define Tframe_abort 30
|
||||||
|
|
||||||
/* The maximum idle time a sending node may allow to elapse between octets */
|
|
||||||
/* of a frame the node is transmitting: 20 bit times. */
|
|
||||||
#define Tframe_gap 20
|
|
||||||
|
|
||||||
/* The maximum time a node may wait after reception of a frame that expects */
|
/* The maximum time a node may wait after reception of a frame that expects */
|
||||||
/* a reply before sending the first octet of a reply or Reply Postponed */
|
/* a reply before sending the first octet of a reply or Reply Postponed */
|
||||||
/* frame: 250 milliseconds. */
|
/* frame: 250 milliseconds. */
|
||||||
#define Treply_delay 250
|
#define Treply_delay 250
|
||||||
|
|
||||||
/* The width of the time slot within which a node may generate a token: */
|
|
||||||
/* 10 milliseconds. */
|
|
||||||
#define Tslot 10
|
|
||||||
|
|
||||||
/* The maximum time a node may wait after reception of the token or */
|
|
||||||
/* a Poll For Master frame before sending the first octet of a frame: */
|
|
||||||
/* 15 milliseconds. */
|
|
||||||
#define Tusage_delay 15
|
|
||||||
|
|
||||||
/* we need to be able to increment without rolling over */
|
/* we need to be able to increment without rolling over */
|
||||||
#define INCREMENT_AND_LIMIT_UINT8(x) {if (x < 0xFF) x++;}
|
#define INCREMENT_AND_LIMIT_UINT8(x) {if (x < 0xFF) x++;}
|
||||||
|
|
||||||
@@ -257,6 +217,7 @@ static void MSTP_Send_Frame(
|
|||||||
crc8 = CRC_Calc_Header(buffer[3], crc8);
|
crc8 = CRC_Calc_Header(buffer[3], crc8);
|
||||||
buffer[4] = source;
|
buffer[4] = source;
|
||||||
crc8 = CRC_Calc_Header(buffer[4], crc8);
|
crc8 = CRC_Calc_Header(buffer[4], crc8);
|
||||||
|
|
||||||
buffer[5] = HI_BYTE(pdu_len);
|
buffer[5] = HI_BYTE(pdu_len);
|
||||||
crc8 = CRC_Calc_Header(buffer[5], crc8);
|
crc8 = CRC_Calc_Header(buffer[5], crc8);
|
||||||
buffer[6] = LO_BYTE(pdu_len);
|
buffer[6] = LO_BYTE(pdu_len);
|
||||||
@@ -283,116 +244,6 @@ static void MSTP_Send_Frame(
|
|||||||
RS485_Transmitter_Enable(false);
|
RS485_Transmitter_Enable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* return true if the packet is good. */
|
|
||||||
/* note: buffer should include the CRC as the last byte */
|
|
||||||
static bool crc_header_good(
|
|
||||||
uint8_t * buffer,
|
|
||||||
uint8_t len)
|
|
||||||
{
|
|
||||||
uint8_t i; /* loop counter */
|
|
||||||
uint8_t crc8 = 0xFF; /* loop counter */
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
crc8 = CRC_Calc_Header(buffer[i], crc8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (crc8 == 0x55);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void mstp_receive_handler(
|
|
||||||
void)
|
|
||||||
{
|
|
||||||
uint8_t data_register = 0; /* data from UART */
|
|
||||||
|
|
||||||
if (RS485_ReceiveError()) {
|
|
||||||
timer_silence_reset();
|
|
||||||
} else if (RS485_DataAvailable(&data_register)) {
|
|
||||||
timer_silence_reset();
|
|
||||||
if ((MSTP_Receive_Packet.preamble1 == false) &&
|
|
||||||
(data_register == 0x55)) {
|
|
||||||
MSTP_Receive_Packet.preamble1 = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((MSTP_Receive_Packet.preamble2 == false) &&
|
|
||||||
(MSTP_Receive_Packet.preamble1 == true)) {
|
|
||||||
if (data_register == 0xFF) {
|
|
||||||
MSTP_Receive_Packet.preamble2 = true;
|
|
||||||
MSTP_Receive_Packet.index = 0;
|
|
||||||
MSTP_Receive_Packet.data_len = 0;
|
|
||||||
} else if (data_register == 0x55) {
|
|
||||||
/* repeated preamble1 */
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
MSTP_Receive_Packet.preamble1 = false;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (DataLength == 0) {
|
|
||||||
MSTP_Receive_Packet.header[MSTP_Receive_Packet.index] =
|
|
||||||
data_register;
|
|
||||||
if (MSTP_Receive_Packet.index == 5) {
|
|
||||||
if (crc_header_good(MSTP_Receive_Packet.header, 6)) {
|
|
||||||
FrameType = MSTP_Receive_Packet.header[0];
|
|
||||||
DestinationAddress = MSTP_Receive_Packet.header[1];
|
|
||||||
SourceAddress = MSTP_Receive_Packet.header[2];
|
|
||||||
DataLength =
|
|
||||||
(MSTP_Receive_Packet.header[3] * 256) +
|
|
||||||
MSTP_Receive_Packet.header[4];
|
|
||||||
if (DataLength == 0) {
|
|
||||||
MSTP_Receive_Packet.valid_frame = true;
|
|
||||||
} else {
|
|
||||||
MSTP_Receive_Packet.index = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MSTP_Receive_Packet.preamble2 = false;
|
|
||||||
MSTP_Receive_Packet.preamble2 = false;
|
|
||||||
MSTP_Receive_Packet.index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MSTP_Receive_Packet.buffer[MSTP_Receive_Packet.index] =
|
|
||||||
data_register;
|
|
||||||
if (packet_info->index == packet_info->len) {
|
|
||||||
/* PDU length ended */
|
|
||||||
packet_info->ready = true;
|
|
||||||
} else if (packet_info->index >= sizeof(packet_info->buffer)) {
|
|
||||||
/* exceeded the size of the storage */
|
|
||||||
packet_info->len = packet_info->index;
|
|
||||||
packet_info->ready = true;
|
|
||||||
} else {
|
|
||||||
packet_info->index++;
|
|
||||||
}
|
|
||||||
MSTP_Receive_Packet.index++;
|
|
||||||
if (packet_info->ready) {
|
|
||||||
/* validate the CRC */
|
|
||||||
if (!lrc_packet_good(packet_info->buffer,
|
|
||||||
packet_info->len + 1)) {
|
|
||||||
packet_info->ready = false;
|
|
||||||
}
|
|
||||||
/* pull off the CRC */
|
|
||||||
packet_info->crc = packet_info->buffer[packet_info->len];
|
|
||||||
/* get ready for the next packet */
|
|
||||||
packet_info->index = 0;
|
|
||||||
packet_info->preamble1 = false;
|
|
||||||
packet_info->preamble2 = false;
|
|
||||||
led_setup_off();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ReceivePreamble1 == true) {
|
|
||||||
if (timer_silence_elapsed(Tframe_abort)) {
|
|
||||||
/* we've been busy too long! Abort packet! */
|
|
||||||
Index = 0;
|
|
||||||
ReceivePreamble1 = false;
|
|
||||||
ReceivePreamble2 = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void MSTP_Receive_Frame_FSM(
|
static void MSTP_Receive_Frame_FSM(
|
||||||
void)
|
void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,173 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 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 <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "txbuf.h"
|
|
||||||
#include "bacdef.h"
|
|
||||||
#include "bacdcode.h"
|
|
||||||
#include "bacerror.h"
|
|
||||||
#include "apdu.h"
|
|
||||||
#include "npdu.h"
|
|
||||||
#include "abort.h"
|
|
||||||
#include "rp.h"
|
|
||||||
/* demo objects */
|
|
||||||
#include "device.h"
|
|
||||||
#if MAX_ANALOG_VALUES
|
|
||||||
#include "av.h"
|
|
||||||
#endif
|
|
||||||
#if MAX_BINARY_VALUES
|
|
||||||
#include "bv.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Encodes the property APDU and returns the length,
|
|
||||||
or sets the error, and returns -1 */
|
|
||||||
int Encode_Property_APDU(
|
|
||||||
uint8_t * apdu,
|
|
||||||
BACNET_READ_PROPERTY_DATA * rp_data,
|
|
||||||
BACNET_ERROR_CLASS * error_class,
|
|
||||||
BACNET_ERROR_CODE * error_code)
|
|
||||||
{
|
|
||||||
int apdu_len = -1;
|
|
||||||
|
|
||||||
/* handle each object type */
|
|
||||||
switch (rp_data->object_type) {
|
|
||||||
case OBJECT_DEVICE:
|
|
||||||
if (Device_Valid_Object_Instance_Number(rp_data->object_instance)) {
|
|
||||||
apdu_len =
|
|
||||||
Device_Encode_Property_APDU(&apdu[0],
|
|
||||||
rp_data->object_instance, rp_data->object_property,
|
|
||||||
rp_data->array_index, error_class, error_code);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#if MAX_ANALOG_VALUES
|
|
||||||
case OBJECT_ANALOG_VALUE:
|
|
||||||
if (Analog_Value_Valid_Instance(rp_data->object_instance)) {
|
|
||||||
apdu_len =
|
|
||||||
Analog_Value_Encode_Property_APDU(&apdu[0],
|
|
||||||
rp_data->object_instance, rp_data->object_property,
|
|
||||||
rp_data->array_index, error_class, error_code);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if MAX_BINARY_VALUES
|
|
||||||
case OBJECT_BINARY_VALUE:
|
|
||||||
if (Binary_Value_Valid_Instance(rp_data->object_instance)) {
|
|
||||||
apdu_len =
|
|
||||||
Binary_Value_Encode_Property_APDU(&apdu[0],
|
|
||||||
rp_data->object_instance, rp_data->object_property,
|
|
||||||
rp_data->array_index, error_class, error_code);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
*error_class = ERROR_CLASS_OBJECT;
|
|
||||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return apdu_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void handler_read_property(
|
|
||||||
uint8_t * service_request,
|
|
||||||
uint16_t service_len,
|
|
||||||
BACNET_ADDRESS * src,
|
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
|
||||||
{
|
|
||||||
BACNET_READ_PROPERTY_DATA data;
|
|
||||||
int len = 0;
|
|
||||||
int ack_len = 0;
|
|
||||||
int property_len = 0;
|
|
||||||
int pdu_len = 0;
|
|
||||||
BACNET_NPDU_DATA npdu_data;
|
|
||||||
int bytes_sent = 0;
|
|
||||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
|
||||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
|
||||||
BACNET_ADDRESS my_address;
|
|
||||||
|
|
||||||
/* encode the NPDU portion of the packet */
|
|
||||||
datalink_get_my_address(&my_address);
|
|
||||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
|
||||||
pdu_len =
|
|
||||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
|
||||||
&npdu_data);
|
|
||||||
if (service_data->segmented_message) {
|
|
||||||
/* we don't support segmentation - send an abort */
|
|
||||||
len =
|
|
||||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
|
||||||
true);
|
|
||||||
goto RP_ABORT;
|
|
||||||
}
|
|
||||||
len = rp_decode_service_request(service_request, service_len, &data);
|
|
||||||
if (len < 0) {
|
|
||||||
/* bad decoding - send an abort */
|
|
||||||
len =
|
|
||||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
|
||||||
goto RP_ABORT;
|
|
||||||
}
|
|
||||||
/* most cases will be error */
|
|
||||||
ack_len =
|
|
||||||
rp_ack_encode_apdu_init(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id, &data);
|
|
||||||
/* FIXME: add buffer len as passed into function or use smart buffer */
|
|
||||||
property_len =
|
|
||||||
Encode_Property_APDU(&Handler_Transmit_Buffer[pdu_len + ack_len],
|
|
||||||
&data, &error_class, &error_code);
|
|
||||||
if (property_len >= 0) {
|
|
||||||
len =
|
|
||||||
rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
|
|
||||||
[pdu_len + property_len + ack_len]);
|
|
||||||
len += ack_len + property_len;
|
|
||||||
} else {
|
|
||||||
switch (property_len) {
|
|
||||||
/* BACnet APDU too small to fit data, so proper response is Abort */
|
|
||||||
case BACNET_STATUS_ABORT:
|
|
||||||
len =
|
|
||||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id,
|
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
len =
|
|
||||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
|
||||||
error_class, error_code);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RP_ABORT:
|
|
||||||
pdu_len += len;
|
|
||||||
bytes_sent =
|
|
||||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
|
||||||
pdu_len);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 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 <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "txbuf.h"
|
|
||||||
#include "bacdef.h"
|
|
||||||
#include "bacdcode.h"
|
|
||||||
#include "whois.h"
|
|
||||||
#include "iam.h"
|
|
||||||
#include "device.h"
|
|
||||||
#include "client.h"
|
|
||||||
#include "txbuf.h"
|
|
||||||
|
|
||||||
bool Send_I_Am = true;
|
|
||||||
|
|
||||||
void handler_who_is(
|
|
||||||
uint8_t * service_request,
|
|
||||||
uint16_t service_len,
|
|
||||||
BACNET_ADDRESS * src)
|
|
||||||
{
|
|
||||||
int len = 0;
|
|
||||||
int32_t low_limit = 0;
|
|
||||||
int32_t high_limit = 0;
|
|
||||||
int32_t target_device;
|
|
||||||
|
|
||||||
(void) src;
|
|
||||||
len =
|
|
||||||
whois_decode_service_request(service_request, service_len, &low_limit,
|
|
||||||
&high_limit);
|
|
||||||
if (len == 0) {
|
|
||||||
Send_I_Am = true;
|
|
||||||
} 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))
|
|
||||||
||
|
|
||||||
/* BACnet wildcard is the max instance number - everyone responds */
|
|
||||||
((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) &&
|
|
||||||
(BACNET_MAX_INSTANCE <= (uint32_t) high_limit))) {
|
|
||||||
Send_I_Am = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
/**************************************************************************
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 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 <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "txbuf.h"
|
|
||||||
#include "bacdef.h"
|
|
||||||
#include "bacdcode.h"
|
|
||||||
#include "bacerror.h"
|
|
||||||
#include "apdu.h"
|
|
||||||
#include "npdu.h"
|
|
||||||
#include "abort.h"
|
|
||||||
#include "wp.h"
|
|
||||||
/* demo objects */
|
|
||||||
#include "device.h"
|
|
||||||
#include "av.h"
|
|
||||||
#include "bv.h"
|
|
||||||
|
|
||||||
/* too big to reside on stack frame for PIC */
|
|
||||||
static BACNET_WRITE_PROPERTY_DATA wp_data;
|
|
||||||
|
|
||||||
void handler_write_property(
|
|
||||||
uint8_t * service_request,
|
|
||||||
uint16_t service_len,
|
|
||||||
BACNET_ADDRESS * src,
|
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
|
||||||
{
|
|
||||||
int len = 0;
|
|
||||||
int pdu_len = 0;
|
|
||||||
BACNET_NPDU_DATA npdu_data;
|
|
||||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
|
||||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
|
||||||
int bytes_sent = 0;
|
|
||||||
BACNET_ADDRESS my_address;
|
|
||||||
|
|
||||||
/* decode the service request only */
|
|
||||||
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);
|
|
||||||
pdu_len =
|
|
||||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
|
||||||
&npdu_data);
|
|
||||||
/* bad decoding or something we didn't understand - send an abort */
|
|
||||||
if (len <= 0) {
|
|
||||||
len =
|
|
||||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
|
||||||
} else if (service_data->segmented_message) {
|
|
||||||
len =
|
|
||||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
|
||||||
true);
|
|
||||||
} else {
|
|
||||||
switch (wp_data.object_type) {
|
|
||||||
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_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;
|
|
||||||
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;
|
|
||||||
default:
|
|
||||||
len =
|
|
||||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
|
||||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
|
||||||
error_class, error_code);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pdu_len += len;
|
|
||||||
bytes_sent =
|
|
||||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
|
||||||
pdu_len);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -32,9 +32,17 @@
|
|||||||
|
|
||||||
#if defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ASM__)
|
#if defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ASM__)
|
||||||
#include <iom168.h>
|
#include <iom168.h>
|
||||||
|
#define WATCHDOG_INIT() {BIT_CLEAR(MCUSR, WDRF); WDTCSR = 0;}
|
||||||
#else
|
#else
|
||||||
#if !defined(__AVR_ATmega168__)
|
#if !defined(__AVR_ATmega168__)
|
||||||
#error Firmware is configured for ATmega168 only (-mmcu=atmega168)
|
#error Firmware is configured for ATmega168 only (-mmcu=atmega168)
|
||||||
|
|
||||||
|
#if defined(__AVR_ATmega168__)
|
||||||
|
#define WATCHDOG_INIT() {BIT_CLEAR(MCUSR, WDRF); WDTCSR = 0;}
|
||||||
|
#else
|
||||||
|
#define WATCHDOG_INIT() {BIT_CLEAR(MCUCSR, WDRF); WDTCR = 0;}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#include "iar2gcc.h"
|
#include "iar2gcc.h"
|
||||||
|
|||||||
@@ -1,49 +1,45 @@
|
|||||||
/*####COPYRIGHTBEGIN####
|
/**************************************************************************
|
||||||
-------------------------------------------
|
*
|
||||||
Copyright (C) 2007 Steve Karg
|
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
*
|
||||||
This program is free software; you can redistribute it and/or
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
modify it under the terms of the GNU General Public License
|
* a copy of this software and associated documentation files (the
|
||||||
as published by the Free Software Foundation; either version 2
|
* "Software"), to deal in the Software without restriction, including
|
||||||
of the License, or (at your option) any later version.
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
This program is distributed in the hope that it will be useful,
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* the following conditions:
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
*
|
||||||
GNU General Public License for more details.
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
You should have received a copy of the GNU General Public License
|
*
|
||||||
along with this program; if not, write to:
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
The Free Software Foundation, Inc.
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
59 Temple Place - Suite 330
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
Boston, MA 02111-1307, USA.
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
As a special exception, if other files instantiate templates or
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
use macros or inline functions from this file, or you compile
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
this file and link it with other works to produce a work based
|
*********************************************************************/
|
||||||
on this file, this file does not by itself cause the resulting
|
|
||||||
work to be covered by the GNU General Public License. However
|
|
||||||
the source code for this file must still be made available in
|
|
||||||
accordance with section (3) of the GNU General Public License.
|
|
||||||
|
|
||||||
This exception does not invalidate any other reasons why a work
|
|
||||||
based on this file might be covered by the GNU General Public
|
|
||||||
License.
|
|
||||||
-------------------------------------------
|
|
||||||
####COPYRIGHTEND####*/
|
|
||||||
#ifndef IAR2GCC_H
|
#ifndef IAR2GCC_H
|
||||||
#define IAR2GCC_H
|
#define IAR2GCC_H
|
||||||
|
|
||||||
|
/* common embedded extensions for different compilers */
|
||||||
|
|
||||||
#if !defined(F_CPU)
|
#if !defined(F_CPU)
|
||||||
#define F_CPU (7372800)
|
#error You must define F_CPU - clock frequency!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (__CROSSWORKS_AVR)
|
||||||
|
#include <inavr.h>
|
||||||
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* IAR */
|
/* IAR */
|
||||||
#if defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ASM__)
|
#if defined(__ICCAVR__)
|
||||||
#include <inavr.h>
|
#include <inavr.h>
|
||||||
#include <ioavr.h>
|
#include <intrinsics.h>
|
||||||
/* BitValue is used alot in GCC examples */
|
#include <stdint.h>
|
||||||
#define _BV(bit_num) (1 << (bit_num))
|
|
||||||
|
|
||||||
/* inline function */
|
/* inline function */
|
||||||
static inline void _delay_us(
|
static inline void _delay_us(
|
||||||
@@ -55,6 +51,56 @@ static inline void _delay_us(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#include <util/delay.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* adjust some definitions to common versions */
|
||||||
|
#if defined (__CROSSWORKS_AVR)
|
||||||
|
#if (__TARGET_PROCESSOR == ATmega644P)
|
||||||
|
#define PRR PRR0
|
||||||
|
#define UBRR0 UBRR0W
|
||||||
|
#define UBRR1 UBRR1W
|
||||||
|
|
||||||
|
#define PA0 PORTA0
|
||||||
|
#define PA1 PORTA1
|
||||||
|
#define PA2 PORTA2
|
||||||
|
#define PA3 PORTA3
|
||||||
|
#define PA4 PORTA4
|
||||||
|
#define PA5 PORTA5
|
||||||
|
#define PA6 PORTA6
|
||||||
|
#define PA7 PORTA7
|
||||||
|
|
||||||
|
#define PB0 PORTB0
|
||||||
|
#define PB1 PORTB1
|
||||||
|
#define PB2 PORTB2
|
||||||
|
#define PB3 PORTB3
|
||||||
|
#define PB4 PORTB4
|
||||||
|
#define PB5 PORTB5
|
||||||
|
#define PB6 PORTB6
|
||||||
|
#define PB7 PORTB7
|
||||||
|
|
||||||
|
#define PC0 PORTC0
|
||||||
|
#define PC1 PORTC1
|
||||||
|
#define PC2 PORTC2
|
||||||
|
#define PC3 PORTC3
|
||||||
|
#define PC4 PORTC4
|
||||||
|
#define PC5 PORTC5
|
||||||
|
#define PC6 PORTC6
|
||||||
|
#define PC7 PORTC7
|
||||||
|
|
||||||
|
#define PD0 PORTD0
|
||||||
|
#define PD1 PORTD1
|
||||||
|
#define PD2 PORTD2
|
||||||
|
#define PD3 PORTD3
|
||||||
|
#define PD4 PORTD4
|
||||||
|
#define PD5 PORTD5
|
||||||
|
#define PD6 PORTD6
|
||||||
|
#define PD7 PORTD7
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Input/Output Registers */
|
/* Input/Output Registers */
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
@@ -192,27 +238,54 @@ typedef struct {
|
|||||||
/* Interrupts */
|
/* Interrupts */
|
||||||
#if defined(__ICCAVR__)
|
#if defined(__ICCAVR__)
|
||||||
#define PRAGMA(x) _Pragma( #x )
|
#define PRAGMA(x) _Pragma( #x )
|
||||||
#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
|
#define ISR(vec) \
|
||||||
#endif
|
/* function prototype for use with "require protoptypes" option. */ \
|
||||||
#if defined(__GNUC__)
|
PRAGMA( vector=vec ) __interrupt void handler_##vec(void); \
|
||||||
|
PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
#elif defined (__CROSSWORKS_AVR)
|
||||||
|
#define ISR(vec) void handler_##vec(void) __interrupt[vec]
|
||||||
|
#else
|
||||||
|
#error ISR() not defined!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Flash */
|
/* Flash */
|
||||||
#if defined(__ICCAVR__)
|
#if defined(__ICCAVR__)
|
||||||
#define FLASH_DECLARE(x) __flash x
|
#define FLASH_DECLARE(x) __flash x
|
||||||
#endif
|
#elif defined(__GNUC__)
|
||||||
#if defined(__GNUC__)
|
|
||||||
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
|
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
|
||||||
|
#elif defined (__CROSSWORKS_AVR)
|
||||||
|
#define FLASH_DECLARE (x) const __code x
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* EEPROM */
|
/* EEPROM */
|
||||||
#if defined(__ICCAVR__)
|
#if defined(__ICCAVR__)
|
||||||
#define EEPROM_DECLARE(x) __eeprom x
|
#define EEPROM_DECLARE(x) __eeprom x
|
||||||
#endif
|
#elif defined(__GNUC__)
|
||||||
#if defined(__GNUC__)
|
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
#define EEPROM_DECLARE(x) x __attribute__((section (".eeprom")))
|
#define EEPROM_DECLARE(x) x __attribute__((section (".eeprom")))
|
||||||
|
#if ((__GNUC__ < 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)) || \
|
||||||
|
((__GNUC__ == 4) && (__GNUC_MINOR__ == 3) && (__GNUC_PATCHLEVEL__ <= 3)))
|
||||||
|
/* bug in WinAVR - not quite IAR compatible */
|
||||||
|
#ifndef __EEPUT
|
||||||
|
#define __EEPUT _EEPUT
|
||||||
|
#endif
|
||||||
|
#ifndef __EEGET
|
||||||
|
#define __EEGET _EEGET
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#elif defined (__CROSSWORKS_AVR)
|
||||||
|
/* use functions defined in crt0.s to mimic IAR macros */
|
||||||
|
void __uint8_eeprom_store(
|
||||||
|
unsigned char byte,
|
||||||
|
unsigned addr);
|
||||||
|
unsigned char __uint8_eeprom_load(
|
||||||
|
unsigned addr);
|
||||||
|
#define __EEPUT(addr, var) \
|
||||||
|
__uint8_eeprom_store((unsigned char)(var), (unsigned)(addr))
|
||||||
|
#define __EEGET(var, addr) \
|
||||||
|
(var) = __uint8_eeprom_load((unsigned)(addr))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* IAR intrinsic routines */
|
/* IAR intrinsic routines */
|
||||||
@@ -223,4 +296,50 @@ typedef struct {
|
|||||||
#define __root
|
#define __root
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* watchdog defines in GCC */
|
||||||
|
#if defined(__ICCAVR__) || defined(__CROSSWORKS_AVR)
|
||||||
|
#define WDTO_15MS 0
|
||||||
|
#define WDTO_30MS 1
|
||||||
|
#define WDTO_60MS 2
|
||||||
|
#define WDTO_120MS 3
|
||||||
|
#define WDTO_250MS 4
|
||||||
|
#define WDTO_500MS 5
|
||||||
|
#define WDTO_1S 6
|
||||||
|
#define WDTO_2S 7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* power macros in GCC-AVR */
|
||||||
|
#if (defined(__ICCAVR__) && (defined(__ATmega644P__))) || \
|
||||||
|
(defined(__CROSSWORKS_AVR) && (__TARGET_PROCESSOR == ATmega644P))
|
||||||
|
#define power_adc_enable() (PRR &= (uint8_t)~(1 << PRADC))
|
||||||
|
#define power_spi_enable() (PRR &= (uint8_t)~(1 << PRSPI))
|
||||||
|
#define power_usart0_enable() (PRR &= (uint8_t)~(1 << PRUSART0))
|
||||||
|
#define power_usart1_enable() (PRR &= (uint8_t)~(1 << PRUSART1))
|
||||||
|
#define power_timer0_enable() (PRR &= (uint8_t)~(1 << PRTIM0))
|
||||||
|
#define power_timer1_enable() (PRR &= (uint8_t)~(1 << PRTIM1))
|
||||||
|
#define power_timer2_enable() (PRR &= (uint8_t)~(1 << PRTIM2))
|
||||||
|
#endif
|
||||||
|
#if (defined(__ICCAVR__) && (defined(__ATmega1284P__))) || \
|
||||||
|
(defined(__CROSSWORKS_AVR) && (__TARGET_PROCESSOR == ATmega1284P))
|
||||||
|
#define power_adc_enable() (PRR0 &= (uint8_t)~(1 << PRADC))
|
||||||
|
#define power_spi_enable() (PRR0 &= (uint8_t)~(1 << PRSPI))
|
||||||
|
#define power_usart0_enable() (PRR0 &= (uint8_t)~(1 << PRUSART0))
|
||||||
|
#define power_usart1_enable() (PRR0 &= (uint8_t)~(1 << PRUSART1))
|
||||||
|
#define power_timer0_enable() (PRR0 &= (uint8_t)~(1 << PRTIM0))
|
||||||
|
#define power_timer1_enable() (PRR0 &= (uint8_t)~(1 << PRTIM1))
|
||||||
|
#define power_timer2_enable() (PRR0 &= (uint8_t)~(1 << PRTIM2))
|
||||||
|
#endif
|
||||||
|
#if (defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ < 5)))
|
||||||
|
#if defined(__AVR_ATmega644P__)
|
||||||
|
/* bug in WinAVR - fixed in later versions */
|
||||||
|
#define power_usart1_enable() (PRR &= (uint8_t)~(1 << PRUSART1))
|
||||||
|
#elif defined(__AVR_ATmega1284P__)
|
||||||
|
#define power_usart1_enable() (PRR0 &= (uint8_t)~(1 << PRUSART1))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__CROSSWORKS_AVR)
|
||||||
|
#define inline
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -84,13 +84,7 @@ static void init(
|
|||||||
PORTD = 0;
|
PORTD = 0;
|
||||||
|
|
||||||
/* Configure the watchdog timer - Disabled for testing */
|
/* Configure the watchdog timer - Disabled for testing */
|
||||||
#if defined(__AVR_ATmega168__)
|
WATCHDOG_INIT();
|
||||||
BIT_CLEAR(MCUSR, WDRF);
|
|
||||||
WDTCSR = 0;
|
|
||||||
#else
|
|
||||||
BIT_CLEAR(MCUCSR, WDRF);
|
|
||||||
WDTCR = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Configure Specialized Hardware */
|
/* Configure Specialized Hardware */
|
||||||
RS485_Initialize();
|
RS485_Initialize();
|
||||||
|
|||||||
@@ -31,10 +31,11 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
/*#include "mstp.h" */
|
#include "bits.h"
|
||||||
|
|
||||||
/* This file has been customized for use with ATMEGA168 */
|
/* This file has been customized for use with ATMEGA168 */
|
||||||
#if defined(__AVR_ATmega168__)
|
#if (defined(__ICCAVR__) && (defined(__ATmega168__))) || \
|
||||||
|
(defined(__GNUC__) && defined(__AVR_ATmega168__))
|
||||||
/* USART defines for RS-485 port */
|
/* USART defines for RS-485 port */
|
||||||
#define UCSRB UCSR0B
|
#define UCSRB UCSR0B
|
||||||
#define TXEN TXEN0
|
#define TXEN TXEN0
|
||||||
@@ -152,6 +153,22 @@ bool RS485_Set_Baud_Rate(
|
|||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DESCRIPTION: Enable or disable the transmitter
|
||||||
|
* RETURN: none
|
||||||
|
* ALGORITHM: none
|
||||||
|
* NOTES: none
|
||||||
|
*****************************************************************************/
|
||||||
|
void RS485_Transmitter_Enable(
|
||||||
|
bool enable)
|
||||||
|
{
|
||||||
|
if (enable) {
|
||||||
|
BIT_SET(PORTD, PD2);
|
||||||
|
} else {
|
||||||
|
BIT_CLEAR(PORTD, PD2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||||
* RETURN: none
|
* RETURN: none
|
||||||
@@ -181,22 +198,6 @@ void RS485_Turnaround_Delay(
|
|||||||
BIT_SET(UCSR0A, TXC0);
|
BIT_SET(UCSR0A, TXC0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
* DESCRIPTION: Enable or disable the transmitter
|
|
||||||
* RETURN: none
|
|
||||||
* ALGORITHM: none
|
|
||||||
* NOTES: none
|
|
||||||
*****************************************************************************/
|
|
||||||
void RS485_Transmitter_Enable(
|
|
||||||
bool enable)
|
|
||||||
{
|
|
||||||
if (enable) {
|
|
||||||
BIT_SET(PORTD, PD2);
|
|
||||||
} else {
|
|
||||||
BIT_CLEAR(PORTD, PD2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* DESCRIPTION: Send some data and wait until it is sent
|
* DESCRIPTION: Send some data and wait until it is sent
|
||||||
* RETURN: none
|
* RETURN: none
|
||||||
|
|||||||
@@ -180,17 +180,22 @@ bool Binary_Output_Present_Value_Set(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Binary_Output_Polarity_Set(
|
bool Binary_Output_Polarity_Set(
|
||||||
uint32_t instance,
|
uint32_t instance,
|
||||||
BACNET_POLARITY polarity)
|
BACNET_POLARITY polarity)
|
||||||
{
|
{
|
||||||
|
bool status = false;
|
||||||
|
|
||||||
if (instance < MAX_BINARY_OUTPUTS) {
|
if (instance < MAX_BINARY_OUTPUTS) {
|
||||||
if (polarity < MAX_POLARITY) {
|
if (polarity < MAX_POLARITY) {
|
||||||
Polarity[instance] = polarity;
|
Polarity[instance] = polarity;
|
||||||
seeprom_bytes_write(NV_SEEPROM_BINARY_OUTPUT(instance,
|
seeprom_bytes_write(NV_SEEPROM_BINARY_OUTPUT(instance,
|
||||||
NV_SEEPROM_BO_POLARITY), &Polarity[instance], 1);
|
NV_SEEPROM_BO_POLARITY), &Polarity[instance], 1);
|
||||||
|
status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
BACNET_POLARITY Binary_Output_Polarity(
|
BACNET_POLARITY Binary_Output_Polarity(
|
||||||
|
|||||||
@@ -175,15 +175,20 @@ bool Binary_Output_Present_Value_Set(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Binary_Output_Polarity_Set(
|
bool Binary_Output_Polarity_Set(
|
||||||
uint32_t instance,
|
uint32_t instance,
|
||||||
BACNET_POLARITY polarity)
|
BACNET_POLARITY polarity)
|
||||||
{
|
{
|
||||||
|
bool status = false;
|
||||||
|
|
||||||
if (instance < MAX_BINARY_OUTPUTS) {
|
if (instance < MAX_BINARY_OUTPUTS) {
|
||||||
if (polarity < MAX_POLARITY) {
|
if (polarity < MAX_POLARITY) {
|
||||||
Polarity[instance] = polarity;
|
Polarity[instance] = polarity;
|
||||||
|
status = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
BACNET_POLARITY Binary_Output_Polarity(
|
BACNET_POLARITY Binary_Output_Polarity(
|
||||||
@@ -198,7 +203,7 @@ BACNET_POLARITY Binary_Output_Polarity(
|
|||||||
return polarity;
|
return polarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Binary_Output_Out_Of_Service_Set(
|
void Binary_Output_Out_Of_Service_Set(
|
||||||
uint32_t instance,
|
uint32_t instance,
|
||||||
bool flag)
|
bool flag)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user