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:
Steve Karg
2020-04-30 10:13:11 -05:00
committed by GitHub
parent 0abcbea971
commit fdd49f1791
152 changed files with 9668 additions and 11674 deletions
+13 -12
View File
@@ -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
View File
@@ -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;
+6 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+18 -20
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+3 -5
View File
@@ -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);
+4 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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:
+9 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+61 -61
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {
+42 -47
View File
@@ -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
View File
@@ -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);
+46 -60
View File
@@ -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
View File
@@ -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);
}
}
+140 -156
View File
@@ -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 */
+28 -31
View 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
View File
@@ -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
View File
@@ -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;
}
+29 -31
View File
@@ -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) {
+56 -56
View File
@@ -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
View File
@@ -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;
+31 -38
View File
@@ -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
View File
@@ -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
View File
@@ -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 */
+51 -55
View File
@@ -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
View File
@@ -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();
+91 -85
View File
@@ -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;
+37 -47
View File
@@ -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();
+44 -47
View File
@@ -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
View File
@@ -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;
+35 -40
View File
@@ -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
View File
@@ -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;
+7 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+7 -8
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+71 -76
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+7 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 *) &eth_addr,
sizeof(struct sockaddr));
bytes = sendto(eth802_sockfd, &mtu, mtu_len, 0,
(struct sockaddr *)&eth_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 *) &eth_addr,
sizeof(struct sockaddr));
bytes = sendto(eth802_sockfd, &mtu, mtu_len, 0,
(struct sockaddr *)&eth_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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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