Feature/make pretty apps and ports (#80)
* Added pretty-apps and pretty-ports make targets * pretty-fied apps folder C files * Pretty-fied ports folder C and H files Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
+13
-12
@@ -60,15 +60,15 @@ bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_decode_confirmed_service_request(uint8_t *apdu, /* APDU data */
|
||||
|
||||
uint16_t apdu_len,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||
uint8_t * service_choice,
|
||||
uint8_t ** service_request,
|
||||
uint16_t * service_request_len)
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data,
|
||||
uint8_t *service_choice,
|
||||
uint8_t **service_request,
|
||||
uint16_t *service_request_len)
|
||||
{
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
service_data->segmented_message = (apdu[0] & BIT(3)) ? true : false;
|
||||
service_data->more_follows = (apdu[0] & BIT(2)) ? true : false;
|
||||
@@ -89,8 +89,8 @@ uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
|
||||
return len;
|
||||
}
|
||||
|
||||
void apdu_handler(BACNET_ADDRESS * src,
|
||||
uint8_t * apdu, /* APDU data */
|
||||
void apdu_handler(BACNET_ADDRESS *src,
|
||||
uint8_t *apdu, /* APDU data */
|
||||
|
||||
uint16_t apdu_len)
|
||||
{
|
||||
@@ -98,13 +98,14 @@ void apdu_handler(BACNET_ADDRESS * src,
|
||||
uint8_t service_choice = 0;
|
||||
uint8_t *service_request = NULL;
|
||||
uint16_t service_request_len = 0;
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
if (apdu) {
|
||||
/* PDU Type */
|
||||
switch (apdu[0] & 0xF0) {
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
len = apdu_decode_confirmed_service_request(
|
||||
&apdu[0], /* APDU data */
|
||||
apdu_len, &service_data, &service_choice, &service_request,
|
||||
&service_request_len);
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
@@ -113,8 +114,8 @@ void apdu_handler(BACNET_ADDRESS * src,
|
||||
}
|
||||
#ifdef WRITE_PROPERTY
|
||||
else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
|
||||
handler_write_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
handler_write_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
||||
+45
-50
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/basic/object/av.h"
|
||||
|
||||
@@ -80,33 +80,32 @@ 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;
|
||||
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,
|
||||
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)
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
object_instance);
|
||||
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));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Analog_Value_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -116,9 +115,8 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
|
||||
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]);
|
||||
apdu_len = encode_application_real(
|
||||
&apdu[0], AV_Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
@@ -155,11 +153,11 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data,
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
@@ -170,9 +168,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -206,7 +203,7 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testAnalog_Value(Test * pTest)
|
||||
void testAnalog_Value(Test *pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 0;
|
||||
@@ -218,14 +215,12 @@ void testAnalog_Value(Test * pTest)
|
||||
BACNET_ERROR_CLASS error_class;
|
||||
BACNET_ERROR_CODE error_code;
|
||||
|
||||
len =
|
||||
Analog_Value_Encode_Property_APDU(&apdu[0], instance,
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -245,7 +240,7 @@ int main(void)
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
(void)ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <stdio.h>
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/datalink/bip.h"
|
||||
@@ -71,7 +71,6 @@ long bip_getaddrbyname(const char *host_name)
|
||||
*/
|
||||
void bip_set_interface(char *ifname)
|
||||
{
|
||||
|
||||
uint8_t local_address[] = { 0, 0, 0, 0 };
|
||||
uint8_t broadcast_address[] = { 0, 0, 0, 0 };
|
||||
uint8_t netmask[] = { 0, 0, 0, 0 };
|
||||
@@ -87,7 +86,7 @@ void bip_set_interface(char *ifname)
|
||||
|
||||
/* setup local broadcast address */
|
||||
getSubnetMask_func(CW5100Class_new(), netmask);
|
||||
for (int i = 0; i < 4; i++) { //FIXME: IPv4 ?
|
||||
for (int i = 0; i < 4; i++) { // FIXME: IPv4 ?
|
||||
invertedNetmask[i] = ~netmask[i];
|
||||
broadcast_address[i] = (local_address[i] | invertedNetmask[i]);
|
||||
}
|
||||
@@ -130,7 +129,7 @@ bool bip_init(char *ifname)
|
||||
/* assumes that the driver has already been initialized */
|
||||
for (sock_fd = 0; sock_fd < MAX_SOCK_NUM; sock_fd++) {
|
||||
if (readSnSR_func(CW5100Class_new(), sock_fd) == SnSR_CLOSED()) {
|
||||
socket_func(sock_fd, SnMR_UDP(), (uint16_t) 47808, 0);
|
||||
socket_func(sock_fd, SnMR_UDP(), (uint16_t)47808, 0);
|
||||
listen_func(sock_fd);
|
||||
isOpen = true;
|
||||
break;
|
||||
@@ -149,7 +148,7 @@ bool bip_init(char *ifname)
|
||||
|
||||
/** Cleanup and close out the BACnet/IP services by closing the socket.
|
||||
* @ingroup DLBIP
|
||||
*/
|
||||
*/
|
||||
void bip_cleanup(void)
|
||||
{
|
||||
int sock_fd = 0;
|
||||
@@ -167,7 +166,7 @@ void bip_cleanup(void)
|
||||
* @param netmask [out] The netmask, in host order.
|
||||
* @return 0 on success, else the error from the ioctl() call.
|
||||
*/
|
||||
int bip_get_local_netmask(uint8_t * netmask)
|
||||
int bip_get_local_netmask(uint8_t *netmask)
|
||||
{
|
||||
getSubnetMask_func(CW5100Class_new(), netmask);
|
||||
return 0;
|
||||
|
||||
+52
-59
@@ -32,8 +32,8 @@
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <string.h>
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacint.h"
|
||||
@@ -42,42 +42,40 @@
|
||||
#include "socketWrapper.h"
|
||||
#include "w5100Wrapper.h"
|
||||
|
||||
|
||||
#if PRINT_ENABLED | DEBUG
|
||||
#include <stdio.h> /* for standard i/o, like printing */
|
||||
#include <stdio.h> /* for standard i/o, like printing */
|
||||
#endif
|
||||
|
||||
/** @file bip.c Configuration and Operations for BACnet/IP */
|
||||
|
||||
static uint8_t BIP_Socket = MAX_SOCK_NUM;
|
||||
/* port to use - stored in network byte order */
|
||||
static uint16_t BIP_Port = 0; /* this will force initialization in demos */
|
||||
static uint16_t BIP_Port = 0; /* this will force initialization in demos */
|
||||
/* IP Address - stored in network byte order */
|
||||
//static struct in_addr BIP_Address;
|
||||
// static struct in_addr BIP_Address;
|
||||
static uint8_t BIP_Address[4] = { 0, 0, 0, 0 };
|
||||
/* Broadcast Address - stored in network byte order */
|
||||
//static struct in_addr BIP_Broadcast_Address;
|
||||
// static struct in_addr BIP_Broadcast_Address;
|
||||
static uint8_t BIP_Broadcast_Address[4] = { 0, 0, 0, 0 };
|
||||
|
||||
/** Converter from uint8_t[4] type address to uint32_t
|
||||
*
|
||||
*/
|
||||
uint32_t convertBIP_Address2uint32(uint8_t * bip_address)
|
||||
uint32_t convertBIP_Address2uint32(uint8_t *bip_address)
|
||||
{
|
||||
return (uint32_t) ((bip_address[0] * 2 ^ 24) + (bip_address[1] * 2 ^ 16) +
|
||||
return (uint32_t)((bip_address[0] * 2 ^ 24) + (bip_address[1] * 2 ^ 16) +
|
||||
(bip_address[2] * 2 ^ 8) + bip_address[3]);
|
||||
}
|
||||
|
||||
/** Convert from uint32_t IPv4 address to uint8_t[4] address
|
||||
*
|
||||
*/
|
||||
void convertUint32Address_2_uint8Address(uint32_t ip,
|
||||
uint8_t * address)
|
||||
void convertUint32Address_2_uint8Address(uint32_t ip, uint8_t *address)
|
||||
{
|
||||
address[0] = (uint8_t) (ip >> 24);
|
||||
address[1] = (uint8_t) (ip >> 16);
|
||||
address[2] = (uint8_t) (ip >> 8);
|
||||
address[3] = (uint8_t) (ip >> 0);
|
||||
address[0] = (uint8_t)(ip >> 24);
|
||||
address[1] = (uint8_t)(ip >> 16);
|
||||
address[2] = (uint8_t)(ip >> 8);
|
||||
address[3] = (uint8_t)(ip >> 0);
|
||||
}
|
||||
|
||||
/** Setter for the BACnet/IP socket handle.
|
||||
@@ -103,8 +101,8 @@ bool bip_valid(void)
|
||||
return (BIP_Socket < MAX_SOCK_NUM);
|
||||
}
|
||||
|
||||
void bip_set_addr(uint8_t * net_address)
|
||||
{ /* in network byte order */
|
||||
void bip_set_addr(uint8_t *net_address)
|
||||
{ /* in network byte order */
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
BIP_Address[i] = net_address[i];
|
||||
}
|
||||
@@ -115,8 +113,8 @@ uint8_t *bip_get_addr(void)
|
||||
return BIP_Address;
|
||||
}
|
||||
|
||||
void bip_set_broadcast_addr(uint8_t * net_address)
|
||||
{ /* in network byte order */
|
||||
void bip_set_broadcast_addr(uint8_t *net_address)
|
||||
{ /* in network byte order */
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
BIP_Broadcast_Address[i] = net_address[i];
|
||||
}
|
||||
@@ -127,9 +125,8 @@ uint8_t *bip_get_broadcast_addr(void)
|
||||
return BIP_Broadcast_Address;
|
||||
}
|
||||
|
||||
|
||||
void bip_set_port(uint16_t port)
|
||||
{ /* in network byte order */
|
||||
{ /* in network byte order */
|
||||
BIP_Port = htons(port);
|
||||
}
|
||||
|
||||
@@ -139,11 +136,11 @@ uint16_t bip_get_port(void)
|
||||
return ntohs(BIP_Port);
|
||||
}
|
||||
|
||||
static int bip_decode_bip_address(BACNET_ADDRESS * bac_addr,
|
||||
uint8_t * address, /* in network format */
|
||||
static int bip_decode_bip_address(BACNET_ADDRESS *bac_addr,
|
||||
uint8_t *address, /* in network format */
|
||||
|
||||
uint16_t * port)
|
||||
{ /* in network format */
|
||||
uint16_t *port)
|
||||
{ /* in network format */
|
||||
int len = 0;
|
||||
|
||||
if (bac_addr) {
|
||||
@@ -164,14 +161,14 @@ static int bip_decode_bip_address(BACNET_ADDRESS * bac_addr,
|
||||
* @param pdu_len [in] Number of bytes in the pdu buffer.
|
||||
* @return Number of bytes sent on success, negative number on failure.
|
||||
*/
|
||||
int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
int bip_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
|
||||
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||
int mtu_len = 0;
|
||||
@@ -180,15 +177,15 @@ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
uint8_t address[] = { 0, 0, 0, 0 };
|
||||
uint16_t port = 0;
|
||||
|
||||
(void) npdu_data;
|
||||
(void)npdu_data;
|
||||
/* assumes that the driver has already been initialized */
|
||||
if (BIP_Socket < 0) {
|
||||
return BIP_Socket;
|
||||
}
|
||||
|
||||
mtu[0] = BVLL_TYPE_BACNET_IP;
|
||||
if ((dest->net == BACNET_BROADCAST_NETWORK) || ((dest->net > 0) &&
|
||||
(dest->len == 0)) || (dest->mac_len == 0)) {
|
||||
if ((dest->net == BACNET_BROADCAST_NETWORK) ||
|
||||
((dest->net > 0) && (dest->len == 0)) || (dest->mac_len == 0)) {
|
||||
/* broadcast */
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
address[i] = BIP_Broadcast_Address[i];
|
||||
@@ -196,16 +193,14 @@ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Send Broadcast NPDU to %d.%d.%d.%d:%d\n", address[0],
|
||||
address[1]
|
||||
, address[2], address[3], port);
|
||||
address[1], address[2], address[3], port);
|
||||
#endif
|
||||
} else if (dest->mac_len == 6) {
|
||||
bip_decode_bip_address(dest, address, &port);
|
||||
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Send Unicast NPDU to %d.%d.%d.%d:%d\n", address[0],
|
||||
address[1]
|
||||
, address[2], address[3], port);
|
||||
address[1], address[2], address[3], port);
|
||||
#endif
|
||||
} else {
|
||||
/* invalid address */
|
||||
@@ -213,9 +208,8 @@ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
}
|
||||
|
||||
mtu_len = 2;
|
||||
mtu_len +=
|
||||
encode_unsigned16(&mtu[mtu_len],
|
||||
(uint16_t) (pdu_len + 4 /*inclusive */ ));
|
||||
mtu_len += encode_unsigned16(
|
||||
&mtu[mtu_len], (uint16_t)(pdu_len + 4 /*inclusive */));
|
||||
memcpy(&mtu[mtu_len], pdu, pdu_len);
|
||||
mtu_len += pdu_len;
|
||||
|
||||
@@ -224,8 +218,7 @@ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
#endif
|
||||
|
||||
/* Send the packet */
|
||||
bytes_sent =
|
||||
sendto_func(BIP_Socket, mtu, (uint16_t) mtu_len, address, port);
|
||||
bytes_sent = sendto_func(BIP_Socket, mtu, (uint16_t)mtu_len, address, port);
|
||||
|
||||
return bytes_sent;
|
||||
}
|
||||
@@ -236,21 +229,22 @@ int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
||||
*
|
||||
* @param src [out] Source of the packet - who should receive any response.
|
||||
* @param pdu [out] A buffer to hold the PDU portion of the received packet,
|
||||
* after the BVLC portion has been stripped off.
|
||||
* after the BVLC portion has been stripped
|
||||
* off.
|
||||
* @param max_pdu [in] Size of the pdu[] buffer.
|
||||
* @param timeout [in] The number of milliseconds to wait for a packet.
|
||||
* @return The number of octets (remaining) in the PDU, or zero on failure.
|
||||
*/
|
||||
uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
||||
uint16_t bip_receive(BACNET_ADDRESS *src, /* source address */
|
||||
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
|
||||
unsigned timeout)
|
||||
{
|
||||
int received_bytes = 0;
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
uint8_t src_addr[] = { 0, 0, 0, 0 };
|
||||
uint16_t src_port = 0;
|
||||
uint16_t i = 0;
|
||||
@@ -263,9 +257,8 @@ uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
||||
if (getRXReceivedSize_func(CW5100Class_new(), BIP_Socket)) {
|
||||
memcpy(&src_addr, &src->mac[0], 4);
|
||||
memcpy(&src_port, &src->mac[4], 2);
|
||||
received_bytes =
|
||||
(int) recvfrom_func(BIP_Socket, &pdu[0], max_pdu, src_addr,
|
||||
&src_port);
|
||||
received_bytes = (int)recvfrom_func(
|
||||
BIP_Socket, &pdu[0], max_pdu, src_addr, &src_port);
|
||||
}
|
||||
|
||||
/* See if there is a problem */
|
||||
@@ -289,7 +282,7 @@ uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
||||
return 0;
|
||||
}
|
||||
|
||||
function = bvlc_get_function_code(); /* aka, pdu[1] */
|
||||
function = bvlc_get_function_code(); /* aka, pdu[1] */
|
||||
if ((function == BVLC_ORIGINAL_UNICAST_NPDU) ||
|
||||
(function == BVLC_ORIGINAL_BROADCAST_NPDU)) {
|
||||
/* ignore messages from me */
|
||||
@@ -312,7 +305,7 @@ uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
||||
/* FIXME: check destination address */
|
||||
/* see if it is broadcast or for us */
|
||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
||||
(void) decode_unsigned16(&pdu[2], &pdu_len);
|
||||
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
||||
/* subtract off the BVLC header */
|
||||
pdu_len -= 4;
|
||||
if (pdu_len < max_pdu) {
|
||||
@@ -355,7 +348,7 @@ uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
||||
/* FIXME: check destination address */
|
||||
/* see if it is broadcast or for us */
|
||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
||||
(void) decode_unsigned16(&pdu[2], &pdu_len);
|
||||
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
||||
/* subtract off the BVLC header */
|
||||
pdu_len -= 10;
|
||||
if (pdu_len < max_pdu) {
|
||||
@@ -374,7 +367,7 @@ uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void bip_get_my_address(BACNET_ADDRESS * my_address)
|
||||
void bip_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -382,8 +375,8 @@ void bip_get_my_address(BACNET_ADDRESS * my_address)
|
||||
my_address->mac_len = 6;
|
||||
memcpy(&my_address->mac[0], &BIP_Address, 4);
|
||||
memcpy(&my_address->mac[4], &BIP_Port, 2);
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0; /* no SLEN */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0; /* no SLEN */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
/* no SADR */
|
||||
my_address->adr[i] = 0;
|
||||
@@ -393,16 +386,16 @@ void bip_get_my_address(BACNET_ADDRESS * my_address)
|
||||
return;
|
||||
}
|
||||
|
||||
void bip_get_broadcast_address(BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void bip_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 6;
|
||||
memcpy(&dest->mac[0], &BIP_Broadcast_Address, 4);
|
||||
memcpy(&dest->mac[4], &BIP_Port, 2);
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* no SLEN */
|
||||
dest->len = 0; /* no SLEN */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
/* no SADR */
|
||||
dest->adr[i] = 0;
|
||||
|
||||
+49
-55
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/basic/object/bv.h"
|
||||
|
||||
@@ -87,10 +87,10 @@ static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t object_instance)
|
||||
/* 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 */
|
||||
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;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
return text_string;
|
||||
}
|
||||
|
||||
@@ -98,14 +98,14 @@ char *Binary_Value_Name(uint32_t object_instance)
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
|
||||
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)
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
@@ -113,15 +113,14 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
|
||||
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
|
||||
object_instance);
|
||||
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));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Binary_Value_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -171,11 +170,11 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
|
||||
}
|
||||
|
||||
/* 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 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 */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
@@ -186,9 +185,8 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -201,20 +199,19 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
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);
|
||||
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;
|
||||
(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();
|
||||
// LED_GREEN_ON();
|
||||
} else {
|
||||
// LED_GREEN_OFF();
|
||||
// LED_GREEN_OFF();
|
||||
}
|
||||
status = true;
|
||||
} else {
|
||||
@@ -253,7 +250,7 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testBinary_Value(Test * pTest)
|
||||
void testBinary_Value(Test *pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 0;
|
||||
@@ -265,15 +262,12 @@ void testBinary_Value(Test * pTest)
|
||||
BACNET_ERROR_CLASS error_class;
|
||||
BACNET_ERROR_CODE error_code;
|
||||
|
||||
|
||||
len =
|
||||
Binary_Value_Encode_Property_APDU(&apdu[0], instance,
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -293,7 +287,7 @@ int main(void)
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
(void)ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
/** result from a client request */
|
||||
BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION;
|
||||
/** The current BVLC Function Code being handled. */
|
||||
BACNET_BVLC_FUNCTION BVLC_Function_Code = BVLC_RESULT; /* A safe default */
|
||||
BACNET_BVLC_FUNCTION BVLC_Function_Code = BVLC_RESULT; /* A safe default */
|
||||
|
||||
/** Encode the BVLC Result message
|
||||
*
|
||||
@@ -26,8 +26,7 @@ BACNET_BVLC_FUNCTION BVLC_Function_Code = BVLC_RESULT; /* A safe default */
|
||||
*
|
||||
* @return number of bytes encoded
|
||||
*/
|
||||
static int bvlc_encode_bvlc_result(uint8_t * pdu,
|
||||
BACNET_BVLC_RESULT result_code)
|
||||
static int bvlc_encode_bvlc_result(uint8_t *pdu, BACNET_BVLC_RESULT result_code)
|
||||
{
|
||||
if (pdu) {
|
||||
pdu[0] = BVLL_TYPE_BACNET_IP;
|
||||
@@ -36,7 +35,7 @@ static int bvlc_encode_bvlc_result(uint8_t * pdu,
|
||||
of the entire BVLL message, including the two octets of the
|
||||
length field itself, most significant octet first. */
|
||||
encode_unsigned16(&pdu[2], 6);
|
||||
encode_unsigned16(&pdu[4], (uint16_t) result_code);
|
||||
encode_unsigned16(&pdu[4], (uint16_t)result_code);
|
||||
}
|
||||
|
||||
return 6;
|
||||
@@ -55,14 +54,14 @@ static int bvlc_encode_bvlc_result(uint8_t * pdu,
|
||||
* @return Upon successful completion, returns the number of bytes sent.
|
||||
* Otherwise, -1 shall be returned and errno set to indicate the error.
|
||||
*/
|
||||
static int bvlc_send_mpdu(uint8_t * dest_addr, /* the destination address */
|
||||
static int bvlc_send_mpdu(uint8_t *dest_addr, /* the destination address */
|
||||
|
||||
uint16_t * dest_port, /* the destination port */
|
||||
uint16_t *dest_port, /* the destination port */
|
||||
|
||||
uint8_t * mtu, /* the data */
|
||||
uint8_t *mtu, /* the data */
|
||||
|
||||
uint16_t mtu_len)
|
||||
{ /* amount of data to send */
|
||||
{ /* amount of data to send */
|
||||
/* assumes that the driver has already been initialized */
|
||||
if (bip_valid()) {
|
||||
return 0;
|
||||
@@ -76,15 +75,15 @@ static int bvlc_send_mpdu(uint8_t * dest_addr, /* the destination address */
|
||||
* @param dest_addr - destination address
|
||||
* @param dest_port - destination port
|
||||
*/
|
||||
static void bvlc_send_result(uint8_t * dest_addr,
|
||||
uint16_t * dest_port, /* the destination address */
|
||||
static void bvlc_send_result(uint8_t *dest_addr,
|
||||
uint16_t *dest_port, /* the destination address */
|
||||
|
||||
BACNET_BVLC_RESULT result_code)
|
||||
{
|
||||
uint8_t mtu[MAX_MPDU] = { 0 };
|
||||
uint16_t mtu_len = 0;
|
||||
|
||||
mtu_len = (uint16_t) bvlc_encode_bvlc_result(&mtu[0], result_code);
|
||||
mtu_len = (uint16_t)bvlc_encode_bvlc_result(&mtu[0], result_code);
|
||||
bvlc_send_mpdu(dest_addr, dest_port, mtu, mtu_len);
|
||||
|
||||
return;
|
||||
@@ -101,30 +100,29 @@ static void bvlc_send_result(uint8_t * dest_addr,
|
||||
* @return Non-zero BVLC_RESULT_ code if we sent a response (NAK) to this
|
||||
* BVLC message. If zero, may need further processing.
|
||||
*/
|
||||
uint16_t bvlc_for_non_bbmd(uint8_t * addr,
|
||||
uint16_t * port,
|
||||
uint8_t * npdu,
|
||||
uint16_t received_bytes)
|
||||
uint16_t bvlc_for_non_bbmd(
|
||||
uint8_t *addr, uint16_t *port, uint8_t *npdu, uint16_t received_bytes)
|
||||
{
|
||||
uint16_t result_code = 0; /* aka, BVLC_RESULT_SUCCESSFUL_COMPLETION */
|
||||
uint16_t result_code = 0; /* aka, BVLC_RESULT_SUCCESSFUL_COMPLETION */
|
||||
|
||||
/* To check the BVLC-function code, the buffer of received
|
||||
* bytes has to be at least one byte long. */
|
||||
if (received_bytes >= 1) {
|
||||
BVLC_Function_Code = npdu[1]; /* The BVLC function */
|
||||
BVLC_Function_Code = npdu[1]; /* The BVLC function */
|
||||
switch (BVLC_Function_Code) {
|
||||
case BVLC_RESULT:
|
||||
if (received_bytes >= 6) {
|
||||
/* This is the result of our foreign device registration */
|
||||
(void) decode_unsigned16(&npdu[4], &result_code);
|
||||
BVLC_Result_Code = (BACNET_BVLC_RESULT) result_code;
|
||||
(void)decode_unsigned16(&npdu[4], &result_code);
|
||||
BVLC_Result_Code = (BACNET_BVLC_RESULT)result_code;
|
||||
fprintf(stderr, "BVLC: Result Code=%d\n", BVLC_Result_Code);
|
||||
/* But don't send any response */
|
||||
result_code = 0;
|
||||
}
|
||||
break;
|
||||
case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE:
|
||||
result_code = BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK;
|
||||
result_code =
|
||||
BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK;
|
||||
break;
|
||||
case BVLC_READ_BROADCAST_DIST_TABLE:
|
||||
result_code = BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK;
|
||||
|
||||
+120
-122
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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>
|
||||
@@ -106,9 +106,8 @@ unsigned Device_Object_List_Count(void)
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(uint32_t array_index,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * instance)
|
||||
bool Device_Object_List_Identifier(
|
||||
uint32_t array_index, BACNET_OBJECT_TYPE *object_type, uint32_t *instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t object_index = 0;
|
||||
@@ -154,15 +153,15 @@ bool Device_Object_List_Identifier(uint32_t array_index,
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error */
|
||||
int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
int Device_Encode_Property_APDU(uint8_t *apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
uint32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint32_t i = 0;
|
||||
@@ -170,13 +169,12 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
uint32_t instance = 0;
|
||||
uint32_t count = 0;
|
||||
|
||||
//object_instance = object_instance;
|
||||
// object_instance = object_instance;
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_DEVICE, Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, Object_Name);
|
||||
@@ -195,9 +193,8 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
@@ -220,16 +217,15 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
BACNET_PROTOCOL_REVISION);
|
||||
encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_REVISION);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED)i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -240,7 +236,7 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
/* must have the bit string as big as it can be */
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
@@ -260,9 +256,8 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
else if (array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
Device_Object_List_Identifier(i, &object_type, &instance);
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
len = encode_application_object_id(
|
||||
&apdu[apdu_len], object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
@@ -275,11 +270,10 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
array_index, &object_type, &instance))
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], object_type, instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
@@ -306,25 +300,27 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0],
|
||||
// dlmstp_max_info_frames());
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||
// break;
|
||||
// case 9600:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
|
||||
// break;
|
||||
// case 512:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0], stack_size());
|
||||
// break;
|
||||
// case 513:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0], stack_unused());
|
||||
// break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0],
|
||||
// dlmstp_max_info_frames());
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0],
|
||||
// dlmstp_max_master());
|
||||
// break;
|
||||
// case 9600:
|
||||
// apdu_len =
|
||||
// encode_application_unsigned(&apdu[0],
|
||||
// RS485_Get_Baud_Rate());
|
||||
// break;
|
||||
// case 512:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0],
|
||||
// stack_size()); break;
|
||||
// case 513:
|
||||
// apdu_len = encode_application_unsigned(&apdu[0],
|
||||
// stack_unused()); break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
@@ -342,11 +338,11 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data,
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
@@ -356,9 +352,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -370,8 +365,8 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.Object_Id.
|
||||
instance))) {
|
||||
(Device_Set_Object_Instance_Number(
|
||||
value.type.Object_Id.instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
@@ -383,35 +378,37 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if (value.type.Unsigned_Int <= 255) {
|
||||
// dlmstp_set_max_info_frames(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if ((value.type.Unsigned_Int > 0) &&
|
||||
// (value.type.Unsigned_Int <= 127)) {
|
||||
// dlmstp_set_max_master(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
// case PROP_MAX_INFO_FRAMES:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT)
|
||||
// {
|
||||
// if (value.type.Unsigned_Int <= 255) {
|
||||
// dlmstp_set_max_info_frames(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
// case PROP_MAX_MASTER:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT)
|
||||
// {
|
||||
// if ((value.type.Unsigned_Int > 0) &&
|
||||
// (value.type.Unsigned_Int <= 127)) {
|
||||
// dlmstp_set_max_master(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
case PROP_OBJECT_NAME:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
uint8_t encoding;
|
||||
@@ -436,20 +433,21 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
// case 9600:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||
// if (value.type.Unsigned_Int > 115200) {
|
||||
// RS485_Set_Baud_Rate(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
// case 9600:
|
||||
// if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT)
|
||||
// {
|
||||
// if (value.type.Unsigned_Int > 115200) {
|
||||
// RS485_Set_Baud_Rate(value.type.Unsigned_Int);
|
||||
// status = true;
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
// }
|
||||
// } else {
|
||||
// *error_class = ERROR_CLASS_PROPERTY;
|
||||
// *error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
// }
|
||||
// break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
|
||||
+48
-57
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -43,10 +43,10 @@
|
||||
|
||||
/* 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 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;
|
||||
|
||||
@@ -54,24 +54,21 @@ int Encode_Property_APDU(uint8_t * apdu,
|
||||
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],
|
||||
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;
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||
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;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Binary_Value_Encode_Property_APDU(&apdu[0],
|
||||
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);
|
||||
}
|
||||
@@ -85,10 +82,10 @@ int Encode_Property_APDU(uint8_t * apdu,
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
void handler_read_property(uint8_t * service_request,
|
||||
void handler_read_property(uint8_t *service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
BACNET_ADDRESS *src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data)
|
||||
{
|
||||
BACNET_READ_PROPERTY_DATA data;
|
||||
int len = 0;
|
||||
@@ -103,13 +100,11 @@ void handler_read_property(uint8_t * service_request,
|
||||
/* 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);
|
||||
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],
|
||||
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
goto RP_ABORT;
|
||||
@@ -117,42 +112,38 @@ void handler_read_property(uint8_t * service_request,
|
||||
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],
|
||||
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);
|
||||
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);
|
||||
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 = 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 */
|
||||
/* 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],
|
||||
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],
|
||||
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RP_ABORT:
|
||||
RP_ABORT:
|
||||
pdu_len += len;
|
||||
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
|
||||
|
||||
+29
-32
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -39,8 +39,7 @@
|
||||
|
||||
bool Send_I_Am_Flag = true;
|
||||
|
||||
void sendIamUnicast(uint8_t * buffer,
|
||||
BACNET_ADDRESS * src)
|
||||
void sendIamUnicast(uint8_t *buffer, BACNET_ADDRESS *src)
|
||||
{
|
||||
BACNET_ADDRESS dest;
|
||||
int pdu_len = 0;
|
||||
@@ -61,24 +60,22 @@ void sendIamUnicast(uint8_t * buffer,
|
||||
/* encode the APDU portion of the packet */
|
||||
apdu_len =
|
||||
iam_encode_apdu(&buffer[npdu_len], Device_Object_Instance_Number(),
|
||||
MAX_APDU, SEGMENTATION_NONE, Device_Vendor_Identifier());
|
||||
MAX_APDU, SEGMENTATION_NONE, Device_Vendor_Identifier());
|
||||
/* send data */
|
||||
pdu_len = npdu_len + apdu_len;
|
||||
int bytes = datalink_send_pdu(&dest, &npdu_data, &buffer[0], pdu_len);
|
||||
}
|
||||
|
||||
void handler_who_is(uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src)
|
||||
void handler_who_is(
|
||||
uint8_t *service_request, uint16_t service_len, BACNET_ADDRESS *src)
|
||||
{
|
||||
int len = 0;
|
||||
int32_t low_limit = 0;
|
||||
int32_t high_limit = 0;
|
||||
int32_t target_device;
|
||||
|
||||
len =
|
||||
whois_decode_service_request(service_request, service_len, &low_limit,
|
||||
&high_limit);
|
||||
len = whois_decode_service_request(
|
||||
service_request, service_len, &low_limit, &high_limit);
|
||||
if (len == 0) {
|
||||
sendIamUnicast(&Handler_Transmit_Buffer[0], src);
|
||||
} else if (len != -1) {
|
||||
|
||||
+49
-55
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -44,10 +44,10 @@
|
||||
/* too big to reside on stack frame for PIC */
|
||||
static BACNET_WRITE_PROPERTY_DATA wp_data;
|
||||
|
||||
void handler_write_property(uint8_t * service_request,
|
||||
void handler_write_property(uint8_t *service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
BACNET_ADDRESS *src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
@@ -61,68 +61,62 @@ void handler_write_property(uint8_t * service_request,
|
||||
/* 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);
|
||||
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],
|
||||
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],
|
||||
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],
|
||||
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);
|
||||
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],
|
||||
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);
|
||||
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],
|
||||
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);
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
extern bool Send_I_Am_Flag;
|
||||
/* local version override */
|
||||
const char *BACnet_Version = "1.0";
|
||||
static uint8_t Ethernet_MAC_Address[MAX_MAC_LEN] =
|
||||
{ 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
static uint8_t Ethernet_MAC_Address[MAX_MAC_LEN] = { 0xDE, 0xAD, 0xBE, 0xEF,
|
||||
0xFE, 0xED };
|
||||
uint8_t ipAddress[] = { 192, 168, 0, 185 };
|
||||
uint8_t gateway[] = { 192, 168, 0, 1 };
|
||||
uint8_t netmask[] = { 255, 255, 255, 0 };
|
||||
@@ -53,7 +53,7 @@ bool dcc_communication_enabled(void)
|
||||
|
||||
void setup()
|
||||
{
|
||||
//INIT W5100
|
||||
// INIT W5100
|
||||
init_func(CW5100Class_new());
|
||||
setMACAddress_func(CW5100Class_new(), Ethernet_MAC_Address);
|
||||
setIPAddress_func(CW5100Class_new(), ipAddress);
|
||||
@@ -68,7 +68,6 @@ void setup()
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "Starting BACNET application..\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static uint8_t PDUBuffer[MAX_MPDU];
|
||||
@@ -83,7 +82,6 @@ int main(void)
|
||||
|
||||
datalink_init(NULL);
|
||||
for (;;) {
|
||||
|
||||
/* other tasks */
|
||||
/* BACnet handling */
|
||||
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
|
||||
|
||||
@@ -24,11 +24,10 @@ void uart_init(void)
|
||||
#endif
|
||||
|
||||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
|
||||
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
|
||||
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
|
||||
}
|
||||
|
||||
void uart_putchar(char c,
|
||||
FILE * stream)
|
||||
void uart_putchar(char c, FILE *stream)
|
||||
{
|
||||
if (c == '\n') {
|
||||
uart_putchar('\r', stream);
|
||||
@@ -37,8 +36,8 @@ void uart_putchar(char c,
|
||||
UDR0 = c;
|
||||
}
|
||||
|
||||
char uart_getchar(FILE * stream)
|
||||
char uart_getchar(FILE *stream)
|
||||
{
|
||||
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
|
||||
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
|
||||
return UDR0;
|
||||
}
|
||||
|
||||
+44
-70
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -45,31 +45,16 @@
|
||||
static float Present_Value[MAX_ANALOG_INPUTS];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Analog_Input_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_Input_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_Input_Properties_Optional[] = {
|
||||
PROP_DESCRIPTION,
|
||||
-1
|
||||
};
|
||||
static const int Analog_Input_Properties_Optional[] = { PROP_DESCRIPTION, -1 };
|
||||
|
||||
static const int Analog_Input_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Analog_Input_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Analog_Input_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Analog_Input_Properties_Required;
|
||||
@@ -84,8 +69,7 @@ void Analog_Input_Property_Lists(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
@@ -94,36 +78,32 @@ bool Analog_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
unsigned Analog_Input_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
bool Analog_Input_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[16] = "AI-0"; /* okay for single thread */
|
||||
static char text_string[16] = "AI-0"; /* okay for single thread */
|
||||
bool status = false;
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
status = characterstring_init_ansi(object_name, text_string);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
float Analog_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = 0.0;
|
||||
|
||||
@@ -133,9 +113,7 @@ float Analog_Input_Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
void Analog_Input_Present_Value_Set(
|
||||
uint32_t object_instance,
|
||||
float value)
|
||||
void Analog_Input_Present_Value_Set(uint32_t object_instance, float value)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
Present_Value[object_instance] = value;
|
||||
@@ -144,10 +122,9 @@ void Analog_Input_Present_Value_Set(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object has already exists */
|
||||
int Analog_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint8_t *apdu = NULL;
|
||||
@@ -159,9 +136,8 @@ int Analog_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_ANALOG_INPUT, rpdata->object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
You could make Description writable and different */
|
||||
@@ -176,9 +152,8 @@ int Analog_Input_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
Analog_Input_Present_Value(rpdata->object_instance));
|
||||
apdu_len = encode_application_real(
|
||||
&apdu[0], Analog_Input_Present_Value(rpdata->object_instance));
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
@@ -214,8 +189,7 @@ int Analog_Input_Read_Property(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
void Analog_Input_Init(
|
||||
void)
|
||||
void Analog_Input_Init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+55
-80
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/basic/object/av.h"
|
||||
#include "bacnet/basic/services.h"
|
||||
|
||||
@@ -55,35 +55,21 @@
|
||||
static uint8_t 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_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,
|
||||
static const int Analog_Value_Properties_Optional[] = { PROP_DESCRIPTION,
|
||||
#if 0
|
||||
PROP_PRIORITY_ARRAY,
|
||||
PROP_RELINQUISH_DEFAULT,
|
||||
#endif
|
||||
-1
|
||||
};
|
||||
-1 };
|
||||
|
||||
static const int Analog_Value_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Analog_Value_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Analog_Value_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Analog_Value_Properties_Required;
|
||||
@@ -95,8 +81,7 @@ void Analog_Value_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
void Analog_Value_Init(
|
||||
void)
|
||||
void Analog_Value_Init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@@ -111,8 +96,7 @@ void Analog_Value_Init(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
return true;
|
||||
@@ -122,8 +106,7 @@ bool Analog_Value_Valid_Instance(
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
unsigned Analog_Value_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_VALUES;
|
||||
}
|
||||
@@ -131,8 +114,7 @@ unsigned Analog_Value_Count(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Value_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -140,8 +122,7 @@ uint32_t Analog_Value_Index_To_Instance(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_ANALOG_VALUES;
|
||||
|
||||
@@ -151,8 +132,7 @@ unsigned Analog_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
float Analog_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = ANALOG_RELINQUISH_DEFAULT;
|
||||
unsigned index = 0;
|
||||
@@ -166,14 +146,13 @@ float Analog_Value_Present_Value(
|
||||
}
|
||||
|
||||
bool Analog_Value_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[16] = "AV-0"; /* okay for single thread */
|
||||
static char text_string[16] = "AV-0"; /* okay for single thread */
|
||||
bool status = false;
|
||||
|
||||
if (object_instance < MAX_ANALOG_VALUES) {
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
status = characterstring_init_ansi(object_name, text_string);
|
||||
}
|
||||
|
||||
@@ -181,13 +160,12 @@ bool Analog_Value_Object_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
float real_value = (float) 1.414;
|
||||
float real_value = (float)1.414;
|
||||
#if 0
|
||||
int len = 0;
|
||||
unsigned object_index = 0;
|
||||
@@ -203,9 +181,8 @@ int Analog_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_ANALOG_VALUE, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
@@ -322,10 +299,9 @@ int Analog_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
uint8_t level = ANALOG_LEVEL_NULL;
|
||||
@@ -338,9 +314,8 @@ bool Analog_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -363,19 +338,19 @@ bool Analog_Value_Write_Property(
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Real >= 0.0) && (value.type.Real <= 100.0)) {
|
||||
level = (uint8_t) value.type.Real;
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
level = (uint8_t)value.type.Real;
|
||||
object_index = Analog_Value_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority--;
|
||||
Present_Value[object_index] = level;
|
||||
/* 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) */
|
||||
main loop (i.e. check out of service before changing
|
||||
output) */
|
||||
status = true;
|
||||
} else if (priority == 6) {
|
||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||
|
||||
+42
-66
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 Input Objects customize for your use */
|
||||
|
||||
@@ -43,31 +43,16 @@
|
||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Binary_Input_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_POLARITY,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Input_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_POLARITY, -1 };
|
||||
|
||||
static const int Binary_Input_Properties_Optional[] = {
|
||||
PROP_DESCRIPTION,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Input_Properties_Optional[] = { PROP_DESCRIPTION, -1 };
|
||||
|
||||
static const int Binary_Input_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Binary_Input_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Binary_Input_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired) {
|
||||
*pRequired = Binary_Input_Properties_Required;
|
||||
@@ -82,8 +67,7 @@ void Binary_Input_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
void Binary_Input_Init(
|
||||
void)
|
||||
void Binary_Input_Init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@@ -93,8 +77,7 @@ void Binary_Input_Init(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_INPUTS)
|
||||
return true;
|
||||
@@ -103,15 +86,13 @@ bool Binary_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Input_Count(
|
||||
void)
|
||||
unsigned Binary_Input_Count(void)
|
||||
{
|
||||
return MAX_BINARY_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances.*/
|
||||
uint32_t Binary_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Binary_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -119,8 +100,7 @@ uint32_t Binary_Input_Index_To_Instance(
|
||||
/* 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 Binary_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_INPUTS;
|
||||
|
||||
@@ -130,8 +110,7 @@ unsigned Binary_Input_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
unsigned index = 0;
|
||||
@@ -145,14 +124,13 @@ BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
}
|
||||
|
||||
bool Binary_Input_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[16] = "BI-0"; /* okay for single thread */
|
||||
static char text_string[16] = "BI-0"; /* okay for single thread */
|
||||
bool status = false;
|
||||
|
||||
if (object_instance < MAX_BINARY_INPUTS) {
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
status = characterstring_init_ansi(object_name, text_string);
|
||||
}
|
||||
|
||||
@@ -161,10 +139,9 @@ bool Binary_Input_Object_Name(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object already exists, and has been bounds checked */
|
||||
int Binary_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
||||
@@ -178,9 +155,8 @@ int Binary_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_INPUT, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
/* global variables */
|
||||
unsigned long blinkcount;
|
||||
|
||||
void blinker(
|
||||
unsigned char code)
|
||||
void blinker(unsigned char code)
|
||||
{
|
||||
|
||||
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; /* pointer to PIO register structure */
|
||||
volatile AT91PS_PIO pPIO =
|
||||
AT91C_BASE_PIOA; /* pointer to PIO register structure */
|
||||
volatile unsigned int j, k; /* loop counters */
|
||||
|
||||
/* endless loop */
|
||||
@@ -29,14 +28,17 @@ void blinker(
|
||||
/* turn LED1 (DS1) on */
|
||||
pPIO->PIO_CODR = LED1;
|
||||
/* wait 250 msec */
|
||||
for (k = 600000; k != 0; k--);
|
||||
for (k = 600000; k != 0; k--)
|
||||
;
|
||||
/* turn LED1 (DS1) off */
|
||||
pPIO->PIO_SODR = LED1;
|
||||
/* wait 250 msec */
|
||||
for (k = 600000; k != 0; k--);
|
||||
for (k = 600000; k != 0; k--)
|
||||
;
|
||||
}
|
||||
/* wait 2 seconds */
|
||||
for (k = 5000000; (code != 0) && (k != 0); k--);
|
||||
for (k = 5000000; (code != 0) && (k != 0); k--)
|
||||
;
|
||||
blinkcount++;
|
||||
}
|
||||
}
|
||||
|
||||
+51
-78
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/basic/object/bv.h"
|
||||
#include "bacnet/basic/services.h"
|
||||
|
||||
@@ -45,30 +45,16 @@
|
||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_VALUES];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Binary_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,
|
||||
-1
|
||||
};
|
||||
static const int Binary_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, -1 };
|
||||
|
||||
static const int Binary_Value_Properties_Optional[] = {
|
||||
PROP_DESCRIPTION,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Value_Properties_Optional[] = { PROP_DESCRIPTION, -1 };
|
||||
|
||||
static const int Binary_Value_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Binary_Value_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Binary_Value_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Binary_Value_Properties_Required;
|
||||
@@ -80,8 +66,7 @@ void Binary_Value_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
void Binary_Value_Init(
|
||||
void)
|
||||
void Binary_Value_Init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@@ -91,8 +76,7 @@ void Binary_Value_Init(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_VALUES)
|
||||
return true;
|
||||
@@ -101,22 +85,19 @@ bool Binary_Value_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Value_Count(
|
||||
void)
|
||||
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)
|
||||
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 Binary_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_VALUES;
|
||||
|
||||
@@ -126,8 +107,7 @@ unsigned Binary_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
|
||||
@@ -140,14 +120,13 @@ BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
bool Binary_Value_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[16] = "BV-0"; /* okay for single thread */
|
||||
static char text_string[16] = "BV-0"; /* okay for single thread */
|
||||
bool status = false;
|
||||
|
||||
if (object_instance < MAX_BINARY_VALUES) {
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
status = characterstring_init_ansi(object_name, text_string);
|
||||
}
|
||||
|
||||
@@ -155,10 +134,9 @@ bool Binary_Value_Object_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Binary_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
@@ -173,9 +151,8 @@ int Binary_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_VALUE, rpdata->object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
You could make Description writable and different */
|
||||
@@ -190,8 +167,7 @@ int Binary_Value_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
present_value =
|
||||
Binary_Value_Present_Value(rpdata->object_instance);
|
||||
present_value = Binary_Value_Present_Value(rpdata->object_instance);
|
||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
@@ -232,10 +208,9 @@ int Binary_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Binary_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
BACNET_BINARY_PV level = BINARY_NULL;
|
||||
@@ -248,9 +223,8 @@ bool Binary_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -273,13 +247,12 @@ bool Binary_Value_Write_Property(
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Enumerated >= MIN_BINARY_PV) &&
|
||||
(value.type.Enumerated <= MAX_BINARY_PV)) {
|
||||
level = value.type.Enumerated;
|
||||
object_index =
|
||||
Binary_Value_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
object_index = Binary_Value_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority--;
|
||||
/* NOTE: this Binary value has no priority array */
|
||||
Present_Value[object_index] = level;
|
||||
|
||||
+143
-212
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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>
|
||||
@@ -50,10 +50,8 @@
|
||||
static const char *BACnet_Version = BACNET_VERSION_TEXT;
|
||||
|
||||
/* forward prototype */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata);
|
||||
bool Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data);
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
static struct my_object_functions {
|
||||
BACNET_OBJECT_TYPE Object_Type;
|
||||
@@ -65,31 +63,28 @@ static struct my_object_functions {
|
||||
read_property_function Object_Read_Property;
|
||||
write_property_function Object_Write_Property;
|
||||
rpm_property_lists_function Object_RPM_List;
|
||||
} Object_Table[] = {
|
||||
{
|
||||
OBJECT_DEVICE, NULL, /* don't init - recursive! */
|
||||
Device_Count, Device_Index_To_Instance,
|
||||
Device_Valid_Object_Instance_Number, Device_Object_Name,
|
||||
Device_Read_Property_Local, Device_Write_Property_Local,
|
||||
Device_Property_Lists}, {
|
||||
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
|
||||
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
|
||||
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
|
||||
Analog_Input_Property_Lists}, {
|
||||
OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
|
||||
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
|
||||
Analog_Value_Object_Name, Analog_Value_Read_Property,
|
||||
Analog_Value_Write_Property, Analog_Value_Property_Lists}, {
|
||||
OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count,
|
||||
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance,
|
||||
Binary_Input_Object_Name, Binary_Input_Read_Property, NULL,
|
||||
Binary_Input_Property_Lists}, {
|
||||
OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
|
||||
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
|
||||
Binary_Value_Object_Name, Binary_Value_Read_Property,
|
||||
Binary_Value_Write_Property, Binary_Value_Property_Lists}, {
|
||||
MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
|
||||
Device_Count, Device_Index_To_Instance,
|
||||
Device_Valid_Object_Instance_Number,
|
||||
Device_Object_Name, Device_Read_Property_Local,
|
||||
Device_Write_Property_Local, Device_Property_Lists },
|
||||
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
|
||||
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
|
||||
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
|
||||
Analog_Input_Property_Lists },
|
||||
{ OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
|
||||
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
|
||||
Analog_Value_Object_Name, Analog_Value_Read_Property,
|
||||
Analog_Value_Write_Property, Analog_Value_Property_Lists },
|
||||
{ OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count,
|
||||
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance,
|
||||
Binary_Input_Object_Name, Binary_Input_Read_Property, NULL,
|
||||
Binary_Input_Property_Lists },
|
||||
{ OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
|
||||
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
|
||||
Binary_Value_Object_Name, Binary_Value_Read_Property,
|
||||
Binary_Value_Write_Property, Binary_Value_Property_Lists },
|
||||
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
@@ -103,42 +98,21 @@ static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
||||
static const char *Reinit_Password = "rehmite";
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Device_Properties_Required[] = {
|
||||
PROP_OBJECT_IDENTIFIER,
|
||||
PROP_OBJECT_NAME,
|
||||
PROP_OBJECT_TYPE,
|
||||
PROP_SYSTEM_STATUS,
|
||||
PROP_VENDOR_NAME,
|
||||
PROP_VENDOR_IDENTIFIER,
|
||||
PROP_MODEL_NAME,
|
||||
PROP_FIRMWARE_REVISION,
|
||||
PROP_APPLICATION_SOFTWARE_VERSION,
|
||||
PROP_PROTOCOL_VERSION,
|
||||
PROP_PROTOCOL_REVISION,
|
||||
PROP_PROTOCOL_SERVICES_SUPPORTED,
|
||||
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
|
||||
PROP_OBJECT_LIST,
|
||||
PROP_MAX_APDU_LENGTH_ACCEPTED,
|
||||
PROP_SEGMENTATION_SUPPORTED,
|
||||
PROP_APDU_TIMEOUT,
|
||||
PROP_NUMBER_OF_APDU_RETRIES,
|
||||
PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES,
|
||||
PROP_DEVICE_ADDRESS_BINDING,
|
||||
PROP_DATABASE_REVISION,
|
||||
-1
|
||||
};
|
||||
static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
|
||||
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_SYSTEM_STATUS, PROP_VENDOR_NAME,
|
||||
PROP_VENDOR_IDENTIFIER, PROP_MODEL_NAME, PROP_FIRMWARE_REVISION,
|
||||
PROP_APPLICATION_SOFTWARE_VERSION, PROP_PROTOCOL_VERSION,
|
||||
PROP_PROTOCOL_REVISION, PROP_PROTOCOL_SERVICES_SUPPORTED,
|
||||
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED, PROP_OBJECT_LIST,
|
||||
PROP_MAX_APDU_LENGTH_ACCEPTED, PROP_SEGMENTATION_SUPPORTED,
|
||||
PROP_APDU_TIMEOUT, PROP_NUMBER_OF_APDU_RETRIES, PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES, PROP_DEVICE_ADDRESS_BINDING, PROP_DATABASE_REVISION,
|
||||
-1 };
|
||||
|
||||
static const int Device_Properties_Optional[] = {
|
||||
PROP_DESCRIPTION,
|
||||
PROP_LOCATION,
|
||||
-1
|
||||
};
|
||||
static const int Device_Properties_Optional[] = { PROP_DESCRIPTION,
|
||||
PROP_LOCATION, -1 };
|
||||
|
||||
static const int Device_Properties_Proprietary[] = {
|
||||
9600,
|
||||
-1
|
||||
};
|
||||
static const int Device_Properties_Proprietary[] = { 9600, -1 };
|
||||
|
||||
static struct my_object_functions *Device_Objects_Find_Functions(
|
||||
BACNET_OBJECT_TYPE Object_Type)
|
||||
@@ -159,8 +133,7 @@ static struct my_object_functions *Device_Objects_Find_Functions(
|
||||
}
|
||||
|
||||
static int Read_Property_Common(
|
||||
struct my_object_functions *pObject,
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
struct my_object_functions *pObject, BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
@@ -184,9 +157,8 @@ static int Read_Property_Common(
|
||||
if (rpdata->object_type == OBJECT_DEVICE) {
|
||||
rpdata->object_instance = Object_Instance_Number;
|
||||
}
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], rpdata->object_type,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], rpdata->object_type, rpdata->object_instance);
|
||||
}
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
@@ -198,12 +170,11 @@ static int Read_Property_Common(
|
||||
} else {
|
||||
characterstring_init_ansi(&char_string, "");
|
||||
if (pObject->Object_Name) {
|
||||
(void) pObject->Object_Name(rpdata->object_instance,
|
||||
&char_string);
|
||||
(void)pObject->Object_Name(
|
||||
rpdata->object_instance, &char_string);
|
||||
}
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0],
|
||||
&char_string);
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
}
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
@@ -213,9 +184,8 @@ static int Read_Property_Common(
|
||||
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
} else {
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
rpdata->object_type);
|
||||
apdu_len = encode_application_enumerated(
|
||||
&apdu[0], rpdata->object_type);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -230,8 +200,7 @@ static int Read_Property_Common(
|
||||
|
||||
/* Encodes the property APDU and returns the length,
|
||||
or sets the error, and returns BACNET_STATUS_ERROR */
|
||||
int Device_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
struct my_object_functions *pObject = NULL;
|
||||
@@ -254,8 +223,7 @@ int Device_Read_Property(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false;
|
||||
struct my_object_functions *pObject = NULL;
|
||||
@@ -284,8 +252,7 @@ bool Device_Write_Property(
|
||||
}
|
||||
|
||||
/* for a given object type, returns the special property list */
|
||||
void Device_Objects_Property_List(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
struct special_property_list_t *pPropertyList)
|
||||
{
|
||||
@@ -308,25 +275,23 @@ void Device_Objects_Property_List(
|
||||
}
|
||||
|
||||
/* Fetch the counts if available otherwise zero them */
|
||||
pPropertyList->Required.count =
|
||||
pPropertyList->Required.pList ==
|
||||
NULL ? 0 : property_list_count(pPropertyList->Required.pList);
|
||||
pPropertyList->Required.count = pPropertyList->Required.pList == NULL
|
||||
? 0
|
||||
: property_list_count(pPropertyList->Required.pList);
|
||||
|
||||
pPropertyList->Optional.count =
|
||||
pPropertyList->Optional.pList ==
|
||||
NULL ? 0 : property_list_count(pPropertyList->Optional.pList);
|
||||
pPropertyList->Optional.count = pPropertyList->Optional.pList == NULL
|
||||
? 0
|
||||
: property_list_count(pPropertyList->Optional.pList);
|
||||
|
||||
pPropertyList->Proprietary.count =
|
||||
pPropertyList->Proprietary.pList ==
|
||||
NULL ? 0 : property_list_count(pPropertyList->Proprietary.pList);
|
||||
pPropertyList->Proprietary.count = pPropertyList->Proprietary.pList == NULL
|
||||
? 0
|
||||
: property_list_count(pPropertyList->Proprietary.pList);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Device_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Device_Properties_Required;
|
||||
@@ -338,22 +303,19 @@ void Device_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned Device_Count(
|
||||
void)
|
||||
unsigned Device_Count(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t Device_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Device_Index_To_Instance(unsigned index)
|
||||
{
|
||||
index = index;
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -364,10 +326,9 @@ bool Device_Object_Name(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Name(
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
bool status = false; /*return value */
|
||||
bool status = false; /*return value */
|
||||
|
||||
if (!characterstring_same(&My_Object_Name, object_name)) {
|
||||
/* Make the change and update the database revision */
|
||||
@@ -378,8 +339,7 @@ bool Device_Set_Object_Name(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Reinitialize(
|
||||
BACNET_REINITIALIZE_DEVICE_DATA * rd_data)
|
||||
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -422,20 +382,18 @@ bool Device_Reinitialize(
|
||||
return status;
|
||||
}
|
||||
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(
|
||||
void)
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(void)
|
||||
{
|
||||
return Reinitialize_State;
|
||||
}
|
||||
|
||||
void Device_Init(
|
||||
object_functions_t * object_table)
|
||||
void Device_Init(object_functions_t *object_table)
|
||||
{
|
||||
struct my_object_functions *pObject = NULL;
|
||||
|
||||
/* we don't use the object table passed in
|
||||
since there is extra stuff we don't need in there. */
|
||||
(void) object_table;
|
||||
(void)object_table;
|
||||
/* our local object table */
|
||||
pObject = &Object_Table[0];
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
@@ -450,14 +408,12 @@ void Device_Init(
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
@@ -469,21 +425,17 @@ bool Device_Set_Object_Instance_Number(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
return (Object_Instance_Number == object_id);
|
||||
}
|
||||
|
||||
BACNET_DEVICE_STATUS Device_System_Status(
|
||||
void)
|
||||
BACNET_DEVICE_STATUS Device_System_Status(void)
|
||||
{
|
||||
return System_Status;
|
||||
}
|
||||
|
||||
int Device_Set_System_Status(
|
||||
BACNET_DEVICE_STATUS status,
|
||||
bool local)
|
||||
int Device_Set_System_Status(BACNET_DEVICE_STATUS status, bool local)
|
||||
{
|
||||
/*return value - 0 = ok, -1 = bad value, -2 = not allowed */
|
||||
int result = -1;
|
||||
@@ -496,34 +448,29 @@ int Device_Set_System_Status(
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(
|
||||
void)
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
|
||||
{
|
||||
return SEGMENTATION_NONE;
|
||||
}
|
||||
|
||||
uint32_t Device_Database_Revision(
|
||||
void)
|
||||
uint32_t Device_Database_Revision(void)
|
||||
{
|
||||
return Database_Revision;
|
||||
}
|
||||
|
||||
void Device_Inc_Database_Revision(
|
||||
void)
|
||||
void Device_Inc_Database_Revision(void)
|
||||
{
|
||||
Database_Revision++;
|
||||
}
|
||||
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 0; /* number of objects */
|
||||
struct my_object_functions *pObject = NULL;
|
||||
@@ -541,9 +488,7 @@ unsigned Device_Object_List_Count(
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(
|
||||
uint32_t array_index,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * instance)
|
||||
uint32_t array_index, BACNET_OBJECT_TYPE *object_type, uint32_t *instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t count = 0;
|
||||
@@ -574,10 +519,9 @@ bool Device_Object_List_Identifier(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Name(
|
||||
BACNET_CHARACTER_STRING * object_name1,
|
||||
bool Device_Valid_Object_Name(BACNET_CHARACTER_STRING *object_name1,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * object_instance)
|
||||
uint32_t *object_instance)
|
||||
{
|
||||
bool found = false;
|
||||
BACNET_OBJECT_TYPE type = OBJECT_NONE;
|
||||
@@ -591,7 +535,7 @@ bool Device_Valid_Object_Name(
|
||||
for (i = 1; i <= max_objects; i++) {
|
||||
check_id = Device_Object_List_Identifier(i, &type, &instance);
|
||||
if (check_id) {
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE) type);
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE)type);
|
||||
if ((pObject != NULL) && (pObject->Object_Name != NULL) &&
|
||||
(pObject->Object_Name(instance, &object_name2) &&
|
||||
characterstring_same(object_name1, &object_name2))) {
|
||||
@@ -611,13 +555,12 @@ bool Device_Valid_Object_Name(
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Id(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance)
|
||||
BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
struct my_object_functions *pObject = NULL;
|
||||
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE) object_type);
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE)object_type);
|
||||
if ((pObject != NULL) && (pObject->Object_Valid_Instance != NULL)) {
|
||||
status = pObject->Object_Valid_Instance(object_instance);
|
||||
}
|
||||
@@ -625,10 +568,9 @@ bool Device_Valid_Object_Id(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Object_Name_Copy(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
bool Device_Object_Name_Copy(BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
struct my_object_functions *pObject = NULL;
|
||||
bool found = false;
|
||||
@@ -642,11 +584,10 @@ bool Device_Object_Name_Copy(
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or BACNET_STATUS_ERROR for error */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint32_t i = 0;
|
||||
@@ -661,7 +602,7 @@ int Device_Read_Property_Local(
|
||||
return 0;
|
||||
}
|
||||
apdu = rpdata->application_data;
|
||||
switch ((int) rpdata->object_property) {
|
||||
switch ((int)rpdata->object_property) {
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string, "BACnet Demo");
|
||||
apdu_len =
|
||||
@@ -674,8 +615,7 @@ int Device_Read_Property_Local(
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_System_Status());
|
||||
encode_application_enumerated(&apdu[0], Device_System_Status());
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
@@ -706,16 +646,15 @@ int Device_Read_Property_Local(
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
BACNET_PROTOCOL_REVISION);
|
||||
encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_REVISION);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED)i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -725,7 +664,7 @@ int Device_Read_Property_Local(
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i, false);
|
||||
}
|
||||
/* set the object types with objects to supported */
|
||||
i = 0;
|
||||
@@ -749,11 +688,10 @@ int Device_Read_Property_Local(
|
||||
/* your maximum APDU size. */
|
||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
if (Device_Object_List_Identifier(i, &object_type,
|
||||
&instance)) {
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
i, &object_type, &instance)) {
|
||||
len = encode_application_object_id(
|
||||
&apdu[apdu_len], object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
@@ -773,11 +711,10 @@ int Device_Read_Property_Local(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(rpdata->array_index,
|
||||
&object_type, &instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
rpdata->array_index, &object_type, &instance))
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], object_type, instance);
|
||||
else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
@@ -789,9 +726,8 @@ int Device_Read_Property_Local(
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_Segmentation_Supported());
|
||||
apdu_len = encode_application_enumerated(
|
||||
&apdu[0], Device_Segmentation_Supported());
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout());
|
||||
@@ -803,14 +739,12 @@ int Device_Read_Property_Local(
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Database_Revision());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Database_Revision());
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
dlmstp_max_info_frames());
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len =
|
||||
@@ -837,19 +771,17 @@ int Device_Read_Property_Local(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value - false=error */
|
||||
bool status = false; /* return value - false=error */
|
||||
int len = 0;
|
||||
uint8_t encoding = 0;
|
||||
size_t length = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -864,12 +796,12 @@ bool Device_Write_Property_Local(
|
||||
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
return false;
|
||||
}
|
||||
switch ((int) wp_data->object_property) {
|
||||
switch ((int)wp_data->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.
|
||||
Object_Id.instance))) {
|
||||
(Device_Set_Object_Instance_Number(
|
||||
value.type.Object_Id.instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
@@ -921,13 +853,13 @@ bool Device_Write_Property_Local(
|
||||
characterstring_encoding(&value.type.Character_String);
|
||||
if (encoding < MAX_CHARACTER_STRING_ENCODING) {
|
||||
/* All the object names in a device must be unique. */
|
||||
if (Device_Valid_Object_Name(&value.type.
|
||||
Character_String, NULL, NULL)) {
|
||||
if (Device_Valid_Object_Name(
|
||||
&value.type.Character_String, NULL, NULL)) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_DUPLICATE_NAME;
|
||||
} else {
|
||||
Device_Set_Object_Name(&value.type.
|
||||
Character_String);
|
||||
Device_Set_Object_Name(
|
||||
&value.type.Character_String);
|
||||
status = true;
|
||||
}
|
||||
} else {
|
||||
@@ -937,8 +869,7 @@ bool Device_Write_Property_Local(
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code =
|
||||
ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
|
||||
+82
-101
@@ -64,19 +64,19 @@ static struct mstp_flag_t {
|
||||
/* A Boolean flag set to TRUE by the Receive State Machine */
|
||||
/* if an invalid frame is received. */
|
||||
/* 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;
|
||||
/* set to TRUE when we get a frame not for us */
|
||||
unsigned ReceivedValidFrameNotForUs:1;
|
||||
unsigned ReceivedValidFrameNotForUs : 1;
|
||||
/* A Boolean flag set to TRUE by the master machine if this node is the */
|
||||
/* only known master node. */
|
||||
unsigned SoleMaster:1;
|
||||
unsigned SoleMaster : 1;
|
||||
/* A Boolean flag set TRUE by the datalink if a
|
||||
packet has been received, but not processed. */
|
||||
unsigned ReceivePacketPending:1;
|
||||
unsigned ReceivePacketPending : 1;
|
||||
} MSTP_Flag;
|
||||
|
||||
/* Used to store the data length of a received frame. */
|
||||
@@ -178,7 +178,11 @@ static uint8_t Nmax_master = 127;
|
||||
#define Tusage_delay 15
|
||||
|
||||
/* 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++; \
|
||||
}
|
||||
|
||||
/* data structure for MS/TP PDU Queue */
|
||||
struct mstp_pdu_packet {
|
||||
@@ -194,27 +198,23 @@ struct mstp_pdu_packet {
|
||||
static struct mstp_pdu_packet PDU_Buffer[MSTP_PDU_PACKET_COUNT];
|
||||
static RING_BUFFER PDU_Queue;
|
||||
|
||||
bool dlmstp_init(
|
||||
char *ifname)
|
||||
bool dlmstp_init(char *ifname)
|
||||
{
|
||||
(void) ifname;
|
||||
(void)ifname;
|
||||
/* initialize hardware */
|
||||
RS485_Initialize();
|
||||
Ringbuf_Init(&PDU_Queue, (uint8_t *) & PDU_Buffer,
|
||||
Ringbuf_Init(&PDU_Queue, (uint8_t *)&PDU_Buffer,
|
||||
sizeof(struct mstp_pdu_packet), MSTP_PDU_PACKET_COUNT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dlmstp_cleanup(
|
||||
void)
|
||||
void dlmstp_cleanup(void)
|
||||
{
|
||||
/* nothing to do for static buffers */
|
||||
}
|
||||
|
||||
void dlmstp_fill_bacnet_address(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t mstp_address)
|
||||
void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -237,11 +237,10 @@ void dlmstp_fill_bacnet_address(
|
||||
}
|
||||
}
|
||||
|
||||
static bool dlmstp_compare_data_expecting_reply(
|
||||
uint8_t * request_pdu,
|
||||
static bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
uint16_t request_pdu_len,
|
||||
uint8_t src_address,
|
||||
uint8_t * reply_pdu,
|
||||
uint8_t *reply_pdu,
|
||||
uint16_t reply_pdu_len,
|
||||
uint8_t dest_address)
|
||||
{
|
||||
@@ -262,9 +261,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the request data */
|
||||
request.address.mac[0] = src_address;
|
||||
request.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&request_pdu[0], NULL, &request.address,
|
||||
&request.npdu_data);
|
||||
offset = npdu_decode(
|
||||
&request_pdu[0], NULL, &request.address, &request.npdu_data);
|
||||
if (request.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
@@ -281,8 +279,7 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the reply data */
|
||||
reply.address.mac[0] = dest_address;
|
||||
reply.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
offset = npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
if (reply.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
@@ -323,7 +320,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (request.npdu_data.protocol_version != reply.npdu_data.protocol_version) {
|
||||
if (request.npdu_data.protocol_version !=
|
||||
reply.npdu_data.protocol_version) {
|
||||
return false;
|
||||
}
|
||||
#if 0
|
||||
@@ -355,15 +353,15 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* (pad): (optional) at most one octet of padding: X'FF' */
|
||||
static void MSTP_Send_Frame(
|
||||
uint8_t frame_type, /* type of frame to send - see defines */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t * data, /* any data to be sent - may be null */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t *data, /* any data to be sent - may be null */
|
||||
uint16_t data_len)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
uint8_t buffer[8]; /* stores the header and data crc */
|
||||
uint16_t i = 0; /* used to calculate CRC for data */
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
uint8_t buffer[8]; /* stores the header and data crc */
|
||||
uint16_t i = 0; /* used to calculate CRC for data */
|
||||
|
||||
/* create the MS/TP header */
|
||||
buffer[0] = 0x55;
|
||||
@@ -397,8 +395,7 @@ static void MSTP_Send_Frame(
|
||||
RS485_Transmitter_Enable(false);
|
||||
}
|
||||
|
||||
static void MSTP_Receive_Frame_FSM(
|
||||
void)
|
||||
static void MSTP_Receive_Frame_FSM(void)
|
||||
{
|
||||
/* stores the latest received data octet */
|
||||
uint8_t DataRegister = 0;
|
||||
@@ -633,8 +630,7 @@ static void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
|
||||
/* returns true if we need to transition immediately */
|
||||
static bool MSTP_Master_Node_FSM(
|
||||
void)
|
||||
static bool MSTP_Master_Node_FSM(void)
|
||||
{
|
||||
/* The number of frames sent by this node during a single token hold. */
|
||||
/* When this counter reaches the value Nmax_info_frames, the node must */
|
||||
@@ -719,8 +715,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* ReceivedPFM */
|
||||
/* DestinationAddress is equal to TS */
|
||||
if (DestinationAddress == This_Station) {
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
|
||||
MSTP_Send_Frame(FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER,
|
||||
SourceAddress, This_Station, NULL, 0);
|
||||
}
|
||||
break;
|
||||
@@ -738,9 +733,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
}
|
||||
break;
|
||||
case FRAME_TYPE_TEST_REQUEST:
|
||||
MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE,
|
||||
SourceAddress, This_Station, &InputBuffer[0],
|
||||
DataLength);
|
||||
MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, SourceAddress,
|
||||
This_Station, &InputBuffer[0], DataLength);
|
||||
break;
|
||||
case FRAME_TYPE_TEST_RESPONSE:
|
||||
default:
|
||||
@@ -765,14 +759,14 @@ static bool MSTP_Master_Node_FSM(
|
||||
transition_now = true;
|
||||
} else {
|
||||
uint8_t frame_type;
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
if (pkt->data_expecting_reply) {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
|
||||
} else {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station,
|
||||
(uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
FrameCount++;
|
||||
switch (frame_type) {
|
||||
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
|
||||
@@ -792,7 +786,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
break;
|
||||
}
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
}
|
||||
break;
|
||||
case MSTP_MASTER_STATE_WAIT_FOR_REPLY:
|
||||
@@ -903,8 +897,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
may be found in that case. */
|
||||
TokenCount++;
|
||||
/* transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
RetryCount = 0;
|
||||
EventCount = 0;
|
||||
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
|
||||
@@ -918,7 +912,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* no known successor node */
|
||||
Next_Station = This_Station;
|
||||
RetryCount = 0;
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
/* EventCount = 0; removed in Addendum 135-2004d-8 */
|
||||
/* find a new successor to TS */
|
||||
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
@@ -926,10 +920,10 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* ResetMaintenancePFM */
|
||||
Poll_Station = This_Station;
|
||||
/* transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
RetryCount = 0;
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
EventCount = 0;
|
||||
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
|
||||
}
|
||||
@@ -959,8 +953,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* RetrySendToken */
|
||||
RetryCount++;
|
||||
/* Transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
EventCount = 0;
|
||||
/* re-enter the current state to listen for NS */
|
||||
/* to begin using the token. */
|
||||
@@ -1024,15 +1018,15 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* a successor node. */
|
||||
case MSTP_MASTER_STATE_POLL_FOR_MASTER:
|
||||
if (MSTP_Flag.ReceivedValidFrame == true) {
|
||||
if ((DestinationAddress == This_Station)
|
||||
&& (FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
|
||||
if ((DestinationAddress == This_Station) &&
|
||||
(FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
|
||||
/* ReceivedReplyToPFM */
|
||||
MSTP_Flag.SoleMaster = false;
|
||||
Next_Station = SourceAddress;
|
||||
EventCount = 0;
|
||||
/* Transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
Poll_Station = This_Station;
|
||||
TokenCount = 0;
|
||||
RetryCount = 0;
|
||||
@@ -1095,10 +1089,9 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* BACnet Data Expecting Reply, a Test_Request, or */
|
||||
/* a proprietary frame that expects a reply is received. */
|
||||
case MSTP_MASTER_STATE_ANSWER_DATA_REQUEST:
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
if (pkt != NULL) {
|
||||
matched =
|
||||
dlmstp_compare_data_expecting_reply(&InputBuffer[0],
|
||||
matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0],
|
||||
DataLength, SourceAddress, &pkt->buffer[0], pkt->length,
|
||||
pkt->destination_mac);
|
||||
} else {
|
||||
@@ -1119,12 +1112,12 @@ static bool MSTP_Master_Node_FSM(
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station,
|
||||
(uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
Master_State = MSTP_MASTER_STATE_IDLE;
|
||||
/* clear our flag we were holding for comparison */
|
||||
MSTP_Flag.ReceivedValidFrame = false;
|
||||
/* clear the queue */
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
} else if ((Timer_Silence() > Treply_delay) || (pkt != NULL)) {
|
||||
/* DeferredReply */
|
||||
/* If no reply will be available from the higher layers */
|
||||
@@ -1150,8 +1143,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
return transition_now;
|
||||
}
|
||||
|
||||
static void MSTP_Slave_Node_FSM(
|
||||
void)
|
||||
static void MSTP_Slave_Node_FSM(void)
|
||||
{
|
||||
/* packet from the PDU Queue */
|
||||
struct mstp_pdu_packet *pkt;
|
||||
@@ -1185,9 +1177,8 @@ static void MSTP_Slave_Node_FSM(
|
||||
}
|
||||
} else if (MSTP_Flag.ReceivePacketPending) {
|
||||
if (!Ringbuf_Empty(&PDU_Queue)) {
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
matched =
|
||||
dlmstp_compare_data_expecting_reply(&InputBuffer[0],
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0],
|
||||
DataLength, SourceAddress, &pkt->buffer[0], pkt->length,
|
||||
pkt->destination_mac);
|
||||
if (matched) {
|
||||
@@ -1205,8 +1196,8 @@ static void MSTP_Slave_Node_FSM(
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station,
|
||||
(uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
}
|
||||
/* clear our flag we were holding for comparison */
|
||||
MSTP_Flag.ReceivePacketPending = false;
|
||||
@@ -1222,17 +1213,16 @@ static void MSTP_Slave_Node_FSM(
|
||||
}
|
||||
|
||||
/* returns number of bytes sent on success, zero on failure */
|
||||
int dlmstp_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int dlmstp_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int bytes_sent = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
uint16_t i = 0;
|
||||
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Data_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Data_Peek(&PDU_Queue);
|
||||
if (pkt) {
|
||||
pkt->data_expecting_reply = npdu_data->data_expecting_reply;
|
||||
for (i = 0; i < pdu_len; i++) {
|
||||
@@ -1254,13 +1244,12 @@ int dlmstp_send_pdu(
|
||||
}
|
||||
|
||||
/* Return the length of the packet */
|
||||
uint16_t dlmstp_receive(
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t dlmstp_receive(BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
|
||||
/* set the input buffer to the same data storage for zero copy */
|
||||
if (!InputBuffer) {
|
||||
@@ -1302,8 +1291,7 @@ uint16_t dlmstp_receive(
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void dlmstp_set_mac_address(
|
||||
uint8_t mac_address)
|
||||
void dlmstp_set_mac_address(uint8_t mac_address)
|
||||
{
|
||||
/* Master Nodes can only have address 0-127 */
|
||||
if (mac_address <= 127) {
|
||||
@@ -1320,8 +1308,7 @@ void dlmstp_set_mac_address(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_mac_address(
|
||||
void)
|
||||
uint8_t dlmstp_mac_address(void)
|
||||
{
|
||||
return This_Station;
|
||||
}
|
||||
@@ -1333,8 +1320,7 @@ uint8_t dlmstp_mac_address(
|
||||
/* nodes. This may be used to allocate more or less of the available link */
|
||||
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
||||
/* node, its value shall be 1. */
|
||||
void dlmstp_set_max_info_frames(
|
||||
uint8_t max_info_frames)
|
||||
void dlmstp_set_max_info_frames(uint8_t max_info_frames)
|
||||
{
|
||||
if (max_info_frames >= 1) {
|
||||
Nmax_info_frames = max_info_frames;
|
||||
@@ -1348,8 +1334,7 @@ void dlmstp_set_max_info_frames(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_info_frames(
|
||||
void)
|
||||
uint8_t dlmstp_max_info_frames(void)
|
||||
{
|
||||
return Nmax_info_frames;
|
||||
}
|
||||
@@ -1359,8 +1344,7 @@ uint8_t dlmstp_max_info_frames(
|
||||
/* allowable address for master nodes. The value of Max_Master shall be */
|
||||
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
||||
/* its value shall be 127. */
|
||||
void dlmstp_set_max_master(
|
||||
uint8_t max_master)
|
||||
void dlmstp_set_max_master(uint8_t max_master)
|
||||
{
|
||||
if (max_master <= 127) {
|
||||
if (This_Station <= max_master) {
|
||||
@@ -1376,20 +1360,18 @@ void dlmstp_set_max_master(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_master(
|
||||
void)
|
||||
uint8_t dlmstp_max_master(void)
|
||||
{
|
||||
return Nmax_master;
|
||||
}
|
||||
|
||||
void dlmstp_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void dlmstp_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0; /* counter */
|
||||
int i = 0; /* counter */
|
||||
|
||||
my_address->mac_len = 1;
|
||||
my_address->mac[0] = This_Station;
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -1398,16 +1380,15 @@ void dlmstp_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void dlmstp_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 1;
|
||||
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
|
||||
+33
-27
@@ -1,39 +1,42 @@
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* ----------------------------------------------------------------------------
|
||||
*/
|
||||
/* ATMEL Microcontroller Software Support - ROUSSET - */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* ----------------------------------------------------------------------------
|
||||
*/
|
||||
/* The software is delivered "AS IS" without warranty or condition of any */
|
||||
/* kind, either express, implied or statutory. This includes without */
|
||||
/* limitation any warranty or condition with respect to merchantability or */
|
||||
/* fitness for any particular purpose, or against the infringements of */
|
||||
/* intellectual property rights of others. */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* ----------------------------------------------------------------------------
|
||||
*/
|
||||
/* File Name : Cstartup_SAM7.c */
|
||||
/* Object : Low level initializations written in C for IAR tools */
|
||||
/* Object : Low level initializations written in C for IAR tools
|
||||
*/
|
||||
/* 1.0 08/Sep/04 JPP : Creation */
|
||||
/* 1.10 10/Sep/04 JPP : Update AT91C_CKGR_PLLCOUNT filed */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Include the board file description */
|
||||
#include "board.h"
|
||||
|
||||
/* The following functions must be write in ARM mode this function called directly */
|
||||
/* The following functions must be write in ARM mode this function called
|
||||
* directly */
|
||||
/* by exception vector */
|
||||
extern void AT91F_Spurious_handler(
|
||||
void);
|
||||
extern void AT91F_Default_IRQ_handler(
|
||||
void);
|
||||
extern void AT91F_Default_FIQ_handler(
|
||||
void);
|
||||
extern void AT91F_Spurious_handler(void);
|
||||
extern void AT91F_Default_IRQ_handler(void);
|
||||
extern void AT91F_Default_FIQ_handler(void);
|
||||
|
||||
/**---------------------------------------------------------------------------- */
|
||||
/**----------------------------------------------------------------------------
|
||||
*/
|
||||
/** \fn AT91F_LowLevelInit */
|
||||
/** \brief This function performs very low level HW initialization */
|
||||
/** this function can be use a Stack, depending the compilation */
|
||||
/** optimization mode */
|
||||
/**---------------------------------------------------------------------------- */
|
||||
void LowLevelInit(
|
||||
void)
|
||||
/**----------------------------------------------------------------------------
|
||||
*/
|
||||
void LowLevelInit(void)
|
||||
{
|
||||
int i;
|
||||
AT91PS_PMC pPMC = AT91C_BASE_PMC;
|
||||
@@ -57,7 +60,8 @@ void LowLevelInit(
|
||||
pPMC->PMC_MOR = ((AT91C_CKGR_OSCOUNT & (0x06 << 8)) | AT91C_CKGR_MOSCEN);
|
||||
|
||||
/* Wait the startup time */
|
||||
while (!(pPMC->PMC_SR & AT91C_PMC_MOSCS));
|
||||
while (!(pPMC->PMC_SR & AT91C_PMC_MOSCS))
|
||||
;
|
||||
|
||||
/* PMC Clock Generator PLL Register setup */
|
||||
/* */
|
||||
@@ -65,9 +69,11 @@ void LowLevelInit(
|
||||
/* MUL = 72 */
|
||||
/* PLLCOUNT = 10 */
|
||||
/* */
|
||||
/* Main Clock (MAINCK from crystal oscillator) = 18432000 hz (see AT91SAM7-EK schematic) */
|
||||
/* Main Clock (MAINCK from crystal oscillator) = 18432000 hz (see
|
||||
* AT91SAM7-EK schematic) */
|
||||
/* MAINCK / DIV = 18432000/14 = 1316571 hz */
|
||||
/* PLLCK = 1316571 * (MUL + 1) = 1316571 * (72 + 1) = 1316571 * 73 = 96109683 hz */
|
||||
/* PLLCK = 1316571 * (MUL + 1) = 1316571 * (72 + 1) = 1316571 * 73 =
|
||||
* 96109683 hz */
|
||||
/* */
|
||||
/* PLLCOUNT = number of slow clock cycles before the LOCK bit is set */
|
||||
/* in PMC_SR after CKGR_PLLR is written. */
|
||||
@@ -76,12 +82,12 @@ void LowLevelInit(
|
||||
/* */
|
||||
/* OUT = 0 (not used) */
|
||||
/* result: AT91C_CKGR_PLLR = 0x00000000480A0E (PLL Register) */
|
||||
pPMC->PMC_PLLR =
|
||||
((AT91C_CKGR_DIV & 14) | (AT91C_CKGR_PLLCOUNT & (10 << 8)) |
|
||||
(AT91C_CKGR_MUL & (72 << 16)));
|
||||
pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 14) |
|
||||
(AT91C_CKGR_PLLCOUNT & (10 << 8)) | (AT91C_CKGR_MUL & (72 << 16)));
|
||||
|
||||
/* Wait the startup time (until PMC Status register LOCK bit is set) */
|
||||
while (!(pPMC->PMC_SR & AT91C_PMC_LOCK));
|
||||
while (!(pPMC->PMC_SR & AT91C_PMC_LOCK))
|
||||
;
|
||||
|
||||
/* PMC Master Clock (MCK) Register setup */
|
||||
/* */
|
||||
@@ -94,9 +100,9 @@ void LowLevelInit(
|
||||
pPMC->PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_2;
|
||||
|
||||
/* Set up the default interrupts handler vectors */
|
||||
AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler;
|
||||
AT91C_BASE_AIC->AIC_SVR[0] = (int)AT91F_Default_FIQ_handler;
|
||||
for (i = 1; i < 31; i++) {
|
||||
AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler;
|
||||
AT91C_BASE_AIC->AIC_SVR[i] = (int)AT91F_Default_IRQ_handler;
|
||||
}
|
||||
AT91C_BASE_AIC->AIC_SPU = (int) AT91F_Spurious_handler;
|
||||
AT91C_BASE_AIC->AIC_SPU = (int)AT91F_Spurious_handler;
|
||||
}
|
||||
|
||||
+25
-17
@@ -1,32 +1,40 @@
|
||||
/* 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)
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
void AT91F_Spurious_handler(void)
|
||||
{
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
/* Default handler for fast interrupt requests. Infinite loop. */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
void AT91F_Default_FIQ_handler(
|
||||
void)
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
void AT91F_Default_FIQ_handler(void)
|
||||
{
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
/* Default handler for standard interrupt requests. Infinite loop. */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
void AT91F_Default_IRQ_handler(
|
||||
void)
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
void AT91F_Default_IRQ_handler(void)
|
||||
{
|
||||
while (1);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
+18
-23
@@ -1,4 +1,5 @@
|
||||
/* ********************************************************************************************** */
|
||||
/* **********************************************************************************************
|
||||
*/
|
||||
/* */
|
||||
/* File Name : isr.c */
|
||||
/* Title : interrupt enable/disable functions */
|
||||
@@ -12,10 +13,13 @@
|
||||
/* notice remains intact. */
|
||||
/* */
|
||||
/* Note from Jim Lynch: */
|
||||
/* This module was developed by Bill Knight, RO Software and used with his permission. */
|
||||
/* This module was developed by Bill Knight, RO Software and used with his
|
||||
* permission. */
|
||||
/* Taken from the Yahoo LPC2000 User's Group - Files Section 'UT050418A.ZIP' */
|
||||
/* Specifically, the module armVIC.c with the include file references removed */
|
||||
/* ********************************************************************************************** */
|
||||
/* Specifically, the module armVIC.c with the include file references removed
|
||||
*/
|
||||
/* **********************************************************************************************
|
||||
*/
|
||||
#include "at91sam7s256.h"
|
||||
#include "isr.h"
|
||||
|
||||
@@ -23,23 +27,19 @@
|
||||
#define FIQ_MASK 0x00000040
|
||||
#define INT_MASK (IRQ_MASK | FIQ_MASK)
|
||||
|
||||
static inline unsigned __get_cpsr(
|
||||
void)
|
||||
static inline unsigned __get_cpsr(void)
|
||||
{
|
||||
unsigned long retval;
|
||||
asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ );
|
||||
asm volatile(" mrs %0, cpsr" : "=r"(retval) : /* no inputs */);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static inline void __set_cpsr(
|
||||
unsigned val)
|
||||
static inline void __set_cpsr(unsigned val)
|
||||
{
|
||||
asm volatile (
|
||||
" msr cpsr, %0": /* no outputs */ :"r" (val));
|
||||
asm volatile(" msr cpsr, %0" : /* no outputs */ : "r"(val));
|
||||
}
|
||||
|
||||
unsigned disableIRQ(
|
||||
void)
|
||||
unsigned disableIRQ(void)
|
||||
{
|
||||
unsigned _cpsr;
|
||||
_cpsr = __get_cpsr();
|
||||
@@ -47,8 +47,7 @@ unsigned disableIRQ(
|
||||
return _cpsr;
|
||||
}
|
||||
|
||||
unsigned restoreIRQ(
|
||||
unsigned oldCPSR)
|
||||
unsigned restoreIRQ(unsigned oldCPSR)
|
||||
{
|
||||
unsigned _cpsr;
|
||||
|
||||
@@ -57,8 +56,7 @@ unsigned restoreIRQ(
|
||||
return _cpsr;
|
||||
}
|
||||
|
||||
unsigned enableIRQ(
|
||||
void)
|
||||
unsigned enableIRQ(void)
|
||||
{
|
||||
unsigned _cpsr;
|
||||
|
||||
@@ -67,8 +65,7 @@ unsigned enableIRQ(
|
||||
return _cpsr;
|
||||
}
|
||||
|
||||
unsigned disableFIQ(
|
||||
void)
|
||||
unsigned disableFIQ(void)
|
||||
{
|
||||
unsigned _cpsr;
|
||||
|
||||
@@ -77,8 +74,7 @@ unsigned disableFIQ(
|
||||
return _cpsr;
|
||||
}
|
||||
|
||||
unsigned restoreFIQ(
|
||||
unsigned oldCPSR)
|
||||
unsigned restoreFIQ(unsigned oldCPSR)
|
||||
{
|
||||
unsigned _cpsr;
|
||||
|
||||
@@ -87,8 +83,7 @@ unsigned restoreFIQ(
|
||||
return _cpsr;
|
||||
}
|
||||
|
||||
unsigned enableFIQ(
|
||||
void)
|
||||
unsigned enableFIQ(void)
|
||||
{
|
||||
unsigned _cpsr;
|
||||
|
||||
|
||||
+42
-50
@@ -1,28 +1,28 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Portions of the AT91SAM7S startup code were developed by James P Lynch.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Portions of the AT91SAM7S startup code were developed by James P Lynch.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
/* hardware specific */
|
||||
#include "board.h"
|
||||
#include "timer.h"
|
||||
@@ -48,12 +48,9 @@
|
||||
/* ******************************************************* */
|
||||
/* FIXME: use header files? External References */
|
||||
/* ******************************************************* */
|
||||
extern void LowLevelInit(
|
||||
void);
|
||||
extern unsigned enableIRQ(
|
||||
void);
|
||||
extern unsigned enableFIQ(
|
||||
void);
|
||||
extern void LowLevelInit(void);
|
||||
extern unsigned enableIRQ(void);
|
||||
extern unsigned enableFIQ(void);
|
||||
|
||||
/* used by crt.s file */
|
||||
unsigned FiqCount = 0;
|
||||
@@ -64,8 +61,7 @@ static unsigned long LED_Timer_3 = 0;
|
||||
static unsigned long LED_Timer_4 = 1000;
|
||||
static unsigned long DCC_Timer = 1000;
|
||||
|
||||
static inline void millisecond_timer(
|
||||
void)
|
||||
static inline void millisecond_timer(void)
|
||||
{
|
||||
while (Timer_Milliseconds) {
|
||||
Timer_Milliseconds--;
|
||||
@@ -88,8 +84,7 @@ static inline void millisecond_timer(
|
||||
/* note: MS/TP silence timer is updated in ISR */
|
||||
}
|
||||
|
||||
static inline void init(
|
||||
void)
|
||||
static inline void init(void)
|
||||
{
|
||||
unsigned int pcsr;
|
||||
|
||||
@@ -133,8 +128,7 @@ static inline void init(
|
||||
pAIC->AIC_IECR = (1 << AT91C_ID_FIQ);
|
||||
}
|
||||
|
||||
static inline void bacnet_init(
|
||||
void)
|
||||
static inline void bacnet_init(void)
|
||||
{
|
||||
#if defined(BACDL_MSTP)
|
||||
uint8_t MAC_Address = 0x55;
|
||||
@@ -149,31 +143,29 @@ static inline void bacnet_init(
|
||||
/* initialize objects */
|
||||
Device_Init(NULL);
|
||||
/* set up our confirmed service unrecognized service handler - required! */
|
||||
apdu_set_unrecognized_service_handler_handler
|
||||
(handler_unrecognized_service);
|
||||
apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service);
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
/* Set the handlers for any confirmed services that we support. */
|
||||
/* We must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
|
||||
handler_read_property_multiple);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
|
||||
handler_reinitialize_device);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
handler_write_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROP_MULTIPLE, handler_read_property_multiple);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_REINITIALIZE_DEVICE, handler_reinitialize_device);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property);
|
||||
/* handle communication so we can shutup when asked */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||
handler_device_communication_control);
|
||||
}
|
||||
|
||||
static uint8_t Receive_PDU[MAX_MPDU]; /* PDU data */
|
||||
int main(
|
||||
void)
|
||||
static uint8_t Receive_PDU[MAX_MPDU]; /* PDU data */
|
||||
int main(void)
|
||||
{
|
||||
unsigned long IdleCount = 0; /* idle loop blink counter */
|
||||
unsigned long IdleCount = 0; /* idle loop blink counter */
|
||||
bool LED1_Off_Enabled = true;
|
||||
bool LED2_Off_Enabled = true;
|
||||
bool LED3_Off_Enabled = true;
|
||||
|
||||
+90
-100
@@ -1,28 +1,28 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
* RS-485 initialization on AT91SAM7S inspired by Keil Eletronik serial.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
* RS-485 initialization on AT91SAM7S inspired by Keil Eletronik serial.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* The module handles sending data out the RS-485 port */
|
||||
/* and handles receiving data from the RS-485 port. */
|
||||
@@ -52,18 +52,17 @@ static int RS485_Baud = 38400;
|
||||
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
|
||||
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
|
||||
/* 40 bits is 4 octets including a start and stop bit with each octet */
|
||||
#define Tturnaround (40UL)
|
||||
#define Tturnaround (40UL)
|
||||
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/RS485_Baud; */
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(
|
||||
void)
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(void)
|
||||
{
|
||||
unsigned int pcsr;
|
||||
/* Enable the USART0 clock in the Power Management Controller */
|
||||
@@ -81,17 +80,18 @@ void RS485_Initialize(
|
||||
/* enable the peripheral by disabling the pin in the PIO controller */
|
||||
*AT91C_PIOA_PDR = AT91C_PA5_RXD0 | AT91C_PA6_TXD0 | AT91C_PA7_RTS0;
|
||||
|
||||
RS485_Interface->US_CR = AT91C_US_RSTRX | /* Reset Receiver */
|
||||
AT91C_US_RSTTX | /* Reset Transmitter */
|
||||
AT91C_US_RSTSTA | /* Clear status register */
|
||||
AT91C_US_RXDIS | /* Receiver Disable */
|
||||
RS485_Interface->US_CR = AT91C_US_RSTRX | /* Reset Receiver */
|
||||
AT91C_US_RSTTX | /* Reset Transmitter */
|
||||
AT91C_US_RSTSTA | /* Clear status register */
|
||||
AT91C_US_RXDIS | /* Receiver Disable */
|
||||
AT91C_US_TXDIS; /* Transmitter Disable */
|
||||
|
||||
RS485_Interface->US_MR = AT91C_US_USMODE_RS485 | /* RS-485 Mode - RTS auto assert */
|
||||
AT91C_US_CLKS_CLOCK | /* Clock = MCK */
|
||||
AT91C_US_CHRL_8_BITS | /* 8-bit Data */
|
||||
AT91C_US_PAR_NONE | /* No Parity */
|
||||
AT91C_US_NBSTOP_1_BIT; /* 1 Stop Bit */
|
||||
RS485_Interface->US_MR =
|
||||
AT91C_US_USMODE_RS485 | /* RS-485 Mode - RTS auto assert */
|
||||
AT91C_US_CLKS_CLOCK | /* Clock = MCK */
|
||||
AT91C_US_CHRL_8_BITS | /* 8-bit Data */
|
||||
AT91C_US_PAR_NONE | /* No Parity */
|
||||
AT91C_US_NBSTOP_1_BIT; /* 1 Stop Bit */
|
||||
|
||||
/* set the Time Guard to release RTS after x bit times */
|
||||
RS485_Interface->US_TTGR = 1;
|
||||
@@ -102,38 +102,34 @@ void RS485_Initialize(
|
||||
/* baud rate */
|
||||
RS485_Interface->US_BRGR = MCK / 16 / RS485_Baud;
|
||||
|
||||
RS485_Interface->US_CR = AT91C_US_RXEN | /* Receiver Enable */
|
||||
AT91C_US_TXEN; /* Transmitter Enable */
|
||||
RS485_Interface->US_CR = AT91C_US_RXEN | /* Receiver Enable */
|
||||
AT91C_US_TXEN; /* Transmitter Enable */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void RS485_Cleanup(
|
||||
void)
|
||||
void RS485_Cleanup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void)
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(void)
|
||||
{
|
||||
return RS485_Baud;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud)
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
@@ -157,13 +153,12 @@ bool RS485_Set_Baud_Rate(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(
|
||||
void)
|
||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(void)
|
||||
{
|
||||
uint16_t turnaround_time;
|
||||
|
||||
@@ -177,27 +172,25 @@ void RS485_Turnaround_Delay(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Enable or disable the transmitter
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: The Atmel ARM7 has an automatic enable/disable in RS485 mode.
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable)
|
||||
* DESCRIPTION: Enable or disable the transmitter
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: The Atmel ARM7 has an automatic enable/disable in RS485 mode.
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(bool enable)
|
||||
{
|
||||
(void) enable;
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(uint8_t *buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
/* LED on send */
|
||||
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
|
||||
/* LED ON */
|
||||
@@ -219,13 +212,12 @@ void RS485_Send_Data(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if a framing or overrun error is present
|
||||
* RETURN: true if error
|
||||
* ALGORITHM: none
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(
|
||||
void)
|
||||
* DESCRIPTION: Return true if a framing or overrun error is present
|
||||
* RETURN: true if error
|
||||
* ALGORITHM: none
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(void)
|
||||
{
|
||||
bool ReceiveError = false;
|
||||
/* LED on send */
|
||||
@@ -244,13 +236,12 @@ bool RS485_ReceiveError(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if data is available
|
||||
* RETURN: true if data is available, with the data in the parameter set
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * DataRegister)
|
||||
* DESCRIPTION: Return true if data is available
|
||||
* RETURN: true if data is available, with the data in the parameter set
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(uint8_t *DataRegister)
|
||||
{
|
||||
bool DataAvailable = false;
|
||||
/* LED on send */
|
||||
@@ -270,8 +261,7 @@ bool RS485_DataAvailable(
|
||||
}
|
||||
|
||||
#ifdef TEST_RS485
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
{
|
||||
unsigned i = 0;
|
||||
uint8_t DataRegister;
|
||||
|
||||
+96
-63
@@ -1,4 +1,5 @@
|
||||
/* ***************************************************************************** */
|
||||
/* *****************************************************************************
|
||||
*/
|
||||
/* */
|
||||
/* Purpose: Set up the 16-bit Timer/Counter */
|
||||
/* */
|
||||
@@ -34,8 +35,8 @@
|
||||
/* Modified by Steve Karg */
|
||||
/* Changed timer to 1ms. */
|
||||
/* Encapsulated the intialization */
|
||||
/* ***************************************************************************** */
|
||||
|
||||
/* *****************************************************************************
|
||||
*/
|
||||
|
||||
/**********************************************************
|
||||
Header files
|
||||
@@ -50,18 +51,21 @@ volatile unsigned long Timer_Milliseconds;
|
||||
/* MS/TP Silence Timer */
|
||||
static volatile int SilenceTime;
|
||||
|
||||
static void Timer0_Setup(
|
||||
int milliseconds)
|
||||
static void Timer0_Setup(int milliseconds)
|
||||
{
|
||||
/* TC Block Control Register TC_BCR (read/write) */
|
||||
/* */
|
||||
/* |------------------------------------------------------------------|------| */
|
||||
/* | SYNC | */
|
||||
/* |------------------------------------------------------------------|------| */
|
||||
/* 31 1 0 */
|
||||
/* |------------------------------------------------------------------|------|
|
||||
*/
|
||||
/* | SYNC | */
|
||||
/* |------------------------------------------------------------------|------|
|
||||
*/
|
||||
/* 31 1 0
|
||||
*/
|
||||
/* */
|
||||
/* SYNC = 0 (no effect) <===== take default */
|
||||
/* SYNC = 1 (generate software trigger for all 3 timer channels simultaneously) */
|
||||
/* SYNC = 1 (generate software trigger for all 3 timer channels
|
||||
* simultaneously) */
|
||||
/* */
|
||||
/* create a pointer to TC Global Register structure */
|
||||
AT91PS_TCB pTCB = AT91C_BASE_TCB;
|
||||
@@ -70,10 +74,13 @@ static void Timer0_Setup(
|
||||
|
||||
/* TC Block Mode Register TC_BMR (read/write) */
|
||||
/* */
|
||||
/* |-------------------------------------|-----------|-----------|-----------| */
|
||||
/* | TC2XC2S TCXC1S TC0XC0S | */
|
||||
/* |-------------------------------------|-----------|-----------|-----------| */
|
||||
/* 31 5 4 3 2 1 0 */
|
||||
/* |-------------------------------------|-----------|-----------|-----------|
|
||||
*/
|
||||
/* | TC2XC2S TCXC1S TC0XC0S
|
||||
* | */
|
||||
/* |-------------------------------------|-----------|-----------|-----------|
|
||||
*/
|
||||
/* 31 5 4 3 2 1 0 */
|
||||
/* */
|
||||
/* TC0XC0S Select = 00 TCLK0 (PA4) */
|
||||
/* = 01 none <===== we select this one */
|
||||
@@ -93,13 +100,16 @@ static void Timer0_Setup(
|
||||
/* external clocks not used */
|
||||
pTCB->TCB_BMR = 0x15;
|
||||
|
||||
|
||||
/* TC Channel Control Register TC_CCR (read/write) */
|
||||
/* */
|
||||
/* |----------------------------------|--------------|------------|-----------| */
|
||||
/* | SWTRG CLKDIS CLKENS | */
|
||||
/* |----------------------------------|--------------|------------|-----------| */
|
||||
/* 31 2 1 0 */
|
||||
/* |----------------------------------|--------------|------------|-----------|
|
||||
*/
|
||||
/* | SWTRG CLKDIS CLKENS
|
||||
* | */
|
||||
/* |----------------------------------|--------------|------------|-----------|
|
||||
*/
|
||||
/* 31 2 1 0
|
||||
*/
|
||||
/* */
|
||||
/* CLKEN = 0 no effect */
|
||||
/* CLKEN = 1 enables the clock <===== we select this one */
|
||||
@@ -108,7 +118,8 @@ static void Timer0_Setup(
|
||||
/* CLKDIS = 1 disables the clock */
|
||||
/* */
|
||||
/* SWTRG = 0 no effect */
|
||||
/* SWTRG = 1 software trigger aserted counter reset and clock starts <===== we select this one */
|
||||
/* SWTRG = 1 software trigger aserted counter reset and clock starts
|
||||
* <===== we select this one */
|
||||
/* */
|
||||
/* create a pointer to channel 0 Register structure */
|
||||
AT91PS_TC pTC = AT91C_BASE_TC0;
|
||||
@@ -137,27 +148,32 @@ static void Timer0_Setup(
|
||||
/* 001 TIMER_CLOCK2 (MCK/8 = 6006855 hz) */
|
||||
/* 010 TIMER_CLOCK3 (MCK/32 = 1501713 hz) */
|
||||
/* 011 TIMER_CLOCK4 (MCK/128 = 375428 hz) */
|
||||
/* 100 TIMER_CLOCK5 (MCK/1024 = 46928 hz) <===== we select this one */
|
||||
/* 100 TIMER_CLOCK5 (MCK/1024 = 46928 hz) <===== we
|
||||
* select this one */
|
||||
/* 101 XC0 */
|
||||
/* 101 XC1 */
|
||||
/* 101 XC2 */
|
||||
/* */
|
||||
/* CLOCK INVERT */
|
||||
/* CLKI = 0 counter incremented on rising clock edge <===== we select this one */
|
||||
/* CLKI = 0 counter incremented on rising clock edge <===== we
|
||||
* select this one */
|
||||
/* CLKI = 1 counter incremented on falling clock edge */
|
||||
/* */
|
||||
/* BURST SIGNAL SELECTION */
|
||||
/* BURST = 00 clock is not gated by any external system <===== take default */
|
||||
/* BURST = 00 clock is not gated by any external system <===== take
|
||||
* default */
|
||||
/* 01 XC0 is anded with the clock */
|
||||
/* 10 XC1 is anded with the clock */
|
||||
/* 11 XC2 is anded with the clock */
|
||||
/* */
|
||||
/* COUNTER CLOCK STOPPED WITH RB LOADING */
|
||||
/* LDBSTOP = 0 counter clock is not stopped when RB loading occurs <===== take default */
|
||||
/* LDBSTOP = 0 counter clock is not stopped when RB loading occurs
|
||||
* <===== take default */
|
||||
/* = 1 counter clock is stopped when RB loading occur */
|
||||
/* */
|
||||
/* COUNTER CLOCK DISABLE WITH RB LOADING */
|
||||
/* LDBDIS = 0 counter clock is not disabled when RB loading occurs <===== take default */
|
||||
/* LDBDIS = 0 counter clock is not disabled when RB loading occurs
|
||||
* <===== take default */
|
||||
/* = 1 counter clock is disabled when RB loading occurs */
|
||||
/* */
|
||||
/* EXTERNAL TRIGGER EDGE SELECTION */
|
||||
@@ -172,7 +188,8 @@ static void Timer0_Setup(
|
||||
/* */
|
||||
/* RC COMPARE TRIGGER ENABLE */
|
||||
/* CPCTRG = 0 (RC Compare has no effect on the counter and its clock) */
|
||||
/* 1 (RC Compare resets the counter and starts the clock) <===== we select this one */
|
||||
/* 1 (RC Compare resets the counter and starts the clock)
|
||||
* <===== we select this one */
|
||||
/* */
|
||||
/* WAVE */
|
||||
/* WAVE = 0 Capture Mode is enabled <===== we select this one */
|
||||
@@ -195,12 +212,15 @@ static void Timer0_Setup(
|
||||
/* WAVE = 0 (Capture mode enabled) */
|
||||
pTC->TC_CMR = 0x4004;
|
||||
|
||||
/* TC Register C TC_RC (read/write) Compare Register 16-bits */
|
||||
/* TC Register C TC_RC (read/write) Compare Register 16-bits
|
||||
*/
|
||||
/* */
|
||||
/* |----------------------------------|----------------------------------------| */
|
||||
/* | not used RC | */
|
||||
/* |----------------------------------|----------------------------------------| */
|
||||
/* 31 16 15 0 */
|
||||
/* |----------------------------------|----------------------------------------|
|
||||
*/
|
||||
/* | not used RC | */
|
||||
/* |----------------------------------|----------------------------------------|
|
||||
*/
|
||||
/* 31 16 15 0 */
|
||||
/* */
|
||||
/* Timer Calculation: What count gives 1 msec time-out? */
|
||||
/* */
|
||||
@@ -221,10 +241,14 @@ static void Timer0_Setup(
|
||||
/* TC Interrupt Enable Register TC_IER (write-only) */
|
||||
/* */
|
||||
/* */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------| */
|
||||
/* | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS COVFS | */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------| */
|
||||
/* 31 8 7 6 5 4 3 2 1 0 */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------|
|
||||
*/
|
||||
/* | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS
|
||||
* COVFS | */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------|
|
||||
*/
|
||||
/* 31 8 7 6 5 4 3 2 1
|
||||
* 0 */
|
||||
/* */
|
||||
/* COVFS = 0 no effect <===== take default */
|
||||
/* 1 enable counter overflow interrupt */
|
||||
@@ -239,7 +263,8 @@ static void Timer0_Setup(
|
||||
/* 1 enable RB compare interrupt */
|
||||
/* */
|
||||
/* CPCS = 0 no effect */
|
||||
/* 1 enable RC compare interrupt <===== we select this one */
|
||||
/* 1 enable RC compare interrupt <===== we select this one
|
||||
*/
|
||||
/* */
|
||||
/* LDRAS = 0 no effect <===== take default */
|
||||
/* 1 enable RA load interrupt */
|
||||
@@ -256,22 +281,30 @@ static void Timer0_Setup(
|
||||
/* TC Interrupt Disable Register TC_IDR (write-only) */
|
||||
/* */
|
||||
/* */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------| */
|
||||
/* | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS COVFS | */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------| */
|
||||
/* 31 8 7 6 5 4 3 2 1 0 */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------|
|
||||
*/
|
||||
/* | ETRGS LDRBS LDRAS CPCS CPBS CPAS LOVRS
|
||||
* COVFS | */
|
||||
/* |------------|-------|-------|-------|-------|--------|--------|--------|--------|
|
||||
*/
|
||||
/* 31 8 7 6 5 4 3 2 1
|
||||
* 0 */
|
||||
/* */
|
||||
/* COVFS = 0 no effect */
|
||||
/* 1 disable counter overflow interrupt <===== we select this one */
|
||||
/* 1 disable counter overflow interrupt <===== we select
|
||||
* this one */
|
||||
/* */
|
||||
/* LOVRS = 0 no effect */
|
||||
/* 1 disable load overrun interrupt <===== we select this one */
|
||||
/* 1 disable load overrun interrupt <===== we select this
|
||||
* one */
|
||||
/* */
|
||||
/* CPAS = 0 no effect */
|
||||
/* 1 disable RA compare interrupt <===== we select this one */
|
||||
/* 1 disable RA compare interrupt <===== we select this one
|
||||
*/
|
||||
/* */
|
||||
/* CPBS = 0 no effect */
|
||||
/* 1 disable RB compare interrupt <===== we select this one */
|
||||
/* 1 disable RB compare interrupt <===== we select this one
|
||||
*/
|
||||
/* */
|
||||
/* CPCS = 0 no effect <===== take default */
|
||||
/* 1 disable RC compare interrupt */
|
||||
@@ -283,13 +316,15 @@ static void Timer0_Setup(
|
||||
/* 1 disable RB load interrupt <===== we select this one */
|
||||
/* */
|
||||
/* ETRGS = 0 no effect */
|
||||
/* 1 disable External Trigger interrupt <===== we select this one */
|
||||
/* 1 disable External Trigger interrupt <===== we select
|
||||
* this one */
|
||||
/* */
|
||||
/* disable all except RC compare interrupt */
|
||||
pTC->TC_IDR = 0xEF;
|
||||
}
|
||||
|
||||
/* ***************************************************************************** */
|
||||
/* *****************************************************************************
|
||||
*/
|
||||
/* */
|
||||
/* Timer 0 Interrupt Service Routine */
|
||||
/* */
|
||||
@@ -298,13 +333,13 @@ static void Timer0_Setup(
|
||||
/* Author: James P Lynch May 12, 2007 */
|
||||
/* Modified by Steve Karg */
|
||||
/* simplified and changed to a millisecond count-up timer */
|
||||
/* ***************************************************************************** */
|
||||
static void Timer0IrqHandler(
|
||||
void)
|
||||
/* *****************************************************************************
|
||||
*/
|
||||
static void Timer0IrqHandler(void)
|
||||
{
|
||||
|
||||
volatile AT91PS_TC pTC = AT91C_BASE_TC0; /* pointer to timer channel 0 register structure */
|
||||
volatile unsigned int dummy; /* temporary */
|
||||
volatile AT91PS_TC pTC =
|
||||
AT91C_BASE_TC0; /* pointer to timer channel 0 register structure */
|
||||
volatile unsigned int dummy; /* temporary */
|
||||
|
||||
/* read TC0 Status Register to clear interrupt */
|
||||
dummy = pTC->TC_SR;
|
||||
@@ -316,19 +351,18 @@ static void Timer0IrqHandler(
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
int Timer_Silence(
|
||||
void)
|
||||
int Timer_Silence(void)
|
||||
{
|
||||
return SilenceTime;
|
||||
}
|
||||
|
||||
void Timer_Silence_Reset(
|
||||
void)
|
||||
void Timer_Silence_Reset(void)
|
||||
{
|
||||
SilenceTime = 0;
|
||||
}
|
||||
|
||||
/* ***************************************************************************** */
|
||||
/* *****************************************************************************
|
||||
*/
|
||||
/* */
|
||||
/* Timer 0 Initialization */
|
||||
/* */
|
||||
@@ -336,9 +370,9 @@ void Timer_Silence_Reset(
|
||||
/* Modified by Steve Karg */
|
||||
/* Moved timer startup code from main */
|
||||
/* modified the peripheral clock init */
|
||||
/* ***************************************************************************** */
|
||||
void TimerInit(
|
||||
void)
|
||||
/* *****************************************************************************
|
||||
*/
|
||||
void TimerInit(void)
|
||||
{
|
||||
unsigned int pcsr;
|
||||
/* enable the Timer0 peripheral clock */
|
||||
@@ -353,11 +387,10 @@ void TimerInit(
|
||||
pAIC->AIC_IDCR = (1 << AT91C_ID_TC0);
|
||||
/* Set the TC0 IRQ handler address in */
|
||||
/* AIC Source Vector Register[12] */
|
||||
pAIC->AIC_SVR[AT91C_ID_TC0] = (unsigned int) Timer0IrqHandler;
|
||||
pAIC->AIC_SVR[AT91C_ID_TC0] = (unsigned int)Timer0IrqHandler;
|
||||
/* Set the interrupt source type and priority */
|
||||
/* in AIC Source Mode Register[12] */
|
||||
pAIC->AIC_SMR[AT91C_ID_TC0] =
|
||||
(AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 0x4);
|
||||
pAIC->AIC_SMR[AT91C_ID_TC0] = (AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 0x4);
|
||||
/* Clear the TC0 interrupt */
|
||||
/* in AIC Interrupt Clear Command Register */
|
||||
pAIC->AIC_ICCR = (1 << AT91C_ID_TC0);
|
||||
|
||||
+39
-48
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -44,8 +44,7 @@ float Present_Value[MAX_ANALOG_INPUTS];
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
@@ -54,34 +53,29 @@ bool Analog_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
unsigned Analog_Input_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Analog_Input_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
|
||||
char *Analog_Input_Name(
|
||||
uint32_t object_instance)
|
||||
char *Analog_Input_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AI-0"; /* okay for single thread */
|
||||
static char text_string[5] = "AI-0"; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
return text_string;
|
||||
}
|
||||
|
||||
@@ -90,34 +84,31 @@ char *Analog_Input_Name(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object has already exists */
|
||||
int Analog_Input_Encode_Property_APDU(
|
||||
uint8_t * apdu,
|
||||
int Analog_Input_Encode_Property_APDU(uint8_t *apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
uint32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
|
||||
|
||||
(void) array_index;
|
||||
(void)array_index;
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
object_instance);
|
||||
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));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Analog_Input_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
|
||||
+14
-16
@@ -41,8 +41,7 @@
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/basic/services.h"
|
||||
|
||||
bool apdu_service_supported(
|
||||
BACNET_SERVICES_SUPPORTED service_supported)
|
||||
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -61,15 +60,14 @@ bool apdu_service_supported(
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t apdu_decode_confirmed_service_request(
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_decode_confirmed_service_request(uint8_t *apdu, /* APDU data */
|
||||
uint16_t apdu_len,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||
uint8_t * service_choice,
|
||||
uint8_t ** service_request,
|
||||
uint16_t * service_request_len)
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data,
|
||||
uint8_t *service_choice,
|
||||
uint8_t **service_request,
|
||||
uint16_t *service_request_len)
|
||||
{
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
service_data->segmented_message = (apdu[0] & BIT(3)) ? true : false;
|
||||
service_data->more_follows = (apdu[0] & BIT(2)) ? true : false;
|
||||
@@ -90,22 +88,22 @@ uint16_t apdu_decode_confirmed_service_request(
|
||||
return len;
|
||||
}
|
||||
|
||||
void apdu_handler(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * apdu, /* APDU data */
|
||||
void apdu_handler(BACNET_ADDRESS *src,
|
||||
uint8_t *apdu, /* APDU data */
|
||||
uint16_t apdu_len)
|
||||
{
|
||||
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
|
||||
uint8_t service_choice = 0;
|
||||
uint8_t *service_request = NULL;
|
||||
uint16_t service_request_len = 0;
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
if (apdu) {
|
||||
/* PDU Type */
|
||||
switch (apdu[0] & 0xF0) {
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
len = apdu_decode_confirmed_service_request(
|
||||
&apdu[0], /* APDU data */
|
||||
apdu_len, &service_data, &service_choice, &service_request,
|
||||
&service_request_len);
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
@@ -114,8 +112,8 @@ void apdu_handler(
|
||||
}
|
||||
#ifdef WRITE_PROPERTY
|
||||
else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
|
||||
handler_write_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
handler_write_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
|
||||
+50
-65
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/basic/object/av.h"
|
||||
|
||||
@@ -49,8 +49,7 @@ 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)
|
||||
bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
return true;
|
||||
@@ -60,8 +59,7 @@ bool Analog_Value_Valid_Instance(
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
unsigned Analog_Value_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_VALUES;
|
||||
}
|
||||
@@ -69,8 +67,7 @@ unsigned Analog_Value_Count(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Value_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -78,28 +75,25 @@ uint32_t Analog_Value_Index_To_Instance(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Analog_Value_Name(
|
||||
uint32_t object_instance)
|
||||
char *Analog_Value_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AV-"; /* okay for single thread */
|
||||
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
|
||||
return text_string;
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
@@ -108,13 +102,12 @@ int Analog_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_ANALOG_VALUE, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Value_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Analog_Value_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -123,11 +116,10 @@ int Analog_Value_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Value_Instance_To_Index(
|
||||
rpdata->object_instance);
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
AV_Present_Value[object_index]);
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index(rpdata->object_instance);
|
||||
apdu_len = encode_application_real(
|
||||
&apdu[0], AV_Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
@@ -154,8 +146,7 @@ int Analog_Value_Read_Property(
|
||||
break;
|
||||
}
|
||||
/* only array properties can have array options */
|
||||
if ((apdu_len >= 0) &&
|
||||
(rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||
if ((apdu_len >= 0) && (rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
@@ -165,10 +156,9 @@ int Analog_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
@@ -179,9 +169,8 @@ bool Analog_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -233,8 +222,7 @@ bool Analog_Value_Write_Property(
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testAnalog_Value(
|
||||
Test * pTest)
|
||||
void testAnalog_Value(Test *pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 0;
|
||||
@@ -246,14 +234,12 @@ void testAnalog_Value(
|
||||
BACNET_ERROR_CLASS error_class;
|
||||
BACNET_ERROR_CODE error_code;
|
||||
|
||||
len =
|
||||
Analog_Value_Encode_Property_APDU(&apdu[0], instance,
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -261,8 +247,7 @@ void testAnalog_Value(
|
||||
}
|
||||
|
||||
#ifdef TEST_ANALOG_VALUE
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
@@ -274,7 +259,7 @@ int main(
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
(void)ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
|
||||
+50
-66
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/basic/object/bv.h"
|
||||
|
||||
@@ -47,8 +47,7 @@
|
||||
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)
|
||||
bool Binary_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_VALUES)
|
||||
return true;
|
||||
@@ -57,22 +56,19 @@ bool Binary_Value_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Value_Count(
|
||||
void)
|
||||
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)
|
||||
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 Binary_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_VALUES;
|
||||
|
||||
@@ -82,8 +78,7 @@ unsigned Binary_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
|
||||
@@ -95,13 +90,12 @@ BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Binary_Value_Name(
|
||||
uint32_t object_instance)
|
||||
char *Binary_Value_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "BV-0"; /* okay for single thread */
|
||||
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;
|
||||
text_string[3] = '0' + (uint8_t)object_instance;
|
||||
return text_string;
|
||||
}
|
||||
|
||||
@@ -109,10 +103,9 @@ char *Binary_Value_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Binary_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
@@ -122,15 +115,14 @@ int Binary_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_VALUE, rpdata->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(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Binary_Value_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -180,10 +172,9 @@ int Binary_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Binary_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
@@ -194,9 +185,8 @@ bool Binary_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -216,12 +206,11 @@ bool Binary_Value_Write_Property(
|
||||
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);
|
||||
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;
|
||||
(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
|
||||
@@ -277,8 +266,7 @@ bool Binary_Value_Write_Property(
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testBinary_Value(
|
||||
Test * pTest)
|
||||
void testBinary_Value(Test *pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 0;
|
||||
@@ -290,15 +278,12 @@ void testBinary_Value(
|
||||
BACNET_ERROR_CLASS error_class;
|
||||
BACNET_ERROR_CODE error_code;
|
||||
|
||||
|
||||
len =
|
||||
Binary_Value_Encode_Property_APDU(&apdu[0], instance,
|
||||
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);
|
||||
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);
|
||||
|
||||
@@ -306,8 +291,7 @@ void testBinary_Value(
|
||||
}
|
||||
|
||||
#ifdef TEST_BINARY_VALUE
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
@@ -319,7 +303,7 @@ int main(
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
(void)ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
|
||||
+59
-74
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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>
|
||||
@@ -50,8 +50,7 @@ static uint32_t Object_Instance_Number = 260001;
|
||||
static char Object_Name[20] = "My Device";
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
|
||||
void Device_Init(
|
||||
object_functions_t * object_table)
|
||||
void Device_Init(object_functions_t *object_table)
|
||||
{
|
||||
(void)object_table;
|
||||
/* Reinitialize_State = BACNET_REINIT_IDLE; */
|
||||
@@ -64,14 +63,12 @@ void Device_Init(
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
@@ -89,21 +86,18 @@ bool Device_Set_Object_Instance_Number(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return (Object_Instance_Number == object_id);
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
@@ -115,9 +109,7 @@ unsigned Device_Object_List_Count(
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(
|
||||
uint32_t array_index,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * instance)
|
||||
uint32_t array_index, BACNET_OBJECT_TYPE *object_type, uint32_t *instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t object_index = 0;
|
||||
@@ -163,12 +155,11 @@ bool Device_Object_List_Identifier(
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error */
|
||||
int Device_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
uint8_t * apdu;
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
uint8_t *apdu;
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint32_t i = 0;
|
||||
@@ -179,9 +170,8 @@ int Device_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_DEVICE, Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, Object_Name);
|
||||
@@ -200,9 +190,8 @@ int Device_Read_Property(
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
@@ -225,16 +214,15 @@ int Device_Read_Property(
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
BACNET_PROTOCOL_REVISION);
|
||||
encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_REVISION);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED)i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -245,7 +233,7 @@ int Device_Read_Property(
|
||||
/* must have the bit string as big as it can be */
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
@@ -265,9 +253,8 @@ int Device_Read_Property(
|
||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
Device_Object_List_Identifier(i, &object_type, &instance);
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
len = encode_application_object_id(
|
||||
&apdu[apdu_len], object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
@@ -280,11 +267,10 @@ int Device_Read_Property(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(rpdata->array_index,
|
||||
&object_type, &instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
rpdata->array_index, &object_type, &instance))
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], object_type, instance);
|
||||
else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
@@ -313,8 +299,7 @@ int Device_Read_Property(
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
dlmstp_max_info_frames());
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len =
|
||||
@@ -347,10 +332,9 @@ int Device_Read_Property(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
@@ -360,9 +344,8 @@ bool Device_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -381,8 +364,8 @@ bool Device_Write_Property(
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.
|
||||
Object_Id.instance))) {
|
||||
(Device_Set_Object_Instance_Number(
|
||||
value.type.Object_Id.instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
@@ -436,11 +419,13 @@ bool Device_Write_Property(
|
||||
status = true;
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
wp_data->error_code =
|
||||
ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
|
||||
wp_data->error_code =
|
||||
ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
|
||||
}
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
|
||||
+111
-102
@@ -66,23 +66,23 @@ static struct mstp_flag_t {
|
||||
/* A Boolean flag set to TRUE by the Receive State Machine */
|
||||
/* if an invalid frame is received. */
|
||||
/* 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 to TRUE by the master machine if this node is the */
|
||||
/* only known master node. */
|
||||
unsigned SoleMaster:1;
|
||||
unsigned SoleMaster : 1;
|
||||
/* A Boolean flag set TRUE by the datalink transmit if a
|
||||
frame is pending */
|
||||
unsigned TransmitPacketPending:1;
|
||||
unsigned TransmitPacketPending : 1;
|
||||
/* A Boolean flag set TRUE by the datalink transmit if a
|
||||
pending packet is DataExpectingReply */
|
||||
unsigned TransmitPacketDER:1;
|
||||
unsigned TransmitPacketDER : 1;
|
||||
/* A Boolean flag set TRUE by the datalink if a
|
||||
packet has been received, but not processed. */
|
||||
unsigned ReceivePacketPending:1;
|
||||
unsigned ReceivePacketPending : 1;
|
||||
} MSTP_Flag;
|
||||
|
||||
/* Used to store the data length of a received frame. */
|
||||
@@ -165,10 +165,13 @@ static uint8_t TransmitPacketDest;
|
||||
#define Treply_delay 250
|
||||
|
||||
/* 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++; \
|
||||
}
|
||||
|
||||
bool dlmstp_init(
|
||||
char *ifname)
|
||||
bool dlmstp_init(char *ifname)
|
||||
{
|
||||
ifname = ifname;
|
||||
/* initialize hardware */
|
||||
@@ -177,15 +180,12 @@ bool dlmstp_init(
|
||||
return true;
|
||||
}
|
||||
|
||||
void dlmstp_cleanup(
|
||||
void)
|
||||
void dlmstp_cleanup(void)
|
||||
{
|
||||
/* nothing to do for static buffers */
|
||||
}
|
||||
|
||||
void dlmstp_fill_bacnet_address(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t mstp_address)
|
||||
void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -212,8 +212,7 @@ void dlmstp_fill_bacnet_address(
|
||||
extern bool Send_I_Am_Flag;
|
||||
|
||||
/* look at any of the unconfirmed message bits and encode if set */
|
||||
static uint16_t dlmstp_encode_unconfirmed_frame(
|
||||
void)
|
||||
static uint16_t dlmstp_encode_unconfirmed_frame(void)
|
||||
{
|
||||
BACNET_ADDRESS dest;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
@@ -243,16 +242,16 @@ static uint16_t dlmstp_encode_unconfirmed_frame(
|
||||
/* (pad): (optional) at most one octet of padding: X'FF' */
|
||||
static void MSTP_Send_Frame(
|
||||
uint8_t frame_type, /* type of frame to send - see defines */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
uint16_t pdu_len)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
uint8_t buffer[8]; /* stores the header and crc */
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
uint8_t buffer[8]; /* stores the header and crc */
|
||||
uint8_t datacrc[2]; /* stores the data crc */
|
||||
uint16_t i = 0; /* used to calculate CRC for data */
|
||||
uint16_t i = 0; /* used to calculate CRC for data */
|
||||
|
||||
/* create the MS/TP header */
|
||||
buffer[0] = 0x55;
|
||||
@@ -290,8 +289,7 @@ static void MSTP_Send_Frame(
|
||||
RS485_Transmitter_Enable(false);
|
||||
}
|
||||
|
||||
static void MSTP_Receive_Frame_FSM(
|
||||
void)
|
||||
static void MSTP_Receive_Frame_FSM(void)
|
||||
{
|
||||
/* stores the latest received data octet */
|
||||
uint8_t DataRegister = 0;
|
||||
@@ -305,7 +303,8 @@ static void MSTP_Receive_Frame_FSM(
|
||||
|
||||
switch (Receive_State) {
|
||||
case MSTP_RECEIVE_STATE_IDLE:
|
||||
/* In the IDLE state, the node waits for the beginning of a frame. */
|
||||
/* In the IDLE state, the node waits for the beginning of a frame.
|
||||
*/
|
||||
if (RS485_ReceiveError()) {
|
||||
/* EatAnError */
|
||||
Timer_Silence_Reset();
|
||||
@@ -355,10 +354,12 @@ static void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
break;
|
||||
case MSTP_RECEIVE_STATE_HEADER:
|
||||
/* In the HEADER state, the node waits for the fixed message header. */
|
||||
/* In the HEADER state, the node waits for the fixed message header.
|
||||
*/
|
||||
if (Timer_Silence() > Tframe_abort) {
|
||||
/* Timeout */
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the reception of a
|
||||
* frame */
|
||||
MSTP_Flag.ReceivedInvalidFrame = true;
|
||||
/* wait for the start of a frame. */
|
||||
Receive_State = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -366,7 +367,8 @@ static void MSTP_Receive_Frame_FSM(
|
||||
/* Error */
|
||||
Timer_Silence_Reset();
|
||||
INCREMENT_AND_LIMIT_UINT8(EventCount);
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the reception of a
|
||||
* frame */
|
||||
MSTP_Flag.ReceivedInvalidFrame = true;
|
||||
/* wait for the start of a frame. */
|
||||
Receive_State = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -454,10 +456,12 @@ static void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
break;
|
||||
case MSTP_RECEIVE_STATE_DATA:
|
||||
/* In the DATA state, the node waits for the data portion of a frame. */
|
||||
/* In the DATA state, the node waits for the data portion of a
|
||||
* frame. */
|
||||
if (Timer_Silence() > Tframe_abort) {
|
||||
/* Timeout */
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the reception of a
|
||||
* frame */
|
||||
MSTP_Flag.ReceivedInvalidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
Receive_State = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -512,15 +516,16 @@ static void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
|
||||
/* returns true if we need to transition immediately */
|
||||
static bool MSTP_Master_Node_FSM(
|
||||
void)
|
||||
static bool MSTP_Master_Node_FSM(void)
|
||||
{
|
||||
/* The number of frames sent by this node during a single token hold. */
|
||||
/* When this counter reaches the value Nmax_info_frames, the node must */
|
||||
/* pass the token. */
|
||||
static uint8_t FrameCount;
|
||||
/* "Next Station," the MAC address of the node to which This Station passes */
|
||||
/* the token. If the Next_Station is unknown, Next_Station shall be equal to */
|
||||
/* "Next Station," the MAC address of the node to which This Station passes
|
||||
*/
|
||||
/* the token. If the Next_Station is unknown, Next_Station shall be equal to
|
||||
*/
|
||||
/* This_Station. */
|
||||
static uint8_t Next_Station;
|
||||
/* "Poll Station," the MAC address of the node to which This Station last */
|
||||
@@ -529,7 +534,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* A counter of transmission retries used for Token and Poll For Master */
|
||||
/* transmission. */
|
||||
static unsigned RetryCount;
|
||||
/* The number of tokens received by this node. When this counter reaches the */
|
||||
/* The number of tokens received by this node. When this counter reaches the
|
||||
*/
|
||||
/* value Npoll, the node polls the address range between TS and NS for */
|
||||
/* additional master nodes. TokenCount is set to zero at the end of the */
|
||||
/* polling process. */
|
||||
@@ -603,7 +609,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
MSTP_Flag.ReceivePacketPending = true;
|
||||
break;
|
||||
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
|
||||
/* indicate successful reception to the higher layers */
|
||||
/* indicate successful reception to the higher layers */
|
||||
MSTP_Flag.ReceivePacketPending = true;
|
||||
/* broadcast DER just remains IDLE */
|
||||
if (DestinationAddress != MSTP_BROADCAST_ADDRESS) {
|
||||
@@ -612,9 +618,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
}
|
||||
break;
|
||||
case FRAME_TYPE_TEST_REQUEST:
|
||||
MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE,
|
||||
SourceAddress, This_Station, &InputBuffer[0],
|
||||
DataLength);
|
||||
MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, SourceAddress,
|
||||
This_Station, &InputBuffer[0], DataLength);
|
||||
break;
|
||||
case FRAME_TYPE_TEST_RESPONSE:
|
||||
default:
|
||||
@@ -638,7 +643,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
if (TransmitPacketLen) {
|
||||
MSTP_Send_Frame(FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY,
|
||||
MSTP_BROADCAST_ADDRESS, This_Station,
|
||||
(uint8_t *) & TransmitPacket[0], TransmitPacketLen);
|
||||
(uint8_t *)&TransmitPacket[0], TransmitPacketLen);
|
||||
FrameCount++;
|
||||
} else {
|
||||
/* NothingToSend */
|
||||
@@ -656,8 +661,10 @@ static bool MSTP_Master_Node_FSM(
|
||||
FrameCount = Nmax_info_frames;
|
||||
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
/* Any retry of the data frame shall await the next entry */
|
||||
/* to the USE_TOKEN state. (Because of the length of the timeout, */
|
||||
/* this transition will cause the token to be passed regardless */
|
||||
/* to the USE_TOKEN state. (Because of the length of the
|
||||
* timeout, */
|
||||
/* this transition will cause the token to be passed regardless
|
||||
*/
|
||||
/* of the initial value of FrameCount.) */
|
||||
transition_now = true;
|
||||
} else {
|
||||
@@ -682,8 +689,10 @@ static bool MSTP_Master_Node_FSM(
|
||||
break;
|
||||
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
|
||||
/* ReceivedReply */
|
||||
/* or a proprietary type that indicates a reply */
|
||||
/* indicate successful reception to the higher layers */
|
||||
/* or a proprietary type that indicates a reply
|
||||
*/
|
||||
/* indicate successful reception to the higher
|
||||
* layers */
|
||||
MSTP_Flag.ReceivePacketPending = true;
|
||||
Master_State =
|
||||
MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
@@ -735,7 +744,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
(Next_Station != next_this_station)) {
|
||||
/* SoleMaster */
|
||||
/* there are no other known master nodes to */
|
||||
/* which the token may be sent (true master-slave operation). */
|
||||
/* which the token may be sent (true master-slave
|
||||
* operation). */
|
||||
FrameCount = 0;
|
||||
TokenCount++;
|
||||
Master_State = MSTP_MASTER_STATE_USE_TOKEN;
|
||||
@@ -743,13 +753,16 @@ static bool MSTP_Master_Node_FSM(
|
||||
} else {
|
||||
/* SendToken */
|
||||
/* Npoll changed in Errata SSPC-135-2004 */
|
||||
/* The comparison of NS and TS+1 eliminates the Poll For Master */
|
||||
/* if there are no addresses between TS and NS, since there is no */
|
||||
/* address at which a new master node may be found in that case. */
|
||||
/* The comparison of NS and TS+1 eliminates the Poll For
|
||||
* Master */
|
||||
/* if there are no addresses between TS and NS, since there
|
||||
* is no */
|
||||
/* address at which a new master node may be found in that
|
||||
* case. */
|
||||
TokenCount++;
|
||||
/* transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
RetryCount = 0;
|
||||
EventCount = 0;
|
||||
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
|
||||
@@ -763,7 +776,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* no known successor node */
|
||||
Next_Station = This_Station;
|
||||
RetryCount = 0;
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
/* EventCount = 0; removed in Addendum 135-2004d-8 */
|
||||
/* find a new successor to TS */
|
||||
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
@@ -771,10 +784,10 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* ResetMaintenancePFM */
|
||||
Poll_Station = This_Station;
|
||||
/* transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
RetryCount = 0;
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
EventCount = 0;
|
||||
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
|
||||
}
|
||||
@@ -793,7 +806,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
if (Timer_Silence() <= Tusage_timeout) {
|
||||
if (EventCount > Nmin_octets) {
|
||||
/* SawTokenUser */
|
||||
/* Assume that a frame has been sent by the new token user. */
|
||||
/* Assume that a frame has been sent by the new token user.
|
||||
*/
|
||||
/* Enter the IDLE state to process the frame. */
|
||||
Master_State = MSTP_MASTER_STATE_IDLE;
|
||||
transition_now = true;
|
||||
@@ -803,8 +817,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* RetrySendToken */
|
||||
RetryCount++;
|
||||
/* Transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
EventCount = 0;
|
||||
/* re-enter the current state to listen for NS */
|
||||
/* to begin using the token. */
|
||||
@@ -826,9 +840,11 @@ static bool MSTP_Master_Node_FSM(
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* The NO_TOKEN state is entered if Timer_Silence() becomes greater */
|
||||
/* than Tno_token, indicating that there has been no network activity */
|
||||
/* for that period of time. The timeout is continued to determine */
|
||||
/* The NO_TOKEN state is entered if Timer_Silence() becomes greater
|
||||
*/
|
||||
/* than Tno_token, indicating that there has been no network
|
||||
* activity */
|
||||
/* for that period of time. The timeout is continued to determine */
|
||||
/* whether or not this node may create a token. */
|
||||
case MSTP_MASTER_STATE_NO_TOKEN:
|
||||
my_timeout = Tno_token + (Tslot * This_Station);
|
||||
@@ -836,7 +852,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
if (EventCount > Nmin_octets) {
|
||||
/* SawFrame */
|
||||
/* Some other node exists at a lower address. */
|
||||
/* Enter the IDLE state to receive and process the incoming frame. */
|
||||
/* Enter the IDLE state to receive and process the incoming
|
||||
* frame. */
|
||||
Master_State = MSTP_MASTER_STATE_IDLE;
|
||||
transition_now = true;
|
||||
}
|
||||
@@ -855,7 +872,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
RetryCount = 0;
|
||||
TokenCount = 0;
|
||||
/* EventCount = 0; removed Addendum 135-2004d-8 */
|
||||
/* enter the POLL_FOR_MASTER state to find a new successor to TS. */
|
||||
/* enter the POLL_FOR_MASTER state to find a new successor
|
||||
* to TS. */
|
||||
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
}
|
||||
}
|
||||
@@ -865,15 +883,15 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* a successor node. */
|
||||
case MSTP_MASTER_STATE_POLL_FOR_MASTER:
|
||||
if (MSTP_Flag.ReceivedValidFrame == true) {
|
||||
if ((DestinationAddress == This_Station)
|
||||
&& (FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
|
||||
if ((DestinationAddress == This_Station) &&
|
||||
(FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
|
||||
/* ReceivedReplyToPFM */
|
||||
MSTP_Flag.SoleMaster = false;
|
||||
Next_Station = SourceAddress;
|
||||
EventCount = 0;
|
||||
/* Transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
Poll_Station = This_Station;
|
||||
TokenCount = 0;
|
||||
RetryCount = 0;
|
||||
@@ -920,7 +938,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* Re-enter the current state. */
|
||||
} else {
|
||||
/* DeclareSoleMaster */
|
||||
/* to indicate that this station is the only master */
|
||||
/* to indicate that this station is the only master
|
||||
*/
|
||||
MSTP_Flag.SoleMaster = true;
|
||||
FrameCount = 0;
|
||||
Master_State = MSTP_MASTER_STATE_USE_TOKEN;
|
||||
@@ -948,7 +967,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* Note: optimized such that we are never a client */
|
||||
MSTP_Send_Frame(FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY,
|
||||
TransmitPacketDest, This_Station,
|
||||
(uint8_t *) & TransmitPacket[0], TransmitPacketLen);
|
||||
(uint8_t *)&TransmitPacket[0], TransmitPacketLen);
|
||||
MSTP_Flag.TransmitPacketPending = false;
|
||||
Master_State = MSTP_MASTER_STATE_IDLE;
|
||||
} else {
|
||||
@@ -977,12 +996,11 @@ static bool MSTP_Master_Node_FSM(
|
||||
}
|
||||
|
||||
/* returns number of bytes sent on success, zero on failure */
|
||||
int dlmstp_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int dlmstp_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int bytes_sent = 0;
|
||||
|
||||
if (MSTP_Flag.TransmitPacketPending == false) {
|
||||
@@ -1003,13 +1021,12 @@ int dlmstp_send_pdu(
|
||||
}
|
||||
|
||||
/* Return the length of the packet */
|
||||
uint16_t dlmstp_receive(
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t dlmstp_receive(BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
|
||||
/* dummy - unused parameter */
|
||||
timeout = timeout;
|
||||
@@ -1051,8 +1068,7 @@ uint16_t dlmstp_receive(
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void dlmstp_set_mac_address(
|
||||
uint8_t mac_address)
|
||||
void dlmstp_set_mac_address(uint8_t mac_address)
|
||||
{
|
||||
/* Master Nodes can only have address 0-127 */
|
||||
if (mac_address <= 127) {
|
||||
@@ -1069,8 +1085,7 @@ void dlmstp_set_mac_address(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_mac_address(
|
||||
void)
|
||||
uint8_t dlmstp_mac_address(void)
|
||||
{
|
||||
return This_Station;
|
||||
}
|
||||
@@ -1082,8 +1097,7 @@ uint8_t dlmstp_mac_address(
|
||||
/* nodes. This may be used to allocate more or less of the available link */
|
||||
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
||||
/* node, its value shall be 1. */
|
||||
void dlmstp_set_max_info_frames(
|
||||
uint8_t max_info_frames)
|
||||
void dlmstp_set_max_info_frames(uint8_t max_info_frames)
|
||||
{
|
||||
if (max_info_frames >= 1) {
|
||||
Nmax_info_frames = max_info_frames;
|
||||
@@ -1097,8 +1111,7 @@ void dlmstp_set_max_info_frames(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_info_frames(
|
||||
void)
|
||||
uint8_t dlmstp_max_info_frames(void)
|
||||
{
|
||||
return Nmax_info_frames;
|
||||
}
|
||||
@@ -1108,8 +1121,7 @@ uint8_t dlmstp_max_info_frames(
|
||||
/* allowable address for master nodes. The value of Max_Master shall be */
|
||||
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
||||
/* its value shall be 127. */
|
||||
void dlmstp_set_max_master(
|
||||
uint8_t max_master)
|
||||
void dlmstp_set_max_master(uint8_t max_master)
|
||||
{
|
||||
if (max_master <= 127) {
|
||||
if (This_Station <= max_master) {
|
||||
@@ -1125,20 +1137,18 @@ void dlmstp_set_max_master(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_master(
|
||||
void)
|
||||
uint8_t dlmstp_max_master(void)
|
||||
{
|
||||
return Nmax_master;
|
||||
}
|
||||
|
||||
void dlmstp_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void dlmstp_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0; /* counter */
|
||||
int i = 0; /* counter */
|
||||
|
||||
my_address->mac_len = 1;
|
||||
my_address->mac[0] = This_Station;
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -1147,16 +1157,15 @@ void dlmstp_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void dlmstp_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 1;
|
||||
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
|
||||
+44
-55
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -44,9 +44,7 @@
|
||||
|
||||
/* 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 * rpdata)
|
||||
int Encode_Property_APDU(uint8_t *apdu, BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = -1;
|
||||
|
||||
@@ -80,11 +78,10 @@ int Encode_Property_APDU(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
void handler_read_property(
|
||||
uint8_t * service_request,
|
||||
void handler_read_property(uint8_t *service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
BACNET_ADDRESS *src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data)
|
||||
{
|
||||
BACNET_READ_PROPERTY_DATA data;
|
||||
int len = 0;
|
||||
@@ -98,13 +95,11 @@ void handler_read_property(
|
||||
/* 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);
|
||||
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],
|
||||
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
goto RP_ABORT;
|
||||
@@ -112,48 +107,42 @@ void handler_read_property(
|
||||
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],
|
||||
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);
|
||||
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 */
|
||||
data.error_class = ERROR_CLASS_OBJECT;
|
||||
data.error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
property_len =
|
||||
Encode_Property_APDU(&Handler_Transmit_Buffer[pdu_len + ack_len],
|
||||
&data);
|
||||
property_len = Encode_Property_APDU(
|
||||
&Handler_Transmit_Buffer[pdu_len + ack_len], &data);
|
||||
if (property_len >= 0) {
|
||||
len =
|
||||
rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
|
||||
[pdu_len + property_len + ack_len]);
|
||||
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 */
|
||||
/* 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],
|
||||
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],
|
||||
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
data.error_class, data.error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RP_ABORT:
|
||||
RP_ABORT:
|
||||
pdu_len += len;
|
||||
bytes_sent =
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
||||
pdu_len);
|
||||
bytes_sent = datalink_send_pdu(
|
||||
src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
|
||||
(void)bytes_sent;
|
||||
|
||||
return;
|
||||
|
||||
+27
-30
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -40,19 +40,16 @@
|
||||
bool Send_I_Am_Flag = true;
|
||||
|
||||
void handler_who_is(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src)
|
||||
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);
|
||||
(void)src;
|
||||
len = whois_decode_service_request(
|
||||
service_request, service_len, &low_limit, &high_limit);
|
||||
if (len == 0) {
|
||||
Send_I_Am_Flag = true;
|
||||
} else if (len != BACNET_STATUS_ERROR) {
|
||||
|
||||
+45
-54
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -45,11 +45,10 @@
|
||||
/* too big to reside on stack frame for PIC */
|
||||
static BACNET_WRITE_PROPERTY_DATA wp_data;
|
||||
|
||||
void handler_write_property(
|
||||
uint8_t * service_request,
|
||||
void handler_write_property(uint8_t *service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
BACNET_ADDRESS *src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
@@ -62,17 +61,14 @@ void handler_write_property(
|
||||
/* 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);
|
||||
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],
|
||||
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],
|
||||
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
} else {
|
||||
@@ -81,58 +77,53 @@ void handler_write_property(
|
||||
switch (wp_data.object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Write_Property(&wp_data)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
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, wp_data.error_class,
|
||||
wp_data.error_code);
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
wp_data.error_class, wp_data.error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Write_Property(&wp_data)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
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, wp_data.error_class,
|
||||
wp_data.error_code);
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
wp_data.error_class, wp_data.error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Write_Property(&wp_data)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
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, wp_data.error_class,
|
||||
wp_data.error_code);
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
wp_data.error_class, wp_data.error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
wp_data.error_class, wp_data.error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pdu_len += len;
|
||||
bytes_sent =
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
||||
pdu_len);
|
||||
bytes_sent = datalink_send_pdu(
|
||||
src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
|
||||
(void)bytes_sent;
|
||||
|
||||
return;
|
||||
|
||||
+28
-33
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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>
|
||||
@@ -45,14 +45,12 @@ const char *BACnet_Version = "1.0";
|
||||
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
|
||||
|
||||
/* dummy function - so we can use default demo handlers */
|
||||
bool dcc_communication_enabled(
|
||||
void)
|
||||
bool dcc_communication_enabled(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init(
|
||||
void)
|
||||
static void init(void)
|
||||
{
|
||||
/* Initialize the Clock Prescaler for ATmega48/88/168 */
|
||||
/* The default CLKPSx bits are factory set to 0011 */
|
||||
@@ -105,8 +103,7 @@ static void init(
|
||||
__enable_interrupt();
|
||||
}
|
||||
|
||||
static void task_milliseconds(
|
||||
void)
|
||||
static void task_milliseconds(void)
|
||||
{
|
||||
while (Timer_Milliseconds) {
|
||||
Timer_Milliseconds--;
|
||||
@@ -117,8 +114,7 @@ static void task_milliseconds(
|
||||
|
||||
static uint8_t Address_Switch;
|
||||
|
||||
static void input_switch_read(
|
||||
void)
|
||||
static void input_switch_read(void)
|
||||
{
|
||||
uint8_t value;
|
||||
static uint8_t old_value = 0;
|
||||
@@ -140,8 +136,7 @@ static void input_switch_read(
|
||||
}
|
||||
|
||||
static uint8_t PDUBuffer[MAX_MPDU];
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src; /* source address */
|
||||
|
||||
+92
-104
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* The module handles sending data out the RS-485 port */
|
||||
/* and handles receiving data from the RS-485 port. */
|
||||
@@ -45,14 +45,13 @@ static uint8_t LED3_Off_Timer;
|
||||
static uint32_t RS485_Baud = 9600;
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(
|
||||
void)
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(void)
|
||||
{
|
||||
/* enable Transmit and Receive */
|
||||
UCSR0B = _BV(TXEN0) | _BV(RXEN0);
|
||||
@@ -81,25 +80,23 @@ void RS485_Initialize(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void)
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(void)
|
||||
{
|
||||
return RS485_Baud;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: true if valid baud rate
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud)
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: true if valid baud rate
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
@@ -126,13 +123,12 @@ bool RS485_Set_Baud_Rate(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Enable or disable the transmitter
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable)
|
||||
* DESCRIPTION: Enable or disable the transmitter
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
BIT_SET(PORTD, PD2);
|
||||
@@ -142,13 +138,12 @@ void RS485_Transmitter_Enable(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(
|
||||
void)
|
||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(void)
|
||||
{
|
||||
uint8_t nbytes = 4;
|
||||
|
||||
@@ -171,13 +166,12 @@ void RS485_Turnaround_Delay(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Timers for delaying the LED indicators going off
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: expected to be called once a millisecond
|
||||
*****************************************************************************/
|
||||
void RS485_LED_Timers(
|
||||
void)
|
||||
* DESCRIPTION: Timers for delaying the LED indicators going off
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: expected to be called once a millisecond
|
||||
*****************************************************************************/
|
||||
void RS485_LED_Timers(void)
|
||||
{
|
||||
if (LED1_Off_Timer) {
|
||||
LED1_Off_Timer--;
|
||||
@@ -194,41 +188,38 @@ void RS485_LED_Timers(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Turn on the LED, and set the off timer to turn it off
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void RS485_LED1_On(
|
||||
void)
|
||||
* DESCRIPTION: Turn on the LED, and set the off timer to turn it off
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void RS485_LED1_On(void)
|
||||
{
|
||||
BIT_CLEAR(PORTD, PD6);
|
||||
LED1_Off_Timer = 20;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Turn on the LED, and set the off timer to turn it off
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void RS485_LED3_On(
|
||||
void)
|
||||
* DESCRIPTION: Turn on the LED, and set the off timer to turn it off
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void RS485_LED3_On(void)
|
||||
{
|
||||
BIT_CLEAR(PORTD, PD7);
|
||||
LED3_Off_Timer = 20;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(uint8_t *buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
RS485_LED3_On();
|
||||
while (nbytes) {
|
||||
while (!BIT_CHECK(UCSR0A, UDRE0)) {
|
||||
@@ -251,13 +242,12 @@ void RS485_Send_Data(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if a framing or overrun error is present
|
||||
* RETURN: true if error
|
||||
* ALGORITHM: autobaud - if there are a lot of errors, switch baud rate
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(
|
||||
void)
|
||||
* DESCRIPTION: Return true if a framing or overrun error is present
|
||||
* RETURN: true if error
|
||||
* ALGORITHM: autobaud - if there are a lot of errors, switch baud rate
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(void)
|
||||
{
|
||||
bool ReceiveError = false;
|
||||
volatile uint8_t dummy_data;
|
||||
@@ -287,13 +277,12 @@ bool RS485_ReceiveError(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if data is available
|
||||
* RETURN: true if data is available, with the data in the parameter set
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * data)
|
||||
* DESCRIPTION: Return true if data is available
|
||||
* RETURN: true if data is available, with the data in the parameter set
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(uint8_t *data)
|
||||
{
|
||||
bool DataAvailable = false;
|
||||
|
||||
@@ -308,8 +297,7 @@ bool RS485_DataAvailable(
|
||||
}
|
||||
|
||||
#ifdef TEST_RS485
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
{
|
||||
unsigned i = 0;
|
||||
uint8_t DataRegister;
|
||||
|
||||
+40
-38
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include "hardware.h"
|
||||
|
||||
@@ -33,12 +33,10 @@ extern uint8_t __stack;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define STACK_CANARY (0xC5)
|
||||
void stack_init(
|
||||
void) __attribute__ ((naked)) __attribute__ ((section(".init1")));
|
||||
void stack_init(void) __attribute__((naked)) __attribute__((section(".init1")));
|
||||
#endif
|
||||
|
||||
void stack_init(
|
||||
void)
|
||||
void stack_init(void)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
#if 0
|
||||
@@ -49,17 +47,23 @@ void stack_init(
|
||||
p++;
|
||||
}
|
||||
#else
|
||||
__asm volatile (
|
||||
" ldi r30,lo8(_end)\n" " ldi r31,hi8(_end)\n" " ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
|
||||
" ldi r25,hi8(__stack)\n" " rjmp .cmp\n" ".loop:\n"
|
||||
" st Z+,r24\n" ".cmp:\n" " cpi r30,lo8(__stack)\n"
|
||||
" cpc r31,r25\n" " brlo .loop\n" " breq .loop"::);
|
||||
__asm volatile(" ldi r30,lo8(_end)\n"
|
||||
" ldi r31,hi8(_end)\n"
|
||||
" ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
|
||||
" ldi r25,hi8(__stack)\n"
|
||||
" rjmp .cmp\n"
|
||||
".loop:\n"
|
||||
" st Z+,r24\n"
|
||||
".cmp:\n"
|
||||
" cpi r30,lo8(__stack)\n"
|
||||
" cpc r31,r25\n"
|
||||
" brlo .loop\n"
|
||||
" breq .loop" ::);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned stack_size(
|
||||
void)
|
||||
unsigned stack_size(void)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return (&__stack) - (&_end);
|
||||
@@ -68,8 +72,7 @@ unsigned stack_size(
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t stack_byte(
|
||||
unsigned offset)
|
||||
uint8_t stack_byte(unsigned offset)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return *(&_end + offset);
|
||||
@@ -79,8 +82,7 @@ uint8_t stack_byte(
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned stack_unused(
|
||||
void)
|
||||
unsigned stack_unused(void)
|
||||
{
|
||||
unsigned count = 0;
|
||||
#if defined(__GNUC__)
|
||||
|
||||
+28
-31
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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 <stdint.h>
|
||||
#include "hardware.h"
|
||||
|
||||
@@ -30,19 +30,18 @@
|
||||
/* Prescaling: 1, 8, 64, 256, 1024 */
|
||||
#define TIMER_PRESCALER 64
|
||||
/* Count: Timer0 counts up to 0xFF and then signals overflow */
|
||||
#define TIMER_TICKS (F_CPU/TIMER_PRESCALER/1000)
|
||||
#define TIMER_TICKS (F_CPU / TIMER_PRESCALER / 1000)
|
||||
#if (TIMER_TICKS > 0xFF)
|
||||
#error Timer Prescaler value is too small
|
||||
#endif
|
||||
#define TIMER_COUNT (0xFF-TIMER_TICKS)
|
||||
#define TIMER_COUNT (0xFF - TIMER_TICKS)
|
||||
/* Global variable millisecond timer - used by main.c for timers task */
|
||||
volatile uint8_t Timer_Milliseconds = 0;
|
||||
/* MS/TP Silence Timer */
|
||||
static volatile uint16_t SilenceTime;
|
||||
|
||||
/* Configure the Timer */
|
||||
void Timer_Initialize(
|
||||
void)
|
||||
void Timer_Initialize(void)
|
||||
{
|
||||
/* Normal Operation */
|
||||
TCCR1A = 0;
|
||||
@@ -84,8 +83,7 @@ ISR(TIMER0_OVF_vect)
|
||||
}
|
||||
|
||||
/* Public access to the Silence Timer */
|
||||
uint16_t Timer_Silence(
|
||||
void)
|
||||
uint16_t Timer_Silence(void)
|
||||
{
|
||||
uint16_t timer;
|
||||
|
||||
@@ -97,8 +95,7 @@ uint16_t Timer_Silence(
|
||||
}
|
||||
|
||||
/* Public reset of the Silence Timer */
|
||||
void Timer_Silence_Reset(
|
||||
void)
|
||||
void Timer_Silence_Reset(void)
|
||||
{
|
||||
BIT_CLEAR(TIMSK0, TOIE0);
|
||||
SilenceTime = 0;
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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"
|
||||
@@ -28,23 +28,23 @@
|
||||
#include "adc.h"
|
||||
|
||||
/* prescale select bits */
|
||||
#if (F_CPU >> 1) < 1000000
|
||||
#define ADPS_8BIT (1)
|
||||
#define ADPS_10BIT (3)
|
||||
#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)
|
||||
#define ADPS_8BIT (2)
|
||||
#define ADPS_10BIT (4)
|
||||
#elif (F_CPU >> 3) < 1000000
|
||||
#define ADPS_8BIT (3)
|
||||
#define ADPS_10BIT (5)
|
||||
#define ADPS_8BIT (3)
|
||||
#define ADPS_10BIT (5)
|
||||
#elif (F_CPU >> 4) < 1000000
|
||||
#define ADPS_8BIT (4)
|
||||
#define ADPS_10BIT (6)
|
||||
#define ADPS_8BIT (4)
|
||||
#define ADPS_10BIT (6)
|
||||
#elif (F_CPU >> 5) < 1000000
|
||||
#define ADPS_8BIT (5)
|
||||
#define ADPS_10BIT (7)
|
||||
#define ADPS_8BIT (5)
|
||||
#define ADPS_10BIT (7)
|
||||
#else
|
||||
#error "ADC: F_CPU too large for accuracy."
|
||||
#error "ADC: F_CPU too large for accuracy."
|
||||
#endif
|
||||
|
||||
/* ADMUX: channel bits 0..4
|
||||
@@ -59,54 +59,55 @@
|
||||
ADATE = Auto Trigger Enable
|
||||
*/
|
||||
|
||||
void adc_enable(
|
||||
uint8_t index)
|
||||
void adc_enable(uint8_t index)
|
||||
{
|
||||
index = index;
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Description: Run a Analog to Digital conversion
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************/
|
||||
uint8_t adc_result_8bit(
|
||||
uint8_t channel)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
uint8_t value = 0; /* return value */
|
||||
* Description: Run a Analog to Digital conversion
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************/
|
||||
uint8_t adc_result_8bit(uint8_t channel)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
uint8_t value = 0; /* return value */
|
||||
|
||||
while (ADCSRA & (1 << ADSC));
|
||||
while (ADCSRA & (1 << ADSC))
|
||||
;
|
||||
ADMUX = channel | (1 << ADLAR) | (0 << REFS1) | (1 << REFS0);
|
||||
/* Delay needed for the stabilization of the ADC input voltage */
|
||||
_delay_us(10);
|
||||
/* Start the analog to digital conversion */
|
||||
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADIF) | ADPS_8BIT;
|
||||
/* Wait for the analog to digital conversion to complete */
|
||||
while ((ADCSRA & (1 << ADIF)) == 0);
|
||||
while ((ADCSRA & (1 << ADIF)) == 0)
|
||||
;
|
||||
value = ADCH;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Description: Run a Analog to Digital conversion
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************/
|
||||
uint16_t adc_result_10bit(
|
||||
uint8_t channel)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
* Description: Run a Analog to Digital conversion
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************/
|
||||
uint16_t adc_result_10bit(uint8_t channel)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
uint16_t value = 0; /* return value */
|
||||
|
||||
while (ADCSRA & (1 << ADSC));
|
||||
while (ADCSRA & (1 << ADSC))
|
||||
;
|
||||
ADMUX = channel | (0 << ADLAR) | (0 << REFS1) | (1 << REFS0);
|
||||
/* Delay needed for the stabilization of the ADC input voltage */
|
||||
_delay_us(10);
|
||||
/* Start the analog to digital conversion */
|
||||
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADIF) | ADPS_10BIT;
|
||||
/* Wait for the analog to digital conversion to complete */
|
||||
while ((ADCSRA & (1 << ADIF)) == 0);
|
||||
while ((ADCSRA & (1 << ADIF)) == 0)
|
||||
;
|
||||
value = ADCL;
|
||||
value |= (ADCH << 8);
|
||||
|
||||
@@ -114,12 +115,11 @@ uint16_t adc_result_10bit(
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Description: Initializes the Analog to Digital Converter
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************/
|
||||
void adc_init(
|
||||
void)
|
||||
* Description: Initializes the Analog to Digital Converter
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************/
|
||||
void adc_init(void)
|
||||
{
|
||||
/* configure ADC for Free Running Mode - ADTS = 000 */
|
||||
/* AIN1 is applied to the negative input of the Analog Comparator - ACME */
|
||||
|
||||
+42
-46
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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"
|
||||
@@ -28,23 +28,23 @@
|
||||
#include "adc.h"
|
||||
|
||||
/* prescale select bits */
|
||||
#if (F_CPU >> 1) < 1000000
|
||||
#define ADPS_8BIT (1)
|
||||
#define ADPS_10BIT (3)
|
||||
#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)
|
||||
#define ADPS_8BIT (2)
|
||||
#define ADPS_10BIT (4)
|
||||
#elif (F_CPU >> 3) < 1000000
|
||||
#define ADPS_8BIT (3)
|
||||
#define ADPS_10BIT (5)
|
||||
#define ADPS_8BIT (3)
|
||||
#define ADPS_10BIT (5)
|
||||
#elif (F_CPU >> 4) < 1000000
|
||||
#define ADPS_8BIT (4)
|
||||
#define ADPS_10BIT (6)
|
||||
#define ADPS_8BIT (4)
|
||||
#define ADPS_10BIT (6)
|
||||
#elif (F_CPU >> 5) < 1000000
|
||||
#define ADPS_8BIT (5)
|
||||
#define ADPS_10BIT (7)
|
||||
#define ADPS_8BIT (5)
|
||||
#define ADPS_10BIT (7)
|
||||
#else
|
||||
#error "ADC: F_CPU too large for accuracy."
|
||||
#error "ADC: F_CPU too large for accuracy."
|
||||
#endif
|
||||
|
||||
/* Array of ADC results */
|
||||
@@ -86,9 +86,8 @@ ISR(ADC_vect)
|
||||
BIT_SET(ADCSRA, ADSC);
|
||||
}
|
||||
|
||||
void adc_enable(
|
||||
uint8_t index)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
void adc_enable(uint8_t index)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
if (Enabled_Channels) {
|
||||
/* ADC interupt is already started */
|
||||
BIT_SET(Enabled_Channels, index);
|
||||
@@ -106,9 +105,8 @@ void adc_enable(
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t adc_result_8bit(
|
||||
uint8_t index)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
uint8_t adc_result_8bit(uint8_t index)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
uint8_t result = 0;
|
||||
uint8_t sreg;
|
||||
|
||||
@@ -116,16 +114,15 @@ uint8_t adc_result_8bit(
|
||||
adc_enable(index);
|
||||
sreg = SREG;
|
||||
__disable_interrupt();
|
||||
result = (uint8_t) (Sample_Result[index] >> 2);
|
||||
result = (uint8_t)(Sample_Result[index] >> 2);
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t adc_result_10bit(
|
||||
uint8_t index)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
uint16_t adc_result_10bit(uint8_t index)
|
||||
{ /* 0..7 = ADC0..ADC7, respectively */
|
||||
uint16_t result = 0;
|
||||
uint8_t sreg;
|
||||
|
||||
@@ -140,8 +137,7 @@ uint16_t adc_result_10bit(
|
||||
return result;
|
||||
}
|
||||
|
||||
void adc_init(
|
||||
void)
|
||||
void adc_init(void)
|
||||
{
|
||||
/* Initial channel selection */
|
||||
/* ADLAR = Left Adjust Result
|
||||
|
||||
+43
-68
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -42,30 +42,16 @@
|
||||
static float Present_Value[MAX_ANALOG_INPUTS];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Analog_Input_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_Input_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_Input_Properties_Optional[] = {
|
||||
-1
|
||||
};
|
||||
static const int Analog_Input_Properties_Optional[] = { -1 };
|
||||
|
||||
static const int Analog_Input_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Analog_Input_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Analog_Input_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Analog_Input_Properties_Required;
|
||||
@@ -77,8 +63,7 @@ void Analog_Input_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
void Analog_Input_Init(
|
||||
void)
|
||||
void Analog_Input_Init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -86,8 +71,7 @@ void Analog_Input_Init(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
@@ -96,24 +80,21 @@ bool Analog_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
unsigned Analog_Input_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
bool Analog_Input_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
bool status = false;
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
@@ -124,8 +105,7 @@ bool Analog_Input_Object_Name(
|
||||
return status;
|
||||
}
|
||||
|
||||
float Analog_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = 0.0;
|
||||
|
||||
@@ -136,9 +116,7 @@ float Analog_Input_Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
void Analog_Input_Present_Value_Set(
|
||||
uint32_t object_instance,
|
||||
float value)
|
||||
void Analog_Input_Present_Value_Set(uint32_t object_instance, float value)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
Present_Value[object_instance] = value;
|
||||
@@ -147,10 +125,9 @@ void Analog_Input_Present_Value_Set(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object already exists */
|
||||
int Analog_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||
BACNET_BIT_STRING bit_string = { 0 };
|
||||
uint8_t *apdu = NULL;
|
||||
@@ -162,9 +139,8 @@ int Analog_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], rpdata->object_type,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], rpdata->object_type, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
Analog_Input_Object_Name(rpdata->object_instance, &char_string);
|
||||
@@ -176,9 +152,8 @@ int Analog_Input_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], rpdata->object_type);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
Analog_Input_Present_Value(rpdata->object_instance));
|
||||
apdu_len = encode_application_real(
|
||||
&apdu[0], Analog_Input_Present_Value(rpdata->object_instance));
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
|
||||
+53
-79
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/basic/object/av.h"
|
||||
#include "bacnet/basic/services.h"
|
||||
@@ -46,17 +46,9 @@
|
||||
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_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[] = {
|
||||
#if 0
|
||||
@@ -66,14 +58,10 @@ static const int Analog_Value_Properties_Optional[] = {
|
||||
-1
|
||||
};
|
||||
|
||||
static const int Analog_Value_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Analog_Value_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Analog_Value_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Analog_Value_Properties_Required;
|
||||
@@ -85,8 +73,7 @@ void Analog_Value_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
void Analog_Value_Init(
|
||||
void)
|
||||
void Analog_Value_Init(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -94,8 +81,7 @@ void Analog_Value_Init(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
return true;
|
||||
@@ -105,8 +91,7 @@ bool Analog_Value_Valid_Instance(
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
unsigned Analog_Value_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_VALUES;
|
||||
}
|
||||
@@ -114,8 +99,7 @@ unsigned Analog_Value_Count(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Value_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -123,8 +107,7 @@ uint32_t Analog_Value_Index_To_Instance(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_ANALOG_VALUES;
|
||||
|
||||
@@ -134,8 +117,7 @@ unsigned Analog_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
float Analog_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = 0;
|
||||
unsigned index = 0;
|
||||
@@ -149,9 +131,7 @@ float Analog_Value_Present_Value(
|
||||
}
|
||||
|
||||
bool Analog_Value_Present_Value_Set(
|
||||
uint32_t object_instance,
|
||||
float value,
|
||||
uint8_t priority)
|
||||
uint32_t object_instance, float value, uint8_t priority)
|
||||
{
|
||||
unsigned index = 0;
|
||||
bool status = false;
|
||||
@@ -160,8 +140,8 @@ bool Analog_Value_Present_Value_Set(
|
||||
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)) {
|
||||
(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.
|
||||
@@ -176,10 +156,9 @@ bool Analog_Value_Present_Value_Set(
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
bool Analog_Value_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[32] = ""; /* okay for single thread */
|
||||
static char text_string[32] = ""; /* okay for single thread */
|
||||
unsigned index = 0;
|
||||
bool status = false;
|
||||
|
||||
@@ -193,10 +172,9 @@ bool Analog_Value_Object_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
float real_value = 1.414F;
|
||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||
@@ -214,9 +192,8 @@ int Analog_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], rpdata->object_type,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], rpdata->object_type, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
Analog_Value_Object_Name(rpdata->object_instance, &char_string);
|
||||
@@ -332,10 +309,9 @@ int Analog_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
#if 0
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
@@ -344,9 +320,8 @@ bool Analog_Value_Write_Property(
|
||||
int len = 0;
|
||||
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -363,18 +338,17 @@ bool Analog_Value_Write_Property(
|
||||
}
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_PRESENT_VALUE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL,
|
||||
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
status =
|
||||
Analog_Value_Present_Value_Set(wp_data->object_instance,
|
||||
value.type.Real, wp_data->priority);
|
||||
value.type.Real, wp_data->priority);
|
||||
if (!status) {
|
||||
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. */
|
||||
/* Command priority 6 is reserved for use by Minimum
|
||||
On/Off algorithm and may not be used for other
|
||||
purposes in any object. */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
} else {
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2010 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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
/* hardware layer includes */
|
||||
@@ -55,18 +55,16 @@ static uint8_t MSTP_MAC_Address;
|
||||
static struct mstimer DCC_Timer;
|
||||
#define DCC_CYCLE_SECONDS 1
|
||||
|
||||
static bool seeprom_version_test(
|
||||
void)
|
||||
static bool seeprom_version_test(void)
|
||||
{
|
||||
uint16_t version = 0;
|
||||
uint16_t id = 0;
|
||||
bool status = false;
|
||||
int rv;
|
||||
|
||||
rv = seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *) & id, 2);
|
||||
rv = seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *)&id, 2);
|
||||
if (rv > 0) {
|
||||
rv = seeprom_bytes_read(NV_SEEPROM_VERSION_0, (uint8_t *) & version,
|
||||
2);
|
||||
rv = seeprom_bytes_read(NV_SEEPROM_VERSION_0, (uint8_t *)&version, 2);
|
||||
}
|
||||
|
||||
if ((rv > 0) && (id == SEEPROM_ID) && (version == SEEPROM_VERSION)) {
|
||||
@@ -74,8 +72,8 @@ static bool seeprom_version_test(
|
||||
} else if (rv > 0) {
|
||||
version = SEEPROM_VERSION;
|
||||
id = SEEPROM_ID;
|
||||
seeprom_bytes_write(NV_SEEPROM_TYPE_0, (uint8_t *) & id, 2);
|
||||
seeprom_bytes_write(NV_SEEPROM_VERSION_0, (uint8_t *) & version, 2);
|
||||
seeprom_bytes_write(NV_SEEPROM_TYPE_0, (uint8_t *)&id, 2);
|
||||
seeprom_bytes_write(NV_SEEPROM_VERSION_0, (uint8_t *)&version, 2);
|
||||
} else {
|
||||
while (1) {
|
||||
/* SEEPROM is faulty! */
|
||||
@@ -90,8 +88,8 @@ static void device_id_init(uint8_t mac)
|
||||
uint32_t device_id = 0;
|
||||
|
||||
/* Get the device ID from the eeprom */
|
||||
eeprom_bytes_read(NV_EEPROM_DEVICE_0, (uint8_t *) & device_id,
|
||||
sizeof(device_id));
|
||||
eeprom_bytes_read(
|
||||
NV_EEPROM_DEVICE_0, (uint8_t *)&device_id, sizeof(device_id));
|
||||
if (device_id < BACNET_MAX_INSTANCE) {
|
||||
Device_Set_Object_Instance_Number(device_id);
|
||||
} else {
|
||||
@@ -100,8 +98,7 @@ static void device_id_init(uint8_t mac)
|
||||
}
|
||||
}
|
||||
|
||||
void bacnet_init(
|
||||
void)
|
||||
void bacnet_init(void)
|
||||
{
|
||||
uint8_t max_master = 0;
|
||||
|
||||
@@ -121,33 +118,31 @@ void bacnet_init(
|
||||
Device_Init(NULL);
|
||||
device_id_init(MSTP_MAC_Address);
|
||||
/* set up our confirmed service unrecognized service handler - required! */
|
||||
apdu_set_unrecognized_service_handler_handler
|
||||
(handler_unrecognized_service);
|
||||
apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service);
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
|
||||
/* Set the handlers for any confirmed services that we support. */
|
||||
/* We must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
|
||||
handler_read_property_multiple);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
|
||||
handler_reinitialize_device);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
handler_write_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROP_MULTIPLE, handler_read_property_multiple);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_REINITIALIZE_DEVICE, handler_reinitialize_device);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property);
|
||||
/* handle communication so we can shutup when asked */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||
handler_device_communication_control);
|
||||
/* start the cyclic 1 second timer for DCC */
|
||||
mstimer_set(&DCC_Timer, DCC_CYCLE_SECONDS*1000);
|
||||
mstimer_set(&DCC_Timer, DCC_CYCLE_SECONDS * 1000);
|
||||
/* Hello World! */
|
||||
Send_I_Am(&Handler_Transmit_Buffer[0]);
|
||||
}
|
||||
|
||||
static uint8_t PDUBuffer[MAX_MPDU];
|
||||
void bacnet_task(
|
||||
void)
|
||||
void bacnet_task(void)
|
||||
{
|
||||
uint8_t mstp_mac_address;
|
||||
uint16_t pdu_len;
|
||||
|
||||
+42
-66
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 Input Objects customize for your use */
|
||||
|
||||
@@ -42,30 +42,16 @@
|
||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Binary_Input_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_POLARITY,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Input_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_POLARITY, -1 };
|
||||
|
||||
static const int Binary_Input_Properties_Optional[] = {
|
||||
-1
|
||||
};
|
||||
static const int Binary_Input_Properties_Optional[] = { -1 };
|
||||
|
||||
static const int Binary_Input_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Binary_Input_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Binary_Input_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired) {
|
||||
*pRequired = Binary_Input_Properties_Required;
|
||||
@@ -80,8 +66,7 @@ void Binary_Input_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
void Binary_Input_Init(
|
||||
void)
|
||||
void Binary_Input_Init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@@ -91,8 +76,7 @@ void Binary_Input_Init(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_INPUTS)
|
||||
return true;
|
||||
@@ -101,15 +85,13 @@ bool Binary_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Input_Count(
|
||||
void)
|
||||
unsigned Binary_Input_Count(void)
|
||||
{
|
||||
return MAX_BINARY_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances.*/
|
||||
uint32_t Binary_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Binary_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -117,8 +99,7 @@ uint32_t Binary_Input_Index_To_Instance(
|
||||
/* 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 Binary_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_INPUTS;
|
||||
|
||||
@@ -128,8 +109,7 @@ unsigned Binary_Input_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
unsigned index = 0;
|
||||
@@ -143,8 +123,7 @@ BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
}
|
||||
|
||||
bool Binary_Input_Present_Value_Set(
|
||||
uint32_t object_instance,
|
||||
BACNET_BINARY_PV value)
|
||||
uint32_t object_instance, BACNET_BINARY_PV value)
|
||||
{
|
||||
unsigned index = 0;
|
||||
|
||||
@@ -158,10 +137,9 @@ bool Binary_Input_Present_Value_Set(
|
||||
}
|
||||
|
||||
bool Binary_Input_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
bool status = false;
|
||||
|
||||
if (object_instance < MAX_BINARY_INPUTS) {
|
||||
@@ -174,10 +152,9 @@ bool Binary_Input_Object_Name(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object already exists, and has been bounds checked */
|
||||
int Binary_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string = { 0 };
|
||||
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
@@ -191,9 +168,8 @@ int Binary_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], rpdata->object_type,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], rpdata->object_type, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
Binary_Input_Object_Name(rpdata->object_instance, &char_string);
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2011 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2011 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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
@@ -35,10 +35,7 @@
|
||||
#include "bacnet/basic/object/device.h"
|
||||
#include "bname.h"
|
||||
|
||||
static bool bacnet_name_isvalid(
|
||||
uint8_t encoding,
|
||||
uint8_t length,
|
||||
char *str)
|
||||
static bool bacnet_name_isvalid(uint8_t encoding, uint8_t length, char *str)
|
||||
{
|
||||
bool valid = false;
|
||||
|
||||
@@ -55,32 +52,27 @@ static bool bacnet_name_isvalid(
|
||||
}
|
||||
|
||||
bool bacnet_name_save(
|
||||
uint16_t offset,
|
||||
uint8_t encoding,
|
||||
char *str,
|
||||
uint8_t length)
|
||||
uint16_t offset, uint8_t encoding, char *str, uint8_t length)
|
||||
{
|
||||
uint8_t buffer[NV_EEPROM_NAME_SIZE] = { 0 };
|
||||
uint8_t i = 0;
|
||||
|
||||
if (bacnet_name_isvalid(encoding, length, str)) {
|
||||
eeprom_bytes_write(NV_EEPROM_NAME_LENGTH(offset), &length, 1);
|
||||
eeprom_bytes_write(NV_EEPROM_NAME_ENCODING(offset),
|
||||
(uint8_t *) & encoding, 1);
|
||||
eeprom_bytes_write(
|
||||
NV_EEPROM_NAME_ENCODING(offset), (uint8_t *)&encoding, 1);
|
||||
for (i = 0; i < length; i++) {
|
||||
buffer[i] = str[i];
|
||||
}
|
||||
eeprom_bytes_write(NV_EEPROM_NAME_STRING(offset), &buffer[0],
|
||||
NV_EEPROM_NAME_SIZE);
|
||||
eeprom_bytes_write(
|
||||
NV_EEPROM_NAME_STRING(offset), &buffer[0], NV_EEPROM_NAME_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bacnet_name_set(
|
||||
uint16_t offset,
|
||||
BACNET_CHARACTER_STRING * char_string)
|
||||
bool bacnet_name_set(uint16_t offset, BACNET_CHARACTER_STRING *char_string)
|
||||
{
|
||||
uint8_t encoding = 0;
|
||||
uint8_t length = 0;
|
||||
@@ -92,13 +84,12 @@ bool bacnet_name_set(
|
||||
return bacnet_name_save(offset, encoding, str, length);
|
||||
}
|
||||
|
||||
bool bacnet_name_write_unique(
|
||||
uint16_t offset,
|
||||
bool bacnet_name_write_unique(uint16_t offset,
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * char_string,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
BACNET_CHARACTER_STRING *char_string,
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
bool status = false;
|
||||
size_t length = 0;
|
||||
@@ -113,8 +104,8 @@ bool bacnet_name_write_unique(
|
||||
} else if (length <= NV_EEPROM_NAME_SIZE) {
|
||||
encoding = characterstring_encoding(char_string);
|
||||
if (encoding < MAX_CHARACTER_STRING_ENCODING) {
|
||||
if (Device_Valid_Object_Name(char_string, &duplicate_type,
|
||||
&duplicate_instance)) {
|
||||
if (Device_Valid_Object_Name(
|
||||
char_string, &duplicate_type, &duplicate_instance)) {
|
||||
if ((duplicate_type == object_type) &&
|
||||
(duplicate_instance == object_instance)) {
|
||||
/* writing same name to same object */
|
||||
@@ -145,11 +136,10 @@ bool bacnet_name_write_unique(
|
||||
}
|
||||
|
||||
/* no required minumum length or duplicate checking */
|
||||
bool bacnet_name_write(
|
||||
uint16_t offset,
|
||||
BACNET_CHARACTER_STRING * char_string,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
bool bacnet_name_write(uint16_t offset,
|
||||
BACNET_CHARACTER_STRING *char_string,
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
bool status = false;
|
||||
size_t length = 0;
|
||||
@@ -176,18 +166,14 @@ bool bacnet_name_write(
|
||||
return status;
|
||||
}
|
||||
|
||||
void bacnet_name_init(
|
||||
uint16_t offset,
|
||||
char *default_string)
|
||||
void bacnet_name_init(uint16_t offset, char *default_string)
|
||||
{
|
||||
(void) bacnet_name_save(offset, CHARACTER_UTF8, default_string,
|
||||
strlen(default_string));
|
||||
(void)bacnet_name_save(
|
||||
offset, CHARACTER_UTF8, default_string, strlen(default_string));
|
||||
}
|
||||
|
||||
void bacnet_name(
|
||||
uint16_t offset,
|
||||
BACNET_CHARACTER_STRING * char_string,
|
||||
char *default_string)
|
||||
uint16_t offset, BACNET_CHARACTER_STRING *char_string, char *default_string)
|
||||
{
|
||||
uint8_t encoding = 0;
|
||||
uint8_t length = 0;
|
||||
@@ -195,8 +181,8 @@ void bacnet_name(
|
||||
|
||||
eeprom_bytes_read(NV_EEPROM_NAME_ENCODING(offset), &encoding, 1);
|
||||
eeprom_bytes_read(NV_EEPROM_NAME_LENGTH(offset), &length, 1);
|
||||
eeprom_bytes_read(NV_EEPROM_NAME_STRING(offset), (uint8_t *) & name,
|
||||
NV_EEPROM_NAME_SIZE);
|
||||
eeprom_bytes_read(
|
||||
NV_EEPROM_NAME_STRING(offset), (uint8_t *)&name, NV_EEPROM_NAME_SIZE);
|
||||
if (bacnet_name_isvalid(encoding, length, name)) {
|
||||
characterstring_init(char_string, encoding, &name[0], length);
|
||||
} else if (default_string) {
|
||||
|
||||
+96
-134
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* Binary Output Objects - customize for your use */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "hardware.h"
|
||||
#include "led.h"
|
||||
@@ -55,34 +55,18 @@ static uint8_t Out_Of_Service[MAX_BINARY_OUTPUTS];
|
||||
static uint8_t Polarity[MAX_BINARY_OUTPUTS];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Binary_Output_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_POLARITY,
|
||||
PROP_PRIORITY_ARRAY,
|
||||
PROP_RELINQUISH_DEFAULT,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Output_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_POLARITY, PROP_PRIORITY_ARRAY,
|
||||
PROP_RELINQUISH_DEFAULT, -1 };
|
||||
|
||||
static const int Binary_Output_Properties_Optional[] = {
|
||||
PROP_ACTIVE_TEXT,
|
||||
PROP_INACTIVE_TEXT,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Output_Properties_Optional[] = { PROP_ACTIVE_TEXT,
|
||||
PROP_INACTIVE_TEXT, -1 };
|
||||
|
||||
static const int Binary_Output_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Binary_Output_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Binary_Output_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Binary_Output_Properties_Required;
|
||||
@@ -95,8 +79,7 @@ void Binary_Output_Property_Lists(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Output_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Output_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_OUTPUTS)
|
||||
return true;
|
||||
@@ -105,22 +88,19 @@ bool Binary_Output_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Output_Count(
|
||||
void)
|
||||
unsigned Binary_Output_Count(void)
|
||||
{
|
||||
return MAX_BINARY_OUTPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Binary_Output_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Binary_Output_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Output_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Binary_Output_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_OUTPUTS;
|
||||
|
||||
@@ -130,8 +110,7 @@ unsigned Binary_Output_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
static BACNET_BINARY_PV Present_Value(
|
||||
unsigned int index)
|
||||
static BACNET_BINARY_PV Present_Value(unsigned int index)
|
||||
{
|
||||
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
|
||||
BACNET_BINARY_PV current_value = RELINQUISH_DEFAULT;
|
||||
@@ -139,9 +118,9 @@ static BACNET_BINARY_PV Present_Value(
|
||||
|
||||
if (index < MAX_BINARY_OUTPUTS) {
|
||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
||||
current_value = (BACNET_BINARY_PV) Binary_Output_Level[index][i];
|
||||
current_value = (BACNET_BINARY_PV)Binary_Output_Level[index][i];
|
||||
if (current_value != BINARY_NULL) {
|
||||
value = (BACNET_BINARY_PV) Binary_Output_Level[index][i];
|
||||
value = (BACNET_BINARY_PV)Binary_Output_Level[index][i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -150,8 +129,7 @@ static BACNET_BINARY_PV Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Output_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Output_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = 0;
|
||||
|
||||
@@ -161,17 +139,15 @@ BACNET_BINARY_PV Binary_Output_Present_Value(
|
||||
}
|
||||
|
||||
bool Binary_Output_Present_Value_Set(
|
||||
uint32_t instance,
|
||||
BACNET_BINARY_PV binary_value,
|
||||
unsigned priority)
|
||||
{ /* 0..15 */
|
||||
uint32_t instance, BACNET_BINARY_PV binary_value, unsigned priority)
|
||||
{ /* 0..15 */
|
||||
bool status = false;
|
||||
|
||||
if (instance < MAX_BINARY_OUTPUTS) {
|
||||
if (priority < BACNET_MAX_PRIORITY) {
|
||||
Binary_Output_Level[instance][priority] = (uint8_t) binary_value;
|
||||
Binary_Output_Level[instance][priority] = (uint8_t)binary_value;
|
||||
seeprom_bytes_write(NV_SEEPROM_BINARY_OUTPUT(instance,
|
||||
NV_SEEPROM_BO_PRIORITY_ARRAY_1 + priority),
|
||||
NV_SEEPROM_BO_PRIORITY_ARRAY_1 + priority),
|
||||
&Binary_Output_Level[instance][priority], 1);
|
||||
status = true;
|
||||
}
|
||||
@@ -180,17 +156,16 @@ bool Binary_Output_Present_Value_Set(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Binary_Output_Polarity_Set(
|
||||
uint32_t instance,
|
||||
BACNET_POLARITY polarity)
|
||||
bool Binary_Output_Polarity_Set(uint32_t instance, BACNET_POLARITY polarity)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (instance < MAX_BINARY_OUTPUTS) {
|
||||
if (polarity < MAX_POLARITY) {
|
||||
Polarity[instance] = polarity;
|
||||
seeprom_bytes_write(NV_SEEPROM_BINARY_OUTPUT(instance,
|
||||
NV_SEEPROM_BO_POLARITY), &Polarity[instance], 1);
|
||||
seeprom_bytes_write(
|
||||
NV_SEEPROM_BINARY_OUTPUT(instance, NV_SEEPROM_BO_POLARITY),
|
||||
&Polarity[instance], 1);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
@@ -198,31 +173,28 @@ bool Binary_Output_Polarity_Set(
|
||||
return status;
|
||||
}
|
||||
|
||||
BACNET_POLARITY Binary_Output_Polarity(
|
||||
uint32_t instance)
|
||||
BACNET_POLARITY Binary_Output_Polarity(uint32_t instance)
|
||||
{
|
||||
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
||||
|
||||
if (instance < MAX_BINARY_OUTPUTS) {
|
||||
polarity = (BACNET_POLARITY) Polarity[instance];
|
||||
polarity = (BACNET_POLARITY)Polarity[instance];
|
||||
}
|
||||
|
||||
return polarity;
|
||||
}
|
||||
|
||||
void Binary_Output_Out_Of_Service_Set(
|
||||
uint32_t instance,
|
||||
bool flag)
|
||||
void Binary_Output_Out_Of_Service_Set(uint32_t instance, bool flag)
|
||||
{
|
||||
if (instance < MAX_BINARY_OUTPUTS) {
|
||||
Out_Of_Service[instance] = flag;
|
||||
seeprom_bytes_write(NV_SEEPROM_BINARY_OUTPUT(instance,
|
||||
NV_SEEPROM_BO_OUT_OF_SERVICE), &Out_Of_Service[instance], 1);
|
||||
seeprom_bytes_write(
|
||||
NV_SEEPROM_BINARY_OUTPUT(instance, NV_SEEPROM_BO_OUT_OF_SERVICE),
|
||||
&Out_Of_Service[instance], 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool Binary_Output_Out_Of_Service(
|
||||
uint32_t instance)
|
||||
bool Binary_Output_Out_Of_Service(uint32_t instance)
|
||||
{
|
||||
bool flag = false;
|
||||
|
||||
@@ -235,10 +207,9 @@ bool Binary_Output_Out_Of_Service(
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
bool Binary_Output_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
bool status = false;
|
||||
|
||||
if (object_instance < MAX_BINARY_OUTPUTS) {
|
||||
@@ -250,11 +221,10 @@ bool Binary_Output_Object_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Binary_Output_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Output_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string = { 0 };
|
||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
@@ -270,9 +240,8 @@ int Binary_Output_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], rpdata->object_type,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], rpdata->object_type, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
Binary_Output_Object_Name(rpdata->object_instance, &char_string);
|
||||
@@ -312,8 +281,7 @@ int Binary_Output_Read_Property(
|
||||
object_index =
|
||||
Binary_Output_Instance_To_Index(rpdata->object_instance);
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Polarity[object_index]);
|
||||
encode_application_enumerated(&apdu[0], Polarity[object_index]);
|
||||
break;
|
||||
case PROP_PRIORITY_ARRAY:
|
||||
/* Array element zero is the number of elements in the array */
|
||||
@@ -327,14 +295,13 @@ int Binary_Output_Read_Property(
|
||||
Binary_Output_Instance_To_Index(rpdata->object_instance);
|
||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
||||
/* FIXME: check if we have room before adding it to APDU */
|
||||
present_value = (BACNET_BINARY_PV)
|
||||
Binary_Output_Level[object_index][i];
|
||||
present_value =
|
||||
(BACNET_BINARY_PV)Binary_Output_Level[object_index][i];
|
||||
if (present_value == BINARY_NULL) {
|
||||
len = encode_application_null(&apdu[apdu_len]);
|
||||
} else {
|
||||
len =
|
||||
encode_application_enumerated(&apdu[apdu_len],
|
||||
present_value);
|
||||
len = encode_application_enumerated(
|
||||
&apdu[apdu_len], present_value);
|
||||
}
|
||||
/* add it if we have room */
|
||||
if ((apdu_len + len) < MAX_APDU)
|
||||
@@ -351,14 +318,13 @@ int Binary_Output_Read_Property(
|
||||
Binary_Output_Instance_To_Index(rpdata->object_instance);
|
||||
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
|
||||
present_value = (BACNET_BINARY_PV)
|
||||
Binary_Output_Level[object_index][rpdata->array_index -
|
||||
1];
|
||||
Binary_Output_Level[object_index]
|
||||
[rpdata->array_index - 1];
|
||||
if (present_value == BINARY_NULL) {
|
||||
apdu_len = encode_application_null(&apdu[apdu_len]);
|
||||
} else {
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[apdu_len],
|
||||
present_value);
|
||||
apdu_len = encode_application_enumerated(
|
||||
&apdu[apdu_len], present_value);
|
||||
}
|
||||
} else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -399,19 +365,17 @@ int Binary_Output_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Binary_Output_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int priority = 0;
|
||||
BACNET_BINARY_PV level = BINARY_NULL;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -430,19 +394,19 @@ bool Binary_Output_Write_Property(
|
||||
case PROP_PRESENT_VALUE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
priority = wp_data->priority;
|
||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Enumerated <= MAX_BINARY_PV)) {
|
||||
level = (BACNET_BINARY_PV) value.type.Enumerated;
|
||||
level = (BACNET_BINARY_PV)value.type.Enumerated;
|
||||
priority--;
|
||||
Binary_Output_Present_Value_Set(wp_data->object_instance,
|
||||
level, priority);
|
||||
Binary_Output_Present_Value_Set(
|
||||
wp_data->object_instance, level, priority);
|
||||
} else if (priority == 6) {
|
||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||
algorithm and may not be used for other purposes in any
|
||||
@@ -456,21 +420,20 @@ bool Binary_Output_Write_Property(
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
|
||||
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
level = BINARY_NULL;
|
||||
priority = wp_data->priority;
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
|
||||
priority--;
|
||||
Binary_Output_Present_Value_Set
|
||||
(wp_data->object_instance, level, priority);
|
||||
Binary_Output_Present_Value_Set(
|
||||
wp_data->object_instance, level, priority);
|
||||
} else if (priority == 6) {
|
||||
status = false;
|
||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
/* Command priority 6 is reserved for use by Minimum
|
||||
On/Off algorithm and may not be used for other
|
||||
purposes in any object. */
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
} else {
|
||||
@@ -482,22 +445,21 @@ bool Binary_Output_Write_Property(
|
||||
}
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
|
||||
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
Binary_Output_Out_Of_Service_Set(wp_data->object_instance,
|
||||
value.type.Boolean);
|
||||
Binary_Output_Out_Of_Service_Set(
|
||||
wp_data->object_instance, value.type.Boolean);
|
||||
}
|
||||
break;
|
||||
case PROP_POLARITY:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
if (value.type.Enumerated < MAX_POLARITY) {
|
||||
Binary_Output_Polarity_Set(wp_data->object_instance,
|
||||
(BACNET_POLARITY) value.type.Enumerated);
|
||||
(BACNET_POLARITY)value.type.Enumerated);
|
||||
} else {
|
||||
status = false;
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -528,8 +490,7 @@ bool Binary_Output_Write_Property(
|
||||
return status;
|
||||
}
|
||||
|
||||
void Binary_Output_Init(
|
||||
void)
|
||||
void Binary_Output_Init(void)
|
||||
{
|
||||
unsigned i, j;
|
||||
|
||||
@@ -541,14 +502,15 @@ void Binary_Output_Init(
|
||||
if (Polarity[i] >= MAX_POLARITY) {
|
||||
Binary_Output_Polarity_Set(i, POLARITY_NORMAL);
|
||||
}
|
||||
seeprom_bytes_read(NV_SEEPROM_BINARY_OUTPUT(i,
|
||||
NV_SEEPROM_BO_OUT_OF_SERVICE), &Out_Of_Service[i], 1);
|
||||
seeprom_bytes_read(
|
||||
NV_SEEPROM_BINARY_OUTPUT(i, NV_SEEPROM_BO_OUT_OF_SERVICE),
|
||||
&Out_Of_Service[i], 1);
|
||||
if (Out_Of_Service[i] > 1) {
|
||||
Binary_Output_Out_Of_Service_Set(i, false);
|
||||
}
|
||||
for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
|
||||
seeprom_bytes_read(NV_SEEPROM_BINARY_OUTPUT(i,
|
||||
NV_SEEPROM_BO_PRIORITY_ARRAY_1 + j),
|
||||
seeprom_bytes_read(
|
||||
NV_SEEPROM_BINARY_OUTPUT(i, NV_SEEPROM_BO_PRIORITY_ARRAY_1 + j),
|
||||
&Binary_Output_Level[i][j], 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,33 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Atmel Corporation
|
||||
*
|
||||
* File : main.c
|
||||
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
|
||||
* Revision : $Revision: 1.7 $
|
||||
* Date : $Date: Tuesday, June 07, 200 $
|
||||
* Updated by : $Author: raapeland $
|
||||
*
|
||||
* Support mail : avr@atmel.com
|
||||
*
|
||||
* Target platform : All AVRs with bootloader support
|
||||
*
|
||||
* AppNote : AVR109 - Self-programming
|
||||
*
|
||||
* Description : This Program allows an AVR with bootloader capabilities to
|
||||
* Read/write its own Flash/EEprom. To enter Programming mode
|
||||
* an input pin is checked. If this pin is pulled low, programming mode
|
||||
* is entered. If not, normal execution is done from $0000
|
||||
* "reset" vector in Application area.
|
||||
*
|
||||
* Preparations : Use the preprocessor.xls file for obtaining a customized
|
||||
* defines.h file and linker-file code-segment definition for
|
||||
* the device you are compiling for.
|
||||
****************************************************************************/
|
||||
*
|
||||
* Atmel Corporation
|
||||
*
|
||||
* File : main.c
|
||||
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
|
||||
* Revision : $Revision: 1.7 $
|
||||
* Date : $Date: Tuesday, June 07, 200 $
|
||||
* Updated by : $Author: raapeland $
|
||||
*
|
||||
* Support mail : avr@atmel.com
|
||||
*
|
||||
* Target platform : All AVRs with bootloader support
|
||||
*
|
||||
* AppNote : AVR109 - Self-programming
|
||||
*
|
||||
* Description : This Program allows an AVR with bootloader capabilities to
|
||||
* Read/write its own Flash/EEprom. To enter Programming mode
|
||||
* an input pin is checked. If this pin is pulled low,
|
||||
*programming mode is entered. If not, normal execution is done from $0000
|
||||
* "reset" vector in Application area.
|
||||
*
|
||||
* Preparations : Use the preprocessor.xls file for obtaining a customized
|
||||
* defines.h file and linker-file code-segment definition for
|
||||
* the device you are compiling for.
|
||||
****************************************************************************/
|
||||
#include "defines.h"
|
||||
#include "serial.h"
|
||||
#include "flash.h"
|
||||
|
||||
|
||||
|
||||
/* Uncomment the following to save code space */
|
||||
/*#define REMOVE_AVRPROG_SUPPORT */
|
||||
/*#define REMOVE_FUSE_AND_LOCK_BIT_SUPPORT */
|
||||
@@ -52,70 +50,66 @@
|
||||
#endif /* LARGE_MEMORY */
|
||||
|
||||
#ifndef REMOVE_BLOCK_SUPPORT
|
||||
unsigned char BlockLoad(
|
||||
unsigned int size,
|
||||
unsigned char mem,
|
||||
ADDR_T * address);
|
||||
void BlockRead(
|
||||
unsigned int size,
|
||||
unsigned char mem,
|
||||
ADDR_T * address);
|
||||
unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address);
|
||||
void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address);
|
||||
|
||||
/* BLOCKSIZE should be chosen so that the following holds: BLOCKSIZE*n = PAGESIZE, where n=1,2,3... */
|
||||
/* BLOCKSIZE should be chosen so that the following holds: BLOCKSIZE*n =
|
||||
* PAGESIZE, where n=1,2,3... */
|
||||
#define BLOCKSIZE PAGESIZE
|
||||
|
||||
#endif /* REMOVE_BLOCK_SUPPORT */
|
||||
|
||||
#ifdef __ICCAVR__
|
||||
__C_task void main(
|
||||
void)
|
||||
__C_task void main(void)
|
||||
#else /* ! __ICCAVR__ */
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
#endif /* __ICCAVR__ */
|
||||
{
|
||||
ADDR_T address;
|
||||
unsigned int temp_int;
|
||||
unsigned char val;
|
||||
|
||||
|
||||
/* Initialization */
|
||||
void (
|
||||
*funcptr) (
|
||||
void) = 0x0000; /* Set up function pointer to RESET vector. */
|
||||
PROGPORT |= (1 << PROG_NO); /* Enable pull-up on PROG_NO line on PROGPORT. */
|
||||
initbootuart(); /* Initialize UART. */
|
||||
|
||||
void (*funcptr)(void) =
|
||||
0x0000; /* Set up function pointer to RESET vector. */
|
||||
PROGPORT |=
|
||||
(1 << PROG_NO); /* Enable pull-up on PROG_NO line on PROGPORT. */
|
||||
initbootuart(); /* Initialize UART. */
|
||||
|
||||
/* Branch to bootloader or application code? */
|
||||
if (!(PROGPIN & (1 << PROG_NO))) { /* If PROGPIN is pulled low, enter programmingmode. */
|
||||
if (!(PROGPIN & (1 << PROG_NO))) { /* If PROGPIN is pulled low, enter
|
||||
programmingmode. */
|
||||
/* Main loop */
|
||||
for (;;) {
|
||||
val = recchar(); /* Wait for command character. */
|
||||
val = recchar(); /* Wait for command character. */
|
||||
|
||||
/* Check autoincrement status. */
|
||||
if (val == 'a') {
|
||||
sendchar('Y'); /* Yes, we do autoincrement. */
|
||||
sendchar('Y'); /* Yes, we do autoincrement. */
|
||||
}
|
||||
|
||||
|
||||
/* Set address. */
|
||||
else if (val == 'A') { /* Set address... *//* NOTE: Flash addresses are given in words, not bytes. */
|
||||
address = (recchar() << 8) | recchar(); /* Read address high and low byte. */
|
||||
else if (val == 'A') {
|
||||
/* Set address... */ /* NOTE: Flash addresses are given in
|
||||
words, not bytes. */
|
||||
address = (recchar() << 8) |
|
||||
recchar(); /* Read address high and low byte. */
|
||||
sendchar('\r'); /* Send OK back. */
|
||||
}
|
||||
|
||||
|
||||
/* Chip erase. */
|
||||
else if (val == 'e') {
|
||||
for (address = 0; address < APP_END; address += PAGESIZE) { /* NOTE: Here we use address as a byte-address, not word-address, for convenience. */
|
||||
for (address = 0; address < APP_END; address +=
|
||||
PAGESIZE) { /* NOTE: Here we use address as a byte-address,
|
||||
not word-address, for convenience. */
|
||||
_WAIT_FOR_SPM();
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
|
||||
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
|
||||
long-type address to flash ptr. */
|
||||
#endif
|
||||
_PAGE_ERASE(address);
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_default=Pe1053 /* Back to default. */
|
||||
#pragma diag_default = Pe1053 /* Back to default. */
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -124,25 +118,23 @@ int main(
|
||||
#ifndef REMOVE_BLOCK_SUPPORT
|
||||
/* Check block load support. */
|
||||
else if (val == 'b') {
|
||||
sendchar('Y'); /* Report block load supported. */
|
||||
sendchar((BLOCKSIZE >> 8) & 0xFF); /* MSB first. */
|
||||
sendchar(BLOCKSIZE & 0xFF); /* Report BLOCKSIZE (bytes). */
|
||||
sendchar('Y'); /* Report block load supported. */
|
||||
sendchar((BLOCKSIZE >> 8) & 0xFF); /* MSB first. */
|
||||
sendchar(BLOCKSIZE & 0xFF); /* Report BLOCKSIZE (bytes). */
|
||||
}
|
||||
|
||||
|
||||
/* Start block load. */
|
||||
else if (val == 'B') {
|
||||
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
|
||||
val = recchar(); /* Get memtype. */
|
||||
sendchar(BlockLoad(temp_int, val, &address)); /* Block load. */
|
||||
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
|
||||
val = recchar(); /* Get memtype. */
|
||||
sendchar(BlockLoad(temp_int, val, &address)); /* Block load. */
|
||||
}
|
||||
|
||||
|
||||
/* Start block read. */
|
||||
else if (val == 'g') {
|
||||
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
|
||||
val = recchar(); /* Get memtype */
|
||||
BlockRead(temp_int, val, &address); /* Block read */
|
||||
temp_int = (recchar() << 8) | recchar(); /* Get block size. */
|
||||
val = recchar(); /* Get memtype */
|
||||
BlockRead(temp_int, val, &address); /* Block read */
|
||||
}
|
||||
#endif /* REMOVE_BLOCK_SUPPORT */
|
||||
|
||||
@@ -153,53 +145,58 @@ int main(
|
||||
_WAIT_FOR_SPM();
|
||||
_ENABLE_RWW_SECTION();
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
|
||||
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
|
||||
long-type address to flash ptr. */
|
||||
#endif
|
||||
sendchar(_LOAD_PROGRAM_MEMORY((address << 1) + 1));
|
||||
sendchar(_LOAD_PROGRAM_MEMORY((address << 1) + 0));
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_default=Pe1053 /* Back to default. */
|
||||
#pragma diag_default = Pe1053 /* Back to default. */
|
||||
#endif
|
||||
|
||||
address++; /* Auto-advance to next Flash word. */
|
||||
address++; /* Auto-advance to next Flash word. */
|
||||
}
|
||||
|
||||
|
||||
/* Write program memory, low byte. */
|
||||
else if (val == 'c') { /* NOTE: Always use this command before sending high byte. */
|
||||
temp_int = recchar(); /* Get low byte for later _FILL_TEMP_WORD. */
|
||||
else if (val == 'c') { /* NOTE: Always use this command before
|
||||
sending high byte. */
|
||||
temp_int =
|
||||
recchar(); /* Get low byte for later _FILL_TEMP_WORD. */
|
||||
sendchar('\r'); /* Send OK back. */
|
||||
}
|
||||
|
||||
|
||||
/* Write program memory, high byte. */
|
||||
else if (val == 'C') {
|
||||
temp_int |= (recchar() << 8); /* Get and insert high byte. */
|
||||
temp_int |= (recchar() << 8); /* Get and insert high byte. */
|
||||
_WAIT_FOR_SPM();
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
|
||||
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
|
||||
long-type address to flash ptr. */
|
||||
#endif
|
||||
_FILL_TEMP_WORD((address << 1), temp_int); /* Convert word-address to byte-address and fill. */
|
||||
_FILL_TEMP_WORD(
|
||||
(address << 1), temp_int); /* Convert word-address to
|
||||
byte-address and fill. */
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_default=Pe1053 /* Back to default. */
|
||||
#pragma diag_default = Pe1053 /* Back to default. */
|
||||
#endif
|
||||
address++; /* Auto-advance to next Flash word. */
|
||||
address++; /* Auto-advance to next Flash word. */
|
||||
sendchar('\r'); /* Send OK back. */
|
||||
}
|
||||
|
||||
|
||||
/* Write page. */
|
||||
else if (val == 'm') {
|
||||
if (address >= (APP_END >> 1)) { /* Protect bootloader area. */
|
||||
if (address >= (APP_END >> 1)) { /* Protect bootloader area. */
|
||||
sendchar('?');
|
||||
} else {
|
||||
_WAIT_FOR_SPM();
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
|
||||
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
|
||||
long-type address to flash ptr. */
|
||||
#endif
|
||||
_PAGE_WRITE(address << 1); /* Convert word-address to byte-address and write. */
|
||||
_PAGE_WRITE(address << 1); /* Convert word-address to
|
||||
byte-address and write. */
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_default=Pe1053 /* Back to default. */
|
||||
#pragma diag_default = Pe1053 /* Back to default. */
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -211,26 +208,26 @@ int main(
|
||||
/* Write EEPROM memory. */
|
||||
else if (val == 'D') {
|
||||
_WAIT_FOR_SPM();
|
||||
EEARL = address; /* Setup EEPROM address. */
|
||||
EEARL = address; /* Setup EEPROM address. */
|
||||
EEARH = (address >> 8);
|
||||
EEDR = recchar(); /* Get byte. */
|
||||
EECR |= (1 << EEMWE); /* Write byte. */
|
||||
EEDR = recchar(); /* Get byte. */
|
||||
EECR |= (1 << EEMWE); /* Write byte. */
|
||||
EECR |= (1 << EEWE);
|
||||
while (EECR & (1 << EEWE)) /* Wait for write operation to finish. */
|
||||
while (EECR &
|
||||
(1 << EEWE)) /* Wait for write operation to finish. */
|
||||
;
|
||||
|
||||
address++; /* Auto-advance to next EEPROM byte. */
|
||||
address++; /* Auto-advance to next EEPROM byte. */
|
||||
sendchar('\r'); /* Send OK back. */
|
||||
}
|
||||
|
||||
|
||||
/* Read EEPROM memory. */
|
||||
else if (val == 'd') {
|
||||
EEARL = address; /* Setup EEPROM address. */
|
||||
EEARL = address; /* Setup EEPROM address. */
|
||||
EEARH = (address >> 8);
|
||||
EECR |= (1 << EERE); /* Read byte... */
|
||||
EECR |= (1 << EERE); /* Read byte... */
|
||||
sendchar(EEDR); /* ...and send it back. */
|
||||
address++; /* Auto-advance to next EEPROM byte. */
|
||||
address++; /* Auto-advance to next EEPROM byte. */
|
||||
}
|
||||
#endif /* REMOVE_EEPROM_BYTE_SUPPORT */
|
||||
|
||||
@@ -238,7 +235,7 @@ int main(
|
||||
/* Write lockbits. */
|
||||
else if (val == 'l') {
|
||||
_WAIT_FOR_SPM();
|
||||
_SET_LOCK_BITS(recchar()); /* Read and set lock bits. */
|
||||
_SET_LOCK_BITS(recchar()); /* Read and set lock bits. */
|
||||
sendchar('\r'); /* Send OK back. */
|
||||
}
|
||||
#if defined(_GET_LOCK_BITS)
|
||||
@@ -248,21 +245,18 @@ int main(
|
||||
sendchar(_GET_LOCK_BITS());
|
||||
}
|
||||
|
||||
|
||||
/* Read fuse bits. */
|
||||
else if (val == 'F') {
|
||||
_WAIT_FOR_SPM();
|
||||
sendchar(_GET_LOW_FUSES());
|
||||
}
|
||||
|
||||
|
||||
/* Read high fuse bits. */
|
||||
else if (val == 'N') {
|
||||
_WAIT_FOR_SPM();
|
||||
sendchar(_GET_HIGH_FUSES());
|
||||
}
|
||||
|
||||
|
||||
/* Read extended fuse bits. */
|
||||
else if (val == 'Q') {
|
||||
_WAIT_FOR_SPM();
|
||||
@@ -277,42 +271,40 @@ int main(
|
||||
sendchar('\r'); /* Nothing special to do, just answer OK. */
|
||||
}
|
||||
|
||||
|
||||
/* Exit bootloader. */
|
||||
else if (val == 'E') {
|
||||
_WAIT_FOR_SPM();
|
||||
_ENABLE_RWW_SECTION();
|
||||
sendchar('\r');
|
||||
funcptr(); /* Jump to Reset vector 0x0000 in Application Section. */
|
||||
funcptr(); /* Jump to Reset vector 0x0000 in Application
|
||||
Section. */
|
||||
}
|
||||
|
||||
|
||||
/* Get programmer type. */
|
||||
else if (val == 'p') {
|
||||
sendchar('S'); /* Answer 'SERIAL'. */
|
||||
sendchar('S'); /* Answer 'SERIAL'. */
|
||||
}
|
||||
|
||||
|
||||
/* Return supported device codes. */
|
||||
else if (val == 't') {
|
||||
#if PARTCODE+0 > 0
|
||||
sendchar(PARTCODE); /* Supports only this device, of course. */
|
||||
#if PARTCODE + 0 > 0
|
||||
sendchar(PARTCODE); /* Supports only this device, of course. */
|
||||
#endif /* PARTCODE */
|
||||
sendchar(0); /* Send list terminator. */
|
||||
sendchar(0); /* Send list terminator. */
|
||||
}
|
||||
|
||||
|
||||
/* Set LED, clear LED and set device type. */
|
||||
else if ((val == 'x') || (val == 'y') || (val == 'T')) {
|
||||
recchar(); /* Ignore the command and it's parameter. */
|
||||
recchar(); /* Ignore the command and it's parameter. */
|
||||
sendchar('\r'); /* Send OK back. */
|
||||
}
|
||||
#endif /* REMOVE_AVRPROG_SUPPORT */
|
||||
|
||||
/* Return programmer identifier. */
|
||||
else if (val == 'S') {
|
||||
sendchar('A'); /* Return 'AVRBOOT'. */
|
||||
sendchar('V'); /* Software identifier (aka programmer signature) is always 7 characters. */
|
||||
sendchar('A'); /* Return 'AVRBOOT'. */
|
||||
sendchar('V'); /* Software identifier (aka programmer signature)
|
||||
is always 7 characters. */
|
||||
sendchar('R');
|
||||
sendchar('B');
|
||||
sendchar('O');
|
||||
@@ -320,14 +312,12 @@ int main(
|
||||
sendchar('T');
|
||||
}
|
||||
|
||||
|
||||
/* Return software version. */
|
||||
else if (val == 'V') {
|
||||
sendchar('1');
|
||||
sendchar('5');
|
||||
}
|
||||
|
||||
|
||||
/* Return signature bytes. */
|
||||
else if (val == 's') {
|
||||
sendchar(SIGNATURE_BYTE_3);
|
||||
@@ -335,25 +325,20 @@ int main(
|
||||
sendchar(SIGNATURE_BYTE_1);
|
||||
}
|
||||
|
||||
|
||||
/* The last command to accept is ESC (synchronization). */
|
||||
else if (val != 0x1b) { /* If not ESC, then it is unrecognized... */
|
||||
else if (val != 0x1b) { /* If not ESC, then it is unrecognized... */
|
||||
sendchar('?');
|
||||
}
|
||||
} /* end: for(;;) */
|
||||
} /* end: for(;;) */
|
||||
} else {
|
||||
_WAIT_FOR_SPM();
|
||||
_ENABLE_RWW_SECTION();
|
||||
funcptr(); /* Jump to Reset vector 0x0000 in Application Section. */
|
||||
funcptr(); /* Jump to Reset vector 0x0000 in Application Section. */
|
||||
}
|
||||
} /* end: main */
|
||||
|
||||
} /* end: main */
|
||||
|
||||
#ifndef REMOVE_BLOCK_SUPPORT
|
||||
unsigned char BlockLoad(
|
||||
unsigned int size,
|
||||
unsigned char mem,
|
||||
ADDR_T * address)
|
||||
unsigned char BlockLoad(unsigned int size, unsigned char mem, ADDR_T *address)
|
||||
{
|
||||
unsigned char buffer[BLOCKSIZE];
|
||||
unsigned int data;
|
||||
@@ -368,51 +353,54 @@ unsigned char BlockLoad(
|
||||
/* Then program the EEPROM */
|
||||
_WAIT_FOR_SPM();
|
||||
for (tempaddress = 0; tempaddress < size; tempaddress++) {
|
||||
EEARL = *address; /* Setup EEPROM address */
|
||||
EEARL = *address; /* Setup EEPROM address */
|
||||
EEARH = ((*address) >> 8);
|
||||
EEDR = buffer[tempaddress]; /* Get byte. */
|
||||
EECR |= (1 << EEMWE); /* Write byte. */
|
||||
EECR |= (1 << EEMWE); /* Write byte. */
|
||||
EECR |= (1 << EEWE);
|
||||
while (EECR & (1 << EEWE)) /* Wait for write operation to finish. */
|
||||
while (EECR & (1 << EEWE)) /* Wait for write operation to finish. */
|
||||
;
|
||||
|
||||
(*address)++; /* Select next EEPROM byte */
|
||||
(*address)++; /* Select next EEPROM byte */
|
||||
}
|
||||
|
||||
return '\r'; /* Report programming OK */
|
||||
return '\r'; /* Report programming OK */
|
||||
}
|
||||
|
||||
/* Flash memory type. */
|
||||
else if (mem == 'F') { /* NOTE: For flash programming, 'address' is given in words. */
|
||||
(*address) <<= 1; /* Convert address to bytes temporarily. */
|
||||
tempaddress = (*address); /* Store address in page. */
|
||||
else if (mem ==
|
||||
'F') { /* NOTE: For flash programming, 'address' is given in words. */
|
||||
(*address) <<= 1; /* Convert address to bytes temporarily. */
|
||||
tempaddress = (*address); /* Store address in page. */
|
||||
|
||||
do {
|
||||
data = recchar();
|
||||
data |= (recchar() << 8);
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
|
||||
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
|
||||
long-type address to flash ptr. */
|
||||
#endif
|
||||
_FILL_TEMP_WORD(*address, data);
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_default=Pe1053 /* Back to default. */
|
||||
#pragma diag_default = Pe1053 /* Back to default. */
|
||||
#endif
|
||||
(*address) += 2; /* Select next word in memory. */
|
||||
size -= 2; /* Reduce number of bytes to write by two. */
|
||||
(*address) += 2; /* Select next word in memory. */
|
||||
size -= 2; /* Reduce number of bytes to write by two. */
|
||||
} while (size); /* Loop until all bytes written. */
|
||||
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
|
||||
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
|
||||
long-type address to flash ptr. */
|
||||
#endif
|
||||
_PAGE_WRITE(tempaddress);
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_default=Pe1053 /* Back to default. */
|
||||
#pragma diag_default = Pe1053 /* Back to default. */
|
||||
#endif
|
||||
_WAIT_FOR_SPM();
|
||||
_ENABLE_RWW_SECTION();
|
||||
|
||||
(*address) >>= 1; /* Convert address back to Flash words again. */
|
||||
return '\r'; /* Report programming OK */
|
||||
(*address) >>= 1; /* Convert address back to Flash words again. */
|
||||
return '\r'; /* Report programming OK */
|
||||
}
|
||||
|
||||
/* Invalid memory type? */
|
||||
@@ -421,46 +409,42 @@ unsigned char BlockLoad(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BlockRead(
|
||||
unsigned int size,
|
||||
unsigned char mem,
|
||||
ADDR_T * address)
|
||||
void BlockRead(unsigned int size, unsigned char mem, ADDR_T *address)
|
||||
{
|
||||
/* EEPROM memory type. */
|
||||
if (mem == 'E') { /* Read EEPROM */
|
||||
if (mem == 'E') { /* Read EEPROM */
|
||||
do {
|
||||
EEARL = *address; /* Setup EEPROM address */
|
||||
EEARL = *address; /* Setup EEPROM address */
|
||||
EEARH = ((*address) >> 8);
|
||||
(*address)++; /* Select next EEPROM byte */
|
||||
EECR |= (1 << EERE); /* Read EEPROM */
|
||||
sendchar(EEDR); /* Transmit EEPROM dat ato PC */
|
||||
(*address)++; /* Select next EEPROM byte */
|
||||
EECR |= (1 << EERE); /* Read EEPROM */
|
||||
sendchar(EEDR); /* Transmit EEPROM dat ato PC */
|
||||
|
||||
size--; /* Decrease number of bytes to read */
|
||||
size--; /* Decrease number of bytes to read */
|
||||
} while (size); /* Repeat until all block has been read */
|
||||
}
|
||||
|
||||
/* Flash memory type. */
|
||||
else if (mem == 'F') {
|
||||
(*address) <<= 1; /* Convert address to bytes temporarily. */
|
||||
(*address) <<= 1; /* Convert address to bytes temporarily. */
|
||||
|
||||
do {
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_suppress=Pe1053 /* Suppress warning for conversion from long-type address to flash ptr. */
|
||||
#pragma diag_suppress = Pe1053 /* Suppress warning for conversion from \
|
||||
long-type address to flash ptr. */
|
||||
#endif
|
||||
sendchar(_LOAD_PROGRAM_MEMORY(*address));
|
||||
sendchar(_LOAD_PROGRAM_MEMORY((*address) + 1));
|
||||
#ifdef __ICCAVR__
|
||||
#pragma diag_default=Pe1053 /* Back to default. */
|
||||
#pragma diag_default = Pe1053 /* Back to default. */
|
||||
#endif
|
||||
(*address) += 2; /* Select next word in memory. */
|
||||
size -= 2; /* Subtract two bytes from number of bytes to read */
|
||||
(*address) += 2; /* Select next word in memory. */
|
||||
size -= 2; /* Subtract two bytes from number of bytes to read */
|
||||
} while (size); /* Repeat until all block has been read */
|
||||
|
||||
(*address) >>= 1; /* Convert address back to Flash words again. */
|
||||
(*address) >>= 1; /* Convert address back to Flash words again. */
|
||||
}
|
||||
}
|
||||
#endif /* REMOVE_BLOCK_SUPPORT */
|
||||
|
||||
|
||||
/* end of file */
|
||||
|
||||
@@ -1,44 +1,41 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Atmel Corporation
|
||||
*
|
||||
* File : serial.c
|
||||
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
|
||||
* Revision : $Revision: 1.7 $
|
||||
* Date : $Date: Tuesday, June 07, 200 $
|
||||
* Updated by : $Author: raapeland $
|
||||
*
|
||||
* Support mail : avr@atmel.com
|
||||
*
|
||||
* Target platform : All AVRs with bootloader support
|
||||
*
|
||||
* AppNote : AVR109 - Self-programming
|
||||
*
|
||||
* Description : UART communication routines
|
||||
****************************************************************************/
|
||||
*
|
||||
* Atmel Corporation
|
||||
*
|
||||
* File : serial.c
|
||||
* Compiler : IAR C 3.10C Kickstart, AVR-GCC/avr-libc(>= 1.2.5)
|
||||
* Revision : $Revision: 1.7 $
|
||||
* Date : $Date: Tuesday, June 07, 200 $
|
||||
* Updated by : $Author: raapeland $
|
||||
*
|
||||
* Support mail : avr@atmel.com
|
||||
*
|
||||
* Target platform : All AVRs with bootloader support
|
||||
*
|
||||
* AppNote : AVR109 - Self-programming
|
||||
*
|
||||
* Description : UART communication routines
|
||||
****************************************************************************/
|
||||
#include "defines.h"
|
||||
|
||||
|
||||
void initbootuart(
|
||||
void)
|
||||
void initbootuart(void)
|
||||
{
|
||||
BAUD_RATE_LOW_REG = BRREG_VALUE;
|
||||
UART_CONTROL_REG = (1 << ENABLE_RECEIVER_BIT) | (1 << ENABLE_TRANSMITTER_BIT); /* enable receive and transmit */
|
||||
UART_CONTROL_REG = (1 << ENABLE_RECEIVER_BIT) |
|
||||
(1 << ENABLE_TRANSMITTER_BIT); /* enable receive and transmit */
|
||||
}
|
||||
|
||||
|
||||
void sendchar(
|
||||
unsigned char c)
|
||||
void sendchar(unsigned char c)
|
||||
{
|
||||
UART_DATA_REG = c; /* prepare transmission */
|
||||
while (!(UART_STATUS_REG & (1 << TRANSMIT_COMPLETE_BIT))); /* wait until byte sendt */
|
||||
UART_STATUS_REG |= (1 << TRANSMIT_COMPLETE_BIT); /* delete TXCflag */
|
||||
UART_DATA_REG = c; /* prepare transmission */
|
||||
while (!(UART_STATUS_REG & (1 << TRANSMIT_COMPLETE_BIT)))
|
||||
; /* wait until byte sendt */
|
||||
UART_STATUS_REG |= (1 << TRANSMIT_COMPLETE_BIT); /* delete TXCflag */
|
||||
}
|
||||
|
||||
|
||||
unsigned char recchar(
|
||||
void)
|
||||
unsigned char recchar(void)
|
||||
{
|
||||
while (!(UART_STATUS_REG & (1 << RECEIVE_COMPLETE_BIT))); /* wait for data */
|
||||
while (!(UART_STATUS_REG & (1 << RECEIVE_COMPLETE_BIT)))
|
||||
; /* wait for data */
|
||||
return UART_DATA_REG;
|
||||
}
|
||||
|
||||
+139
-212
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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 <stdlib.h>
|
||||
@@ -50,10 +50,8 @@
|
||||
static const char *BACnet_Version = BACNET_VERSION_TEXT;
|
||||
|
||||
/* forward prototype */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata);
|
||||
bool Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data);
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
static struct my_object_functions {
|
||||
BACNET_OBJECT_TYPE Object_Type;
|
||||
@@ -65,31 +63,28 @@ static struct my_object_functions {
|
||||
read_property_function Object_Read_Property;
|
||||
write_property_function Object_Write_Property;
|
||||
rpm_property_lists_function Object_RPM_List;
|
||||
} Object_Table[] = {
|
||||
{
|
||||
OBJECT_DEVICE, NULL, /* don't init - recursive! */
|
||||
Device_Count, Device_Index_To_Instance,
|
||||
Device_Valid_Object_Instance_Number, Device_Object_Name,
|
||||
Device_Read_Property_Local, Device_Write_Property_Local,
|
||||
Device_Property_Lists}, {
|
||||
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
|
||||
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
|
||||
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
|
||||
Analog_Input_Property_Lists}, {
|
||||
OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
|
||||
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
|
||||
Analog_Value_Object_Name, Analog_Value_Read_Property,
|
||||
Analog_Value_Write_Property, Analog_Value_Property_Lists}, {
|
||||
OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count,
|
||||
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance,
|
||||
Binary_Input_Object_Name, Binary_Input_Read_Property, NULL,
|
||||
Binary_Input_Property_Lists}, {
|
||||
OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count,
|
||||
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance,
|
||||
Binary_Output_Object_Name, Binary_Output_Read_Property,
|
||||
Binary_Output_Write_Property, Binary_Output_Property_Lists}, {
|
||||
MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
|
||||
Device_Count, Device_Index_To_Instance,
|
||||
Device_Valid_Object_Instance_Number,
|
||||
Device_Object_Name, Device_Read_Property_Local,
|
||||
Device_Write_Property_Local, Device_Property_Lists },
|
||||
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
|
||||
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
|
||||
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL,
|
||||
Analog_Input_Property_Lists },
|
||||
{ OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
|
||||
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
|
||||
Analog_Value_Object_Name, Analog_Value_Read_Property,
|
||||
Analog_Value_Write_Property, Analog_Value_Property_Lists },
|
||||
{ OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count,
|
||||
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance,
|
||||
Binary_Input_Object_Name, Binary_Input_Read_Property, NULL,
|
||||
Binary_Input_Property_Lists },
|
||||
{ OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count,
|
||||
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance,
|
||||
Binary_Output_Object_Name, Binary_Output_Read_Property,
|
||||
Binary_Output_Write_Property, Binary_Output_Property_Lists },
|
||||
{ MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL } };
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
@@ -102,44 +97,20 @@ static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
||||
static const char *Reinit_Password = "rehmite";
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Device_Properties_Required[] = {
|
||||
PROP_OBJECT_IDENTIFIER,
|
||||
PROP_OBJECT_NAME,
|
||||
PROP_OBJECT_TYPE,
|
||||
PROP_SYSTEM_STATUS,
|
||||
PROP_VENDOR_NAME,
|
||||
PROP_VENDOR_IDENTIFIER,
|
||||
PROP_MODEL_NAME,
|
||||
PROP_FIRMWARE_REVISION,
|
||||
PROP_APPLICATION_SOFTWARE_VERSION,
|
||||
PROP_PROTOCOL_VERSION,
|
||||
PROP_PROTOCOL_REVISION,
|
||||
PROP_PROTOCOL_SERVICES_SUPPORTED,
|
||||
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
|
||||
PROP_OBJECT_LIST,
|
||||
PROP_MAX_APDU_LENGTH_ACCEPTED,
|
||||
PROP_SEGMENTATION_SUPPORTED,
|
||||
PROP_APDU_TIMEOUT,
|
||||
PROP_NUMBER_OF_APDU_RETRIES,
|
||||
PROP_DEVICE_ADDRESS_BINDING,
|
||||
PROP_DATABASE_REVISION,
|
||||
-1
|
||||
};
|
||||
static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
|
||||
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_SYSTEM_STATUS, PROP_VENDOR_NAME,
|
||||
PROP_VENDOR_IDENTIFIER, PROP_MODEL_NAME, PROP_FIRMWARE_REVISION,
|
||||
PROP_APPLICATION_SOFTWARE_VERSION, PROP_PROTOCOL_VERSION,
|
||||
PROP_PROTOCOL_REVISION, PROP_PROTOCOL_SERVICES_SUPPORTED,
|
||||
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED, PROP_OBJECT_LIST,
|
||||
PROP_MAX_APDU_LENGTH_ACCEPTED, PROP_SEGMENTATION_SUPPORTED,
|
||||
PROP_APDU_TIMEOUT, PROP_NUMBER_OF_APDU_RETRIES, PROP_DEVICE_ADDRESS_BINDING,
|
||||
PROP_DATABASE_REVISION, -1 };
|
||||
|
||||
static const int Device_Properties_Optional[] = {
|
||||
PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_LOCATION,
|
||||
-1
|
||||
};
|
||||
static const int Device_Properties_Optional[] = { PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES, PROP_DESCRIPTION, PROP_LOCATION, -1 };
|
||||
|
||||
static const int Device_Properties_Proprietary[] = {
|
||||
512,
|
||||
513,
|
||||
9600,
|
||||
-1
|
||||
};
|
||||
static const int Device_Properties_Proprietary[] = { 512, 513, 9600, -1 };
|
||||
|
||||
static struct my_object_functions *Device_Objects_Find_Functions(
|
||||
BACNET_OBJECT_TYPE Object_Type)
|
||||
@@ -161,8 +132,7 @@ static struct my_object_functions *Device_Objects_Find_Functions(
|
||||
|
||||
/* Encodes the property APDU and returns the length,
|
||||
or sets the error, and returns BACNET_STATUS_ERROR */
|
||||
int Device_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
struct my_object_functions *pObject = NULL;
|
||||
@@ -183,8 +153,7 @@ int Device_Read_Property(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false;
|
||||
struct my_object_functions *pObject = NULL;
|
||||
@@ -212,8 +181,7 @@ bool Device_Write_Property(
|
||||
return status;
|
||||
}
|
||||
|
||||
static unsigned my_property_list_count(
|
||||
const int *pList)
|
||||
static unsigned my_property_list_count(const int *pList)
|
||||
{
|
||||
unsigned property_count = 0;
|
||||
|
||||
@@ -228,8 +196,7 @@ static unsigned my_property_list_count(
|
||||
}
|
||||
|
||||
/* for a given object type, returns the special property list */
|
||||
void Device_Objects_Property_List(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
void Device_Objects_Property_List(BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
struct special_property_list_t *pPropertyList)
|
||||
{
|
||||
@@ -252,25 +219,23 @@ void Device_Objects_Property_List(
|
||||
}
|
||||
|
||||
/* Fetch the counts if available otherwise zero them */
|
||||
pPropertyList->Required.count =
|
||||
pPropertyList->Required.pList ==
|
||||
NULL ? 0 : my_property_list_count(pPropertyList->Required.pList);
|
||||
pPropertyList->Required.count = pPropertyList->Required.pList == NULL
|
||||
? 0
|
||||
: my_property_list_count(pPropertyList->Required.pList);
|
||||
|
||||
pPropertyList->Optional.count =
|
||||
pPropertyList->Optional.pList ==
|
||||
NULL ? 0 : my_property_list_count(pPropertyList->Optional.pList);
|
||||
pPropertyList->Optional.count = pPropertyList->Optional.pList == NULL
|
||||
? 0
|
||||
: my_property_list_count(pPropertyList->Optional.pList);
|
||||
|
||||
pPropertyList->Proprietary.count =
|
||||
pPropertyList->Proprietary.pList ==
|
||||
NULL ? 0 : my_property_list_count(pPropertyList->Proprietary.pList);
|
||||
pPropertyList->Proprietary.count = pPropertyList->Proprietary.pList == NULL
|
||||
? 0
|
||||
: my_property_list_count(pPropertyList->Proprietary.pList);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Device_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Device_Properties_Required;
|
||||
@@ -282,23 +247,20 @@ void Device_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned Device_Count(
|
||||
void)
|
||||
unsigned Device_Count(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t Device_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Device_Index_To_Instance(unsigned index)
|
||||
{
|
||||
index = index;
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
static char *Device_Name_Default(
|
||||
void)
|
||||
static char *Device_Name_Default(void)
|
||||
{
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
static char text_string[32]; /* okay for single thread */
|
||||
|
||||
sprintf(text_string, "DEVICE-%lu", Object_Instance_Number);
|
||||
|
||||
@@ -306,8 +268,7 @@ static char *Device_Name_Default(
|
||||
}
|
||||
|
||||
bool Device_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -319,8 +280,7 @@ bool Device_Object_Name(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Reinitialize(
|
||||
BACNET_REINITIALIZE_DEVICE_DATA * rd_data)
|
||||
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -363,20 +323,18 @@ bool Device_Reinitialize(
|
||||
return status;
|
||||
}
|
||||
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(
|
||||
void)
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(void)
|
||||
{
|
||||
return Reinitialize_State;
|
||||
}
|
||||
|
||||
void Device_Init(
|
||||
object_functions_t * object_table)
|
||||
void Device_Init(object_functions_t *object_table)
|
||||
{
|
||||
struct my_object_functions *pObject = NULL;
|
||||
|
||||
/* we don't use the object table passed in
|
||||
since there is extra stuff we don't need in there. */
|
||||
(void) object_table;
|
||||
(void)object_table;
|
||||
/* our local object table */
|
||||
pObject = &Object_Table[0];
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
@@ -389,14 +347,12 @@ void Device_Init(
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
@@ -411,21 +367,17 @@ bool Device_Set_Object_Instance_Number(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
return (Object_Instance_Number == object_id);
|
||||
}
|
||||
|
||||
BACNET_DEVICE_STATUS Device_System_Status(
|
||||
void)
|
||||
BACNET_DEVICE_STATUS Device_System_Status(void)
|
||||
{
|
||||
return System_Status;
|
||||
}
|
||||
|
||||
int Device_Set_System_Status(
|
||||
BACNET_DEVICE_STATUS status,
|
||||
bool local)
|
||||
int Device_Set_System_Status(BACNET_DEVICE_STATUS status, bool local)
|
||||
{
|
||||
/*return value - 0 = ok, -1 = bad value, -2 = not allowed */
|
||||
int result = -1;
|
||||
@@ -438,34 +390,29 @@ int Device_Set_System_Status(
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(
|
||||
void)
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
|
||||
{
|
||||
return SEGMENTATION_NONE;
|
||||
}
|
||||
|
||||
uint32_t Device_Database_Revision(
|
||||
void)
|
||||
uint32_t Device_Database_Revision(void)
|
||||
{
|
||||
return Database_Revision;
|
||||
}
|
||||
|
||||
void Device_Inc_Database_Revision(
|
||||
void)
|
||||
void Device_Inc_Database_Revision(void)
|
||||
{
|
||||
Database_Revision++;
|
||||
}
|
||||
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 0; /* number of objects */
|
||||
struct my_object_functions *pObject = NULL;
|
||||
@@ -483,9 +430,7 @@ unsigned Device_Object_List_Count(
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(
|
||||
uint32_t array_index,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * instance)
|
||||
uint32_t array_index, BACNET_OBJECT_TYPE *object_type, uint32_t *instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t count = 0;
|
||||
@@ -516,10 +461,9 @@ bool Device_Object_List_Identifier(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Name(
|
||||
BACNET_CHARACTER_STRING * object_name1,
|
||||
bool Device_Valid_Object_Name(BACNET_CHARACTER_STRING *object_name1,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * object_instance)
|
||||
uint32_t *object_instance)
|
||||
{
|
||||
bool found = false;
|
||||
BACNET_OBJECT_TYPE type = OBJECT_NONE;
|
||||
@@ -533,7 +477,7 @@ bool Device_Valid_Object_Name(
|
||||
for (i = 1; i <= max_objects; i++) {
|
||||
check_id = Device_Object_List_Identifier(i, &type, &instance);
|
||||
if (check_id) {
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE) type);
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE)type);
|
||||
if ((pObject != NULL) && (pObject->Object_Name != NULL) &&
|
||||
(pObject->Object_Name(instance, &object_name2) &&
|
||||
characterstring_same(object_name1, &object_name2))) {
|
||||
@@ -553,13 +497,12 @@ bool Device_Valid_Object_Name(
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Id(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance)
|
||||
BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
struct my_object_functions *pObject = NULL;
|
||||
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE) object_type);
|
||||
pObject = Device_Objects_Find_Functions((BACNET_OBJECT_TYPE)object_type);
|
||||
if ((pObject != NULL) && (pObject->Object_Valid_Instance != NULL)) {
|
||||
status = pObject->Object_Valid_Instance(object_instance);
|
||||
}
|
||||
@@ -567,10 +510,9 @@ bool Device_Valid_Object_Id(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Object_Name_Copy(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
bool Device_Object_Name_Copy(BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
struct my_object_functions *pObject = NULL;
|
||||
bool found = false;
|
||||
@@ -584,11 +526,10 @@ bool Device_Object_Name_Copy(
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or BACNET_STATUS_ERROR for error */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string = { 0 };
|
||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||
uint32_t i = 0;
|
||||
@@ -603,11 +544,10 @@ int Device_Read_Property_Local(
|
||||
return 0;
|
||||
}
|
||||
apdu = rpdata->application_data;
|
||||
switch ((int) rpdata->object_property) {
|
||||
switch ((int)rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], rpdata->object_type,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], rpdata->object_type, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
Device_Object_Name(rpdata->object_instance, &char_string);
|
||||
@@ -625,15 +565,14 @@ int Device_Read_Property_Local(
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_LOCATION:
|
||||
bacnet_name(NV_EEPROM_DEVICE_LOCATION, &char_string,
|
||||
"default location");
|
||||
bacnet_name(
|
||||
NV_EEPROM_DEVICE_LOCATION, &char_string, "default location");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_System_Status());
|
||||
encode_application_enumerated(&apdu[0], Device_System_Status());
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
@@ -664,16 +603,15 @@ int Device_Read_Property_Local(
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
BACNET_PROTOCOL_REVISION);
|
||||
encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_REVISION);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED)i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -683,7 +621,7 @@ int Device_Read_Property_Local(
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i, false);
|
||||
}
|
||||
/* set the object types with objects to supported */
|
||||
i = 0;
|
||||
@@ -707,11 +645,10 @@ int Device_Read_Property_Local(
|
||||
/* your maximum APDU size. */
|
||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
if (Device_Object_List_Identifier(i, &object_type,
|
||||
&instance)) {
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
i, &object_type, &instance)) {
|
||||
len = encode_application_object_id(
|
||||
&apdu[apdu_len], object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
@@ -731,11 +668,10 @@ int Device_Read_Property_Local(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(rpdata->array_index,
|
||||
&object_type, &instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
rpdata->array_index, &object_type, &instance))
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], object_type, instance);
|
||||
else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
@@ -747,9 +683,8 @@ int Device_Read_Property_Local(
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_Segmentation_Supported());
|
||||
apdu_len = encode_application_enumerated(
|
||||
&apdu[0], Device_Segmentation_Supported());
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout());
|
||||
@@ -761,14 +696,12 @@ int Device_Read_Property_Local(
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Database_Revision());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Database_Revision());
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
dlmstp_max_info_frames());
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len =
|
||||
@@ -781,8 +714,7 @@ int Device_Read_Property_Local(
|
||||
apdu_len = encode_application_unsigned(&apdu[0], stack_unused());
|
||||
break;
|
||||
case 9600:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], rs485_baud_rate());
|
||||
apdu_len = encode_application_unsigned(&apdu[0], rs485_baud_rate());
|
||||
break;
|
||||
default:
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -801,18 +733,16 @@ int Device_Read_Property_Local(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value - false=error */
|
||||
bool status = false; /* return value - false=error */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
uint8_t max_master = 0;
|
||||
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -827,14 +757,14 @@ bool Device_Write_Property_Local(
|
||||
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
return false;
|
||||
}
|
||||
switch ((int) wp_data->object_property) {
|
||||
switch ((int)wp_data->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.
|
||||
Object_Id.instance))) {
|
||||
(Device_Set_Object_Instance_Number(
|
||||
value.type.Object_Id.instance))) {
|
||||
eeprom_bytes_write(NV_EEPROM_DEVICE_0,
|
||||
(uint8_t *) & value.type.Object_Id.instance, 4);
|
||||
(uint8_t *)&value.type.Object_Id.instance, 4);
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
@@ -879,8 +809,7 @@ bool Device_Write_Property_Local(
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
status =
|
||||
bacnet_name_write_unique(NV_EEPROM_DEVICE_NAME,
|
||||
status = bacnet_name_write_unique(NV_EEPROM_DEVICE_NAME,
|
||||
wp_data->object_type, wp_data->object_instance,
|
||||
&value.type.Character_String, &wp_data->error_class,
|
||||
&wp_data->error_code);
|
||||
@@ -891,8 +820,7 @@ bool Device_Write_Property_Local(
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
status =
|
||||
bacnet_name_write(NV_EEPROM_DEVICE_DESCRIPTION,
|
||||
status = bacnet_name_write(NV_EEPROM_DEVICE_DESCRIPTION,
|
||||
&value.type.Character_String, &wp_data->error_class,
|
||||
&wp_data->error_code);
|
||||
} else {
|
||||
@@ -902,8 +830,7 @@ bool Device_Write_Property_Local(
|
||||
break;
|
||||
case PROP_LOCATION:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
|
||||
status =
|
||||
bacnet_name_write(NV_EEPROM_DEVICE_LOCATION,
|
||||
status = bacnet_name_write(NV_EEPROM_DEVICE_LOCATION,
|
||||
&value.type.Character_String, &wp_data->error_class,
|
||||
&wp_data->error_code);
|
||||
} else {
|
||||
|
||||
+86
-107
@@ -68,19 +68,19 @@ static struct mstp_flag_t {
|
||||
/* A Boolean flag set to TRUE by the Receive State Machine */
|
||||
/* if an invalid frame is received. */
|
||||
/* 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;
|
||||
/* set to TRUE when we get a frame not for us */
|
||||
unsigned ReceivedValidFrameNotForUs:1;
|
||||
unsigned ReceivedValidFrameNotForUs : 1;
|
||||
/* A Boolean flag set to TRUE by the master machine if this node is the */
|
||||
/* only known master node. */
|
||||
unsigned SoleMaster:1;
|
||||
unsigned SoleMaster : 1;
|
||||
/* A Boolean flag set TRUE by the datalink if a
|
||||
packet has been received, but not processed. */
|
||||
unsigned ReceivePacketPending:1;
|
||||
unsigned ReceivePacketPending : 1;
|
||||
} MSTP_Flag;
|
||||
|
||||
/* Used to store the data length of a received frame. */
|
||||
@@ -182,7 +182,11 @@ static uint8_t Nmax_master = 127;
|
||||
#define Tusage_delay 15
|
||||
|
||||
/* 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++; \
|
||||
}
|
||||
|
||||
/* data structure for MS/TP PDU Queue */
|
||||
struct mstp_pdu_packet {
|
||||
@@ -194,26 +198,22 @@ struct mstp_pdu_packet {
|
||||
static struct mstp_pdu_packet PDU_Buffer[MSTP_PDU_PACKET_COUNT];
|
||||
static RING_BUFFER PDU_Queue;
|
||||
|
||||
bool dlmstp_init(
|
||||
char *ifname)
|
||||
bool dlmstp_init(char *ifname)
|
||||
{
|
||||
ifname = ifname;
|
||||
|
||||
Ringbuf_Init(&PDU_Queue, (uint8_t *) & PDU_Buffer,
|
||||
Ringbuf_Init(&PDU_Queue, (uint8_t *)&PDU_Buffer,
|
||||
sizeof(struct mstp_pdu_packet), MSTP_PDU_PACKET_COUNT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dlmstp_cleanup(
|
||||
void)
|
||||
void dlmstp_cleanup(void)
|
||||
{
|
||||
/* nothing to do for static buffers */
|
||||
}
|
||||
|
||||
void dlmstp_fill_bacnet_address(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t mstp_address)
|
||||
void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -236,11 +236,10 @@ void dlmstp_fill_bacnet_address(
|
||||
}
|
||||
}
|
||||
|
||||
static bool dlmstp_compare_data_expecting_reply(
|
||||
uint8_t * request_pdu,
|
||||
static bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
uint16_t request_pdu_len,
|
||||
uint8_t src_address,
|
||||
uint8_t * reply_pdu,
|
||||
uint8_t *reply_pdu,
|
||||
uint16_t reply_pdu_len,
|
||||
uint8_t dest_address)
|
||||
{
|
||||
@@ -261,9 +260,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the request data */
|
||||
request.address.mac[0] = src_address;
|
||||
request.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&request_pdu[0], NULL, &request.address,
|
||||
&request.npdu_data);
|
||||
offset = npdu_decode(
|
||||
&request_pdu[0], NULL, &request.address, &request.npdu_data);
|
||||
if (request.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
@@ -280,8 +278,7 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the reply data */
|
||||
reply.address.mac[0] = dest_address;
|
||||
reply.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
offset = npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
if (reply.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
@@ -322,7 +319,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (request.npdu_data.protocol_version != reply.npdu_data.protocol_version) {
|
||||
if (request.npdu_data.protocol_version !=
|
||||
reply.npdu_data.protocol_version) {
|
||||
return false;
|
||||
}
|
||||
#if 0
|
||||
@@ -354,16 +352,16 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* (pad): (optional) at most one octet of padding: X'FF' */
|
||||
static void MSTP_Send_Frame(
|
||||
uint8_t frame_type, /* type of frame to send - see defines */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t * data, /* any data to be sent - may be null */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t *data, /* any data to be sent - may be null */
|
||||
uint16_t data_len)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
uint8_t buffer[8]; /* stores the header and header crc */
|
||||
uint8_t buffer_crc[2]; /* stores the data crc */
|
||||
uint16_t i = 0; /* used to calculate CRC for data */
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
uint8_t buffer[8]; /* stores the header and header crc */
|
||||
uint8_t buffer_crc[2]; /* stores the data crc */
|
||||
uint16_t i = 0; /* used to calculate CRC for data */
|
||||
|
||||
/* create the MS/TP header */
|
||||
buffer[0] = 0x55;
|
||||
@@ -401,8 +399,7 @@ static void MSTP_Send_Frame(
|
||||
rs485_rts_enable(false);
|
||||
}
|
||||
|
||||
static void MSTP_Receive_Frame_FSM(
|
||||
void)
|
||||
static void MSTP_Receive_Frame_FSM(void)
|
||||
{
|
||||
/* stores the latest received data octet */
|
||||
uint8_t DataRegister = 0;
|
||||
@@ -638,8 +635,7 @@ static void MSTP_Receive_Frame_FSM(
|
||||
#ifdef MSTP_DEBUG_STATES
|
||||
static MSTP_MASTER_STATE Master_State_Log[128];
|
||||
static unsigned master_state_log_index = 0;
|
||||
void log_master_state(
|
||||
MSTP_MASTER_STATE state)
|
||||
void log_master_state(MSTP_MASTER_STATE state)
|
||||
{
|
||||
Master_State_Log[master_state_log_index] = state;
|
||||
master_state_log_index++;
|
||||
@@ -652,8 +648,7 @@ void log_master_state(
|
||||
#endif
|
||||
|
||||
/* returns true if we need to transition immediately */
|
||||
static bool MSTP_Master_Node_FSM(
|
||||
void)
|
||||
static bool MSTP_Master_Node_FSM(void)
|
||||
{
|
||||
/* The number of frames sent by this node during a single token hold. */
|
||||
/* When this counter reaches the value Nmax_info_frames, the node must */
|
||||
@@ -758,9 +753,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
}
|
||||
break;
|
||||
case FRAME_TYPE_TEST_REQUEST:
|
||||
MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE,
|
||||
SourceAddress, This_Station, &InputBuffer[0],
|
||||
DataLength);
|
||||
MSTP_Send_Frame(FRAME_TYPE_TEST_RESPONSE, SourceAddress,
|
||||
This_Station, &InputBuffer[0], DataLength);
|
||||
break;
|
||||
case FRAME_TYPE_TEST_RESPONSE:
|
||||
default:
|
||||
@@ -785,14 +779,14 @@ static bool MSTP_Master_Node_FSM(
|
||||
transition_now = true;
|
||||
} else {
|
||||
uint8_t frame_type;
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
if (pkt->data_expecting_reply) {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
|
||||
} else {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station,
|
||||
(uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
FrameCount++;
|
||||
switch (frame_type) {
|
||||
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
|
||||
@@ -812,7 +806,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
Master_State = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
break;
|
||||
}
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
}
|
||||
break;
|
||||
case MSTP_MASTER_STATE_WAIT_FOR_REPLY:
|
||||
@@ -924,8 +918,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
may be found in that case. */
|
||||
TokenCount++;
|
||||
/* transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
RetryCount = 0;
|
||||
EventCount = 0;
|
||||
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
|
||||
@@ -939,7 +933,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* no known successor node */
|
||||
Next_Station = This_Station;
|
||||
RetryCount = 0;
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
/* EventCount = 0; removed in Addendum 135-2004d-8 */
|
||||
/* find a new successor to TS */
|
||||
Master_State = MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
@@ -947,10 +941,10 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* ResetMaintenancePFM */
|
||||
Poll_Station = This_Station;
|
||||
/* transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
RetryCount = 0;
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
EventCount = 0;
|
||||
Master_State = MSTP_MASTER_STATE_PASS_TOKEN;
|
||||
}
|
||||
@@ -971,8 +965,8 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* RetrySendToken */
|
||||
RetryCount++;
|
||||
/* Transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
EventCount = 0;
|
||||
/* re-enter the current state to listen for NS */
|
||||
/* to begin using the token. */
|
||||
@@ -1049,15 +1043,15 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* a successor node. */
|
||||
case MSTP_MASTER_STATE_POLL_FOR_MASTER:
|
||||
if (MSTP_Flag.ReceivedValidFrame == true) {
|
||||
if ((DestinationAddress == This_Station)
|
||||
&& (FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
|
||||
if ((DestinationAddress == This_Station) &&
|
||||
(FrameType == FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
|
||||
/* ReceivedReplyToPFM */
|
||||
MSTP_Flag.SoleMaster = false;
|
||||
Next_Station = SourceAddress;
|
||||
EventCount = 0;
|
||||
/* Transmit a Token frame to NS */
|
||||
MSTP_Send_Frame(FRAME_TYPE_TOKEN, Next_Station,
|
||||
This_Station, NULL, 0);
|
||||
MSTP_Send_Frame(
|
||||
FRAME_TYPE_TOKEN, Next_Station, This_Station, NULL, 0);
|
||||
Poll_Station = This_Station;
|
||||
TokenCount = 0;
|
||||
RetryCount = 0;
|
||||
@@ -1122,12 +1116,11 @@ static bool MSTP_Master_Node_FSM(
|
||||
/* a proprietary frame that expects a reply is received. */
|
||||
timeout = rs485_silence_time_elapsed(Treply_delay);
|
||||
if (!timeout) {
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
if (pkt != NULL) {
|
||||
matched =
|
||||
dlmstp_compare_data_expecting_reply(&InputBuffer[0],
|
||||
DataLength, SourceAddress, &pkt->buffer[0],
|
||||
pkt->length, pkt->destination_mac);
|
||||
matched = dlmstp_compare_data_expecting_reply(
|
||||
&InputBuffer[0], DataLength, SourceAddress,
|
||||
&pkt->buffer[0], pkt->length, pkt->destination_mac);
|
||||
} else {
|
||||
matched = false;
|
||||
}
|
||||
@@ -1144,17 +1137,15 @@ static bool MSTP_Master_Node_FSM(
|
||||
if (pkt->data_expecting_reply) {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
|
||||
} else {
|
||||
frame_type =
|
||||
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
MSTP_Send_Frame(frame_type, pkt->destination_mac,
|
||||
This_Station, (uint8_t *) & pkt->buffer[0],
|
||||
pkt->length);
|
||||
MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station,
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
Master_State = MSTP_MASTER_STATE_IDLE;
|
||||
/* clear our flag we were holding for comparison */
|
||||
MSTP_Flag.ReceivedValidFrame = false;
|
||||
/* clear the queue */
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
} else if ((pkt != NULL) || timeout) {
|
||||
/* DeferredReply */
|
||||
/* If no reply will be available from the higher layers */
|
||||
@@ -1180,8 +1171,7 @@ static bool MSTP_Master_Node_FSM(
|
||||
return transition_now;
|
||||
}
|
||||
|
||||
static void MSTP_Slave_Node_FSM(
|
||||
void)
|
||||
static void MSTP_Slave_Node_FSM(void)
|
||||
{
|
||||
/* packet from the PDU Queue */
|
||||
struct mstp_pdu_packet *pkt;
|
||||
@@ -1215,9 +1205,8 @@ static void MSTP_Slave_Node_FSM(
|
||||
}
|
||||
} else if (MSTP_Flag.ReceivePacketPending) {
|
||||
if (!Ringbuf_Empty(&PDU_Queue)) {
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
matched =
|
||||
dlmstp_compare_data_expecting_reply(&InputBuffer[0],
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
matched = dlmstp_compare_data_expecting_reply(&InputBuffer[0],
|
||||
DataLength, SourceAddress, &pkt->buffer[0], pkt->length,
|
||||
pkt->destination_mac);
|
||||
if (matched) {
|
||||
@@ -1235,8 +1224,8 @@ static void MSTP_Slave_Node_FSM(
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
MSTP_Send_Frame(frame_type, pkt->destination_mac, This_Station,
|
||||
(uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
}
|
||||
/* clear our flag we were holding for comparison */
|
||||
MSTP_Flag.ReceivePacketPending = false;
|
||||
@@ -1252,17 +1241,16 @@ static void MSTP_Slave_Node_FSM(
|
||||
}
|
||||
|
||||
/* returns number of bytes sent on success, zero on failure */
|
||||
int dlmstp_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int dlmstp_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int bytes_sent = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
uint16_t i = 0;
|
||||
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Data_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Data_Peek(&PDU_Queue);
|
||||
if (pkt) {
|
||||
pkt->data_expecting_reply = npdu_data->data_expecting_reply;
|
||||
for (i = 0; i < pdu_len; i++) {
|
||||
@@ -1284,13 +1272,12 @@ int dlmstp_send_pdu(
|
||||
}
|
||||
|
||||
/* Return the length of the packet */
|
||||
uint16_t dlmstp_receive(
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t dlmstp_receive(BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
|
||||
/* set the input buffer to the same data storage for zero copy */
|
||||
if (!InputBuffer) {
|
||||
@@ -1335,8 +1322,7 @@ uint16_t dlmstp_receive(
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void dlmstp_set_mac_address(
|
||||
uint8_t mac_address)
|
||||
void dlmstp_set_mac_address(uint8_t mac_address)
|
||||
{
|
||||
/* Master Nodes can only have address 0-127 */
|
||||
if (mac_address <= 127) {
|
||||
@@ -1348,8 +1334,7 @@ void dlmstp_set_mac_address(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_mac_address(
|
||||
void)
|
||||
uint8_t dlmstp_mac_address(void)
|
||||
{
|
||||
return This_Station;
|
||||
}
|
||||
@@ -1361,8 +1346,7 @@ uint8_t dlmstp_mac_address(
|
||||
/* nodes. This may be used to allocate more or less of the available link */
|
||||
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
||||
/* node, its value shall be 1. */
|
||||
void dlmstp_set_max_info_frames(
|
||||
uint8_t max_info_frames)
|
||||
void dlmstp_set_max_info_frames(uint8_t max_info_frames)
|
||||
{
|
||||
if (max_info_frames >= MSTP_PDU_PACKET_COUNT) {
|
||||
Nmax_info_frames = max_info_frames;
|
||||
@@ -1371,8 +1355,7 @@ void dlmstp_set_max_info_frames(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_info_frames(
|
||||
void)
|
||||
uint8_t dlmstp_max_info_frames(void)
|
||||
{
|
||||
return Nmax_info_frames;
|
||||
}
|
||||
@@ -1382,8 +1365,7 @@ uint8_t dlmstp_max_info_frames(
|
||||
/* allowable address for master nodes. The value of Max_Master shall be */
|
||||
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
||||
/* its value shall be 127. */
|
||||
void dlmstp_set_max_master(
|
||||
uint8_t max_master)
|
||||
void dlmstp_set_max_master(uint8_t max_master)
|
||||
{
|
||||
if (max_master <= 127) {
|
||||
if (This_Station <= max_master) {
|
||||
@@ -1394,20 +1376,18 @@ void dlmstp_set_max_master(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_master(
|
||||
void)
|
||||
uint8_t dlmstp_max_master(void)
|
||||
{
|
||||
return Nmax_master;
|
||||
}
|
||||
|
||||
void dlmstp_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void dlmstp_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0; /* counter */
|
||||
int i = 0; /* counter */
|
||||
|
||||
my_address->mac_len = 1;
|
||||
my_address->mac[0] = This_Station;
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -1416,16 +1396,15 @@ void dlmstp_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void dlmstp_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 1;
|
||||
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
@@ -29,13 +29,12 @@
|
||||
|
||||
/* Internal EEPROM of the AVR - http://supp.iar.com/Support/?note=45745 */
|
||||
|
||||
|
||||
int eeprom_bytes_read(
|
||||
uint16_t eeaddr, /* EEPROM starting memory address (offset of zero) */
|
||||
uint8_t * buf, /* data to store */
|
||||
uint16_t eeaddr, /* EEPROM starting memory address (offset of zero) */
|
||||
uint8_t *buf, /* data to store */
|
||||
int len)
|
||||
{ /* number of bytes of data to read */
|
||||
int count = 0; /* return value */
|
||||
{ /* number of bytes of data to read */
|
||||
int count = 0; /* return value */
|
||||
|
||||
while (len) {
|
||||
__EEGET(buf[count], eeaddr);
|
||||
@@ -47,11 +46,10 @@ int eeprom_bytes_read(
|
||||
return count;
|
||||
}
|
||||
|
||||
int eeprom_bytes_write(
|
||||
uint16_t eeaddr, /* EEPROM starting memory address */
|
||||
uint8_t * buf, /* data to send */
|
||||
int eeprom_bytes_write(uint16_t eeaddr, /* EEPROM starting memory address */
|
||||
uint8_t *buf, /* data to send */
|
||||
int len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int count = 0;
|
||||
|
||||
while (len) {
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*************************************************************************/
|
||||
*
|
||||
* 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 "hardware.h"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
@@ -53,39 +53,39 @@ FUSES = {
|
||||
any fuses listed below are cleared fuses,
|
||||
or are CKSEL or SUT bits that are zero. */
|
||||
.low = (FUSE_CKSEL3 & FUSE_SUT1),
|
||||
/* == HIGH FUSE or HFUSE settings == */
|
||||
/* BOOTRST: Enable Bootloader Reset Vector */
|
||||
/* EESAVE: Enable preserve EEPROM on Chip Erase */
|
||||
/* WDTON: Enable watchdog timer always on */
|
||||
/* SPIEN: Enable Serial Program and Data Downloading */
|
||||
/* JTAGEN: Enable JTAG */
|
||||
/* OCDEN: Enable OCD */
|
||||
/* BOOTSZ configuration:
|
||||
BOOTSZ1 BOOTSZ0 Boot Size
|
||||
------- ------- ---------
|
||||
1 1 512
|
||||
1 0 1024
|
||||
0 1 2048
|
||||
0 0 4096
|
||||
*/
|
||||
/* note: fuses are enabled by clearing the bit, so
|
||||
any fuses listed below are cleared fuses,
|
||||
or are BOOTSZ bits that are zero. */
|
||||
.high = (FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
|
||||
/* == EXTENDED FUSE or EFUSE settings == */
|
||||
/* BODLEVEL configuration
|
||||
BODLEVEL2 BODLEVEL1 BODLEVEL0 Voltage
|
||||
--------- --------- --------- --------
|
||||
1 1 1 disabled
|
||||
1 1 0 1.8V
|
||||
1 0 1 2.7V
|
||||
1 0 0 4.3V
|
||||
*/
|
||||
/* note: fuses are enabled by clearing the bit, so
|
||||
any fuses listed below are cleared fuses,
|
||||
or are BODLEVEL bits that are zero. */
|
||||
/* Brown-out detection VCC=4.3V */
|
||||
.extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0)
|
||||
/* == HIGH FUSE or HFUSE settings == */
|
||||
/* BOOTRST: Enable Bootloader Reset Vector */
|
||||
/* EESAVE: Enable preserve EEPROM on Chip Erase */
|
||||
/* WDTON: Enable watchdog timer always on */
|
||||
/* SPIEN: Enable Serial Program and Data Downloading */
|
||||
/* JTAGEN: Enable JTAG */
|
||||
/* OCDEN: Enable OCD */
|
||||
/* BOOTSZ configuration:
|
||||
BOOTSZ1 BOOTSZ0 Boot Size
|
||||
------- ------- ---------
|
||||
1 1 512
|
||||
1 0 1024
|
||||
0 1 2048
|
||||
0 0 4096
|
||||
*/
|
||||
/* note: fuses are enabled by clearing the bit, so
|
||||
any fuses listed below are cleared fuses,
|
||||
or are BOOTSZ bits that are zero. */
|
||||
.high = (FUSE_BOOTSZ1 & FUSE_EESAVE & FUSE_SPIEN & FUSE_JTAGEN),
|
||||
/* == EXTENDED FUSE or EFUSE settings == */
|
||||
/* BODLEVEL configuration
|
||||
BODLEVEL2 BODLEVEL1 BODLEVEL0 Voltage
|
||||
--------- --------- --------- --------
|
||||
1 1 1 disabled
|
||||
1 1 0 1.8V
|
||||
1 0 1 2.7V
|
||||
1 0 0 4.3V
|
||||
*/
|
||||
/* note: fuses are enabled by clearing the bit, so
|
||||
any fuses listed below are cleared fuses,
|
||||
or are BODLEVEL bits that are zero. */
|
||||
/* Brown-out detection VCC=4.3V */
|
||||
.extended = (FUSE_BODLEVEL1 & FUSE_BODLEVEL0)
|
||||
};
|
||||
|
||||
/* AVR lock bits - unlocked */
|
||||
|
||||
+24
-25
@@ -1,33 +1,32 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 "hardware.h"
|
||||
/* me */
|
||||
#include "init.h"
|
||||
|
||||
void init(
|
||||
void)
|
||||
void init(void)
|
||||
{
|
||||
/* clear the MCU Status Register */
|
||||
MCUSR = 0;
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hardware.h"
|
||||
@@ -43,8 +43,7 @@ static struct mstimer Debounce_Timer;
|
||||
|
||||
#if BDK_V1_HACK
|
||||
/* version 1 BDK workaournd for floating inputs */
|
||||
static void input_switch_workaround(
|
||||
void)
|
||||
static void input_switch_workaround(void)
|
||||
{
|
||||
/* configure the port pins for the switch - as outputs */
|
||||
BIT_SET(DDRA, DDA0);
|
||||
@@ -76,8 +75,7 @@ static void input_switch_workaround(
|
||||
#endif
|
||||
|
||||
/* debounce the inputs */
|
||||
void input_task(
|
||||
void)
|
||||
void input_task(void)
|
||||
{
|
||||
uint8_t value;
|
||||
static uint8_t old_address = 0;
|
||||
@@ -100,7 +98,7 @@ void input_task(
|
||||
Address_Switch = old_address;
|
||||
}
|
||||
old_address = value;
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
/* pins used are PB3, PB2, PB1 */
|
||||
value = BITMASK_CHECK(PINB, 0x0E);
|
||||
value >>= 1;
|
||||
@@ -119,20 +117,17 @@ void input_task(
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t input_address(
|
||||
void)
|
||||
uint8_t input_address(void)
|
||||
{
|
||||
return Address_Switch;
|
||||
}
|
||||
|
||||
uint8_t input_rotary_value(
|
||||
uint8_t index)
|
||||
uint8_t input_rotary_value(uint8_t index)
|
||||
{
|
||||
return Buttons;
|
||||
}
|
||||
|
||||
bool input_button_value(
|
||||
uint8_t index)
|
||||
bool input_button_value(uint8_t index)
|
||||
{
|
||||
bool value = false;
|
||||
|
||||
@@ -159,9 +154,7 @@ bool input_button_value(
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void input_init(
|
||||
void)
|
||||
void input_init(void)
|
||||
{
|
||||
/* configure the port pins for the switch */
|
||||
BIT_CLEAR(DDRA, DDA0);
|
||||
@@ -180,7 +173,7 @@ void input_init(
|
||||
BIT_SET(PORTA, PORTA5);
|
||||
BIT_SET(PORTA, PORTA6);
|
||||
/* configure the port pins for rotary switch inputs */
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_CLEAR(DDRB, DDB1);
|
||||
BIT_CLEAR(DDRB, DDB2);
|
||||
BIT_CLEAR(DDRB, DDB3);
|
||||
|
||||
+71
-81
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
#include "hardware.h"
|
||||
#include "bacnet/basic/sys/mstimer.h"
|
||||
@@ -33,12 +33,11 @@
|
||||
static struct mstimer Off_Delay_Timer[MAX_LEDS];
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Turn on an LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_on(
|
||||
uint8_t index)
|
||||
* Description: Turn on an LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_on(uint8_t index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0:
|
||||
@@ -48,14 +47,14 @@ void led_on(
|
||||
BIT_SET(PORTD, PD6);
|
||||
break;
|
||||
case 2:
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_SET(PORTB, PB0);
|
||||
#else
|
||||
BIT_SET(PORTC, PC7);
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_SET(PORTB, PB4);
|
||||
#else
|
||||
BIT_SET(PORTC, PC6);
|
||||
@@ -70,12 +69,11 @@ void led_on(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Turn off an LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_off(
|
||||
uint8_t index)
|
||||
* Description: Turn off an LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_off(uint8_t index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0:
|
||||
@@ -85,14 +83,14 @@ void led_off(
|
||||
BIT_CLEAR(PORTD, PD6);
|
||||
break;
|
||||
case 2:
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_CLEAR(PORTB, PB0);
|
||||
#else
|
||||
BIT_CLEAR(PORTC, PC7);
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_CLEAR(PORTB, PB4);
|
||||
#else
|
||||
BIT_CLEAR(PORTC, PC6);
|
||||
@@ -107,12 +105,11 @@ void led_off(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Get the state of the LED
|
||||
* Returns: true if on, false if off.
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
bool led_state(
|
||||
uint8_t index)
|
||||
* Description: Get the state of the LED
|
||||
* Returns: true if on, false if off.
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
bool led_state(uint8_t index)
|
||||
{
|
||||
switch (index) {
|
||||
case 0:
|
||||
@@ -120,13 +117,13 @@ bool led_state(
|
||||
case 1:
|
||||
return (BIT_CHECK(PIND, PIND6));
|
||||
case 2:
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
return (BIT_CHECK(PINB, PINC0));
|
||||
#else
|
||||
return (BIT_CHECK(PINC, PINC7));
|
||||
#endif
|
||||
case 3:
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
return (BIT_CHECK(PINB, PINC4));
|
||||
#else
|
||||
return (BIT_CHECK(PINC, PINC6));
|
||||
@@ -139,12 +136,11 @@ bool led_state(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Toggle the state of the setup LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_toggle(
|
||||
uint8_t index)
|
||||
* Description: Toggle the state of the setup LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_toggle(uint8_t index)
|
||||
{
|
||||
if (led_state(index)) {
|
||||
led_off(index);
|
||||
@@ -154,13 +150,11 @@ void led_toggle(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Delay before going off to give minimum brightness.
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_off_delay(
|
||||
uint8_t index,
|
||||
uint32_t delay_ms)
|
||||
* Description: Delay before going off to give minimum brightness.
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_off_delay(uint8_t index, uint32_t delay_ms)
|
||||
{
|
||||
if (index < MAX_LEDS) {
|
||||
mstimer_set(&Off_Delay_Timer[index], delay_ms);
|
||||
@@ -168,13 +162,11 @@ void led_off_delay(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Turn on, and delay before going off.
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_on_interval(
|
||||
uint8_t index,
|
||||
uint16_t interval_ms)
|
||||
* Description: Turn on, and delay before going off.
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_on_interval(uint8_t index, uint16_t interval_ms)
|
||||
{
|
||||
if (index < MAX_LEDS) {
|
||||
led_on(index);
|
||||
@@ -183,14 +175,13 @@ void led_on_interval(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Task for blinking LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_task(
|
||||
void)
|
||||
* Description: Task for blinking LED
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_task(void)
|
||||
{
|
||||
uint8_t i; /* loop counter */
|
||||
uint8_t i; /* loop counter */
|
||||
|
||||
for (i = 0; i < MAX_LEDS; i++) {
|
||||
if (mstimer_expired(&Off_Delay_Timer[i])) {
|
||||
@@ -201,19 +192,18 @@ void led_task(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Initialize the LED hardware
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_init(
|
||||
void)
|
||||
* Description: Initialize the LED hardware
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void led_init(void)
|
||||
{
|
||||
uint8_t i; /* loop counter */
|
||||
uint8_t i; /* loop counter */
|
||||
|
||||
/* configure the port pins as outputs */
|
||||
BIT_SET(DDRD, DDD7);
|
||||
BIT_SET(DDRD, DDD6);
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_SET(DDRB, DDB0);
|
||||
BIT_SET(DDRB, DDB4);
|
||||
#else
|
||||
|
||||
+24
-25
@@ -1,27 +1,27 @@
|
||||
/************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*************************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -47,8 +47,7 @@ char *BACnet_Version = BACNET_VERSION_TEXT;
|
||||
/* For porting to IAR, see:
|
||||
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
|
||||
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
{
|
||||
init();
|
||||
/* Configure the watchdog timer - Disabled for debugging */
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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"
|
||||
@@ -32,8 +32,7 @@
|
||||
/* Timer2 Prescaling: 1, 8, 32, 64, 128, 256, or 1024 */
|
||||
#define TIMER_MICROSECONDS 1000UL
|
||||
#define TIMER_TICKS(p) \
|
||||
(((((F_CPU)/(p))/1000UL) \
|
||||
*(TIMER_MICROSECONDS))/1000UL)
|
||||
(((((F_CPU) / (p)) / 1000UL) * (TIMER_MICROSECONDS)) / 1000UL)
|
||||
#define TIMER_TICKS_MAX 255UL
|
||||
/* adjust the prescaler for the processor clock */
|
||||
#if (TIMER_TICKS(1) <= TIMER_TICKS_MAX)
|
||||
@@ -55,18 +54,17 @@
|
||||
#endif
|
||||
#define TIMER2_TICKS TIMER_TICKS(TIMER2_PRESCALER)
|
||||
/* Timer counts up from count to TIMER_TICKS_MAX and then signals overflow */
|
||||
#define TIMER2_COUNT (TIMER_TICKS_MAX-TIMER2_TICKS)
|
||||
#define TIMER2_COUNT (TIMER_TICKS_MAX - TIMER2_TICKS)
|
||||
|
||||
/* counter for the the timer which wraps every 49.7 days */
|
||||
static volatile uint32_t Millisecond_Counter;
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Timer Interrupt Handler
|
||||
* Returns: nothing
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void timer_interrupt_handler(
|
||||
void)
|
||||
* Description: Timer Interrupt Handler
|
||||
* Returns: nothing
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void timer_interrupt_handler(void)
|
||||
{
|
||||
/* Set the counter for the next interrupt */
|
||||
TCNT2 = TIMER2_COUNT;
|
||||
@@ -74,24 +72,23 @@ static inline void timer_interrupt_handler(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Timer Interrupt Service Routine - Timer Overflowed!
|
||||
* Returns: none
|
||||
* Notes: Global interupts must be enabled
|
||||
*************************************************************************/
|
||||
* Description: Timer Interrupt Service Routine - Timer Overflowed!
|
||||
* Returns: none
|
||||
* Notes: Global interupts must be enabled
|
||||
*************************************************************************/
|
||||
ISR(TIMER2_OVF_vect)
|
||||
{
|
||||
timer_interrupt_handler();
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: returns the current millisecond count
|
||||
* Returns: none
|
||||
* Notes: This method only disables the timer overflow interrupt.
|
||||
*************************************************************************/
|
||||
unsigned long mstimer_now(
|
||||
void)
|
||||
* Description: returns the current millisecond count
|
||||
* Returns: none
|
||||
* Notes: This method only disables the timer overflow interrupt.
|
||||
*************************************************************************/
|
||||
unsigned long mstimer_now(void)
|
||||
{
|
||||
unsigned long timer_value; /* return value */
|
||||
unsigned long timer_value; /* return value */
|
||||
|
||||
/* Disable the overflow interrupt.
|
||||
Prevents value corruption that would happen if interrupted */
|
||||
@@ -104,12 +101,11 @@ unsigned long mstimer_now(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Initialization for Timer
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void mstimer_init(
|
||||
void)
|
||||
* Description: Initialization for Timer
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
void mstimer_init(void)
|
||||
{
|
||||
/* Normal Operation */
|
||||
TCCR2A = 0;
|
||||
@@ -125,19 +121,19 @@ void mstimer_init(
|
||||
1 1 0 CLKt2s/256
|
||||
1 1 1 CLKt2s/1024
|
||||
*/
|
||||
#if (TIMER2_PRESCALER==1)
|
||||
#if (TIMER2_PRESCALER == 1)
|
||||
TCCR2B = _BV(CS20);
|
||||
#elif (TIMER2_PRESCALER==8)
|
||||
#elif (TIMER2_PRESCALER == 8)
|
||||
TCCR2B = _BV(CS21);
|
||||
#elif (TIMER2_PRESCALER==32)
|
||||
#elif (TIMER2_PRESCALER == 32)
|
||||
TCCR2B = _BV(CS21) | _BV(CS20);
|
||||
#elif (TIMER2_PRESCALER==64)
|
||||
#elif (TIMER2_PRESCALER == 64)
|
||||
TCCR2B = _BV(CS22);
|
||||
#elif (TIMER2_PRESCALER==128)
|
||||
#elif (TIMER2_PRESCALER == 128)
|
||||
TCCR2B = _BV(CS22) | _BV(CS20);
|
||||
#elif (TIMER2_PRESCALER==256)
|
||||
#elif (TIMER2_PRESCALER == 256)
|
||||
TCCR2B = _BV(CS22) | _BV(CS21);
|
||||
#elif (TIMER2_PRESCALER==1024)
|
||||
#elif (TIMER2_PRESCALER == 1024)
|
||||
TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20);
|
||||
#else
|
||||
#error Timer2 Prescale: Invalid Value
|
||||
|
||||
+106
-121
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
@@ -44,7 +44,7 @@ static uint32_t Baud_Rate = 9600;
|
||||
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
|
||||
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
|
||||
/* 40 bits is 4 octets including a start and stop bit with each octet */
|
||||
#define Tturnaround (40UL)
|
||||
#define Tturnaround (40UL)
|
||||
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/Baud_Rate; */
|
||||
|
||||
/* buffer for storing received bytes - size must be power of two */
|
||||
@@ -54,46 +54,42 @@ static FIFO_BUFFER Receive_Buffer;
|
||||
static struct mstimer Silence_Timer;
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Determines the amount of silence time elapsed
|
||||
* RETURN: true if the amount of silence time has elapsed
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_silence_time_elapsed(
|
||||
uint16_t milliseconds)
|
||||
* DESCRIPTION: Determines the amount of silence time elapsed
|
||||
* RETURN: true if the amount of silence time has elapsed
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_silence_time_elapsed(uint16_t milliseconds)
|
||||
{
|
||||
return (mstimer_elapsed(&Silence_Timer) > milliseconds);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Resets the silence timer
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_silence_time_reset(
|
||||
void)
|
||||
* DESCRIPTION: Resets the silence timer
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_silence_time_reset(void)
|
||||
{
|
||||
mstimer_set(&Silence_Timer, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Configures the RTS output
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_rts_init(
|
||||
void)
|
||||
* DESCRIPTION: Configures the RTS output
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_rts_init(void)
|
||||
{
|
||||
/* configure the port pin as an output */
|
||||
BIT_SET(DDRD, DDD4);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: enable the transmit-enable line on the RS-485 transceiver
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_rts_enable(
|
||||
bool enable)
|
||||
* DESCRIPTION: enable the transmit-enable line on the RS-485 transceiver
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_rts_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
BIT_SET(PORTD, PD4);
|
||||
@@ -103,23 +99,21 @@ void rs485_rts_enable(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: enable the UART receiver and interrupt
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_receiver_enable(
|
||||
void)
|
||||
* DESCRIPTION: enable the UART receiver and interrupt
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_receiver_enable(void)
|
||||
{
|
||||
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: delay for 40 bit times
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_turnaround_delay(
|
||||
void)
|
||||
* DESCRIPTION: delay for 40 bit times
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_turnaround_delay(void)
|
||||
{
|
||||
uint8_t nbytes = 4;
|
||||
|
||||
@@ -144,10 +138,10 @@ void rs485_turnaround_delay(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Interrupt service routine for UART Receiver
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
* DESCRIPTION: Interrupt service routine for UART Receiver
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
ISR(USART0_RX_vect)
|
||||
{
|
||||
uint8_t data_byte;
|
||||
@@ -158,19 +152,18 @@ ISR(USART0_RX_vect)
|
||||
#ifdef MSTP_MONITOR
|
||||
UDR1 = data_byte;
|
||||
#endif
|
||||
(void) FIFO_Put(&Receive_Buffer, data_byte);
|
||||
(void)FIFO_Put(&Receive_Buffer, data_byte);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Checks for data on the receive UART, and handles errors
|
||||
* RETURN: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_byte_available(
|
||||
uint8_t * data_register)
|
||||
* DESCRIPTION: Checks for data on the receive UART, and handles errors
|
||||
* RETURN: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_byte_available(uint8_t *data_register)
|
||||
{
|
||||
bool data_available = false; /* return value */
|
||||
bool data_available = false; /* return value */
|
||||
|
||||
if (!FIFO_Empty(&Receive_Buffer)) {
|
||||
led_on_interval(LED_4, 1);
|
||||
@@ -184,25 +177,23 @@ bool rs485_byte_available(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: returns an error indication if errors are enabled
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_receive_error(
|
||||
void)
|
||||
* DESCRIPTION: returns an error indication if errors are enabled
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_receive_error(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Transmits a frame using the UART
|
||||
* RETURN: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_bytes_send(
|
||||
uint8_t * buffer, /* data to send */
|
||||
* DESCRIPTION: Transmits a frame using the UART
|
||||
* RETURN: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_bytes_send(uint8_t *buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
led_on(LED_5);
|
||||
while (!BIT_CHECK(UCSR0A, UDRE0)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
@@ -233,23 +224,21 @@ void rs485_bytes_send(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: baud rate in bps
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t rs485_baud_rate(
|
||||
void)
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: baud rate in bps
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t rs485_baud_rate(void)
|
||||
{
|
||||
return Baud_Rate;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: configure the UART baud rate
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_baud_rate_configure(
|
||||
void)
|
||||
* DESCRIPTION: configure the UART baud rate
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_baud_rate_configure(void)
|
||||
{
|
||||
/* 2x speed mode */
|
||||
BIT_SET(UCSR0A, U2X0);
|
||||
@@ -258,12 +247,11 @@ static void rs485_baud_rate_configure(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: set the UART baud rate to a standard value
|
||||
* RETURN: true if the baud rate is valid
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_baud_rate_set(
|
||||
uint32_t baud)
|
||||
* DESCRIPTION: set the UART baud rate to a standard value
|
||||
* RETURN: true if the baud rate is valid
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool rs485_baud_rate_set(uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
uint8_t baud_k = 0;
|
||||
@@ -290,12 +278,11 @@ bool rs485_baud_rate_set(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: initialize the hardware UART
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_usart_init(
|
||||
void)
|
||||
* DESCRIPTION: initialize the hardware UART
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_usart_init(void)
|
||||
{
|
||||
/* enable the internal pullup on RXD0 */
|
||||
BIT_CLEAR(DDRD, DDD0);
|
||||
@@ -314,12 +301,11 @@ static void rs485_usart_init(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: read any non-volatile data
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_init_nvdata(
|
||||
void)
|
||||
* DESCRIPTION: read any non-volatile data
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
static void rs485_init_nvdata(void)
|
||||
{
|
||||
uint8_t baud_k = 9; /* from EEPROM value */
|
||||
|
||||
@@ -354,15 +340,14 @@ static void rs485_init_nvdata(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: initialize the module
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_init(
|
||||
void)
|
||||
* DESCRIPTION: initialize the module
|
||||
* RETURN: nothing
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void rs485_init(void)
|
||||
{
|
||||
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
|
||||
(unsigned) sizeof(Receive_Buffer_Data));
|
||||
(unsigned)sizeof(Receive_Buffer_Data));
|
||||
rs485_silence_time_reset();
|
||||
rs485_rts_init();
|
||||
rs485_usart_init();
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Used algorithm and code from Joerg Wunsch and Ruwan Jayanetti.
|
||||
* http://www.nongnu.org/avr-libc/user-manual/group__twi__demo.html
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Used algorithm and code from Joerg Wunsch and Ruwan Jayanetti.
|
||||
* http://www.nongnu.org/avr-libc/user-manual/group__twi__demo.html
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
@@ -57,7 +57,8 @@
|
||||
#endif
|
||||
|
||||
/* The lower 3 bits of TWSR are reserved on the ATmega163 */
|
||||
#define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3))
|
||||
#define TW_STATUS_MASK \
|
||||
(_BV(TWS7) | _BV(TWS6) | _BV(TWS5) | _BV(TWS4) | _BV(TWS3))
|
||||
/* start condition transmitted */
|
||||
#define TW_START 0x08
|
||||
/* repeated start condition transmitted */
|
||||
@@ -93,21 +94,20 @@
|
||||
/* Number of iterations is the max amount to wait for write cycle
|
||||
to complete a full page write */
|
||||
/* .005s/.000025=200 */
|
||||
#define MAX_ITER (((SEEPROM_I2C_CLOCK/1000)/10)*SEEPROM_WRITE_CYCLE)
|
||||
#define MAX_ITER (((SEEPROM_I2C_CLOCK / 1000) / 10) * SEEPROM_WRITE_CYCLE)
|
||||
|
||||
/*************************************************************************
|
||||
* DESCRIPTION: Return bytes from SEEPROM memory at address
|
||||
* RETURN: number of bytes read, or -1 on error
|
||||
* NOTES: none
|
||||
**************************************************************************/
|
||||
int seeprom_bytes_read(
|
||||
uint16_t eeaddr, /* SEEPROM starting memory address */
|
||||
uint8_t * buf, /* data to store */
|
||||
* DESCRIPTION: Return bytes from SEEPROM memory at address
|
||||
* RETURN: number of bytes read, or -1 on error
|
||||
* NOTES: none
|
||||
**************************************************************************/
|
||||
int seeprom_bytes_read(uint16_t eeaddr, /* SEEPROM starting memory address */
|
||||
uint8_t *buf, /* data to store */
|
||||
int len)
|
||||
{ /* number of bytes of data to read */
|
||||
{ /* number of bytes of data to read */
|
||||
uint8_t sla, twcr, n = 0;
|
||||
int rv = 0;
|
||||
uint8_t twst; /* status - only valid while TWINT is set. */
|
||||
uint8_t twst; /* status - only valid while TWINT is set. */
|
||||
uint16_t timeout = 0xFFFF;
|
||||
|
||||
#if SEEPROM_WORD_ADDRESS_16BIT
|
||||
@@ -118,11 +118,11 @@ int seeprom_bytes_read(
|
||||
sla = SEEPROM_I2C_ADDRESS | (((eeaddr >> 8) & 0x07) << 1);
|
||||
#endif
|
||||
/* First cycle: master transmitter mode */
|
||||
restart:
|
||||
restart:
|
||||
if (n++ >= MAX_ITER) {
|
||||
return -1;
|
||||
}
|
||||
begin:
|
||||
begin:
|
||||
/* send start condition */
|
||||
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
@@ -159,7 +159,8 @@ int seeprom_bytes_read(
|
||||
/* clear interrupt to start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MT_SLA_ACK:
|
||||
@@ -184,7 +185,8 @@ int seeprom_bytes_read(
|
||||
/* clear interrupt to start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MT_DATA_ACK:
|
||||
@@ -203,7 +205,8 @@ int seeprom_bytes_read(
|
||||
/* clear interrupt to start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MT_DATA_ACK:
|
||||
@@ -229,7 +232,8 @@ int seeprom_bytes_read(
|
||||
/* send repeated start condition */
|
||||
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_START:
|
||||
@@ -247,7 +251,8 @@ int seeprom_bytes_read(
|
||||
/* clear interrupt to start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MR_SLA_ACK:
|
||||
@@ -272,7 +277,8 @@ int seeprom_bytes_read(
|
||||
/* clear int to start transmission */
|
||||
TWCR = twcr;
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MR_DATA_NACK:
|
||||
@@ -288,32 +294,32 @@ int seeprom_bytes_read(
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
quit:
|
||||
quit:
|
||||
/* Except in the case of lost arbitration, all bus transactions
|
||||
must properly be terminated by the master initiating a
|
||||
stop condition. */
|
||||
/* send stop condition */
|
||||
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
|
||||
return rv;
|
||||
error:
|
||||
error:
|
||||
rv = -1;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* DESCRIPTION: Write some data and wait until it is sent
|
||||
* RETURN: number of bytes written, or -1 on error
|
||||
* NOTES: only writes from offset to end of page.
|
||||
**************************************************************************/
|
||||
* DESCRIPTION: Write some data and wait until it is sent
|
||||
* RETURN: number of bytes written, or -1 on error
|
||||
* NOTES: only writes from offset to end of page.
|
||||
**************************************************************************/
|
||||
static int seeprom_bytes_write_page(
|
||||
uint16_t eeaddr, /* SEEPROM starting memory address */
|
||||
uint8_t * buf, /* data to send */
|
||||
uint16_t eeaddr, /* SEEPROM starting memory address */
|
||||
uint8_t *buf, /* data to send */
|
||||
int len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
uint8_t sla, n = 0;
|
||||
int rv = 0;
|
||||
uint16_t endaddr;
|
||||
uint8_t twst; /* status - only valid while TWINT is set. */
|
||||
uint8_t twst; /* status - only valid while TWINT is set. */
|
||||
uint16_t page_end_addr;
|
||||
uint16_t timeout = 0xFFFF;
|
||||
|
||||
@@ -330,11 +336,11 @@ static int seeprom_bytes_write_page(
|
||||
/* patch high bits of EEPROM address into SLA */
|
||||
sla = SEEPROM_I2C_ADDRESS | (((eeaddr >> 8) & 0x07) << 1);
|
||||
#endif
|
||||
restart:
|
||||
restart:
|
||||
if (n++ >= MAX_ITER) {
|
||||
return -1;
|
||||
}
|
||||
begin:
|
||||
begin:
|
||||
/* Writing to the EEPROM device is simpler than reading,
|
||||
since only a master transmitter mode transfer is needed.
|
||||
Note that the first packet after the SLA+W selection is
|
||||
@@ -373,7 +379,8 @@ static int seeprom_bytes_write_page(
|
||||
/* clear interrupt to start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MT_SLA_ACK:
|
||||
@@ -394,7 +401,8 @@ static int seeprom_bytes_write_page(
|
||||
/* clear interrupt to start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MT_DATA_ACK:
|
||||
@@ -413,8 +421,7 @@ static int seeprom_bytes_write_page(
|
||||
/* clear interrupt to start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0) {
|
||||
};
|
||||
while ((TWCR & _BV(TWINT)) == 0) { };
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MT_DATA_ACK:
|
||||
@@ -432,7 +439,8 @@ static int seeprom_bytes_write_page(
|
||||
/* start transmission */
|
||||
TWCR = _BV(TWINT) | _BV(TWEN);
|
||||
/* wait for transmission */
|
||||
while ((TWCR & _BV(TWINT)) == 0);
|
||||
while ((TWCR & _BV(TWINT)) == 0)
|
||||
;
|
||||
twst = TWSR & TW_STATUS_MASK;
|
||||
switch (twst) {
|
||||
case TW_MT_DATA_NACK:
|
||||
@@ -446,36 +454,35 @@ static int seeprom_bytes_write_page(
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
quit:
|
||||
quit:
|
||||
/* send stop condition */
|
||||
TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
|
||||
|
||||
return rv;
|
||||
|
||||
error:
|
||||
error:
|
||||
rv = -1;
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* DESCRIPTION: Write some data and wait until it is sent
|
||||
* RETURN: number of bytes written, or -1 on error
|
||||
* NOTES:
|
||||
* When the word address, internally generated,
|
||||
* reaches the page boundary, the following
|
||||
* byte is placed at the beginning of the same
|
||||
* page. If more than 64 data words are
|
||||
* transmitted to the EEPROM, the data word
|
||||
* address will "roll over" and previous data will be
|
||||
* overwritten. The address "roll over" during write
|
||||
* is from the last byte of the current page to the
|
||||
* first byte of the same page.
|
||||
**************************************************************************/
|
||||
int seeprom_bytes_write(
|
||||
uint16_t off, /* SEEPROM starting memory address */
|
||||
uint8_t * buf, /* data to send */
|
||||
* DESCRIPTION: Write some data and wait until it is sent
|
||||
* RETURN: number of bytes written, or -1 on error
|
||||
* NOTES:
|
||||
* When the word address, internally generated,
|
||||
* reaches the page boundary, the following
|
||||
* byte is placed at the beginning of the same
|
||||
* page. If more than 64 data words are
|
||||
* transmitted to the EEPROM, the data word
|
||||
* address will "roll over" and previous data will be
|
||||
* overwritten. The address "roll over" during write
|
||||
* is from the last byte of the current page to the
|
||||
* first byte of the same page.
|
||||
**************************************************************************/
|
||||
int seeprom_bytes_write(uint16_t off, /* SEEPROM starting memory address */
|
||||
uint8_t *buf, /* data to send */
|
||||
int len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int status = 0;
|
||||
int rv = 0;
|
||||
|
||||
@@ -497,12 +504,11 @@ int seeprom_bytes_write(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Initialize the SEEPROM TWI connection
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
void seeprom_init(
|
||||
void)
|
||||
* Description: Initialize the SEEPROM TWI connection
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
void seeprom_init(void)
|
||||
{
|
||||
/* bit rate prescaler */
|
||||
TWSR = 0;
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
@@ -35,8 +35,7 @@ static uint32_t Baud_Rate = 9600;
|
||||
static uint8_t Receive_Buffer_Data[128];
|
||||
static FIFO_BUFFER Receive_Buffer;
|
||||
|
||||
static void serial_receiver_enable(
|
||||
void)
|
||||
static void serial_receiver_enable(void)
|
||||
{
|
||||
UCSR1B = _BV(TXEN1) | _BV(RXEN1) | _BV(RXCIE1);
|
||||
}
|
||||
@@ -48,14 +47,13 @@ ISR(USART1_RX_vect)
|
||||
if (BIT_CHECK(UCSR1A, RXC1)) {
|
||||
/* data is available */
|
||||
data_byte = UDR1;
|
||||
(void) FIFO_Put(&Receive_Buffer, data_byte);
|
||||
(void)FIFO_Put(&Receive_Buffer, data_byte);
|
||||
}
|
||||
}
|
||||
|
||||
bool serial_byte_get(
|
||||
uint8_t * data_register)
|
||||
bool serial_byte_get(uint8_t *data_register)
|
||||
{
|
||||
bool data_available = false; /* return value */
|
||||
bool data_available = false; /* return value */
|
||||
|
||||
if (!FIFO_Empty(&Receive_Buffer)) {
|
||||
*data_register = FIFO_Get(&Receive_Buffer);
|
||||
@@ -65,10 +63,9 @@ bool serial_byte_get(
|
||||
return data_available;
|
||||
}
|
||||
|
||||
bool serial_byte_peek(
|
||||
uint8_t * data_register)
|
||||
bool serial_byte_peek(uint8_t *data_register)
|
||||
{
|
||||
bool data_available = false; /* return value */
|
||||
bool data_available = false; /* return value */
|
||||
|
||||
if (!FIFO_Empty(&Receive_Buffer)) {
|
||||
*data_register = FIFO_Peek(&Receive_Buffer);
|
||||
@@ -78,10 +75,9 @@ bool serial_byte_peek(
|
||||
return data_available;
|
||||
}
|
||||
|
||||
void serial_bytes_send(
|
||||
uint8_t * buffer, /* data to send */
|
||||
void serial_bytes_send(uint8_t *buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
while (!BIT_CHECK(UCSR1A, UDRE1)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
}
|
||||
@@ -105,8 +101,7 @@ void serial_bytes_send(
|
||||
return;
|
||||
}
|
||||
|
||||
void serial_byte_send(
|
||||
uint8_t ch)
|
||||
void serial_byte_send(uint8_t ch)
|
||||
{
|
||||
while (!BIT_CHECK(UCSR1A, UDRE1)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
@@ -117,8 +112,7 @@ void serial_byte_send(
|
||||
return;
|
||||
}
|
||||
|
||||
void serial_byte_transmit_complete(
|
||||
void)
|
||||
void serial_byte_transmit_complete(void)
|
||||
{
|
||||
/* was the frame sent? */
|
||||
while (!BIT_CHECK(UCSR1A, TXC1)) {
|
||||
@@ -129,14 +123,12 @@ void serial_byte_transmit_complete(
|
||||
BIT_SET(UCSR1A, TXC1);
|
||||
}
|
||||
|
||||
uint32_t serial_baud_rate(
|
||||
void)
|
||||
uint32_t serial_baud_rate(void)
|
||||
{
|
||||
return Baud_Rate;
|
||||
}
|
||||
|
||||
bool serial_baud_rate_set(
|
||||
uint32_t baud)
|
||||
bool serial_baud_rate_set(uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
@@ -162,8 +154,7 @@ bool serial_baud_rate_set(
|
||||
return valid;
|
||||
}
|
||||
|
||||
static void serial_usart_init(
|
||||
void)
|
||||
static void serial_usart_init(void)
|
||||
{
|
||||
/* enable the internal pullup on RXD1 */
|
||||
BIT_CLEAR(DDRD, DDD2);
|
||||
@@ -181,11 +172,10 @@ static void serial_usart_init(
|
||||
power_usart1_enable();
|
||||
}
|
||||
|
||||
void serial_init(
|
||||
void)
|
||||
void serial_init(void)
|
||||
{
|
||||
FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0],
|
||||
(unsigned) sizeof(Receive_Buffer_Data));
|
||||
(unsigned)sizeof(Receive_Buffer_Data));
|
||||
serial_usart_init();
|
||||
serial_baud_rate_set(Baud_Rate);
|
||||
serial_receiver_enable();
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 "hardware.h"
|
||||
/* me */
|
||||
#include "stack.h"
|
||||
@@ -32,11 +32,9 @@ extern uint8_t _end;
|
||||
extern uint8_t __stack;
|
||||
|
||||
#define STACK_CANARY (0xC5)
|
||||
void stack_init(
|
||||
void) __attribute__ ((naked)) __attribute__ ((section(".init1")));
|
||||
void stack_init(void) __attribute__((naked)) __attribute__((section(".init1")));
|
||||
|
||||
void stack_init(
|
||||
void)
|
||||
void stack_init(void)
|
||||
{
|
||||
#if 0
|
||||
uint8_t *p = &_end;
|
||||
@@ -46,28 +44,32 @@ void stack_init(
|
||||
p++;
|
||||
}
|
||||
#else
|
||||
__asm volatile (
|
||||
" ldi r30,lo8(_end)\n" " ldi r31,hi8(_end)\n" " ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
|
||||
" ldi r25,hi8(__stack)\n" " rjmp .cmp\n" ".loop:\n"
|
||||
" st Z+,r24\n" ".cmp:\n" " cpi r30,lo8(__stack)\n"
|
||||
" cpc r31,r25\n" " brlo .loop\n" " breq .loop"::);
|
||||
__asm volatile(" ldi r30,lo8(_end)\n"
|
||||
" ldi r31,hi8(_end)\n"
|
||||
" ldi r24,lo8(0xc5)\n" /* STACK_CANARY = 0xc5 */
|
||||
" ldi r25,hi8(__stack)\n"
|
||||
" rjmp .cmp\n"
|
||||
".loop:\n"
|
||||
" st Z+,r24\n"
|
||||
".cmp:\n"
|
||||
" cpi r30,lo8(__stack)\n"
|
||||
" cpc r31,r25\n"
|
||||
" brlo .loop\n"
|
||||
" breq .loop" ::);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned stack_size(
|
||||
void)
|
||||
unsigned stack_size(void)
|
||||
{
|
||||
return (&__stack) - (&_end);
|
||||
}
|
||||
|
||||
uint8_t stack_byte(
|
||||
unsigned offset)
|
||||
uint8_t stack_byte(unsigned offset)
|
||||
{
|
||||
return *(&_end + offset);
|
||||
}
|
||||
|
||||
unsigned stack_unused(
|
||||
void)
|
||||
unsigned stack_unused(void)
|
||||
{
|
||||
uint8_t *p = &_end;
|
||||
unsigned count = 0;
|
||||
@@ -82,26 +84,21 @@ unsigned stack_unused(
|
||||
return count;
|
||||
}
|
||||
#else
|
||||
void stack_init(
|
||||
void)
|
||||
void stack_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
unsigned stack_size(
|
||||
void)
|
||||
unsigned stack_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t stack_byte(
|
||||
unsigned offset)
|
||||
uint8_t stack_byte(unsigned offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned stack_unused(
|
||||
void)
|
||||
unsigned stack_unused(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
+65
-77
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2010 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2010 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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
@@ -42,26 +42,24 @@
|
||||
#endif
|
||||
|
||||
#define BINARY_STRING_MAX 3
|
||||
const char * const binary_string[BINARY_STRING_MAX] = {
|
||||
"INACTIVE", "ACTIVE", "RELINQUISH"
|
||||
};
|
||||
const char *const binary_string[BINARY_STRING_MAX] = { "INACTIVE", "ACTIVE",
|
||||
"RELINQUISH" };
|
||||
|
||||
/* timer for test task */
|
||||
static struct mstimer Test_Timer;
|
||||
/* MAC Address of MS/TP */
|
||||
static uint8_t MSTP_MAC_Address;
|
||||
|
||||
void test_init(
|
||||
void)
|
||||
void test_init(void)
|
||||
{
|
||||
#ifdef MSTP_MONITOR
|
||||
serial_baud_rate_set(115200);
|
||||
#else
|
||||
serial_baud_rate_set(9600);
|
||||
#endif
|
||||
mstimer_set(&Test_Timer, 1*1000);
|
||||
mstimer_set(&Test_Timer, 1 * 1000);
|
||||
/* configure a port pin as output */
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_SET(DDRD, DDB5);
|
||||
#else
|
||||
BIT_SET(DDRB, DDB0);
|
||||
@@ -69,10 +67,10 @@ void test_init(
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief send a string of text to the RS-232 port
|
||||
* @param text - C string of text (null terminated)
|
||||
*/
|
||||
static void test_write_string(const char * text)
|
||||
* @brief send a string of text to the RS-232 port
|
||||
* @param text - C string of text (null terminated)
|
||||
*/
|
||||
static void test_write_string(const char *text)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
@@ -82,16 +80,14 @@ static void test_write_string(const char * text)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Turn on a pin
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void test_pin_on(
|
||||
void)
|
||||
* Description: Turn on a pin
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void test_pin_on(void)
|
||||
{
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_SET(PORTD, PD5);
|
||||
#else
|
||||
BIT_SET(PORTB, PB0);
|
||||
@@ -99,14 +95,13 @@ static inline void test_pin_on(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Turn off a pin
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void test_pin_off(
|
||||
void)
|
||||
* Description: Turn off a pin
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void test_pin_off(void)
|
||||
{
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
BIT_CLEAR(PORTD, PD5);
|
||||
#else
|
||||
BIT_CLEAR(PORTB, PB0);
|
||||
@@ -114,14 +109,13 @@ static inline void test_pin_off(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Get the state of the test pin
|
||||
* Returns: true if on, false if off.
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline bool test_pin_state(
|
||||
void)
|
||||
* Description: Get the state of the test pin
|
||||
* Returns: true if on, false if off.
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline bool test_pin_state(void)
|
||||
{
|
||||
#if (BDK_VERSION==4)
|
||||
#if (BDK_VERSION == 4)
|
||||
return (BIT_CHECK(PIND, PD5));
|
||||
#else
|
||||
return (BIT_CHECK(PINB, PB0));
|
||||
@@ -129,12 +123,11 @@ static inline bool test_pin_state(
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Toggle the test pin
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void test_pin_toggle(
|
||||
void)
|
||||
* Description: Toggle the test pin
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
*************************************************************************/
|
||||
static inline void test_pin_toggle(void)
|
||||
{
|
||||
if (test_pin_state()) {
|
||||
test_pin_off();
|
||||
@@ -144,8 +137,7 @@ static inline void test_pin_toggle(
|
||||
}
|
||||
|
||||
#ifdef MSTP_MONITOR
|
||||
void test_task(
|
||||
void)
|
||||
void test_task(void)
|
||||
{
|
||||
if (mstimer_expired(&Test_Timer)) {
|
||||
mstimer_reset(&Test_Timer);
|
||||
@@ -155,8 +147,7 @@ void test_task(
|
||||
#else
|
||||
char Send_Buffer[32];
|
||||
|
||||
void test_task(
|
||||
void)
|
||||
void test_task(void)
|
||||
{
|
||||
uint8_t data_register = 0;
|
||||
uint16_t id = 0;
|
||||
@@ -172,7 +163,7 @@ void test_task(
|
||||
Send_Buffer[12] = (MSTP_MAC_Address & BIT(4)) ? '1' : '0';
|
||||
Send_Buffer[13] = (MSTP_MAC_Address & BIT(5)) ? '1' : '0';
|
||||
Send_Buffer[14] = (MSTP_MAC_Address & BIT(6)) ? '1' : '0';
|
||||
serial_bytes_send((uint8_t *) Send_Buffer, 17);
|
||||
serial_bytes_send((uint8_t *)Send_Buffer, 17);
|
||||
}
|
||||
if (serial_byte_get(&data_register)) {
|
||||
/* echo the character */
|
||||
@@ -206,22 +197,19 @@ void test_task(
|
||||
rs485_baud_rate_set(9600);
|
||||
break;
|
||||
case 'e':
|
||||
seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *) & id, 2);
|
||||
seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *)&id, 2);
|
||||
sprintf(Send_Buffer, "\r\n%04X", id);
|
||||
serial_bytes_send((uint8_t *) Send_Buffer,
|
||||
strlen(Send_Buffer));
|
||||
serial_bytes_send((uint8_t *)Send_Buffer, strlen(Send_Buffer));
|
||||
break;
|
||||
case 'b':
|
||||
sprintf(Send_Buffer, "\r\n%lubps",
|
||||
(unsigned long) rs485_baud_rate());
|
||||
serial_bytes_send((uint8_t *) Send_Buffer,
|
||||
strlen(Send_Buffer));
|
||||
(unsigned long)rs485_baud_rate());
|
||||
serial_bytes_send((uint8_t *)Send_Buffer, strlen(Send_Buffer));
|
||||
break;
|
||||
case 'm':
|
||||
sprintf(Send_Buffer, "\r\nMax:%u",
|
||||
(unsigned) dlmstp_max_master());
|
||||
serial_bytes_send((uint8_t *) Send_Buffer,
|
||||
strlen(Send_Buffer));
|
||||
sprintf(
|
||||
Send_Buffer, "\r\nMax:%u", (unsigned)dlmstp_max_master());
|
||||
serial_bytes_send((uint8_t *)Send_Buffer, strlen(Send_Buffer));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 "hardware.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
#if !defined(__GNUC__)
|
||||
static inline void wdt_enable(
|
||||
int value)
|
||||
static inline void wdt_enable(int value)
|
||||
{
|
||||
__disable_interrupt();
|
||||
__watchdog_reset();
|
||||
@@ -38,8 +37,7 @@ static inline void wdt_enable(
|
||||
__enable_interrupt(); */
|
||||
}
|
||||
|
||||
static inline void wdt_disable(
|
||||
void)
|
||||
static inline void wdt_disable(void)
|
||||
{
|
||||
__disable_interrupt();
|
||||
__watchdog_reset();
|
||||
@@ -53,31 +51,28 @@ static inline void wdt_disable(
|
||||
__enable_interrupt();
|
||||
}
|
||||
|
||||
static inline void wdt_reset(
|
||||
void)
|
||||
static inline void wdt_reset(void)
|
||||
{
|
||||
__watchdog_reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Reset the watchdog timer
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
void watchdog_reset(
|
||||
void)
|
||||
* Description: Reset the watchdog timer
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
void watchdog_reset(void)
|
||||
{
|
||||
wdt_reset();
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* Description: Initialize the watchdog timer
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
void watchdog_init(
|
||||
unsigned milliseconds)
|
||||
* Description: Initialize the watchdog timer
|
||||
* Returns: none
|
||||
* Notes: none
|
||||
**************************************************************************/
|
||||
void watchdog_init(unsigned milliseconds)
|
||||
{
|
||||
unsigned value = WDTO_15MS;
|
||||
if (milliseconds) {
|
||||
|
||||
+31
-40
@@ -32,8 +32,8 @@
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <ifaddrs.h>
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacint.h"
|
||||
@@ -68,8 +68,10 @@ static bool BIP_Debug = false;
|
||||
* @param str - debug info string
|
||||
* @param addr - IPv4 address
|
||||
*/
|
||||
static void debug_print_ipv4(const char *str, const struct in_addr *addr,
|
||||
const unsigned int port, const unsigned int count)
|
||||
static void debug_print_ipv4(const char *str,
|
||||
const struct in_addr *addr,
|
||||
const unsigned int port,
|
||||
const unsigned int count)
|
||||
{
|
||||
if (BIP_Debug) {
|
||||
fprintf(stderr, "BIP: %s %s:%hu (%u bytes)\n", str, inet_ntoa(*addr),
|
||||
@@ -233,7 +235,7 @@ uint8_t bip_get_subnet_prefix(void)
|
||||
if (test_broadcast == broadcast) {
|
||||
break;
|
||||
}
|
||||
mask = mask<<1;
|
||||
mask = mask << 1;
|
||||
}
|
||||
|
||||
return prefix;
|
||||
@@ -267,8 +269,8 @@ int bip_send_mpdu(BACNET_IP_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len)
|
||||
memcpy(&bip_dest.sin_addr.s_addr, &dest->address[0], 4);
|
||||
bip_dest.sin_port = htons(dest->port);
|
||||
/* Send the packet */
|
||||
debug_print_ipv4("Sending MPDU->", &bip_dest.sin_addr, bip_dest.sin_port,
|
||||
mtu_len);
|
||||
debug_print_ipv4(
|
||||
"Sending MPDU->", &bip_dest.sin_addr, bip_dest.sin_port, mtu_len);
|
||||
return sendto(BIP_Socket, (char *)mtu, mtu_len, 0,
|
||||
(struct sockaddr *)&bip_dest, sizeof(struct sockaddr));
|
||||
}
|
||||
@@ -341,14 +343,14 @@ uint16_t bip_receive(
|
||||
*/
|
||||
memcpy(&addr.address[0], &sin.sin_addr.s_addr, 4);
|
||||
addr.port = ntohs(sin.sin_port);
|
||||
debug_print_ipv4("Received MPDU->", &sin.sin_addr, sin.sin_port,
|
||||
received_bytes);
|
||||
debug_print_ipv4(
|
||||
"Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes);
|
||||
/* pass the packet into the BBMD handler */
|
||||
offset = bvlc_handler(&addr, src, npdu, received_bytes);
|
||||
if (offset > 0) {
|
||||
npdu_len = received_bytes - offset;
|
||||
debug_print_ipv4("Received NPDU->", &sin.sin_addr, sin.sin_port,
|
||||
npdu_len);
|
||||
debug_print_ipv4(
|
||||
"Received NPDU->", &sin.sin_addr, sin.sin_port, npdu_len);
|
||||
if (npdu_len <= max_npdu) {
|
||||
/* shift the buffer to return a valid NPDU */
|
||||
for (i = 0; i < npdu_len; i++) {
|
||||
@@ -414,14 +416,13 @@ bool bip_get_addr_by_name(const char *host_name, BACNET_IP_ADDRESS *addr)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void *get_addr_ptr(
|
||||
struct sockaddr *sockaddr_ptr)
|
||||
static void *get_addr_ptr(struct sockaddr *sockaddr_ptr)
|
||||
{
|
||||
void *addr_ptr;
|
||||
if (sockaddr_ptr->sa_family == AF_INET) {
|
||||
addr_ptr = &((struct sockaddr_in *) sockaddr_ptr)->sin_addr;
|
||||
addr_ptr = &((struct sockaddr_in *)sockaddr_ptr)->sin_addr;
|
||||
} else if (sockaddr_ptr->sa_family == AF_INET6) {
|
||||
addr_ptr = &((struct sockaddr_in6 *) sockaddr_ptr)->sin6_addr;
|
||||
addr_ptr = &((struct sockaddr_in6 *)sockaddr_ptr)->sin6_addr;
|
||||
}
|
||||
return addr_ptr;
|
||||
}
|
||||
@@ -434,20 +435,16 @@ static void *get_addr_ptr(
|
||||
* @param addr [out] The netmask addr, broadcast addr, ip addr.
|
||||
* @param request [in] addr broadaddr netmask
|
||||
*/
|
||||
static int get_local_address(
|
||||
char *ifname,
|
||||
struct in_addr *addr,
|
||||
char *request)
|
||||
static int get_local_address(char *ifname, struct in_addr *addr, char *request)
|
||||
{
|
||||
|
||||
char rv; /* return value */
|
||||
char rv; /* return value */
|
||||
|
||||
struct ifaddrs *ifaddrs_ptr;
|
||||
int status;
|
||||
status = getifaddrs(&ifaddrs_ptr);
|
||||
if (status == -1) {
|
||||
fprintf(stderr, "Error in 'getifaddrs': %d (%s)\n", errno,
|
||||
strerror(errno));
|
||||
fprintf(
|
||||
stderr, "Error in 'getifaddrs': %d (%s)\n", errno, strerror(errno));
|
||||
}
|
||||
while (ifaddrs_ptr) {
|
||||
if ((ifaddrs_ptr->ifa_addr->sa_family == AF_INET) &&
|
||||
@@ -477,11 +474,10 @@ static int get_local_address(
|
||||
* @param netmask [out] The netmask, in host order.
|
||||
* @return 0 on success, else the error from the getifaddrs() call.
|
||||
*/
|
||||
int bip_get_local_netmask(
|
||||
struct in_addr *netmask)
|
||||
int bip_get_local_netmask(struct in_addr *netmask)
|
||||
{
|
||||
int rv;
|
||||
char *ifname = getenv("BACNET_IFACE"); /* will probably be null */
|
||||
char *ifname = getenv("BACNET_IFACE"); /* will probably be null */
|
||||
if (ifname == NULL)
|
||||
ifname = "en0";
|
||||
printf("ifname %s", ifname);
|
||||
@@ -497,8 +493,7 @@ int bip_get_local_netmask(
|
||||
* @param ifname [in] The named interface to use for the network layer.
|
||||
* Eg, for MAC OS X, ifname is en0, en1, and others.
|
||||
*/
|
||||
void bip_set_interface(
|
||||
char *ifname)
|
||||
void bip_set_interface(char *ifname)
|
||||
{
|
||||
struct in_addr local_address;
|
||||
struct in_addr broadcast_address;
|
||||
@@ -550,10 +545,9 @@ void bip_set_interface(
|
||||
* @return True if the socket is successfully opened for BACnet/IP,
|
||||
* else False if the socket functions fail.
|
||||
*/
|
||||
bool bip_init(
|
||||
char *ifname)
|
||||
bool bip_init(char *ifname)
|
||||
{
|
||||
int status = 0; /* return from socket lib calls */
|
||||
int status = 0; /* return from socket lib calls */
|
||||
struct sockaddr_in sin;
|
||||
int sockopt = 0;
|
||||
int sock_fd = -1;
|
||||
@@ -572,18 +566,16 @@ bool bip_init(
|
||||
/* Allow us to use the same socket for sending and receiving */
|
||||
/* This makes sure that the src port is correct when sending */
|
||||
sockopt = 1;
|
||||
status =
|
||||
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt,
|
||||
sizeof(sockopt));
|
||||
status = setsockopt(
|
||||
sock_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(sock_fd);
|
||||
BIP_Socket = -1;
|
||||
return status;
|
||||
}
|
||||
/* allow us to send a broadcast */
|
||||
status =
|
||||
setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &sockopt,
|
||||
sizeof(sockopt));
|
||||
status = setsockopt(
|
||||
sock_fd, SOL_SOCKET, SO_BROADCAST, &sockopt, sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(sock_fd);
|
||||
BIP_Socket = -1;
|
||||
@@ -595,7 +587,7 @@ bool bip_init(
|
||||
sin.sin_port = BIP_Port;
|
||||
memset(&(sin.sin_zero), '\0', sizeof(sin.sin_zero));
|
||||
status =
|
||||
bind(sock_fd, (const struct sockaddr *) &sin, sizeof(struct sockaddr));
|
||||
bind(sock_fd, (const struct sockaddr *)&sin, sizeof(struct sockaddr));
|
||||
if (status < 0) {
|
||||
close(sock_fd);
|
||||
BIP_Socket = -1;
|
||||
@@ -617,8 +609,7 @@ bool bip_valid(void)
|
||||
/** Cleanup and close out the BACnet/IP services by closing the socket.
|
||||
* @ingroup DLBIP
|
||||
*/
|
||||
void bip_cleanup(
|
||||
void)
|
||||
void bip_cleanup(void)
|
||||
{
|
||||
int sock_fd = 0;
|
||||
|
||||
|
||||
@@ -27,11 +27,10 @@
|
||||
* @param true if DST is enabled and active
|
||||
* @return true if local time was retrieved
|
||||
*/
|
||||
bool datetime_local(
|
||||
BACNET_DATE * bdate,
|
||||
BACNET_TIME * btime,
|
||||
int16_t * utc_offset_minutes,
|
||||
bool * dst_active)
|
||||
bool datetime_local(BACNET_DATE *bdate,
|
||||
BACNET_TIME *btime,
|
||||
int16_t *utc_offset_minutes,
|
||||
bool *dst_active)
|
||||
{
|
||||
bool status = false;
|
||||
struct tm *tblock = NULL;
|
||||
@@ -54,11 +53,10 @@ bool datetime_local(
|
||||
* int tm_isdst Daylight Savings flag.
|
||||
*/
|
||||
datetime_set_date(bdate, (uint16_t)tblock->tm_year + 1900,
|
||||
(uint8_t)tblock->tm_mon + 1,
|
||||
(uint8_t)tblock->tm_mday);
|
||||
(uint8_t)tblock->tm_mon + 1, (uint8_t)tblock->tm_mday);
|
||||
datetime_set_time(btime, (uint8_t)tblock->tm_hour,
|
||||
(uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec,
|
||||
(uint8_t)(tv.tv_usec / 10000));
|
||||
(uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec,
|
||||
(uint8_t)(tv.tv_usec / 10000));
|
||||
if (dst_active) {
|
||||
/* The value of tm_isdst is:
|
||||
- positive if Daylight Saving Time is in effect,
|
||||
|
||||
+61
-85
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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>
|
||||
@@ -46,7 +46,8 @@
|
||||
#include "bacnet/basic/tsm/tsm.h"
|
||||
#include "bacnet/datalink/dlenv.h"
|
||||
|
||||
/** @file bsd/main.c Example application using the BACnet Stack on BSD/MAC OS X. */
|
||||
/** @file bsd/main.c Example application using the BACnet Stack on BSD/MAC OS
|
||||
* X. */
|
||||
|
||||
bool Who_Is_Request = true;
|
||||
|
||||
@@ -54,9 +55,7 @@ bool Who_Is_Request = true;
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
static void LocalIAmHandler(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src)
|
||||
uint8_t *service_request, uint16_t service_len, BACNET_ADDRESS *src)
|
||||
{
|
||||
int len = 0;
|
||||
uint32_t device_id = 0;
|
||||
@@ -64,11 +63,10 @@ static void LocalIAmHandler(
|
||||
int segmentation = 0;
|
||||
uint16_t vendor_id = 0;
|
||||
|
||||
(void) src;
|
||||
(void) service_len;
|
||||
len =
|
||||
iam_decode_service_request(service_request, &device_id, &max_apdu,
|
||||
&segmentation, &vendor_id);
|
||||
(void)src;
|
||||
(void)service_len;
|
||||
len = iam_decode_service_request(
|
||||
service_request, &device_id, &max_apdu, &segmentation, &vendor_id);
|
||||
fprintf(stderr, "Received I-Am Request");
|
||||
if (len != -1) {
|
||||
fprintf(stderr, " from %u!\n", device_id);
|
||||
@@ -79,8 +77,7 @@ static void LocalIAmHandler(
|
||||
return;
|
||||
}
|
||||
|
||||
static void Read_Properties(
|
||||
void)
|
||||
static void Read_Properties(void)
|
||||
{
|
||||
uint32_t device_id = 0;
|
||||
bool status = false;
|
||||
@@ -93,32 +90,17 @@ static void Read_Properties(
|
||||
properties in the Device Object. Note that this demo
|
||||
tests for error messages so that the device doesn't have
|
||||
to have all the properties listed here. */
|
||||
const int object_props[] = {
|
||||
PROP_OBJECT_IDENTIFIER,
|
||||
PROP_OBJECT_NAME,
|
||||
PROP_OBJECT_TYPE,
|
||||
PROP_SYSTEM_STATUS,
|
||||
PROP_VENDOR_NAME,
|
||||
PROP_VENDOR_IDENTIFIER,
|
||||
PROP_MODEL_NAME,
|
||||
PROP_FIRMWARE_REVISION,
|
||||
PROP_APPLICATION_SOFTWARE_VERSION,
|
||||
PROP_PROTOCOL_VERSION,
|
||||
PROP_PROTOCOL_SERVICES_SUPPORTED,
|
||||
PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
|
||||
PROP_MAX_APDU_LENGTH_ACCEPTED,
|
||||
PROP_SEGMENTATION_SUPPORTED,
|
||||
PROP_LOCAL_TIME,
|
||||
PROP_LOCAL_DATE,
|
||||
PROP_UTC_OFFSET,
|
||||
PROP_DAYLIGHT_SAVINGS_STATUS,
|
||||
PROP_APDU_SEGMENT_TIMEOUT,
|
||||
PROP_APDU_TIMEOUT,
|
||||
PROP_NUMBER_OF_APDU_RETRIES,
|
||||
PROP_TIME_SYNCHRONIZATION_RECIPIENTS,
|
||||
PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES,
|
||||
PROP_DEVICE_ADDRESS_BINDING,
|
||||
const int object_props[] = { PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
|
||||
PROP_OBJECT_TYPE, PROP_SYSTEM_STATUS, PROP_VENDOR_NAME,
|
||||
PROP_VENDOR_IDENTIFIER, PROP_MODEL_NAME, PROP_FIRMWARE_REVISION,
|
||||
PROP_APPLICATION_SOFTWARE_VERSION, PROP_PROTOCOL_VERSION,
|
||||
PROP_PROTOCOL_SERVICES_SUPPORTED, PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED,
|
||||
PROP_MAX_APDU_LENGTH_ACCEPTED, PROP_SEGMENTATION_SUPPORTED,
|
||||
PROP_LOCAL_TIME, PROP_LOCAL_DATE, PROP_UTC_OFFSET,
|
||||
PROP_DAYLIGHT_SAVINGS_STATUS, PROP_APDU_SEGMENT_TIMEOUT,
|
||||
PROP_APDU_TIMEOUT, PROP_NUMBER_OF_APDU_RETRIES,
|
||||
PROP_TIME_SYNCHRONIZATION_RECIPIENTS, PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES, PROP_DEVICE_ADDRESS_BINDING,
|
||||
/* note: PROP_OBJECT_LIST is missing because
|
||||
the result can be very large. Read index 0
|
||||
which gives us the number of objects in the list,
|
||||
@@ -128,8 +110,7 @@ static void Read_Properties(
|
||||
/* some proprietary properties */
|
||||
514, 515,
|
||||
/* end of list */
|
||||
-1
|
||||
};
|
||||
-1 };
|
||||
|
||||
if (address_count()) {
|
||||
if (address_get_by_index(index, &device_id, &max_apdu, &src)) {
|
||||
@@ -139,8 +120,10 @@ static void Read_Properties(
|
||||
/* note: if we wanted to do this synchronously, we would get the
|
||||
invoke ID from the sending of the request, and wait until we
|
||||
got the reply with matching invoke ID or the TSM of the
|
||||
invoke ID expired. This demo is doing things asynchronously. */
|
||||
status = Send_Read_Property_Request(device_id, /* destination device */
|
||||
invoke ID expired. This demo is doing things asynchronously.
|
||||
*/
|
||||
status = Send_Read_Property_Request(
|
||||
device_id, /* destination device */
|
||||
OBJECT_DEVICE, device_id, object_props[property],
|
||||
BACNET_ARRAY_ALL);
|
||||
if (status)
|
||||
@@ -160,31 +143,28 @@ static void Read_Properties(
|
||||
return;
|
||||
}
|
||||
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
static void Init_Service_Handlers(void)
|
||||
{
|
||||
Device_Init(NULL);
|
||||
handler_read_property_object_set(OBJECT_DEVICE,
|
||||
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
|
||||
handler_read_property_object_set(OBJECT_DEVICE, Device_Encode_Property_APDU,
|
||||
Device_Valid_Object_Instance_Number);
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, LocalIAmHandler);
|
||||
|
||||
/* set the handler for all the services we don't implement */
|
||||
/* It is required to send the proper reject message... */
|
||||
apdu_set_unrecognized_service_handler_handler
|
||||
(handler_unrecognized_service);
|
||||
apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service);
|
||||
/* Set the handlers for any confirmed services that we support. */
|
||||
/* We must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property);
|
||||
/* handle the data coming back from confirmed requests */
|
||||
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property_ack);
|
||||
apdu_set_confirmed_ack_handler(
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property_ack);
|
||||
}
|
||||
|
||||
static void print_address_cache(
|
||||
void)
|
||||
static void print_address_cache(void)
|
||||
{
|
||||
unsigned i, j;
|
||||
BACNET_ADDRESS address;
|
||||
@@ -205,8 +185,7 @@ static void print_address_cache(
|
||||
}
|
||||
}
|
||||
|
||||
static void print_tsm_stats(
|
||||
void)
|
||||
static void print_tsm_stats(void)
|
||||
{
|
||||
int idle = 0;
|
||||
int total = 0;
|
||||
@@ -216,8 +195,7 @@ static void print_tsm_stats(
|
||||
fprintf(stderr, "TSM: %d idle of %d transactions\n", idle, total);
|
||||
}
|
||||
|
||||
static void sig_handler(
|
||||
int signo)
|
||||
static void sig_handler(int signo)
|
||||
{
|
||||
datalink_cleanup();
|
||||
print_address_cache();
|
||||
@@ -226,18 +204,16 @@ static void sig_handler(
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||
uint16_t pdu_len = 0;
|
||||
unsigned timeout = 100; /* milliseconds */
|
||||
unsigned timeout = 100; /* milliseconds */
|
||||
unsigned count = 0; /* milliseconds */
|
||||
time_t start_time;
|
||||
time_t new_time = 0;
|
||||
|
||||
start_time = time(NULL); /* get current time */
|
||||
start_time = time(NULL); /* get current time */
|
||||
/* Linux specials */
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGHUP, sig_handler);
|
||||
|
||||
+32
-35
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
@@ -40,8 +40,7 @@ static volatile unsigned long Millisecond_Counter;
|
||||
static struct timespec start;
|
||||
/* The timeGetTime function retrieves the system time, in milliseconds.
|
||||
The system time is the time elapsed since the OS was started. */
|
||||
unsigned long timeGetTime(
|
||||
void)
|
||||
unsigned long timeGetTime(void)
|
||||
{
|
||||
struct timespec now;
|
||||
unsigned long ticks;
|
||||
@@ -54,17 +53,16 @@ unsigned long timeGetTime(
|
||||
now.tv_sec = mts.tv_sec;
|
||||
now.tv_nsec = mts.tv_nsec;
|
||||
|
||||
ticks =
|
||||
(now.tv_sec - start.tv_sec) * 1000 + (now.tv_nsec -
|
||||
start.tv_nsec) / 1000000;
|
||||
ticks = (now.tv_sec - start.tv_sec) * 1000 +
|
||||
(now.tv_nsec - start.tv_nsec) / 1000000;
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the current millisecond count
|
||||
* @return millisecond counter
|
||||
*/
|
||||
* @brief returns the current millisecond count
|
||||
* @return millisecond counter
|
||||
*/
|
||||
unsigned long mstimer_now(void)
|
||||
{
|
||||
unsigned long now = timeGetTime();
|
||||
@@ -80,10 +78,9 @@ unsigned long mstimer_now(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialization for timer
|
||||
*/
|
||||
void timer_init(
|
||||
void)
|
||||
* @brief Initialization for timer
|
||||
*/
|
||||
void timer_init(void)
|
||||
{
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
|
||||
+264
-335
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,7 @@
|
||||
|
||||
#include "bacnet/datalink/bip.h"
|
||||
|
||||
long bip_get_addr_by_name(
|
||||
const char *host_name)
|
||||
long bip_get_addr_by_name(const char *host_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -20,7 +19,7 @@ void bip_set_interface(char *ifname)
|
||||
{
|
||||
}
|
||||
|
||||
void bip_cleanup (void)
|
||||
void bip_cleanup(void)
|
||||
{
|
||||
close(bip_socket());
|
||||
bip_set_socket(-1);
|
||||
@@ -28,7 +27,6 @@ void bip_cleanup (void)
|
||||
|
||||
bool bip_init(char *ifname)
|
||||
{
|
||||
|
||||
tcpip_adapter_ip_info_t ip_info = { 0 };
|
||||
|
||||
int value = 1;
|
||||
@@ -38,9 +36,10 @@ bool bip_init(char *ifname)
|
||||
bip_set_interface(ifname);
|
||||
bip_set_port(0xBAC0U);
|
||||
bip_set_addr(ip_info.ip.addr);
|
||||
bip_set_broadcast_addr((ip_info.ip.addr&ip_info.netmask.addr)|(~ip_info.netmask.addr));
|
||||
bip_set_broadcast_addr(
|
||||
(ip_info.ip.addr & ip_info.netmask.addr) | (~ip_info.netmask.addr));
|
||||
|
||||
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
struct sockaddr_in saddr = { 0 };
|
||||
|
||||
saddr.sin_family = PF_INET;
|
||||
@@ -48,8 +47,8 @@ bool bip_init(char *ifname)
|
||||
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
|
||||
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &value, sizeof(value));
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &value, sizeof(value));
|
||||
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(value));
|
||||
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(value));
|
||||
|
||||
bip_set_socket(sock);
|
||||
|
||||
|
||||
+86
-125
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* Binary Output Objects - customize for your use */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/basic/object/bo.h"
|
||||
@@ -46,42 +46,25 @@
|
||||
/* the Relinquish Default value */
|
||||
#define RELINQUISH_DEFAULT BINARY_INACTIVE
|
||||
/* Here is our Priority Array.*/
|
||||
static BACNET_BINARY_PV
|
||||
Binary_Output_Level[MAX_BINARY_OUTPUTS][BACNET_MAX_PRIORITY];
|
||||
static BACNET_BINARY_PV Binary_Output_Level[MAX_BINARY_OUTPUTS]
|
||||
[BACNET_MAX_PRIORITY];
|
||||
/* Writable out-of-service allows others to play with our Present Value */
|
||||
/* without changing the physical output */
|
||||
static bool Out_Of_Service[MAX_BINARY_OUTPUTS];
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
static const int Binary_Output_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_POLARITY,
|
||||
PROP_PRIORITY_ARRAY,
|
||||
PROP_RELINQUISH_DEFAULT,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Output_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_POLARITY, PROP_PRIORITY_ARRAY,
|
||||
PROP_RELINQUISH_DEFAULT, -1 };
|
||||
|
||||
static const int Binary_Output_Properties_Optional[] = {
|
||||
PROP_DESCRIPTION,
|
||||
PROP_ACTIVE_TEXT,
|
||||
PROP_INACTIVE_TEXT,
|
||||
-1
|
||||
};
|
||||
static const int Binary_Output_Properties_Optional[] = { PROP_DESCRIPTION,
|
||||
PROP_ACTIVE_TEXT, PROP_INACTIVE_TEXT, -1 };
|
||||
|
||||
static const int Binary_Output_Properties_Proprietary[] = {
|
||||
-1
|
||||
};
|
||||
static const int Binary_Output_Properties_Proprietary[] = { -1 };
|
||||
|
||||
void Binary_Output_Property_Lists(
|
||||
const int **pRequired,
|
||||
const int **pOptional,
|
||||
const int **pProprietary)
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary)
|
||||
{
|
||||
if (pRequired)
|
||||
*pRequired = Binary_Output_Properties_Required;
|
||||
@@ -93,8 +76,7 @@ void Binary_Output_Property_Lists(
|
||||
return;
|
||||
}
|
||||
|
||||
void Binary_Output_Init(
|
||||
void)
|
||||
void Binary_Output_Init(void)
|
||||
{
|
||||
unsigned i, j;
|
||||
static bool initialized = false;
|
||||
@@ -116,8 +98,7 @@ void Binary_Output_Init(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Binary_Output_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Output_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_OUTPUTS)
|
||||
return true;
|
||||
@@ -127,8 +108,7 @@ bool Binary_Output_Valid_Instance(
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Binary_Output_Count(
|
||||
void)
|
||||
unsigned Binary_Output_Count(void)
|
||||
{
|
||||
return MAX_BINARY_OUTPUTS;
|
||||
}
|
||||
@@ -136,8 +116,7 @@ unsigned Binary_Output_Count(
|
||||
/* 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 Binary_Output_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Binary_Output_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -145,8 +124,7 @@ uint32_t Binary_Output_Index_To_Instance(
|
||||
/* 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 Binary_Output_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Binary_Output_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_OUTPUTS;
|
||||
|
||||
@@ -156,8 +134,7 @@ unsigned Binary_Output_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Output_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Output_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
|
||||
unsigned index = 0;
|
||||
@@ -176,8 +153,7 @@ BACNET_BINARY_PV Binary_Output_Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
bool Binary_Output_Out_Of_Service(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Output_Out_Of_Service(uint32_t object_instance)
|
||||
{
|
||||
bool value = false;
|
||||
unsigned index = 0;
|
||||
@@ -193,32 +169,28 @@ bool Binary_Output_Out_Of_Service(
|
||||
/* note: the object name must be unique within this device */
|
||||
|
||||
bool Binary_Output_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
|
||||
{
|
||||
static char text_string[32] = "";
|
||||
static char text_string[32] = "";
|
||||
bool status = false;
|
||||
|
||||
if (object_instance==0)
|
||||
status=characterstring_init_ansi(object_name, "Led");
|
||||
else
|
||||
{
|
||||
if (object_instance == 0)
|
||||
status = characterstring_init_ansi(object_name, "Led");
|
||||
else {
|
||||
if (object_instance < MAX_BINARY_OUTPUTS) {
|
||||
sprintf(text_string, "BINARY OUTPUT %lu",
|
||||
(unsigned long) object_instance);
|
||||
(unsigned long)object_instance);
|
||||
status = characterstring_init_ansi(object_name, text_string);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* return apdu len, or BACNET_STATUS_ERROR on error */
|
||||
int Binary_Output_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Output_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
@@ -235,9 +207,8 @@ int Binary_Output_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_OUTPUT,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_OUTPUT, rpdata->object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
You could make Description writable and different */
|
||||
@@ -295,9 +266,8 @@ int Binary_Output_Read_Property(
|
||||
len = encode_application_null(&apdu[apdu_len]);
|
||||
else {
|
||||
present_value = Binary_Output_Level[object_index][i];
|
||||
len =
|
||||
encode_application_enumerated(&apdu[apdu_len],
|
||||
present_value);
|
||||
len = encode_application_enumerated(
|
||||
&apdu[apdu_len], present_value);
|
||||
}
|
||||
/* add it if we have room */
|
||||
if ((apdu_len + len) < MAX_APDU)
|
||||
@@ -317,11 +287,11 @@ int Binary_Output_Read_Property(
|
||||
1] == BINARY_NULL)
|
||||
apdu_len = encode_application_null(&apdu[apdu_len]);
|
||||
else {
|
||||
present_value = Binary_Output_Level[object_index]
|
||||
[rpdata->array_index - 1];
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[apdu_len],
|
||||
present_value);
|
||||
present_value =
|
||||
Binary_Output_Level[object_index]
|
||||
[rpdata->array_index - 1];
|
||||
apdu_len = encode_application_enumerated(
|
||||
&apdu[apdu_len], present_value);
|
||||
}
|
||||
} else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -363,10 +333,9 @@ int Binary_Output_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Binary_Output_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
BACNET_BINARY_PV level = BINARY_NULL;
|
||||
@@ -374,9 +343,8 @@ bool Binary_Output_Write_Property(
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -399,19 +367,19 @@ bool Binary_Output_Write_Property(
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Enumerated <= MAX_BINARY_PV)) {
|
||||
level = (BACNET_BINARY_PV) value.type.Enumerated;
|
||||
object_index =
|
||||
Binary_Output_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
level = (BACNET_BINARY_PV)value.type.Enumerated;
|
||||
object_index = Binary_Output_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority--;
|
||||
Binary_Output_Level[object_index][priority] = level;
|
||||
/* 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) */
|
||||
main loop (i.e. check out of service before changing
|
||||
output) */
|
||||
status = true;
|
||||
} else if (priority == 6) {
|
||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||
@@ -424,24 +392,23 @@ bool Binary_Output_Write_Property(
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
|
||||
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
level = BINARY_NULL;
|
||||
object_index =
|
||||
Binary_Output_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
object_index = Binary_Output_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority = wp_data->priority;
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
|
||||
priority--;
|
||||
Binary_Output_Level[object_index][priority] = level;
|
||||
/* Note: you could set the physical output here to the next
|
||||
highest priority, or to the relinquish default if no
|
||||
priorities are set.
|
||||
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) */
|
||||
/* Note: you could set the physical output here to the
|
||||
next highest priority, or to the relinquish default
|
||||
if no priorities are set. 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) */
|
||||
} else {
|
||||
status = false;
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -451,14 +418,12 @@ bool Binary_Output_Write_Property(
|
||||
}
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
status =
|
||||
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
|
||||
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
if (status) {
|
||||
object_index =
|
||||
Binary_Output_Instance_To_Index(wp_data->object_instance);
|
||||
Out_Of_Service[object_index] =
|
||||
value.type.Boolean;
|
||||
Out_Of_Service[object_index] = value.type.Boolean;
|
||||
}
|
||||
break;
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
@@ -484,17 +449,15 @@ bool Binary_Output_Write_Property(
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
bool WPValidateArgType(
|
||||
BACNET_APPLICATION_DATA_VALUE * pValue,
|
||||
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
|
||||
uint8_t ucExpectedTag,
|
||||
BACNET_ERROR_CLASS * pErrorClass,
|
||||
BACNET_ERROR_CODE * pErrorCode)
|
||||
BACNET_ERROR_CLASS *pErrorClass,
|
||||
BACNET_ERROR_CODE *pErrorCode)
|
||||
{
|
||||
pValue = pValue;
|
||||
ucExpectedTag = ucExpectedTag;
|
||||
@@ -504,8 +467,7 @@ bool WPValidateArgType(
|
||||
return false;
|
||||
}
|
||||
|
||||
void testBinaryOutput(
|
||||
Test * pTest)
|
||||
void testBinaryOutput(Test *pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 0;
|
||||
@@ -534,8 +496,7 @@ void testBinaryOutput(
|
||||
}
|
||||
|
||||
#ifdef TEST_BINARY_OUTPUT
|
||||
int main(
|
||||
void)
|
||||
int main(void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
@@ -547,7 +508,7 @@ int main(
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
(void)ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
|
||||
+262
-406
File diff suppressed because it is too large
Load Diff
+71
-76
@@ -60,51 +60,49 @@ void StartBACnet()
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
/* set the handler for all the services we don't implement */
|
||||
/* It is required to send the proper reject message... */
|
||||
apdu_set_unrecognized_service_handler_handler
|
||||
(handler_unrecognized_service);
|
||||
/* It is required to send the proper reject message... */
|
||||
apdu_set_unrecognized_service_handler_handler(handler_unrecognized_service);
|
||||
/* Set the handlers for any confirmed services that we support. */
|
||||
/* We must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROP_MULTIPLE,
|
||||
handler_read_property_multiple);
|
||||
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
handler_write_property);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV,
|
||||
handler_cov_subscribe);
|
||||
|
||||
address_init();
|
||||
bip_init(NULL);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROPERTY, handler_read_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_READ_PROP_MULTIPLE, handler_read_property_multiple);
|
||||
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, handler_write_property);
|
||||
apdu_set_confirmed_handler(
|
||||
SERVICE_CONFIRMED_SUBSCRIBE_COV, handler_cov_subscribe);
|
||||
|
||||
address_init();
|
||||
bip_init(NULL);
|
||||
Send_I_Am(&Handler_Transmit_Buffer[0]);
|
||||
}
|
||||
|
||||
/* wifi events handler : start & stop bacnet with an event */
|
||||
esp_err_t wifi_event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
switch(event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
break ;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
if (xEventGroupGetBits(wifi_event_group)!=CONNECTED_BIT)
|
||||
{
|
||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||
StartBACnet();
|
||||
}
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
/* This is a workaround as ESP32 WiFi libs don't currently
|
||||
auto-reassociate. */
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
bip_cleanup();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch (event->event_id) {
|
||||
case SYSTEM_EVENT_STA_START:
|
||||
esp_wifi_connect();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_CONNECTED:
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
if (xEventGroupGetBits(wifi_event_group) != CONNECTED_BIT) {
|
||||
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
|
||||
StartBACnet();
|
||||
}
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
/* This is a workaround as ESP32 WiFi libs don't currently
|
||||
auto-reassociate. */
|
||||
esp_wifi_connect();
|
||||
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
|
||||
bip_cleanup();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -125,7 +123,7 @@ void wifi_init_station(void)
|
||||
|
||||
esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config);
|
||||
|
||||
esp_wifi_start() ;
|
||||
esp_wifi_start();
|
||||
}
|
||||
|
||||
/* setup gpio & nv flash, call wifi init code */
|
||||
@@ -134,25 +132,22 @@ void setup()
|
||||
gpio_pad_select_gpio(BACNET_LED);
|
||||
gpio_set_direction(BACNET_LED, GPIO_MODE_OUTPUT);
|
||||
|
||||
gpio_set_level(BACNET_LED,0);
|
||||
gpio_set_level(BACNET_LED, 0);
|
||||
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES)
|
||||
{
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||||
nvs_flash_erase();
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
wifi_init_station();
|
||||
wifi_init_station();
|
||||
}
|
||||
|
||||
/* Bacnet Task */
|
||||
void BACnetTask(void *pvParameters)
|
||||
{
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src = {
|
||||
0
|
||||
};
|
||||
unsigned timeout = 1;
|
||||
BACNET_ADDRESS src = { 0 };
|
||||
unsigned timeout = 1;
|
||||
|
||||
// Init Bacnet objets dictionnary
|
||||
Device_Init(NULL);
|
||||
@@ -160,41 +155,41 @@ void BACnetTask(void *pvParameters)
|
||||
|
||||
setup();
|
||||
|
||||
uint32_t tickcount=xTaskGetTickCount();
|
||||
uint32_t tickcount = xTaskGetTickCount();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS); // could be remove to speed the code
|
||||
for (;;) {
|
||||
vTaskDelay(
|
||||
10 / portTICK_PERIOD_MS); // could be remove to speed the code
|
||||
|
||||
// do nothing if not connected to wifi
|
||||
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
{
|
||||
uint32_t newtick=xTaskGetTickCount();
|
||||
xEventGroupWaitBits(
|
||||
wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
|
||||
{
|
||||
uint32_t newtick = xTaskGetTickCount();
|
||||
|
||||
// one second elapse at least (maybe much more if Wifi was deconnected for a long)
|
||||
if ((newtick<tickcount)||((newtick-tickcount)>=configTICK_RATE_HZ))
|
||||
{
|
||||
tickcount=newtick;
|
||||
// one second elapse at least (maybe much more if Wifi was
|
||||
// deconnected for a long)
|
||||
if ((newtick < tickcount) ||
|
||||
((newtick - tickcount) >= configTICK_RATE_HZ)) {
|
||||
tickcount = newtick;
|
||||
dcc_timer_seconds(1);
|
||||
bvlc_maintenance_timer(1);
|
||||
bvlc_maintenance_timer(1);
|
||||
handler_cov_timer_seconds(1);
|
||||
tsm_timer_milliseconds(1000);
|
||||
|
||||
// Read analog values from internal sensors
|
||||
Analog_Input_Present_Value_Set(0,temprature_sens_read());
|
||||
Analog_Input_Present_Value_Set(1,hall_sens_read());
|
||||
|
||||
Analog_Input_Present_Value_Set(0, temprature_sens_read());
|
||||
Analog_Input_Present_Value_Set(1, hall_sens_read());
|
||||
}
|
||||
|
||||
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
|
||||
if (pdu_len)
|
||||
{
|
||||
if (pdu_len) {
|
||||
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
||||
|
||||
if(Binary_Output_Present_Value(0)==BINARY_ACTIVE)
|
||||
gpio_set_level(BACNET_LED,1);
|
||||
if (Binary_Output_Present_Value(0) == BINARY_ACTIVE)
|
||||
gpio_set_level(BACNET_LED, 1);
|
||||
else
|
||||
gpio_set_level(BACNET_LED,0);
|
||||
gpio_set_level(BACNET_LED, 0);
|
||||
}
|
||||
|
||||
handler_cov_task();
|
||||
@@ -203,13 +198,13 @@ void BACnetTask(void *pvParameters)
|
||||
}
|
||||
/* Entry point */
|
||||
void app_main()
|
||||
{
|
||||
// Cannot run BACnet code here, the default stack size is to small : 4096 byte
|
||||
xTaskCreate(
|
||||
BACnetTask, /* Function to implement the task */
|
||||
"BACnetTask", /* Name of the task */
|
||||
10000, /* Stack size in words */
|
||||
NULL, /* Task input parameter */
|
||||
20, /* Priority of the task */
|
||||
NULL); /* Task handle. */
|
||||
{
|
||||
// Cannot run BACnet code here, the default stack size is to small : 4096
|
||||
// byte
|
||||
xTaskCreate(BACnetTask, /* Function to implement the task */
|
||||
"BACnetTask", /* Name of the task */
|
||||
10000, /* Stack size in words */
|
||||
NULL, /* Task input parameter */
|
||||
20, /* Priority of the task */
|
||||
NULL); /* Task handle. */
|
||||
}
|
||||
+50
-56
@@ -50,7 +50,7 @@ static struct sockaddr ARCNET_Socket_Address;
|
||||
#define ARCNET_BROADCAST 0
|
||||
|
||||
/*
|
||||
Hints:
|
||||
Hints:
|
||||
|
||||
When using a PCI20-485D ARCNET card from Contemporary Controls,
|
||||
you might need to know about the following settings:
|
||||
@@ -62,7 +62,7 @@ clockp Clock Prescaler DataRate
|
||||
0 8 2.5 Mbps
|
||||
1 16 1.25 Mbps
|
||||
2 32 625 Kbps
|
||||
3 64 312.5 Kbps
|
||||
3 64 312.5 Kbps
|
||||
4 128 156.25Kbps
|
||||
|
||||
1. Install the arcnet driver and arcnet raw mode driver:
|
||||
@@ -76,20 +76,18 @@ clockp Clock Prescaler DataRate
|
||||
on the back of the card. 0 is broadcast, so don't use 0.
|
||||
|
||||
4. The backplane mode on the PCI20-485D card is done in hardware,
|
||||
so the driver does not need to do backplane mode. If you
|
||||
use another type of PCI20 card, you could pass in backplane=1 or
|
||||
so the driver does not need to do backplane mode. If you
|
||||
use another type of PCI20 card, you could pass in backplane=1 or
|
||||
backplane=0 as an option to the modprobe of com20020_pci.
|
||||
|
||||
*/
|
||||
|
||||
bool arcnet_valid(
|
||||
void)
|
||||
bool arcnet_valid(void)
|
||||
{
|
||||
return (ARCNET_Sock_FD >= 0);
|
||||
}
|
||||
|
||||
void arcnet_cleanup(
|
||||
void)
|
||||
void arcnet_cleanup(void)
|
||||
{
|
||||
if (arcnet_valid())
|
||||
close(ARCNET_Sock_FD);
|
||||
@@ -98,12 +96,11 @@ void arcnet_cleanup(
|
||||
return;
|
||||
}
|
||||
|
||||
static int arcnet_bind(
|
||||
char *interface_name)
|
||||
static int arcnet_bind(char *interface_name)
|
||||
{
|
||||
int sock_fd = -1; /* return value */
|
||||
int sock_fd = -1; /* return value */
|
||||
struct ifreq ifr;
|
||||
int rv; /* return value - error value from df or ioctl call */
|
||||
int rv; /* return value - error value from df or ioctl call */
|
||||
int uid = 0;
|
||||
|
||||
/* check to see if we are being run as root */
|
||||
@@ -126,13 +123,15 @@ static int arcnet_bind(
|
||||
"You might need to add the following to modules.conf\n"
|
||||
"(or in /etc/modutils/alias on Debian with update-modules):\n"
|
||||
"alias net-pf-17 af_packet\n"
|
||||
"Also, add af_packet to /etc/modules.\n" "Then follow it by:\n"
|
||||
"Also, add af_packet to /etc/modules.\n"
|
||||
"Then follow it by:\n"
|
||||
"# modprobe af_packet\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (ARCNET_Sock_FD >= 0) {
|
||||
/* Bind the socket to an interface name so we only get packets from it */
|
||||
/* Bind the socket to an interface name so we only get packets from it
|
||||
*/
|
||||
ARCNET_Socket_Address.sa_family = ARPHRD_ARCNET;
|
||||
/*ARCNET_Socket_Address.sa_family = PF_INET; */
|
||||
/* Clear the memory before copying */
|
||||
@@ -141,8 +140,8 @@ static int arcnet_bind(
|
||||
/* Strcpy the interface name into the address */
|
||||
strncpy(ARCNET_Socket_Address.sa_data, interface_name,
|
||||
sizeof(ARCNET_Socket_Address.sa_data) - 1);
|
||||
fprintf(stderr, "arcnet: binding \"%s\"\n",
|
||||
ARCNET_Socket_Address.sa_data);
|
||||
fprintf(
|
||||
stderr, "arcnet: binding \"%s\"\n", ARCNET_Socket_Address.sa_data);
|
||||
if (bind(sock_fd, &ARCNET_Socket_Address,
|
||||
sizeof(ARCNET_Socket_Address)) != 0) {
|
||||
/* Bind problem, close socket and return */
|
||||
@@ -152,7 +151,8 @@ static int arcnet_bind(
|
||||
"You might need to add the following to modules.conf\n"
|
||||
"(or in /etc/modutils/alias on Debian with update-modules):\n"
|
||||
"alias net-pf-17 af_packet\n"
|
||||
"Also, add af_packet to /etc/modules.\n" "Then follow it by:\n"
|
||||
"Also, add af_packet to /etc/modules.\n"
|
||||
"Then follow it by:\n"
|
||||
"# modprobe af_packet\n");
|
||||
/* Close the socket */
|
||||
close(sock_fd);
|
||||
@@ -161,7 +161,7 @@ static int arcnet_bind(
|
||||
}
|
||||
strncpy(ifr.ifr_name, interface_name, sizeof(ifr.ifr_name));
|
||||
rv = ioctl(sock_fd, SIOCGIFHWADDR, &ifr);
|
||||
if (rv != -1) /* worked okay */
|
||||
if (rv != -1) /* worked okay */
|
||||
ARCNET_MAC_Address = ifr.ifr_hwaddr.sa_data[0];
|
||||
/* copy this info into the local copy since bind wiped it out */
|
||||
ARCNET_Socket_Address.sa_family = ARPHRD_ARCNET;
|
||||
@@ -180,8 +180,7 @@ static int arcnet_bind(
|
||||
return sock_fd;
|
||||
}
|
||||
|
||||
bool arcnet_init(
|
||||
char *interface_name)
|
||||
bool arcnet_init(char *interface_name)
|
||||
{
|
||||
if (interface_name)
|
||||
ARCNET_Sock_FD = arcnet_bind(interface_name);
|
||||
@@ -193,19 +192,18 @@ bool arcnet_init(
|
||||
|
||||
/* function to send a PDU out the socket */
|
||||
/* returns number of bytes sent on success, negative on failure */
|
||||
int arcnet_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int arcnet_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
BACNET_ADDRESS src = { 0 }; /* source address */
|
||||
int bytes = 0;
|
||||
uint8_t mtu[512] = { 0 };
|
||||
int mtu_len = 0;
|
||||
struct archdr *pkt = (struct archdr *) mtu;
|
||||
struct archdr *pkt = (struct archdr *)mtu;
|
||||
|
||||
(void) npdu_data;
|
||||
(void)npdu_data;
|
||||
src.mac[0] = ARCNET_MAC_Address;
|
||||
src.mac_len = 1;
|
||||
|
||||
@@ -228,21 +226,20 @@ int arcnet_send_pdu(
|
||||
return -3;
|
||||
}
|
||||
/* Logical PDU portion */
|
||||
pkt->soft.raw[0] = 0xCD; /* SC for BACnet */
|
||||
pkt->soft.raw[1] = 0x82; /* DSAP for BACnet */
|
||||
pkt->soft.raw[2] = 0x82; /* SSAP for BACnet */
|
||||
pkt->soft.raw[3] = 0x03; /* LLC Control byte in header */
|
||||
pkt->soft.raw[0] = 0xCD; /* SC for BACnet */
|
||||
pkt->soft.raw[1] = 0x82; /* DSAP for BACnet */
|
||||
pkt->soft.raw[2] = 0x82; /* SSAP for BACnet */
|
||||
pkt->soft.raw[3] = 0x03; /* LLC Control byte in header */
|
||||
/* packet length */
|
||||
mtu_len = ARC_HDR_SIZE + 4 /*SC,DSAP,SSAP,LLC */ + pdu_len;
|
||||
mtu_len = ARC_HDR_SIZE + 4 /*SC,DSAP,SSAP,LLC */ + pdu_len;
|
||||
if (mtu_len > 512) {
|
||||
fprintf(stderr, "arcnet: PDU is too big to send!\n");
|
||||
return -4;
|
||||
}
|
||||
memcpy(&pkt->soft.raw[4], pdu, pdu_len);
|
||||
/* Send the packet */
|
||||
bytes =
|
||||
sendto(ARCNET_Sock_FD, &mtu, mtu_len, 0,
|
||||
(struct sockaddr *) &ARCNET_Socket_Address,
|
||||
bytes = sendto(ARCNET_Sock_FD, &mtu, mtu_len, 0,
|
||||
(struct sockaddr *)&ARCNET_Socket_Address,
|
||||
sizeof(ARCNET_Socket_Address));
|
||||
/* did it get sent? */
|
||||
if (bytes < 0)
|
||||
@@ -253,19 +250,18 @@ int arcnet_send_pdu(
|
||||
|
||||
/* receives an framed packet */
|
||||
/* returns the number of octets in the PDU, or zero on failure */
|
||||
uint16_t arcnet_receive(
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t arcnet_receive(BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
{ /* milliseconds to wait for a packet */
|
||||
int received_bytes;
|
||||
uint8_t buf[512] = { 0 }; /* data */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
uint8_t buf[512] = { 0 }; /* data */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
fd_set read_fds;
|
||||
int max;
|
||||
struct timeval select_timeout;
|
||||
struct archdr *pkt = (struct archdr *) buf;
|
||||
struct archdr *pkt = (struct archdr *)buf;
|
||||
|
||||
/* Make sure the socket is open */
|
||||
if (ARCNET_Sock_FD <= 0)
|
||||
@@ -307,7 +303,7 @@ uint16_t arcnet_receive(
|
||||
|
||||
/* printf("arcnet: received %u bytes (offset=%02Xh %02Xh) "
|
||||
"from %02Xh (proto==%02Xh)\n",
|
||||
received_bytes, pkt->offset[0], pkt->offset[1],
|
||||
received_bytes, pkt->offset[0], pkt->offset[1],
|
||||
pkt->hard.source, pkt->soft.raw[0]);
|
||||
*/
|
||||
|
||||
@@ -324,9 +320,9 @@ uint16_t arcnet_receive(
|
||||
fprintf(stderr, "arcnet: This packet is not for us.\n");
|
||||
return 0;
|
||||
}
|
||||
if ((pkt->soft.raw[1] != 0x82) || /* DSAP */
|
||||
(pkt->soft.raw[2] != 0x82) || /* LSAP */
|
||||
(pkt->soft.raw[3] != 0x03)) { /* LLC Control */
|
||||
if ((pkt->soft.raw[1] != 0x82) || /* DSAP */
|
||||
(pkt->soft.raw[2] != 0x82) || /* LSAP */
|
||||
(pkt->soft.raw[3] != 0x03)) { /* LLC Control */
|
||||
fprintf(stderr, "arcnet: BACnet packet has invalid LLC.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -341,7 +337,7 @@ uint16_t arcnet_receive(
|
||||
src->mac[0] = pkt->hard.source;
|
||||
/* compute the PDU length */
|
||||
pdu_len = received_bytes - ARC_HDR_SIZE;
|
||||
pdu_len -= 4 /* SC, DSAP, SSAP, LLC Control */ ;
|
||||
pdu_len -= 4 /* SC, DSAP, SSAP, LLC Control */;
|
||||
/* copy the buffer into the PDU */
|
||||
if (pdu_len < max_pdu)
|
||||
memmove(&pdu[0], &pkt->soft.raw[4], pdu_len);
|
||||
@@ -352,14 +348,13 @@ uint16_t arcnet_receive(
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void arcnet_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void arcnet_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
my_address->mac_len = 1;
|
||||
my_address->mac[0] = ARCNET_MAC_Address;
|
||||
my_address->net = 0; /* DNET=0 is local only, no routing */
|
||||
my_address->net = 0; /* DNET=0 is local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -368,16 +363,15 @@ void arcnet_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void arcnet_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void arcnet_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac[0] = ARCNET_BROADCAST;
|
||||
dest->mac_len = 1;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
|
||||
+53
-79
@@ -35,8 +35,8 @@
|
||||
#include <ifaddrs.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/config.h"
|
||||
#include "bacnet/datalink/bip6.h"
|
||||
@@ -45,16 +45,16 @@
|
||||
#include "bacnet/basic/bbmd6/h_bbmd6.h"
|
||||
#include "bacport.h"
|
||||
|
||||
static void debug_print_ipv6(const char *str, const struct in6_addr * addr) {
|
||||
debug_printf( "BIP6: %s %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n",
|
||||
str,
|
||||
(int)addr->s6_addr[0], (int)addr->s6_addr[1],
|
||||
(int)addr->s6_addr[2], (int)addr->s6_addr[3],
|
||||
(int)addr->s6_addr[4], (int)addr->s6_addr[5],
|
||||
(int)addr->s6_addr[6], (int)addr->s6_addr[7],
|
||||
(int)addr->s6_addr[8], (int)addr->s6_addr[9],
|
||||
(int)addr->s6_addr[10], (int)addr->s6_addr[11],
|
||||
(int)addr->s6_addr[12], (int)addr->s6_addr[13],
|
||||
static void debug_print_ipv6(const char *str, const struct in6_addr *addr)
|
||||
{
|
||||
debug_printf("BIP6: %s "
|
||||
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%"
|
||||
"02x:%02x%02x\n",
|
||||
str, (int)addr->s6_addr[0], (int)addr->s6_addr[1],
|
||||
(int)addr->s6_addr[2], (int)addr->s6_addr[3], (int)addr->s6_addr[4],
|
||||
(int)addr->s6_addr[5], (int)addr->s6_addr[6], (int)addr->s6_addr[7],
|
||||
(int)addr->s6_addr[8], (int)addr->s6_addr[9], (int)addr->s6_addr[10],
|
||||
(int)addr->s6_addr[11], (int)addr->s6_addr[12], (int)addr->s6_addr[13],
|
||||
(int)addr->s6_addr[14], (int)addr->s6_addr[15]);
|
||||
}
|
||||
|
||||
@@ -71,8 +71,7 @@ static BACNET_IP6_ADDRESS BIP6_Broadcast_Addr;
|
||||
*
|
||||
* @param ifname - C string for name or text address
|
||||
*/
|
||||
void bip6_set_interface(
|
||||
char *ifname)
|
||||
void bip6_set_interface(char *ifname)
|
||||
{
|
||||
struct ifaddrs *ifa, *ifa_tmp;
|
||||
struct sockaddr_in6 *sin;
|
||||
@@ -85,16 +84,13 @@ void bip6_set_interface(
|
||||
ifa_tmp = ifa;
|
||||
debug_printf("BIP6: seeking interface: %s\n", ifname);
|
||||
while (ifa_tmp) {
|
||||
if ((ifa_tmp->ifa_addr) &&
|
||||
(ifa_tmp->ifa_addr->sa_family == AF_INET6)) {
|
||||
if ((ifa_tmp->ifa_addr) && (ifa_tmp->ifa_addr->sa_family == AF_INET6)) {
|
||||
debug_printf("BIP6: found interface: %s\n", ifa_tmp->ifa_name);
|
||||
}
|
||||
if ((ifa_tmp->ifa_addr) &&
|
||||
(ifa_tmp->ifa_addr->sa_family == AF_INET6) &&
|
||||
(strcasecmp(ifa_tmp->ifa_name,ifname) == 0)) {
|
||||
sin = (struct sockaddr_in6*) ifa_tmp->ifa_addr;
|
||||
bvlc6_address_set(&BIP6_Addr,
|
||||
ntohs(sin->sin6_addr.s6_addr16[0]),
|
||||
if ((ifa_tmp->ifa_addr) && (ifa_tmp->ifa_addr->sa_family == AF_INET6) &&
|
||||
(strcasecmp(ifa_tmp->ifa_name, ifname) == 0)) {
|
||||
sin = (struct sockaddr_in6 *)ifa_tmp->ifa_addr;
|
||||
bvlc6_address_set(&BIP6_Addr, ntohs(sin->sin6_addr.s6_addr16[0]),
|
||||
ntohs(sin->sin6_addr.s6_addr16[1]),
|
||||
ntohs(sin->sin6_addr.s6_addr16[2]),
|
||||
ntohs(sin->sin6_addr.s6_addr16[3]),
|
||||
@@ -119,8 +115,7 @@ void bip6_set_interface(
|
||||
*
|
||||
* @param port - IPv6 UDP port number
|
||||
*/
|
||||
void bip6_set_port(
|
||||
uint16_t port)
|
||||
void bip6_set_port(uint16_t port)
|
||||
{
|
||||
BIP6_Addr.port = port;
|
||||
BIP6_Broadcast_Addr.port = port;
|
||||
@@ -131,8 +126,7 @@ void bip6_set_port(
|
||||
*
|
||||
* @return IPv6 UDP port number
|
||||
*/
|
||||
uint16_t bip6_get_port(
|
||||
void)
|
||||
uint16_t bip6_get_port(void)
|
||||
{
|
||||
return BIP6_Addr.port;
|
||||
}
|
||||
@@ -143,8 +137,7 @@ uint16_t bip6_get_port(
|
||||
*
|
||||
* @param addr - IPv6 source address
|
||||
*/
|
||||
void bip6_get_broadcast_address(
|
||||
BACNET_ADDRESS * addr)
|
||||
void bip6_get_broadcast_address(BACNET_ADDRESS *addr)
|
||||
{
|
||||
if (addr) {
|
||||
addr->net = BACNET_BROADCAST_NETWORK;
|
||||
@@ -158,8 +151,7 @@ void bip6_get_broadcast_address(
|
||||
*
|
||||
* @param addr - IPv6 source address
|
||||
*/
|
||||
void bip6_get_my_address(
|
||||
BACNET_ADDRESS * addr)
|
||||
void bip6_get_my_address(BACNET_ADDRESS *addr)
|
||||
{
|
||||
uint32_t device_id = 0;
|
||||
|
||||
@@ -174,8 +166,7 @@ void bip6_get_my_address(
|
||||
*
|
||||
* @param addr - network IPv6 address
|
||||
*/
|
||||
bool bip6_set_addr(
|
||||
BACNET_IP6_ADDRESS *addr)
|
||||
bool bip6_set_addr(BACNET_IP6_ADDRESS *addr)
|
||||
{
|
||||
return bvlc6_address_copy(&BIP6_Addr, addr);
|
||||
}
|
||||
@@ -185,8 +176,7 @@ bool bip6_set_addr(
|
||||
*
|
||||
* @return BACnet/IP address
|
||||
*/
|
||||
bool bip6_get_addr(
|
||||
BACNET_IP6_ADDRESS *addr)
|
||||
bool bip6_get_addr(BACNET_IP6_ADDRESS *addr)
|
||||
{
|
||||
return bvlc6_address_copy(addr, &BIP6_Addr);
|
||||
}
|
||||
@@ -196,8 +186,7 @@ bool bip6_get_addr(
|
||||
*
|
||||
* @param addr - network IPv6 address
|
||||
*/
|
||||
bool bip6_set_broadcast_addr(
|
||||
BACNET_IP6_ADDRESS *addr)
|
||||
bool bip6_set_broadcast_addr(BACNET_IP6_ADDRESS *addr)
|
||||
{
|
||||
return bvlc6_address_copy(&BIP6_Broadcast_Addr, addr);
|
||||
}
|
||||
@@ -207,8 +196,7 @@ bool bip6_set_broadcast_addr(
|
||||
*
|
||||
* @return BACnet/IP address
|
||||
*/
|
||||
bool bip6_get_broadcast_addr(
|
||||
BACNET_IP6_ADDRESS *addr)
|
||||
bool bip6_get_broadcast_addr(BACNET_IP6_ADDRESS *addr)
|
||||
{
|
||||
return bvlc6_address_copy(addr, &BIP6_Broadcast_Addr);
|
||||
}
|
||||
@@ -224,10 +212,7 @@ bool bip6_get_broadcast_addr(
|
||||
* @return Upon successful completion, returns the number of bytes sent.
|
||||
* Otherwise, -1 shall be returned and errno set to indicate the error.
|
||||
*/
|
||||
int bip6_send_mpdu(
|
||||
BACNET_IP6_ADDRESS *dest,
|
||||
uint8_t * mtu,
|
||||
uint16_t mtu_len)
|
||||
int bip6_send_mpdu(BACNET_IP6_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len)
|
||||
{
|
||||
struct sockaddr_in6 bvlc_dest = { 0 };
|
||||
uint16_t addr16[8];
|
||||
@@ -251,8 +236,8 @@ int bip6_send_mpdu(
|
||||
bvlc_dest.sin6_port = htons(dest->port);
|
||||
debug_print_ipv6("Sending MPDU->", &bvlc_dest.sin6_addr);
|
||||
/* Send the packet */
|
||||
return sendto(BIP6_Socket, (char *) mtu, mtu_len, 0,
|
||||
(struct sockaddr *) &bvlc_dest, sizeof(bvlc_dest));
|
||||
return sendto(BIP6_Socket, (char *)mtu, mtu_len, 0,
|
||||
(struct sockaddr *)&bvlc_dest, sizeof(bvlc_dest));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,17 +271,14 @@ int bip6_send_pdu(BACNET_ADDRESS *dest,
|
||||
* @return Number of bytes received, or 0 if none or timeout.
|
||||
*/
|
||||
uint16_t bip6_receive(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * npdu,
|
||||
uint16_t max_npdu,
|
||||
unsigned timeout)
|
||||
BACNET_ADDRESS *src, uint8_t *npdu, uint16_t max_npdu, unsigned timeout)
|
||||
{
|
||||
uint16_t npdu_len = 0; /* return value */
|
||||
fd_set read_fds;
|
||||
int max = 0;
|
||||
struct timeval select_timeout;
|
||||
struct sockaddr_in6 sin = { 0 };
|
||||
BACNET_IP6_ADDRESS addr = {{ 0 }};
|
||||
BACNET_IP6_ADDRESS addr = { { 0 } };
|
||||
socklen_t sin_len = sizeof(sin);
|
||||
int received_bytes = 0;
|
||||
int offset = 0;
|
||||
@@ -322,9 +304,8 @@ uint16_t bip6_receive(
|
||||
max = BIP6_Socket;
|
||||
/* see if there is a packet for us */
|
||||
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
|
||||
received_bytes =
|
||||
recvfrom(BIP6_Socket, (char *) &npdu[0], max_npdu, 0,
|
||||
(struct sockaddr *) &sin, &sin_len);
|
||||
received_bytes = recvfrom(BIP6_Socket, (char *)&npdu[0], max_npdu, 0,
|
||||
(struct sockaddr *)&sin, &sin_len);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@@ -342,14 +323,10 @@ uint16_t bip6_receive(
|
||||
}
|
||||
/* pass the packet into the BBMD handler */
|
||||
debug_print_ipv6("Received MPDU->", &sin.sin6_addr);
|
||||
bvlc6_address_set(&addr,
|
||||
ntohs(sin.sin6_addr.s6_addr16[0]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[1]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[2]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[3]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[4]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[5]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[6]),
|
||||
bvlc6_address_set(&addr, ntohs(sin.sin6_addr.s6_addr16[0]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[1]), ntohs(sin.sin6_addr.s6_addr16[2]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[3]), ntohs(sin.sin6_addr.s6_addr16[4]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[5]), ntohs(sin.sin6_addr.s6_addr16[6]),
|
||||
ntohs(sin.sin6_addr.s6_addr16[7]));
|
||||
addr.port = ntohs(sin.sin6_port);
|
||||
offset = bvlc6_handler(&addr, src, npdu, received_bytes);
|
||||
@@ -370,9 +347,8 @@ uint16_t bip6_receive(
|
||||
|
||||
/** Cleanup and close out the BACnet/IP services by closing the socket.
|
||||
* @ingroup DLBIP6
|
||||
*/
|
||||
void bip6_cleanup(
|
||||
void)
|
||||
*/
|
||||
void bip6_cleanup(void)
|
||||
{
|
||||
if (BIP6_Socket != -1) {
|
||||
close(BIP6_Socket);
|
||||
@@ -399,11 +375,10 @@ void bip6_cleanup(
|
||||
* @return True if the socket is successfully opened for BACnet/IP,
|
||||
* else False if the socket functions fail.
|
||||
*/
|
||||
bool bip6_init(
|
||||
char *ifname)
|
||||
bool bip6_init(char *ifname)
|
||||
{
|
||||
int status = 0; /* return from socket lib calls */
|
||||
struct sockaddr_in6 server = {0};
|
||||
int status = 0; /* return from socket lib calls */
|
||||
struct sockaddr_in6 server = { 0 };
|
||||
struct in6_addr broadcast_address;
|
||||
struct ipv6_mreq join_request;
|
||||
int sockopt = 0;
|
||||
@@ -418,9 +393,8 @@ bool bip6_init(
|
||||
}
|
||||
debug_printf("BIP6: IPv6 UDP port: 0x%04X\n", htons(BIP6_Addr.port));
|
||||
if (BIP6_Broadcast_Addr.address[0] == 0) {
|
||||
bvlc6_address_set(&BIP6_Broadcast_Addr,
|
||||
BIP6_MULTICAST_SITE_LOCAL, 0, 0, 0, 0, 0, 0,
|
||||
BIP6_MULTICAST_GROUP_ID);
|
||||
bvlc6_address_set(&BIP6_Broadcast_Addr, BIP6_MULTICAST_SITE_LOCAL, 0, 0,
|
||||
0, 0, 0, 0, BIP6_MULTICAST_GROUP_ID);
|
||||
}
|
||||
/* assumes that the driver has already been initialized */
|
||||
BIP6_Socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
@@ -429,26 +403,26 @@ bool bip6_init(
|
||||
/* Allow us to use the same socket for sending and receiving */
|
||||
/* This makes sure that the src port is correct when sending */
|
||||
sockopt = 1;
|
||||
status =
|
||||
setsockopt(BIP6_Socket, SOL_SOCKET, SO_REUSEADDR, &sockopt,
|
||||
sizeof(sockopt));
|
||||
status = setsockopt(
|
||||
BIP6_Socket, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return status;
|
||||
}
|
||||
/* allow us to send a broadcast */
|
||||
status =
|
||||
setsockopt(BIP6_Socket, SOL_SOCKET, SO_BROADCAST, &sockopt,
|
||||
sizeof(sockopt));
|
||||
status = setsockopt(
|
||||
BIP6_Socket, SOL_SOCKET, SO_BROADCAST, &sockopt, sizeof(sockopt));
|
||||
if (status < 0) {
|
||||
close(BIP6_Socket);
|
||||
BIP6_Socket = -1;
|
||||
return false;
|
||||
}
|
||||
/* subscribe to a multicast address */
|
||||
memcpy(&broadcast_address.s6_addr[0], &BIP6_Broadcast_Addr.address[0], IP6_ADDRESS_MAX);
|
||||
memcpy(&join_request.ipv6mr_multiaddr, &broadcast_address, sizeof(struct in6_addr));
|
||||
memcpy(&broadcast_address.s6_addr[0], &BIP6_Broadcast_Addr.address[0],
|
||||
IP6_ADDRESS_MAX);
|
||||
memcpy(&join_request.ipv6mr_multiaddr, &broadcast_address,
|
||||
sizeof(struct in6_addr));
|
||||
/* Let system choose the interface */
|
||||
join_request.ipv6mr_interface = 0;
|
||||
status = setsockopt(BIP6_Socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
@@ -461,7 +435,7 @@ bool bip6_init(
|
||||
server.sin6_family = AF_INET6;
|
||||
server.sin6_addr = in6addr_any;
|
||||
server.sin6_port = htons(BIP6_Addr.port);
|
||||
status = bind(BIP6_Socket, (const void*)&server, sizeof(server));
|
||||
status = bind(BIP6_Socket, (const void *)&server, sizeof(server));
|
||||
if (status < 0) {
|
||||
perror("BIP: bind");
|
||||
close(BIP6_Socket);
|
||||
|
||||
@@ -27,11 +27,10 @@
|
||||
* @param true if DST is enabled and active
|
||||
* @return true if local time was retrieved
|
||||
*/
|
||||
bool datetime_local(
|
||||
BACNET_DATE * bdate,
|
||||
BACNET_TIME * btime,
|
||||
int16_t * utc_offset_minutes,
|
||||
bool * dst_active)
|
||||
bool datetime_local(BACNET_DATE *bdate,
|
||||
BACNET_TIME *btime,
|
||||
int16_t *utc_offset_minutes,
|
||||
bool *dst_active)
|
||||
{
|
||||
bool status = false;
|
||||
struct tm *tblock = NULL;
|
||||
@@ -54,11 +53,10 @@ bool datetime_local(
|
||||
* int tm_isdst Daylight Savings flag.
|
||||
*/
|
||||
datetime_set_date(bdate, (uint16_t)tblock->tm_year + 1900,
|
||||
(uint8_t)tblock->tm_mon + 1,
|
||||
(uint8_t)tblock->tm_mday);
|
||||
(uint8_t)tblock->tm_mon + 1, (uint8_t)tblock->tm_mday);
|
||||
datetime_set_time(btime, (uint8_t)tblock->tm_hour,
|
||||
(uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec,
|
||||
(uint8_t)(tv.tv_usec / 10000));
|
||||
(uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec,
|
||||
(uint8_t)(tv.tv_usec / 10000));
|
||||
if (dst_active) {
|
||||
/* The value of tm_isdst is:
|
||||
- positive if Daylight Saving Time is in effect,
|
||||
|
||||
+140
-162
@@ -1,28 +1,28 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Updated by Nikola Jelic 2011 <nikola.jelic@euroicc.com>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||
* Updated by Nikola Jelic 2011 <nikola.jelic@euroicc.com>
|
||||
*
|
||||
* 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 <stddef.h>
|
||||
@@ -42,7 +42,8 @@
|
||||
/* OS Specific include */
|
||||
#include "bacport.h"
|
||||
|
||||
/** @file linux/dlmstp.c Provides Linux-specific DataLink functions for MS/TP. */
|
||||
/** @file linux/dlmstp.c Provides Linux-specific DataLink functions for MS/TP.
|
||||
*/
|
||||
|
||||
/* Number of MS/TP Packets Rx/Tx */
|
||||
uint16_t MSTP_Packets = 0;
|
||||
@@ -108,24 +109,23 @@ static struct timespec start;
|
||||
*
|
||||
* @returns True if the difference is negative, otherwise 0.
|
||||
*/
|
||||
static int timespec_subtract(struct timespec *result,
|
||||
const struct timespec *l,
|
||||
const struct timespec *r)
|
||||
static int timespec_subtract(
|
||||
struct timespec *result, const struct timespec *l, const struct timespec *r)
|
||||
{
|
||||
# define NS_PER_S 1000000000 // nano-seconds per second
|
||||
#define NS_PER_S 1000000000 // nano-seconds per second
|
||||
struct timespec right = *r;
|
||||
int secs;
|
||||
|
||||
// Perform the carry for the later subtraction by updating y.
|
||||
if (l->tv_nsec < right.tv_nsec) {
|
||||
secs = (right.tv_nsec - l->tv_nsec) / NS_PER_S + 1;
|
||||
right.tv_nsec -= NS_PER_S * secs;
|
||||
right.tv_sec += secs;
|
||||
secs = (right.tv_nsec - l->tv_nsec) / NS_PER_S + 1;
|
||||
right.tv_nsec -= NS_PER_S * secs;
|
||||
right.tv_sec += secs;
|
||||
}
|
||||
if (l->tv_nsec - right.tv_nsec > NS_PER_S) {
|
||||
secs = (l->tv_nsec - right.tv_nsec) / NS_PER_S;
|
||||
right.tv_nsec += NS_PER_S * secs;
|
||||
right.tv_sec -= secs;
|
||||
secs = (l->tv_nsec - right.tv_nsec) / NS_PER_S;
|
||||
right.tv_nsec += NS_PER_S * secs;
|
||||
right.tv_sec -= secs;
|
||||
}
|
||||
|
||||
// Compute the time remaining. tv_nsec is certainly positive.
|
||||
@@ -144,18 +144,17 @@ static int timespec_subtract(struct timespec *result,
|
||||
*/
|
||||
static void timespec_add_ns(struct timespec *ts, long ns)
|
||||
{
|
||||
ts->tv_nsec += ns;
|
||||
if (ts->tv_nsec > NS_PER_S) {
|
||||
ts->tv_nsec -= NS_PER_S;
|
||||
ts->tv_sec += 1;
|
||||
} else if (ts->tv_nsec < 0) {
|
||||
ts->tv_nsec += NS_PER_S;
|
||||
ts->tv_sec -= 1;
|
||||
}
|
||||
ts->tv_nsec += ns;
|
||||
if (ts->tv_nsec > NS_PER_S) {
|
||||
ts->tv_nsec -= NS_PER_S;
|
||||
ts->tv_sec += 1;
|
||||
} else if (ts->tv_nsec < 0) {
|
||||
ts->tv_nsec += NS_PER_S;
|
||||
ts->tv_sec -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t Timer_Silence(
|
||||
void *pArg)
|
||||
static uint32_t Timer_Silence(void *pArg)
|
||||
{
|
||||
struct timespec now, diff;
|
||||
int32_t res;
|
||||
@@ -167,27 +166,23 @@ static uint32_t Timer_Silence(
|
||||
return (res >= 0 ? res : 0);
|
||||
}
|
||||
|
||||
static void Timer_Silence_Reset(
|
||||
void *pArg)
|
||||
static void Timer_Silence_Reset(void *pArg)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
}
|
||||
|
||||
static void get_abstime(
|
||||
struct timespec *abstime,
|
||||
unsigned long milliseconds)
|
||||
static void get_abstime(struct timespec *abstime, unsigned long milliseconds)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, abstime);
|
||||
if (milliseconds > 1000) {
|
||||
fprintf(stderr, "DLMSTP: limited timeout of %lums to 1000ms\n",
|
||||
milliseconds);
|
||||
milliseconds = 1000;
|
||||
fprintf(stderr, "DLMSTP: limited timeout of %lums to 1000ms\n",
|
||||
milliseconds);
|
||||
milliseconds = 1000;
|
||||
}
|
||||
timespec_add_ns(abstime, 1000000 * milliseconds);
|
||||
}
|
||||
|
||||
void dlmstp_cleanup(
|
||||
void)
|
||||
void dlmstp_cleanup(void)
|
||||
{
|
||||
pthread_cond_destroy(&Received_Frame_Flag);
|
||||
pthread_cond_destroy(&Receive_Packet_Flag);
|
||||
@@ -198,17 +193,16 @@ void dlmstp_cleanup(
|
||||
}
|
||||
|
||||
/* returns number of bytes sent on success, zero on failure */
|
||||
int dlmstp_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int dlmstp_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int bytes_sent = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
unsigned i = 0;
|
||||
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Data_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Data_Peek(&PDU_Queue);
|
||||
if (pkt) {
|
||||
pkt->data_expecting_reply = npdu_data->data_expecting_reply;
|
||||
for (i = 0; i < pdu_len; i++) {
|
||||
@@ -229,22 +223,21 @@ int dlmstp_send_pdu(
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
uint16_t dlmstp_receive(
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t dlmstp_receive(BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0;
|
||||
struct timespec abstime;
|
||||
|
||||
(void) max_pdu;
|
||||
(void)max_pdu;
|
||||
/* see if there is a packet available, and a place
|
||||
to put the reply (if necessary) and process it */
|
||||
pthread_mutex_lock(&Receive_Packet_Mutex);
|
||||
get_abstime(&abstime, timeout);
|
||||
pthread_cond_timedwait(&Receive_Packet_Flag, &Receive_Packet_Mutex,
|
||||
&abstime);
|
||||
pthread_cond_timedwait(
|
||||
&Receive_Packet_Flag, &Receive_Packet_Mutex, &abstime);
|
||||
if (Receive_Packet.ready) {
|
||||
if (Receive_Packet.pdu_len) {
|
||||
MSTP_Packets++;
|
||||
@@ -253,8 +246,7 @@ uint16_t dlmstp_receive(
|
||||
sizeof(Receive_Packet.address));
|
||||
}
|
||||
if (pdu) {
|
||||
memmove(pdu, &Receive_Packet.pdu,
|
||||
sizeof(Receive_Packet.pdu));
|
||||
memmove(pdu, &Receive_Packet.pdu, sizeof(Receive_Packet.pdu));
|
||||
}
|
||||
pdu_len = Receive_Packet.pdu_len;
|
||||
}
|
||||
@@ -265,13 +257,12 @@ uint16_t dlmstp_receive(
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
static void *dlmstp_master_fsm_task(
|
||||
void *pArg)
|
||||
static void *dlmstp_master_fsm_task(void *pArg)
|
||||
{
|
||||
uint32_t silence = 0;
|
||||
bool run_master = false;
|
||||
|
||||
(void) pArg;
|
||||
(void)pArg;
|
||||
for (;;) {
|
||||
if (MSTP_Port.ReceivedValidFrame == false &&
|
||||
MSTP_Port.ReceivedInvalidFrame == false) {
|
||||
@@ -314,9 +305,7 @@ static void *dlmstp_master_fsm_task(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dlmstp_fill_bacnet_address(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t mstp_address)
|
||||
void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -340,8 +329,7 @@ void dlmstp_fill_bacnet_address(
|
||||
}
|
||||
|
||||
/* for the MS/TP state machine to use for putting received data */
|
||||
uint16_t MSTP_Put_Receive(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
|
||||
@@ -357,10 +345,10 @@ uint16_t MSTP_Put_Receive(
|
||||
if (pdu_len == 0) {
|
||||
debug_printf("MS/TP: PDU Length is 0!\n");
|
||||
}
|
||||
memmove((void *) &Receive_Packet.pdu[0],
|
||||
(void *) &mstp_port->InputBuffer[0], pdu_len);
|
||||
dlmstp_fill_bacnet_address(&Receive_Packet.address,
|
||||
mstp_port->SourceAddress);
|
||||
memmove((void *)&Receive_Packet.pdu[0],
|
||||
(void *)&mstp_port->InputBuffer[0], pdu_len);
|
||||
dlmstp_fill_bacnet_address(
|
||||
&Receive_Packet.address, mstp_port->SourceAddress);
|
||||
Receive_Packet.pdu_len = mstp_port->DataLength;
|
||||
Receive_Packet.ready = true;
|
||||
pthread_cond_signal(&Receive_Packet_Flag);
|
||||
@@ -373,37 +361,36 @@ uint16_t MSTP_Put_Receive(
|
||||
/* for the MS/TP state machine to use for getting data to send */
|
||||
/* Return: amount of PDU data */
|
||||
uint16_t MSTP_Get_Send(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0;
|
||||
uint8_t frame_type = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
|
||||
(void) timeout;
|
||||
(void)timeout;
|
||||
if (Ringbuf_Empty(&PDU_Queue)) {
|
||||
return 0;
|
||||
}
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
if (pkt->data_expecting_reply) {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
|
||||
} else {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
/* convert the PDU into the MSTP Frame */
|
||||
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
pdu_len =
|
||||
MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
static bool dlmstp_compare_data_expecting_reply(
|
||||
uint8_t * request_pdu,
|
||||
static bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
uint16_t request_pdu_len,
|
||||
uint8_t src_address,
|
||||
uint8_t * reply_pdu,
|
||||
uint8_t *reply_pdu,
|
||||
uint16_t reply_pdu_len,
|
||||
uint8_t dest_address)
|
||||
{
|
||||
@@ -427,13 +414,13 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the request data */
|
||||
request.address.mac[0] = src_address;
|
||||
request.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&request_pdu[0], NULL, &request.address,
|
||||
&request.npdu_data);
|
||||
offset = npdu_decode(
|
||||
&request_pdu[0], NULL, &request.address, &request.npdu_data);
|
||||
if (request.npdu_data.network_layer_message) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Request is Network message.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Request is Network message.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -441,7 +428,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
if (request.pdu_type != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Not Confirmed Request.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Not Confirmed Request.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -455,12 +443,12 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the reply data */
|
||||
reply.address.mac[0] = dest_address;
|
||||
reply.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
offset = npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
if (reply.npdu_data.network_layer_message) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Reply is Network message.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Reply is Network message.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -498,7 +486,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
if (request.invoke_id != reply.invoke_id) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Invoke ID mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Invoke ID mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -506,19 +495,22 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
if (request.invoke_id != reply.invoke_id) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Invoke ID mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Invoke ID mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (request.service_choice != reply.service_choice) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Service choice mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Service choice mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (request.npdu_data.protocol_version != reply.npdu_data.protocol_version) {
|
||||
if (request.npdu_data.protocol_version !=
|
||||
reply.npdu_data.protocol_version) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: "
|
||||
@@ -540,7 +532,8 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
if (!bacnet_address_same(&request.address, &reply.address)) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "BACnet Address mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"BACnet Address mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -550,24 +543,22 @@ static bool dlmstp_compare_data_expecting_reply(
|
||||
|
||||
/* Get the reply to a DATA_EXPECTING_REPLY frame, or nothing */
|
||||
uint16_t MSTP_Get_Reply(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
bool matched = false;
|
||||
uint8_t frame_type = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
|
||||
(void) timeout;
|
||||
(void)timeout;
|
||||
if (Ringbuf_Empty(&PDU_Queue)) {
|
||||
return 0;
|
||||
}
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&PDU_Queue);
|
||||
/* is this the reply to the DER? */
|
||||
matched =
|
||||
dlmstp_compare_data_expecting_reply(&mstp_port->InputBuffer[0],
|
||||
matched = dlmstp_compare_data_expecting_reply(&mstp_port->InputBuffer[0],
|
||||
mstp_port->DataLength, mstp_port->SourceAddress,
|
||||
(uint8_t *) & pkt->buffer[0], pkt->length, pkt->destination_mac);
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length, pkt->destination_mac);
|
||||
if (!matched) {
|
||||
return 0;
|
||||
}
|
||||
@@ -577,16 +568,16 @@ uint16_t MSTP_Get_Reply(
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
/* convert the PDU into the MSTP Frame */
|
||||
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(void) Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
pdu_len =
|
||||
MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
(void)Ringbuf_Pop(&PDU_Queue, NULL);
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void dlmstp_set_mac_address(
|
||||
uint8_t mac_address)
|
||||
void dlmstp_set_mac_address(uint8_t mac_address)
|
||||
{
|
||||
/* Master Nodes can only have address 0-127 */
|
||||
if (mac_address <= 127) {
|
||||
@@ -603,8 +594,7 @@ void dlmstp_set_mac_address(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_mac_address(
|
||||
void)
|
||||
uint8_t dlmstp_mac_address(void)
|
||||
{
|
||||
return MSTP_Port.This_Station;
|
||||
}
|
||||
@@ -616,8 +606,7 @@ uint8_t dlmstp_mac_address(
|
||||
/* nodes. This may be used to allocate more or less of the available link */
|
||||
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
||||
/* node, its value shall be 1. */
|
||||
void dlmstp_set_max_info_frames(
|
||||
uint8_t max_info_frames)
|
||||
void dlmstp_set_max_info_frames(uint8_t max_info_frames)
|
||||
{
|
||||
if (max_info_frames >= 1) {
|
||||
MSTP_Port.Nmax_info_frames = max_info_frames;
|
||||
@@ -631,8 +620,7 @@ void dlmstp_set_max_info_frames(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_info_frames(
|
||||
void)
|
||||
uint8_t dlmstp_max_info_frames(void)
|
||||
{
|
||||
return MSTP_Port.Nmax_info_frames;
|
||||
}
|
||||
@@ -642,8 +630,7 @@ uint8_t dlmstp_max_info_frames(
|
||||
/* allowable address for master nodes. The value of Max_Master shall be */
|
||||
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
||||
/* its value shall be 127. */
|
||||
void dlmstp_set_max_master(
|
||||
uint8_t max_master)
|
||||
void dlmstp_set_max_master(uint8_t max_master)
|
||||
{
|
||||
if (max_master <= 127) {
|
||||
if (MSTP_Port.This_Station <= max_master) {
|
||||
@@ -659,33 +646,29 @@ void dlmstp_set_max_master(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_master(
|
||||
void)
|
||||
uint8_t dlmstp_max_master(void)
|
||||
{
|
||||
return MSTP_Port.Nmax_master;
|
||||
}
|
||||
|
||||
/* RS485 Baud Rate 9600, 19200, 38400, 57600, 115200 */
|
||||
void dlmstp_set_baud_rate(
|
||||
uint32_t baud)
|
||||
void dlmstp_set_baud_rate(uint32_t baud)
|
||||
{
|
||||
RS485_Set_Baud_Rate(baud);
|
||||
}
|
||||
|
||||
uint32_t dlmstp_baud_rate(
|
||||
void)
|
||||
uint32_t dlmstp_baud_rate(void)
|
||||
{
|
||||
return RS485_Get_Baud_Rate();
|
||||
}
|
||||
|
||||
void dlmstp_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void dlmstp_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0; /* counter */
|
||||
int i = 0; /* counter */
|
||||
|
||||
my_address->mac_len = 1;
|
||||
my_address->mac[0] = MSTP_Port.This_Station;
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -694,16 +677,15 @@ void dlmstp_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void dlmstp_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 1;
|
||||
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
@@ -712,8 +694,7 @@ void dlmstp_get_broadcast_address(
|
||||
return;
|
||||
}
|
||||
|
||||
bool dlmstp_init(
|
||||
char *ifname)
|
||||
bool dlmstp_init(char *ifname)
|
||||
{
|
||||
unsigned long hThread = 0;
|
||||
pthread_condattr_t attr;
|
||||
@@ -721,13 +702,13 @@ bool dlmstp_init(
|
||||
|
||||
pthread_condattr_init(&attr);
|
||||
if ((rv = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) != 0) {
|
||||
fprintf(stderr, "MS/TP Interface: %s\n failed to set MONOTONIC clock\n",
|
||||
ifname);
|
||||
exit(1);
|
||||
fprintf(stderr, "MS/TP Interface: %s\n failed to set MONOTONIC clock\n",
|
||||
ifname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* initialize PDU queue */
|
||||
Ringbuf_Init(&PDU_Queue, (uint8_t *) & PDU_Buffer,
|
||||
Ringbuf_Init(&PDU_Queue, (uint8_t *)&PDU_Buffer,
|
||||
sizeof(struct mstp_pdu_packet), MSTP_PDU_PACKET_COUNT);
|
||||
/* initialize packet queue */
|
||||
Receive_Packet.ready = false;
|
||||
@@ -782,21 +763,18 @@ bool dlmstp_init(
|
||||
#ifdef TEST_DLMSTP
|
||||
#include <stdio.h>
|
||||
|
||||
void apdu_handler(
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * apdu, /* APDU data */
|
||||
void apdu_handler(BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *apdu, /* APDU data */
|
||||
uint16_t pdu_len)
|
||||
{ /* for confirmed messages */
|
||||
(void) src;
|
||||
(void) apdu;
|
||||
(void) pdu_len;
|
||||
{ /* for confirmed messages */
|
||||
(void)src;
|
||||
(void)apdu;
|
||||
(void)pdu_len;
|
||||
}
|
||||
|
||||
static char *Network_Interface = NULL;
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
|
||||
|
||||
+205
-245
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2008 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 <stddef.h>
|
||||
@@ -41,24 +41,28 @@
|
||||
#include "bacport.h"
|
||||
#include "bacnet/basic/sys/ringbuf.h"
|
||||
|
||||
/** @file linux/dlmstp.c Provides Linux-specific DataLink functions for MS/TP. */
|
||||
/** @file linux/dlmstp.c Provides Linux-specific DataLink functions for MS/TP.
|
||||
*/
|
||||
|
||||
#define BACNET_PDU_CONTROL_BYTE_OFFSET 1
|
||||
#define BACNET_DATA_EXPECTING_REPLY_BIT 2
|
||||
#define BACNET_DATA_EXPECTING_REPLY(control) ( (control & (1 << BACNET_DATA_EXPECTING_REPLY_BIT) ) > 0 )
|
||||
#define BACNET_DATA_EXPECTING_REPLY(control) \
|
||||
((control & (1 << BACNET_DATA_EXPECTING_REPLY_BIT)) > 0)
|
||||
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
|
||||
uint32_t Timer_Silence(
|
||||
void *poPort)
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) \
|
||||
{ \
|
||||
if (x < 0xFFFF) \
|
||||
x++; \
|
||||
}
|
||||
uint32_t Timer_Silence(void *poPort)
|
||||
{
|
||||
struct timeval now, tmp_diff;
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return -1;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return -1;
|
||||
}
|
||||
@@ -72,16 +76,14 @@ uint32_t Timer_Silence(
|
||||
return (res >= 0 ? res : -res);
|
||||
}
|
||||
|
||||
void Timer_Silence_Reset(
|
||||
void *poPort)
|
||||
void Timer_Silence_Reset(void *poPort)
|
||||
{
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return;
|
||||
}
|
||||
@@ -89,9 +91,7 @@ void Timer_Silence_Reset(
|
||||
gettimeofday(&poSharedData->start, NULL);
|
||||
}
|
||||
|
||||
void get_abstime(
|
||||
struct timespec *abstime,
|
||||
unsigned long milliseconds)
|
||||
void get_abstime(struct timespec *abstime, unsigned long milliseconds)
|
||||
{
|
||||
struct timeval now, offset, result;
|
||||
|
||||
@@ -103,23 +103,20 @@ void get_abstime(
|
||||
abstime->tv_nsec = result.tv_usec * 1000;
|
||||
}
|
||||
|
||||
void dlmstp_cleanup(
|
||||
void *poPort)
|
||||
void dlmstp_cleanup(void *poPort)
|
||||
{
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* restore the old port settings */
|
||||
tcsetattr(poSharedData->RS485_Handle, TCSANOW,
|
||||
&poSharedData->RS485_oldtio);
|
||||
tcsetattr(poSharedData->RS485_Handle, TCSANOW, &poSharedData->RS485_oldtio);
|
||||
close(poSharedData->RS485_Handle);
|
||||
|
||||
pthread_cond_destroy(&poSharedData->Received_Frame_Flag);
|
||||
@@ -130,27 +127,25 @@ void dlmstp_cleanup(
|
||||
}
|
||||
|
||||
/* returns number of bytes sent on success, zero on failure */
|
||||
int dlmstp_send_pdu(
|
||||
void *poPort,
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int dlmstp_send_pdu(void *poPort,
|
||||
BACNET_ADDRESS *dest, /* destination address */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int bytes_sent = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
unsigned i = 0;
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return 0;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Data_Peek(&poSharedData->PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Data_Peek(&poSharedData->PDU_Queue);
|
||||
if (pkt) {
|
||||
pkt->data_expecting_reply =
|
||||
BACNET_DATA_EXPECTING_REPLY(pdu[BACNET_PDU_CONTROL_BYTE_OFFSET]);
|
||||
@@ -167,27 +162,25 @@ int dlmstp_send_pdu(
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
uint16_t dlmstp_receive(
|
||||
void *poPort,
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t dlmstp_receive(void *poPort,
|
||||
BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0;
|
||||
struct timespec abstime;
|
||||
int rv = 0;
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return 0;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return 0;
|
||||
}
|
||||
(void) max_pdu;
|
||||
(void)max_pdu;
|
||||
/* see if there is a packet available, and a place
|
||||
to put the reply (if necessary) and process it */
|
||||
get_abstime(&abstime, timeout);
|
||||
@@ -213,18 +206,17 @@ uint16_t dlmstp_receive(
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void *dlmstp_receive_fsm_task(
|
||||
void *pArg)
|
||||
void *dlmstp_receive_fsm_task(void *pArg)
|
||||
{
|
||||
bool received_frame;
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *) pArg;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)pArg;
|
||||
if (!mstp_port) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
poSharedData =
|
||||
(SHARED_MSTP_DATA *) ((struct mstp_port_struct_t *) pArg)->UserData;
|
||||
(SHARED_MSTP_DATA *)((struct mstp_port_struct_t *)pArg)->UserData;
|
||||
if (!poSharedData) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -235,8 +227,8 @@ void *dlmstp_receive_fsm_task(
|
||||
(mstp_port->ReceivedInvalidFrame == false)) {
|
||||
do {
|
||||
RS485_Check_UART_Data(mstp_port);
|
||||
MSTP_Receive_Frame_FSM((volatile struct mstp_port_struct_t *)
|
||||
pArg);
|
||||
MSTP_Receive_Frame_FSM(
|
||||
(volatile struct mstp_port_struct_t *)pArg);
|
||||
received_frame = mstp_port->ReceivedValidFrame ||
|
||||
mstp_port->ReceivedInvalidFrame;
|
||||
if (received_frame) {
|
||||
@@ -250,19 +242,18 @@ void *dlmstp_receive_fsm_task(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *dlmstp_master_fsm_task(
|
||||
void *pArg)
|
||||
void *dlmstp_master_fsm_task(void *pArg)
|
||||
{
|
||||
uint32_t silence = 0;
|
||||
bool run_master = false;
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *) pArg;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)pArg;
|
||||
if (!mstp_port) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
poSharedData =
|
||||
(SHARED_MSTP_DATA *) ((struct mstp_port_struct_t *) pArg)->UserData;
|
||||
(SHARED_MSTP_DATA *)((struct mstp_port_struct_t *)pArg)->UserData;
|
||||
if (!poSharedData) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -309,9 +300,7 @@ void *dlmstp_master_fsm_task(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dlmstp_fill_bacnet_address(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t mstp_address)
|
||||
void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -335,11 +324,10 @@ void dlmstp_fill_bacnet_address(
|
||||
}
|
||||
|
||||
/* for the MS/TP state machine to use for putting received data */
|
||||
uint16_t MSTP_Put_Receive(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
|
||||
if (!poSharedData) {
|
||||
return 0;
|
||||
@@ -350,10 +338,10 @@ uint16_t MSTP_Put_Receive(
|
||||
pdu_len = mstp_port->DataLength;
|
||||
if (pdu_len > sizeof(poSharedData->Receive_Packet.pdu))
|
||||
pdu_len = sizeof(poSharedData->Receive_Packet.pdu);
|
||||
memmove((void *) &poSharedData->Receive_Packet.pdu[0],
|
||||
(void *) &mstp_port->InputBuffer[0], pdu_len);
|
||||
dlmstp_fill_bacnet_address(&poSharedData->Receive_Packet.address,
|
||||
mstp_port->SourceAddress);
|
||||
memmove((void *)&poSharedData->Receive_Packet.pdu[0],
|
||||
(void *)&mstp_port->InputBuffer[0], pdu_len);
|
||||
dlmstp_fill_bacnet_address(
|
||||
&poSharedData->Receive_Packet.address, mstp_port->SourceAddress);
|
||||
poSharedData->Receive_Packet.pdu_len = mstp_port->DataLength;
|
||||
poSharedData->Receive_Packet.ready = true;
|
||||
sem_post(&poSharedData->Receive_Packet_Flag);
|
||||
@@ -365,42 +353,41 @@ uint16_t MSTP_Put_Receive(
|
||||
/* for the MS/TP state machine to use for getting data to send */
|
||||
/* Return: amount of PDU data */
|
||||
uint16_t MSTP_Get_Send(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0;
|
||||
uint8_t frame_type = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
|
||||
if (!poSharedData) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) timeout;
|
||||
(void)timeout;
|
||||
if (Ringbuf_Empty(&poSharedData->PDU_Queue)) {
|
||||
return 0;
|
||||
}
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&poSharedData->PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&poSharedData->PDU_Queue);
|
||||
if (pkt->data_expecting_reply) {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
|
||||
} else {
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
/* convert the PDU into the MSTP Frame */
|
||||
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
(void) Ringbuf_Pop(&poSharedData->PDU_Queue, NULL);
|
||||
pdu_len =
|
||||
MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
(void)Ringbuf_Pop(&poSharedData->PDU_Queue, NULL);
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
bool dlmstp_compare_data_expecting_reply(
|
||||
uint8_t * request_pdu,
|
||||
bool dlmstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
uint16_t request_pdu_len,
|
||||
uint8_t src_address,
|
||||
uint8_t * reply_pdu,
|
||||
uint8_t *reply_pdu,
|
||||
uint16_t reply_pdu_len,
|
||||
uint8_t dest_address)
|
||||
{
|
||||
@@ -424,13 +411,13 @@ bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the request data */
|
||||
request.address.mac[0] = src_address;
|
||||
request.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&request_pdu[0], NULL, &request.address,
|
||||
&request.npdu_data);
|
||||
offset = npdu_decode(
|
||||
&request_pdu[0], NULL, &request.address, &request.npdu_data);
|
||||
if (request.npdu_data.network_layer_message) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Request is Network message.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Request is Network message.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -438,7 +425,8 @@ bool dlmstp_compare_data_expecting_reply(
|
||||
if (request.pdu_type != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Not Confirmed Request.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Not Confirmed Request.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -452,12 +440,12 @@ bool dlmstp_compare_data_expecting_reply(
|
||||
/* decode the reply data */
|
||||
reply.address.mac[0] = dest_address;
|
||||
reply.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
offset = npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
if (reply.npdu_data.network_layer_message) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Reply is Network message.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Reply is Network message.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -495,7 +483,8 @@ bool dlmstp_compare_data_expecting_reply(
|
||||
if (request.invoke_id != reply.invoke_id) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Invoke ID mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Invoke ID mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -503,19 +492,22 @@ bool dlmstp_compare_data_expecting_reply(
|
||||
if (request.invoke_id != reply.invoke_id) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Invoke ID mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Invoke ID mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (request.service_choice != reply.service_choice) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "Service choice mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"Service choice mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (request.npdu_data.protocol_version != reply.npdu_data.protocol_version) {
|
||||
if (request.npdu_data.protocol_version !=
|
||||
reply.npdu_data.protocol_version) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: "
|
||||
@@ -537,7 +529,8 @@ bool dlmstp_compare_data_expecting_reply(
|
||||
if (!bacnet_address_same(&request.address, &reply.address)) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"DLMSTP: DER Compare failed: " "BACnet Address mismatch.\n");
|
||||
"DLMSTP: DER Compare failed: "
|
||||
"BACnet Address mismatch.\n");
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -547,14 +540,13 @@ bool dlmstp_compare_data_expecting_reply(
|
||||
|
||||
/* Get the reply to a DATA_EXPECTING_REPLY frame, or nothing */
|
||||
uint16_t MSTP_Get_Reply(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
bool matched = false;
|
||||
uint8_t frame_type = 0;
|
||||
struct mstp_pdu_packet *pkt;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
|
||||
if (!poSharedData) {
|
||||
return 0;
|
||||
@@ -563,23 +555,20 @@ uint16_t MSTP_Get_Reply(
|
||||
if (Ringbuf_Empty(&poSharedData->PDU_Queue)) {
|
||||
return 0;
|
||||
}
|
||||
pkt = (struct mstp_pdu_packet *) Ringbuf_Peek(&poSharedData->PDU_Queue);
|
||||
pkt = (struct mstp_pdu_packet *)Ringbuf_Peek(&poSharedData->PDU_Queue);
|
||||
/* is this the reply to the DER? */
|
||||
matched =
|
||||
dlmstp_compare_data_expecting_reply(&mstp_port->InputBuffer[0],
|
||||
matched = dlmstp_compare_data_expecting_reply(&mstp_port->InputBuffer[0],
|
||||
mstp_port->DataLength, mstp_port->SourceAddress,
|
||||
(uint8_t *) & pkt->buffer[0], pkt->length, pkt->destination_mac);
|
||||
(uint8_t *)&pkt->buffer[0], pkt->length, pkt->destination_mac);
|
||||
if (!matched) {
|
||||
/* Walk the rest of the ring buffer to see if we can find a match */
|
||||
while (!matched &&
|
||||
(pkt = (struct mstp_pdu_packet *)Ringbuf_Peek_Next(&poSharedData->PDU_Queue, (uint8_t *)pkt)) != NULL) {
|
||||
matched =
|
||||
dlmstp_compare_data_expecting_reply(&mstp_port->InputBuffer[0],
|
||||
mstp_port->DataLength,
|
||||
mstp_port->SourceAddress,
|
||||
(uint8_t *) & pkt->buffer[0],
|
||||
pkt->length,
|
||||
pkt->destination_mac);
|
||||
(pkt = (struct mstp_pdu_packet *)Ringbuf_Peek_Next(
|
||||
&poSharedData->PDU_Queue, (uint8_t *)pkt)) != NULL) {
|
||||
matched = dlmstp_compare_data_expecting_reply(
|
||||
&mstp_port->InputBuffer[0], mstp_port->DataLength,
|
||||
mstp_port->SourceAddress, (uint8_t *)&pkt->buffer[0],
|
||||
pkt->length, pkt->destination_mac);
|
||||
}
|
||||
if (!matched) {
|
||||
/* Still didn't find a match so just bail out */
|
||||
@@ -592,32 +581,30 @@ uint16_t MSTP_Get_Reply(
|
||||
frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
|
||||
}
|
||||
/* convert the PDU into the MSTP Frame */
|
||||
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *) & pkt->buffer[0], pkt->length);
|
||||
pdu_len =
|
||||
MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
|
||||
mstp_port->OutputBufferSize, frame_type, pkt->destination_mac,
|
||||
mstp_port->This_Station, (uint8_t *)&pkt->buffer[0], pkt->length);
|
||||
/* This will pop the element no matter where we found it */
|
||||
(void) Ringbuf_Pop_Element(&poSharedData->PDU_Queue, (uint8_t *)pkt, NULL);
|
||||
(void)Ringbuf_Pop_Element(&poSharedData->PDU_Queue, (uint8_t *)pkt, NULL);
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void dlmstp_set_mac_address(
|
||||
void *poPort,
|
||||
uint8_t mac_address)
|
||||
void dlmstp_set_mac_address(void *poPort, uint8_t mac_address)
|
||||
{
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
/* Master Nodes can only have address 0-127 */
|
||||
if (mac_address <= 127) {
|
||||
mstp_port->This_Station = mac_address;
|
||||
@@ -633,21 +620,19 @@ void dlmstp_set_mac_address(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_mac_address(
|
||||
void *poPort)
|
||||
uint8_t dlmstp_mac_address(void *poPort)
|
||||
{
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return 0;
|
||||
}
|
||||
/* poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
/* poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
return mstp_port->This_Station;
|
||||
}
|
||||
@@ -659,23 +644,20 @@ uint8_t dlmstp_mac_address(
|
||||
/* nodes. This may be used to allocate more or less of the available link */
|
||||
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
||||
/* node, its value shall be 1. */
|
||||
void dlmstp_set_max_info_frames(
|
||||
void *poPort,
|
||||
uint8_t max_info_frames)
|
||||
void dlmstp_set_max_info_frames(void *poPort, uint8_t max_info_frames)
|
||||
{
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
if (max_info_frames >= 1) {
|
||||
mstp_port->Nmax_info_frames = max_info_frames;
|
||||
/* FIXME: implement your data storage */
|
||||
@@ -688,22 +670,20 @@ void dlmstp_set_max_info_frames(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_info_frames(
|
||||
void *poPort)
|
||||
uint8_t dlmstp_max_info_frames(void *poPort)
|
||||
{
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
return mstp_port->Nmax_info_frames;
|
||||
}
|
||||
|
||||
@@ -712,23 +692,20 @@ uint8_t dlmstp_max_info_frames(
|
||||
/* allowable address for master nodes. The value of Max_Master shall be */
|
||||
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
||||
/* its value shall be 127. */
|
||||
void dlmstp_set_max_master(
|
||||
void *poPort,
|
||||
uint8_t max_master)
|
||||
void dlmstp_set_max_master(void *poPort, uint8_t max_master)
|
||||
{
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
*/
|
||||
if (max_master <= 127) {
|
||||
if (mstp_port->This_Station <= max_master) {
|
||||
mstp_port->Nmax_master = max_master;
|
||||
@@ -743,37 +720,32 @@ void dlmstp_set_max_master(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_master(
|
||||
void *poPort)
|
||||
uint8_t dlmstp_max_master(void *poPort)
|
||||
{
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
/* SHARED_MSTP_DATA * poSharedData; */
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
if(!poSharedData)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
return mstp_port->Nmax_master;
|
||||
}
|
||||
|
||||
/* RS485 Baud Rate 9600, 19200, 38400, 57600, 115200 */
|
||||
void dlmstp_set_baud_rate(
|
||||
void *poPort,
|
||||
uint32_t baud)
|
||||
void dlmstp_set_baud_rate(void *poPort, uint32_t baud)
|
||||
{
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return;
|
||||
}
|
||||
@@ -799,16 +771,14 @@ void dlmstp_set_baud_rate(
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t dlmstp_baud_rate(
|
||||
void *poPort)
|
||||
uint32_t dlmstp_baud_rate(void *poPort)
|
||||
{
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return false;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return false;
|
||||
}
|
||||
@@ -828,24 +798,21 @@ uint32_t dlmstp_baud_rate(
|
||||
}
|
||||
}
|
||||
|
||||
void dlmstp_get_my_address(
|
||||
void *poPort,
|
||||
BACNET_ADDRESS * my_address)
|
||||
void dlmstp_get_my_address(void *poPort, BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0; /* counter */
|
||||
int i = 0; /* counter */
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return;
|
||||
}
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return;
|
||||
}
|
||||
my_address->mac_len = 1;
|
||||
my_address->mac[0] = mstp_port->This_Station;
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -854,16 +821,15 @@ void dlmstp_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void dlmstp_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 1;
|
||||
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
@@ -872,30 +838,26 @@ void dlmstp_get_broadcast_address(
|
||||
return;
|
||||
}
|
||||
|
||||
bool dlmstp_init(
|
||||
void *poPort,
|
||||
char *ifname)
|
||||
bool dlmstp_init(void *poPort, char *ifname)
|
||||
{
|
||||
unsigned long hThread = 0;
|
||||
int rv = 0;
|
||||
SHARED_MSTP_DATA *poSharedData;
|
||||
struct mstp_port_struct_t *mstp_port =
|
||||
(struct mstp_port_struct_t *) poPort;
|
||||
struct mstp_port_struct_t *mstp_port = (struct mstp_port_struct_t *)poPort;
|
||||
if (!mstp_port) {
|
||||
return false;
|
||||
}
|
||||
|
||||
poSharedData = (SHARED_MSTP_DATA *) ((struct mstp_port_struct_t *)
|
||||
mstp_port)->UserData;
|
||||
poSharedData =
|
||||
(SHARED_MSTP_DATA *)((struct mstp_port_struct_t *)mstp_port)->UserData;
|
||||
if (!poSharedData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
poSharedData->RS485_Port_Name = ifname;
|
||||
/* initialize PDU queue */
|
||||
Ringbuf_Init(&poSharedData->PDU_Queue,
|
||||
(uint8_t *) & poSharedData->PDU_Buffer, sizeof(struct mstp_pdu_packet),
|
||||
MSTP_PDU_PACKET_COUNT);
|
||||
Ringbuf_Init(&poSharedData->PDU_Queue, (uint8_t *)&poSharedData->PDU_Buffer,
|
||||
sizeof(struct mstp_pdu_packet), MSTP_PDU_PACKET_COUNT);
|
||||
/* initialize packet queue */
|
||||
poSharedData->Receive_Packet.ready = false;
|
||||
poSharedData->Receive_Packet.pdu_len = 0;
|
||||
@@ -913,9 +875,8 @@ bool dlmstp_init(
|
||||
Open device for reading and writing.
|
||||
Blocking mode - more CPU effecient
|
||||
*/
|
||||
poSharedData->RS485_Handle =
|
||||
open(poSharedData->RS485_Port_Name,
|
||||
O_RDWR | O_NOCTTY | O_NONBLOCK /*| O_NDELAY */ );
|
||||
poSharedData->RS485_Handle = open(poSharedData->RS485_Port_Name,
|
||||
O_RDWR | O_NOCTTY | O_NONBLOCK /*| O_NDELAY */);
|
||||
if (poSharedData->RS485_Handle < 0) {
|
||||
perror(poSharedData->RS485_Port_Name);
|
||||
exit(-1);
|
||||
@@ -966,8 +927,7 @@ bool dlmstp_init(
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "MS/TP MAC: %02X\n", mstp_port->This_Station);
|
||||
fprintf(stderr, "MS/TP Max_Master: %02X\n", mstp_port->Nmax_master);
|
||||
fprintf(stderr, "MS/TP Max_Info_Frames: %u\n",
|
||||
mstp_port->Nmax_info_frames);
|
||||
fprintf(stderr, "MS/TP Max_Info_Frames: %u\n", mstp_port->Nmax_info_frames);
|
||||
#endif
|
||||
|
||||
rv = pthread_create(&hThread, NULL, dlmstp_master_fsm_task, mstp_port);
|
||||
|
||||
+62
-79
@@ -32,36 +32,35 @@
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
|
||||
#include "bacport.h"
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/datalink/ethernet.h"
|
||||
#include "bacnet/bacint.h"
|
||||
|
||||
/** @file linux/ethernet.c Provides Linux-specific functions for BACnet/Ethernet. */
|
||||
/** @file linux/ethernet.c Provides Linux-specific functions for
|
||||
* BACnet/Ethernet. */
|
||||
|
||||
/* commonly used comparison address for ethernet */
|
||||
uint8_t Ethernet_Broadcast[MAX_MAC_LEN] =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
uint8_t Ethernet_Broadcast[MAX_MAC_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF };
|
||||
/* commonly used empty address for ethernet quick compare */
|
||||
uint8_t Ethernet_Empty_MAC[MAX_MAC_LEN] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
/* my local device data - MAC address */
|
||||
uint8_t Ethernet_MAC_Address[MAX_MAC_LEN] = { 0 };
|
||||
|
||||
static int eth802_sockfd = -1; /* 802.2 file handle */
|
||||
static struct sockaddr eth_addr = { 0 }; /* used for binding 802.2 */
|
||||
static int eth802_sockfd = -1; /* 802.2 file handle */
|
||||
static struct sockaddr eth_addr = { 0 }; /* used for binding 802.2 */
|
||||
|
||||
bool ethernet_valid(
|
||||
void)
|
||||
bool ethernet_valid(void)
|
||||
{
|
||||
return (eth802_sockfd >= 0);
|
||||
}
|
||||
|
||||
void ethernet_cleanup(
|
||||
void)
|
||||
void ethernet_cleanup(void)
|
||||
{
|
||||
if (ethernet_valid())
|
||||
close(eth802_sockfd);
|
||||
@@ -92,11 +91,9 @@ int setNonblocking(
|
||||
#endif
|
||||
|
||||
/* opens an 802.2 socket to receive and send packets */
|
||||
static int ethernet_bind(
|
||||
struct sockaddr *eth_addr,
|
||||
char *interface_name)
|
||||
static int ethernet_bind(struct sockaddr *eth_addr, char *interface_name)
|
||||
{
|
||||
int sock_fd = -1; /* return value */
|
||||
int sock_fd = -1; /* return value */
|
||||
#if 0
|
||||
int sockopt = 0;
|
||||
#endif
|
||||
@@ -121,13 +118,14 @@ static int ethernet_bind(
|
||||
/* Attempt to open the socket for 802.2 ethernet frames */
|
||||
if ((sock_fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_802_2))) < 0) {
|
||||
/* Error occured */
|
||||
fprintf(stderr, "ethernet: Error opening socket: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(
|
||||
stderr, "ethernet: Error opening socket: %s\n", strerror(errno));
|
||||
fprintf(stderr,
|
||||
"You might need to add the following to modules.conf\n"
|
||||
"(or in /etc/modutils/alias on Debian with update-modules):\n"
|
||||
"alias net-pf-17 af_packet\n"
|
||||
"Also, add af_packet to /etc/modules.\n" "Then follow it by:\n"
|
||||
"Also, add af_packet to /etc/modules.\n"
|
||||
"Then follow it by:\n"
|
||||
"# modprobe af_packet\n");
|
||||
exit(-1);
|
||||
}
|
||||
@@ -156,7 +154,8 @@ static int ethernet_bind(
|
||||
"You might need to add the following to modules.conf\n"
|
||||
"(or in /etc/modutils/alias on Debian with update-modules):\n"
|
||||
"alias net-pf-17 af_packet\n"
|
||||
"Also, add af_packet to /etc/modules.\n" "Then follow it by:\n"
|
||||
"Also, add af_packet to /etc/modules.\n"
|
||||
"Then follow it by:\n"
|
||||
"# modprobe af_packet\n");
|
||||
/* Close the socket */
|
||||
close(sock_fd);
|
||||
@@ -169,13 +168,11 @@ static int ethernet_bind(
|
||||
}
|
||||
|
||||
/* function to find the local ethernet MAC address */
|
||||
static int get_local_hwaddr(
|
||||
const char *ifname,
|
||||
unsigned char *mac)
|
||||
static int get_local_hwaddr(const char *ifname, unsigned char *mac)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd;
|
||||
int rv; /* return value - error value from df or ioctl call */
|
||||
int rv; /* return value - error value from df or ioctl call */
|
||||
|
||||
/* determine the local MAC address */
|
||||
strcpy(ifr.ifr_name, ifname);
|
||||
@@ -184,15 +181,14 @@ static int get_local_hwaddr(
|
||||
rv = fd;
|
||||
else {
|
||||
rv = ioctl(fd, SIOCGIFHWADDR, &ifr);
|
||||
if (rv >= 0) /* worked okay */
|
||||
if (rv >= 0) /* worked okay */
|
||||
memcpy(mac, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool ethernet_init(
|
||||
char *interface_name)
|
||||
bool ethernet_init(char *interface_name)
|
||||
{
|
||||
if (interface_name) {
|
||||
get_local_hwaddr(interface_name, Ethernet_MAC_Address);
|
||||
@@ -205,40 +201,35 @@ bool ethernet_init(
|
||||
return ethernet_valid();
|
||||
}
|
||||
|
||||
int ethernet_send(
|
||||
uint8_t * mtu,
|
||||
int mtu_len)
|
||||
int ethernet_send(uint8_t *mtu, int mtu_len)
|
||||
{
|
||||
int bytes = 0;
|
||||
|
||||
/* Send the packet */
|
||||
bytes =
|
||||
sendto(eth802_sockfd, &mtu, mtu_len, 0, (struct sockaddr *) ð_addr,
|
||||
sizeof(struct sockaddr));
|
||||
bytes = sendto(eth802_sockfd, &mtu, mtu_len, 0,
|
||||
(struct sockaddr *)ð_addr, sizeof(struct sockaddr));
|
||||
/* did it get sent? */
|
||||
if (bytes < 0)
|
||||
fprintf(stderr, "ethernet: Error sending packet: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(
|
||||
stderr, "ethernet: Error sending packet: %s\n", strerror(errno));
|
||||
|
||||
return bytes;
|
||||
|
||||
}
|
||||
|
||||
/* function to send a packet out the 802.2 socket */
|
||||
/* returns number of bytes sent on success, negative on failure */
|
||||
int ethernet_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int ethernet_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
int i = 0; /* counter */
|
||||
{ /* number of bytes of data */
|
||||
int i = 0; /* counter */
|
||||
int bytes = 0;
|
||||
BACNET_ADDRESS src = { 0 }; /* source address for npdu */
|
||||
uint8_t mtu[MAX_MPDU] = { 0 }; /* our buffer */
|
||||
uint8_t mtu[MAX_MPDU] = { 0 }; /* our buffer */
|
||||
int mtu_len = 0;
|
||||
|
||||
(void) npdu_data;
|
||||
(void)npdu_data;
|
||||
/* load the BACnet address for NPDU data */
|
||||
for (i = 0; i < 6; i++) {
|
||||
src.mac[i] = Ethernet_MAC_Address[i];
|
||||
@@ -270,9 +261,9 @@ int ethernet_send_pdu(
|
||||
return -3;
|
||||
}
|
||||
/* Logical PDU portion */
|
||||
mtu[14] = 0x82; /* DSAP for BACnet */
|
||||
mtu[15] = 0x82; /* SSAP for BACnet */
|
||||
mtu[16] = 0x03; /* Control byte in header */
|
||||
mtu[14] = 0x82; /* DSAP for BACnet */
|
||||
mtu[15] = 0x82; /* SSAP for BACnet */
|
||||
mtu[16] = 0x03; /* Control byte in header */
|
||||
mtu_len = 17;
|
||||
if ((mtu_len + pdu_len) > MAX_MPDU) {
|
||||
fprintf(stderr, "ethernet: PDU is too big to send!\n");
|
||||
@@ -284,28 +275,26 @@ int ethernet_send_pdu(
|
||||
encode_unsigned16(&mtu[12], 3 + pdu_len);
|
||||
|
||||
/* Send the packet */
|
||||
bytes =
|
||||
sendto(eth802_sockfd, &mtu, mtu_len, 0, (struct sockaddr *) ð_addr,
|
||||
sizeof(struct sockaddr));
|
||||
bytes = sendto(eth802_sockfd, &mtu, mtu_len, 0,
|
||||
(struct sockaddr *)ð_addr, sizeof(struct sockaddr));
|
||||
/* did it get sent? */
|
||||
if (bytes < 0)
|
||||
fprintf(stderr, "ethernet: Error sending packet: %s\n",
|
||||
strerror(errno));
|
||||
fprintf(
|
||||
stderr, "ethernet: Error sending packet: %s\n", strerror(errno));
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* receives an 802.2 framed packet */
|
||||
/* returns the number of octets in the PDU, or zero on failure */
|
||||
uint16_t ethernet_receive(
|
||||
BACNET_ADDRESS * src, /* source address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
uint16_t ethernet_receive(BACNET_ADDRESS *src, /* source address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||
unsigned timeout)
|
||||
{ /* number of milliseconds to wait for a packet */
|
||||
{ /* number of milliseconds to wait for a packet */
|
||||
int received_bytes;
|
||||
uint8_t buf[MAX_MPDU] = { 0 }; /* data */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
uint8_t buf[MAX_MPDU] = { 0 }; /* data */
|
||||
uint16_t pdu_len = 0; /* return value */
|
||||
fd_set read_fds;
|
||||
int max;
|
||||
struct timeval select_timeout;
|
||||
@@ -359,14 +348,14 @@ uint16_t ethernet_receive(
|
||||
|
||||
/* check destination address for when */
|
||||
/* the Ethernet card is in promiscious mode */
|
||||
if ((memcmp(&buf[0], Ethernet_MAC_Address, 6) != 0)
|
||||
&& (memcmp(&buf[0], Ethernet_Broadcast, 6) != 0)) {
|
||||
if ((memcmp(&buf[0], Ethernet_MAC_Address, 6) != 0) &&
|
||||
(memcmp(&buf[0], Ethernet_Broadcast, 6) != 0)) {
|
||||
/*fprintf(stderr, "ethernet: This packet isn't for us\n"); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) decode_unsigned16(&buf[12], &pdu_len);
|
||||
pdu_len -= 3 /* DSAP, SSAP, LLC Control */ ;
|
||||
(void)decode_unsigned16(&buf[12], &pdu_len);
|
||||
pdu_len -= 3 /* DSAP, SSAP, LLC Control */;
|
||||
/* copy the buffer into the PDU */
|
||||
if (pdu_len < max_pdu)
|
||||
memmove(&pdu[0], &buf[17], pdu_len);
|
||||
@@ -374,12 +363,10 @@ uint16_t ethernet_receive(
|
||||
else
|
||||
pdu_len = 0;
|
||||
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void ethernet_set_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void ethernet_set_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -390,8 +377,7 @@ void ethernet_set_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void ethernet_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void ethernet_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -400,7 +386,7 @@ void ethernet_get_my_address(
|
||||
my_address->mac[i] = Ethernet_MAC_Address[i];
|
||||
my_address->mac_len++;
|
||||
}
|
||||
my_address->net = 0; /* DNET=0 is local only, no routing */
|
||||
my_address->net = 0; /* DNET=0 is local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -409,10 +395,9 @@ void ethernet_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void ethernet_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void ethernet_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
for (i = 0; i < 6; i++) {
|
||||
@@ -420,7 +405,7 @@ void ethernet_get_broadcast_address(
|
||||
}
|
||||
dest->mac_len = 6;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
@@ -429,11 +414,9 @@ void ethernet_get_broadcast_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void ethernet_debug_address(
|
||||
const char *info,
|
||||
BACNET_ADDRESS * dest)
|
||||
void ethernet_debug_address(const char *info, BACNET_ADDRESS *dest)
|
||||
{
|
||||
int i = 0; /* counter */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (info)
|
||||
fprintf(stderr, "%s", info);
|
||||
@@ -442,14 +425,14 @@ void ethernet_debug_address(
|
||||
fprintf(stderr, " MAC Length=%d\n", dest->mac_len);
|
||||
fprintf(stderr, " MAC Address=");
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned) dest->mac[i]);
|
||||
fprintf(stderr, "%02X ", (unsigned)dest->mac[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " Net=%hu\n", dest->net);
|
||||
fprintf(stderr, " Len=%d\n", dest->len);
|
||||
fprintf(stderr, " Adr=");
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
fprintf(stderr, "%02X ", (unsigned) dest->adr[i]);
|
||||
fprintf(stderr, "%02X ", (unsigned)dest->adr[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
+32
-35
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
@@ -41,25 +41,23 @@ static struct timespec start;
|
||||
/** @brief The timeGetTime function retrieves the system time, in milliseconds.
|
||||
* The system time is the time elapsed since Windows was started.
|
||||
*/
|
||||
static unsigned long timeGetTime(
|
||||
void)
|
||||
static unsigned long timeGetTime(void)
|
||||
{
|
||||
struct timespec now;
|
||||
unsigned long ticks;
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
ticks =
|
||||
(now.tv_sec - start.tv_sec) * 1000 + (now.tv_nsec -
|
||||
start.tv_nsec) / 1000000;
|
||||
ticks = (now.tv_sec - start.tv_sec) * 1000 +
|
||||
(now.tv_nsec - start.tv_nsec) / 1000000;
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief returns the current millisecond count
|
||||
* @return millisecond counter
|
||||
*/
|
||||
* @brief returns the current millisecond count
|
||||
* @return millisecond counter
|
||||
*/
|
||||
unsigned long mstimer_now(void)
|
||||
{
|
||||
unsigned long now = timeGetTime();
|
||||
@@ -75,10 +73,9 @@ unsigned long mstimer_now(void)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialization for timer
|
||||
*/
|
||||
void mstimer_init(
|
||||
void)
|
||||
* @brief Initialization for timer
|
||||
*/
|
||||
void mstimer_init(void)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
}
|
||||
|
||||
+52
-61
@@ -50,11 +50,12 @@
|
||||
#include "bacnet/datalink/mstptext.h"
|
||||
#include "bacnet/bacint.h"
|
||||
|
||||
/** @file linux/mstpsnap.c Example application testing BACnet MS/TP on Linux. */
|
||||
/** @file linux/mstpsnap.c Example application testing BACnet MS/TP on Linux.
|
||||
*/
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) (((a) (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a)(b)) ? (a) : (b))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* local port data - shared with RS-485 */
|
||||
@@ -64,8 +65,7 @@ static uint8_t RxBuffer[MAX_MPDU];
|
||||
static uint8_t TxBuffer[MAX_MPDU];
|
||||
static struct mstimer Silence_Timer;
|
||||
|
||||
static uint32_t Timer_Silence(
|
||||
void *pArg)
|
||||
static uint32_t Timer_Silence(void *pArg)
|
||||
{
|
||||
uint32_t delta_time = 0;
|
||||
|
||||
@@ -77,17 +77,15 @@ static uint32_t Timer_Silence(
|
||||
return delta_time;
|
||||
}
|
||||
|
||||
static void Timer_Silence_Reset(
|
||||
void *pArg)
|
||||
static void Timer_Silence_Reset(void *pArg)
|
||||
{
|
||||
mstimer_set(&Silence_Timer, 0);
|
||||
}
|
||||
|
||||
/* functions used by the MS/TP state machine to put or get data */
|
||||
uint16_t MSTP_Put_Receive(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
(void) mstp_port;
|
||||
(void)mstp_port;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -95,26 +93,22 @@ uint16_t MSTP_Put_Receive(
|
||||
/* for the MS/TP state machine to use for getting data to send */
|
||||
/* Return: amount of PDU data */
|
||||
uint16_t MSTP_Get_Send(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void) mstp_port;
|
||||
(void) timeout;
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void)mstp_port;
|
||||
(void)timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t MSTP_Get_Reply(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void) mstp_port;
|
||||
(void) timeout;
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void)mstp_port;
|
||||
(void)timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int network_init(
|
||||
const char *name,
|
||||
int protocol)
|
||||
static int network_init(const char *name, int protocol)
|
||||
{
|
||||
/* check to see if we are being run as root */
|
||||
if (getuid() != 0) {
|
||||
@@ -146,7 +140,7 @@ static int network_init(
|
||||
sll.sll_ifindex = ifr.ifr_ifindex;
|
||||
sll.sll_protocol = htons(protocol);
|
||||
|
||||
if (bind(sockfd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
|
||||
if (bind(sockfd, (struct sockaddr *)&sll, sizeof(sll)) == -1) {
|
||||
perror("Unable to bind socket");
|
||||
return -1;
|
||||
}
|
||||
@@ -155,11 +149,10 @@ static int network_init(
|
||||
}
|
||||
|
||||
static void snap_received_packet(
|
||||
volatile struct mstp_port_struct_t *mstp_port,
|
||||
int sockfd)
|
||||
volatile struct mstp_port_struct_t *mstp_port, int sockfd)
|
||||
{
|
||||
uint16_t mtu_len = 0; /* number of octets of packet saved in file */
|
||||
unsigned i = 0; /* counter */
|
||||
uint16_t mtu_len = 0; /* number of octets of packet saved in file */
|
||||
unsigned i = 0; /* counter */
|
||||
static uint8_t mtu[1500] = { 0 };
|
||||
uint16_t max_data = 0;
|
||||
|
||||
@@ -176,17 +169,17 @@ static void snap_received_packet(
|
||||
mtu[10] = 0;
|
||||
mtu[11] = mstp_port->SourceAddress;
|
||||
/* length - 12, 13 */
|
||||
mtu[14] = 0xaa; /* DSAP for SNAP */
|
||||
mtu[15] = 0xaa; /* SSAP for SNAP */
|
||||
mtu[16] = 0x03; /* Control Field for SNAP */
|
||||
mtu[17] = 0x00; /* Organization Code: Cimetrics */
|
||||
mtu[18] = 0x10; /* Organization Code: Cimetrics */
|
||||
mtu[19] = 0x90; /* Organization Code: Cimetrics */
|
||||
mtu[20] = 0x00; /* Protocol ID */
|
||||
mtu[21] = 0x01; /* Protocol ID */
|
||||
mtu[22] = 0x00; /* delta time */
|
||||
mtu[23] = 0x00; /* delta time */
|
||||
mtu[24] = 0x80; /* unknown byte */
|
||||
mtu[14] = 0xaa; /* DSAP for SNAP */
|
||||
mtu[15] = 0xaa; /* SSAP for SNAP */
|
||||
mtu[16] = 0x03; /* Control Field for SNAP */
|
||||
mtu[17] = 0x00; /* Organization Code: Cimetrics */
|
||||
mtu[18] = 0x10; /* Organization Code: Cimetrics */
|
||||
mtu[19] = 0x90; /* Organization Code: Cimetrics */
|
||||
mtu[20] = 0x00; /* Protocol ID */
|
||||
mtu[21] = 0x01; /* Protocol ID */
|
||||
mtu[22] = 0x00; /* delta time */
|
||||
mtu[23] = 0x00; /* delta time */
|
||||
mtu[24] = 0x80; /* unknown byte */
|
||||
mtu[25] = mstp_port->FrameType;
|
||||
mtu[26] = mstp_port->DestinationAddress;
|
||||
mtu[27] = mstp_port->SourceAddress;
|
||||
@@ -205,27 +198,23 @@ static void snap_received_packet(
|
||||
}
|
||||
/* Ethernet length is data only - not address or length bytes */
|
||||
encode_unsigned16(&mtu[12], mtu_len - 14);
|
||||
(void) write(sockfd, &mtu[0], mtu_len);
|
||||
(void)write(sockfd, &mtu[0], mtu_len);
|
||||
}
|
||||
|
||||
|
||||
static void cleanup(
|
||||
void)
|
||||
static void cleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
#if (!defined(_WIN32))
|
||||
static void sig_int(
|
||||
int signo)
|
||||
static void sig_int(int signo)
|
||||
{
|
||||
(void) signo;
|
||||
(void)signo;
|
||||
|
||||
cleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void signal_init(
|
||||
void)
|
||||
void signal_init(void)
|
||||
{
|
||||
signal(SIGINT, sig_int);
|
||||
signal(SIGHUP, sig_int);
|
||||
@@ -234,9 +223,7 @@ void signal_init(
|
||||
#endif
|
||||
|
||||
/* simple test to packetize the data and print it */
|
||||
int main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
volatile struct mstp_port_struct_t *mstp_port;
|
||||
long my_baud = 38400;
|
||||
@@ -248,14 +235,18 @@ int main(
|
||||
mstp_port = &MSTP_Port;
|
||||
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
|
||||
printf("mstsnap [serial] [baud] [network]\r\n"
|
||||
"Captures MS/TP packets from a serial interface\r\n"
|
||||
"and sends them to a network interface using SNAP \r\n"
|
||||
"protocol packets (mimics Cimetrics U+4 packet).\r\n" "\r\n"
|
||||
"Command line options:\r\n" "[serial] - serial interface.\r\n"
|
||||
" defaults to /dev/ttyUSB0.\r\n"
|
||||
"[baud] - baud rate. 9600, 19200, 38400, 57600, 115200\r\n"
|
||||
" defaults to 38400.\r\n" "[network] - network interface.\r\n"
|
||||
" defaults to eth0.\r\n" "");
|
||||
"Captures MS/TP packets from a serial interface\r\n"
|
||||
"and sends them to a network interface using SNAP \r\n"
|
||||
"protocol packets (mimics Cimetrics U+4 packet).\r\n"
|
||||
"\r\n"
|
||||
"Command line options:\r\n"
|
||||
"[serial] - serial interface.\r\n"
|
||||
" defaults to /dev/ttyUSB0.\r\n"
|
||||
"[baud] - baud rate. 9600, 19200, 38400, 57600, 115200\r\n"
|
||||
" defaults to 38400.\r\n"
|
||||
"[network] - network interface.\r\n"
|
||||
" defaults to eth0.\r\n"
|
||||
"");
|
||||
return 0;
|
||||
}
|
||||
/* initialize our interface */
|
||||
@@ -285,11 +276,11 @@ int main(
|
||||
MSTP_Port.SilenceTimerReset = Timer_Silence_Reset;
|
||||
MSTP_Init(mstp_port);
|
||||
fprintf(stdout, "mstpcap: Using %s for capture at %ld bps.\n",
|
||||
RS485_Interface(), (long) RS485_Get_Baud_Rate());
|
||||
RS485_Interface(), (long)RS485_Get_Baud_Rate());
|
||||
atexit(cleanup);
|
||||
#if defined(_WIN32)
|
||||
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_PROCESSED_INPUT);
|
||||
SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlCHandler, TRUE);
|
||||
SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlCHandler, TRUE);
|
||||
#else
|
||||
signal_init();
|
||||
#endif
|
||||
|
||||
+92
-106
@@ -54,8 +54,8 @@
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <linux/serial.h> /* for struct serial_struct */
|
||||
#include <math.h> /* for calculation of custom divisor */
|
||||
#include <linux/serial.h> /* for struct serial_struct */
|
||||
#include <math.h> /* for calculation of custom divisor */
|
||||
#include <sys/ioctl.h>
|
||||
/* for scandir */
|
||||
#include <dirent.h>
|
||||
@@ -106,13 +106,12 @@ static uint8_t Rx_Buffer[4096];
|
||||
#define _POSIX_SOURCE 1 /* POSIX compliant source */
|
||||
|
||||
/*********************************************************************
|
||||
* DESCRIPTION: Configures the interface name
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*********************************************************************/
|
||||
void RS485_Set_Interface(
|
||||
char *ifname)
|
||||
* DESCRIPTION: Configures the interface name
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*********************************************************************/
|
||||
void RS485_Set_Interface(char *ifname)
|
||||
{
|
||||
/* note: expects a constant char, or char from the heap */
|
||||
if (ifname) {
|
||||
@@ -121,25 +120,23 @@ void RS485_Set_Interface(
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* DESCRIPTION: Returns the interface name
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*********************************************************************/
|
||||
const char *RS485_Interface(
|
||||
void)
|
||||
* DESCRIPTION: Returns the interface name
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*********************************************************************/
|
||||
const char *RS485_Interface(void)
|
||||
{
|
||||
return RS485_Port_Name;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void)
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(void)
|
||||
{
|
||||
uint32_t baud = 0;
|
||||
|
||||
@@ -215,16 +212,15 @@ uint32_t RS485_Get_Baud_Rate(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Port_Baud_Rate(
|
||||
volatile struct mstp_port_struct_t * mstp_port)
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Port_Baud_Rate(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
uint32_t baud = 0;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
return 0;
|
||||
}
|
||||
@@ -295,13 +291,12 @@ uint32_t RS485_Get_Port_Baud_Rate(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud)
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
@@ -381,16 +376,16 @@ bool RS485_Set_Baud_Rate(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Transmit a frame on the wire
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
* DESCRIPTION: Transmit a frame on the wire
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t *buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint32_t turnaround_time = Tturnaround * 1000;
|
||||
uint32_t baud;
|
||||
ssize_t written = 0;
|
||||
@@ -398,7 +393,7 @@ void RS485_Send_Frame(
|
||||
SHARED_MSTP_DATA *poSharedData = NULL;
|
||||
|
||||
if (mstp_port) {
|
||||
poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
}
|
||||
if (!poSharedData) {
|
||||
baud = RS485_Get_Baud_Rate();
|
||||
@@ -406,11 +401,12 @@ void RS485_Send_Frame(
|
||||
time to change from sending to receiving state. */
|
||||
usleep(turnaround_time / baud);
|
||||
/*
|
||||
On success, the number of bytes written are returned (zero indicates
|
||||
nothing was written). On error, -1 is returned, and errno is set
|
||||
appropriately. If count is zero and the file descriptor refers to a
|
||||
regular file, 0 will be returned without causing any other effect. For
|
||||
a special file, the results are not portable.
|
||||
On success, the number of bytes written are returned (zero
|
||||
indicates nothing was written). On error, -1 is returned, and
|
||||
errno is set appropriately. If count is zero and the file
|
||||
descriptor refers to a regular file, 0 will be returned without
|
||||
causing any other effect. For a special file, the results are not
|
||||
portable.
|
||||
*/
|
||||
written = write(RS485_Handle, buffer, nbytes);
|
||||
greska = errno;
|
||||
@@ -423,7 +419,7 @@ void RS485_Send_Frame(
|
||||
/* tcdrain(RS485_Handle); */
|
||||
/* per MSTP spec, sort of */
|
||||
if (mstp_port) {
|
||||
mstp_port->SilenceTimerReset((void *) mstp_port);
|
||||
mstp_port->SilenceTimerReset((void *)mstp_port);
|
||||
}
|
||||
} else {
|
||||
baud = RS485_Get_Port_Baud_Rate(mstp_port);
|
||||
@@ -431,11 +427,12 @@ void RS485_Send_Frame(
|
||||
time to change from sending to receiving state. */
|
||||
usleep(turnaround_time / baud);
|
||||
/*
|
||||
On success, the number of bytes written are returned (zero indicates
|
||||
nothing was written). On error, -1 is returned, and errno is set
|
||||
appropriately. If count is zero and the file descriptor refers to a
|
||||
regular file, 0 will be returned without causing any other effect. For
|
||||
a special file, the results are not portable.
|
||||
On success, the number of bytes written are returned (zero
|
||||
indicates nothing was written). On error, -1 is returned, and
|
||||
errno is set appropriately. If count is zero and the file
|
||||
descriptor refers to a regular file, 0 will be returned without
|
||||
causing any other effect. For a special file, the results are not
|
||||
portable.
|
||||
*/
|
||||
written = write(poSharedData->RS485_Handle, buffer, nbytes);
|
||||
greska = errno;
|
||||
@@ -448,7 +445,7 @@ void RS485_Send_Frame(
|
||||
/* tcdrain(RS485_Handle); */
|
||||
/* per MSTP spec, sort of */
|
||||
if (mstp_port) {
|
||||
mstp_port->SilenceTimerReset((void *) mstp_port);
|
||||
mstp_port->SilenceTimerReset((void *)mstp_port);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,20 +453,19 @@ void RS485_Send_Frame(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Get a byte of receive data
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Check_UART_Data(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
* DESCRIPTION: Get a byte of receive data
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
fd_set input;
|
||||
struct timeval waiter;
|
||||
uint8_t buf[2048];
|
||||
int n;
|
||||
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *) mstp_port->UserData;
|
||||
SHARED_MSTP_DATA *poSharedData = (SHARED_MSTP_DATA *)mstp_port->UserData;
|
||||
if (!poSharedData) {
|
||||
if (mstp_port->ReceiveError == true) {
|
||||
/* do nothing but wait for state machine to clear the error */
|
||||
@@ -526,8 +522,7 @@ void RS485_Check_UART_Data(
|
||||
/* grab bytes and stuff them into the FIFO every time */
|
||||
FD_ZERO(&input);
|
||||
FD_SET(poSharedData->RS485_Handle, &input);
|
||||
n = select(poSharedData->RS485_Handle + 1, &input, NULL, NULL,
|
||||
&waiter);
|
||||
n = select(poSharedData->RS485_Handle + 1, &input, NULL, NULL, &waiter);
|
||||
if (n < 0) {
|
||||
return;
|
||||
}
|
||||
@@ -538,8 +533,7 @@ void RS485_Check_UART_Data(
|
||||
}
|
||||
}
|
||||
|
||||
void RS485_Cleanup(
|
||||
void)
|
||||
void RS485_Cleanup(void)
|
||||
{
|
||||
/* restore the old port settings */
|
||||
tcsetattr(RS485_Handle, TCSANOW, &RS485_oldtio);
|
||||
@@ -547,9 +541,7 @@ void RS485_Cleanup(
|
||||
close(RS485_Handle);
|
||||
}
|
||||
|
||||
|
||||
void RS485_Initialize(
|
||||
void)
|
||||
void RS485_Initialize(void)
|
||||
{
|
||||
struct termios newtio;
|
||||
struct serial_struct newserial;
|
||||
@@ -560,7 +552,7 @@ void RS485_Initialize(
|
||||
Open device for reading and writing.
|
||||
Blocking mode - more CPU effecient
|
||||
*/
|
||||
RS485_Handle = open(RS485_Port_Name, O_RDWR | O_NOCTTY /*| O_NDELAY */ );
|
||||
RS485_Handle = open(RS485_Port_Name, O_RDWR | O_NOCTTY /*| O_NDELAY */);
|
||||
if (RS485_Handle < 0) {
|
||||
perror(RS485_Port_Name);
|
||||
exit(-1);
|
||||
@@ -600,14 +592,12 @@ void RS485_Initialize(
|
||||
if (RS485_SpecBaud) {
|
||||
/* 76800, custom divisor must be set */
|
||||
newserial.flags |= ASYNC_SPD_CUST;
|
||||
newserial.custom_divisor =
|
||||
round(((float) newserial.baud_base) / 76800);
|
||||
newserial.custom_divisor = round(((float)newserial.baud_base) / 76800);
|
||||
/* we must check that we calculated some sane value;
|
||||
small baud bases yield bad custom divisor values */
|
||||
baud_error =
|
||||
fabs(1 -
|
||||
((float) newserial.baud_base) /
|
||||
((float) newserial.custom_divisor) / 76800);
|
||||
baud_error = fabs(1 -
|
||||
((float)newserial.baud_base) / ((float)newserial.custom_divisor) /
|
||||
76800);
|
||||
if ((newserial.custom_divisor == 0) || (baud_error > 0.02)) {
|
||||
/* bad divisor */
|
||||
fprintf(stderr, "bad custom divisor %d, base baud %d\n",
|
||||
@@ -633,7 +623,7 @@ void RS485_Print_Ports(void)
|
||||
{
|
||||
int n;
|
||||
struct dirent **namelist;
|
||||
const char* sysdir = "/sys/class/tty/";
|
||||
const char *sysdir = "/sys/class/tty/";
|
||||
struct stat st;
|
||||
char buffer[1024];
|
||||
char device_dir[1024];
|
||||
@@ -648,29 +638,27 @@ void RS485_Print_Ports(void)
|
||||
perror("RS485: scandir");
|
||||
} else {
|
||||
while (n--) {
|
||||
if (strcmp(namelist[n]->d_name,"..") &&
|
||||
strcmp(namelist[n]->d_name,".")) {
|
||||
snprintf(device_dir, sizeof(device_dir),
|
||||
"%s%s/device",
|
||||
sysdir, namelist[n]->d_name);
|
||||
if (strcmp(namelist[n]->d_name, "..") &&
|
||||
strcmp(namelist[n]->d_name, ".")) {
|
||||
snprintf(device_dir, sizeof(device_dir), "%s%s/device", sysdir,
|
||||
namelist[n]->d_name);
|
||||
// Stat the devicedir and handle it if it is a symlink
|
||||
if (lstat(device_dir, &st)==0 && S_ISLNK(st.st_mode)) {
|
||||
if (lstat(device_dir, &st) == 0 && S_ISLNK(st.st_mode)) {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
snprintf(device_dir, sizeof(device_dir),
|
||||
"%s%s/device/driver",
|
||||
sysdir, namelist[n]->d_name);
|
||||
"%s%s/device/driver", sysdir, namelist[n]->d_name);
|
||||
if (readlink(device_dir, buffer, sizeof(buffer)) > 0) {
|
||||
valid_port = false;
|
||||
driver_name=basename(buffer);
|
||||
if (strcmp(driver_name,"serial8250") == 0) {
|
||||
driver_name = basename(buffer);
|
||||
if (strcmp(driver_name, "serial8250") == 0) {
|
||||
// serial8250-devices must be probed
|
||||
snprintf(device_dir, sizeof(device_dir),
|
||||
"/dev/%s", namelist[n]->d_name);
|
||||
fd = open(device_dir,
|
||||
O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
snprintf(device_dir, sizeof(device_dir), "/dev/%s",
|
||||
namelist[n]->d_name);
|
||||
fd = open(
|
||||
device_dir, O_RDWR | O_NONBLOCK | O_NOCTTY);
|
||||
if (fd >= 0) {
|
||||
// Get serial_info
|
||||
if (ioctl(fd, TIOCGSERIAL, &serinfo)==0) {
|
||||
if (ioctl(fd, TIOCGSERIAL, &serinfo) == 0) {
|
||||
// If device type is not PORT_UNKNOWN
|
||||
// we accept the port
|
||||
if (serinfo.type != PORT_UNKNOWN) {
|
||||
@@ -685,7 +673,7 @@ void RS485_Print_Ports(void)
|
||||
if (valid_port) {
|
||||
// print full absolute file path
|
||||
printf("interface {value=/dev/%s}"
|
||||
"{display=MS/TP Capture on /dev/%s}\n",
|
||||
"{display=MS/TP Capture on /dev/%s}\n",
|
||||
namelist[n]->d_name, namelist[n]->d_name);
|
||||
}
|
||||
}
|
||||
@@ -699,13 +687,11 @@ void RS485_Print_Ports(void)
|
||||
|
||||
#ifdef TEST_RS485
|
||||
#include <string.h>
|
||||
int main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
volatile struct mstp_port_struct_t mstp_port = {0};
|
||||
uint8_t token_buf[8] = {0x55, 0xFF, 0x00, 0x7E, 0x07, 0x00, 0x00, 0xFD};
|
||||
uint8_t pfm_buf[8] = {0x55, 0xFF, 0x01, 0x67, 0x07, 0x00, 0x00, 0x3E};
|
||||
volatile struct mstp_port_struct_t mstp_port = { 0 };
|
||||
uint8_t token_buf[8] = { 0x55, 0xFF, 0x00, 0x7E, 0x07, 0x00, 0x00, 0xFD };
|
||||
uint8_t pfm_buf[8] = { 0x55, 0xFF, 0x01, 0x67, 0x07, 0x00, 0x00, 0x3E };
|
||||
long baud = 38400;
|
||||
bool write_token = false;
|
||||
bool write_pfm = false;
|
||||
@@ -729,10 +715,10 @@ int main(
|
||||
RS485_Initialize();
|
||||
for (;;) {
|
||||
if (write_token) {
|
||||
RS485_Send_Frame(NULL,token_buf, sizeof(token_buf));
|
||||
RS485_Send_Frame(NULL, token_buf, sizeof(token_buf));
|
||||
usleep(25000);
|
||||
} else if (write_pfm) {
|
||||
RS485_Send_Frame(NULL,pfm_buf, sizeof(pfm_buf));
|
||||
RS485_Send_Frame(NULL, pfm_buf, sizeof(pfm_buf));
|
||||
usleep(100000);
|
||||
} else {
|
||||
RS485_Check_UART_Data(&mstp_port);
|
||||
|
||||
+50
-61
@@ -45,7 +45,7 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h> /* signal handling functions */
|
||||
#include <signal.h> /* signal handling functions */
|
||||
|
||||
/* local includes */
|
||||
#include "bacnet/bytes.h"
|
||||
@@ -54,11 +54,12 @@
|
||||
#include "bacnet/datalink/mstp.h"
|
||||
#include "bacnet/datalink/mstptext.h"
|
||||
|
||||
/** @file linux/rx_fsm.c Example app testing MS/TP Rx State Machine on Linux. */
|
||||
/** @file linux/rx_fsm.c Example app testing MS/TP Rx State Machine on Linux.
|
||||
*/
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) (((a) (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a)(b)) ? (a) : (b))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef LOCAL_PRINT
|
||||
@@ -71,27 +72,27 @@ static volatile struct mstp_port_struct_t MSTP_Port;
|
||||
static uint8_t RxBuffer[MAX_MPDU];
|
||||
static uint8_t TxBuffer[MAX_MPDU];
|
||||
static uint16_t SilenceTime;
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
|
||||
static uint16_t Timer_Silence(
|
||||
void)
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) \
|
||||
{ \
|
||||
if (x < 0xFFFF) \
|
||||
x++; \
|
||||
}
|
||||
static uint16_t Timer_Silence(void)
|
||||
{
|
||||
return SilenceTime;
|
||||
}
|
||||
|
||||
static void Timer_Silence_Reset(
|
||||
void)
|
||||
static void Timer_Silence_Reset(void)
|
||||
{
|
||||
SilenceTime = 0;
|
||||
}
|
||||
|
||||
static void dlmstp_millisecond_timer(
|
||||
void)
|
||||
static void dlmstp_millisecond_timer(void)
|
||||
{
|
||||
INCREMENT_AND_LIMIT_UINT16(SilenceTime);
|
||||
}
|
||||
|
||||
void *milliseconds_task(
|
||||
void *pArg)
|
||||
void *milliseconds_task(void *pArg)
|
||||
{
|
||||
struct timespec timeOut, remains;
|
||||
|
||||
@@ -107,10 +108,9 @@ void *milliseconds_task(
|
||||
}
|
||||
|
||||
/* functions used by the MS/TP state machine to put or get data */
|
||||
uint16_t MSTP_Put_Receive(
|
||||
volatile struct mstp_port_struct_t * mstp_port)
|
||||
uint16_t MSTP_Put_Receive(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
(void) mstp_port;
|
||||
(void)mstp_port;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -118,26 +118,23 @@ uint16_t MSTP_Put_Receive(
|
||||
/* for the MS/TP state machine to use for getting data to send */
|
||||
/* Return: amount of PDU data */
|
||||
uint16_t MSTP_Get_Send(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void) mstp_port;
|
||||
(void) timeout;
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void)mstp_port;
|
||||
(void)timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t MSTP_Get_Reply(
|
||||
volatile struct mstp_port_struct_t * mstp_port,
|
||||
unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void) mstp_port;
|
||||
(void) timeout;
|
||||
volatile struct mstp_port_struct_t *mstp_port, unsigned timeout)
|
||||
{ /* milliseconds to wait for a packet */
|
||||
(void)mstp_port;
|
||||
(void)timeout;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns a delta timestamp */
|
||||
int timestamp_ms(
|
||||
void)
|
||||
int timestamp_ms(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
int delta_ticks = 0;
|
||||
@@ -158,19 +155,18 @@ int timestamp_ms(
|
||||
}
|
||||
|
||||
static const char *Capture_Filename = "mstp.cap";
|
||||
static FILE *pFile = NULL; /* stream pointer */
|
||||
static FILE *pFile = NULL; /* stream pointer */
|
||||
|
||||
/* write packet to file in libpcap format */
|
||||
static void write_global_header(
|
||||
void)
|
||||
static void write_global_header(void)
|
||||
{
|
||||
uint32_t magic_number = 0xa1b2c3d4; /* magic number */
|
||||
uint16_t version_major = 2; /* major version number */
|
||||
uint16_t version_minor = 4; /* minor version number */
|
||||
int32_t thiszone = 0; /* GMT to local correction */
|
||||
uint32_t sigfigs = 0; /* accuracy of timestamps */
|
||||
uint32_t snaplen = 65535; /* max length of captured packets, in octets */
|
||||
uint32_t network = 165; /* data link type - BACNET_MS_TP */
|
||||
int32_t thiszone = 0; /* GMT to local correction */
|
||||
uint32_t sigfigs = 0; /* accuracy of timestamps */
|
||||
uint32_t snaplen = 65535; /* max length of captured packets, in octets */
|
||||
uint32_t network = 165; /* data link type - BACNET_MS_TP */
|
||||
|
||||
/* create a new file. */
|
||||
pFile = fopen(Capture_Filename, "wb");
|
||||
@@ -188,14 +184,13 @@ static void write_global_header(
|
||||
}
|
||||
}
|
||||
|
||||
static void write_received_packet(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
static void write_received_packet(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
uint32_t ts_sec; /* timestamp seconds */
|
||||
uint32_t ts_usec; /* timestamp microseconds */
|
||||
uint32_t incl_len; /* number of octets of packet saved in file */
|
||||
uint32_t orig_len; /* actual length of packet */
|
||||
uint8_t header[8]; /* MS/TP header */
|
||||
uint32_t ts_sec; /* timestamp seconds */
|
||||
uint32_t ts_usec; /* timestamp microseconds */
|
||||
uint32_t incl_len; /* number of octets of packet saved in file */
|
||||
uint32_t orig_len; /* actual length of packet */
|
||||
uint8_t header[8]; /* MS/TP header */
|
||||
struct timeval tv;
|
||||
size_t max_data = 0;
|
||||
|
||||
@@ -224,8 +219,8 @@ static void write_received_packet(
|
||||
fwrite(header, sizeof(header), 1, pFile);
|
||||
if (mstp_port->DataLength) {
|
||||
fwrite(mstp_port->InputBuffer, max_data, 1, pFile);
|
||||
fwrite((char *) &(mstp_port->DataCRCActualMSB), 1, 1, pFile);
|
||||
fwrite((char *) &(mstp_port->DataCRCActualLSB), 1, 1, pFile);
|
||||
fwrite((char *)&(mstp_port->DataCRCActualMSB), 1, 1, pFile);
|
||||
fwrite((char *)&(mstp_port->DataCRCActualLSB), 1, 1, pFile);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "rx_fsm: failed to open %s: %s\n", Capture_Filename,
|
||||
@@ -233,19 +228,17 @@ static void write_received_packet(
|
||||
}
|
||||
}
|
||||
|
||||
static void cleanup(
|
||||
void)
|
||||
static void cleanup(void)
|
||||
{
|
||||
if (pFile) {
|
||||
fflush(pFile); /* stream pointer */
|
||||
fclose(pFile); /* stream pointer */
|
||||
fflush(pFile); /* stream pointer */
|
||||
fclose(pFile); /* stream pointer */
|
||||
}
|
||||
pFile = NULL;
|
||||
}
|
||||
|
||||
#if LOCAL_PRINT
|
||||
static void print_received_packet(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
static void print_received_packet(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
unsigned i = 0;
|
||||
int timestamp = 0;
|
||||
@@ -280,17 +273,15 @@ static void print_received_packet(
|
||||
}
|
||||
#endif
|
||||
|
||||
static void sig_int(
|
||||
int signo)
|
||||
static void sig_int(int signo)
|
||||
{
|
||||
(void) signo;
|
||||
(void)signo;
|
||||
|
||||
cleanup();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void signal_init(
|
||||
void)
|
||||
void signal_init(void)
|
||||
{
|
||||
signal(SIGINT, sig_int);
|
||||
signal(SIGHUP, sig_int);
|
||||
@@ -298,9 +289,7 @@ void signal_init(
|
||||
}
|
||||
|
||||
/* simple test to packetize the data and print it */
|
||||
int main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
volatile struct mstp_port_struct_t *mstp_port;
|
||||
int rc = 0;
|
||||
@@ -339,7 +328,7 @@ int main(
|
||||
rc = pthread_create(&hThread, NULL, milliseconds_task, NULL);
|
||||
atexit(cleanup);
|
||||
write_global_header();
|
||||
fflush(pFile); /* stream pointer */
|
||||
fflush(pFile); /* stream pointer */
|
||||
/* run forever */
|
||||
for (;;) {
|
||||
RS485_Check_UART_Data(mstp_port);
|
||||
@@ -351,7 +340,7 @@ int main(
|
||||
print_received_packet(mstp_port);
|
||||
#endif
|
||||
write_received_packet(mstp_port);
|
||||
fflush(pFile); /* stream pointer */
|
||||
fflush(pFile); /* stream pointer */
|
||||
} else if (mstp_port->ReceivedInvalidFrame) {
|
||||
mstp_port->ReceivedInvalidFrame = false;
|
||||
fprintf(stderr, "ReceivedInvalidFrame\n");
|
||||
@@ -359,7 +348,7 @@ int main(
|
||||
print_received_packet(mstp_port);
|
||||
#endif
|
||||
write_received_packet(mstp_port);
|
||||
fflush(pFile); /* stream pointer */
|
||||
fflush(pFile); /* stream pointer */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+60
-86
@@ -31,15 +31,15 @@
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include <stdint.h> /* for standard integer types uint8_t etc. */
|
||||
#include <stdbool.h> /* for the standard bool type. */
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacint.h"
|
||||
#include "bacnet/datalink/bip.h"
|
||||
#include "bacnet/datalink/bvlc.h"
|
||||
#include "bacnet/basic/services.h"
|
||||
#include "bacport.h" /* custom per port */
|
||||
#include "bacport.h" /* custom per port */
|
||||
|
||||
/** @file bip.c Configuration and Operations for BACnet/IP */
|
||||
|
||||
@@ -54,9 +54,9 @@ static struct in_addr BIP_Broadcast_Address;
|
||||
static struct udp_pcb *Server_upcb;
|
||||
/* track packets for diagnostics */
|
||||
struct bacnet_stats {
|
||||
uint32_t xmit; /* Transmitted packets. */
|
||||
uint32_t recv; /* Received packets. */
|
||||
uint32_t drop; /* Dropped packets. */
|
||||
uint32_t xmit; /* Transmitted packets. */
|
||||
uint32_t recv; /* Received packets. */
|
||||
uint32_t drop; /* Dropped packets. */
|
||||
};
|
||||
struct bacnet_stats BIP_Stats;
|
||||
#define BIP_STATS_INC(x) ++BIP_Stats.x
|
||||
@@ -76,28 +76,24 @@ uint32_t bip_stats_drop(void)
|
||||
return BIP_Stats.drop;
|
||||
}
|
||||
|
||||
void bip_set_addr(
|
||||
uint32_t net_address)
|
||||
{ /* in network byte order */
|
||||
void bip_set_addr(uint32_t net_address)
|
||||
{ /* in network byte order */
|
||||
BIP_Address.s_addr = net_address;
|
||||
}
|
||||
|
||||
/* returns network byte order */
|
||||
uint32_t bip_get_addr(
|
||||
void)
|
||||
uint32_t bip_get_addr(void)
|
||||
{
|
||||
return BIP_Address.s_addr;
|
||||
}
|
||||
|
||||
void bip_set_broadcast_addr(
|
||||
uint32_t net_address)
|
||||
{ /* in network byte order */
|
||||
void bip_set_broadcast_addr(uint32_t net_address)
|
||||
{ /* in network byte order */
|
||||
BIP_Broadcast_Address.s_addr = net_address;
|
||||
}
|
||||
|
||||
/* returns network byte order */
|
||||
uint32_t bip_get_broadcast_addr(
|
||||
void)
|
||||
uint32_t bip_get_broadcast_addr(void)
|
||||
{
|
||||
return BIP_Broadcast_Address.s_addr;
|
||||
}
|
||||
@@ -106,8 +102,7 @@ uint32_t bip_get_broadcast_addr(
|
||||
* @brief Set the BACnet IPv4 UDP port number
|
||||
* @param port - IPv4 UDP port number - in host byte order
|
||||
*/
|
||||
void bip_set_port(
|
||||
uint16_t port)
|
||||
void bip_set_port(uint16_t port)
|
||||
{
|
||||
if (BIP_Port != htons(port)) {
|
||||
BIP_Port_Changed = true;
|
||||
@@ -121,41 +116,35 @@ bool bip_port_changed(void)
|
||||
}
|
||||
|
||||
/* returns host byte order */
|
||||
uint16_t bip_get_port(
|
||||
void)
|
||||
uint16_t bip_get_port(void)
|
||||
{
|
||||
return ntohs(BIP_Port);
|
||||
}
|
||||
|
||||
static void bip_mac_to_addr(
|
||||
struct ip_addr *address,
|
||||
uint8_t * mac)
|
||||
static void bip_mac_to_addr(struct ip_addr *address, uint8_t *mac)
|
||||
{
|
||||
if (mac && address) {
|
||||
address->addr = ((u32_t) ((((uint32_t) mac[0]) << 24) & 0xff000000));
|
||||
address->addr |= ((u32_t) ((((uint32_t) mac[1]) << 16) & 0x00ff0000));
|
||||
address->addr |= ((u32_t) ((((uint32_t) mac[2]) << 8) & 0x0000ff00));
|
||||
address->addr |= ((u32_t) (((uint32_t) mac[3]) & 0x000000ff));
|
||||
address->addr = ((u32_t)((((uint32_t)mac[0]) << 24) & 0xff000000));
|
||||
address->addr |= ((u32_t)((((uint32_t)mac[1]) << 16) & 0x00ff0000));
|
||||
address->addr |= ((u32_t)((((uint32_t)mac[2]) << 8) & 0x0000ff00));
|
||||
address->addr |= ((u32_t)(((uint32_t)mac[3]) & 0x000000ff));
|
||||
}
|
||||
}
|
||||
|
||||
static void bip_addr_to_mac(
|
||||
uint8_t * mac,
|
||||
struct ip_addr *address)
|
||||
static void bip_addr_to_mac(uint8_t *mac, struct ip_addr *address)
|
||||
{
|
||||
if (mac && address) {
|
||||
mac[0] = (uint8_t) (address->addr >> 24);
|
||||
mac[1] = (uint8_t) (address->addr >> 16);
|
||||
mac[2] = (uint8_t) (address->addr >> 8);
|
||||
mac[3] = (uint8_t) (address->addr);
|
||||
mac[0] = (uint8_t)(address->addr >> 24);
|
||||
mac[1] = (uint8_t)(address->addr >> 16);
|
||||
mac[2] = (uint8_t)(address->addr >> 8);
|
||||
mac[3] = (uint8_t)(address->addr);
|
||||
}
|
||||
}
|
||||
|
||||
static int bip_decode_bip_address(
|
||||
BACNET_ADDRESS * bac_addr,
|
||||
struct ip_addr *address, /* in network format */
|
||||
uint16_t * port)
|
||||
{ /* in network format */
|
||||
static int bip_decode_bip_address(BACNET_ADDRESS *bac_addr,
|
||||
struct ip_addr *address, /* in network format */
|
||||
uint16_t *port)
|
||||
{ /* in network format */
|
||||
int len = 0;
|
||||
|
||||
if (bac_addr) {
|
||||
@@ -177,9 +166,7 @@ static int bip_decode_bip_address(
|
||||
* @return true if the packet was sent
|
||||
*/
|
||||
static bool bip_send_mpdu(
|
||||
struct ip_addr *dst_ip,
|
||||
uint16_t port,
|
||||
struct pbuf *pkt)
|
||||
struct ip_addr *dst_ip, uint16_t port, struct pbuf *pkt)
|
||||
{
|
||||
err_t status = ERR_OK;
|
||||
|
||||
@@ -203,14 +190,13 @@ static bool bip_send_mpdu(
|
||||
*
|
||||
* @return number of bytes sent
|
||||
*/
|
||||
int bip_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int bip_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{
|
||||
struct pbuf *pkt = NULL, *pkt0 = NULL;
|
||||
uint8_t mtu[4] = {0};
|
||||
uint8_t mtu[4] = { 0 };
|
||||
int mtu_len = 0;
|
||||
/* addr and port in host format */
|
||||
struct ip_addr dst_ip;
|
||||
@@ -240,7 +226,7 @@ int bip_send_pdu(
|
||||
/* invalid address */
|
||||
return -1;
|
||||
}
|
||||
mtu_len = pdu_len + 4 /*inclusive */ ;
|
||||
mtu_len = pdu_len + 4 /*inclusive */;
|
||||
encode_unsigned16(&mtu[2], mtu_len);
|
||||
pbuf_take(pkt0, mtu, 4);
|
||||
pbuf_take(pkt, pdu, pdu_len);
|
||||
@@ -260,9 +246,7 @@ int bip_send_pdu(
|
||||
*
|
||||
* @return number of bytes encoded
|
||||
*/
|
||||
static bool bvlc_send_result(
|
||||
struct ip_addr *addr,
|
||||
uint16_t result_code)
|
||||
static bool bvlc_send_result(struct ip_addr *addr, uint16_t result_code)
|
||||
{
|
||||
struct pbuf *pkt = NULL;
|
||||
uint8_t mtu[6] = { 0 };
|
||||
@@ -284,8 +268,7 @@ static bool bvlc_send_result(
|
||||
return bip_send_mpdu(addr, BIP_Port, pkt);
|
||||
}
|
||||
|
||||
void bip_server_callback(
|
||||
void *arg,
|
||||
void bip_server_callback(void *arg,
|
||||
struct udp_pcb *upcb,
|
||||
struct pbuf *pkt,
|
||||
struct ip_addr *addr,
|
||||
@@ -294,12 +277,10 @@ void bip_server_callback(
|
||||
uint8_t function = 0;
|
||||
uint16_t pdu_len = 0;
|
||||
uint16_t pdu_offset = 0;
|
||||
BACNET_ADDRESS src = {
|
||||
0
|
||||
}; /* address where message came from */
|
||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||
struct ip_addr sin_addr;
|
||||
uint16_t sin_port = 0;
|
||||
uint8_t *pdu = (uint8_t *) pkt->payload;
|
||||
uint8_t *pdu = (uint8_t *)pkt->payload;
|
||||
|
||||
/* the signature of a BACnet/IP packet */
|
||||
if (pdu[0] != BVLL_TYPE_BACNET_IP) {
|
||||
@@ -317,13 +298,13 @@ void bip_server_callback(
|
||||
bip_addr_to_mac(&src.mac[0], addr);
|
||||
memcpy(&src.mac[4], &port, 2);
|
||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
||||
(void) decode_unsigned16(&pdu[2], &pdu_len);
|
||||
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
||||
/* subtract off the BVLC header */
|
||||
pdu_len -= 4;
|
||||
pdu_offset = 4;
|
||||
}
|
||||
} else if (function == BVLC_FORWARDED_NPDU) {
|
||||
IP4_ADDR(&sin_addr,pdu[4],pdu[5],pdu[6],pdu[7]);
|
||||
IP4_ADDR(&sin_addr, pdu[4], pdu[5], pdu[6], pdu[7]);
|
||||
decode_unsigned16(&pdu[8], &sin_port);
|
||||
if ((sin_addr.addr == BIP_Address.s_addr) && (sin_port == BIP_Port)) {
|
||||
/* ignore forwarded messages from me */
|
||||
@@ -334,29 +315,26 @@ void bip_server_callback(
|
||||
bip_addr_to_mac(&src.mac[0], &sin_addr);
|
||||
memcpy(&src.mac[4], &sin_port, 2);
|
||||
/* decode the length of the PDU - length is inclusive of BVLC */
|
||||
(void) decode_unsigned16(&pdu[2], &pdu_len);
|
||||
(void)decode_unsigned16(&pdu[2], &pdu_len);
|
||||
/* subtract off the BVLC header */
|
||||
pdu_len -= 10;
|
||||
pdu_offset = 10;
|
||||
}
|
||||
} else if (function == BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE) {
|
||||
bvlc_send_result(addr,
|
||||
BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||
bvlc_send_result(
|
||||
addr, BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||
} else if (function == BVLC_READ_BROADCAST_DIST_TABLE) {
|
||||
bvlc_send_result(addr,
|
||||
BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||
bvlc_send_result(
|
||||
addr, BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK);
|
||||
} else if (function == BVLC_REGISTER_FOREIGN_DEVICE) {
|
||||
bvlc_send_result(addr,
|
||||
BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK);
|
||||
bvlc_send_result(addr, BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK);
|
||||
} else if (function == BVLC_READ_FOREIGN_DEVICE_TABLE) {
|
||||
bvlc_send_result(addr,
|
||||
BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK);
|
||||
bvlc_send_result(addr, BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK);
|
||||
} else if (function == BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY) {
|
||||
bvlc_send_result(addr,
|
||||
BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK);
|
||||
bvlc_send_result(
|
||||
addr, BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK);
|
||||
} else if (function == BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK) {
|
||||
bvlc_send_result(addr,
|
||||
BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
|
||||
bvlc_send_result(addr, BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK);
|
||||
}
|
||||
if (pdu_len) {
|
||||
BIP_STATS_INC(recv);
|
||||
@@ -376,8 +354,7 @@ void bip_server_callback(
|
||||
pbuf_free(pkt);
|
||||
}
|
||||
|
||||
void bip_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void bip_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -385,8 +362,8 @@ void bip_get_my_address(
|
||||
my_address->mac_len = 6;
|
||||
memcpy(&my_address->mac[0], &BIP_Address.s_addr, 4);
|
||||
memcpy(&my_address->mac[4], &BIP_Port, 2);
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0; /* no SLEN */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0; /* no SLEN */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
/* no SADR */
|
||||
my_address->adr[i] = 0;
|
||||
@@ -396,17 +373,16 @@ void bip_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void bip_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void bip_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 6;
|
||||
memcpy(&dest->mac[0], &BIP_Broadcast_Address.s_addr, 4);
|
||||
memcpy(&dest->mac[4], &BIP_Port, 2);
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* no SLEN */
|
||||
dest->len = 0; /* no SLEN */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
/* no SADR */
|
||||
dest->adr[i] = 0;
|
||||
@@ -433,16 +409,14 @@ void bip_get_broadcast_address(
|
||||
* @return True if the socket is successfully opened for BACnet/IP,
|
||||
* else False if the socket functions fail.
|
||||
*/
|
||||
bool bip_init(
|
||||
char *ifname)
|
||||
bool bip_init(char *ifname)
|
||||
{
|
||||
(void) ifname;
|
||||
(void)ifname;
|
||||
/* Create a new UDP control block */
|
||||
Server_upcb = udp_new();
|
||||
if (Server_upcb == NULL) {
|
||||
/* increase MEMP_NUM_UDP_PCB in lwipopts.h */
|
||||
while (1) {
|
||||
};
|
||||
while (1) { };
|
||||
}
|
||||
/* Bind the upcb to the UDP_PORT port */
|
||||
/* Using IP_ADDR_ANY allow the upcb to be used by any local interface */
|
||||
|
||||
+39
-49
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -44,8 +44,7 @@ static uint8_t Present_Value[MAX_ANALOG_INPUTS];
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
@@ -54,34 +53,30 @@ bool Analog_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
unsigned Analog_Input_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
char *Analog_Input_Name(
|
||||
uint32_t object_instance)
|
||||
char *Analog_Input_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
sprintf(text_string, "AI-%lu", (unsigned long) object_instance);
|
||||
sprintf(text_string, "AI-%lu", (unsigned long)object_instance);
|
||||
return text_string;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float Analog_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = 0.0;
|
||||
|
||||
@@ -91,9 +86,7 @@ float Analog_Input_Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
void Analog_Input_Present_Value_Set(
|
||||
uint32_t object_instance,
|
||||
float value)
|
||||
void Analog_Input_Present_Value_Set(uint32_t object_instance, float value)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
Present_Value[object_instance] = value;
|
||||
@@ -102,10 +95,9 @@ void Analog_Input_Present_Value_Set(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object has already exists */
|
||||
int Analog_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint8_t *apdu = NULL;
|
||||
@@ -117,16 +109,15 @@ int Analog_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_ANALOG_INPUT, rpdata->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:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Input_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Analog_Input_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -135,9 +126,8 @@ int Analog_Input_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
Analog_Input_Present_Value(rpdata->object_instance));
|
||||
apdu_len = encode_application_real(
|
||||
&apdu[0], Analog_Input_Present_Value(rpdata->object_instance));
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
|
||||
+25
-30
@@ -43,20 +43,17 @@
|
||||
/* me */
|
||||
#include "bacnet/apdu.h"
|
||||
|
||||
uint16_t apdu_timeout(
|
||||
void)
|
||||
uint16_t apdu_timeout(void)
|
||||
{
|
||||
return 3000;
|
||||
}
|
||||
|
||||
uint8_t apdu_retries(
|
||||
void)
|
||||
uint8_t apdu_retries(void)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool apdu_service_supported(
|
||||
BACNET_SERVICES_SUPPORTED service_supported)
|
||||
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -75,15 +72,14 @@ bool apdu_service_supported(
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t apdu_decode_confirmed_service_request(
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_decode_confirmed_service_request(uint8_t *apdu, /* APDU data */
|
||||
uint16_t apdu_len,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||
uint8_t * service_choice,
|
||||
uint8_t ** service_request,
|
||||
uint16_t * service_request_len)
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data,
|
||||
uint8_t *service_choice,
|
||||
uint8_t **service_request,
|
||||
uint16_t *service_request_len)
|
||||
{
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
service_data->segmented_message = (apdu[0] & BIT(3)) ? true : false;
|
||||
service_data->more_follows = (apdu[0] & BIT(2)) ? true : false;
|
||||
@@ -110,8 +106,7 @@ uint16_t apdu_decode_confirmed_service_request(
|
||||
When the initiation of communications is disabled,
|
||||
all APDUs shall be processed and responses returned as
|
||||
required... */
|
||||
static bool apdu_confirmed_dcc_disabled(
|
||||
uint8_t service_choice)
|
||||
static bool apdu_confirmed_dcc_disabled(uint8_t service_choice)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -136,8 +131,7 @@ static bool apdu_confirmed_dcc_disabled(
|
||||
DISABLE_INITIATION, the responding BACnet-user shall
|
||||
discontinue the initiation of messages except for I-Am
|
||||
requests issued in accordance with the Who-Is service procedure.*/
|
||||
static bool apdu_unconfirmed_dcc_disabled(
|
||||
uint8_t service_choice)
|
||||
static bool apdu_unconfirmed_dcc_disabled(uint8_t service_choice)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -159,36 +153,37 @@ static bool apdu_unconfirmed_dcc_disabled(
|
||||
return status;
|
||||
}
|
||||
|
||||
void apdu_handler(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * apdu, /* APDU data */
|
||||
void apdu_handler(BACNET_ADDRESS *src,
|
||||
uint8_t *apdu, /* APDU data */
|
||||
uint16_t apdu_len)
|
||||
{
|
||||
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
|
||||
uint8_t service_choice = 0;
|
||||
uint8_t *service_request = NULL;
|
||||
uint16_t service_request_len = 0;
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
if (apdu) {
|
||||
/* PDU Type */
|
||||
switch (apdu[0] & 0xF0) {
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
len = apdu_decode_confirmed_service_request(
|
||||
&apdu[0], /* APDU data */
|
||||
apdu_len, &service_data, &service_choice, &service_request,
|
||||
&service_request_len);
|
||||
if (apdu_confirmed_dcc_disabled(service_choice)) {
|
||||
/* When network communications are completely disabled,
|
||||
only DeviceCommunicationControl and ReinitializeDevice APDUs
|
||||
shall be processed and no messages shall be initiated. */
|
||||
only DeviceCommunicationControl and ReinitializeDevice
|
||||
APDUs shall be processed and no messages shall be
|
||||
initiated. */
|
||||
break;
|
||||
}
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
handler_read_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
} else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
|
||||
handler_write_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
handler_write_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
} else if (service_choice ==
|
||||
SERVICE_CONFIRMED_REINITIALIZE_DEVICE) {
|
||||
handler_reinitialize_device(service_request,
|
||||
@@ -208,10 +203,10 @@ void apdu_handler(
|
||||
service_request_len = apdu_len - 2;
|
||||
if (apdu_unconfirmed_dcc_disabled(service_choice)) {
|
||||
/* When network communications are disabled,
|
||||
only DeviceCommunicationControl and ReinitializeDevice APDUs
|
||||
shall be processed and no messages shall be initiated.
|
||||
If communications have been initiation disabled, then
|
||||
WhoIs may be processed. */
|
||||
only DeviceCommunicationControl and ReinitializeDevice
|
||||
APDUs shall be processed and no messages shall be
|
||||
initiated. If communications have been initiation
|
||||
disabled, then WhoIs may be processed. */
|
||||
break;
|
||||
}
|
||||
if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
|
||||
|
||||
+49
-60
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/basic/object/av.h"
|
||||
@@ -54,8 +54,7 @@ static uint8_t Present_Value[MAX_ANALOG_VALUES];
|
||||
/* we need to have our arrays initialized before answering any calls */
|
||||
static bool Analog_Value_Initialized = false;
|
||||
|
||||
void Analog_Value_Init(
|
||||
void)
|
||||
void Analog_Value_Init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@@ -74,8 +73,7 @@ void Analog_Value_Init(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
Analog_Value_Init();
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
@@ -86,8 +84,7 @@ bool Analog_Value_Valid_Instance(
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
unsigned Analog_Value_Count(void)
|
||||
{
|
||||
Analog_Value_Init();
|
||||
return MAX_ANALOG_VALUES;
|
||||
@@ -96,8 +93,7 @@ unsigned Analog_Value_Count(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Value_Index_To_Instance(unsigned index)
|
||||
{
|
||||
Analog_Value_Init();
|
||||
return index;
|
||||
@@ -106,8 +102,7 @@ uint32_t Analog_Value_Index_To_Instance(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_ANALOG_VALUES;
|
||||
|
||||
@@ -118,8 +113,7 @@ unsigned Analog_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
float Analog_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = ANALOG_RELINQUISH_DEFAULT;
|
||||
unsigned index = 0;
|
||||
@@ -135,10 +129,9 @@ float Analog_Value_Present_Value(
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Analog_Value_Name(
|
||||
uint32_t object_instance)
|
||||
char *Analog_Value_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[32] = ""; /* okay for single thread */
|
||||
static char text_string[32] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_VALUES) {
|
||||
sprintf(text_string, "AV-%lu", object_instance);
|
||||
@@ -149,14 +142,13 @@ char *Analog_Value_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
float real_value = (float) 1.414;
|
||||
float real_value = (float)1.414;
|
||||
unsigned object_index = 0;
|
||||
unsigned i = 0;
|
||||
bool state = false;
|
||||
@@ -170,14 +162,13 @@ int Analog_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_ANALOG_VALUE, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Value_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Analog_Value_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -287,10 +278,9 @@ int Analog_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
uint8_t level = ANALOG_LEVEL_NULL;
|
||||
@@ -304,9 +294,8 @@ bool Analog_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -329,19 +318,19 @@ bool Analog_Value_Write_Property(
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Real >= 0.0) && (value.type.Real <= 100.0)) {
|
||||
level = (uint8_t) value.type.Real;
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
level = (uint8_t)value.type.Real;
|
||||
object_index = Analog_Value_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority--;
|
||||
Present_Value[object_index] = level;
|
||||
/* 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) */
|
||||
main loop (i.e. check out of service before changing
|
||||
output) */
|
||||
status = true;
|
||||
} else if (priority == 6) {
|
||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||
|
||||
+37
-46
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 Input Objects customize for your use */
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
|
||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
|
||||
|
||||
static void Binary_Input_Initialize(
|
||||
void)
|
||||
static void Binary_Input_Initialize(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
unsigned i;
|
||||
@@ -55,8 +54,7 @@ static void Binary_Input_Initialize(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_INPUTS)
|
||||
return true;
|
||||
@@ -65,15 +63,13 @@ bool Binary_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Input_Count(
|
||||
void)
|
||||
unsigned Binary_Input_Count(void)
|
||||
{
|
||||
return MAX_BINARY_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances.*/
|
||||
uint32_t Binary_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Binary_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -81,8 +77,7 @@ uint32_t Binary_Input_Index_To_Instance(
|
||||
/* 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 Binary_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_INPUTS;
|
||||
|
||||
@@ -92,8 +87,7 @@ unsigned Binary_Input_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
unsigned index = 0;
|
||||
@@ -107,10 +101,9 @@ BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
char *Binary_Input_Name(
|
||||
uint32_t object_instance)
|
||||
char *Binary_Input_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_BINARY_INPUTS) {
|
||||
sprintf(text_string, "BI-%lu", object_instance);
|
||||
@@ -122,10 +115,9 @@ char *Binary_Input_Name(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object already exists, and has been bounds checked */
|
||||
int Binary_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
||||
@@ -140,15 +132,14 @@ int Binary_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_INPUT, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
/* note: object name must be unique in our device */
|
||||
characterstring_init_ansi(&char_string,
|
||||
Binary_Input_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Binary_Input_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
|
||||
+46
-59
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/basic/object/bv.h"
|
||||
@@ -40,8 +40,7 @@
|
||||
|
||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_VALUES];
|
||||
|
||||
static void Binary_Value_Initialize(
|
||||
void)
|
||||
static void Binary_Value_Initialize(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
unsigned i;
|
||||
@@ -55,8 +54,7 @@ static void Binary_Value_Initialize(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_VALUES)
|
||||
return true;
|
||||
@@ -65,22 +63,19 @@ bool Binary_Value_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Value_Count(
|
||||
void)
|
||||
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)
|
||||
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 Binary_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_VALUES;
|
||||
|
||||
@@ -90,8 +85,7 @@ unsigned Binary_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
|
||||
@@ -104,10 +98,9 @@ BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Binary_Value_Name(
|
||||
uint32_t object_instance)
|
||||
char *Binary_Value_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_BINARY_VALUES) {
|
||||
sprintf(text_string, "BV-%lu", object_instance);
|
||||
@@ -118,11 +111,10 @@ char *Binary_Value_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Binary_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
@@ -140,16 +132,15 @@ int Binary_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_VALUE, rpdata->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:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Binary_Value_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Binary_Value_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -158,8 +149,7 @@ int Binary_Value_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
present_value =
|
||||
Binary_Value_Present_Value(rpdata->object_instance);
|
||||
present_value = Binary_Value_Present_Value(rpdata->object_instance);
|
||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
@@ -200,10 +190,9 @@ int Binary_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Binary_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
BACNET_BINARY_PV level = BINARY_NULL;
|
||||
@@ -216,9 +205,8 @@ bool Binary_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -241,13 +229,12 @@ bool Binary_Value_Write_Property(
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Enumerated >= MIN_BINARY_PV) &&
|
||||
(value.type.Enumerated <= MAX_BINARY_PV)) {
|
||||
level = value.type.Enumerated;
|
||||
object_index =
|
||||
Binary_Value_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
object_index = Binary_Value_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority--;
|
||||
/* NOTE: this Binary value has no priority array */
|
||||
Present_Value[object_index] = level;
|
||||
|
||||
+97
-128
@@ -1,36 +1,36 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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 <string.h> /* for memmove */
|
||||
#include <string.h> /* for memmove */
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacstr.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/apdu.h"
|
||||
#include "bacnet/datalink/dlmstp.h"
|
||||
#include "rs485.h"
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/dcc.h"
|
||||
#include "bacnet/version.h"
|
||||
#include "bacnet/basic/object/device.h" /* me */
|
||||
#include "bacnet/basic/object/device.h" /* me */
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
@@ -54,8 +54,7 @@ static uint8_t Database_Revision;
|
||||
BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
||||
static char Reinit_Password[16] = "filister";
|
||||
|
||||
bool Device_Reinitialize(
|
||||
BACNET_REINITIALIZE_DEVICE_DATA * rd_data)
|
||||
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -98,16 +97,14 @@ bool Device_Reinitialize(
|
||||
return status;
|
||||
}
|
||||
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(
|
||||
void)
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(void)
|
||||
{
|
||||
return Reinitialize_State;
|
||||
}
|
||||
|
||||
void Device_Init(
|
||||
object_functions_t * object_table)
|
||||
void Device_Init(object_functions_t *object_table)
|
||||
{
|
||||
(void) object_table;
|
||||
(void)object_table;
|
||||
Reinitialize_State = BACNET_REINIT_IDLE;
|
||||
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
||||
/* FIXME: Get the data from the eeprom */
|
||||
@@ -118,14 +115,12 @@ void Device_Init(
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
@@ -144,66 +139,56 @@ bool Device_Set_Object_Instance_Number(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return (Object_Instance_Number == object_id);
|
||||
}
|
||||
|
||||
BACNET_DEVICE_STATUS Device_System_Status(
|
||||
void)
|
||||
BACNET_DEVICE_STATUS Device_System_Status(void)
|
||||
{
|
||||
return System_Status;
|
||||
}
|
||||
|
||||
int Device_Set_System_Status(
|
||||
BACNET_DEVICE_STATUS status,
|
||||
bool local)
|
||||
int Device_Set_System_Status(BACNET_DEVICE_STATUS status, bool local)
|
||||
{
|
||||
if (status < MAX_DEVICE_STATUS) {
|
||||
System_Status = status;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Version(
|
||||
void)
|
||||
uint8_t Device_Protocol_Version(void)
|
||||
{
|
||||
return BACNET_PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Revision(
|
||||
void)
|
||||
uint8_t Device_Protocol_Revision(void)
|
||||
{
|
||||
return BACNET_PROTOCOL_REVISION;
|
||||
}
|
||||
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(
|
||||
void)
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
|
||||
{
|
||||
return SEGMENTATION_NONE;
|
||||
}
|
||||
|
||||
uint32_t Device_Database_Revision(
|
||||
void)
|
||||
uint32_t Device_Database_Revision(void)
|
||||
{
|
||||
return Database_Revision;
|
||||
}
|
||||
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
/* FIXME: add objects as needed */
|
||||
/* FIXME: add objects as needed */
|
||||
count += Binary_Value_Count();
|
||||
count += Analog_Input_Count();
|
||||
count += Binary_Input_Count();
|
||||
@@ -215,9 +200,7 @@ unsigned Device_Object_List_Count(
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
bool Device_Object_List_Identifier(
|
||||
uint32_t array_index,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * instance)
|
||||
uint32_t array_index, BACNET_OBJECT_TYPE *object_type, uint32_t *instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t object_index = 0;
|
||||
@@ -287,13 +270,12 @@ bool Device_Object_List_Identifier(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
static char string_buffer[28];
|
||||
static BACNET_CHARACTER_STRING char_string;
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
uint32_t i = 0;
|
||||
BACNET_OBJECT_TYPE object_type = OBJECT_NONE;
|
||||
@@ -313,12 +295,11 @@ int Device_Read_Property_Local(
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_DEVICE, Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "PIC18F6720 Device");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "PIC18F6720 Device");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
@@ -327,68 +308,64 @@ int Device_Read_Property_Local(
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "BACnet Demo");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "BACnet Demo");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_System_Status());
|
||||
encode_application_enumerated(&apdu[0], Device_System_Status());
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
(void) strcpypgm2ram(&string_buffer[0], BACNET_VENDOR_NAME);
|
||||
(void)strcpypgm2ram(&string_buffer[0], BACNET_VENDOR_NAME);
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "GNU Demo");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "GNU Demo");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], BACNET_VERSION_TEXT);
|
||||
(void)strcpypgm2ram(&string_buffer[0], BACNET_VERSION_TEXT);
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "1.0");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "1.0");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_LOCATION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "USA");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "USA");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Protocol_Version());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Protocol_Version());
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Protocol_Revision());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Protocol_Revision());
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported(i));
|
||||
bitstring_set_bit(
|
||||
&bit_string, (uint8_t)i, apdu_service_supported(i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -398,7 +375,7 @@ int Device_Read_Property_Local(
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
@@ -419,11 +396,10 @@ int Device_Read_Property_Local(
|
||||
/* your maximum APDU size. */
|
||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
if (Device_Object_List_Identifier(i, &object_type,
|
||||
&instance)) {
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
i, &object_type, &instance)) {
|
||||
len = encode_application_object_id(
|
||||
&apdu[apdu_len], object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
@@ -442,11 +418,10 @@ int Device_Read_Property_Local(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(rpdata->array_index,
|
||||
&object_type, &instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
rpdata->array_index, &object_type, &instance))
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], object_type, instance);
|
||||
else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
@@ -458,9 +433,8 @@ int Device_Read_Property_Local(
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_Segmentation_Supported());
|
||||
apdu_len = encode_application_enumerated(
|
||||
&apdu[0], Device_Segmentation_Supported());
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout());
|
||||
@@ -472,14 +446,12 @@ int Device_Read_Property_Local(
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Database_Revision());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Database_Revision());
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
dlmstp_max_info_frames());
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len =
|
||||
@@ -496,14 +468,14 @@ int Device_Read_Property_Local(
|
||||
case PROP_UTC_OFFSET:
|
||||
/* Note: BACnet Time Zone is offset of local time and UTC,
|
||||
rather than offset of GMT. It is expressed in minutes */
|
||||
apdu_len = encode_application_signed(&apdu[0], 5 * 60 /* EST */ );
|
||||
apdu_len = encode_application_signed(&apdu[0], 5 * 60 /* EST */);
|
||||
break;
|
||||
case PROP_LOCAL_DATE:
|
||||
/* FIXME: if you support date */
|
||||
local_date.year = 2006; /* AD */
|
||||
local_date.month = 4; /* Jan=1..Dec=12 */
|
||||
local_date.day = 11; /* 1..31 */
|
||||
local_date.wday = 0; /* 1=Mon..7=Sun */
|
||||
local_date.year = 2006; /* AD */
|
||||
local_date.month = 4; /* Jan=1..Dec=12 */
|
||||
local_date.day = 11; /* 1..31 */
|
||||
local_date.wday = 0; /* 1=Mon..7=Sun */
|
||||
apdu_len = encode_application_date(&apdu[0], &local_date);
|
||||
break;
|
||||
case PROP_DAYLIGHT_SAVINGS_STATUS:
|
||||
@@ -531,8 +503,7 @@ int Device_Read_Property_Local(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int Device_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
|
||||
@@ -572,10 +543,9 @@ int Device_Read_Property(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
@@ -585,9 +555,8 @@ bool Device_Write_Property_Local(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -606,8 +575,8 @@ bool Device_Write_Property_Local(
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.
|
||||
Object_Id.instance))) {
|
||||
(Device_Set_Object_Instance_Number(
|
||||
value.type.Object_Id.instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
@@ -660,10 +629,11 @@ bool Device_Write_Property_Local(
|
||||
if (len <= 20) {
|
||||
/* FIXME: set the name */
|
||||
/* Display_Set_Name(
|
||||
characterstring_value(&value.type.Character_String)); */
|
||||
/* FIXME: All the object names in a device must be unique.
|
||||
Disallow setting the Device Object Name to any objects in
|
||||
the device. */
|
||||
characterstring_value(&value.type.Character_String));
|
||||
*/
|
||||
/* FIXME: All the object names in a device must be
|
||||
unique. Disallow setting the Device Object Name to
|
||||
any objects in the device. */
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code =
|
||||
@@ -729,10 +699,9 @@ bool Device_Write_Property_Local(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* Ever the pessamist! */
|
||||
bool status = false; /* Ever the pessamist! */
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
/* initialize the default return values */
|
||||
|
||||
+58
-72
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
@@ -48,16 +48,18 @@ static DLMSTP_PACKET Receive_Buffer;
|
||||
volatile struct mstp_port_struct_t MSTP_Port;
|
||||
#pragma udata
|
||||
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
|
||||
#define INCREMENT_AND_LIMIT_UINT16(x) \
|
||||
{ \
|
||||
if (x < 0xFFFF) \
|
||||
x++; \
|
||||
}
|
||||
|
||||
void dlmstp_millisecond_timer(
|
||||
void)
|
||||
void dlmstp_millisecond_timer(void)
|
||||
{
|
||||
INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer);
|
||||
}
|
||||
|
||||
void dlmstp_reinit(
|
||||
void)
|
||||
void dlmstp_reinit(void)
|
||||
{
|
||||
RS485_Reinit();
|
||||
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
|
||||
@@ -65,8 +67,7 @@ void dlmstp_reinit(
|
||||
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
|
||||
}
|
||||
|
||||
void dlmstp_init(
|
||||
void)
|
||||
void dlmstp_init(void)
|
||||
{
|
||||
uint8_t data;
|
||||
|
||||
@@ -79,24 +80,22 @@ void dlmstp_init(
|
||||
MSTP_Init(&MSTP_Port);
|
||||
}
|
||||
|
||||
void dlmstp_cleanup(
|
||||
void)
|
||||
void dlmstp_cleanup(void)
|
||||
{
|
||||
/* nothing to do for static buffers */
|
||||
}
|
||||
|
||||
/* returns number of bytes sent on success, zero on failure */
|
||||
int dlmstp_send_pdu(
|
||||
BACNET_ADDRESS * dest, /* destination address */
|
||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||
uint8_t * pdu, /* any data to be sent - may be null */
|
||||
int dlmstp_send_pdu(BACNET_ADDRESS *dest, /* destination address */
|
||||
BACNET_NPDU_DATA *npdu_data, /* network information */
|
||||
uint8_t *pdu, /* any data to be sent - may be null */
|
||||
unsigned pdu_len)
|
||||
{ /* number of bytes of data */
|
||||
{ /* number of bytes of data */
|
||||
int bytes_sent = 0;
|
||||
unsigned npdu_len = 0;
|
||||
uint8_t frame_type = 0;
|
||||
BACNET_ADDRESS src;
|
||||
unsigned i = 0; /* loop counter */
|
||||
unsigned i = 0; /* loop counter */
|
||||
|
||||
if (MSTP_Port.TxReady == false) {
|
||||
if (npdu_data->data_expecting_reply)
|
||||
@@ -115,8 +114,7 @@ int dlmstp_send_pdu(
|
||||
if ((MAX_HEADER + pdu_len) > MAX_MPDU) {
|
||||
return -4;
|
||||
}
|
||||
bytes_sent =
|
||||
MSTP_Create_Frame((uint8_t *) & MSTP_Port.TxBuffer[0],
|
||||
bytes_sent = MSTP_Create_Frame((uint8_t *)&MSTP_Port.TxBuffer[0],
|
||||
sizeof(MSTP_Port.TxBuffer), MSTP_Port.TxFrameType,
|
||||
MSTP_Port.TxDestination, MSTP_Port.This_Station, pdu, pdu_len);
|
||||
MSTP_Port.TxLength = bytes_sent;
|
||||
@@ -127,8 +125,7 @@ int dlmstp_send_pdu(
|
||||
return bytes_sent;
|
||||
}
|
||||
|
||||
void dlmstp_task(
|
||||
void)
|
||||
void dlmstp_task(void)
|
||||
{
|
||||
bool bytes_remaining;
|
||||
bool received_frame;
|
||||
@@ -139,8 +136,8 @@ void dlmstp_task(
|
||||
do {
|
||||
bytes_remaining = RS485_Check_UART_Data(&MSTP_Port);
|
||||
MSTP_Receive_Frame_FSM(&MSTP_Port);
|
||||
received_frame = MSTP_Port.ReceivedValidFrame ||
|
||||
MSTP_Port.ReceivedInvalidFrame;
|
||||
received_frame =
|
||||
MSTP_Port.ReceivedValidFrame || MSTP_Port.ReceivedInvalidFrame;
|
||||
if (received_frame)
|
||||
break;
|
||||
} while (bytes_remaining);
|
||||
@@ -167,9 +164,7 @@ void dlmstp_task(
|
||||
return;
|
||||
}
|
||||
|
||||
void dlmstp_fill_bacnet_address(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t mstp_address)
|
||||
void dlmstp_fill_bacnet_address(BACNET_ADDRESS *src, uint8_t mstp_address)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
@@ -193,19 +188,17 @@ void dlmstp_fill_bacnet_address(
|
||||
}
|
||||
|
||||
/* for the MS/TP state machine to use for putting received data */
|
||||
uint16_t dlmstp_put_receive(
|
||||
uint8_t src, /* source MS/TP address */
|
||||
uint8_t * pdu, /* PDU data */
|
||||
uint16_t dlmstp_put_receive(uint8_t src, /* source MS/TP address */
|
||||
uint8_t *pdu, /* PDU data */
|
||||
uint16_t pdu_len)
|
||||
{ /* amount of PDU data */
|
||||
{ /* amount of PDU data */
|
||||
/* PDU is already in the Receive_Buffer */
|
||||
dlmstp_fill_bacnet_address(&Receive_Buffer.address, src);
|
||||
Receive_Buffer.pdu_len = pdu_len;
|
||||
Receive_Buffer.ready = true;
|
||||
}
|
||||
|
||||
void dlmstp_set_my_address(
|
||||
uint8_t mac_address)
|
||||
void dlmstp_set_my_address(uint8_t mac_address)
|
||||
{
|
||||
/* Master Nodes can only have address 0-127 */
|
||||
if (mac_address <= 127) {
|
||||
@@ -222,8 +215,7 @@ void dlmstp_set_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_my_address(
|
||||
void)
|
||||
uint8_t dlmstp_my_address(void)
|
||||
{
|
||||
return MSTP_Port.This_Station;
|
||||
}
|
||||
@@ -235,8 +227,7 @@ uint8_t dlmstp_my_address(
|
||||
/* nodes. This may be used to allocate more or less of the available link */
|
||||
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
||||
/* node, its value shall be 1. */
|
||||
void dlmstp_set_max_info_frames(
|
||||
uint8_t max_info_frames)
|
||||
void dlmstp_set_max_info_frames(uint8_t max_info_frames)
|
||||
{
|
||||
if (max_info_frames >= 1) {
|
||||
MSTP_Port.Nmax_info_frames = max_info_frames;
|
||||
@@ -250,8 +241,7 @@ void dlmstp_set_max_info_frames(
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned dlmstp_max_info_frames(
|
||||
void)
|
||||
unsigned dlmstp_max_info_frames(void)
|
||||
{
|
||||
return MSTP_Port.Nmax_info_frames;
|
||||
}
|
||||
@@ -261,8 +251,7 @@ unsigned dlmstp_max_info_frames(
|
||||
/* allowable address for master nodes. The value of Max_Master shall be */
|
||||
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
||||
/* its value shall be 127. */
|
||||
void dlmstp_set_max_master(
|
||||
uint8_t max_master)
|
||||
void dlmstp_set_max_master(uint8_t max_master)
|
||||
{
|
||||
if (max_master <= 127) {
|
||||
if (MSTP_Port.This_Station <= max_master) {
|
||||
@@ -278,20 +267,18 @@ void dlmstp_set_max_master(
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t dlmstp_max_master(
|
||||
void)
|
||||
uint8_t dlmstp_max_master(void)
|
||||
{
|
||||
return MSTP_Port.Nmax_master;
|
||||
}
|
||||
|
||||
void dlmstp_get_my_address(
|
||||
BACNET_ADDRESS * my_address)
|
||||
void dlmstp_get_my_address(BACNET_ADDRESS *my_address)
|
||||
{
|
||||
int i = 0; /* counter */
|
||||
int i = 0; /* counter */
|
||||
|
||||
my_address->mac_len = 1;
|
||||
my_address->mac[0] = MSTP_Port.This_Station;
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->net = 0; /* local only, no routing */
|
||||
my_address->len = 0;
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
my_address->adr[i] = 0;
|
||||
@@ -300,16 +287,15 @@ void dlmstp_get_my_address(
|
||||
return;
|
||||
}
|
||||
|
||||
void dlmstp_get_broadcast_address(
|
||||
BACNET_ADDRESS * dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
void dlmstp_get_broadcast_address(BACNET_ADDRESS *dest)
|
||||
{ /* destination address */
|
||||
int i = 0; /* counter */
|
||||
|
||||
if (dest) {
|
||||
dest->mac_len = 1;
|
||||
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
|
||||
dest->net = BACNET_BROADCAST_NETWORK;
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
dest->len = 0; /* always zero when DNET is broadcast */
|
||||
for (i = 0; i < MAX_MAC_LEN; i++) {
|
||||
dest->adr[i] = 0;
|
||||
}
|
||||
|
||||
+84
-100
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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 "stdint.h"
|
||||
#include "hardware.h"
|
||||
#include "rs485.h"
|
||||
@@ -30,42 +30,32 @@
|
||||
/* from main.c */
|
||||
extern volatile uint8_t Milliseconds;
|
||||
|
||||
void InterruptHandlerHigh(
|
||||
void);
|
||||
void InterruptHandlerLow(
|
||||
void);
|
||||
void Interrupt_Timer2(
|
||||
void);
|
||||
void Interrupt_Timer3(
|
||||
void);
|
||||
void Interrupt_Timer4(
|
||||
void);
|
||||
void Interrupt_USART_Rx(
|
||||
void);
|
||||
void Interrupt_USART_Tx(
|
||||
void);
|
||||
void Interrupt_CCP2(
|
||||
void);
|
||||
void INT0_Interrupt(
|
||||
void);
|
||||
void InterruptHandlerHigh(void);
|
||||
void InterruptHandlerLow(void);
|
||||
void Interrupt_Timer2(void);
|
||||
void Interrupt_Timer3(void);
|
||||
void Interrupt_Timer4(void);
|
||||
void Interrupt_USART_Rx(void);
|
||||
void Interrupt_USART_Tx(void);
|
||||
void Interrupt_CCP2(void);
|
||||
void INT0_Interrupt(void);
|
||||
|
||||
#pragma code InterruptVectorHigh = 0x08
|
||||
void InterruptVectorHigh(
|
||||
void)
|
||||
void InterruptVectorHigh(void)
|
||||
{
|
||||
/* jump to interrupt routine */
|
||||
_asm goto InterruptHandlerHigh _endasm}
|
||||
_asm goto InterruptHandlerHigh _endasm
|
||||
}
|
||||
#pragma code
|
||||
#pragma code InterruptVectorLow = 0x18
|
||||
void InterruptVectorLow(
|
||||
void)
|
||||
void InterruptVectorLow(void)
|
||||
{
|
||||
/* jump to interrupt routine */
|
||||
_asm goto InterruptHandlerLow _endasm}
|
||||
_asm goto InterruptHandlerLow _endasm
|
||||
}
|
||||
#pragma code
|
||||
#pragma interrupt InterruptHandlerHigh
|
||||
void InterruptHandlerHigh(
|
||||
void)
|
||||
void InterruptHandlerHigh(void)
|
||||
{
|
||||
#if 0
|
||||
/* check for USART Rx int */
|
||||
@@ -92,11 +82,10 @@ void InterruptHandlerHigh(
|
||||
}
|
||||
}
|
||||
|
||||
#pragma interruptlow InterruptHandlerLow save = PROD, section(".tmpdata"), TABLAT, TBLPTR, section \
|
||||
("MATH_DATA")
|
||||
#pragma interruptlow InterruptHandlerLow save = PROD, section(".tmpdata"), \
|
||||
TABLAT, TBLPTR, section("MATH_DATA")
|
||||
|
||||
void InterruptHandlerLow(
|
||||
void)
|
||||
void InterruptHandlerLow(void)
|
||||
{
|
||||
/* check for timer2 int */
|
||||
if ((PIR1bits.TMR2IF) && (PIE1bits.TMR2IE)) {
|
||||
@@ -133,74 +122,69 @@ void InterruptHandlerLow(
|
||||
RS485_Interrupt_Rx();
|
||||
}
|
||||
|
||||
/* Unused Interrupts
|
||||
//check for timer1 int
|
||||
if ((PIR1bits.TMR1IF) && (PIE1bits.TMR1IE))
|
||||
{
|
||||
PIR1bits.TMR1IF = 0;
|
||||
Interrupt_Timer1();
|
||||
}
|
||||
/* Unused Interrupts
|
||||
//check for timer1 int
|
||||
if ((PIR1bits.TMR1IF) && (PIE1bits.TMR1IE))
|
||||
{
|
||||
PIR1bits.TMR1IF = 0;
|
||||
Interrupt_Timer1();
|
||||
}
|
||||
|
||||
//check for compare int
|
||||
if ((PIR1bits.CCP1IF) && (PIE1bits.CCP1IE))
|
||||
{
|
||||
PIR1bits.CCP1IF = 0;
|
||||
Interrupt_CCP1();
|
||||
}
|
||||
//check for compare int
|
||||
if ((PIR1bits.CCP1IF) && (PIE1bits.CCP1IE))
|
||||
{
|
||||
PIR1bits.CCP1IF = 0;
|
||||
Interrupt_CCP1();
|
||||
}
|
||||
|
||||
//check for compare int
|
||||
if ((PIR3bits.CCP3IF) && (PIE3bits.CCP3IE))
|
||||
{
|
||||
PIR3bits.CCP3IF = 0;
|
||||
Interrupt_CCP3();
|
||||
}
|
||||
//check for compare int
|
||||
if ((PIR3bits.CCP3IF) && (PIE3bits.CCP3IE))
|
||||
{
|
||||
PIR3bits.CCP3IF = 0;
|
||||
Interrupt_CCP3();
|
||||
}
|
||||
|
||||
//check for compare int
|
||||
if ((PIR3bits.CCP4IF) && (PIE3bits.CCP4IE))
|
||||
{
|
||||
PIR3bits.CCP4IF = 0;
|
||||
//check for compare int
|
||||
if ((PIR3bits.CCP4IF) && (PIE3bits.CCP4IE))
|
||||
{
|
||||
PIR3bits.CCP4IF = 0;
|
||||
|
||||
Interrupt_CCP4();
|
||||
}
|
||||
Interrupt_CCP4();
|
||||
}
|
||||
|
||||
//check for AD int
|
||||
if ((PIR1bits.ADIF) && (PIE1bits.ADIE))
|
||||
{
|
||||
PIR1bits.ADIF = 0;
|
||||
Interrupt_ADC();
|
||||
}
|
||||
//check for AD int
|
||||
if ((PIR1bits.ADIF) && (PIE1bits.ADIE))
|
||||
{
|
||||
PIR1bits.ADIF = 0;
|
||||
Interrupt_ADC();
|
||||
}
|
||||
|
||||
//check for MSSP int
|
||||
if ((PIR1bits.SSPIF) && (PIE1bits.SSPIE))
|
||||
{
|
||||
PIR1bits.SSPIF = 0;
|
||||
Interrupt_SSP();
|
||||
}
|
||||
//check for MSSP int
|
||||
if ((PIR1bits.SSPIF) && (PIE1bits.SSPIE))
|
||||
{
|
||||
PIR1bits.SSPIF = 0;
|
||||
Interrupt_SSP();
|
||||
}
|
||||
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
void Interrupt_Timer2(
|
||||
void)
|
||||
void Interrupt_Timer2(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Interrupt_Timer3(
|
||||
void)
|
||||
void Interrupt_Timer3(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Timer4 is set to go off every 1ms. This is our system tick */
|
||||
void Interrupt_Timer4(
|
||||
void)
|
||||
void Interrupt_Timer4(void)
|
||||
{
|
||||
/* Milisecond is our system tick */
|
||||
if (Milliseconds < 0xFF)
|
||||
++Milliseconds;
|
||||
}
|
||||
|
||||
void Interrupt_CCP2(
|
||||
void)
|
||||
void Interrupt_CCP2(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
+30
-36
@@ -1,31 +1,31 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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 <string.h> /* for memmove */
|
||||
#include <string.h> /* for memmove */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "stdint.h"
|
||||
@@ -92,8 +92,7 @@
|
||||
volatile uint8_t Milliseconds = 0;
|
||||
volatile uint8_t Zero_Cross_Timeout = 0;
|
||||
|
||||
void Reinitialize(
|
||||
void)
|
||||
void Reinitialize(void)
|
||||
{
|
||||
uint8_t i;
|
||||
char name = 0;
|
||||
@@ -101,8 +100,7 @@ void Reinitialize(
|
||||
_asm reset _endasm return;
|
||||
}
|
||||
|
||||
void Global_Int(
|
||||
enum INT_STATE state)
|
||||
void Global_Int(enum INT_STATE state)
|
||||
{
|
||||
static uint8_t intstate = 0;
|
||||
|
||||
@@ -125,8 +123,7 @@ void Global_Int(
|
||||
}
|
||||
}
|
||||
|
||||
void Hardware_Initialize(
|
||||
void)
|
||||
void Hardware_Initialize(void)
|
||||
{
|
||||
TRISA = 0x00;
|
||||
TRISB = 0x00;
|
||||
@@ -153,8 +150,7 @@ void Hardware_Initialize(
|
||||
Global_Int(INT_ENABLED);
|
||||
}
|
||||
|
||||
void Initialize_Variables(
|
||||
void)
|
||||
void Initialize_Variables(void)
|
||||
{
|
||||
/* Check to see if we need to initialize our eeproms */
|
||||
ENABLE_TIMER4_INT();
|
||||
@@ -164,8 +160,7 @@ void Initialize_Variables(
|
||||
Milliseconds = 0;
|
||||
}
|
||||
|
||||
void MainTasks(
|
||||
void)
|
||||
void MainTasks(void)
|
||||
{
|
||||
static uint16_t millisecond_counter = 0;
|
||||
/* Handle our millisecond counters */
|
||||
@@ -180,8 +175,7 @@ void MainTasks(
|
||||
}
|
||||
}
|
||||
|
||||
void main(
|
||||
void)
|
||||
void main(void)
|
||||
{
|
||||
RCONbits.NOT_POR = 1;
|
||||
RCONbits.NOT_RI = 1;
|
||||
|
||||
+163
-143
@@ -150,25 +150,27 @@
|
||||
#define Tusage_timeout 20
|
||||
|
||||
/* 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++; \
|
||||
}
|
||||
|
||||
bool MSTP_Line_Active(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
return (mstp_port->EventCount > Nmin_octets);
|
||||
}
|
||||
|
||||
unsigned MSTP_Create_Frame(
|
||||
uint8_t * buffer, /* where frame is loaded */
|
||||
unsigned buffer_len, /* amount of space available */
|
||||
unsigned MSTP_Create_Frame(uint8_t *buffer, /* where frame is loaded */
|
||||
unsigned buffer_len, /* amount of space available */
|
||||
uint8_t frame_type, /* type of frame to send - see defines */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t * data, /* any data to be sent - may be null */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t *data, /* any data to be sent - may be null */
|
||||
unsigned data_len)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t crc8 = 0xFF; /* used to calculate the crc value */
|
||||
uint16_t crc16 = 0xFFFF; /* used to calculate the crc value */
|
||||
unsigned index = 0; /* used to load the data portion of the frame */
|
||||
|
||||
/* not enough to do a header */
|
||||
@@ -209,47 +211,48 @@ unsigned MSTP_Create_Frame(
|
||||
return 0;
|
||||
}
|
||||
|
||||
return index; /* returns the frame length */
|
||||
return index; /* returns the frame length */
|
||||
}
|
||||
|
||||
void MSTP_Create_And_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port to send from */
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port to send from */
|
||||
uint8_t frame_type, /* type of frame to send - see defines */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t * data, /* any data to be sent - may be null */
|
||||
uint8_t destination, /* destination address */
|
||||
uint8_t source, /* source address */
|
||||
uint8_t *data, /* any data to be sent - may be null */
|
||||
unsigned data_len)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t buffer[MAX_MPDU] = { 0 }; /* buffer for sending */
|
||||
uint16_t len = 0; /* number of bytes to send */
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint8_t buffer[MAX_MPDU] = { 0 }; /* buffer for sending */
|
||||
uint16_t len = 0; /* number of bytes to send */
|
||||
|
||||
len = (uint16_t) MSTP_Create_Frame(&buffer[0], /* where frame is loaded */
|
||||
len = (uint16_t)MSTP_Create_Frame(&buffer[0], /* where frame is loaded */
|
||||
sizeof(buffer), /* amount of space available */
|
||||
frame_type, /* type of frame to send - see defines */
|
||||
destination, /* destination address */
|
||||
frame_type, /* type of frame to send - see defines */
|
||||
destination, /* destination address */
|
||||
source, /* source address */
|
||||
data, /* any data to be sent - may be null */
|
||||
data_len); /* number of bytes of data (up to 501) */
|
||||
data, /* any data to be sent - may be null */
|
||||
data_len); /* number of bytes of data (up to 501) */
|
||||
|
||||
RS485_Send_Frame(mstp_port, &buffer[0], len);
|
||||
/* FIXME: be sure to reset SilenceTimer after each octet is sent! */
|
||||
}
|
||||
|
||||
void MSTP_Receive_Frame_FSM(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
#if PRINT_ENABLED_RECEIVE_DATA
|
||||
static MSTP_RECEIVE_STATE receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
#endif
|
||||
#if PRINT_ENABLED_RECEIVE
|
||||
fprintf(stderr,
|
||||
"MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u Silence=%u\n",
|
||||
"MSTP Rx: State=%s Data=%02X hCRC=%02X Index=%u EC=%u DateLen=%u "
|
||||
"Silence=%u\n",
|
||||
mstptext_receive_state(mstp_port->receive_state),
|
||||
mstp_port->DataRegister, mstp_port->HeaderCRC, mstp_port->Index,
|
||||
mstp_port->EventCount, mstp_port->DataLength, mstp_port->SilenceTimer);
|
||||
#endif
|
||||
switch (mstp_port->receive_state) {
|
||||
/* In the IDLE state, the node waits for the beginning of a frame. */
|
||||
/* In the IDLE state, the node waits for the beginning of a frame.
|
||||
*/
|
||||
case MSTP_RECEIVE_STATE_IDLE:
|
||||
/* EatAnError */
|
||||
if (mstp_port->ReceiveError == true) {
|
||||
@@ -283,7 +286,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* In the PREAMBLE state, the node waits for the second octet of the preamble. */
|
||||
/* In the PREAMBLE state, the node waits for the second octet of the
|
||||
* preamble. */
|
||||
case MSTP_RECEIVE_STATE_PREAMBLE:
|
||||
/* Timeout */
|
||||
if (mstp_port->SilenceTimer > Tframe_abort) {
|
||||
@@ -330,11 +334,13 @@ void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* In the HEADER state, the node waits for the fixed message header. */
|
||||
/* In the HEADER state, the node waits for the fixed message header.
|
||||
*/
|
||||
case MSTP_RECEIVE_STATE_HEADER:
|
||||
/* Timeout */
|
||||
if (mstp_port->SilenceTimer > Tframe_abort) {
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the reception of a
|
||||
* frame */
|
||||
mstp_port->ReceivedInvalidFrame = true;
|
||||
/* wait for the start of a frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -344,7 +350,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
mstp_port->ReceiveError = false;
|
||||
mstp_port->SilenceTimer = 0;
|
||||
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the reception of a
|
||||
* frame */
|
||||
mstp_port->ReceivedInvalidFrame = true;
|
||||
/* wait for the start of a frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -356,9 +363,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
if (mstp_port->Index == 0) {
|
||||
mstp_port->SilenceTimer = 0;
|
||||
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
|
||||
mstp_port->HeaderCRC =
|
||||
CRC_Calc_Header(mstp_port->DataRegister,
|
||||
mstp_port->HeaderCRC);
|
||||
mstp_port->HeaderCRC = CRC_Calc_Header(
|
||||
mstp_port->DataRegister, mstp_port->HeaderCRC);
|
||||
mstp_port->FrameType = mstp_port->DataRegister;
|
||||
mstp_port->DataAvailable = false;
|
||||
mstp_port->Index = 1;
|
||||
@@ -368,9 +374,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
else if (mstp_port->Index == 1) {
|
||||
mstp_port->SilenceTimer = 0;
|
||||
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
|
||||
mstp_port->HeaderCRC =
|
||||
CRC_Calc_Header(mstp_port->DataRegister,
|
||||
mstp_port->HeaderCRC);
|
||||
mstp_port->HeaderCRC = CRC_Calc_Header(
|
||||
mstp_port->DataRegister, mstp_port->HeaderCRC);
|
||||
mstp_port->DestinationAddress = mstp_port->DataRegister;
|
||||
mstp_port->DataAvailable = false;
|
||||
mstp_port->Index = 2;
|
||||
@@ -380,9 +385,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
else if (mstp_port->Index == 2) {
|
||||
mstp_port->SilenceTimer = 0;
|
||||
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
|
||||
mstp_port->HeaderCRC =
|
||||
CRC_Calc_Header(mstp_port->DataRegister,
|
||||
mstp_port->HeaderCRC);
|
||||
mstp_port->HeaderCRC = CRC_Calc_Header(
|
||||
mstp_port->DataRegister, mstp_port->HeaderCRC);
|
||||
mstp_port->SourceAddress = mstp_port->DataRegister;
|
||||
mstp_port->DataAvailable = false;
|
||||
mstp_port->Index = 3;
|
||||
@@ -392,9 +396,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
else if (mstp_port->Index == 3) {
|
||||
mstp_port->SilenceTimer = 0;
|
||||
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
|
||||
mstp_port->HeaderCRC =
|
||||
CRC_Calc_Header(mstp_port->DataRegister,
|
||||
mstp_port->HeaderCRC);
|
||||
mstp_port->HeaderCRC = CRC_Calc_Header(
|
||||
mstp_port->DataRegister, mstp_port->HeaderCRC);
|
||||
mstp_port->DataLength = mstp_port->DataRegister * 256;
|
||||
mstp_port->DataAvailable = false;
|
||||
mstp_port->Index = 4;
|
||||
@@ -404,9 +407,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
else if (mstp_port->Index == 4) {
|
||||
mstp_port->SilenceTimer = 0;
|
||||
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
|
||||
mstp_port->HeaderCRC =
|
||||
CRC_Calc_Header(mstp_port->DataRegister,
|
||||
mstp_port->HeaderCRC);
|
||||
mstp_port->HeaderCRC = CRC_Calc_Header(
|
||||
mstp_port->DataRegister, mstp_port->HeaderCRC);
|
||||
mstp_port->DataLength += mstp_port->DataRegister;
|
||||
mstp_port->DataAvailable = false;
|
||||
mstp_port->Index = 5;
|
||||
@@ -416,21 +418,21 @@ void MSTP_Receive_Frame_FSM(
|
||||
else if (mstp_port->Index == 5) {
|
||||
mstp_port->SilenceTimer = 0;
|
||||
INCREMENT_AND_LIMIT_UINT8(mstp_port->EventCount);
|
||||
mstp_port->HeaderCRC =
|
||||
CRC_Calc_Header(mstp_port->DataRegister,
|
||||
mstp_port->HeaderCRC);
|
||||
mstp_port->HeaderCRC = CRC_Calc_Header(
|
||||
mstp_port->DataRegister, mstp_port->HeaderCRC);
|
||||
mstp_port->DataAvailable = false;
|
||||
/* don't wait for next state - do it here */
|
||||
if (mstp_port->HeaderCRC != 0x55) {
|
||||
/* BadCRC */
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the
|
||||
* reception of a frame */
|
||||
mstp_port->ReceivedInvalidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
} else {
|
||||
if ((mstp_port->DestinationAddress ==
|
||||
mstp_port->This_Station)
|
||||
|| (mstp_port->DestinationAddress ==
|
||||
mstp_port->This_Station) ||
|
||||
(mstp_port->DestinationAddress ==
|
||||
MSTP_BROADCAST_ADDRESS)) {
|
||||
/* FrameTooLong */
|
||||
if (mstp_port->DataLength > MAX_MPDU) {
|
||||
@@ -443,7 +445,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
/* NoData */
|
||||
else if (mstp_port->DataLength == 0) {
|
||||
/* indicate that a frame with no data has been received */
|
||||
/* indicate that a frame with no data has been
|
||||
* received */
|
||||
mstp_port->ReceivedValidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state =
|
||||
@@ -465,7 +468,6 @@ void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/* not per MS/TP standard, but it is a case not covered */
|
||||
else {
|
||||
@@ -480,11 +482,13 @@ void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* In the DATA state, the node waits for the data portion of a frame. */
|
||||
/* In the DATA state, the node waits for the data portion of a
|
||||
* frame. */
|
||||
case MSTP_RECEIVE_STATE_DATA:
|
||||
/* Timeout */
|
||||
if (mstp_port->SilenceTimer > Tframe_abort) {
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the reception of a
|
||||
* frame */
|
||||
mstp_port->ReceivedInvalidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -493,7 +497,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
else if (mstp_port->ReceiveError == true) {
|
||||
mstp_port->ReceiveError = false;
|
||||
mstp_port->SilenceTimer = 0;
|
||||
/* indicate that an error has occurred during the reception of a frame */
|
||||
/* indicate that an error has occurred during the reception of a
|
||||
* frame */
|
||||
mstp_port->ReceivedInvalidFrame = true;
|
||||
/* wait for the start of the next frame. */
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -503,9 +508,8 @@ void MSTP_Receive_Frame_FSM(
|
||||
#endif
|
||||
/* DataOctet */
|
||||
if (mstp_port->Index < mstp_port->DataLength) {
|
||||
mstp_port->DataCRC =
|
||||
CRC_Calc_Data(mstp_port->DataRegister,
|
||||
mstp_port->DataCRC);
|
||||
mstp_port->DataCRC = CRC_Calc_Data(
|
||||
mstp_port->DataRegister, mstp_port->DataCRC);
|
||||
mstp_port->InputBuffer[mstp_port->Index] =
|
||||
mstp_port->DataRegister;
|
||||
mstp_port->Index++;
|
||||
@@ -513,17 +517,15 @@ void MSTP_Receive_Frame_FSM(
|
||||
}
|
||||
/* CRC1 */
|
||||
else if (mstp_port->Index == mstp_port->DataLength) {
|
||||
mstp_port->DataCRC =
|
||||
CRC_Calc_Data(mstp_port->DataRegister,
|
||||
mstp_port->DataCRC);
|
||||
mstp_port->DataCRC = CRC_Calc_Data(
|
||||
mstp_port->DataRegister, mstp_port->DataCRC);
|
||||
mstp_port->Index++;
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_DATA;
|
||||
}
|
||||
/* CRC2 */
|
||||
else if (mstp_port->Index == (mstp_port->DataLength + 1)) {
|
||||
mstp_port->DataCRC =
|
||||
CRC_Calc_Data(mstp_port->DataRegister,
|
||||
mstp_port->DataCRC);
|
||||
mstp_port->DataCRC = CRC_Calc_Data(
|
||||
mstp_port->DataRegister, mstp_port->DataCRC);
|
||||
/* STATE DATA CRC - no need for new state */
|
||||
/* indicate the complete reception of a valid frame */
|
||||
if (mstp_port->DataCRC == 0xF0B8)
|
||||
@@ -553,11 +555,10 @@ void MSTP_Receive_Frame_FSM(
|
||||
return;
|
||||
}
|
||||
|
||||
static bool mstp_compare_data_expecting_reply(
|
||||
uint8_t * request_pdu,
|
||||
static bool mstp_compare_data_expecting_reply(uint8_t *request_pdu,
|
||||
uint16_t request_pdu_len,
|
||||
uint8_t src_address,
|
||||
uint8_t * reply_pdu,
|
||||
uint8_t *reply_pdu,
|
||||
uint16_t reply_pdu_len,
|
||||
uint8_t dest_address)
|
||||
{
|
||||
@@ -578,9 +579,8 @@ static bool mstp_compare_data_expecting_reply(
|
||||
/* decode the request data */
|
||||
request.address.mac[0] = src_address;
|
||||
request.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&request_pdu[0], NULL, &request.address,
|
||||
&request.npdu_data);
|
||||
offset = npdu_decode(
|
||||
&request_pdu[0], NULL, &request.address, &request.npdu_data);
|
||||
if (request.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
@@ -597,8 +597,7 @@ static bool mstp_compare_data_expecting_reply(
|
||||
/* decode the reply data */
|
||||
reply.address.mac[0] = dest_address;
|
||||
reply.address.mac_len = 1;
|
||||
offset =
|
||||
npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
offset = npdu_decode(&reply_pdu[0], &reply.address, NULL, &reply.npdu_data);
|
||||
if (reply.npdu_data.network_layer_message) {
|
||||
return false;
|
||||
}
|
||||
@@ -639,7 +638,8 @@ static bool mstp_compare_data_expecting_reply(
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (request.npdu_data.protocol_version != reply.npdu_data.protocol_version) {
|
||||
if (request.npdu_data.protocol_version !=
|
||||
reply.npdu_data.protocol_version) {
|
||||
return false;
|
||||
}
|
||||
#if 0
|
||||
@@ -657,8 +657,7 @@ static bool mstp_compare_data_expecting_reply(
|
||||
}
|
||||
|
||||
/* returns true if we need to transition immediately */
|
||||
bool MSTP_Master_Node_FSM(
|
||||
volatile struct mstp_port_struct_t * mstp_port)
|
||||
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
int mtu_len = 0;
|
||||
int frame_type = 0;
|
||||
@@ -684,11 +683,12 @@ bool MSTP_Master_Node_FSM(
|
||||
if (mstp_port->master_state != master_state) {
|
||||
master_state = mstp_port->master_state;
|
||||
fprintf(stderr,
|
||||
"MSTP: TS=%02X[%02X] NS=%02X[%02X] PS=%02X[%02X] EC=%u TC=%u ST=%u %s\n",
|
||||
mstp_port->This_Station, next_this_station,
|
||||
mstp_port->Next_Station, next_next_station,
|
||||
mstp_port->Poll_Station, next_poll_station, mstp_port->EventCount,
|
||||
mstp_port->TokenCount, mstp_port->SilenceTimer,
|
||||
"MSTP: TS=%02X[%02X] NS=%02X[%02X] PS=%02X[%02X] EC=%u TC=%u ST=%u "
|
||||
"%s\n",
|
||||
mstp_port->This_Station, next_this_station, mstp_port->Next_Station,
|
||||
next_next_station, mstp_port->Poll_Station, next_poll_station,
|
||||
mstp_port->EventCount, mstp_port->TokenCount,
|
||||
mstp_port->SilenceTimer,
|
||||
mstptext_master_state(mstp_port->master_state));
|
||||
}
|
||||
#endif
|
||||
@@ -711,7 +711,7 @@ bool MSTP_Master_Node_FSM(
|
||||
/* LostToken */
|
||||
if (mstp_port->SilenceTimer >= Tno_token) {
|
||||
/* assume that the token has been lost */
|
||||
mstp_port->EventCount = 0; /* Addendum 135-2004d-8 */
|
||||
mstp_port->EventCount = 0; /* Addendum 135-2004d-8 */
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_NO_TOKEN;
|
||||
/* set the receive frame flags to false in case we received
|
||||
some bytes and had a timeout for some reason */
|
||||
@@ -727,16 +727,17 @@ bool MSTP_Master_Node_FSM(
|
||||
} else if (mstp_port->ReceivedValidFrame == true) {
|
||||
#if PRINT_ENABLED_MASTER
|
||||
fprintf(stderr,
|
||||
"MSTP: ReceivedValidFrame Src=%02X Dest=%02X DataLen=%u FC=%u ST=%u Type=%s\n",
|
||||
"MSTP: ReceivedValidFrame Src=%02X Dest=%02X DataLen=%u "
|
||||
"FC=%u ST=%u Type=%s\n",
|
||||
mstp_port->SourceAddress, mstp_port->DestinationAddress,
|
||||
mstp_port->DataLength, mstp_port->FrameCount,
|
||||
mstp_port->SilenceTimer,
|
||||
mstptext_frame_type(mstp_port->FrameType));
|
||||
#endif
|
||||
/* destined for me! */
|
||||
if ((mstp_port->DestinationAddress == mstp_port->This_Station)
|
||||
|| (mstp_port->DestinationAddress ==
|
||||
MSTP_BROADCAST_ADDRESS)) {
|
||||
if ((mstp_port->DestinationAddress ==
|
||||
mstp_port->This_Station) ||
|
||||
(mstp_port->DestinationAddress == MSTP_BROADCAST_ADDRESS)) {
|
||||
switch (mstp_port->FrameType) {
|
||||
/* ReceivedToken */
|
||||
case FRAME_TYPE_TOKEN:
|
||||
@@ -763,16 +764,18 @@ bool MSTP_Master_Node_FSM(
|
||||
}
|
||||
break;
|
||||
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
|
||||
/* indicate successful reception to the higher layers */
|
||||
/* indicate successful reception to the higher
|
||||
* layers */
|
||||
dlmstp_put_receive(mstp_port->SourceAddress,
|
||||
(uint8_t *) & mstp_port->InputBuffer[0],
|
||||
(uint8_t *)&mstp_port->InputBuffer[0],
|
||||
mstp_port->DataLength);
|
||||
break;
|
||||
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
|
||||
/*mstp_port->ReplyPostponedTimer = 0; */
|
||||
/* indicate successful reception to the higher layers */
|
||||
/* indicate successful reception to the higher
|
||||
* layers */
|
||||
dlmstp_put_receive(mstp_port->SourceAddress,
|
||||
(uint8_t *) & mstp_port->InputBuffer[0],
|
||||
(uint8_t *)&mstp_port->InputBuffer[0],
|
||||
mstp_port->DataLength);
|
||||
/* broadcast DER just remains IDLE */
|
||||
if (mstp_port->DestinationAddress !=
|
||||
@@ -786,7 +789,7 @@ bool MSTP_Master_Node_FSM(
|
||||
FRAME_TYPE_TEST_RESPONSE,
|
||||
mstp_port->SourceAddress,
|
||||
mstp_port->This_Station,
|
||||
(uint8_t *) & mstp_port->InputBuffer[0],
|
||||
(uint8_t *)&mstp_port->InputBuffer[0],
|
||||
mstp_port->DataLength);
|
||||
break;
|
||||
case FRAME_TYPE_TEST_RESPONSE:
|
||||
@@ -808,8 +811,8 @@ bool MSTP_Master_Node_FSM(
|
||||
transition_now = true;
|
||||
} else {
|
||||
uint8_t destination = mstp_port->TxBuffer[3];
|
||||
RS485_Send_Frame(mstp_port,
|
||||
(uint8_t *) & mstp_port->TxBuffer[0], mstp_port->TxLength);
|
||||
RS485_Send_Frame(mstp_port, (uint8_t *)&mstp_port->TxBuffer[0],
|
||||
mstp_port->TxLength);
|
||||
mstp_port->FrameCount++;
|
||||
switch (mstp_port->TxFrameType) {
|
||||
case FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY:
|
||||
@@ -845,8 +848,10 @@ bool MSTP_Master_Node_FSM(
|
||||
mstp_port->FrameCount = mstp_port->Nmax_info_frames;
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
/* Any retry of the data frame shall await the next entry */
|
||||
/* to the USE_TOKEN state. (Because of the length of the timeout, */
|
||||
/* this transition will cause the token to be passed regardless */
|
||||
/* to the USE_TOKEN state. (Because of the length of the
|
||||
* timeout, */
|
||||
/* this transition will cause the token to be passed regardless
|
||||
*/
|
||||
/* of the initial value of FrameCount.) */
|
||||
transition_now = true;
|
||||
} else {
|
||||
@@ -854,8 +859,7 @@ bool MSTP_Master_Node_FSM(
|
||||
/* InvalidFrame */
|
||||
/* error in frame reception */
|
||||
mstp_port->ReceivedInvalidFrame = false;
|
||||
mstp_port->master_state =
|
||||
MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
transition_now = true;
|
||||
} else if (mstp_port->ReceivedValidFrame == true) {
|
||||
if (mstp_port->DestinationAddress ==
|
||||
@@ -872,10 +876,14 @@ bool MSTP_Master_Node_FSM(
|
||||
break;
|
||||
case FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY:
|
||||
/* ReceivedReply */
|
||||
/* or a proprietary type that indicates a reply */
|
||||
/* indicate successful reception to the higher layers */
|
||||
dlmstp_put_receive(mstp_port->SourceAddress, /* source MS/TP address */
|
||||
(uint8_t *) & mstp_port->InputBuffer[0],
|
||||
/* or a proprietary type that indicates a reply
|
||||
*/
|
||||
/* indicate successful reception to the higher
|
||||
* layers */
|
||||
dlmstp_put_receive(
|
||||
mstp_port->SourceAddress, /* source MS/TP
|
||||
address */
|
||||
(uint8_t *)&mstp_port->InputBuffer[0],
|
||||
mstp_port->DataLength);
|
||||
mstp_port->master_state =
|
||||
MSTP_MASTER_STATE_DONE_WITH_TOKEN;
|
||||
@@ -890,7 +898,7 @@ bool MSTP_Master_Node_FSM(
|
||||
} else {
|
||||
/* ReceivedUnexpectedFrame */
|
||||
/* an unexpected frame was received */
|
||||
/* This may indicate the presence of multiple tokens. */
|
||||
/* This may indicate the presence of multiple tokens. */
|
||||
/* Synchronize with the network. */
|
||||
/* This action drops the token. */
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
|
||||
@@ -927,7 +935,8 @@ bool MSTP_Master_Node_FSM(
|
||||
(mstp_port->Next_Station != next_this_station)) {
|
||||
/* SoleMaster */
|
||||
/* there are no other known master nodes to */
|
||||
/* which the token may be sent (true master-slave operation). */
|
||||
/* which the token may be sent (true master-slave
|
||||
* operation). */
|
||||
mstp_port->FrameCount = 0;
|
||||
mstp_port->TokenCount++;
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_USE_TOKEN;
|
||||
@@ -935,9 +944,12 @@ bool MSTP_Master_Node_FSM(
|
||||
} else {
|
||||
/* SendToken */
|
||||
/* Npoll changed in Errata SSPC-135-2004 */
|
||||
/* The comparison of NS and TS+1 eliminates the Poll For Master */
|
||||
/* if there are no addresses between TS and NS, since there is no */
|
||||
/* address at which a new master node may be found in that case. */
|
||||
/* The comparison of NS and TS+1 eliminates the Poll For
|
||||
* Master */
|
||||
/* if there are no addresses between TS and NS, since there
|
||||
* is no */
|
||||
/* address at which a new master node may be found in that
|
||||
* case. */
|
||||
mstp_port->TokenCount++;
|
||||
/* transmit a Token frame to NS */
|
||||
MSTP_Create_And_Send_Frame(mstp_port, FRAME_TYPE_TOKEN,
|
||||
@@ -957,11 +969,12 @@ bool MSTP_Master_Node_FSM(
|
||||
/* no known successor node */
|
||||
mstp_port->Next_Station = mstp_port->This_Station;
|
||||
mstp_port->RetryCount = 0;
|
||||
mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
/* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */
|
||||
mstp_port->TokenCount =
|
||||
1; /* changed in Errata SSPC-135-2004 */
|
||||
/* mstp_port->EventCount = 0; removed in Addendum
|
||||
* 135-2004d-8 */
|
||||
/* find a new successor to TS */
|
||||
mstp_port->master_state =
|
||||
MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
} else {
|
||||
/* ResetMaintenancePFM */
|
||||
mstp_port->Poll_Station = mstp_port->This_Station;
|
||||
@@ -970,7 +983,8 @@ bool MSTP_Master_Node_FSM(
|
||||
mstp_port->Next_Station, mstp_port->This_Station, NULL,
|
||||
0);
|
||||
mstp_port->RetryCount = 0;
|
||||
mstp_port->TokenCount = 1; /* changed in Errata SSPC-135-2004 */
|
||||
mstp_port->TokenCount =
|
||||
1; /* changed in Errata SSPC-135-2004 */
|
||||
mstp_port->EventCount = 0;
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_PASS_TOKEN;
|
||||
}
|
||||
@@ -990,7 +1004,8 @@ bool MSTP_Master_Node_FSM(
|
||||
if (mstp_port->SilenceTimer < Tusage_timeout) {
|
||||
if (mstp_port->EventCount > Nmin_octets) {
|
||||
/* SawTokenUser */
|
||||
/* Assume that a frame has been sent by the new token user. */
|
||||
/* Assume that a frame has been sent by the new token user.
|
||||
*/
|
||||
/* Enter the IDLE state to process the frame. */
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
|
||||
transition_now = true;
|
||||
@@ -1019,16 +1034,18 @@ bool MSTP_Master_Node_FSM(
|
||||
mstp_port->Next_Station = mstp_port->This_Station;
|
||||
mstp_port->RetryCount = 0;
|
||||
mstp_port->TokenCount = 0;
|
||||
/* mstp_port->EventCount = 0; removed in Addendum 135-2004d-8 */
|
||||
/* mstp_port->EventCount = 0; removed in Addendum
|
||||
* 135-2004d-8 */
|
||||
/* find a new successor to TS */
|
||||
mstp_port->master_state =
|
||||
MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
/* The NO_TOKEN state is entered if mstp_port->SilenceTimer becomes greater */
|
||||
/* than Tno_token, indicating that there has been no network activity */
|
||||
/* for that period of time. The timeout is continued to determine */
|
||||
/* The NO_TOKEN state is entered if mstp_port->SilenceTimer becomes
|
||||
* greater */
|
||||
/* than Tno_token, indicating that there has been no network
|
||||
* activity */
|
||||
/* for that period of time. The timeout is continued to determine */
|
||||
/* whether or not this node may create a token. */
|
||||
case MSTP_MASTER_STATE_NO_TOKEN:
|
||||
my_timeout = Tno_token + (Tslot * mstp_port->This_Station);
|
||||
@@ -1036,7 +1053,8 @@ bool MSTP_Master_Node_FSM(
|
||||
if (mstp_port->EventCount > Nmin_octets) {
|
||||
/* SawFrame */
|
||||
/* Some other node exists at a lower address. */
|
||||
/* Enter the IDLE state to receive and process the incoming frame. */
|
||||
/* Enter the IDLE state to receive and process the incoming
|
||||
* frame. */
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
|
||||
transition_now = true;
|
||||
}
|
||||
@@ -1056,10 +1074,11 @@ bool MSTP_Master_Node_FSM(
|
||||
mstp_port->Next_Station = mstp_port->This_Station;
|
||||
mstp_port->RetryCount = 0;
|
||||
mstp_port->TokenCount = 0;
|
||||
/* mstp_port->EventCount = 0; removed Addendum 135-2004d-8 */
|
||||
/* enter the POLL_FOR_MASTER state to find a new successor to TS. */
|
||||
mstp_port->master_state =
|
||||
MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
/* mstp_port->EventCount = 0; removed Addendum 135-2004d-8
|
||||
*/
|
||||
/* enter the POLL_FOR_MASTER state to find a new successor
|
||||
* to TS. */
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_POLL_FOR_MASTER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1068,8 +1087,9 @@ bool MSTP_Master_Node_FSM(
|
||||
/* a successor node. */
|
||||
case MSTP_MASTER_STATE_POLL_FOR_MASTER:
|
||||
if (mstp_port->ReceivedValidFrame == true) {
|
||||
if ((mstp_port->DestinationAddress == mstp_port->This_Station)
|
||||
&& (mstp_port->FrameType ==
|
||||
if ((mstp_port->DestinationAddress ==
|
||||
mstp_port->This_Station) &&
|
||||
(mstp_port->FrameType ==
|
||||
FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER)) {
|
||||
/* ReceivedReplyToPFM */
|
||||
mstp_port->SoleMaster = false;
|
||||
@@ -1128,7 +1148,8 @@ bool MSTP_Master_Node_FSM(
|
||||
/* Re-enter the current state. */
|
||||
} else {
|
||||
/* DeclareSoleMaster */
|
||||
/* to indicate that this station is the only master */
|
||||
/* to indicate that this station is the only master
|
||||
*/
|
||||
mstp_port->SoleMaster = true;
|
||||
mstp_port->FrameCount = 0;
|
||||
mstp_port->master_state =
|
||||
@@ -1148,11 +1169,10 @@ bool MSTP_Master_Node_FSM(
|
||||
/* Compare the APDU type received and
|
||||
see if the message is that same APDU type
|
||||
along with the matching src/dest and invoke ID */
|
||||
matched =
|
||||
mstp_compare_data_expecting_reply(&mstp_port->InputBuffer
|
||||
[0], mstp_port->DataLength, mstp_port->SourceAddress,
|
||||
&mstp_port->TxBuffer[8], mstp_port->TxLength,
|
||||
mstp_port->TxDestination);
|
||||
matched = mstp_compare_data_expecting_reply(
|
||||
&mstp_port->InputBuffer[0], mstp_port->DataLength,
|
||||
mstp_port->SourceAddress, &mstp_port->TxBuffer[8],
|
||||
mstp_port->TxLength, mstp_port->TxDestination);
|
||||
}
|
||||
if (matched && mstp_port->TxReady) {
|
||||
/* Reply */
|
||||
@@ -1160,10 +1180,11 @@ bool MSTP_Master_Node_FSM(
|
||||
/* within Treply_delay after the reception of the */
|
||||
/* final octet of the requesting frame */
|
||||
/* (the mechanism used to determine this is a local matter), */
|
||||
/* then call MSTP_Create_And_Send_Frame to transmit the reply frame */
|
||||
/* then call MSTP_Create_And_Send_Frame to transmit the reply
|
||||
* frame */
|
||||
/* and enter the IDLE state to wait for the next frame. */
|
||||
RS485_Send_Frame(mstp_port,
|
||||
(uint8_t *) & mstp_port->TxBuffer[0], mstp_port->TxLength);
|
||||
RS485_Send_Frame(mstp_port, (uint8_t *)&mstp_port->TxBuffer[0],
|
||||
mstp_port->TxLength);
|
||||
mstp_port->TxReady = false;
|
||||
mstp_port->master_state = MSTP_MASTER_STATE_IDLE;
|
||||
} else if (mstp_port->SilenceTimer > Treply_delay) {
|
||||
@@ -1193,10 +1214,9 @@ bool MSTP_Master_Node_FSM(
|
||||
/* note: This_Station should be set with the MAC address */
|
||||
/* note: Nmax_info_frames should be set */
|
||||
/* note: Nmax_master should be set */
|
||||
void MSTP_Init(
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
int i; /*loop counter */
|
||||
int i; /*loop counter */
|
||||
|
||||
if (mstp_port) {
|
||||
mstp_port->receive_state = MSTP_RECEIVE_STATE_IDLE;
|
||||
@@ -1223,7 +1243,7 @@ void MSTP_Init(
|
||||
mstp_port->ReceivedValidFrame = false;
|
||||
mstp_port->RetryCount = 0;
|
||||
mstp_port->SilenceTimer = 0;
|
||||
/* mstp_port->ReplyPostponedTimer = 0; */
|
||||
/* mstp_port->ReplyPostponedTimer = 0; */
|
||||
mstp_port->SoleMaster = false;
|
||||
mstp_port->SourceAddress = 0;
|
||||
mstp_port->TokenCount = 0;
|
||||
@@ -1233,7 +1253,8 @@ void MSTP_Init(
|
||||
mstp_port->Nmax_master = DEFAULT_MAX_MASTER;
|
||||
#endif
|
||||
|
||||
/* An array of octets, used to store PDU octets prior to being transmitted. */
|
||||
/* An array of octets, used to store PDU octets prior to being
|
||||
* transmitted. */
|
||||
/* This array is only used for APDU messages */
|
||||
for (i = 0; i < sizeof(mstp_port->TxBuffer); i++) {
|
||||
mstp_port->TxBuffer[i] = 0;
|
||||
@@ -1241,6 +1262,5 @@ void MSTP_Init(
|
||||
mstp_port->TxLength = 0;
|
||||
mstp_port->TxReady = false;
|
||||
mstp_port->TxFrameType = 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+82
-91
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* The module handles sending data out the RS-485 port */
|
||||
/* and handles receiving data from the RS-485 port. */
|
||||
@@ -52,17 +52,17 @@ volatile uint8_t RS485_Tx_Buffer[128];
|
||||
#pragma udata
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Transmits a frame using the UART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
* DESCRIPTION: Transmits a frame using the UART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Frame(
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
|
||||
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
|
||||
uint8_t *buffer, /* frame to send (up to 501 bytes of data) */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint16_t i = 0; /* loop counter */
|
||||
{ /* number of bytes of data (up to 501) */
|
||||
uint16_t i = 0; /* loop counter */
|
||||
uint8_t turnaround_time;
|
||||
|
||||
if (!buffer)
|
||||
@@ -102,13 +102,12 @@ void RS485_Send_Frame(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Checks for data on the receive UART, and handles errors
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Check_UART_Data(
|
||||
volatile struct mstp_port_struct_t * mstp_port)
|
||||
* DESCRIPTION: Checks for data on the receive UART, and handles errors
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
/* check for data */
|
||||
if (!FIFO_Empty(&FIFO_Rx)) {
|
||||
@@ -128,8 +127,7 @@ bool RS485_Check_UART_Data(
|
||||
|
||||
NOTES: none
|
||||
*************************************************************************** */
|
||||
void RS485_Interrupt_Rx(
|
||||
void)
|
||||
void RS485_Interrupt_Rx(void)
|
||||
{
|
||||
uint8_t data_byte;
|
||||
|
||||
@@ -154,14 +152,14 @@ void RS485_Interrupt_Rx(
|
||||
|
||||
NOTES: none
|
||||
*************************************************************************** */
|
||||
void RS485_Interrupt_Tx(
|
||||
void)
|
||||
void RS485_Interrupt_Tx(void)
|
||||
{
|
||||
if (!FIFO_Empty(&FIFO_Tx)) {
|
||||
TXREG2 = FIFO_Get(&FIFO_Tx);
|
||||
} else {
|
||||
/* wait for the USART to be empty */
|
||||
while (!TXSTA2bits.TRMT);
|
||||
while (!TXSTA2bits.TRMT)
|
||||
;
|
||||
/* disable this interrupt */
|
||||
PIE3bits.TX2IE = 0;
|
||||
/* enable the receiver */
|
||||
@@ -174,25 +172,23 @@ void RS485_Interrupt_Tx(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void)
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(void)
|
||||
{
|
||||
return RS485_Baud_Rate;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud)
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
@@ -223,16 +219,14 @@ bool RS485_Set_Baud_Rate(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize_Port(
|
||||
void)
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize_Port(void)
|
||||
{
|
||||
|
||||
/* Reset USART registers to POR state */
|
||||
TXSTA2 = 0;
|
||||
RCSTA2 = 0;
|
||||
@@ -304,39 +298,36 @@ void RS485_Initialize_Port(
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Disables the RS485 hardware
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Disable_Port(
|
||||
void)
|
||||
* DESCRIPTION: Disables the RS485 hardware
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Disable_Port(void)
|
||||
{
|
||||
RCSTA2 &= 0x4F; /* Disable the receiver */
|
||||
TXSTA2bits.TXEN = 0; /* and transmitter */
|
||||
PIE3 &= 0xCF; /* Disable both interrupts */
|
||||
RCSTA2 &= 0x4F; /* Disable the receiver */
|
||||
TXSTA2bits.TXEN = 0; /* and transmitter */
|
||||
PIE3 &= 0xCF; /* Disable both interrupts */
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Reinitializes the port
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Reinit(
|
||||
void)
|
||||
* DESCRIPTION: Reinitializes the port
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Reinit(void)
|
||||
{
|
||||
RS485_Set_Baud_Rate(38400);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Initializes the data and the port
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(
|
||||
void)
|
||||
* DESCRIPTION: Initializes the data and the port
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(void)
|
||||
{
|
||||
/* Init the Rs485 buffers */
|
||||
FIFO_Init(&FIFO_Rx, RS485_Rx_Buffer, sizeof(RS485_Rx_Buffer));
|
||||
|
||||
+39
-49
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -44,8 +44,7 @@ static uint8_t Present_Value[MAX_ANALOG_INPUTS];
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
@@ -54,34 +53,30 @@ bool Analog_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
unsigned Analog_Input_Count(void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
char *Analog_Input_Name(
|
||||
uint32_t object_instance)
|
||||
char *Analog_Input_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
sprintf(text_string, "AI-%lu", (unsigned long) object_instance);
|
||||
sprintf(text_string, "AI-%lu", (unsigned long)object_instance);
|
||||
return text_string;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
float Analog_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = 0.0;
|
||||
|
||||
@@ -91,9 +86,7 @@ float Analog_Input_Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
void Analog_Input_Present_Value_Set(
|
||||
uint32_t object_instance,
|
||||
float value)
|
||||
void Analog_Input_Present_Value_Set(uint32_t object_instance, float value)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
Present_Value[object_instance] = value;
|
||||
@@ -102,10 +95,9 @@ void Analog_Input_Present_Value_Set(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object has already exists */
|
||||
int Analog_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint8_t *apdu = NULL;
|
||||
@@ -117,16 +109,15 @@ int Analog_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_ANALOG_INPUT, rpdata->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:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Input_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Analog_Input_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -135,9 +126,8 @@ int Analog_Input_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
Analog_Input_Present_Value(rpdata->object_instance));
|
||||
apdu_len = encode_application_real(
|
||||
&apdu[0], Analog_Input_Present_Value(rpdata->object_instance));
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
|
||||
+25
-30
@@ -43,20 +43,17 @@
|
||||
/* me */
|
||||
#include "bacnet/apdu.h"
|
||||
|
||||
uint16_t apdu_timeout(
|
||||
void)
|
||||
uint16_t apdu_timeout(void)
|
||||
{
|
||||
return 3000;
|
||||
}
|
||||
|
||||
uint8_t apdu_retries(
|
||||
void)
|
||||
uint8_t apdu_retries(void)
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool apdu_service_supported(
|
||||
BACNET_SERVICES_SUPPORTED service_supported)
|
||||
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -75,15 +72,14 @@ bool apdu_service_supported(
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t apdu_decode_confirmed_service_request(
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_decode_confirmed_service_request(uint8_t *apdu, /* APDU data */
|
||||
uint16_t apdu_len,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||
uint8_t * service_choice,
|
||||
uint8_t ** service_request,
|
||||
uint16_t * service_request_len)
|
||||
BACNET_CONFIRMED_SERVICE_DATA *service_data,
|
||||
uint8_t *service_choice,
|
||||
uint8_t **service_request,
|
||||
uint16_t *service_request_len)
|
||||
{
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
service_data->segmented_message = (apdu[0] & BIT(3)) ? true : false;
|
||||
service_data->more_follows = (apdu[0] & BIT(2)) ? true : false;
|
||||
@@ -110,8 +106,7 @@ uint16_t apdu_decode_confirmed_service_request(
|
||||
When the initiation of communications is disabled,
|
||||
all APDUs shall be processed and responses returned as
|
||||
required... */
|
||||
static bool apdu_confirmed_dcc_disabled(
|
||||
uint8_t service_choice)
|
||||
static bool apdu_confirmed_dcc_disabled(uint8_t service_choice)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -136,8 +131,7 @@ static bool apdu_confirmed_dcc_disabled(
|
||||
DISABLE_INITIATION, the responding BACnet-user shall
|
||||
discontinue the initiation of messages except for I-Am
|
||||
requests issued in accordance with the Who-Is service procedure.*/
|
||||
static bool apdu_unconfirmed_dcc_disabled(
|
||||
uint8_t service_choice)
|
||||
static bool apdu_unconfirmed_dcc_disabled(uint8_t service_choice)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
@@ -159,36 +153,37 @@ static bool apdu_unconfirmed_dcc_disabled(
|
||||
return status;
|
||||
}
|
||||
|
||||
void apdu_handler(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * apdu, /* APDU data */
|
||||
void apdu_handler(BACNET_ADDRESS *src,
|
||||
uint8_t *apdu, /* APDU data */
|
||||
uint16_t apdu_len)
|
||||
{
|
||||
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
|
||||
uint8_t service_choice = 0;
|
||||
uint8_t *service_request = NULL;
|
||||
uint16_t service_request_len = 0;
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
if (apdu) {
|
||||
/* PDU Type */
|
||||
switch (apdu[0] & 0xF0) {
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
len = apdu_decode_confirmed_service_request(
|
||||
&apdu[0], /* APDU data */
|
||||
apdu_len, &service_data, &service_choice, &service_request,
|
||||
&service_request_len);
|
||||
if (apdu_confirmed_dcc_disabled(service_choice)) {
|
||||
/* When network communications are completely disabled,
|
||||
only DeviceCommunicationControl and ReinitializeDevice APDUs
|
||||
shall be processed and no messages shall be initiated. */
|
||||
only DeviceCommunicationControl and ReinitializeDevice
|
||||
APDUs shall be processed and no messages shall be
|
||||
initiated. */
|
||||
break;
|
||||
}
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
handler_read_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
} else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
|
||||
handler_write_property(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
handler_write_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
} else if (service_choice ==
|
||||
SERVICE_CONFIRMED_REINITIALIZE_DEVICE) {
|
||||
handler_reinitialize_device(service_request,
|
||||
@@ -208,10 +203,10 @@ void apdu_handler(
|
||||
service_request_len = apdu_len - 2;
|
||||
if (apdu_unconfirmed_dcc_disabled(service_choice)) {
|
||||
/* When network communications are disabled,
|
||||
only DeviceCommunicationControl and ReinitializeDevice APDUs
|
||||
shall be processed and no messages shall be initiated.
|
||||
If communications have been initiation disabled, then
|
||||
WhoIs may be processed. */
|
||||
only DeviceCommunicationControl and ReinitializeDevice
|
||||
APDUs shall be processed and no messages shall be
|
||||
initiated. If communications have been initiation
|
||||
disabled, then WhoIs may be processed. */
|
||||
break;
|
||||
}
|
||||
if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
|
||||
|
||||
+49
-60
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/basic/object/av.h"
|
||||
@@ -54,8 +54,7 @@ static uint8_t Present_Value[MAX_ANALOG_VALUES];
|
||||
/* we need to have our arrays initialized before answering any calls */
|
||||
static bool Analog_Value_Initialized = false;
|
||||
|
||||
void Analog_Value_Init(
|
||||
void)
|
||||
void Analog_Value_Init(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@@ -74,8 +73,7 @@ void Analog_Value_Init(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
Analog_Value_Init();
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
@@ -86,8 +84,7 @@ bool Analog_Value_Valid_Instance(
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
unsigned Analog_Value_Count(void)
|
||||
{
|
||||
Analog_Value_Init();
|
||||
return MAX_ANALOG_VALUES;
|
||||
@@ -96,8 +93,7 @@ unsigned Analog_Value_Count(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Analog_Value_Index_To_Instance(unsigned index)
|
||||
{
|
||||
Analog_Value_Init();
|
||||
return index;
|
||||
@@ -106,8 +102,7 @@ uint32_t Analog_Value_Index_To_Instance(
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_ANALOG_VALUES;
|
||||
|
||||
@@ -118,8 +113,7 @@ unsigned Analog_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
float Analog_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
float Analog_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
float value = ANALOG_RELINQUISH_DEFAULT;
|
||||
unsigned index = 0;
|
||||
@@ -135,10 +129,9 @@ float Analog_Value_Present_Value(
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Analog_Value_Name(
|
||||
uint32_t object_instance)
|
||||
char *Analog_Value_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[32] = ""; /* okay for single thread */
|
||||
static char text_string[32] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_VALUES) {
|
||||
sprintf(text_string, "AV-%lu", object_instance);
|
||||
@@ -149,14 +142,13 @@ char *Analog_Value_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Analog_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
float real_value = (float) 1.414;
|
||||
float real_value = (float)1.414;
|
||||
unsigned object_index = 0;
|
||||
unsigned i = 0;
|
||||
bool state = false;
|
||||
@@ -170,14 +162,13 @@ int Analog_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_ANALOG_VALUE, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Value_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Analog_Value_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -287,10 +278,9 @@ int Analog_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
uint8_t level = ANALOG_LEVEL_NULL;
|
||||
@@ -304,9 +294,8 @@ bool Analog_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -329,19 +318,19 @@ bool Analog_Value_Write_Property(
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Real >= 0.0) && (value.type.Real <= 100.0)) {
|
||||
level = (uint8_t) value.type.Real;
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
level = (uint8_t)value.type.Real;
|
||||
object_index = Analog_Value_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority--;
|
||||
Present_Value[object_index] = level;
|
||||
/* 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) */
|
||||
main loop (i.e. check out of service before changing
|
||||
output) */
|
||||
status = true;
|
||||
} else if (priority == 6) {
|
||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||
|
||||
+37
-46
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 Input Objects customize for your use */
|
||||
|
||||
@@ -40,8 +40,7 @@
|
||||
|
||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
|
||||
|
||||
static void Binary_Input_Initialize(
|
||||
void)
|
||||
static void Binary_Input_Initialize(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
unsigned i;
|
||||
@@ -55,8 +54,7 @@ static void Binary_Input_Initialize(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Input_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_INPUTS)
|
||||
return true;
|
||||
@@ -65,15 +63,13 @@ bool Binary_Input_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Input_Count(
|
||||
void)
|
||||
unsigned Binary_Input_Count(void)
|
||||
{
|
||||
return MAX_BINARY_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances.*/
|
||||
uint32_t Binary_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
uint32_t Binary_Input_Index_To_Instance(unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
@@ -81,8 +77,7 @@ uint32_t Binary_Input_Index_To_Instance(
|
||||
/* 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 Binary_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_INPUTS;
|
||||
|
||||
@@ -92,8 +87,7 @@ unsigned Binary_Input_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
unsigned index = 0;
|
||||
@@ -107,10 +101,9 @@ BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||
return value;
|
||||
}
|
||||
|
||||
char *Binary_Input_Name(
|
||||
uint32_t object_instance)
|
||||
char *Binary_Input_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_BINARY_INPUTS) {
|
||||
sprintf(text_string, "BI-%lu", object_instance);
|
||||
@@ -122,10 +115,9 @@ char *Binary_Input_Name(
|
||||
|
||||
/* return apdu length, or -1 on error */
|
||||
/* assumption - object already exists, and has been bounds checked */
|
||||
int Binary_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
||||
@@ -140,15 +132,14 @@ int Binary_Input_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_INPUT, rpdata->object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
/* note: object name must be unique in our device */
|
||||
characterstring_init_ansi(&char_string,
|
||||
Binary_Input_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Binary_Input_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
|
||||
+46
-59
@@ -1,27 +1,27 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* 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 */
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/basic/object/bv.h"
|
||||
@@ -40,8 +40,7 @@
|
||||
|
||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_VALUES];
|
||||
|
||||
static void Binary_Value_Initialize(
|
||||
void)
|
||||
static void Binary_Value_Initialize(void)
|
||||
{
|
||||
static bool initialized = false;
|
||||
unsigned i;
|
||||
@@ -55,8 +54,7 @@ static void Binary_Value_Initialize(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
bool Binary_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
bool Binary_Value_Valid_Instance(uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_BINARY_VALUES)
|
||||
return true;
|
||||
@@ -65,22 +63,19 @@ bool Binary_Value_Valid_Instance(
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Binary_Value_Count(
|
||||
void)
|
||||
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)
|
||||
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 Binary_Value_Instance_To_Index(uint32_t object_instance)
|
||||
{
|
||||
unsigned index = MAX_BINARY_VALUES;
|
||||
|
||||
@@ -90,8 +85,7 @@ unsigned Binary_Value_Instance_To_Index(
|
||||
return index;
|
||||
}
|
||||
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
uint32_t object_instance)
|
||||
BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t object_instance)
|
||||
{
|
||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||
|
||||
@@ -104,10 +98,9 @@ BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Binary_Value_Name(
|
||||
uint32_t object_instance)
|
||||
char *Binary_Value_Name(uint32_t object_instance)
|
||||
{
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
static char text_string[16] = ""; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_BINARY_VALUES) {
|
||||
sprintf(text_string, "BV-%lu", object_instance);
|
||||
@@ -118,11 +111,10 @@ char *Binary_Value_Name(
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Binary_Value_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Binary_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* return value */
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
@@ -140,16 +132,15 @@ int Binary_Value_Read_Property(
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
|
||||
rpdata->object_instance);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_BINARY_VALUE, rpdata->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:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Binary_Value_Name(rpdata->object_instance));
|
||||
characterstring_init_ansi(
|
||||
&char_string, Binary_Value_Name(rpdata->object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
@@ -158,8 +149,7 @@ int Binary_Value_Read_Property(
|
||||
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
present_value =
|
||||
Binary_Value_Present_Value(rpdata->object_instance);
|
||||
present_value = Binary_Value_Present_Value(rpdata->object_instance);
|
||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
@@ -200,10 +190,9 @@ int Binary_Value_Read_Property(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Binary_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
unsigned int priority = 0;
|
||||
BACNET_BINARY_PV level = BINARY_NULL;
|
||||
@@ -216,9 +205,8 @@ bool Binary_Value_Write_Property(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -241,13 +229,12 @@ bool Binary_Value_Write_Property(
|
||||
algorithm and may not be used for other purposes in any
|
||||
object. */
|
||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||
(priority != 6 /* reserved */ ) &&
|
||||
(priority != 6 /* reserved */) &&
|
||||
(value.type.Enumerated >= MIN_BINARY_PV) &&
|
||||
(value.type.Enumerated <= MAX_BINARY_PV)) {
|
||||
level = value.type.Enumerated;
|
||||
object_index =
|
||||
Binary_Value_Instance_To_Index
|
||||
(wp_data->object_instance);
|
||||
object_index = Binary_Value_Instance_To_Index(
|
||||
wp_data->object_instance);
|
||||
priority--;
|
||||
/* NOTE: this Binary value has no priority array */
|
||||
Present_Value[object_index] = level;
|
||||
|
||||
+97
-128
@@ -1,36 +1,36 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 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.
|
||||
*
|
||||
*********************************************************************/
|
||||
*
|
||||
* Copyright (C) 2007 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 <string.h> /* for memmove */
|
||||
#include <string.h> /* for memmove */
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bacstr.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/config.h" /* the custom stuff */
|
||||
#include "bacnet/apdu.h"
|
||||
#include "bacnet/datalink/dlmstp.h"
|
||||
#include "rs485.h"
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "bacnet/wp.h"
|
||||
#include "bacnet/dcc.h"
|
||||
#include "bacnet/version.h"
|
||||
#include "bacnet/basic/object/device.h" /* me */
|
||||
#include "bacnet/basic/object/device.h" /* me */
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
@@ -53,8 +53,7 @@ static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
static uint8_t Database_Revision;
|
||||
BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_IDLE;
|
||||
|
||||
bool Device_Reinitialize(
|
||||
BACNET_REINITIALIZE_DEVICE_DATA * rd_data)
|
||||
bool Device_Reinitialize(BACNET_REINITIALIZE_DEVICE_DATA *rd_data)
|
||||
{
|
||||
bool status = false;
|
||||
char password[16] = "filister";
|
||||
@@ -76,16 +75,14 @@ bool Device_Reinitialize(
|
||||
return status;
|
||||
}
|
||||
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(
|
||||
void)
|
||||
BACNET_REINITIALIZED_STATE Device_Reinitialized_State(void)
|
||||
{
|
||||
return Reinitialize_State;
|
||||
}
|
||||
|
||||
void Device_Init(
|
||||
object_functions_t * object_table)
|
||||
void Device_Init(object_functions_t *object_table)
|
||||
{
|
||||
(void) object_table;
|
||||
(void)object_table;
|
||||
Reinitialize_State = BACNET_REINIT_IDLE;
|
||||
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
|
||||
/* FIXME: Get the data from the eeprom */
|
||||
@@ -96,14 +93,12 @@ void Device_Init(
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
uint32_t Device_Object_Instance_Number(void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Set_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
@@ -122,66 +117,56 @@ bool Device_Set_Object_Instance_Number(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return (Object_Instance_Number == object_id);
|
||||
}
|
||||
|
||||
BACNET_DEVICE_STATUS Device_System_Status(
|
||||
void)
|
||||
BACNET_DEVICE_STATUS Device_System_Status(void)
|
||||
{
|
||||
return System_Status;
|
||||
}
|
||||
|
||||
int Device_Set_System_Status(
|
||||
BACNET_DEVICE_STATUS status,
|
||||
bool local)
|
||||
int Device_Set_System_Status(BACNET_DEVICE_STATUS status, bool local)
|
||||
{
|
||||
if (status < MAX_DEVICE_STATUS) {
|
||||
System_Status = status;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
uint16_t Device_Vendor_Identifier(void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Version(
|
||||
void)
|
||||
uint8_t Device_Protocol_Version(void)
|
||||
{
|
||||
return BACNET_PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Revision(
|
||||
void)
|
||||
uint8_t Device_Protocol_Revision(void)
|
||||
{
|
||||
return BACNET_PROTOCOL_REVISION;
|
||||
}
|
||||
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(
|
||||
void)
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
|
||||
{
|
||||
return SEGMENTATION_NONE;
|
||||
}
|
||||
|
||||
uint32_t Device_Database_Revision(
|
||||
void)
|
||||
uint32_t Device_Database_Revision(void)
|
||||
{
|
||||
return Database_Revision;
|
||||
}
|
||||
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
unsigned Device_Object_List_Count(void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
/* FIXME: add objects as needed */
|
||||
/* FIXME: add objects as needed */
|
||||
count += Binary_Value_Count();
|
||||
count += Analog_Input_Count();
|
||||
count += Binary_Input_Count();
|
||||
@@ -193,9 +178,7 @@ unsigned Device_Object_List_Count(
|
||||
/* Since many network clients depend on the object list */
|
||||
/* for discovery, it must be consistent! */
|
||||
bool Device_Object_List_Identifier(
|
||||
uint32_t array_index,
|
||||
BACNET_OBJECT_TYPE *object_type,
|
||||
uint32_t * instance)
|
||||
uint32_t array_index, BACNET_OBJECT_TYPE *object_type, uint32_t *instance)
|
||||
{
|
||||
bool status = false;
|
||||
uint32_t object_index = 0;
|
||||
@@ -265,11 +248,10 @@ bool Device_Object_List_Identifier(
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
uint32_t i = 0;
|
||||
@@ -291,12 +273,11 @@ int Device_Read_Property_Local(
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], OBJECT_DEVICE, Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "PIC18F6720 Device");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "PIC18F6720 Device");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
@@ -305,68 +286,64 @@ int Device_Read_Property_Local(
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "BACnet Demo");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "BACnet Demo");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_System_Status());
|
||||
encode_application_enumerated(&apdu[0], Device_System_Status());
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
(void) strcpypgm2ram(&string_buffer[0], BACNET_VENDOR_NAME);
|
||||
(void)strcpypgm2ram(&string_buffer[0], BACNET_VENDOR_NAME);
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "GNU Demo");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "GNU Demo");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], BACNET_VERSION_TEXT);
|
||||
(void)strcpypgm2ram(&string_buffer[0], BACNET_VERSION_TEXT);
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "1.0");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "1.0");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_LOCATION:
|
||||
(void) strcpypgm2ram(&string_buffer[0], "USA");
|
||||
(void)strcpypgm2ram(&string_buffer[0], "USA");
|
||||
characterstring_init_ansi(&char_string, string_buffer);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Protocol_Version());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Protocol_Version());
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Protocol_Revision());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Protocol_Revision());
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported(i));
|
||||
bitstring_set_bit(
|
||||
&bit_string, (uint8_t)i, apdu_service_supported(i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
@@ -376,7 +353,7 @@ int Device_Read_Property_Local(
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
bitstring_set_bit(&bit_string, (uint8_t)i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
@@ -397,11 +374,10 @@ int Device_Read_Property_Local(
|
||||
/* your maximum APDU size. */
|
||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
if (Device_Object_List_Identifier(i, &object_type,
|
||||
&instance)) {
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
i, &object_type, &instance)) {
|
||||
len = encode_application_object_id(
|
||||
&apdu[apdu_len], object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
@@ -420,11 +396,10 @@ int Device_Read_Property_Local(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(rpdata->array_index,
|
||||
&object_type, &instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
if (Device_Object_List_Identifier(
|
||||
rpdata->array_index, &object_type, &instance))
|
||||
apdu_len = encode_application_object_id(
|
||||
&apdu[0], object_type, instance);
|
||||
else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
@@ -436,9 +411,8 @@ int Device_Read_Property_Local(
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_Segmentation_Supported());
|
||||
apdu_len = encode_application_enumerated(
|
||||
&apdu[0], Device_Segmentation_Supported());
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout());
|
||||
@@ -450,14 +424,12 @@ int Device_Read_Property_Local(
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Database_Revision());
|
||||
apdu_len = encode_application_unsigned(
|
||||
&apdu[0], Device_Database_Revision());
|
||||
break;
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
dlmstp_max_info_frames());
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len =
|
||||
@@ -474,14 +446,14 @@ int Device_Read_Property_Local(
|
||||
case PROP_UTC_OFFSET:
|
||||
/* Note: BACnet Time Zone is offset of local time and UTC,
|
||||
rather than offset of GMT. It is expressed in minutes */
|
||||
apdu_len = encode_application_signed(&apdu[0], 5 * 60 /* EST */ );
|
||||
apdu_len = encode_application_signed(&apdu[0], 5 * 60 /* EST */);
|
||||
break;
|
||||
case PROP_LOCAL_DATE:
|
||||
/* FIXME: if you support date */
|
||||
local_date.year = 2006; /* AD */
|
||||
local_date.month = 4; /* Jan=1..Dec=12 */
|
||||
local_date.day = 11; /* 1..31 */
|
||||
local_date.wday = 0; /* 1=Mon..7=Sun */
|
||||
local_date.year = 2006; /* AD */
|
||||
local_date.month = 4; /* Jan=1..Dec=12 */
|
||||
local_date.day = 11; /* 1..31 */
|
||||
local_date.wday = 0; /* 1=Mon..7=Sun */
|
||||
apdu_len = encode_application_date(&apdu[0], &local_date);
|
||||
break;
|
||||
case PROP_DAYLIGHT_SAVINGS_STATUS:
|
||||
@@ -509,8 +481,7 @@ int Device_Read_Property_Local(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int Device_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
|
||||
@@ -550,10 +521,9 @@ int Device_Read_Property(
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
bool Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
bool status = false; /* return value */
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
@@ -563,9 +533,8 @@ bool Device_Write_Property_Local(
|
||||
return false;
|
||||
}
|
||||
/* decode the some of the request */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
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 */
|
||||
@@ -584,8 +553,8 @@ bool Device_Write_Property_Local(
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
|
||||
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
|
||||
(Device_Set_Object_Instance_Number(value.type.
|
||||
Object_Id.instance))) {
|
||||
(Device_Set_Object_Instance_Number(
|
||||
value.type.Object_Id.instance))) {
|
||||
/* we could send an I-Am broadcast to let the world know */
|
||||
status = true;
|
||||
} else {
|
||||
@@ -638,10 +607,11 @@ bool Device_Write_Property_Local(
|
||||
if (len <= 20) {
|
||||
/* FIXME: set the name */
|
||||
/* Display_Set_Name(
|
||||
characterstring_value(&value.type.Character_String)); */
|
||||
/* FIXME: All the object names in a device must be unique.
|
||||
Disallow setting the Device Object Name to any objects in
|
||||
the device. */
|
||||
characterstring_value(&value.type.Character_String));
|
||||
*/
|
||||
/* FIXME: All the object names in a device must be
|
||||
unique. Disallow setting the Device Object Name to
|
||||
any objects in the device. */
|
||||
} else {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code =
|
||||
@@ -707,10 +677,9 @@ bool Device_Write_Property_Local(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data)
|
||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
{
|
||||
bool status = false; /* Ever the pessamist! */
|
||||
bool status = false; /* Ever the pessamist! */
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
/* initialize the default return values */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user