Indented.

This commit is contained in:
skarg
2007-11-29 15:56:53 +00:00
parent c585241c03
commit 411d6c1b24
236 changed files with 17864 additions and 15724 deletions
+1 -1
View File
@@ -15,4 +15,4 @@ typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
/* typedef signed long long int64_t; */
/* typedef unsigned long long uint64_t; */
#endif /* STDINT_H */
#endif /* STDINT_H */
+105 -93
View File
@@ -32,12 +32,12 @@
-------------------------------------------
####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 "bacdcode.h"
#include "bip.h"
#include "eth.h"
#include "net.h" /* custom per port */
#include "net.h" /* custom per port */
static int BIP_Socket = -1;
/* port to use - stored in host byte order */
@@ -47,22 +47,26 @@ static struct in_addr BIP_Address;
/* Broadcast Address - stored in host byte order */
static struct in_addr BIP_Broadcast_Address;
void bip_set_socket(int sock_fd)
void bip_set_socket(
int sock_fd)
{
BIP_Socket = sock_fd;
}
int bip_socket(void)
int bip_socket(
void)
{
return BIP_Socket;
}
bool bip_valid(void)
bool bip_valid(
void)
{
return (BIP_Socket != -1);
}
void bip_cleanup(void)
void bip_cleanup(
void)
{
/* if (bip_valid()) */
/* close(BIP_Socket); */
@@ -72,142 +76,149 @@ void bip_cleanup(void)
}
/* set using network byte order */
void bip_set_addr(uint32_t net_address)
void bip_set_addr(
uint32_t net_address)
{
/* BIP_Address.s_addr = ntohl(net_address); */
BIP_Address.s_addr = net_address;
}
/* returns host byte order */
uint32_t bip_get_addr(void)
uint32_t bip_get_addr(
void)
{
return BIP_Address.s_addr;
}
/* set using network byte order */
void bip_set_broadcast_addr(uint32_t net_address)
void bip_set_broadcast_addr(
uint32_t net_address)
{
/* BIP_Broadcast_Address.s_addr = ntohl(net_address); */
BIP_Broadcast_Address.s_addr = net_address;
}
/* returns host byte order */
uint32_t bip_get_broadcast_addr(void)
uint32_t bip_get_broadcast_addr(
void)
{
return BIP_Broadcast_Address.s_addr;
}
/* set using host byte order */
void bip_set_port(uint16_t port)
void bip_set_port(
uint16_t port)
{
BIP_Port = port;
}
/* returns host byte order */
uint16_t bip_get_port(void)
uint16_t bip_get_port(
void)
{
return BIP_Port;
}
/* function to send a packet out the BACnet/IP socket (Annex J) */
/* returns 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 */
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 */
struct sockaddr_in bip_dest;
uint8_t mtu[4];
int mtu_len = 0;
int bytes_sent = 0;
UDP_HDR udphdr;
IP_HDR iphdr;
uint8_t mac[6];
struct sockaddr_in bip_dest;
uint8_t mtu[4];
int mtu_len = 0;
int bytes_sent = 0;
UDP_HDR udphdr;
IP_HDR iphdr;
uint8_t mac[6];
(void) npdu_data;
/* assumes that the driver has already been initialized */
(void) npdu_data;
/* assumes that the driver has already been initialized */
/* if (BIP_Socket < 0) */
/* return BIP_Socket; */
mtu[0] = BVLL_TYPE_BACNET_IP;
bip_dest.sin_family = AF_INET;
if (dest->mac_len == 6)
{
memcpy(&(bip_dest.sin_addr.s_addr),&dest->mac[0],4);
decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port));
memset(&(bip_dest.sin_zero), '\0', 8);
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
}
/* broadcast */
else if (dest->mac_len == 0)
{
bip_dest.sin_addr.s_addr = BIP_Broadcast_Address.s_addr;
bip_dest.sin_port = htons(BIP_Port);
memset(&(bip_dest.sin_zero), '\0', 8);
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
}
else
return -1;
mtu_len = 2;
mtu_len += encode_unsigned16(&mtu[mtu_len], (uint16_t) (pdu_len + 4 /*inclusive */ ));
mtu_len += pdu_len;
/* IP address should be in network byte order */
ARPIsResolved(bip_dest.sin_addr.s_addr, mac);
mtu[0] = BVLL_TYPE_BACNET_IP;
bip_dest.sin_family = AF_INET;
iphdr.vhl = 0x45;
iphdr.tos = 0;
iphdr.iplen = htons(mtu_len + sizeof(IP_HDR) + sizeof(UDP_HDR));
++ipid;
iphdr.ipid = htons(ipid);
iphdr.ipoffset[0] = iphdr.ipoffset[1] = 0;
iphdr.ttl = UIP_TTL;
iphdr.proto = UIP_PROTO_UDP;
iphdr.ipchksum = 0;
iphdr.srcipaddr = BIP_Address.s_addr;
iphdr.destipaddr = bip_dest.sin_addr.s_addr;
/* Calculate IP checksum. */
iphdr.ipchksum = ~(ip_getchksum((uint8_t*)&iphdr));
if (dest->mac_len == 6) {
memcpy(&(bip_dest.sin_addr.s_addr), &dest->mac[0], 4);
decode_unsigned16(&dest->mac[4], &(bip_dest.sin_port));
memset(&(bip_dest.sin_zero), '\0', 8);
mtu[1] = BVLC_ORIGINAL_UNICAST_NPDU;
}
/* broadcast */
else if (dest->mac_len == 0) {
bip_dest.sin_addr.s_addr = BIP_Broadcast_Address.s_addr;
bip_dest.sin_port = htons(BIP_Port);
memset(&(bip_dest.sin_zero), '\0', 8);
mtu[1] = BVLC_ORIGINAL_BROADCAST_NPDU;
} else
return -1;
/* Ports are sent in Network byte order. BIP_Port is stored in Host byte order */
udphdr.srcport = htons(BIP_Port);
udphdr.destport = bip_dest.sin_port;
udphdr.udplen = htons(mtu_len + sizeof(UDP_HDR));
/* Not using UDP checksums */
udphdr.udpchksum = 0;
mtu_len = 2;
mtu_len +=
encode_unsigned16(&mtu[mtu_len],
(uint16_t) (pdu_len + 4 /*inclusive */ ));
mtu_len += pdu_len;
/* IP address should be in network byte order */
ARPIsResolved(bip_dest.sin_addr.s_addr, mac);
iphdr.vhl = 0x45;
iphdr.tos = 0;
iphdr.iplen = htons(mtu_len + sizeof(IP_HDR) + sizeof(UDP_HDR));
++ipid;
iphdr.ipid = htons(ipid);
iphdr.ipoffset[0] = iphdr.ipoffset[1] = 0;
iphdr.ttl = UIP_TTL;
iphdr.proto = UIP_PROTO_UDP;
iphdr.ipchksum = 0;
iphdr.srcipaddr = BIP_Address.s_addr;
iphdr.destipaddr = bip_dest.sin_addr.s_addr;
/* Calculate IP checksum. */
iphdr.ipchksum = ~(ip_getchksum((uint8_t *) & iphdr));
/* Ports are sent in Network byte order. BIP_Port is stored in Host byte order */
udphdr.srcport = htons(BIP_Port);
udphdr.destport = bip_dest.sin_port;
udphdr.udplen = htons(mtu_len + sizeof(UDP_HDR));
/* Not using UDP checksums */
udphdr.udpchksum = 0;
EthernetSendHeader(mac, UIP_ETHTYPE_IP);
EthernetSend((uint8_t *) & iphdr, sizeof(IP_HDR));
EthernetSend((uint8_t *) & udphdr, sizeof(UDP_HDR));
EthernetSend(mtu, 4);
EthernetSend(pdu, pdu_len);
EthernetFlush();
uip_stat.ip.sent++;
EthernetSendHeader(mac, UIP_ETHTYPE_IP);
EthernetSend((uint8_t*)&iphdr, sizeof(IP_HDR));
EthernetSend((uint8_t*)&udphdr, sizeof(UDP_HDR));
EthernetSend(mtu, 4);
EthernetSend(pdu, pdu_len);
EthernetFlush();
uip_stat.ip.sent++;
}
/* receives a BACnet/IP packet */
/* returns the number of octets in the PDU, or zero on failure */
uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
uint8_t * pdu, /* PDU data */
uint16_t max_pdu, /* amount of space available in the PDU */
uint16_t bip_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 */
return 0;
{ /* number of milliseconds to wait for a packet */
return 0;
}
void bip_get_my_address(BACNET_ADDRESS * my_address)
void bip_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
my_address->mac_len = 6;
(void) encode_unsigned32(&my_address->mac[0],
htonl(BIP_Address.s_addr));
(void) encode_unsigned32(&my_address->mac[0], htonl(BIP_Address.s_addr));
(void) encode_unsigned16(&my_address->mac[4], htons(BIP_Port));
my_address->net = 0; /* local only, no routing */
my_address->len = 0; /* no SLEN */
@@ -219,9 +230,10 @@ 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;
@@ -229,7 +241,7 @@ void bip_get_broadcast_address(BACNET_ADDRESS * dest)
htonl(BIP_Broadcast_Address.s_addr));
(void) encode_unsigned16(&dest->mac[4], htons(BIP_Port));
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;
+44 -40
View File
@@ -29,21 +29,20 @@
#include "stdint.h"
struct sockaddr {
uint16_t sa_family;
char sa_data[14];
uint16_t sa_family;
char sa_data[14];
};
struct in_addr {
uint32_t s_addr; /* load with inet_aton() */
uint32_t s_addr; /* load with inet_aton() */
};
struct sockaddr_in
{
int16_t sin_family; /* e.g. AF_INET */
uint16_t sin_port; /* e.g. htons(3490) */
struct in_addr sin_addr; /* see struct in_addr, below */
char sin_zero[8]; /* zero this if you want to */
struct sockaddr_in {
int16_t sin_family; /* e.g. AF_INET */
uint16_t sin_port; /* e.g. htons(3490) */
struct in_addr sin_addr; /* see struct in_addr, below */
char sin_zero[8]; /* zero this if you want to */
};
@@ -74,42 +73,47 @@ typedef int socklen_t;
((((uint32_t)(n) & 0xFF000000)) >> 24))
#define AF_UNIX 1 /* local to host (pipes, portals) */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */
#define AF_PUP 4 /* pup protocols: e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS protocols */
#define AF_NS 6 /* XEROX NS protocols */
#define AF_IPX AF_NS /* IPX protocols: IPX, SPX, etc. */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO /* OSI is ISO */
#define AF_ECMA 8 /* european computer manufacturers */
#define AF_DATAKIT 9 /* datakit protocols */
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* Direct data link interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* AppleTalk */
#define AF_NETBIOS 17 /* NetBios-style addresses */
#define AF_VOICEVIEW 18 /* VoiceView */
#define AF_FIREFOX 19 /* Protocols from Firefox */
#define AF_UNKNOWN1 20 /* Somebody is using this! */
#define AF_BAN 21 /* Banyan */
#define AF_ATM 22 /* Native ATM Services */
#define AF_INET6 23 /* Internetwork Version 6 */
#define AF_CLUSTER 24 /* Microsoft Wolfpack */
#define AF_12844 25 /* IEEE 1284.4 WG AF */
#define AF_IRDA 26 /* IrDA */
#define AF_NETDES 28 /* Network Designers OSI & gateway
enabled protocols */
#define AF_UNIX 1 /* local to host (pipes, portals) */
#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK 3 /* arpanet imp addresses */
#define AF_PUP 4 /* pup protocols: e.g. BSP */
#define AF_CHAOS 5 /* mit CHAOS protocols */
#define AF_NS 6 /* XEROX NS protocols */
#define AF_IPX AF_NS /* IPX protocols: IPX, SPX, etc. */
#define AF_ISO 7 /* ISO protocols */
#define AF_OSI AF_ISO /* OSI is ISO */
#define AF_ECMA 8 /* european computer manufacturers */
#define AF_DATAKIT 9 /* datakit protocols */
#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
#define AF_SNA 11 /* IBM SNA */
#define AF_DECnet 12 /* DECnet */
#define AF_DLI 13 /* Direct data link interface */
#define AF_LAT 14 /* LAT */
#define AF_HYLINK 15 /* NSC Hyperchannel */
#define AF_APPLETALK 16 /* AppleTalk */
#define AF_NETBIOS 17 /* NetBios-style addresses */
#define AF_VOICEVIEW 18 /* VoiceView */
#define AF_FIREFOX 19 /* Protocols from Firefox */
#define AF_UNKNOWN1 20 /* Somebody is using this! */
#define AF_BAN 21 /* Banyan */
#define AF_ATM 22 /* Native ATM Services */
#define AF_INET6 23 /* Internetwork Version 6 */
#define AF_CLUSTER 24 /* Microsoft Wolfpack */
#define AF_12844 25 /* IEEE 1284.4 WG AF */
#define AF_IRDA 26 /* IrDA */
#define AF_NETDES 28 /* Network Designers OSI & gateway
enabled protocols */
#define AF_TCNPROCESS 29
#define AF_TCNMESSAGE 30
#define AF_ICLFXBM 31
#define AF_MAX 32
extern void set_address(uint32_t *net_address, uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4);
extern void set_address(
uint32_t * net_address,
uint8_t octet1,
uint8_t octet2,
uint8_t octet3,
uint8_t octet4);
#endif
+76 -65
View File
@@ -36,7 +36,7 @@
/* Analog Input = Photocell */
#define MAX_ANALOG_INPUTS 2
#if (MAX_ANALOG_INPUTS > 9)
#error Modify the Analog_Input_Name to handle multiple digits
#error Modify the Analog_Input_Name to handle multiple digits
#endif
static uint8_t Present_Value[MAX_ANALOG_INPUTS];
@@ -44,7 +44,8 @@ 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;
@@ -53,95 +54,104 @@ bool Analog_Input_Valid_Instance(uint32_t object_instance)
}
/* we simply have 0-n object instances. */
unsigned Analog_Input_Count(void)
unsigned Analog_Input_Count(
void)
{
return MAX_ANALOG_INPUTS;
}
/* we simply have 0-n object instances. */
uint32_t Analog_Input_Index_To_Instance(unsigned index)
uint32_t Analog_Input_Index_To_Instance(
unsigned index)
{
return index;
}
char *Analog_Input_Name(uint32_t object_instance)
char *Analog_Input_Name(
uint32_t object_instance)
{
static char text_string[16] = "AI-0"; /* okay for single thread */
static char text_string[16] = "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;
}
return NULL;
}
static float Analog_Input_Present_Value(uint32_t object_instance)
static float Analog_Input_Present_Value(
uint32_t object_instance)
{
float value = 0.0;
if (object_instance < MAX_ANALOG_INPUTS)
value = Present_Value[object_instance];
return value;
float value = 0.0;
if (object_instance < MAX_ANALOG_INPUTS)
value = Present_Value[object_instance];
return value;
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
@@ -152,7 +162,8 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testAnalogInput(Test * pTest)
void testAnalogInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -168,8 +179,7 @@ void testAnalogInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Analog_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -182,7 +192,8 @@ void testAnalogInput(Test * pTest)
}
#ifdef TEST_ANALOG_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -199,5 +210,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
File diff suppressed because it is too large Load Diff
+190 -172
View File
@@ -31,12 +31,12 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_ANALOG_VALUES 4
#if (MAX_ANALOG_VALUES > 9)
#error Modify the Analog_Value_Name to handle multiple digits
#error Modify the Analog_Value_Name to handle multiple digits
#endif
/* we choose to have a NULL level in our system represented by */
@@ -54,7 +54,8 @@ 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;
@@ -73,7 +74,8 @@ void Analog_Value_Init(void)
/* 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)
@@ -84,7 +86,8 @@ bool Analog_Value_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Value_Count(void)
unsigned Analog_Value_Count(
void)
{
Analog_Value_Init();
return MAX_ANALOG_VALUES;
@@ -93,7 +96,8 @@ unsigned Analog_Value_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Value_Index_To_Instance(unsigned index)
uint32_t Analog_Value_Index_To_Instance(
unsigned index)
{
Analog_Value_Init();
return index;
@@ -102,7 +106,8 @@ uint32_t Analog_Value_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
unsigned Analog_Value_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_ANALOG_VALUES;
@@ -113,7 +118,8 @@ unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static float Analog_Value_Present_Value(uint32_t object_instance)
static float Analog_Value_Present_Value(
uint32_t object_instance)
{
float value = ANALOG_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -128,12 +134,13 @@ static float Analog_Value_Present_Value(uint32_t 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[16] = "AV-0"; /* okay for single thread */
static char text_string[16] = "AV-0"; /* okay for single thread */
if (object_instance < MAX_ANALOG_VALUES) {
text_string[3] = '0' + (uint8_t)object_instance;
text_string[3] = '0' + (uint8_t) object_instance;
return text_string;
}
@@ -141,13 +148,15 @@ char *Analog_Value_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = (float) 1.414;
@@ -160,110 +169,118 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
Analog_Value_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Present_Value[object_index][i] ==
ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Present_Value[object_index][i];
len = encode_application_real(&apdu[apdu_len], real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Present_Value[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Present_Value[object_index][array_index - 1];
apdu_len = encode_application_real(&apdu[0], real_value);
state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Present_Value[object_index][i] == ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Present_Value[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Present_Value[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Present_Value[object_index][array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -284,80 +301,80 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
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 */ ) &&
(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);
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) */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
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. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(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);
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) */
status = true;
} 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
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Present_Value[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) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Present_Value[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) */
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
} else {
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -369,7 +386,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testAnalog_Value(Test * pTest)
void testAnalog_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -384,8 +402,7 @@ void testAnalog_Value(Test * pTest)
len = Analog_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -398,7 +415,8 @@ void testAnalog_Value(Test * pTest)
}
#ifdef TEST_ANALOG_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -415,5 +433,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
+84 -71
View File
@@ -35,26 +35,28 @@
#define MAX_BINARY_INPUTS 8
#if (MAX_BINARY_INPUTS > 9)
#error Modify the Binary_Input_Name to handle multiple digits
#error Modify the Binary_Input_Name to handle multiple digits
#endif
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;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
}
}
}
/* 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;
@@ -63,13 +65,15 @@ bool Binary_Input_Valid_Instance(uint32_t object_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;
}
@@ -77,7 +81,8 @@ uint32_t Binary_Input_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
unsigned Binary_Input_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_INPUTS;
@@ -87,8 +92,8 @@ unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
@@ -96,18 +101,19 @@ static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
Binary_Input_Initialize();
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
value = Present_Value[index];
value = Present_Value[index];
}
return value;
}
char *Binary_Input_Name(uint32_t object_instance)
char *Binary_Input_Name(
uint32_t object_instance)
{
static char text_string[16] = "BI-0"; /* okay for single thread */
static char text_string[16] = "BI-0"; /* okay for single thread */
if (object_instance < MAX_BINARY_INPUTS) {
text_string[3] = '0' + (uint8_t)object_instance;
text_string[3] = '0' + (uint8_t) object_instance;
return text_string;
}
@@ -116,13 +122,15 @@ char *Binary_Input_Name(uint32_t object_instance)
/* return apdu length, or -1 on error */
/* assumption - object already exists, and has been bounds checked */
int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
int Binary_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_POLARITY polarity = POLARITY_NORMAL;
@@ -132,48 +140,52 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
(void) array_index;
Binary_Input_Initialize();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
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(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
break;
case PROP_PRESENT_VALUE:
value = Binary_Input_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0],value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
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(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
break;
case PROP_PRESENT_VALUE:
value = Binary_Input_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
@@ -184,7 +196,8 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testBinaryInput(Test * pTest)
void testBinaryInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -200,8 +213,7 @@ void testBinaryInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Binary_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -214,7 +226,8 @@ void testBinaryInput(Test * pTest)
}
#ifdef TEST_BINARY_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -231,5 +244,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
+11 -9
View File
@@ -14,28 +14,30 @@
#include "board.h"
/* global variables */
unsigned long blinkcount;
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 unsigned int j,k; /* loop counters */
volatile unsigned int j, k; /* loop counters */
/* endless loop */
while (1) {
while (1) {
/* count out the proper number of blinks */
for (j = code; j != 0; j--) {
for (j = code; j != 0; j--) {
/* 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++;
}
}
+26 -26
View File
@@ -7,10 +7,10 @@
// fitness for any particular purpose, or against the infringements of
// intellectual property rights of others.
//----------------------------------------------------------------------------------------------------
// File Name: Board.h
// Object: AT91SAM7S Evaluation Board Features Definition File.
// File Name: Board.h
// Object: AT91SAM7S Evaluation Board Features Definition File.
//
// Creation: JPP 16/June/2004
// Creation: JPP 16/June/2004
//----------------------------------------------------------------------------------------------------
#ifndef Board_h
#define Board_h
@@ -35,10 +35,10 @@
//------------------------
// Leds Definition
//------------------------
#define LED1 (1<<0) // PA0
#define LED2 (1<<1) // PA1
#define LED3 (1<<2) // PA2
#define LED4 (1<<3) // PA3
#define LED1 (1<<0) // PA0
#define LED2 (1<<1) // PA1
#define LED3 (1<<2) // PA2
#define LED4 (1<<3) // PA3
#define NB_LEB 4
#define LED_MASK (LED1|LED2|LED3|LED4)
@@ -46,34 +46,34 @@
//----------------------------------
// Push Buttons Definition
//-----------------------------------
#define SW1_MASK (1<<19) // PA19
#define SW2_MASK (1<<20) // PA20
#define SW3_MASK (1<<15) // PA15
#define SW4_MASK (1<<14) // PA14
#define SW1_MASK (1<<19) // PA19
#define SW2_MASK (1<<20) // PA20
#define SW3_MASK (1<<15) // PA15
#define SW4_MASK (1<<14) // PA14
#define SW_MASK (SW1_MASK|SW2_MASK|SW3_MASK|SW4_MASK)
#define SW1 (1<<19) // PA19
#define SW2 (1<<20) // PA20
#define SW3 (1<<15) // PA15
#define SW4 (1<<14) // PA14
#define SW1 (1<<19) // PA19
#define SW2 (1<<20) // PA20
#define SW3 (1<<15) // PA15
#define SW4 (1<<14) // PA14
//-------------------------
// USART Definition
//-------------------------
// SUB-D 9 points J3 DBGU
#define DBGU_RXD AT91C_PA9_DRXD // JP11 must be close
#define DBGU_TXD AT91C_PA10_DTXD // JP12 must be close
#define AT91C_DBGU_BAUD 115200 // Baud rate
#define US_RXD_PIN AT91C_PA5_RXD0 // JP9 must be close
#define US_TXD_PIN AT91C_PA6_TXD0 // JP7 must be close
#define US_RTS_PIN AT91C_PA7_RTS0 // JP8 must be close
#define US_CTS_PIN AT91C_PA8_CTS0 // JP6 must be close
#define DBGU_RXD AT91C_PA9_DRXD // JP11 must be close
#define DBGU_TXD AT91C_PA10_DTXD // JP12 must be close
#define AT91C_DBGU_BAUD 115200 // Baud rate
#define US_RXD_PIN AT91C_PA5_RXD0 // JP9 must be close
#define US_TXD_PIN AT91C_PA6_TXD0 // JP7 must be close
#define US_RTS_PIN AT91C_PA7_RTS0 // JP8 must be close
#define US_CTS_PIN AT91C_PA8_CTS0 // JP6 must be close
//--------------
// Master Clock
//--------------
#define EXT_OC 18432000 // Exetrnal ocilator MAINCK
#define MCK 47923200 // MCK (PLLRC div by 2)
#define MCKKHz (MCK/1000) //
#define EXT_OC 18432000 // Exetrnal ocilator MAINCK
#define MCK 47923200 // MCK (PLLRC div by 2)
#define MCKKHz (MCK/1000) //
#endif // Board_h
#endif // Board_h
+155 -140
View File
@@ -31,31 +31,33 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_BINARY_VALUES 8
#if (MAX_BINARY_VALUES > 9)
#error Modify the Binary_Value_Name to handle multiple digits
#error Modify the Binary_Value_Name to handle multiple digits
#endif
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;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_VALUES; i++) {
Present_Value[i] = BINARY_INACTIVE;
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_VALUES; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
}
}
}
/* 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;
@@ -64,19 +66,22 @@ bool Binary_Value_Valid_Instance(uint32_t object_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;
@@ -86,8 +91,8 @@ unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Value_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
@@ -100,12 +105,13 @@ static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
}
/* 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] = "BV-0"; /* okay for single thread */
static char text_string[16] = "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;
}
@@ -113,13 +119,15 @@ 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,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
@@ -127,58 +135,64 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
Binary_Value_Initialize();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
/* FIXME: figure out the polarity */
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
/* FIXME: figure out the polarity */
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -198,85 +212,85 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
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 */ ) &&
(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);
priority--;
/* NOTE: this Binary value has no priority array */
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. */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
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 */ ) &&
(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);
priority--;
/* NOTE: this Binary value has no priority array */
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. */
status = true;
} 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
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
#if 0
/* NOTE: this Binary Value has no priority array */
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_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) */
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_WRITE_ACCESS_DENIED;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
break;
#if 0
/* NOTE: this Binary Value has no priority array */
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_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) */
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
#else
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
break;
#endif
} else {
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -287,7 +301,8 @@ 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;
@@ -302,8 +317,7 @@ void testBinary_Value(Test * pTest)
len = Binary_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -316,7 +330,8 @@ void testBinary_Value(Test * pTest)
}
#ifdef TEST_BINARY_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -333,5 +348,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
+329 -291
View File
@@ -53,13 +53,15 @@ static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
BACNET_REINITIALIZED_STATE_OF_DEVICE Reinitialize_State =
REINITIALIZED_STATE_IDLE;
void Device_Reinit(void)
void Device_Reinit(
void)
{
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
}
void Device_Init(void)
void Device_Init(
void)
{
Reinitialize_State = REINITIALIZED_STATE_IDLE;
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
@@ -71,14 +73,16 @@ void Device_Init(void)
}
/* methods to manipulate the data */
uint32_t Device_Object_Instance_Number(void)
uint32_t Device_Object_Instance_Number(
void)
{
return Object_Instance_Number;
}
bool Device_Set_Object_Instance_Number(uint32_t object_id)
bool Device_Set_Object_Instance_Number(
uint32_t object_id)
{
bool status = true; /* return value */
bool status = true; /* return value */
if (object_id <= BACNET_MAX_INSTANCE) {
Object_Instance_Number = object_id;
@@ -94,69 +98,81 @@ bool Device_Set_Object_Instance_Number(uint32_t object_id)
return status;
}
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
bool Device_Valid_Object_Instance_Number(
uint32_t object_id)
{
/* BACnet allows for a wildcard instance number */
return ((Object_Instance_Number == object_id) ||
(object_id == BACNET_MAX_INSTANCE));
}
BACNET_DEVICE_STATUS Device_System_Status(void)
BACNET_DEVICE_STATUS Device_System_Status(
void)
{
return System_Status;
}
void Device_Set_System_Status(BACNET_DEVICE_STATUS status)
void Device_Set_System_Status(
BACNET_DEVICE_STATUS status)
{
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 1;
}
uint8_t Device_Protocol_Revision(void)
uint8_t Device_Protocol_Revision(
void)
{
return 5;
}
/* FIXME: MAX_APDU is defined in config.ini - set it! */
uint16_t Device_Max_APDU_Length_Accepted(void)
uint16_t Device_Max_APDU_Length_Accepted(
void)
{
return MAX_APDU;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
BACNET_SEGMENTATION Device_Segmentation_Supported(
void)
{
return SEGMENTATION_NONE;
}
uint16_t Device_APDU_Timeout(void)
uint16_t Device_APDU_Timeout(
void)
{
return 60000;
}
uint8_t Device_Number_Of_APDU_Retries(void)
uint8_t Device_Number_Of_APDU_Retries(
void)
{
return 0;
}
uint8_t Device_Database_Revision(void)
uint8_t Device_Database_Revision(
void)
{
return 0;
}
unsigned Device_Object_List_Count(void)
unsigned Device_Object_List_Count(
void)
{
unsigned count = 1; /* at least 1 for device object */
unsigned count = 1; /* at least 1 for device object */
/* FIXME: add objects as needed */
count += Binary_Input_Count();
@@ -167,8 +183,10 @@ unsigned Device_Object_List_Count(void)
return count;
}
bool Device_Object_List_Identifier(unsigned array_index,
int *object_type, uint32_t * instance)
bool Device_Object_List_Identifier(
unsigned array_index,
int *object_type,
uint32_t * instance)
{
bool status = false;
unsigned object_index = 0;
@@ -238,13 +256,15 @@ bool Device_Object_List_Identifier(unsigned 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,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned i = 0;
@@ -256,203 +276,221 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
/* FIXME: change the hardcoded names to suit your application */
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
characterstring_init_ansi(&char_string, Object_Name);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, "BACnet Demo");
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());
break;
case PROP_VENDOR_NAME:
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
characterstring_init_ansi(&char_string, "GNU Demo");
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
characterstring_init_ansi(&char_string, "1.0");
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_LOCATION:
characterstring_init_ansi(&char_string, "USA");
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());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Protocol_Revision());
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* FIXME: if ReadProperty used an array of Functions... */
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
case PROP_OBJECT_IDENTIFIER:
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);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, "BACnet Demo");
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());
break;
case PROP_VENDOR_NAME:
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
characterstring_init_ansi(&char_string, "GNU Demo");
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
characterstring_init_ansi(&char_string, "1.0");
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_LOCATION:
characterstring_init_ansi(&char_string, "USA");
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());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Protocol_Revision());
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* FIXME: if ReadProperty used an array of Functions... */
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
*error_code = ERROR_CODE_OTHER;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_OTHER;
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
break;
}
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0],
Device_Max_APDU_Length_Accepted());
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_application_unsigned(&apdu[0], Device_APDU_Timeout());
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Number_Of_APDU_Retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Database_Revision());
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 PROP_LOCAL_TIME:
/* FIXME: if you support time */
local_time.hour = 0;
local_time.min = 0;
local_time.sec = 0;
local_time.hundredths = 0;
apdu_len = encode_application_time(&apdu[0], &local_time);
break;
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is inverse of everybody else */
apdu_len = encode_application_signed(&apdu[0], 5 /* 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 */
apdu_len = encode_application_date(&apdu[0], &local_date);
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
/* FIXME: if you support time/date */
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case 9600:
apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0],
Device_Max_APDU_Length_Accepted());
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len =
encode_application_unsigned(&apdu[0], Device_APDU_Timeout());
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Number_Of_APDU_Retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Database_Revision());
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 PROP_LOCAL_TIME:
/* FIXME: if you support time */
local_time.hour = 0;
local_time.min = 0;
local_time.sec = 0;
local_time.hundredths = 0;
apdu_len = encode_application_time(&apdu[0], &local_time);
break;
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is inverse of everybody else */
apdu_len = encode_application_signed(&apdu[0], 5 /* 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 */
apdu_len = encode_application_date(&apdu[0], &local_date);
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
/* FIXME: if you support time/date */
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case 9600:
apdu_len =
encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
int len = 0;
@@ -469,98 +507,98 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
File diff suppressed because it is too large Load Diff
+16 -30
View File
@@ -62,52 +62,39 @@ int Encode_Property_APDU(
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
/* handle each object type */
switch(object_type) {
switch (object_type) {
case OBJECT_DEVICE:
if (Device_Valid_Object_Instance_Number(object_instance)) {
apdu_len = Device_Encode_Property_APDU(
&apdu[0],
property,
array_index,
error_class, error_code);
apdu_len = Device_Encode_Property_APDU(&apdu[0],
property, array_index, error_class, error_code);
}
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(object_instance)) {
apdu_len = Analog_Input_Encode_Property_APDU(
&apdu[0],
apdu_len = Analog_Input_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(object_instance)) {
apdu_len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(object_instance)) {
apdu_len = Binary_Input_Encode_Property_APDU(
&apdu[0],
apdu_len = Binary_Input_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Valid_Instance(object_instance)) {
apdu_len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
default:
@@ -119,9 +106,11 @@ int Encode_Property_APDU(
return apdu_len;
}
void handler_read_property(uint8_t * service_request,
void handler_read_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
@@ -154,13 +143,10 @@ void handler_read_property(uint8_t * service_request,
}
/* most cases will be error */
error = true;
len = Encode_Property_APDU(
&Temp_Buf[0],
len = Encode_Property_APDU(&Temp_Buf[0],
data.object_type,
data.object_instance,
data.object_property,
data.array_index,
&error_class, &error_code);
data.object_property, data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
@@ -183,7 +169,7 @@ void handler_read_property(uint8_t * service_request,
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
}
RP_ABORT:
RP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+55 -60
View File
@@ -46,9 +46,11 @@
/* too big to reside on stack frame for PIC */
static BACNET_WRITE_PROPERTY_DATA wp_data;
void handler_write_property(uint8_t * service_request,
void handler_write_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
@@ -70,8 +72,7 @@ void handler_write_property(uint8_t * service_request,
goto WP_ABORT;
}
/* decode the service request only */
len = wp_decode_service_request(service_request,
service_len, &wp_data);
len = wp_decode_service_request(service_request, service_len, &wp_data);
/* bad decoding or something we didn't understand - send an abort */
if (len <= 0) {
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
@@ -80,67 +81,61 @@ void handler_write_property(uint8_t * service_request,
}
/* handle the object type */
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
}
WP_ABORT:
WP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+24 -23
View File
@@ -20,9 +20,12 @@
// 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
@@ -30,31 +33,33 @@ extern void AT91F_Default_FIQ_handler(void);
//* 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;
int i;
AT91PS_PMC pPMC = AT91C_BASE_PMC;
//* Set Flash Wait sate
// Single Cycle Access at Up to 30 MHz, or 40
// if MCK = 48054841 I have 50 Cycle for 1 usecond ( flied MC_FMR->FMCN
// result: AT91C_MC_FMR = 0x00320100 (MC Flash Mode Register)
AT91C_BASE_MC->MC_FMR = (((AT91C_MC_FMCN) & (50 <<16)) | AT91C_MC_FWS_1FWS);
AT91C_BASE_MC->MC_FMR =
(((AT91C_MC_FMCN) & (50 << 16)) | AT91C_MC_FWS_1FWS);
//* Watchdog Disable
// result: AT91C_WDTC_WDMR = 0x00008000 (Watchdog Mode Register)
AT91C_BASE_WDTC->WDTC_WDMR= AT91C_WDTC_WDDIS;
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
//* Set MCK at 48 054 841
// 1 Enabling the Main Oscillator:
// SCK = 1/32768 = 30.51 uSecond
// Start up time = 8 * 6 / SCK = 56 * 30.51 = 1,46484375 ms
// result: AT91C_CKGR_MOR = 0x00000601 (Main Oscillator Register)
pPMC->PMC_MOR = ((AT91C_CKGR_OSCOUNT & (0x06<<8)) | AT91C_CKGR_MOSCEN);
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
//
// The following settings are used: DIV = 14
@@ -73,12 +78,11 @@ void LowLevelInit(void)
// 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)));
(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
//
// CSS = 3 (PLLCK clock selected)
@@ -88,14 +92,11 @@ void LowLevelInit(void)
// Note: Master Clock MCK = 48054841 hz (this is the CPU clock speed)
// result: AT91C_PMC_MCKR = 0x00000007 (Master Clock Register)
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;
for (i = 1; i < 31; i++)
{
for (i = 1; i < 31; i++) {
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;
}
+20 -10
View File
@@ -21,19 +21,24 @@
#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();
@@ -41,7 +46,8 @@ unsigned disableIRQ(void)
return _cpsr;
}
unsigned restoreIRQ(unsigned oldCPSR)
unsigned restoreIRQ(
unsigned oldCPSR)
{
unsigned _cpsr;
@@ -50,7 +56,8 @@ unsigned restoreIRQ(unsigned oldCPSR)
return _cpsr;
}
unsigned enableIRQ(void)
unsigned enableIRQ(
void)
{
unsigned _cpsr;
@@ -59,7 +66,8 @@ unsigned enableIRQ(void)
return _cpsr;
}
unsigned disableFIQ(void)
unsigned disableFIQ(
void)
{
unsigned _cpsr;
@@ -68,7 +76,8 @@ unsigned disableFIQ(void)
return _cpsr;
}
unsigned restoreFIQ(unsigned oldCPSR)
unsigned restoreFIQ(
unsigned oldCPSR)
{
unsigned _cpsr;
@@ -77,7 +86,8 @@ unsigned restoreFIQ(unsigned oldCPSR)
return _cpsr;
}
unsigned enableFIQ(void)
unsigned enableFIQ(
void)
{
unsigned _cpsr;
+31 -28
View File
@@ -48,9 +48,12 @@
// *******************************************************
// 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);
// *******************************************************
// FIXME: use header files? Global Variables
@@ -64,7 +67,8 @@ static unsigned long LED_Timer_3 = 0;
static unsigned long LED_Timer_4 = 1000;
static unsigned long DCC_Timer = 1000;
static void millisecond_timer(void)
static void millisecond_timer(
void)
{
while (Timer_Milliseconds) {
Timer_Milliseconds--;
@@ -87,11 +91,12 @@ static void millisecond_timer(void)
/* note: MS/TP silence timer is updated in ISR */
}
static void init(void)
static void init(
void)
{
/* Initialize the Parallel I/O Controller A Peripheral Clock */
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<<AT91C_ID_PIOA);
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1 << AT91C_ID_PIOA);
// Set up the LEDs (PA0 - PA3)
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
@@ -112,23 +117,23 @@ static void init(void)
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC;
// Disable FIQ interrupt in
// AIC Interrupt Disable Command Register
pAIC->AIC_IDCR = (1<<AT91C_ID_FIQ);
pAIC->AIC_IDCR = (1 << AT91C_ID_FIQ);
// Set the interrupt source type in
// AIC Source Mode Register[0]
pAIC->AIC_SMR[AT91C_ID_FIQ] =
(AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED);
pAIC->AIC_SMR[AT91C_ID_FIQ] = (AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED);
// Clear the FIQ interrupt in
// AIC Interrupt Clear Command Register
pAIC->AIC_ICCR = (1<<AT91C_ID_FIQ);
pAIC->AIC_ICCR = (1 << AT91C_ID_FIQ);
// Remove disable FIQ interrupt in
// AIC Interrupt Disable Command Register
pAIC->AIC_IDCR = (0<<AT91C_ID_FIQ);
pAIC->AIC_IDCR = (0 << AT91C_ID_FIQ);
// Enable the FIQ interrupt in
// AIC Interrupt Enable Command Register
pAIC->AIC_IECR = (1<<AT91C_ID_FIQ);
pAIC->AIC_IECR = (1 << AT91C_ID_FIQ);
}
static void bacnet_init(void)
static void bacnet_init(
void)
{
#if defined(BACDL_MSTP)
RS485_Set_Baud_Rate(38400);
@@ -140,8 +145,7 @@ static void bacnet_init(void)
Device_Set_Object_Instance_Number(22222);
#ifndef DLMSTP_TEST
/* 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_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,
@@ -157,14 +161,16 @@ static void bacnet_init(void)
#endif
}
int main (void) {
unsigned long IdleCount = 0; // idle loop blink counter
int main(
void)
{
unsigned long IdleCount = 0; // idle loop blink counter
bool LED1_Off_Enabled = true;
bool LED2_Off_Enabled = true;
bool LED3_Off_Enabled = true;
uint16_t pdu_len = 0;
BACNET_ADDRESS src; /* source address */
uint8_t pdu[MAX_MPDU]; /* PDU data */
uint8_t pdu[MAX_MPDU]; /* PDU data */
// Set up the LEDs (PA0 - PA3)
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
@@ -177,9 +183,9 @@ int main (void) {
// enable interrupts
enableIRQ();
enableFIQ();
/* broadcast an I-Am on startup */
/* broadcast an I-Am on startup */
iam_send(&Handler_Transmit_Buffer[0]);
// endless blink loop
// endless blink loop
while (1) {
millisecond_timer();
if (!DCC_Timer) {
@@ -187,8 +193,7 @@ int main (void) {
DCC_Timer = 1000;
}
/* USART Tx turns the LED on, we turn it off */
if (((pPIO->PIO_ODSR & LED1) == LED1) && (LED1_Off_Enabled))
{
if (((pPIO->PIO_ODSR & LED1) == LED1) && (LED1_Off_Enabled)) {
LED1_Off_Enabled = false;
/* wait */
LED_Timer_1 = 20;
@@ -199,8 +204,7 @@ int main (void) {
LED1_Off_Enabled = true;
}
/* USART Rx turns the LED on, we turn it off */
if (((pPIO->PIO_ODSR & LED2) == LED2) && (LED2_Off_Enabled))
{
if (((pPIO->PIO_ODSR & LED2) == LED2) && (LED2_Off_Enabled)) {
LED2_Off_Enabled = false;
/* wait */
LED_Timer_2 = 20;
@@ -211,8 +215,7 @@ int main (void) {
LED2_Off_Enabled = true;
}
/* switch or NPDU turns on the LED, we turn it off */
if (((pPIO->PIO_ODSR & LED3) == LED3) && (LED3_Off_Enabled))
{
if (((pPIO->PIO_ODSR & LED3) == LED3) && (LED3_Off_Enabled)) {
LED3_Off_Enabled = false;
/* wait */
LED_Timer_3 = 500;
@@ -224,7 +227,7 @@ int main (void) {
}
/* Blink LED every second */
if (!LED_Timer_4) {
if ((pPIO->PIO_ODSR & LED4) == LED4) {
if ((pPIO->PIO_ODSR & LED4) == LED4) {
/* turn on */
pPIO->PIO_CODR = LED4;
} else {
+50 -45
View File
@@ -62,52 +62,51 @@ static int RS485_Baud = 38400;
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize(void)
void RS485_Initialize(
void)
{
/* Enable the USART0 clock in the Power Management Controller */
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<<AT91C_ID_US0);
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1 << AT91C_ID_US0);
/* Disable and clear USART0 interrupt
in AIC Interrupt Disable Command Register */
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC;
pAIC->AIC_IDCR = (1<<AT91C_ID_US0);
pAIC->AIC_ICCR = (1<<AT91C_ID_US0);
pAIC->AIC_IDCR = (1 << AT91C_ID_US0);
pAIC->AIC_ICCR = (1 << AT91C_ID_US0);
/* 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 */
AT91C_US_TXDIS; /* Transmitter 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;
/* Receiver Time-out disabled */
RS485_Interface->US_RTOR = 0;
/* baud rate */
RS485_Interface->US_BRGR = MCK/16/RS485_Baud;
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)
{
}
@@ -118,7 +117,8 @@ void RS485_Cleanup(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
uint32_t RS485_Get_Baud_Rate(
void)
{
return RS485_Baud;
}
@@ -129,7 +129,8 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_Set_Baud_Rate(uint32_t baud)
bool RS485_Set_Baud_Rate(
uint32_t baud)
{
bool valid = true;
@@ -141,7 +142,7 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
case 76800:
case 115200:
RS485_Baud = baud;
RS485_Interface->US_BRGR = MCK/16/baud;
RS485_Interface->US_BRGR = MCK / 16 / baud;
/* FIXME: store the baud rate */
break;
default:
@@ -158,14 +159,15 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Turnaround_Delay(void)
void RS485_Turnaround_Delay(
void)
{
uint16_t turnaround_time;
/* delay after reception before trasmitting - per MS/TP spec */
/* wait a minimum 40 bit times since reception */
/* at least 1 ms for errors: rounding, clock tick */
turnaround_time = 1 + ((Tturnaround*1000UL)/RS485_Baud);
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud);
while (Timer_Silence() < turnaround_time) {
/* do nothing - wait for timer to increment */
};
@@ -177,9 +179,10 @@ void RS485_Turnaround_Delay(void)
* ALGORITHM: none
* NOTES: The Atmel ARM7 has an automatic enable/disable in RS485 mode.
*****************************************************************************/
void RS485_Transmitter_Enable(bool enable)
void RS485_Transmitter_Enable(
bool enable)
{
(void)enable;
(void) enable;
}
/****************************************************************************
@@ -189,9 +192,9 @@ void RS485_Transmitter_Enable(bool enable)
* NOTES: none
*****************************************************************************/
void RS485_Send_Data(
uint8_t * buffer, /* data to send */
uint16_t nbytes) /* number of bytes of data */
{
uint8_t * buffer, /* data to send */
uint16_t nbytes)
{ /* number of bytes of data */
/* LED on send */
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
/* LED ON */
@@ -218,7 +221,8 @@ void RS485_Send_Data(
* ALGORITHM: none
* NOTES: Clears any error flags.
*****************************************************************************/
bool RS485_ReceiveError(void)
bool RS485_ReceiveError(
void)
{
bool ReceiveError = false;
/* LED on send */
@@ -242,25 +246,27 @@ bool RS485_ReceiveError(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_DataAvailable(uint8_t *DataRegister)
bool RS485_DataAvailable(
uint8_t * DataRegister)
{
bool DataAvailable = false;
/* LED on send */
volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;
if ( RS485_Interface->US_CSR & AT91C_US_RXRDY) {
if (RS485_Interface->US_CSR & AT91C_US_RXRDY) {
/* data is available */
*DataRegister = RS485_Interface->US_RHR;
DataAvailable = true;
/* LED ON */
pPIO->PIO_CODR = LED2;
}
return DataAvailable;
}
#ifdef TEST_RS485
int main(void)
int main(
void)
{
unsigned i = 0;
uint8_t DataRegister;
@@ -270,11 +276,10 @@ int main(void)
/* receive task */
for (;;) {
if (RS485_ReceiveError()) {
fprintf(stderr,"ERROR ");
fprintf(stderr, "ERROR ");
} else if (RS485_DataAvailable(&DataRegister)) {
fprintf(stderr,"%02X ",DataRegister);
fprintf(stderr, "%02X ", DataRegister);
}
}
}
#endif
#endif
+16 -9
View File
@@ -30,24 +30,31 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void RS485_Initialize(void);
void RS485_Initialize(
void);
void RS485_Transmitter_Enable(bool enable);
void RS485_Transmitter_Enable(
bool enable);
void RS485_Send_Data(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
bool RS485_ReceiveError(void);
bool RS485_DataAvailable(uint8_t *data);
bool RS485_ReceiveError(
void);
bool RS485_DataAvailable(
uint8_t * data);
void RS485_Turnaround_Delay(void);
uint32_t RS485_Get_Baud_Rate(void);
bool RS485_Set_Baud_Rate(uint32_t baud);
void RS485_Turnaround_Delay(
void);
uint32_t RS485_Get_Baud_Rate(
void);
bool RS485_Set_Baud_Rate(
uint32_t baud);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+22 -16
View File
@@ -50,7 +50,9 @@ 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)
//
// |------------------------------------------------------------------|------|
@@ -214,7 +216,7 @@ static void Timer0_Setup(int milliseconds) {
//
// TIMER_CLOCK5 = (MCK / 1024) / 1000
// = 48054841 / 1024 / 1000 = 46.928
pTC->TC_RC = ((MCK/1024/1000)+1)*milliseconds;
pTC->TC_RC = ((MCK / 1024 / 1000) + 1) * milliseconds;
// TC Interrupt Enable Register TC_IER (write-only)
//
@@ -297,9 +299,11 @@ static void Timer0_Setup(int milliseconds) {
// 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 AT91PS_TC pTC = AT91C_BASE_TC0; // pointer to timer channel 0 register structure
unsigned int dummy; // temporary
// read TC0 Status Register to clear interrupt
@@ -310,12 +314,14 @@ static void Timer0IrqHandler (void) {
SilenceTime++;
}
int Timer_Silence(void)
int Timer_Silence(
void)
{
return SilenceTime;
}
void Timer_Silence_Reset(void)
void Timer_Silence_Reset(
void)
{
SilenceTime = 0;
}
@@ -330,33 +336,33 @@ void Timer_Silence_Reset(void)
// Moved timer startup code from main
// modified the peripheral clock init
// *****************************************************************************
void TimerInit(void)
void TimerInit(
void)
{
// enable the Timer0 peripheral clock
volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1<<AT91C_ID_TC0);
pPMC->PMC_PCER = pPMC->PMC_PCSR | (1 << AT91C_ID_TC0);
// Set up the AIC registers for Timer 0
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC;
volatile AT91PS_AIC pAIC = AT91C_BASE_AIC;
// Disable timer 0 interrupt
// in AIC Interrupt Disable Command Register
pAIC->AIC_IDCR = (1<<AT91C_ID_TC0);
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 );
(AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 0x4);
// Clear the TC0 interrupt
// in AIC Interrupt Clear Command Register
pAIC->AIC_ICCR = (1<<AT91C_ID_TC0);
pAIC->AIC_ICCR = (1 << AT91C_ID_TC0);
// Remove disable timer 0 interrupt
// in AIC Interrupt Disable Command Reg
pAIC->AIC_IDCR = (0<<AT91C_ID_TC0);
pAIC->AIC_IDCR = (0 << AT91C_ID_TC0);
// Enable the TC0 interrupt
// in AIC Interrupt Enable Command Register
pAIC->AIC_IECR = (1<<AT91C_ID_TC0);
pAIC->AIC_IECR = (1 << AT91C_ID_TC0);
// Setup timer0 to generate a 1 msec periodic interrupt
Timer0_Setup(1);
}
+8 -5
View File
@@ -32,13 +32,16 @@ extern volatile unsigned long Timer_Milliseconds;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void TimerInit(void);
int Timer_Silence(void);
void Timer_Silence_Reset(void);
void TimerInit(
void);
int Timer_Silence(
void);
void Timer_Silence_Reset(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+65 -55
View File
@@ -36,7 +36,7 @@
/* Analog Input = Photocell */
#define MAX_ANALOG_INPUTS 9
#if (MAX_ANALOG_INPUTS > 9)
#error Modify the Analog_Input_Name to handle multiple digits
#error Modify the Analog_Input_Name to handle multiple digits
#endif
float Present_Value[MAX_ANALOG_INPUTS];
@@ -44,7 +44,8 @@ float Present_Value[MAX_ANALOG_INPUTS];
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Input_Valid_Instance(uint32_t object_instance)
bool Analog_Input_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_ANALOG_INPUTS)
return true;
@@ -53,30 +54,34 @@ bool Analog_Input_Valid_Instance(uint32_t object_instance)
}
/* we simply have 0-n object instances. */
unsigned Analog_Input_Count(void)
unsigned Analog_Input_Count(
void)
{
return MAX_ANALOG_INPUTS;
}
/* we simply have 0-n object instances. */
uint32_t Analog_Input_Index_To_Instance(unsigned index)
uint32_t Analog_Input_Index_To_Instance(
unsigned index)
{
return index;
}
/* we simply have 0-n object instances. */
unsigned Analog_Input_Instance_To_Index(uint32_t object_instance)
unsigned Analog_Input_Instance_To_Index(
uint32_t object_instance)
{
return object_instance;
}
char *Analog_Input_Name(uint32_t object_instance)
char *Analog_Input_Name(
uint32_t object_instance)
{
static char text_string[5] = "AI-0"; /* okay for single thread */
static char text_string[5] = "AI-0"; /* okay for single thread */
if (object_instance < MAX_ANALOG_INPUTS) {
text_string[3] = '0' + (uint8_t)object_instance;
text_string[3] = '0' + (uint8_t) object_instance;
return text_string;
}
@@ -85,13 +90,15 @@ char *Analog_Input_Name(uint32_t object_instance)
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned object_index;
@@ -99,50 +106,53 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different.
Note that Object-Name must be unique in this device */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
object_index = Analog_Input_Instance_To_Index(object_instance);
apdu_len = encode_application_real(&apdu[0],
Present_Value[object_index]);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different.
Note that Object-Name must be unique in this device */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
object_index = Analog_Input_Instance_To_Index(object_instance);
apdu_len = encode_application_real(&apdu[0],
Present_Value[object_index]);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
+46 -42
View File
@@ -41,7 +41,8 @@
#include "bacenum.h"
#include "handlers.h"
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
bool apdu_service_supported(
BACNET_SERVICES_SUPPORTED service_supported)
{
bool status = false;
@@ -57,13 +58,15 @@ bool apdu_service_supported(BACNET_SERVICES_SUPPORTED service_supported)
return status;
}
uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
uint16_t apdu_decode_confirmed_service_request(
uint8_t * apdu, /* APDU data */
uint16_t apdu_len,
BACNET_CONFIRMED_SERVICE_DATA * service_data,
uint8_t * service_choice,
uint8_t ** service_request, uint16_t * service_request_len)
uint8_t ** service_request,
uint16_t * service_request_len)
{
uint16_t len = 0; /* counts where we are in PDU */
uint16_t len = 0; /* counts where we are in PDU */
service_data->segmented_message = (apdu[0] & BIT3) ? true : false;
service_data->more_follows = (apdu[0] & BIT2) ? true : false;
@@ -84,55 +87,56 @@ uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
return len;
}
void apdu_handler(BACNET_ADDRESS * src, uint8_t * apdu, /* APDU data */
void apdu_handler(
BACNET_ADDRESS * src,
uint8_t * apdu, /* APDU data */
uint16_t apdu_len)
{
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
uint16_t len = 0; /* counts where we are in PDU */
uint16_t len = 0; /* counts where we are in PDU */
if (apdu) {
/* PDU Type */
switch (apdu[0] & 0xF0) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
apdu_len,
&service_data,
&service_choice, &service_request, &service_request_len);
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
handler_read_property(service_request,
service_request_len, src, &service_data);
}
#if 0
else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
handler_write_property(service_request,
service_request_len, src, &service_data);
}
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
apdu_len,
&service_data,
&service_choice, &service_request, &service_request_len);
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
handler_read_property(service_request,
service_request_len, src, &service_data);
}
#if 0
else if (service_choice == SERVICE_CONFIRMED_WRITE_PROPERTY) {
handler_write_property(service_request,
service_request_len, src, &service_data);
}
#endif
else {
handler_unrecognized_service(service_request,
service_request_len, src, &service_data);
}
break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
service_choice = apdu[1];
service_request = &apdu[2];
service_request_len = apdu_len - 2;
if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
handler_who_is(service_request,
service_request_len, src);
}
break;
case PDU_TYPE_SIMPLE_ACK:
case PDU_TYPE_COMPLEX_ACK:
case PDU_TYPE_SEGMENT_ACK:
case PDU_TYPE_ERROR:
case PDU_TYPE_REJECT:
case PDU_TYPE_ABORT:
default:
break;
else {
handler_unrecognized_service(service_request,
service_request_len, src, &service_data);
}
break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
service_choice = apdu[1];
service_request = &apdu[2];
service_request_len = apdu_len - 2;
if (service_choice == SERVICE_UNCONFIRMED_WHO_IS) {
handler_who_is(service_request, service_request_len, src);
}
break;
case PDU_TYPE_SIMPLE_ACK:
case PDU_TYPE_COMPLEX_ACK:
case PDU_TYPE_SEGMENT_ACK:
case PDU_TYPE_ERROR:
case PDU_TYPE_REJECT:
case PDU_TYPE_ABORT:
default:
break;
}
}
return;
+89 -75
View File
@@ -31,12 +31,12 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_ANALOG_VALUES 9
#if (MAX_ANALOG_VALUES > 9)
#error Modify the Analog_Value_Name to handle multiple digits
#error Modify the Analog_Value_Name to handle multiple digits
#endif
float Present_Value[MAX_ANALOG_VALUES];
@@ -44,7 +44,8 @@ float Present_Value[MAX_ANALOG_VALUES];
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Value_Valid_Instance(uint32_t object_instance)
bool Analog_Value_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_ANALOG_VALUES)
return true;
@@ -54,7 +55,8 @@ bool Analog_Value_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Value_Count(void)
unsigned Analog_Value_Count(
void)
{
return MAX_ANALOG_VALUES;
}
@@ -62,7 +64,8 @@ unsigned Analog_Value_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Value_Index_To_Instance(unsigned index)
uint32_t Analog_Value_Index_To_Instance(
unsigned index)
{
return index;
}
@@ -70,18 +73,20 @@ uint32_t Analog_Value_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
unsigned Analog_Value_Instance_To_Index(
uint32_t object_instance)
{
return object_instance;
}
/* note: the object name must be unique within this device */
char *Analog_Value_Name(uint32_t object_instance)
char *Analog_Value_Name(
uint32_t object_instance)
{
static char text_string[5] = "AV-0"; /* okay for single thread */
static char text_string[5] = "AV-0"; /* okay for single thread */
if (object_instance < MAX_ANALOG_VALUES) {
text_string[3] = '0' + (uint8_t)object_instance;
text_string[3] = '0' + (uint8_t) object_instance;
return text_string;
}
@@ -89,65 +94,74 @@ char *Analog_Value_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned object_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
object_index = Analog_Value_Instance_To_Index(object_instance);
apdu_len = encode_application_real(&apdu[0], Present_Value[object_index]);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
object_index = Analog_Value_Instance_To_Index(object_instance);
apdu_len =
encode_application_real(&apdu[0], Present_Value[object_index]);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -166,22 +180,21 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
object_index =
Analog_Value_Instance_To_Index(wp_data->
object_instance);
Present_Value[object_index] = value.type.Real;
status = true;
} else {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Present_Value[object_index] = value.type.Real;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -192,7 +205,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testAnalog_Value(Test * pTest)
void testAnalog_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -207,8 +221,7 @@ void testAnalog_Value(Test * pTest)
len = Analog_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -221,7 +234,8 @@ void testAnalog_Value(Test * pTest)
}
#ifdef TEST_ANALOG_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -238,5 +252,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
+1 -1
View File
@@ -15,4 +15,4 @@
#define BITMASK_FLIP(x,y) ((x) ^= (y))
#define BITMASK_CHECK(x,y) ((x) & (y))
#endif
#endif
+261 -244
View File
@@ -53,7 +53,8 @@ static uint32_t Object_Instance_Number = 260001;
static char Object_Name[32] = "ATmega168 Device";
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
void Device_Init(void)
void Device_Init(
void)
{
/* Reinitialize_State = REINITIALIZED_STATE_IDLE; */
/* dcc_set_status_duration(COMMUNICATION_ENABLE, 0); */
@@ -65,14 +66,16 @@ void Device_Init(void)
}
/* methods to manipulate the data */
uint32_t Device_Object_Instance_Number(void)
uint32_t Device_Object_Instance_Number(
void)
{
return Object_Instance_Number;
}
bool Device_Set_Object_Instance_Number(uint32_t object_id)
bool Device_Set_Object_Instance_Number(
uint32_t object_id)
{
bool status = true; /* return value */
bool status = true; /* return value */
if (object_id <= BACNET_MAX_INSTANCE) {
Object_Instance_Number = object_id;
@@ -88,21 +91,24 @@ bool Device_Set_Object_Instance_Number(uint32_t object_id)
return status;
}
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
bool Device_Valid_Object_Instance_Number(
uint32_t object_id)
{
/* BACnet allows for a wildcard instance number */
return ((Object_Instance_Number == object_id) ||
(object_id == BACNET_MAX_INSTANCE));
}
uint16_t Device_Vendor_Identifier(void)
uint16_t Device_Vendor_Identifier(
void)
{
return BACNET_VENDOR_ID;
}
unsigned Device_Object_List_Count(void)
unsigned Device_Object_List_Count(
void)
{
unsigned count = 1; /* at least 1 for device object */
unsigned count = 1; /* at least 1 for device object */
/* FIXME: add objects as needed */
#if 0
@@ -115,8 +121,10 @@ unsigned Device_Object_List_Count(void)
return count;
}
bool Device_Object_List_Identifier(unsigned array_index,
int *object_type, uint32_t * instance)
bool Device_Object_List_Identifier(
unsigned array_index,
int *object_type,
uint32_t * instance)
{
bool status = false;
unsigned object_index = 0;
@@ -185,18 +193,20 @@ bool Device_Object_List_Identifier(unsigned array_index,
}
}
#endif
return status;
}
/* return the length of the apdu encoded or -1 for error */
int Device_Encode_Property_APDU(uint8_t * apdu,
int Device_Encode_Property_APDU(
uint8_t * apdu,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned i = 0;
@@ -206,168 +216,175 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
/* FIXME: change the hardcoded names to suit your application */
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, Object_Name);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_SYSTEM_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0], System_Status);
break;
case PROP_VENDOR_NAME:
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
characterstring_init_ansi(&char_string, "GNU Demo");
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
characterstring_init_ansi(&char_string, "1.0");
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_PROTOCOL_VERSION:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_REVISION:
apdu_len = encode_application_unsigned(&apdu[0], 5);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
/* must have the bit string as big as it can be */
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, Object_Name);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_SYSTEM_STATUS:
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
break;
case PROP_VENDOR_NAME:
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
characterstring_init_ansi(&char_string, "GNU Demo");
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
characterstring_init_ansi(&char_string, "1.0");
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_PROTOCOL_VERSION:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_REVISION:
apdu_len = encode_application_unsigned(&apdu[0], 5);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
/* must have the bit string as big as it can be */
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
#if 0
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
#endif
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
*error_code = ERROR_CODE_OTHER;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_OTHER;
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
break;
}
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0],
MAX_APDU);
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
SEGMENTATION_NONE);
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_application_unsigned(&apdu[0], 60000);
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_application_unsigned(&apdu[0], 0);
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], 0);
break;
case PROP_MAX_INFO_FRAMES:
apdu_len =
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
break;
case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master());
break;
case 9600:
apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
SEGMENTATION_NONE);
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_application_unsigned(&apdu[0], 60000);
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len = encode_application_unsigned(&apdu[0], 0);
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len = encode_application_unsigned(&apdu[0], 0);
break;
case PROP_MAX_INFO_FRAMES:
apdu_len =
encode_application_unsigned(&apdu[0],
dlmstp_max_info_frames());
break;
case PROP_MAX_MASTER:
apdu_len =
encode_application_unsigned(&apdu[0], dlmstp_max_master());
break;
case 9600:
apdu_len =
encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
#if 0
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
int len = 0;
@@ -384,98 +401,98 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
File diff suppressed because it is too large Load Diff
+23 -30
View File
@@ -64,24 +64,18 @@ int Encode_Property_APDU(
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
/* handle each object type */
switch(object_type) {
switch (object_type) {
case OBJECT_DEVICE:
if (Device_Valid_Object_Instance_Number(object_instance)) {
apdu_len = Device_Encode_Property_APDU(
&apdu[0],
property,
array_index,
error_class, error_code);
apdu_len = Device_Encode_Property_APDU(&apdu[0],
property, array_index, error_class, error_code);
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(object_instance)) {
apdu_len = Analog_Value_Encode_Property_APDU(
&apdu[0],
apdu_len = Analog_Value_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
default:
@@ -93,9 +87,11 @@ int Encode_Property_APDU(
return apdu_len;
}
void handler_read_property(uint8_t * service_request,
void handler_read_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
@@ -125,13 +121,10 @@ void handler_read_property(uint8_t * service_request,
} else {
/* most cases will be error */
error = true;
len = Encode_Property_APDU(
&Temp_Buf[0],
len = Encode_Property_APDU(&Temp_Buf[0],
data.object_type,
data.object_instance,
data.object_property,
data.array_index,
&error_class, &error_code);
data.object_property, data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
@@ -145,18 +138,18 @@ void handler_read_property(uint8_t * service_request,
}
if (error) {
switch (len) {
/* BACnet APDU too small to fit data, so proper response is Abort */
case -2:
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
break;
case -1:
default:
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
break;
/* BACnet APDU too small to fit data, so proper response is Abort */
case -2:
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
break;
case -1:
default:
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
break;
}
}
pdu_len += len;
+5 -4
View File
@@ -39,8 +39,10 @@
bool Send_I_Am = true;
void handler_who_is(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_who_is(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
int32_t low_limit = 0;
@@ -55,8 +57,7 @@ void handler_who_is(uint8_t * service_request,
} else if (len != -1) {
/* is my device id within the limits? */
target_device = Device_Object_Instance_Number();
if (((target_device >= low_limit) &&
(target_device <= high_limit))
if (((target_device >= low_limit) && (target_device <= high_limit))
||
/* BACnet wildcard is the max instance number - everyone responds */
((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) &&
+60 -59
View File
@@ -48,9 +48,11 @@
/* too big to reside on stack frame for PIC */
static BACNET_WRITE_PROPERTY_DATA wp_data;
void handler_write_property(uint8_t * service_request,
void handler_write_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
@@ -61,8 +63,7 @@ void handler_write_property(uint8_t * service_request,
BACNET_ADDRESS my_address;
/* decode the service request only */
len = wp_decode_service_request(service_request,
service_len, &wp_data);
len = wp_decode_service_request(service_request, service_len, &wp_data);
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
@@ -79,66 +80,66 @@ void handler_write_property(uint8_t * service_request,
} else {
switch (wp_data.object_type) {
#if 0
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
#endif
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
break;
}
}
pdu_len += len;
+1 -1
View File
@@ -26,7 +26,7 @@
#define HARDWARE_H
/* The processor clock frequency */
#define F_CPU (7372800)
#define F_CPU (7372800)
#include <avr/io.h>
#include <avr/interrupt.h>
+38 -30
View File
@@ -39,11 +39,14 @@
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
/* dummy function */
bool dcc_communication_enabled(void) {
bool dcc_communication_enabled(
void)
{
return true;
}
void init(void)
void init(
void)
{
/* Initialize the Clock Prescaler for ATmega48/88/168 */
/* The default CLKPSx bits are factory set to 0011 */
@@ -51,17 +54,17 @@ void init(void)
CLKPR = _BV(CLKPCE);
/* CLKPS3 CLKPS2 CLKPS1 CLKPS0 Clock Division Factor
------ ------ ------ ------ ---------------------
0 0 0 0 1
0 0 0 1 2
0 0 1 0 4
0 0 1 1 8
0 1 0 0 16
0 1 0 1 32
0 1 1 0 64
0 1 1 1 128
1 0 0 0 256
1 x x x Reserved
*/
0 0 0 0 1
0 0 0 1 2
0 0 1 0 4
0 0 1 1 8
0 1 0 0 16
0 1 0 1 32
0 1 1 0 64
0 1 1 1 128
1 0 0 0 256
1 x x x Reserved
*/
/* Set the CLKPS3..0 bits to Prescaler of 1 */
CLKPR = 0;
/* Initialize I/O ports */
@@ -75,7 +78,7 @@ void init(void)
PORTD = 0;
/* Configure the watchdog timer - Disabled for testing */
BIT_CLEAR(MCUSR,WDRF);
BIT_CLEAR(MCUSR, WDRF);
WDTCSR = 0;
/* Configure USART */
@@ -85,11 +88,11 @@ void init(void)
Timer_Initialize();
/* Set the LED ports OFF */
BIT_SET(PORTD,PD4);
BIT_SET(PORTD,PD5);
BIT_SET(PORTD, PD4);
BIT_SET(PORTD, PD5);
/* Configure the LED ports as outputs */
BIT_SET(DDRD,DDD4);
BIT_SET(DDRD,DDD5);
BIT_SET(DDRD, DDD4);
BIT_SET(DDRD, DDD5);
/* Enable global interrupts */
sei();
@@ -97,23 +100,26 @@ void init(void)
static uint8_t NPDU_Timer;
static void NDPU_Timers(void)
static void NDPU_Timers(
void)
{
if (NPDU_Timer) {
NPDU_Timer--;
if (NPDU_Timer == 0) {
BIT_SET(PORTD,PD5);
BIT_SET(PORTD, PD5);
}
}
}
static void NPDU_LED_On(void)
static void NPDU_LED_On(
void)
{
BIT_CLEAR(PORTD,PD5);
BIT_CLEAR(PORTD, PD5);
NPDU_Timer = 20;
}
void task_milliseconds(void)
void task_milliseconds(
void)
{
while (Timer_Milliseconds) {
Timer_Milliseconds--;
@@ -125,31 +131,33 @@ void task_milliseconds(void)
static uint8_t Address_Switch;
void input_switch_read(void)
void input_switch_read(
void)
{
uint8_t value;
static uint8_t old_value = 0;
value = BITMASK_CHECK(PINC,0x0F) | (BITMASK_CHECK(PINB,0x07)<<4);
value = BITMASK_CHECK(PINC, 0x0F) | (BITMASK_CHECK(PINB, 0x07) << 4);
if (value != old_value) {
old_value = value;
} else {
if (old_value != Address_Switch) {
Address_Switch = old_value;
Address_Switch = old_value;
#if defined(BACDL_MSTP)
dlmstp_set_mac_address(Address_Switch);
dlmstp_set_mac_address(Address_Switch);
#endif
Device_Set_Object_Instance_Number(86000 + Address_Switch);
Device_Set_Object_Instance_Number(86000 + Address_Switch);
}
}
}
static uint8_t PDUBuffer[MAX_MPDU];
int main(void)
int main(
void)
{
uint16_t pdu_len = 0;
BACNET_ADDRESS src; /* source address */
init();
#if defined(BACDL_MSTP)
RS485_Set_Baud_Rate(38400);
+63 -53
View File
@@ -70,10 +70,11 @@ static uint32_t RS485_Baud = 9600;
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize(void)
void RS485_Initialize(
void)
{
/* enable Transmit and Receive */
UCSR0B = _BV(TXEN0) | _BV(RXEN0);
UCSR0B = _BV(TXEN0) | _BV(RXEN0);
/* Set USART Control and Status Register n C */
/* Asynchronous USART 8-bit data, No parity, 1 stop */
@@ -84,16 +85,16 @@ void RS485_Initialize(void)
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
/* Clear Power Reduction USART0 */
BIT_CLEAR(PRR,PRUSART0);
BIT_CLEAR(PRR, PRUSART0);
/* Use port PD2 for RTS - enable and disable of Transceiver Tx/Rx */
/* Set port bit as Output - initially receiving */
BIT_CLEAR(PORTD,PD2);
BIT_SET(DDRD,DDD2);
BIT_CLEAR(PORTD, PD2);
BIT_SET(DDRD, DDD2);
/* Configure Transmit and Receive LEDs - initially off */
BIT_SET(PORTD,PD6);
BIT_SET(PORTD,PD7);
BIT_SET(DDRD,DDD6);
BIT_SET(DDRD,DDD7);
BIT_SET(PORTD, PD6);
BIT_SET(PORTD, PD7);
BIT_SET(DDRD, DDD6);
BIT_SET(DDRD, DDD7);
return;
}
@@ -104,7 +105,8 @@ void RS485_Initialize(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
uint32_t RS485_Get_Baud_Rate(
void)
{
return RS485_Baud;
}
@@ -115,7 +117,8 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_Set_Baud_Rate(uint32_t baud)
bool RS485_Set_Baud_Rate(
uint32_t baud)
{
bool valid = true;
@@ -128,7 +131,7 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
case 115200:
RS485_Baud = baud;
/* 2x speed mode */
BIT_SET(UCSR0A,U2X0);
BIT_SET(UCSR0A, U2X0);
/* configure baud rate */
UBRR0 = (F_CPU / (8UL * RS485_Baud)) - 1;
/* FIXME: store the baud rate */
@@ -147,14 +150,15 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Turnaround_Delay(void)
void RS485_Turnaround_Delay(
void)
{
uint16_t turnaround_time;
/* delay after reception before trasmitting - per MS/TP spec */
/* wait a minimum 40 bit times since reception */
/* at least 1 ms for errors: rounding, clock tick */
turnaround_time = 1 + ((Tturnaround*1000UL)/RS485_Baud);
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud);
while (Timer_Silence() < turnaround_time) {
/* do nothing - wait for timer to increment */
};
@@ -166,18 +170,19 @@ void RS485_Turnaround_Delay(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Transmitter_Enable(bool enable)
void RS485_Transmitter_Enable(
bool enable)
{
if (enable) {
BIT_SET(PORTD,PD2);
BIT_SET(PORTD, PD2);
} else {
#if Tpostdrive1
_delay_us(Tpostdrive1/RS485_Baud);
#endif
#if Tpostdrive2
_delay_us(Tpostdrive2/RS485_Baud);
#endif
BIT_CLEAR(PORTD,PD2);
#if Tpostdrive1
_delay_us(Tpostdrive1 / RS485_Baud);
#endif
#if Tpostdrive2
_delay_us(Tpostdrive2 / RS485_Baud);
#endif
BIT_CLEAR(PORTD, PD2);
}
}
@@ -187,18 +192,19 @@ void RS485_Transmitter_Enable(bool enable)
* ALGORITHM: none
* NOTES: expected to be called once a millisecond
*****************************************************************************/
void RS485_LED_Timers(void)
void RS485_LED_Timers(
void)
{
if (LED1_Off_Timer) {
LED1_Off_Timer--;
if (LED1_Off_Timer == 0) {
BIT_SET(PORTD,PD6);
BIT_SET(PORTD, PD6);
}
}
if (LED3_Off_Timer) {
LED3_Off_Timer--;
if (LED3_Off_Timer == 0) {
BIT_SET(PORTD,PD7);
BIT_SET(PORTD, PD7);
}
}
}
@@ -209,9 +215,10 @@ void RS485_LED_Timers(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
static void RS485_LED1_On(void)
static void RS485_LED1_On(
void)
{
BIT_CLEAR(PORTD,PD6);
BIT_CLEAR(PORTD, PD6);
LED1_Off_Timer = 20;
}
@@ -221,9 +228,10 @@ static void RS485_LED1_On(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
static void RS485_LED3_On(void)
static void RS485_LED3_On(
void)
{
BIT_CLEAR(PORTD,PD7);
BIT_CLEAR(PORTD, PD7);
LED3_Off_Timer = 20;
}
@@ -234,27 +242,27 @@ static void RS485_LED3_On(void)
* NOTES: none
*****************************************************************************/
void RS485_Send_Data(
uint8_t * buffer, /* data to send */
uint16_t nbytes) /* number of bytes of data */
{
uint8_t * buffer, /* data to send */
uint16_t nbytes)
{ /* number of bytes of data */
RS485_LED3_On();
while (nbytes) {
while (!BIT_CHECK(UCSR0A,UDRE0)) {
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
UDR0 = *buffer;
buffer++;
nbytes--;
}
while (!BIT_CHECK(UCSR0A,UDRE0)) {
while (!BIT_CHECK(UCSR0A, UDRE0)) {
/* do nothing - wait until Tx buffer is empty */
}
/* is the frame sent? */
while (!BIT_CHECK(UCSR0A,TXC0)) {
while (!BIT_CHECK(UCSR0A, TXC0)) {
/* do nothing - wait until the entire frame in the
Transmit Shift Register has been shifted out */
}
BIT_CLEAR(UCSR0A,TXC0);
BIT_CLEAR(UCSR0A, TXC0);
/* per MSTP spec, sort of */
Timer_Silence_Reset();
}
@@ -266,31 +274,32 @@ void RS485_Send_Data(
* ALGORITHM: autobaud - if there are a lot of errors, switch baud rate
* NOTES: Clears any error flags.
*****************************************************************************/
bool RS485_ReceiveError(void)
bool RS485_ReceiveError(
void)
{
bool ReceiveError = false;
uint8_t dummy_data;
/* check for framing error */
#if 0
if (BIT_CHECK(UCSR0A,FE0)) {
#if 0
if (BIT_CHECK(UCSR0A, FE0)) {
/* FIXME: how do I clear the error flags? */
BITMASK_CLEAR(UCSR0A,(_BV(FE0) | _BV(DOR0) | _BV(UPE0)));
BITMASK_CLEAR(UCSR0A, (_BV(FE0) | _BV(DOR0) | _BV(UPE0)));
ReceiveError = true;
}
#endif
#endif
/* check for overrun error */
if (BIT_CHECK(UCSR0A,DOR0)) {
if (BIT_CHECK(UCSR0A, DOR0)) {
/* flush the receive buffer */
do {
dummy_data = UDR0;
} while (BIT_CHECK(UCSR0A,RXC0));
} while (BIT_CHECK(UCSR0A, RXC0));
ReceiveError = true;
}
if (ReceiveError) {
RS485_LED1_On();
}
return ReceiveError;
}
@@ -300,12 +309,13 @@ bool RS485_ReceiveError(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_DataAvailable(uint8_t *data)
bool RS485_DataAvailable(
uint8_t * data)
{
bool DataAvailable = false;
/* check for data */
if (BIT_CHECK(UCSR0A,RXC0)) {
if (BIT_CHECK(UCSR0A, RXC0)) {
*data = UDR0;
DataAvailable = true;
RS485_LED1_On();
@@ -315,7 +325,8 @@ bool RS485_DataAvailable(uint8_t *data)
}
#ifdef TEST_RS485
int main(void)
int main(
void)
{
unsigned i = 0;
uint8_t DataRegister;
@@ -325,11 +336,10 @@ int main(void)
/* receive task */
for (;;) {
if (RS485_ReceiveError()) {
fprintf(stderr,"ERROR ");
fprintf(stderr, "ERROR ");
} else if (RS485_DataAvailable(&DataRegister)) {
fprintf(stderr,"%02X ",DataRegister);
fprintf(stderr, "%02X ", DataRegister);
}
}
}
#endif /* TEST_RS485 */
#endif /* TEST_RS485 */
+18 -10
View File
@@ -40,26 +40,34 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void RS485_Initialize(void);
void RS485_Initialize(
void);
void RS485_Transmitter_Enable(bool enable);
void RS485_Transmitter_Enable(
bool enable);
void RS485_Send_Data(
uint8_t * buffer, /* data to send */
uint16_t nbytes); /* number of bytes of data */
bool RS485_ReceiveError(void);
bool RS485_DataAvailable(uint8_t *data);
bool RS485_ReceiveError(
void);
bool RS485_DataAvailable(
uint8_t * data);
void RS485_Turnaround_Delay(void);
uint32_t RS485_Get_Baud_Rate(void);
bool RS485_Set_Baud_Rate(uint32_t baud);
void RS485_Turnaround_Delay(
void);
uint32_t RS485_Get_Baud_Rate(
void);
bool RS485_Set_Baud_Rate(
uint32_t baud);
void RS485_LED_Timers(void);
void RS485_LED_Timers(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+19 -16
View File
@@ -41,30 +41,31 @@ volatile uint8_t Timer_Milliseconds = 0;
static volatile uint16_t SilenceTime;
/* Configure the Timer */
void Timer_Initialize(void)
void Timer_Initialize(
void)
{
/* Normal Operation */
TCCR1A = 0;
/* CSn2 CSn1 CSn0 Description
---- ---- ---- -----------
0 0 0 No Clock Source
0 0 1 No prescaling
0 1 0 CLKio/8
0 1 1 CLKio/64
1 0 0 CLKio/256
1 0 1 CLKio/1024
1 1 0 Falling Edge of T0 (external)
1 1 1 Rising Edge of T0 (external)
*/
0 0 0 No Clock Source
0 0 1 No prescaling
0 1 0 CLKio/8
0 1 1 CLKio/64
1 0 0 CLKio/256
1 0 1 CLKio/1024
1 1 0 Falling Edge of T0 (external)
1 1 1 Rising Edge of T0 (external)
*/
TCCR0B = _BV(CS01) | _BV(CS00);
/* Clear any TOV1 Flag set when the timer overflowed */
BIT_CLEAR(TIFR0,TOV0);
BIT_CLEAR(TIFR0, TOV0);
/* Initial value */
TCNT0 = TIMER_COUNT;
/* Enable the overflow interrupt */
BIT_SET(TIMSK0,TOIE0);
BIT_SET(TIMSK0, TOIE0);
/* Clear the Power Reduction Timer/Counter0 */
BIT_CLEAR(PRR,PRTIM0);
BIT_CLEAR(PRR, PRTIM0);
}
/* Timer interupt */
@@ -77,13 +78,14 @@ ISR(TIMER0_OVF_vect)
/* Overflow Flag is automatically cleared */
/* Update the global timer */
if (Timer_Milliseconds < 0xFF)
Timer_Milliseconds++;
Timer_Milliseconds++;
if (SilenceTime < 0xFFFF)
SilenceTime++;
}
/* Public access to the Silence Timer */
uint16_t Timer_Silence(void)
uint16_t Timer_Silence(
void)
{
uint16_t timer;
uint8_t sreg;
@@ -97,7 +99,8 @@ uint16_t Timer_Silence(void)
}
/* Public reset of the Silence Timer */
void Timer_Silence_Reset(void)
void Timer_Silence_Reset(
void)
{
uint8_t sreg;
+8 -6
View File
@@ -29,14 +29,16 @@ extern volatile uint8_t Timer_Milliseconds;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void Timer_Initialize(void);
uint16_t Timer_Silence(void);
void Timer_Silence_Reset(void);
void Timer_Initialize(
void);
uint16_t Timer_Silence(
void);
void Timer_Silence_Reset(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+29 -23
View File
@@ -80,12 +80,14 @@ clockp Clock Prescaler DataRate
*/
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);
@@ -94,11 +96,12 @@ void arcnet_cleanup(void)
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 */
@@ -116,8 +119,7 @@ static int arcnet_bind(char *interface_name)
/* Then follow it by: # modprobe af_packet */
if ((sock_fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ALL))) < 0) {
/* Error occured */
fprintf(stderr,
"arcnet: Error opening socket: %s\n", strerror(errno));
fprintf(stderr, "arcnet: 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"
@@ -157,7 +159,7 @@ static int arcnet_bind(char *interface_name)
}
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;
@@ -176,7 +178,8 @@ static int arcnet_bind(char *interface_name)
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);
@@ -188,11 +191,12 @@ bool arcnet_init(char *interface_name)
/* 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 */
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 */
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 };
@@ -240,19 +244,19 @@ int arcnet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
sizeof(ARCNET_Socket_Address));
/* did it get sent? */
if (bytes < 0)
fprintf(stderr, "arcnet: Error sending packet: %s\n",
strerror(errno));
fprintf(stderr, "arcnet: Error sending packet: %s\n", strerror(errno));
return bytes;
}
/* 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 */
@@ -347,7 +351,8 @@ uint16_t arcnet_receive(BACNET_ADDRESS * src, /* source address */
return pdu_len;
}
void arcnet_get_my_address(BACNET_ADDRESS * my_address)
void arcnet_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
@@ -362,15 +367,16 @@ void arcnet_get_my_address(BACNET_ADDRESS * 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;
}
+18 -14
View File
@@ -32,19 +32,21 @@
-------------------------------------------
####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 "bacdcode.h"
#include "bip.h"
#include "net.h"
bool BIP_Debug = false;
static int get_local_ifr_ioctl(char *ifname, struct ifreq *ifr,
static int get_local_ifr_ioctl(
char *ifname,
struct ifreq *ifr,
int request)
{
int fd;
int rv; /* return value */
int rv; /* return value */
strncpy(ifr->ifr_name, ifname, sizeof(ifr->ifr_name));
fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
@@ -56,12 +58,14 @@ static int get_local_ifr_ioctl(char *ifname, struct ifreq *ifr,
return rv;
}
static int get_local_address_ioctl(char *ifname,
struct in_addr *addr, int request)
static int get_local_address_ioctl(
char *ifname,
struct in_addr *addr,
int request)
{
struct ifreq ifr = { {{0}} };
struct sockaddr_in *tcpip_address;
int rv; /* return value */
int rv; /* return value */
rv = get_local_ifr_ioctl(ifname, &ifr, request);
if (rv >= 0) {
@@ -73,7 +77,8 @@ static int get_local_address_ioctl(char *ifname,
}
/* on Linux, ifname is eth0, ath0, arc0, and others. */
static void bip_set_interface(char *ifname)
static void bip_set_interface(
char *ifname)
{
struct in_addr local_address;
struct in_addr broadcast_address;
@@ -90,8 +95,7 @@ static void bip_set_interface(char *ifname)
fprintf(stderr, "IP Address: %s\n", inet_ntoa(local_address));
}
/* setup local broadcast address */
rv = get_local_address_ioctl(ifname, &broadcast_address,
SIOCGIFBRDADDR);
rv = get_local_address_ioctl(ifname, &broadcast_address, SIOCGIFBRDADDR);
if (rv < 0) {
broadcast_address.s_addr = ~0;
}
@@ -100,14 +104,14 @@ static void bip_set_interface(char *ifname)
fprintf(stderr, "IP Broadcast Address: %s\n",
inet_ntoa(broadcast_address));
fprintf(stderr, "UDP Port: 0x%04X [%hu]\n",
bip_get_port(),
bip_get_port());
bip_get_port(), bip_get_port());
}
}
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;
+153 -150
View File
@@ -63,26 +63,30 @@ static uint8_t RxBuffer[MAX_MPDU];
/* Timer that indicates line silence - and functions */
static uint16_t SilenceTime;
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
static uint16_t Timer_Silence(void)
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);
}
static void *dlmstp_milliseconds_task(void *pArg)
static void *dlmstp_milliseconds_task(
void *pArg)
{
struct timespec timeOut,remains;
struct timespec timeOut, remains;
timeOut.tv_sec = 0;
timeOut.tv_nsec = 1000000; /* 1 millisecond */
timeOut.tv_nsec = 1000000; /* 1 millisecond */
for (;;) {
nanosleep(&timeOut, &remains);
@@ -92,7 +96,8 @@ static void *dlmstp_milliseconds_task(void *pArg)
return NULL;
}
void dlmstp_reinit(void)
void dlmstp_reinit(
void)
{
/*RS485_Reinit(); */
dlmstp_set_mac_address(DEFAULT_MAC_ADDRESS);
@@ -101,22 +106,21 @@ void dlmstp_reinit(void)
}
/* returns number of bytes sent on success, zero on failure */
int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
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 */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
{ /* number of bytes of data */
DLMSTP_PACKET packet;
int bytes_sent = 0;
ssize_t rc = 0;
if (pdu_len) {
if (npdu_data->data_expecting_reply) {
packet.frame_type =
FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
packet.frame_type = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
} else {
packet.frame_type =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
packet.frame_type = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
}
packet.pdu_len = pdu_len;
memmove(&packet.pdu[0], &pdu[0], pdu_len);
@@ -132,11 +136,11 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
/* copy the packet if one is received.
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 */
unsigned timeout) /* milliseconds to wait for a packet */
{
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;
int received_bytes = 0;
DLMSTP_PACKET packet;
@@ -161,10 +165,7 @@ uint16_t dlmstp_receive(
max = Receive_Client_SockFD;
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
received_bytes = read(
Receive_Client_SockFD,
&packet,
sizeof(packet));
received_bytes = read(Receive_Client_SockFD, &packet, sizeof(packet));
} else {
return 0;
}
@@ -198,7 +199,8 @@ uint16_t dlmstp_receive(
return pdu_len;
}
static void *dlmstp_fsm_receive_task(void *pArg)
static void *dlmstp_fsm_receive_task(
void *pArg)
{
bool received_frame = false;
@@ -221,12 +223,13 @@ static void *dlmstp_fsm_receive_task(void *pArg)
return NULL;
}
static void *dlmstp_fsm_master_task(void *pArg)
static void *dlmstp_fsm_master_task(
void *pArg)
{
struct timespec timeOut,remains;
struct timespec timeOut, remains;
timeOut.tv_sec = 0;
timeOut.tv_nsec = 100000; /* .1 millisecond */
timeOut.tv_nsec = 100000; /* .1 millisecond */
for (;;) {
nanosleep(&timeOut, &remains);
@@ -241,7 +244,9 @@ static void *dlmstp_fsm_master_task(void *pArg)
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;
@@ -266,7 +271,7 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_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)
volatile struct mstp_port_struct_t *mstp_port)
{
DLMSTP_PACKET packet;
uint16_t pdu_len = mstp_port->DataLength;
@@ -276,11 +281,8 @@ uint16_t MSTP_Put_Receive(
pdu_len = sizeof(packet.pdu);
if (pdu_len) {
MSTP_Packets++;
memmove(&packet.pdu[0],
(void *) & mstp_port->InputBuffer[0],
pdu_len);
dlmstp_fill_bacnet_address(&packet.address,
mstp_port->SourceAddress);
memmove(&packet.pdu[0], (void *) &mstp_port->InputBuffer[0], pdu_len);
dlmstp_fill_bacnet_address(&packet.address, mstp_port->SourceAddress);
packet.pdu_len = pdu_len;
/* ready is not used in this scheme */
packet.ready = true;
@@ -293,10 +295,10 @@ uint16_t MSTP_Put_Receive(
/* for the MS/TP state machine to use for getting data to send */
/* Return: amount of PDU data */
int dlmstp_get_transmit_packet(
DLMSTP_PACKET *packet,
unsigned timeout) /* milliseconds to wait for a packet */
{
int received_bytes = 0; /* return value */
DLMSTP_PACKET * packet,
unsigned timeout)
{ /* milliseconds to wait for a packet */
int received_bytes = 0; /* return value */
struct timeval select_timeout;
fd_set read_fds;
int max = 0;
@@ -318,10 +320,8 @@ int dlmstp_get_transmit_packet(
max = Transmit_Client_SockFD;
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) {
received_bytes = read(
Transmit_Client_SockFD,
packet,
sizeof(DLMSTP_PACKET));
received_bytes = read(Transmit_Client_SockFD,
packet, sizeof(DLMSTP_PACKET));
} else {
return 0;
}
@@ -347,10 +347,10 @@ int dlmstp_get_transmit_packet(
/* 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 */
{
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 */
int received_bytes = 0;
DLMSTP_PACKET packet;
uint8_t destination = 0; /* destination address */
@@ -368,25 +368,21 @@ uint16_t MSTP_Get_Send(
return 0;
}
/* convert the PDU into the MSTP Frame */
pdu_len = MSTP_Create_Frame(
&mstp_port->OutputBuffer[0], /* <-- loading this */
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
mstp_port->OutputBufferSize,
packet.frame_type,
destination,
mstp_port->This_Station,
&packet.pdu[0],
packet.pdu_len);
destination, mstp_port->This_Station, &packet.pdu[0], packet.pdu_len);
return pdu_len;
}
bool dlmstp_compare_data_expecting_reply(
uint8_t *request_pdu,
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,
BACNET_ADDRESS *dest_address)
BACNET_ADDRESS * dest_address)
{
uint16_t offset;
/* One way to check the message is to compare NPDU
@@ -414,12 +410,12 @@ bool dlmstp_compare_data_expecting_reply(
if (request.pdu_type != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) {
return false;
}
request.invoke_id = request_pdu[offset+2];
request.invoke_id = request_pdu[offset + 2];
/* segmented message? */
if (request_pdu[offset] & BIT3)
request.service_choice = request_pdu[offset+5];
request.service_choice = request_pdu[offset + 5];
else
request.service_choice = request_pdu[offset+3];
request.service_choice = request_pdu[offset + 3];
/* decode the reply data */
bacnet_address_copy(&reply.address, dest_address);
offset = npdu_decode(&reply_pdu[0],
@@ -432,32 +428,32 @@ bool dlmstp_compare_data_expecting_reply(
reply.pdu_type = reply_pdu[offset] & 0xF0;
switch (reply.pdu_type) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
reply.invoke_id = reply_pdu[offset+2];
reply.invoke_id = reply_pdu[offset + 2];
/* segmented message? */
if (reply_pdu[offset] & BIT3)
reply.service_choice = reply_pdu[offset+5];
reply.service_choice = reply_pdu[offset + 5];
else
reply.service_choice = reply_pdu[offset+3];
reply.service_choice = reply_pdu[offset + 3];
break;
case PDU_TYPE_SIMPLE_ACK:
reply.invoke_id = reply_pdu[offset+1];
reply.service_choice = reply_pdu[offset+2];
reply.invoke_id = reply_pdu[offset + 1];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_COMPLEX_ACK:
reply.invoke_id = reply_pdu[offset+1];
reply.invoke_id = reply_pdu[offset + 1];
/* segmented message? */
if (reply_pdu[offset] & BIT3)
reply.service_choice = reply_pdu[offset+4];
reply.service_choice = reply_pdu[offset + 4];
else
reply.service_choice = reply_pdu[offset+2];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_ERROR:
reply.invoke_id = reply_pdu[offset+1];
reply.service_choice = reply_pdu[offset+2];
reply.invoke_id = reply_pdu[offset + 1];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_REJECT:
case PDU_TYPE_ABORT:
reply.invoke_id = reply_pdu[offset+1];
reply.invoke_id = reply_pdu[offset + 1];
break;
default:
return false;
@@ -490,12 +486,12 @@ bool dlmstp_compare_data_expecting_reply(
}
uint16_t MSTP_Get_Reply(
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 */
int received_bytes = 0;
DLMSTP_PACKET Transmit_Packet;
uint16_t pdu_len = 0; /* return value */
uint16_t pdu_len = 0; /* return value */
uint8_t destination = 0; /* destination address */
bool matched = false;
@@ -508,39 +504,36 @@ uint16_t MSTP_Get_Reply(
} else {
return 0;
}
if ((MAX_HEADER + Transmit_Packet.pdu_len) > MAX_MPDU) {
if ((MAX_HEADER + Transmit_Packet.pdu_len) > MAX_MPDU) {
return 0;
}
/* 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,
&Transmit_Packet.pdu[0],
Transmit_Packet.pdu_len,
&Transmit_Packet.address);
Transmit_Packet.pdu_len, &Transmit_Packet.address);
if (matched) {
/* convert the PDU into the MSTP Frame */
pdu_len = MSTP_Create_Frame(
&mstp_port->OutputBuffer[0], /* <-- loading this */
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
mstp_port->OutputBufferSize,
Transmit_Packet.frame_type,
destination,
mstp_port->This_Station,
&Transmit_Packet.pdu[0],
Transmit_Packet.pdu_len);
&Transmit_Packet.pdu[0], Transmit_Packet.pdu_len);
/* not used here, but setting it anyway */
Transmit_Packet.ready = false;
} else {
/* put it back into the queue */
(void)write(Transmit_Server_SockFD,
&Transmit_Packet, sizeof(Transmit_Packet));
(void) write(Transmit_Server_SockFD,
&Transmit_Packet, sizeof(Transmit_Packet));
}
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) {
@@ -557,7 +550,8 @@ void dlmstp_set_mac_address(uint8_t mac_address)
return;
}
uint8_t dlmstp_my_address(void)
uint8_t dlmstp_my_address(
void)
{
return MSTP_Port.This_Station;
}
@@ -569,7 +563,8 @@ uint8_t dlmstp_my_address(void)
/* 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;
@@ -583,7 +578,8 @@ void dlmstp_set_max_info_frames(uint8_t max_info_frames)
return;
}
uint8_t dlmstp_max_info_frames(void)
uint8_t dlmstp_max_info_frames(
void)
{
return MSTP_Port.Nmax_info_frames;
}
@@ -593,7 +589,8 @@ uint8_t dlmstp_max_info_frames(void)
/* 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) {
@@ -609,14 +606,16 @@ void dlmstp_set_max_master(uint8_t 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;
@@ -629,15 +628,16 @@ void dlmstp_get_my_address(BACNET_ADDRESS * 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;
}
@@ -647,84 +647,90 @@ void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest)
}
/* 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();
return RS485_Get_Baud_Rate();
}
static int create_named_server_socket (const char *filename)
static int create_named_server_socket(
const char *filename)
{
struct sockaddr_un name;
int sock;
size_t size;
/* Create the socket. */
sock = socket (PF_LOCAL, SOCK_DGRAM, 0);
sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
if (sock < 0) {
#if PRINT_ENABLED
perror ("socket");
perror("socket");
#endif
exit (EXIT_FAILURE);
exit(EXIT_FAILURE);
}
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sock, sizeof(sock));
/* Bind a name to the socket. */
name.sun_family = AF_LOCAL;
strncpy (name.sun_path, filename, sizeof (name.sun_path));
strncpy(name.sun_path, filename, sizeof(name.sun_path));
/* The size of the address is
the offset of the start of the filename,
plus its length,
plus one for the terminating null byte.
Alternatively you can just do:
size = SUN_LEN (&name);
*/
size = (offsetof (struct sockaddr_un, sun_path)
+ strlen (name.sun_path) + 1);
if (bind (sock, (struct sockaddr *) &name, size) < 0) {
the offset of the start of the filename,
plus its length,
plus one for the terminating null byte.
Alternatively you can just do:
size = SUN_LEN (&name);
*/
size = (offsetof(struct sockaddr_un,
sun_path)
+ strlen (name.sun_path) + 1);
if (bind(sock, (struct sockaddr *) &name, size) < 0) {
#if PRINT_ENABLED
perror ("bind");
perror("bind");
#endif
exit (EXIT_FAILURE);
exit(EXIT_FAILURE);
}
return sock;
}
/* used by the client */
static int connect_named_server_socket (const char *filename)
static int connect_named_server_socket(
const char *filename)
{
struct sockaddr_un name;
int sock;
size_t size;
/* Create the socket. */
sock = socket (PF_LOCAL, SOCK_DGRAM, 0);
sock = socket(PF_LOCAL, SOCK_DGRAM, 0);
if (sock < 0) {
#if PRINT_ENABLED
perror ("socket");
perror("socket");
#endif
exit (EXIT_FAILURE);
exit(EXIT_FAILURE);
}
strncpy (name.sun_path, filename, sizeof (name.sun_path));
strncpy(name.sun_path, filename, sizeof(name.sun_path));
/* The size of the address is
the offset of the start of the filename,
plus its length,
plus one for the terminating null byte.
Alternatively you can just do:
size = SUN_LEN (&name);
*/
size = (offsetof (struct sockaddr_un, sun_path)
+ strlen (name.sun_path) + 1);
the offset of the start of the filename,
plus its length,
plus one for the terminating null byte.
Alternatively you can just do:
size = SUN_LEN (&name);
*/
size = (offsetof(struct sockaddr_un,
sun_path)
+ strlen (name.sun_path) + 1);
if (connect(sock, (struct sockaddr *) &name, size) < 0) {
#if PRINT_ENABLED
perror ("client: can't connect to socket");
perror("client: can't connect to socket");
#endif
exit (EXIT_FAILURE);
exit(EXIT_FAILURE);
}
return sock;
@@ -733,7 +739,8 @@ static int connect_named_server_socket (const char *filename)
static char *dlmstp_transmit_socket_name = "/tmp/BACnet_MSTP_Tx";
static char *dlmstp_receive_socket_name = "/tmp/BACnet_MSTP_Rx";
void dlmstp_cleanup(void)
void dlmstp_cleanup(
void)
{
remove(dlmstp_transmit_socket_name);
remove(dlmstp_receive_socket_name);
@@ -741,7 +748,8 @@ void dlmstp_cleanup(void)
/* nothing to do for static buffers */
}
bool dlmstp_init(char *ifname)
bool dlmstp_init(
char *ifname)
{
int rc = 0;
pthread_t hThread;
@@ -763,7 +771,7 @@ bool dlmstp_init(char *ifname)
if (ifname) {
RS485_Set_Interface(ifname);
#if PRINT_ENABLED
fprintf(stderr,"MS/TP Interface: %s\n", ifname);
fprintf(stderr, "MS/TP Interface: %s\n", ifname);
#endif
}
RS485_Initialize();
@@ -790,12 +798,9 @@ bool dlmstp_init(char *ifname)
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
#endif
#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 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);
#endif
/* start our MilliSec task */
@@ -812,16 +817,18 @@ bool dlmstp_init(char *ifname)
static char *Network_Interface = NULL;
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
uint16_t bytes_received = 0;
BACNET_ADDRESS src; /* source address */
uint8_t pdu[MAX_APDU]; /* PDU data */
uint8_t pdu[MAX_APDU]; /* PDU data */
#if (defined(MSTP_TEST_REQUEST) && MSTP_TEST_REQUEST)
struct timespec timeOut, remains;
timeOut.tv_sec = 1;
timeOut.tv_nsec = 0; /* 1 millisecond */
timeOut.tv_nsec = 0; /* 1 millisecond */
#endif
/* argv has the "/dev/ttyS0" or some other device */
if (argc > 1) {
@@ -835,18 +842,14 @@ int main(int argc, char *argv[])
/* forever task */
for (;;) {
#if (defined(MSTP_TEST_REQUEST) && MSTP_TEST_REQUEST)
MSTP_Create_And_Send_Frame(
&MSTP_Port,
MSTP_Create_And_Send_Frame(&MSTP_Port,
FRAME_TYPE_TEST_REQUEST,
MSTP_Port.SourceAddress,
MSTP_Port.This_Station,
NULL, 0);
MSTP_Port.SourceAddress, MSTP_Port.This_Station, NULL, 0);
nanosleep(&timeOut, &remains);
#endif
bytes_received =
dlmstp_receive(&src, &pdu[0], sizeof(pdu), 10000);
bytes_received = dlmstp_receive(&src, &pdu[0], sizeof(pdu), 10000);
if (bytes_received) {
fprintf(stderr,"Received NPDU!\n");
fprintf(stderr, "Received NPDU!\n");
}
}
return 0;
+47 -34
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 "net.h"
#include "bacdef.h"
@@ -52,12 +52,14 @@ 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 */
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);
@@ -75,7 +77,8 @@ void ethernet_cleanup(void)
to EAGAIN (or EWOULDBLOCK).
Thanks to Bjorn Reese for this code.
----------------------------------------------------------------------*/
int setNonblocking(int fd)
int setNonblocking(
int fd)
{
int flags;
@@ -85,9 +88,11 @@ int setNonblocking(int fd)
}
/* 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 */
int uid = 0;
fprintf(stderr, "ethernet: opening \"%s\"\n", interface_name);
@@ -122,15 +127,13 @@ static int ethernet_bind(struct sockaddr *eth_addr, char *interface_name)
/* Clear the memory before copying */
memset(eth_addr->sa_data, '\0', sizeof(eth_addr->sa_data));
/* Strcpy the interface name into the address */
strncpy(eth_addr->sa_data, interface_name,
sizeof(eth_addr->sa_data) - 1);
strncpy(eth_addr->sa_data, interface_name, sizeof(eth_addr->sa_data) - 1);
fprintf(stderr, "ethernet: binding \"%s\"\n", eth_addr->sa_data);
/* Attempt to bind the socket to the interface */
if (bind(sock_fd, eth_addr, sizeof(struct sockaddr)) != 0) {
/* Bind problem, close socket and return */
fprintf(stderr,
"ethernet: Unable to bind 802.2 socket : %s\n",
strerror(errno));
"ethernet: Unable to bind 802.2 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"
@@ -148,11 +151,13 @@ static int ethernet_bind(struct sockaddr *eth_addr, char *interface_name)
}
/* 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);
@@ -161,14 +166,15 @@ static int get_local_hwaddr(const char *ifname, unsigned char *mac)
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);
@@ -183,12 +189,13 @@ bool ethernet_init(char *interface_name)
/* 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 */
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 */
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 */
@@ -226,9 +233,9 @@ int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
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");
@@ -253,11 +260,12 @@ int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
/* 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 */
@@ -334,7 +342,8 @@ uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
return pdu_len;
}
void ethernet_set_my_address(BACNET_ADDRESS * my_address)
void ethernet_set_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
@@ -345,7 +354,8 @@ void ethernet_set_my_address(BACNET_ADDRESS * my_address)
return;
}
void ethernet_get_my_address(BACNET_ADDRESS * my_address)
void ethernet_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
@@ -363,9 +373,10 @@ void ethernet_get_my_address(BACNET_ADDRESS * 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++) {
@@ -373,7 +384,7 @@ void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
}
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;
}
@@ -382,9 +393,11 @@ void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
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);
+29 -22
View File
@@ -50,8 +50,10 @@ bool Who_Is_Request = true;
/* buffers used for receiving */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
static void LocalIAmHandler(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
static void LocalIAmHandler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
@@ -73,7 +75,8 @@ static void LocalIAmHandler(uint8_t * service_request,
return;
}
static void Read_Properties(void)
static void Read_Properties(
void)
{
uint32_t device_id = 0;
bool status = false;
@@ -154,13 +157,12 @@ static void Read_Properties(void)
return;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* 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);
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... */
@@ -181,7 +183,8 @@ static void Init_Service_Handlers(void)
handler_atomic_read_file_ack);
}
static void print_address_cache(void)
static void print_address_cache(
void)
{
unsigned i, j;
BACNET_ADDRESS address;
@@ -202,7 +205,8 @@ static void print_address_cache(void)
}
}
static void print_tsm_stats(void)
static void print_tsm_stats(
void)
{
int idle = 0;
int total = 0;
@@ -212,7 +216,8 @@ static void print_tsm_stats(void)
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();
@@ -221,12 +226,14 @@ static void sig_handler(int signo)
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 count = 0; /* milliseconds */
unsigned count = 0; /* milliseconds */
time_t start_time;
time_t new_time = 0;
@@ -280,15 +287,15 @@ int main(int argc, char *argv[])
/* some round robin task switching */
count++;
switch (count) {
case 1:
/* used for testing, but kind of noisy on the network */
/*Read_Properties(); */
break;
case 2:
break;
default:
count = 0;
break;
case 1:
/* used for testing, but kind of noisy on the network */
/*Read_Properties(); */
break;
case 2:
break;
default:
count = 0;
break;
}
/* blink LEDs, Turn on or off outputs, etc */
+1 -1
View File
@@ -80,7 +80,7 @@
#include <net/route.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <features.h> /* for the glibc version number */
#include <features.h> /* for the glibc version number */
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
+54 -42
View File
@@ -76,7 +76,8 @@ static struct termios RS485_oldtio;
* ALGORITHM: none
* NOTES: none
*********************************************************************/
void RS485_Set_Interface(char *ifname)
void RS485_Set_Interface(
char *ifname)
{
/* note: expects a constant char, or char from the heap */
RS485_Port_Name = ifname;
@@ -88,15 +89,21 @@ void RS485_Set_Interface(char *ifname)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
uint32_t RS485_Get_Baud_Rate(
void)
{
switch (RS485_Baud) {
case B19200: return 19200;
case B38400: return 38400;
case B57600: return 57600;
case B115200: return 115200;
case B19200:
return 19200;
case B38400:
return 38400;
case B57600:
return 57600;
case B115200:
return 115200;
default:
case B9600: return 9600;
case B9600:
return 9600;
}
}
@@ -106,7 +113,8 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_Set_Baud_Rate(uint32_t baud)
bool RS485_Set_Baud_Rate(
uint32_t baud)
{
bool valid = true;
@@ -140,10 +148,10 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
/* Transmits a Frame on the wire */
void RS485_Send_Frame(
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) */
{
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) */
uint8_t turnaround_time;
uint32_t baud;
ssize_t written = 0;
@@ -163,12 +171,12 @@ void RS485_Send_Frame(
};
}
/*
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);
/* per MSTP spec, sort of */
@@ -180,18 +188,19 @@ void RS485_Send_Frame(
}
/* called by timer, interrupt(?) or other thread */
void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port)
void RS485_Check_UART_Data(
struct mstp_port_struct_t *mstp_port)
{
uint8_t buf[1];
int count;
if (mstp_port->ReceiveError == true) {
/* wait for state machine to clear this */
}
/* wait for state machine to read from the DataRegister */
else if (mstp_port->DataAvailable == false) {
/* check for data */
count = read(RS485_Handle,buf,sizeof(buf));
count = read(RS485_Handle, buf, sizeof(buf));
/* if error, */
/* ReceiveError = TRUE; */
/* return; */
@@ -203,23 +212,24 @@ void RS485_Check_UART_Data(struct mstp_port_struct_t *mstp_port)
}
}
void RS485_Cleanup(void)
void RS485_Cleanup(
void)
{
/* restore the old port settings */
tcsetattr(RS485_Handle,TCSANOW,&RS485_oldtio);
tcsetattr(RS485_Handle, TCSANOW, &RS485_oldtio);
close(RS485_Handle);
}
void RS485_Initialize(void)
void RS485_Initialize(
void)
{
struct termios newtio;
/*
Open device for reading and writing.
*/
RS485_Handle = open(RS485_Port_Name,
O_RDWR | O_NOCTTY | O_NDELAY );
Open device for reading and writing.
*/
RS485_Handle = open(RS485_Port_Name, O_RDWR | O_NOCTTY | O_NDELAY);
if (RS485_Handle < 0) {
perror(RS485_Port_Name);
exit(-1);
@@ -232,17 +242,17 @@ void RS485_Initialize(void)
fcntl(RS485_Handle, F_SETFL, 0);
#endif
/* save current serial port settings */
tcgetattr(RS485_Handle,&RS485_oldtio);
tcgetattr(RS485_Handle, &RS485_oldtio);
/* clear struct for new port settings */
bzero(&newtio, sizeof(newtio));
/*
BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
CRTSCTS : output hardware flow control (only used if the cable has
all necessary lines. See sect. 7 of Serial-HOWTO)
CS8 : 8n1 (8bit,no parity,1 stopbit)
CLOCAL : local connection, no modem contol
CREAD : enable receiving characters
*/
BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
CRTSCTS : output hardware flow control (only used if the cable has
all necessary lines. See sect. 7 of Serial-HOWTO)
CS8 : 8n1 (8bit,no parity,1 stopbit)
CLOCAL : local connection, no modem contol
CREAD : enable receiving characters
*/
newtio.c_cflag = RS485_Baud | CS8 | CLOCAL | CREAD;
/* Raw input */
newtio.c_iflag = 0;
@@ -251,18 +261,20 @@ void RS485_Initialize(void)
/* no processing */
newtio.c_lflag = 0;
/* activate the settings for the port after flushing I/O */
tcsetattr(RS485_Handle,TCSAFLUSH,&newtio);
tcsetattr(RS485_Handle, TCSAFLUSH, &newtio);
/* destructor */
atexit(RS485_Cleanup);
}
#ifdef TEST_RS485
#include <string.h>
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
uint8_t buf[8];
char *wbuf = {"BACnet!"};
size_t wlen = strlen(wbuf)+1;
char *wbuf = { "BACnet!" };
size_t wlen = strlen(wbuf) + 1;
unsigned i = 0;
size_t written = 0;
int rlen;
@@ -276,11 +288,11 @@ int main(int argc, char *argv[])
for (;;) {
written = write(RS485_Handle, wbuf, wlen);
rlen = read(RS485_Handle,buf,sizeof(buf));
rlen = read(RS485_Handle, buf, sizeof(buf));
/* print any characters received */
if (rlen > 0) {
for (i = 0; i < rlen; i++) {
fprintf(stderr,"%02X ",buf[i]);
fprintf(stderr, "%02X ", buf[i]);
}
}
}
+14 -8
View File
@@ -41,23 +41,29 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void RS485_Set_Interface(char *ifname);
void RS485_Set_Interface(
char *ifname);
void RS485_Initialize(void);
void RS485_Initialize(
void);
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
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) */
uint16_t nbytes); /* number of bytes of data (up to 501) */
void RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
uint32_t RS485_Get_Baud_Rate(void);
bool RS485_Set_Baud_Rate(uint32_t baud);
void RS485_Cleanup(void);
uint32_t RS485_Get_Baud_Rate(
void);
bool RS485_Set_Baud_Rate(
uint32_t baud);
void RS485_Cleanup(
void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+37 -35
View File
@@ -58,23 +58,27 @@ 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)
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;
struct timespec timeOut, remains;
timeOut.tv_sec = 0;
timeOut.tv_nsec = 10000000; /* 1 milliseconds */
@@ -89,35 +93,36 @@ void *milliseconds_task(void *pArg)
/* 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)
volatile struct mstp_port_struct_t * mstp_port)
{
(void)mstp_port;
(void) mstp_port;
return 0;
}
/* 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;
@@ -125,7 +130,7 @@ int timestamp_ms(void)
static long last_ticks = 0;
int rv = 0;
rv = gettimeofday(&tv,NULL);
rv = gettimeofday(&tv, NULL);
if (rv == -1)
ticks = 0;
else
@@ -144,7 +149,7 @@ static void print_received_packet(
int timestamp = 0;
timestamp = timestamp_ms();
fprintf(stderr,"%03d ",timestamp);
fprintf(stderr, "%03d ", timestamp);
/* Preamble: two octet preamble: X`55', X`FF' */
/* Frame Type: one octet */
/* Destination Address: one octet address */
@@ -161,25 +166,23 @@ static void print_received_packet(
mstp_port->DestinationAddress,
mstp_port->SourceAddress,
HI_BYTE(mstp_port->DataLength),
LO_BYTE(mstp_port->DataLength),
mstp_port->HeaderCRCActual);
LO_BYTE(mstp_port->DataLength), mstp_port->HeaderCRCActual);
if (mstp_port->DataLength) {
for (i = 0; i < mstp_port->DataLength; i++) {
fprintf(stderr,"%02X ",
mstp_port->InputBuffer[i]);
fprintf(stderr, "%02X ", mstp_port->InputBuffer[i]);
}
fprintf(stderr,
"%02X %02X ",
mstp_port->DataCRCActualMSB,
mstp_port->DataCRCActualLSB);
"%02X %02X ",
mstp_port->DataCRCActualMSB, mstp_port->DataCRCActualLSB);
}
fprintf(stderr,"%s",
mstptext_frame_type(mstp_port->FrameType));
fprintf(stderr,"\n");
fprintf(stderr, "%s", mstptext_frame_type(mstp_port->FrameType));
fprintf(stderr, "\n");
}
/* 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;
@@ -195,7 +198,7 @@ int main(int argc, char *argv[])
if (argc > 2) {
my_mac = strtol(argv[2], NULL, 0);
if (my_mac > 127)
my_mac = 127;
my_mac = 127;
}
RS485_Set_Baud_Rate(38400);
RS485_Initialize();
@@ -229,4 +232,3 @@ int main(int argc, char *argv[])
return 0;
}
+73 -62
View File
@@ -41,7 +41,8 @@ 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;
@@ -50,18 +51,21 @@ bool Analog_Input_Valid_Instance(uint32_t object_instance)
}
/* we simply have 0-n object instances. */
unsigned Analog_Input_Count(void)
unsigned Analog_Input_Count(
void)
{
return MAX_ANALOG_INPUTS;
}
/* we simply have 0-n object instances. */
uint32_t Analog_Input_Index_To_Instance(unsigned index)
uint32_t Analog_Input_Index_To_Instance(
unsigned index)
{
return index;
}
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 */
@@ -73,72 +77,78 @@ char *Analog_Input_Name(uint32_t object_instance)
return NULL;
}
static float Analog_Input_Present_Value(uint32_t object_instance)
static float Analog_Input_Present_Value(
uint32_t object_instance)
{
float value = 0.0;
if (object_instance < MAX_ANALOG_INPUTS)
value = Present_Value[object_instance];
return value;
float value = 0.0;
if (object_instance < MAX_ANALOG_INPUTS)
value = Present_Value[object_instance];
return value;
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
@@ -149,7 +159,8 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testAnalogInput(Test * pTest)
void testAnalogInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -165,8 +176,7 @@ void testAnalogInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Analog_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -179,7 +189,8 @@ void testAnalogInput(Test * pTest)
}
#ifdef TEST_ANALOG_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -196,5 +207,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
+187 -169
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_ANALOG_VALUES 4
@@ -52,7 +52,8 @@ 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;
@@ -71,7 +72,8 @@ void Analog_Value_Init(void)
/* 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)
@@ -82,7 +84,8 @@ bool Analog_Value_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Value_Count(void)
unsigned Analog_Value_Count(
void)
{
Analog_Value_Init();
return MAX_ANALOG_VALUES;
@@ -91,7 +94,8 @@ unsigned Analog_Value_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Value_Index_To_Instance(unsigned index)
uint32_t Analog_Value_Index_To_Instance(
unsigned index)
{
Analog_Value_Init();
return index;
@@ -100,7 +104,8 @@ uint32_t Analog_Value_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
unsigned Analog_Value_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_ANALOG_VALUES;
@@ -111,7 +116,8 @@ unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static float Analog_Value_Present_Value(uint32_t object_instance)
static float Analog_Value_Present_Value(
uint32_t object_instance)
{
float value = ANALOG_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -127,7 +133,8 @@ static float Analog_Value_Present_Value(uint32_t 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[32] = ""; /* okay for single thread */
@@ -140,14 +147,16 @@ char *Analog_Value_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int 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;
@@ -157,110 +166,118 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
Analog_Value_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Present_Value[object_index][i] ==
ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Present_Value[object_index][i];
len = encode_application_real(&apdu[apdu_len], real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Present_Value[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Present_Value[object_index][array_index - 1];
apdu_len = encode_application_real(&apdu[0], real_value);
state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Present_Value[object_index][i] == ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Present_Value[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Present_Value[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Present_Value[object_index][array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -281,80 +298,80 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
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 */ ) &&
(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);
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) */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
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. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(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);
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) */
status = true;
} 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
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Present_Value[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) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Present_Value[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) */
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
} else {
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -366,7 +383,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testAnalog_Value(Test * pTest)
void testAnalog_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -381,8 +399,7 @@ void testAnalog_Value(Test * pTest)
len = Analog_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -395,7 +412,8 @@ void testAnalog_Value(Test * pTest)
}
#ifdef TEST_ANALOG_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -412,5 +430,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
+81 -68
View File
@@ -37,21 +37,23 @@
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;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
}
}
}
/* 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;
@@ -60,13 +62,15 @@ bool Binary_Input_Valid_Instance(uint32_t object_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;
}
@@ -74,7 +78,8 @@ uint32_t Binary_Input_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
unsigned Binary_Input_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_INPUTS;
@@ -84,8 +89,8 @@ unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
@@ -93,13 +98,14 @@ static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
Binary_Input_Initialize();
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
value = Present_Value[index];
value = Present_Value[index];
}
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 */
@@ -113,13 +119,15 @@ char *Binary_Input_Name(uint32_t object_instance)
/* return apdu length, or -1 on error */
/* assumption - object already exists, and has been bounds checked */
int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
int Binary_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_POLARITY polarity = POLARITY_NORMAL;
@@ -129,48 +137,52 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
(void) array_index;
Binary_Input_Initialize();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
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(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
break;
case PROP_PRESENT_VALUE:
value = Binary_Input_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0],value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
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(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
break;
case PROP_PRESENT_VALUE:
value = Binary_Input_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
@@ -181,7 +193,8 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testBinaryInput(Test * pTest)
void testBinaryInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -197,8 +210,7 @@ void testBinaryInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Binary_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -211,7 +223,8 @@ void testBinaryInput(Test * pTest)
}
#ifdef TEST_BINARY_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -228,5 +241,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
+152 -137
View File
@@ -31,28 +31,30 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_BINARY_VALUES 8
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;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_VALUES; i++) {
Present_Value[i] = BINARY_INACTIVE;
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_VALUES; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
}
}
}
/* 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;
@@ -61,19 +63,22 @@ bool Binary_Value_Valid_Instance(uint32_t object_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;
@@ -83,8 +88,8 @@ unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Value_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
@@ -97,7 +102,8 @@ static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
}
/* 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 */
@@ -110,14 +116,16 @@ 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,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int 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;
@@ -128,58 +136,64 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
Binary_Value_Initialize();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
/* FIXME: figure out the polarity */
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
/* FIXME: figure out the polarity */
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -199,85 +213,85 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
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 */ ) &&
(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);
priority--;
/* NOTE: this Binary value has no priority array */
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. */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
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 */ ) &&
(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);
priority--;
/* NOTE: this Binary value has no priority array */
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. */
status = true;
} 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
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
#if 0
/* NOTE: this Binary Value has no priority array */
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_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) */
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_WRITE_ACCESS_DENIED;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
break;
#if 0
/* NOTE: this Binary Value has no priority array */
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_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) */
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
#else
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
break;
#endif
} else {
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -288,7 +302,8 @@ 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;
@@ -303,8 +318,7 @@ void testBinary_Value(Test * pTest)
len = Binary_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -317,7 +331,8 @@ void testBinary_Value(Test * pTest)
}
#ifdef TEST_BINARY_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -334,5 +349,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
+337 -299
View File
@@ -25,14 +25,14 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include <string.h> /* for memmove */
#include "bacdef.h"
#include "bacdcode.h"
#include "bacstr.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "apdu.h"
#include "device.h" /* me */
#include "device.h" /* me */
#include "dlmstp.h"
#include "rs485.h"
#include "ai.h"
@@ -53,13 +53,15 @@ static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
BACNET_REINITIALIZED_STATE_OF_DEVICE Reinitialize_State =
REINITIALIZED_STATE_IDLE;
void Device_Reinit(void)
void Device_Reinit(
void)
{
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
}
void Device_Init(void)
void Device_Init(
void)
{
Reinitialize_State = REINITIALIZED_STATE_IDLE;
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
@@ -71,14 +73,16 @@ void Device_Init(void)
}
/* methods to manipulate the data */
uint32_t Device_Object_Instance_Number(void)
uint32_t Device_Object_Instance_Number(
void)
{
return Object_Instance_Number;
}
bool Device_Set_Object_Instance_Number(uint32_t object_id)
bool Device_Set_Object_Instance_Number(
uint32_t object_id)
{
bool status = true; /* return value */
bool status = true; /* return value */
if (object_id <= BACNET_MAX_INSTANCE) {
Object_Instance_Number = object_id;
@@ -94,71 +98,83 @@ bool Device_Set_Object_Instance_Number(uint32_t object_id)
return status;
}
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
bool Device_Valid_Object_Instance_Number(
uint32_t object_id)
{
/* BACnet allows for a wildcard instance number */
return ((Object_Instance_Number == object_id) ||
(object_id == BACNET_MAX_INSTANCE));
}
BACNET_DEVICE_STATUS Device_System_Status(void)
BACNET_DEVICE_STATUS Device_System_Status(
void)
{
return System_Status;
}
void Device_Set_System_Status(BACNET_DEVICE_STATUS status)
void Device_Set_System_Status(
BACNET_DEVICE_STATUS status)
{
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 1;
}
uint8_t Device_Protocol_Revision(void)
uint8_t Device_Protocol_Revision(
void)
{
return 5;
}
/* FIXME: MAX_APDU is defined in config.ini - set it! */
uint16_t Device_Max_APDU_Length_Accepted(void)
uint16_t Device_Max_APDU_Length_Accepted(
void)
{
return MAX_APDU;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
BACNET_SEGMENTATION Device_Segmentation_Supported(
void)
{
return SEGMENTATION_NONE;
}
uint16_t Device_APDU_Timeout(void)
uint16_t Device_APDU_Timeout(
void)
{
return 60000;
}
uint8_t Device_Number_Of_APDU_Retries(void)
uint8_t Device_Number_Of_APDU_Retries(
void)
{
return 0;
}
uint8_t Device_Database_Revision(void)
uint8_t Device_Database_Revision(
void)
{
return 0;
}
/* 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 */
unsigned count = 1; /* at least 1 for device object */
/* FIXME: add objects as needed */
count += Binary_Value_Count();
@@ -171,8 +187,10 @@ unsigned Device_Object_List_Count(void)
/* Since many network clients depend on the object list */
/* for discovery, it must be consistent! */
bool Device_Object_List_Identifier(unsigned array_index,
int *object_type, uint32_t * instance)
bool Device_Object_List_Identifier(
unsigned array_index,
int *object_type,
uint32_t * instance)
{
bool status = false;
unsigned object_index = 0;
@@ -242,13 +260,15 @@ bool Device_Object_List_Identifier(unsigned 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,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned i = 0;
@@ -263,208 +283,226 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
/* FIXME: change the hardcoded names to suit your application */
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
(void) strcpypgm2ram(&string_buffer[0], "PIC18F6720 Device");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
(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());
break;
case PROP_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());
break;
case PROP_MODEL_NAME:
(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:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
(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");
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());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Protocol_Revision());
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
case PROP_OBJECT_IDENTIFIER:
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");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
(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());
break;
case PROP_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());
break;
case PROP_MODEL_NAME:
(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:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
(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");
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());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Protocol_Revision());
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
*error_code = ERROR_CODE_OTHER;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_OTHER;
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
break;
}
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0],
Device_Max_APDU_Length_Accepted());
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_application_unsigned(&apdu[0], Device_APDU_Timeout());
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Number_Of_APDU_Retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Database_Revision());
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 PROP_LOCAL_TIME:
/* FIXME: if you support time */
local_time.hour = 0;
local_time.min = 0;
local_time.sec = 0;
local_time.hundredths = 0;
apdu_len = encode_application_time(&apdu[0], &local_time);
break;
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is inverse of everybody else */
apdu_len = encode_application_signed(&apdu[0], 5 /* 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 */
apdu_len = encode_application_date(&apdu[0], &local_date);
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
/* FIXME: if you support time/date */
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case 9600:
apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0],
Device_Max_APDU_Length_Accepted());
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len =
encode_application_unsigned(&apdu[0], Device_APDU_Timeout());
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Number_Of_APDU_Retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Database_Revision());
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 PROP_LOCAL_TIME:
/* FIXME: if you support time */
local_time.hour = 0;
local_time.min = 0;
local_time.sec = 0;
local_time.hundredths = 0;
apdu_len = encode_application_time(&apdu[0], &local_time);
break;
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is inverse of everybody else */
apdu_len = encode_application_signed(&apdu[0], 5 /* 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 */
apdu_len = encode_application_date(&apdu[0], &local_date);
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
/* FIXME: if you support time/date */
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case 9600:
apdu_len =
encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
int len = 0;
@@ -481,98 +519,98 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
+49 -33
View File
@@ -49,12 +49,14 @@ volatile struct mstp_port_struct_t MSTP_Port;
#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);
@@ -62,7 +64,8 @@ void dlmstp_reinit(void)
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
}
void dlmstp_init(void)
void dlmstp_init(
void)
{
uint8_t data;
@@ -74,17 +77,17 @@ void dlmstp_init(void)
MSTP_Port.InputBuffer = &Receive_Buffer.pdu[0];
MSTP_Init(&MSTP_Port);
/* FIXME: implement your data storage */
data = 64; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAC_ADDR); */
data = 64; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAC_ADDR); */
if (data <= 127)
MSTP_Port.This_Station = data;
else
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
/* FIXME: implement your data storage */
data = 127; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_MASTER_ADDR); */
data = 127; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_MASTER_ADDR); */
if ((data <= 127) && (data >= MSTP_Port.This_Station))
MSTP_Port.Nmax_master = data;
else
@@ -100,30 +103,31 @@ void dlmstp_init(void)
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
}
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 */
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 */
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;
uint8_t destination = 0; /* destination address */
BACNET_ADDRESS src;
unsigned i = 0; /* loop counter */
unsigned i = 0; /* loop counter */
if (MSTP_Port.TxReady == false) {
if (npdu_data->data_expecting_reply)
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
else
MSTP_Port.TxFrameType =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
/* load destination MAC address */
if (dest && dest->mac_len == 1) {
@@ -148,7 +152,8 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
return bytes_sent;
}
void dlmstp_task(void)
void dlmstp_task(
void)
{
uint8_t bytes_remaining;
bool received_frame;
@@ -184,7 +189,9 @@ void dlmstp_task(void)
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;
@@ -208,17 +215,19 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_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) {
@@ -235,7 +244,8 @@ void dlmstp_set_my_address(uint8_t mac_address)
return;
}
uint8_t dlmstp_my_address(void)
uint8_t dlmstp_my_address(
void)
{
return MSTP_Port.This_Station;
}
@@ -247,7 +257,8 @@ uint8_t dlmstp_my_address(void)
/* 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;
@@ -261,7 +272,8 @@ void dlmstp_set_max_info_frames(uint8_t max_info_frames)
return;
}
unsigned dlmstp_max_info_frames(void)
unsigned dlmstp_max_info_frames(
void)
{
return MSTP_Port.Nmax_info_frames;
}
@@ -271,7 +283,8 @@ unsigned dlmstp_max_info_frames(void)
/* 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) {
@@ -287,14 +300,16 @@ void dlmstp_set_max_master(uint8_t 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;
@@ -307,15 +322,16 @@ void dlmstp_get_my_address(BACNET_ADDRESS * 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;
}
+37 -22
View File
@@ -46,10 +46,10 @@
#define MAX_MPDU (MAX_HEADER+MAX_PDU)
typedef struct dlmstp_packet {
bool ready; /* true if ready to be sent or received */
bool ready; /* true if ready to be sent or received */
BACNET_ADDRESS address; /* source address */
uint8_t frame_type; /* type of message */
unsigned pdu_len; /* packet length */
uint8_t frame_type; /* type of message */
unsigned pdu_len; /* packet length */
uint8_t pdu[MAX_MPDU]; /* packet */
} DLMSTP_PACKET;
@@ -58,18 +58,24 @@ extern uint16_t MSTP_Packets;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void dlmstp_reinit(void);
void dlmstp_init(void);
void dlmstp_cleanup(void);
void dlmstp_millisecond_timer(void);
void dlmstp_task(void);
void dlmstp_reinit(
void);
void dlmstp_init(
void);
void dlmstp_cleanup(
void);
void dlmstp_millisecond_timer(
void);
void dlmstp_task(
void);
/* returns number of bytes sent on success, negative on failure */
int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
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 */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len); /* number of bytes of data */
/* This parameter represents the value of the Max_Info_Frames property of */
@@ -79,32 +85,41 @@ extern "C" {
/* 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);
unsigned dlmstp_max_info_frames(void);
void dlmstp_set_max_info_frames(
uint8_t max_info_frames);
unsigned dlmstp_max_info_frames(
void);
/* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */
/* 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);
uint8_t dlmstp_max_master(void);
void dlmstp_set_max_master(
uint8_t max_master);
uint8_t dlmstp_max_master(
void);
/* MAC address for MS/TP */
void dlmstp_set_my_address(uint8_t my_address);
uint8_t dlmstp_my_address(void);
void dlmstp_set_my_address(
uint8_t my_address);
uint8_t dlmstp_my_address(
void);
/* BACnet address used in datalink */
void dlmstp_get_my_address(BACNET_ADDRESS * my_address);
void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
void dlmstp_get_my_address(
BACNET_ADDRESS * my_address);
void dlmstp_get_broadcast_address(
BACNET_ADDRESS * dest); /* destination address */
/* MS/TP state machine functions */
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);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+92 -90
View File
@@ -46,9 +46,11 @@
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
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;
@@ -83,98 +85,98 @@ void handler_read_property(uint8_t * service_request,
/* most cases will be error */
error = true;
switch (data.object_type) {
case OBJECT_DEVICE:
/* FIXME: probably need a length limitation sent with encode */
if (Device_Valid_Object_Instance_Number(data.object_instance)) {
len = Device_Encode_Property_APDU(&Temp_Buf[0],
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
case OBJECT_DEVICE:
/* FIXME: probably need a length limitation sent with encode */
if (Device_Valid_Object_Instance_Number(data.object_instance)) {
len = Device_Encode_Property_APDU(&Temp_Buf[0],
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(data.object_instance)) {
len = Analog_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(data.object_instance)) {
len = Analog_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(data.object_instance)) {
len = Binary_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(data.object_instance)) {
len = Binary_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Valid_Instance(data.object_instance)) {
len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Valid_Instance(data.object_instance)) {
len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(data.object_instance)) {
len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(data.object_instance)) {
len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
default:
break;
break;
default:
break;
}
if (error) {
if (len == -2) {
@@ -188,7 +190,7 @@ void handler_read_property(uint8_t * service_request,
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
}
RP_ABORT:
RP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+86 -94
View File
@@ -45,9 +45,11 @@
/* too big to reside on stack frame for PIC */
static BACNET_WRITE_PROPERTY_DATA wp_data;
void handler_write_property(uint8_t * service_request,
void handler_write_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
@@ -69,104 +71,94 @@ void handler_write_property(uint8_t * service_request,
goto WP_ABORT;
}
/* decode the service request only */
len = wp_decode_service_request(service_request,
service_len, &wp_data);
len = wp_decode_service_request(service_request, service_len, &wp_data);
/* bad decoding or something we didn't understand - send an abort */
if (len <= 0) {
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
goto WP_ABORT;
}
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for Device!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Error for Device!\n");
#endif
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error!\n");
#endif
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for BV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for BV!\n");
#endif
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for AV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for AV!\n");
#endif
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Unknown Object Error!\n");
#endif
break;
}
WP_ABORT:
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for Device!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Property Error for Device!\n");
#endif
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error!\n");
#endif
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Property Simple Ack for BV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for BV!\n");
#endif
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Property Simple Ack for AV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for AV!\n");
#endif
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Unknown Object Error!\n");
#endif
break;
}
WP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+19 -19
View File
@@ -132,8 +132,8 @@ typedef union {
uint8_t Program:1;
uint8_t Run:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Input1:1;
uint8_t Input2:1;
uint8_t Input3:1;
@@ -141,35 +141,35 @@ typedef union {
uint8_t Input5:1;
uint8_t Input6:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Input7:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Input8:1;
uint8_t Photocell:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Remote:1;
uint8_t Relay8:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Relay7:1;
uint8_t Relay6:1;
uint8_t Relay5:1;
uint8_t Relay4:1;
uint8_t Relay3:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Relay2:1;
uint8_t Relay1:1;
uint8_t Holiday:1;
@@ -268,4 +268,4 @@ extern volatile LED_REGS Blink;
extern uint8_t Piezo_Timer;
extern volatile bool DataPortLocked;
#endif /* HARDWARE_H */
#endif /* HARDWARE_H */
+34 -17
View File
@@ -31,30 +31,42 @@
/* 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}
#pragma code
#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow(void)
void InterruptVectorLow(
void)
{
/* jump to interrupt routine */
_asm goto InterruptHandlerLow _endasm}
#pragma code
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh(void)
void InterruptHandlerHigh(
void)
{
#if 0
/* check for USART Rx int */
@@ -84,7 +96,8 @@ void InterruptHandlerHigh(void)
#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)) {
@@ -168,23 +181,27 @@ void InterruptHandlerLow(void)
*/
}
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)
{
}
+33 -28
View File
@@ -25,7 +25,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include <string.h> /* for memmove */
#include <p18F6720.h>
#include <stdlib.h>
#include <string.h>
@@ -87,16 +87,16 @@
#else
#pragma config WDT = ON, WDTPS = 128
#pragma config DEBUG = OFF
#endif /* USE_ICD */
#endif /* USE_ICD */
volatile uint8_t Milliseconds = 0;
volatile uint8_t Zero_Cross_Timeout = 0;
static void BACnet_Service_Handlers_Init(void)
static void BACnet_Service_Handlers_Init(
void)
{
/* 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_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,
@@ -107,8 +107,7 @@ static void BACnet_Service_Handlers_Init(void)
handler_write_property);
#if 0
apdu_set_unconfirmed_handler
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION,
handler_timesync_utc);
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
handler_timesync);
#endif
@@ -118,7 +117,8 @@ static void BACnet_Service_Handlers_Init(void)
handler_device_communication_control);
}
void Reinitialize(void)
void Reinitialize(
void)
{
uint8_t i;
char name = 0;
@@ -126,30 +126,32 @@ void Reinitialize(void)
_asm reset _endasm return;
}
void Global_Int(enum INT_STATE state)
void Global_Int(
enum INT_STATE state)
{
static uint8_t intstate = 0;
switch (state) {
case INT_DISABLED:
intstate >>= 2;
intstate |= (INTCON & 0xC0);
break;
case INT_ENABLED:
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
intstate <<= 2;
break;
case INT_RESTORE:
INTCON |= (intstate & 0xC0);
intstate <<= 2;
break;
default:
break;
case INT_DISABLED:
intstate >>= 2;
intstate |= (INTCON & 0xC0);
break;
case INT_ENABLED:
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
intstate <<= 2;
break;
case INT_RESTORE:
INTCON |= (intstate & 0xC0);
intstate <<= 2;
break;
default:
break;
}
}
void Hardware_Initialize(void)
void Hardware_Initialize(
void)
{
/* PORTA.0 Input - Photocell PORTA.1 Output - LED Row6 PORTA.2 Output
* - LED Row5 PORTA.3 Output - LED Row4 PORTA.4 Input - Square Wave
@@ -247,7 +249,8 @@ void Hardware_Initialize(void)
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();
@@ -259,7 +262,8 @@ void Initialize_Variables(void)
Milliseconds = 0;
}
void MainTasks(void)
void MainTasks(
void)
{
static uint16_t millisecond_counter = 0;
/* Handle our millisecond counters */
@@ -274,7 +278,8 @@ void MainTasks(void)
}
}
void main(void)
void main(
void)
{
RCONbits.NOT_POR = 1;
RCONbits.NOT_RI = 1;
File diff suppressed because it is too large Load Diff
+15 -10
View File
@@ -199,7 +199,7 @@ struct mstp_port_struct_t {
/* This array is only used for APDU messages */
uint8_t TxBuffer[MAX_MPDU];
unsigned TxLength;
bool TxReady; /* true if ready to be sent or received */
bool TxReady; /* true if ready to be sent or received */
uint8_t TxFrameType; /* type of message - needed by MS/TP */
};
@@ -220,27 +220,32 @@ struct mstp_port_struct_t {
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port);
void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t
void MSTP_Init(
volatile struct mstp_port_struct_t *mstp_port);
void MSTP_Receive_Frame_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t
bool MSTP_Master_Node_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
/* returns true if line is active */
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port);
bool MSTP_Line_Active(
volatile struct mstp_port_struct_t *mstp_port);
unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */
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 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) */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+65 -56
View File
@@ -57,11 +57,12 @@ volatile uint8_t RS485_Tx_Buffer[MAX_MPDU];
* 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) */
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) */
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)
@@ -117,8 +118,8 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *
mstp_port)
uint8_t RS485_Check_UART_Data(
volatile struct mstp_port_struct_t * mstp_port)
{
/* check for data */
if (RS485_Comstat.Rx_Bytes) {
@@ -151,7 +152,8 @@ uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *
NOTES: none
*************************************************************************** */
void RS485_Interrupt_Rx(void)
void RS485_Interrupt_Rx(
void)
{
char dummy;
@@ -184,7 +186,8 @@ void RS485_Interrupt_Rx(void)
NOTES: none
*************************************************************************** */
void RS485_Interrupt_Tx(void)
void RS485_Interrupt_Tx(
void)
{
if (RS485_Comstat.Tx_Bytes) {
/* Get the data byte */
@@ -214,7 +217,8 @@ void RS485_Interrupt_Tx(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
uint32_t RS485_Get_Baud_Rate(
void)
{
return RS485_Baud_Rate;
}
@@ -225,22 +229,23 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_Set_Baud_Rate(uint32_t baud)
bool RS485_Set_Baud_Rate(
uint32_t baud)
{
bool valid = true;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
RS485_Baud_Rate = baud;
break;
default:
valid = false;
break;
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
RS485_Baud_Rate = baud;
break;
default:
valid = false;
break;
}
if (valid) {
@@ -262,7 +267,8 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize_Port(void)
void RS485_Initialize_Port(
void)
{
/* Reset USART registers to POR state */
@@ -292,35 +298,35 @@ void RS485_Initialize_Port(void)
1250000 0
*/
switch (RS485_Baud_Rate) {
case 19200:
SPBRG2 = 64;
TXSTA2bits.BRGH = 1;
break;
case 38400:
SPBRG2 = 32;
TXSTA2bits.BRGH = 1;
break;
case 57600:
SPBRG2 = 21;
TXSTA2bits.BRGH = 1;
break;
case 76800:
SPBRG2 = 3;
TXSTA2bits.BRGH = 0;
break;
case 115200:
SPBRG2 = 10;
TXSTA2bits.BRGH = 1;
break;
case 9600:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
break;
default:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
RS485_Set_Baud_Rate(9600);
break;
case 19200:
SPBRG2 = 64;
TXSTA2bits.BRGH = 1;
break;
case 38400:
SPBRG2 = 32;
TXSTA2bits.BRGH = 1;
break;
case 57600:
SPBRG2 = 21;
TXSTA2bits.BRGH = 1;
break;
case 76800:
SPBRG2 = 3;
TXSTA2bits.BRGH = 0;
break;
case 115200:
SPBRG2 = 10;
TXSTA2bits.BRGH = 1;
break;
case 9600:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
break;
default:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
RS485_Set_Baud_Rate(9600);
break;
}
/* select async mode */
TXSTA2bits.SYNC = 0;
@@ -341,14 +347,16 @@ void RS485_Initialize_Port(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Disable_Port(void)
void RS485_Disable_Port(
void)
{
RCSTA2 &= 0x4F; /* Disable the receiver */
RCSTA2 &= 0x4F; /* Disable the receiver */
TXSTA2bits.TXEN = 0; /* and transmitter */
PIE3 &= 0xCF; /* Disable both interrupts */
PIE3 &= 0xCF; /* Disable both interrupts */
}
void RS485_Reinit(void)
void RS485_Reinit(
void)
{
RS485_Set_Baud_Rate(38400);
}
@@ -359,7 +367,8 @@ void RS485_Reinit(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize(void)
void RS485_Initialize(
void)
{
/* Init the Rs485 buffers */
RS485_Comstat.RxHead = 0;
+20 -11
View File
@@ -58,27 +58,36 @@ extern uint32_t RS485_Baud_Rate;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void RS485_Reinit(void);
void RS485_Initialize(void);
void RS485_Reinit(
void);
void RS485_Initialize(
void);
void RS485_Disable(void);
void RS485_Disable(
void);
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
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) */
uint16_t nbytes); /* number of bytes of data (up to 501) */
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
uint8_t RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
void RS485_Interrupt_Rx(void);
void RS485_Interrupt_Rx(
void);
void RS485_Interrupt_Tx(void);
void RS485_Interrupt_Tx(
void);
uint32_t RS485_Get_Baud_Rate(void);
bool RS485_Set_Baud_Rate(uint32_t baud);
uint32_t RS485_Get_Baud_Rate(
void);
bool RS485_Set_Baud_Rate(
uint32_t baud);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+1 -1
View File
@@ -15,4 +15,4 @@ typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
/* typedef signed long long int64_t; */
/* typedef unsigned long long uint64_t; */
#endif /* STDINT_H */
#endif /* STDINT_H */
+29 -24
View File
@@ -32,15 +32,16 @@
-------------------------------------------
####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 "bacdcode.h"
#include "bip.h"
static int interface = SOCKET_ERROR; /* SOCKET_ERROR means no open interface */
/*-----------------------------------*/
static void Error(const char *Msg)
static void Error(
const char *Msg)
{
int Code = WSAGetLastError();
#ifdef HOST
@@ -53,7 +54,8 @@ static void Error(const char *Msg)
#ifndef HOST
/*-----------------------------------*/
void InterfaceCleanup(void)
void InterfaceCleanup(
void)
{
if (interface != SOCKET_ERROR) {
xn_interface_close(interface);
@@ -64,7 +66,8 @@ void InterfaceCleanup(void)
}
}
static void NetInitialize(void)
static void NetInitialize(
void)
/* initialize the TCP/IP stack */
{
int Result;
@@ -78,7 +81,7 @@ static void NetInitialize(void)
RTURegisterCallback(USBAX772);
RTURegisterCallback(USBKeyboard); /* support USB keyboards */
FindUSBControllers(); /* install USB host controllers */
Sleep(2000); /* give the USB stack time to enumerate devices */
Sleep(2000); /* give the USB stack time to enumerate devices */
#endif
#ifdef DHCP
@@ -129,16 +132,16 @@ static void NetInitialize(void)
#if DEVICE_ID == PRISM_PCMCIA_DEVICE || DEVICE_ID == PRISM_DEVICE
xn_wlan_setup(interface, /* iface_no: value returned by xn_interface_open_config() */
"network name", /* SSID : network name set in the access point */
"station name", /* Name : name of this node */
0, /* Channel : 0 for access points, 1..14 for ad-hoc */
0, /* KeyIndex: 0 .. 3 */
"12345", /* WEP Key : key to use (5 or 13 bytes) */
0); /* Flags : see manual and Wlanapi.h for details */
Sleep(1000); /* wireless devices need a little time before they can be used */
#endif /* WLAN device */
"network name", /* SSID : network name set in the access point */
"station name", /* Name : name of this node */
0, /* Channel : 0 for access points, 1..14 for ad-hoc */
0, /* KeyIndex: 0 .. 3 */
"12345", /* WEP Key : key to use (5 or 13 bytes) */
0); /* Flags : see manual and Wlanapi.h for details */
Sleep(1000); /* wireless devices need a little time before they can be used */
#endif /* WLAN device */
#if defined(AUTO_IP) /* use xn_autoip() to get an IP address */
#if defined(AUTO_IP) /* use xn_autoip() to get an IP address */
Result = xn_autoip(interface, MinIP, MaxIP, NetMask, TargetIP);
if (Result == SOCKET_ERROR)
Error("xn_autoip failed");
@@ -146,11 +149,10 @@ static void NetInitialize(void)
printf("Auto-assigned IP address %i.%i.%i.%i\n", TargetIP[0],
TargetIP[1], TargetIP[2], TargetIP[3]);
/* define default gateway and DNS server */
xn_rt_add(RT_DEFAULT, ip_ffaddr, DefaultGateway, 1, interface,
RT_INF);
xn_rt_add(RT_DEFAULT, ip_ffaddr, DefaultGateway, 1, interface, RT_INF);
xn_set_server_list((DWORD *) DNSServer, 1);
}
#elif defined(DHCP) /* use DHCP */
#elif defined(DHCP) /* use DHCP */
{
DHCP_param param[] = { {SUBNET_MASK, 1}
, {DNS_OP, 1}
@@ -180,7 +182,7 @@ static void NetInitialize(void)
xn_set_server_list((DWORD *) DNSServer, 1);
#endif
#else /* HOST defined, run on Windows */
#else /* HOST defined, run on Windows */
WSADATA wd;
Result = WSAStartup(0x0101, &wd);
@@ -198,7 +200,8 @@ static void NetInitialize(void)
* ALGORITHM: none
* NOTES: none
******************************************************************/
static void RTIP_To_Network_Address(BYTE * octet_address,
static void RTIP_To_Network_Address(
BYTE * octet_address,
struct in_addr *addr)
{
uint32_t ip_address = 0; /* for decoding the subnet mask */
@@ -209,7 +212,8 @@ static void RTIP_To_Network_Address(BYTE * octet_address,
return;
}
static void set_broadcast_address(uint32_t net_address)
static void set_broadcast_address(
uint32_t net_address)
{
long broadcast_address = 0;
long mask = 0;
@@ -238,15 +242,16 @@ static void set_broadcast_address(uint32_t net_address)
#endif
}
bool bip_init(char *ifname)
bool bip_init(
char *ifname)
{
int rv = 0; /* return from socket lib calls */
int rv = 0; /* return from socket lib calls */
struct sockaddr_in sin = { -1 };
int value = 1;
int sock_fd = -1;
struct in_addr my_addr;
(void)ifname;
(void) ifname;
NetInitialize();
+41 -28
View File
@@ -42,9 +42,10 @@ static uint8_t PDU_Buffer[MAX_MPDU];
/* local MS/TP port data */
static volatile struct mstp_port_struct_t MSTP_Port;
void dlmstp_init(char *ifname)
void dlmstp_init(
char *ifname)
{
(void)ifname;
(void) ifname;
/* initialize buffer */
Receive_Buffer.ready = false;
Receive_Buffer.pdu_len = 0;
@@ -53,17 +54,19 @@ void dlmstp_init(char *ifname)
MSTP_Init(&MSTP_Port, MSTP_Port.This_Station);
}
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 */
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 */
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;
uint8_t frame_type = 0;
uint8_t destination = 0; /* destination address */
@@ -74,8 +77,7 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
if (npdu_data->confirmed_message)
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
else
MSTP_Port.TxFrameType =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
/* load destination MAC address */
if (dest && dest->mac_len == 1) {
@@ -109,16 +111,18 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
}
/* called about once a millisecond */
void dlmstp_millisecond_timer(void)
void dlmstp_millisecond_timer(
void)
{
MSTP_Millisecond_Timer(&MSTP_Port);
}
/* returns the number of octets in the PDU, or zero on failure */
/* This function is expecting to be polled. */
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)
{
uint16_t pdu_len = 0;
@@ -137,8 +141,7 @@ uint16_t dlmstp_receive(BACNET_ADDRESS * src, /* source address */
}
/* see if there is a packet available */
if (Receive_Buffer.ready) {
memmove(src, &Receive_Buffer.address,
sizeof(Receive_Buffer.address));
memmove(src, &Receive_Buffer.address, sizeof(Receive_Buffer.address));
pdu_len = Receive_Buffer.pdu_len;
memmove(&pdu[0], &Receive_Buffer.pdu[0], max_pdu);
Receive_Buffer.ready = false;
@@ -147,7 +150,9 @@ uint16_t dlmstp_receive(BACNET_ADDRESS * src, /* source address */
return pdu_len;
}
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;
@@ -171,8 +176,9 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_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)
{
if (Receive_Buffer.ready) {
@@ -191,7 +197,8 @@ uint16_t dlmstp_put_receive(uint8_t src, /* source MS/TP address */
return pdu_len;
}
void dlmstp_set_my_address(uint8_t mac_address)
void dlmstp_set_my_address(
uint8_t mac_address)
{
/* FIXME: Master Nodes can only have address 1-127 */
MSTP_Port.This_Station = mac_address;
@@ -206,14 +213,16 @@ void dlmstp_set_my_address(uint8_t 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(unsigned max_info_frames)
void dlmstp_set_max_info_frames(
unsigned max_info_frames)
{
MSTP_Port.Nmax_info_frames = max_info_frames;
return;
}
unsigned dlmstp_max_info_frames(void)
unsigned dlmstp_max_info_frames(
void)
{
return MSTP_Port.Nmax_info_frames;
}
@@ -223,21 +232,24 @@ unsigned dlmstp_max_info_frames(void)
/* 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)
{
MSTP_Port.Nmax_master = 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;
@@ -250,15 +262,16 @@ void dlmstp_get_my_address(BACNET_ADDRESS * 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; /* len=0 denotes broadcast address */
dest->len = 0; /* len=0 denotes broadcast address */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
+42 -33
View File
@@ -23,10 +23,10 @@
*
*********************************************************************/
#include <stdint.h> /* for standard integer types uint8_t etc. */
#include <stdbool.h> /* for the standard bool type. */
#include <stdio.h> /* for the standard bool type. */
#include <stdlib.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> /* for the standard bool type. */
#include <stdlib.h> /* for the standard bool type. */
#include <rttarget.h>
#include <rtk32.h>
#include <clock.h>
@@ -49,12 +49,14 @@ static SOCKET Ethernet_Socket = -1;
/* used for binding 802.2 */
static struct sockaddr Ethernet_Address = { 0 };
bool ethernet_valid(void)
bool ethernet_valid(
void)
{
return (Ethernet_Socket != -1);
}
void ethernet_cleanup(void)
void ethernet_cleanup(
void)
{
if (ethernet_valid())
closesocket(Ethernet_Socket);
@@ -63,7 +65,8 @@ void ethernet_cleanup(void)
return;
}
bool ethernet_init(char *interface_name)
bool ethernet_init(
char *interface_name)
{
int value = 1;
@@ -85,12 +88,13 @@ bool ethernet_init(char *interface_name)
/* function to send a packet out the 802.2 socket */
/* returns bytes sent on success, negative number on failure */
int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
int ethernet_send(
BACNET_ADDRESS * dest, /* destination address */
BACNET_ADDRESS * src, /* source address */
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 */
int bytes = 0;
uint8_t mtu[MAX_MPDU] = { 0 };
int mtu_len = 0;
@@ -128,8 +132,7 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
return -4;
}
/* packet length */
mtu_len += encode_unsigned16(&mtu[12],
3 /*DSAP,SSAP,LLC */ + pdu_len);
mtu_len += encode_unsigned16(&mtu[12], 3 /*DSAP,SSAP,LLC */ + pdu_len);
/* Logical PDU portion */
mtu[mtu_len++] = 0x82; /* DSAP for BACnet */
mtu[mtu_len++] = 0x82; /* SSAP for BACnet */
@@ -156,12 +159,13 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
/* function to send a packet out the 802.2 socket */
/* returns bytes sent on success, negative number on failure */
int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
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 */
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 */
BACNET_ADDRESS src = { 0 }; /* source address */
for (i = 0; i < 6; i++) {
@@ -173,18 +177,19 @@ int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
/* function to send a packet out the 802.2 socket */
/* returns 1 on success, 0 on failure */
return ethernet_send(dest, /* destination address */
&src, /* source address */
npdu_data, pdu, /* any data to be sent - may be null */
pdu_len); /* number of bytes of data */
&src, /* source address */
npdu_data, pdu, /* any data to be sent - may be null */
pdu_len); /* number of bytes of data */
}
/* 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 */
@@ -212,8 +217,7 @@ uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
max = Ethernet_Socket;
if (select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0)
received_bytes =
recv(Ethernet_Socket, (char *) &buf[0], MAX_MPDU, 0);
received_bytes = recv(Ethernet_Socket, (char *) &buf[0], MAX_MPDU, 0);
else
return 0;
@@ -262,7 +266,8 @@ uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
return pdu_len;
}
void ethernet_get_my_address(BACNET_ADDRESS * my_address)
void ethernet_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
@@ -280,7 +285,8 @@ void ethernet_get_my_address(BACNET_ADDRESS * my_address)
return;
}
void ethernet_set_my_address(BACNET_ADDRESS * my_address)
void ethernet_set_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
@@ -291,9 +297,10 @@ void ethernet_set_my_address(BACNET_ADDRESS * 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++) {
@@ -301,7 +308,7 @@ void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
}
dest->mac_len = 6;
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* denotes broadcast address */
dest->len = 0; /* denotes broadcast address */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
@@ -310,9 +317,11 @@ void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
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);
+8 -7
View File
@@ -27,7 +27,8 @@
#include <rtkernel.h>
#include <windows.h>
extern void RTEmuInit(void);
extern void RTEmuInit(
void);
#ifdef _MSC_VER
#define VOIDEXPORT _declspec(dllexport) void __cdecl
@@ -36,11 +37,11 @@ extern void RTEmuInit(void);
#endif
/* DISK SYSTEM */
#ifdef DOC /* include DiskOnChip driver */
#ifdef DOC /* include DiskOnChip driver */
#include <rtfiles.h>
#define RTF_MAX_FILES 16 /* support for more open files (default is 8) */
#define RTF_BUFFERS_IN_BSS /* we do not need file I/O before the run-time */
#include <rtfdata.c> /* system is initialized */
#include <rtfdata.c> /* system is initialized */
/*#define READ_HEAD_BUFFER_SIZE 2048+4 */
@@ -89,8 +90,7 @@ RTFileSystem Console = { RT_FS_CONSOLE, 0, 0, &RTConsoleFileSystem };
RTFileSystem LPTFiles = { RT_FS_LPT_DEVICE, 0, 0, &RTLPTFileSystem };
/* logical drive Z: can be used to access the RAM drive */
RTFileSystem RAMFiles =
{ RT_FS_FILE, 1 << ('Z' - 'A'), 0, &RTRAMFileSystem };
RTFileSystem RAMFiles = { RT_FS_FILE, 1 << ('Z' - 'A'), 0, &RTRAMFileSystem };
/* logical drive A: through D: are reserved for FAT */
RTFileSystem FATFiles =
@@ -106,12 +106,13 @@ RTFileSystem *RTFileSystemList[] = {
#endif
/*-----------------------------------*/
VOIDEXPORT Init(void)
VOIDEXPORT Init(
void)
{
(void) RTSetFlags(RT_MM_VIRTUAL, 1); /* this is the better method */
(void) RTCMOSExtendHeap(); /* get as much memory as we can */
RTCMOSSetSystemTime(); /* get the right date and time */
RTEmuInit(); /* set up floating point emulation */
RTEmuInit(); /* set up floating point emulation */
/* pizza - RTHaltCPL3 appears to cause problems with file handling */
/*RTIdleHandler = (void RTTAPI *)RTHaltCPL3; // low power when idle */
/* not needed with pre-emptive */
+20 -16
View File
@@ -28,7 +28,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <conio.h> /* for kbhit */
#include <conio.h> /* for kbhit */
#include "config.h"
#include "bacdef.h"
#include "npdu.h"
@@ -45,23 +45,23 @@
#define _USER32_
#define _KERNEL32_
#include <windows.h>
#include <rttarget.h> /* for RTCMOSSetSystemTime */
#include <rtfiles.h> /* file system */
#include <rtfsys.h> /* file system */
#include <rttarget.h> /* for RTCMOSSetSystemTime */
#include <rtfiles.h> /* file system */
#include <rtfsys.h> /* file system */
#include <Rttbios.h>
#endif
#include <rtcom.h> /* serial port driver */
#include <itimer.h> /* time measurement & timer interrupt rate control */
#include <rtkeybrd.h> /* interrupt handler for the keyboard */
#include <rtcom.h> /* serial port driver */
#include <itimer.h> /* time measurement & timer interrupt rate control */
#include <rtkeybrd.h> /* interrupt handler for the keyboard */
/* buffers used for transmit and receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* 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_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
@@ -73,10 +73,11 @@ static void Init_Service_Handlers(void)
handler_write_property);
}
void millisecond_task(void)
void millisecond_task(
void)
{
Time ticks = 0; /* task cycle */
int i = 0; /* loop counter */
Time ticks = 0; /* task cycle */
int i = 0; /* loop counter */
ticks = RTKGetTime() + MilliSecsToTicks(1);
while (TRUE) {
@@ -86,11 +87,12 @@ void millisecond_task(void)
}
}
void RTOS_Initialize(void)
void RTOS_Initialize(
void)
{
/* allow OS to setup IRQ 1 by using a dummy call */
(void) kbhit();
RTKernelInit(5); /* get the kernel going */
RTKernelInit(5); /* get the kernel going */
RTKeybrdInit();
/*(void)CPUMoniInit(); /* not needed - just monitor idle task */ */
RTComInit();
@@ -128,7 +130,9 @@ void RTOS_Initialize(void)
RTKCreateTask(millisecond_task, 16, 1024 * 8, "millisec task");
}
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;
File diff suppressed because it is too large Load Diff
+17 -11
View File
@@ -201,7 +201,7 @@ struct mstp_port_struct_t {
/* This array is only used for APDU messages */
uint8_t TxBuffer[MAX_MPDU];
unsigned TxLength;
bool TxReady; /* true if ready to be sent or received */
bool TxReady; /* true if ready to be sent or received */
uint8_t TxFrameType; /* type of message - needed by MS/TP */
};
@@ -215,30 +215,36 @@ struct mstp_port_struct_t {
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port,
void MSTP_Init(
volatile struct mstp_port_struct_t *mstp_port,
uint8_t this_station_mac);
void MSTP_Millisecond_Timer(volatile struct mstp_port_struct_t
void MSTP_Millisecond_Timer(
volatile struct mstp_port_struct_t
*mstp_port);
void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t
void MSTP_Receive_Frame_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t
bool MSTP_Master_Node_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
/* returns true if line is active */
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port);
bool MSTP_Line_Active(
volatile struct mstp_port_struct_t *mstp_port);
unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */
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 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) */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+9 -9
View File
@@ -31,17 +31,17 @@
/* #define AUTO_IP // use xn_autoip() to get an IP address */
/* #define DHCP // if you enable this, you must also link library dhcpc.lib */
#if defined(AUTO_IP) /* use xn_autoip() to get an IP address */
#if defined(AUTO_IP) /* use xn_autoip() to get an IP address */
static BYTE TargetIP[] = { 0, 0, 0, 0 }; /* will be filled at run-time */
static BYTE NetMask[] = { 255, 255, 255, 0 };
static BYTE MinIP[] = { 192, 168, 0, 128 };
static BYTE MaxIP[] = { 192, 168, 0, 255 };
static BYTE DefaultGateway[] = { 192, 168, 0, 1 }; /* set to zero if not available or required */
static BYTE DNSServer[] = { 192, 168, 0, 1 }; /* ditto */
#elif defined(DHCP) /* use DHCP */
#elif defined(DHCP) /* use DHCP */
#include <dhcpcapi.h>
static BYTE TargetIP[] = { 0, 0, 0, 0 }; /* will be filled at run-time */
#else /* static IP address assignment (default) */
#else /* static IP address assignment (default) */
static BYTE TargetIP[] = { 192, 168, 0, 50 };
static BYTE NetMask[] = { 255, 255, 255, 0 };
static BYTE DefaultGateway[] = { 192, 168, 0, 1 }; /* set to zero if not available or required */
@@ -59,8 +59,8 @@ static BYTE DNSServer[] = { 192, 168, 0, 1 }; /* ditto */
/* PCI devices if you do not have a BIOS */
#define ED_IO_ADD 0x300 /* I/O address of the device */
#define ED_IRQ 5 /* IRQ of the device */
#define ED_MEM_ADD 0 /* Memory Window (only some devices) */
#define ED_IRQ 5 /* IRQ of the device */
#define ED_MEM_ADD 0 /* Memory Window (only some devices) */
/* Define function to pull in the required driver */
@@ -87,17 +87,17 @@ static BYTE DNSServer[] = { 192, 168, 0, 1 }; /* ditto */
#elif DEVICE_ID == RHINE_DEVICE
#define BIND_DRIVER xn_bind_rhine
#elif DEVICE_ID == AX172_DEVICE
#include <rtusb.h> /* must also link Rtusb.lib and UsbInit.cpp */
#include <rtusb.h> /* must also link Rtusb.lib and UsbInit.cpp */
#define BIND_DRIVER xn_bind_ax172
#elif DEVICE_ID == AX772_DEVICE
#include <rtusb.h> /* must also link Rtusb.lib and UsbInit.cpp */
#include <rtusb.h> /* must also link Rtusb.lib and UsbInit.cpp */
#define BIND_DRIVER xn_bind_ax772
#elif DEVICE_ID == PRISM_DEVICE
#include <wlanapi.h> /* must also link Wlan.lib */
#include <wlanapi.h> /* must also link Wlan.lib */
#define BIND_DRIVER xn_bind_prism
#elif DEVICE_ID == PRISM_PCMCIA_DEVICE
#include <rtpcmcia.h>
#include <wlanapi.h> /* must also link Wlan.lib */
#include <wlanapi.h> /* must also link Wlan.lib */
#define BIND_DRIVER xn_bind_prism_pcmcia
#else
#error Invalid DEVICE_ID value
+45 -36
View File
@@ -57,10 +57,13 @@ static FineTime RS485_Debug_Transmit_Timer;
#endif
#if PRINT_ENABLED_RS485
void RS485_Print_Frame(int port, FineTime timer, uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
void RS485_Print_Frame(
int port,
FineTime timer,
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
uint16_t nbytes)
{
uint16_t i; /* byte counter */
uint16_t i; /* byte counter */
unsigned long duration; /* measures the time from last output to this one */
unsigned long seconds;
unsigned long milliseconds;
@@ -79,33 +82,36 @@ void RS485_Print_Frame(int port, FineTime timer, uint8_t * buffer, /* frame
}
#endif
static void RS485_Standard_Port_Settings(long port, long *pIRQ,
static void RS485_Standard_Port_Settings(
long port,
long *pIRQ,
long *pBase)
{
switch (port) {
case COM1:
*pBase = (long) 0x3F8;
*pIRQ = 4L;
break;
case COM2:
*pBase = (long) 0x2F8;
*pIRQ = 3L;
break;
case COM3:
*pBase = (long) 0x3E8;
*pIRQ = 4L;
break;
case COM4:
*pBase = (long) 0x2E8;
*pIRQ = 3L;
break;
default:
break;
case COM1:
*pBase = (long) 0x3F8;
*pIRQ = 4L;
break;
case COM2:
*pBase = (long) 0x2F8;
*pIRQ = 3L;
break;
case COM3:
*pBase = (long) 0x3E8;
*pIRQ = 4L;
break;
case COM4:
*pBase = (long) 0x2E8;
*pIRQ = 3L;
break;
default:
break;
}
}
static int TestCOMPort(int Base)
{ /* base address of UART */
static int TestCOMPort(
int Base)
{ /* base address of UART */
int i;
for (i = 0; i < 256; i++) {
@@ -117,11 +123,12 @@ static int TestCOMPort(int Base)
return TRUE;
}
static RS485_Open_Port(int port, /* COM port number - COM1 = 0 */
long baud, /* baud rate */
unsigned base, /* io base address */
static RS485_Open_Port(
int port, /* COM port number - COM1 = 0 */
long baud, /* baud rate */
unsigned base, /* io base address */
int irq)
{ /* hardware IRQ number */
{ /* hardware IRQ number */
if (!TestCOMPort(base))
return;
@@ -148,21 +155,22 @@ static RS485_Open_Port(int port, /* COM port number - COM1 = 0 */
return;
}
void RS485_Initialize(void)
void RS485_Initialize(
void)
{
#if PRINT_ENABLED_RS485
MarkTime(&RS485_Debug_Transmit_Timer);
#endif
RS485_Standard_Port_Settings(RS485_Port, &RS485_IRQ_Number,
&RS485_Base);
RS485_Standard_Port_Settings(RS485_Port, &RS485_IRQ_Number, &RS485_Base);
RS485_Open_Port(RS485_Port, RS485_Baud, RS485_Base, RS485_IRQ_Number);
}
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) */
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) */
uint16_t nbytes)
{ /* number of bytes of data (up to 501) */
bool status = true; /* return value */
{ /* number of bytes of data (up to 501) */
bool status = true; /* return value */
RS485_TRANSMIT_ENABLE(RS485_Port);
SendBlock(RS485_Port, (char *) buffer, nbytes);
@@ -184,8 +192,9 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
return;
}
void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
{ /* port specific data */
void RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port)
{ /* port specific data */
COMData com_data = 0; /* byte from COM driver */
unsigned timeout = 1; /* milliseconds to wait for a character */
static Duration ticks = 0; /* duration to wait for data */
+8 -5
View File
@@ -41,17 +41,20 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void RS485_Initialize(void);
void RS485_Initialize(
void);
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
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) */
uint16_t nbytes); /* number of bytes of data (up to 501) */
void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
void RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+1 -1
View File
@@ -16,4 +16,4 @@ typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
/* typedef signed long long int64_t; */
/* typedef unsigned long long uint64_t; */
#endif /* STDINT_H */
#endif /* STDINT_H */
+42 -36
View File
@@ -34,15 +34,16 @@
#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 "bacdcode.h"
#include "bip.h"
#include "net.h"
bool BIP_Debug = false;
/* To fill a need, we invent the gethostaddr() function. */
static long gethostaddr(void)
static long gethostaddr(
void)
{
struct hostent *host_ent;
char host_name[255];
@@ -54,16 +55,17 @@ static long gethostaddr(void)
return -1;
if (BIP_Debug) {
printf("host: %s at %u.%u.%u.%u\n", host_name,
((uint8_t*)host_ent->h_addr)[0],
((uint8_t*)host_ent->h_addr)[1],
((uint8_t*)host_ent->h_addr)[2],
((uint8_t*)host_ent->h_addr)[3]);
((uint8_t *) host_ent->h_addr)[0],
((uint8_t *) host_ent->h_addr)[1],
((uint8_t *) host_ent->h_addr)[2],
((uint8_t *) host_ent->h_addr)[3]);
}
/* note: network byte order */
return *(long *) host_ent->h_addr;
}
static void set_broadcast_address(uint32_t net_address)
static void set_broadcast_address(
uint32_t net_address)
{
#if USE_INADDR
/* Note: sometimes INADDR_BROADCAST does not let me get
@@ -91,14 +93,16 @@ static void set_broadcast_address(uint32_t net_address)
#endif
}
static void cleanup(void)
static void cleanup(
void)
{
WSACleanup();
}
/* on Windows, ifname is the dotted ip address of the interface */
void bip_set_interface(char *ifname)
void bip_set_interface(
char *ifname)
{
struct in_addr address;
@@ -117,7 +121,8 @@ void bip_set_interface(char *ifname)
}
}
static char *winsock_error_code_text(int code)
static char *winsock_error_code_text(
int code)
{
switch (code) {
case WSAEACCES:
@@ -135,7 +140,8 @@ static char *winsock_error_code_text(int code)
case WSAEWOULDBLOCK:
return "Operation would block.";
case WSAEINPROGRESS:
return "Operation now in progress. This error is returned if any Windows Sockets API function is called while a blocking function is in progress.";
return
"Operation now in progress. This error is returned if any Windows Sockets API function is called while a blocking function is in progress.";
case WSAENOTSOCK:
return "Socket operation on nonsocket.";
case WSAEDESTADDRREQ:
@@ -161,7 +167,8 @@ static char *winsock_error_code_text(int code)
case WSAEADDRNOTAVAIL:
return "Cannot assign requested address.";
case WSAENETDOWN:
return "Network is down. This error may be reported at any time if the Windows Sockets implementation detects an underlying failure.";
return
"Network is down. This error may be reported at any time if the Windows Sockets implementation detects an underlying failure.";
case WSAENETUNREACH:
return "Network is unreachable.";
case WSAENETRESET:
@@ -194,41 +201,43 @@ static char *winsock_error_code_text(int code)
return "No route to host.";
case WSASYSNOTREADY:
return "Returned by WSAStartup(), "
"indicating that the network subsystem is unusable.";
"indicating that the network subsystem is unusable.";
case WSAVERNOTSUPPORTED:
return "Returned by WSAStartup(), "
"indicating that the Windows Sockets DLL cannot support "
"this application.";
"indicating that the Windows Sockets DLL cannot support "
"this application.";
case WSANOTINITIALISED:
return "Winsock not initialized. "
"This message is returned by any function except WSAStartup(), "
"indicating that a successful WSAStartup() has not yet "
"been performed.";
"This message is returned by any function except WSAStartup(), "
"indicating that a successful WSAStartup() has not yet "
"been performed.";
case WSAEDISCON:
return "Disconnect.";
case WSAHOST_NOT_FOUND:
return "Host not found. "
"This message indicates that the key "
"(name, address, and so on) was not found.";
"This message indicates that the key "
"(name, address, and so on) was not found.";
case WSATRY_AGAIN:
return "Nonauthoritative host not found. "
"This error may suggest that the name service itself "
"is not functioning.";
"This error may suggest that the name service itself "
"is not functioning.";
case WSANO_RECOVERY:
return "Nonrecoverable error. "
"This error may suggest that the name service itself "
"is not functioning.";
"This error may suggest that the name service itself "
"is not functioning.";
case WSANO_DATA:
return "Valid name, no data record of requested type. "
"This error indicates that the key "
"(name, address, and so on) was not found.";
default: return "unknown";
"This error indicates that the key "
"(name, address, and so on) was not found.";
default:
return "unknown";
}
}
bool bip_init(char *ifname)
bool bip_init(
char *ifname)
{
int rv = 0; /* return from socket lib calls */
int rv = 0; /* return from socket lib calls */
struct sockaddr_in sin = { -1 };
int value = 1;
int sock_fd = -1;
@@ -243,8 +252,7 @@ bool bip_init(char *ifname)
if (Result != 0) {
Code = WSAGetLastError();
printf("TCP/IP stack initialization failed\n"
" error code: %i %s\n",
Code, winsock_error_code_text(Code));
" error code: %i %s\n", Code, winsock_error_code_text(Code));
exit(1);
}
atexit(cleanup);
@@ -258,8 +266,7 @@ bool bip_init(char *ifname)
if (address.s_addr == (unsigned) -1) {
Code = WSAGetLastError();
printf("Get host address failed\n"
" error code: %i %s\n",
Code, winsock_error_code_text(Code));
" error code: %i %s\n", Code, winsock_error_code_text(Code));
exit(1);
}
bip_set_addr(address.s_addr);
@@ -276,8 +283,7 @@ bool bip_init(char *ifname)
fprintf(stderr, "IP Broadcast Address: %s\n",
inet_ntoa(broadcast_address));
fprintf(stderr, "UDP Port: 0x%04X [%hu]\n",
bip_get_port(),
bip_get_port());
bip_get_port(), bip_get_port());
}
/* assumes that the driver has already been initialized */
sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+135 -122
View File
@@ -58,21 +58,25 @@ static uint8_t RxBuffer[MAX_MPDU];
/* Timer that indicates line silence - and functions */
static uint16_t SilenceTime;
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
static uint16_t Timer_Silence(void)
static uint16_t Timer_Silence(
void)
{
return SilenceTime;
}
static void Timer_Silence_Reset(void)
static void Timer_Silence_Reset(
void)
{
SilenceTime = 0;
}
void dlmstp_millisecond_timer(void)
void dlmstp_millisecond_timer(
void)
{
INCREMENT_AND_LIMIT_UINT16(SilenceTime);
}
void dlmstp_reinit(void)
void dlmstp_reinit(
void)
{
/*RS485_Reinit(); */
dlmstp_set_mac_address(DEFAULT_MAC_ADDRESS);
@@ -80,7 +84,8 @@ void dlmstp_reinit(void)
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
}
void dlmstp_cleanup(void)
void dlmstp_cleanup(
void)
{
/* nothing to do for static buffers */
if (Received_Frame_Flag) {
@@ -92,11 +97,12 @@ void dlmstp_cleanup(void)
}
/* returns number of bytes sent on success, zero on failure */
int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
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 */
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 i = 0;
@@ -121,18 +127,18 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
}
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 */
{
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;
DWORD wait_status = 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 */
wait_status = WaitForSingleObject(Receive_Packet_Flag,timeout);
wait_status = WaitForSingleObject(Receive_Packet_Flag, timeout);
if (wait_status == WAIT_OBJECT_0) {
if (Receive_Packet.ready) {
if (Receive_Packet.pdu_len) {
@@ -144,8 +150,7 @@ uint16_t dlmstp_receive(
}
if (pdu) {
memmove(pdu,
&Receive_Packet.pdu,
sizeof(Receive_Packet.pdu));
&Receive_Packet.pdu, sizeof(Receive_Packet.pdu));
}
pdu_len = Receive_Packet.pdu_len;
}
@@ -156,12 +161,14 @@ uint16_t dlmstp_receive(
return pdu_len;
}
static void dlmstp_receive_fsm_task(void *pArg)
static void dlmstp_receive_fsm_task(
void *pArg)
{
bool received_frame;
(void)pArg;
(void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
(void) pArg;
(void) SetThreadPriority(GetCurrentThread(),
THREAD_PRIORITY_TIME_CRITICAL);
while (TRUE) {
/* only do receive state machine while we don't have a frame */
if ((MSTP_Port.ReceivedValidFrame == false) &&
@@ -180,12 +187,14 @@ static void dlmstp_receive_fsm_task(void *pArg)
}
}
static void dlmstp_master_fsm_task(void *pArg)
static void dlmstp_master_fsm_task(
void *pArg)
{
DWORD dwMilliseconds = 0;
(void)pArg;
(void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
(void) pArg;
(void) SetThreadPriority(GetCurrentThread(),
THREAD_PRIORITY_TIME_CRITICAL);
while (TRUE) {
switch (MSTP_Port.master_state) {
case MSTP_MASTER_STATE_IDLE:
@@ -202,22 +211,26 @@ static void dlmstp_master_fsm_task(void *pArg)
break;
}
if (dwMilliseconds)
WaitForSingleObject(Received_Frame_Flag,dwMilliseconds);
WaitForSingleObject(Received_Frame_Flag, dwMilliseconds);
MSTP_Master_Node_FSM(&MSTP_Port);
}
}
static void dlmstp_millisecond_task(void *pArg)
static void dlmstp_millisecond_task(
void *pArg)
{
(void)pArg;
(void)SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
(void) pArg;
(void) SetThreadPriority(GetCurrentThread(),
THREAD_PRIORITY_TIME_CRITICAL);
for (;;) {
dlmstp_millisecond_timer();
Sleep(1);
}
}
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;
@@ -242,7 +255,7 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_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)
volatile struct mstp_port_struct_t *mstp_port)
{
uint16_t pdu_len = 0;
BOOL rc;
@@ -252,9 +265,8 @@ uint16_t MSTP_Put_Receive(
pdu_len = mstp_port->DataLength;
if (pdu_len > sizeof(Receive_Packet.pdu))
pdu_len = sizeof(Receive_Packet.pdu);
memmove((void *) & Receive_Packet.pdu[0],
(void *) & mstp_port->InputBuffer[0],
pdu_len);
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;
@@ -268,13 +280,13 @@ 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 destination = 0; /* destination address */
(void)timeout;
(void) timeout;
if (!Transmit_Packet.ready) {
return 0;
}
@@ -288,26 +300,24 @@ uint16_t MSTP_Get_Send(
return 0;
}
/* convert the PDU into the MSTP Frame */
pdu_len = MSTP_Create_Frame(
&mstp_port->OutputBuffer[0], /* <-- loading this */
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
mstp_port->OutputBufferSize,
Transmit_Packet.frame_type,
destination,
mstp_port->This_Station,
&Transmit_Packet.pdu[0],
Transmit_Packet.pdu_len);
&Transmit_Packet.pdu[0], Transmit_Packet.pdu_len);
Transmit_Packet.ready = false;
return pdu_len;
}
bool dlmstp_compare_data_expecting_reply(
uint8_t *request_pdu,
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,
BACNET_ADDRESS *dest_address)
BACNET_ADDRESS * dest_address)
{
uint16_t offset;
/* One way to check the message is to compare NPDU
@@ -335,12 +345,12 @@ bool dlmstp_compare_data_expecting_reply(
if (request.pdu_type != PDU_TYPE_CONFIRMED_SERVICE_REQUEST) {
return false;
}
request.invoke_id = request_pdu[offset+2];
request.invoke_id = request_pdu[offset + 2];
/* segmented message? */
if (request_pdu[offset] & BIT3)
request.service_choice = request_pdu[offset+5];
request.service_choice = request_pdu[offset + 5];
else
request.service_choice = request_pdu[offset+3];
request.service_choice = request_pdu[offset + 3];
/* decode the reply data */
bacnet_address_copy(&reply.address, dest_address);
offset = npdu_decode(&reply_pdu[0],
@@ -353,32 +363,32 @@ bool dlmstp_compare_data_expecting_reply(
reply.pdu_type = reply_pdu[offset] & 0xF0;
switch (reply.pdu_type) {
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
reply.invoke_id = reply_pdu[offset+2];
reply.invoke_id = reply_pdu[offset + 2];
/* segmented message? */
if (reply_pdu[offset] & BIT3)
reply.service_choice = reply_pdu[offset+5];
reply.service_choice = reply_pdu[offset + 5];
else
reply.service_choice = reply_pdu[offset+3];
reply.service_choice = reply_pdu[offset + 3];
break;
case PDU_TYPE_SIMPLE_ACK:
reply.invoke_id = reply_pdu[offset+1];
reply.service_choice = reply_pdu[offset+2];
reply.invoke_id = reply_pdu[offset + 1];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_COMPLEX_ACK:
reply.invoke_id = reply_pdu[offset+1];
reply.invoke_id = reply_pdu[offset + 1];
/* segmented message? */
if (reply_pdu[offset] & BIT3)
reply.service_choice = reply_pdu[offset+4];
reply.service_choice = reply_pdu[offset + 4];
else
reply.service_choice = reply_pdu[offset+2];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_ERROR:
reply.invoke_id = reply_pdu[offset+1];
reply.service_choice = reply_pdu[offset+2];
reply.invoke_id = reply_pdu[offset + 1];
reply.service_choice = reply_pdu[offset + 2];
break;
case PDU_TYPE_REJECT:
case PDU_TYPE_ABORT:
reply.invoke_id = reply_pdu[offset+1];
reply.invoke_id = reply_pdu[offset + 1];
break;
default:
return false;
@@ -412,14 +422,14 @@ 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 */
uint8_t destination = 0; /* destination address */
bool matched = false;
(void)timeout;
(void) timeout;
if (!Transmit_Packet.ready) {
return 0;
}
@@ -433,29 +443,26 @@ uint16_t MSTP_Get_Reply(
return 0;
}
/* 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,
&Transmit_Packet.pdu[0],
Transmit_Packet.pdu_len,
&Transmit_Packet.address);
Transmit_Packet.pdu_len, &Transmit_Packet.address);
if (!matched)
return 0;
/* convert the PDU into the MSTP Frame */
pdu_len = MSTP_Create_Frame(
&mstp_port->OutputBuffer[0], /* <-- loading this */
pdu_len = MSTP_Create_Frame(&mstp_port->OutputBuffer[0], /* <-- loading this */
mstp_port->OutputBufferSize,
Transmit_Packet.frame_type,
destination, mstp_port->This_Station,
&Transmit_Packet.pdu[0],
Transmit_Packet.pdu_len);
&Transmit_Packet.pdu[0], Transmit_Packet.pdu_len);
Transmit_Packet.ready = false;
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) {
@@ -472,7 +479,8 @@ void dlmstp_set_mac_address(uint8_t mac_address)
return;
}
uint8_t dlmstp_mac_address(void)
uint8_t dlmstp_mac_address(
void)
{
return MSTP_Port.This_Station;
}
@@ -484,7 +492,8 @@ uint8_t dlmstp_mac_address(void)
/* 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;
@@ -498,7 +507,8 @@ void dlmstp_set_max_info_frames(uint8_t max_info_frames)
return;
}
uint8_t dlmstp_max_info_frames(void)
uint8_t dlmstp_max_info_frames(
void)
{
return MSTP_Port.Nmax_info_frames;
}
@@ -508,7 +518,8 @@ uint8_t dlmstp_max_info_frames(void)
/* 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) {
@@ -524,25 +535,29 @@ void dlmstp_set_max_master(uint8_t 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();
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;
@@ -555,15 +570,16 @@ void dlmstp_get_my_address(BACNET_ADDRESS * 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;
}
@@ -572,7 +588,8 @@ void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest)
return;
}
bool dlmstp_init(char *ifname)
bool dlmstp_init(
char *ifname)
{
unsigned long hThread = 0;
uint32_t arg_value = 0;
@@ -580,10 +597,10 @@ bool dlmstp_init(char *ifname)
/* initialize packet queue */
Receive_Packet.ready = false;
Receive_Packet.pdu_len = 0;
Receive_Packet_Flag = CreateSemaphore (NULL,0,1,"dlmstpReceivePacket");
Receive_Packet_Flag = CreateSemaphore(NULL, 0, 1, "dlmstpReceivePacket");
if (Receive_Packet_Flag == NULL)
exit(1);
Received_Frame_Flag = CreateSemaphore (NULL,0,1,"dlsmtpReceiveFrame");
Received_Frame_Flag = CreateSemaphore(NULL, 0, 1, "dlsmtpReceiveFrame");
if (Received_Frame_Flag == NULL) {
CloseHandle(Receive_Packet_Flag);
exit(1);
@@ -593,7 +610,7 @@ bool dlmstp_init(char *ifname)
if (ifname) {
RS485_Set_Interface(ifname);
#if PRINT_ENABLED
fprintf(stderr,"MS/TP Interface: %s\n", ifname);
fprintf(stderr, "MS/TP Interface: %s\n", ifname);
#endif
}
RS485_Initialize();
@@ -608,17 +625,17 @@ bool dlmstp_init(char *ifname)
uint8_t data;
/* FIXME: implement your data storage */
data = 64; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAC_ADDR); */
data = 64; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAC_ADDR); */
if (data <= 127)
MSTP_Port.This_Station = data;
else
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
/* FIXME: implement your data storage */
data = 127; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_MASTER_ADDR); */
data = 127; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_MASTER_ADDR); */
if ((data <= 127) && (data >= MSTP_Port.This_Station))
MSTP_Port.Nmax_master = data;
else
@@ -634,23 +651,20 @@ bool dlmstp_init(char *ifname)
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
#endif
#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 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);
#endif
/* start the threads */
hThread = _beginthread(dlmstp_millisecond_task,4096,&arg_value);
hThread = _beginthread(dlmstp_millisecond_task, 4096, &arg_value);
if (hThread == 0) {
fprintf(stderr, "Failed to start timer task\n");
}
hThread = _beginthread(dlmstp_receive_fsm_task,4096,&arg_value);
hThread = _beginthread(dlmstp_receive_fsm_task, 4096, &arg_value);
if (hThread == 0) {
fprintf(stderr, "Failed to start recive FSM task\n");
}
hThread = _beginthread(dlmstp_master_fsm_task,4096,&arg_value);
hThread = _beginthread(dlmstp_master_fsm_task, 4096, &arg_value);
if (hThread == 0) {
fprintf(stderr, "Failed to start Master Node FSM task\n");
}
@@ -661,26 +675,26 @@ bool dlmstp_init(char *ifname)
#ifdef TEST_DLMSTP
#include <stdio.h>
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;
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;
}
/* returns a delta timestamp */
uint32_t timestamp_ms(void)
uint32_t timestamp_ms(
void)
{
DWORD ticks = 0, delta_ticks = 0;
static DWORD last_ticks = 0;
ticks = GetTickCount();
delta_ticks =
(ticks >= last_ticks ?
ticks - last_ticks :
MAXDWORD - last_ticks);
(ticks >= last_ticks ? ticks - last_ticks : MAXDWORD - last_ticks);
last_ticks = ticks;
return delta_ticks;
@@ -688,7 +702,9 @@ uint32_t timestamp_ms(void)
static char *Network_Interface = NULL;
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
uint16_t pdu_len = 0;
@@ -703,14 +719,11 @@ int main(int argc, char *argv[])
dlmstp_init(Network_Interface);
/* forever task */
for (;;) {
pdu_len = dlmstp_receive(NULL,NULL,0,INFINITE);
pdu_len = dlmstp_receive(NULL, NULL, 0, INFINITE);
#if 0
MSTP_Create_And_Send_Frame(
&MSTP_Port,
MSTP_Create_And_Send_Frame(&MSTP_Port,
FRAME_TYPE_TEST_REQUEST,
MSTP_Port.SourceAddress,
MSTP_Port.This_Station,
NULL, 0);
MSTP_Port.SourceAddress, MSTP_Port.This_Station, NULL, 0);
#endif
}
+56 -45
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 <assert.h>
#include <direct.h>
#include <io.h>
@@ -78,19 +78,24 @@ static unsigned eth_timeout = 100;
/* couple of external func for runtime error logging, you can simply */
/* replace them with standard "printf(...)" */
/* Logging extern functions: Info level */
extern void LogInfo(const char *msg);
extern void LogInfo(
const char *msg);
/* Logging extern functions: Error level*/
extern void LogError(const char *msg);
extern void LogError(
const char *msg);
/* Logging extern functions: Debug level*/
extern void LogDebug(const char *msg);
extern void LogDebug(
const char *msg);
bool ethernet_valid(void)
bool ethernet_valid(
void)
{
return (pcap_eth802_fp != NULL);
}
void ethernet_cleanup(void)
void ethernet_cleanup(
void)
{
if (pcap_eth802_fp) {
pcap_close(pcap_eth802_fp);
@@ -99,7 +104,8 @@ void ethernet_cleanup(void)
LogInfo("ethernet.c: ethernet_cleanup() ok.\n");
}
void ethernet_set_timeout(unsigned timeout)
void ethernet_set_timeout(
unsigned timeout)
{
eth_timeout = timeout;
}
@@ -129,7 +135,8 @@ int setNonblocking(int fd)
}
*/
bool ethernet_init(char *if_name)
bool ethernet_init(
char *if_name)
{
PPACKET_OID_DATA pOidData;
LPADAPTER lpAdapter;
@@ -197,11 +204,11 @@ bool ethernet_init(char *if_name)
*/
/* Open the output device */
pcap_eth802_fp = pcap_open(if_name, /* name of the device */
MAX_MPDU, /* portion of the packet to capture */
MAX_MPDU, /* portion of the packet to capture */
PCAP_OPENFLAG_PROMISCUOUS, /* promiscuous mode */
eth_timeout, /* read timeout */
NULL, /* authentication on the remote machine */
pcap_errbuf /* error buffer */
eth_timeout, /* read timeout */
NULL, /* authentication on the remote machine */
pcap_errbuf /* error buffer */
);
if (pcap_eth802_fp == NULL) {
PacketCloseAdapter(lpAdapter);
@@ -222,10 +229,11 @@ bool ethernet_init(char *if_name)
/* function to send a packet out the 802.2 socket */
/* returns bytes sent success, negative on failure */
int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
int ethernet_send(
BACNET_ADDRESS * dest, /* destination address */
BACNET_ADDRESS * src, /* source address */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len /* number of bytes of data */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len /* number of bytes of data */
)
{
int bytes = 0;
@@ -235,8 +243,7 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
/* don't waste time if the socket is not valid */
if (!ethernet_valid()) {
LogError
("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
LogError("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
return -1;
}
/* load destination ethernet MAC address */
@@ -265,8 +272,7 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
return -4;
}
/* packet length */
mtu_len +=
encode_unsigned16(&mtu[12], 3 /*DSAP,SSAP,LLC */ + pdu_len);
mtu_len += encode_unsigned16(&mtu[12], 3 /*DSAP,SSAP,LLC */ + pdu_len);
/* Logical PDU portion */
mtu[mtu_len++] = 0x82; /* DSAP for BACnet */
mtu[mtu_len++] = 0x82; /* SSAP for BACnet */
@@ -290,12 +296,13 @@ int ethernet_send(BACNET_ADDRESS * dest, /* destination address */
/* 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 */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len /* number of bytes of data */
int ethernet_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len /* number of bytes of data */
)
{
int i = 0; /* counter */
int i = 0; /* counter */
BACNET_ADDRESS src = { 0 }; /* source address */
for (i = 0; i < 6; i++) {
@@ -305,18 +312,19 @@ int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
/* function to send a packet out the 802.2 socket */
/* returns 1 on success, 0 on failure */
return ethernet_send(dest, /* destination address */
&src, /* source address */
pdu, /* any data to be sent - may be null */
pdu_len /* number of bytes of data */
&src, /* source address */
pdu, /* any data to be sent - may be null */
pdu_len /* number of bytes of data */
);
}
/* 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 */
unsigned timeout /* number of milliseconds to wait for a packet. we ommit it due to winpcap API. */
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. we ommit it due to winpcap API. */
)
{
struct pcap_pkthdr *header;
@@ -326,8 +334,7 @@ uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
/* Make sure the socket is open */
if (!ethernet_valid()) {
LogError
("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
LogError("ethernet.c: invalid 802.2 ethernet interface descriptor!\n");
return 0;
}
@@ -374,7 +381,8 @@ uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
return pdu_len;
}
void ethernet_set_my_address(BACNET_ADDRESS * my_address)
void ethernet_set_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
@@ -385,7 +393,8 @@ void ethernet_set_my_address(BACNET_ADDRESS * my_address)
return;
}
void ethernet_get_my_address(BACNET_ADDRESS * my_address)
void ethernet_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0;
@@ -403,9 +412,10 @@ void ethernet_get_my_address(BACNET_ADDRESS * 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++) {
@@ -413,7 +423,7 @@ void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
}
dest->mac_len = 6;
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* denotes broadcast address */
dest->len = 0; /* denotes broadcast address */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
@@ -422,9 +432,11 @@ void ethernet_get_broadcast_address(BACNET_ADDRESS * dest)
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 */
char msgBuf[200];
if (info) {
@@ -439,15 +451,14 @@ void ethernet_debug_address(const char *info, BACNET_ADDRESS * dest)
for (i = 0; i < MAX_MAC_LEN; i++) {
sprintf(msgBuf, "%02X ", (unsigned) dest->mac[i]);
LogInfo(msgBuf);
} /* for */
} /* for */
LogInfo("\n");
sprintf(msgBuf,
" Net=%hu\n Len=%d\n Adr=", dest->net, dest->len);
sprintf(msgBuf, " Net=%hu\n Len=%d\n Adr=", dest->net, dest->len);
LogInfo(msgBuf);
for (i = 0; i < MAX_MAC_LEN; i++) {
sprintf(msgBuf, "%02X ", (unsigned) dest->adr[i]);
LogInfo(msgBuf);
} /* for */
} /* for */
LogInfo("\n");
}
/* if ( dest ) */
+21 -14
View File
@@ -29,7 +29,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <conio.h> /* for kbhit and getch */
#include <conio.h> /* for kbhit and getch */
#include "iam.h"
#include "address.h"
#include "config.h"
@@ -49,7 +49,8 @@ static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
static bool Who_Is_Request = true;
bool I_Am_Request = true;
static void Read_Properties(void)
static void Read_Properties(
void)
{
uint32_t device_id = 0;
bool status = false;
@@ -123,8 +124,10 @@ static void Read_Properties(void)
return;
}
static void LocalIAmHandler(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
static void LocalIAmHandler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
@@ -146,13 +149,12 @@ static void LocalIAmHandler(uint8_t * service_request,
return;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* 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);
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... */
@@ -168,9 +170,11 @@ static void Init_Service_Handlers(void)
handler_read_property_ack);
}
static void print_address(char *name, BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
static void print_address(
char *name,
BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
printf("%s: ", name);
@@ -181,7 +185,8 @@ static void print_address(char *name, BACNET_ADDRESS * dest)
}
}
static void print_address_cache(void)
static void print_address_cache(
void)
{
int i, j;
BACNET_ADDRESS address;
@@ -202,7 +207,9 @@ static void print_address_cache(void)
}
}
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;
+100 -90
View File
@@ -40,7 +40,7 @@
B&B Electronics USOPTL4
SerialGear USB-COMi-SI-M
*/
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
@@ -88,41 +88,44 @@ static DWORD RS485_RTSControl = RTS_CONTROL_DISABLE;
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Set_Interface(char *ifname)
void RS485_Set_Interface(
char *ifname)
{
/* note: expects a constant char, or char from the heap */
RS485_Port_Name = ifname;
}
static void RS485_Print_Error(void)
static void RS485_Print_Error(
void)
{
char * szExtended = ""; /* error string translated from error code */
char *szExtended = ""; /* error string translated from error code */
DWORD dwExtSize;
DWORD dwErr;
dwErr = GetLastError();
fprintf(stderr,"Error %lu:\r\n", dwErr);
fprintf(stderr, "Error %lu:\r\n", dwErr);
/* Get error string from system */
dwExtSize = FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | 80 ,
NULL, dwErr,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
(LPTSTR) szExtended, 0, NULL);
fprintf(stderr,"%s\r\n", szExtended);
dwExtSize =
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER | 80, NULL, dwErr,
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), (LPTSTR) szExtended, 0,
NULL);
fprintf(stderr, "%s\r\n", szExtended);
return;
}
static void RS485_Configure_Status(void)
static void RS485_Configure_Status(
void)
{
DCB dcb = {0};
DCB dcb = { 0 };
COMMTIMEOUTS ctNew;
dcb.DCBlength = sizeof(dcb);
/* get current DCB settings */
if (!GetCommState(RS485_Handle, &dcb)) {
fprintf(stderr,"Unable to get status from %s\n", RS485_Port_Name);
fprintf(stderr, "Unable to get status from %s\n", RS485_Port_Name);
RS485_Print_Error();
exit(1);
}
@@ -130,49 +133,49 @@ static void RS485_Configure_Status(void)
/* update DCB rate, byte size, parity, and stop bits size */
dcb.BaudRate = RS485_Baud;
dcb.ByteSize = RS485_ByteSize;
dcb.Parity = RS485_Parity;
dcb.Parity = RS485_Parity;
dcb.StopBits = RS485_StopBits;
/* update flow control settings */
dcb.fDtrControl = RS485_DTRControl;
dcb.fRtsControl = RS485_RTSControl;
dcb.fDtrControl = RS485_DTRControl;
dcb.fRtsControl = RS485_RTSControl;
/*
dcb.fOutxCtsFlow = CTSOUTFLOW(TTYInfo);
dcb.fOutxDsrFlow = DSROUTFLOW(TTYInfo);
dcb.fDsrSensitivity = DSRINFLOW(TTYInfo);
dcb.fOutX = XONXOFFOUTFLOW(TTYInfo);
dcb.fInX = XONXOFFINFLOW(TTYInfo);
dcb.fTXContinueOnXoff = TXAFTERXOFFSENT(TTYInfo);
dcb.XonChar = XONCHAR(TTYInfo);
dcb.XoffChar = XOFFCHAR(TTYInfo);
dcb.XonLim = XONLIMIT(TTYInfo);
dcb.XoffLim = XOFFLIMIT(TTYInfo);
// DCB settings not in the user's control
dcb.fParity = TRUE;
*/
dcb.fOutxCtsFlow = CTSOUTFLOW(TTYInfo);
dcb.fOutxDsrFlow = DSROUTFLOW(TTYInfo);
dcb.fDsrSensitivity = DSRINFLOW(TTYInfo);
dcb.fOutX = XONXOFFOUTFLOW(TTYInfo);
dcb.fInX = XONXOFFINFLOW(TTYInfo);
dcb.fTXContinueOnXoff = TXAFTERXOFFSENT(TTYInfo);
dcb.XonChar = XONCHAR(TTYInfo);
dcb.XoffChar = XOFFCHAR(TTYInfo);
dcb.XonLim = XONLIMIT(TTYInfo);
dcb.XoffLim = XOFFLIMIT(TTYInfo);
// DCB settings not in the user's control
dcb.fParity = TRUE;
*/
if (!SetCommState(RS485_Handle, &dcb)) {
fprintf(stderr,"Unable to set status on %s\n", RS485_Port_Name);
fprintf(stderr, "Unable to set status on %s\n", RS485_Port_Name);
RS485_Print_Error();
}
/* configure the COM port timeout values */
ctNew.ReadIntervalTimeout = MAXDWORD;
ctNew.ReadTotalTimeoutMultiplier = MAXDWORD;
ctNew.ReadTotalTimeoutConstant = 1000;
ctNew.ReadIntervalTimeout = MAXDWORD;
ctNew.ReadTotalTimeoutMultiplier = MAXDWORD;
ctNew.ReadTotalTimeoutConstant = 1000;
ctNew.WriteTotalTimeoutMultiplier = 0;
ctNew.WriteTotalTimeoutConstant = 0;
ctNew.WriteTotalTimeoutConstant = 0;
if (!SetCommTimeouts(RS485_Handle, &ctNew)) {
RS485_Print_Error();
}
/* Get rid of any stray characters */
if (!PurgeComm(RS485_Handle, PURGE_TXABORT | PURGE_RXABORT)) {
fprintf(stderr,"Unable to purge %s\n", RS485_Port_Name);
fprintf(stderr, "Unable to purge %s\n", RS485_Port_Name);
RS485_Print_Error();
}
/* Set the Comm buffer size */
SetupComm(RS485_Handle, MAX_MPDU, MAX_MPDU);
/* raise DTR */
if (!EscapeCommFunction(RS485_Handle, SETDTR)) {
fprintf(stderr,"Unable to set DTR on %s\n", RS485_Port_Name);
fprintf(stderr, "Unable to set DTR on %s\n", RS485_Port_Name);
RS485_Print_Error();
}
}
@@ -184,22 +187,19 @@ static void RS485_Configure_Status(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize(void)
void RS485_Initialize(
void)
{
RS485_Handle = CreateFile(
RS485_Port_Name,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
/*FILE_FLAG_OVERLAPPED*/0,
RS485_Handle = CreateFile(RS485_Port_Name,
GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
/*FILE_FLAG_OVERLAPPED */ 0,
0);
if (RS485_Handle == INVALID_HANDLE_VALUE) {
fprintf(stderr,"Unable to open %s\n", RS485_Port_Name);
fprintf(stderr, "Unable to open %s\n", RS485_Port_Name);
RS485_Print_Error();
exit(1);
}
if (!GetCommTimeouts( RS485_Handle, &RS485_Timeouts)) {
if (!GetCommTimeouts(RS485_Handle, &RS485_Timeouts)) {
RS485_Print_Error();
}
RS485_Configure_Status();
@@ -207,13 +207,14 @@ void RS485_Initialize(void)
return;
}
void RS485_Cleanup(void)
void RS485_Cleanup(
void)
{
if (!EscapeCommFunction(RS485_Handle, CLRDTR)) {
RS485_Print_Error();
}
if (!SetCommTimeouts(RS485_Handle, &RS485_Timeouts)) {
if (!SetCommTimeouts(RS485_Handle, &RS485_Timeouts)) {
RS485_Print_Error();
}
@@ -226,15 +227,21 @@ void RS485_Cleanup(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
uint32_t RS485_Get_Baud_Rate(
void)
{
switch (RS485_Baud) {
case CBR_19200: return 19200;
case CBR_38400: return 38400;
case CBR_57600: return 57600;
case CBR_115200: return 115200;
case CBR_19200:
return 19200;
case CBR_38400:
return 38400;
case CBR_57600:
return 57600;
case CBR_115200:
return 115200;
default:
case CBR_9600: return 9600;
case CBR_9600:
return 9600;
}
}
@@ -244,29 +251,30 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_Set_Baud_Rate(uint32_t baud)
bool RS485_Set_Baud_Rate(
uint32_t baud)
{
bool valid = true;
switch (baud) {
case 9600:
RS485_Baud = CBR_9600;
break;
case 19200:
RS485_Baud = CBR_19200;
break;
case 38400:
RS485_Baud = CBR_38400;
break;
case 57600:
RS485_Baud = CBR_57600;
break;
case 115200:
RS485_Baud = CBR_115200;
break;
default:
valid = false;
break;
case 9600:
RS485_Baud = CBR_9600;
break;
case 19200:
RS485_Baud = CBR_19200;
break;
case 38400:
RS485_Baud = CBR_38400;
break;
case 57600:
RS485_Baud = CBR_57600;
break;
case 115200:
RS485_Baud = CBR_115200;
break;
default:
valid = false;
break;
}
if (valid) {
@@ -278,11 +286,11 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
/* Transmits a Frame on the wire */
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) */
uint16_t nbytes) /* number of bytes of data (up to 501) */
{
DWORD dwWritten = 0;
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) */
DWORD dwWritten = 0;
if (mstp_port) {
uint32_t baud;
@@ -310,7 +318,8 @@ void RS485_Send_Frame(
}
/* called by timer, interrupt(?) or other thread */
void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
void RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port)
{
char lpBuf[1];
DWORD dwRead = 0;
@@ -322,7 +331,7 @@ void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
else if (mstp_port->DataAvailable == false) {
/* check for data */
if (!ReadFile(RS485_Handle, lpBuf, sizeof(lpBuf), &dwRead, NULL)) {
if (GetLastError() != ERROR_IO_PENDING) {
if (GetLastError() != ERROR_IO_PENDING) {
mstp_port->ReceiveError = TRUE;
}
} else {
@@ -335,10 +344,11 @@ void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port)
}
#ifdef TEST_RS485
static void test_transmit_task(void *pArg)
static void test_transmit_task(
void *pArg)
{
char *TxBuf = "BACnet MS/TP";
size_t len = strlen(TxBuf)+1;
size_t len = strlen(TxBuf) + 1;
while (TRUE) {
Sleep(1000);
@@ -346,7 +356,8 @@ static void test_transmit_task(void *pArg)
}
}
int main(void)
int main(
void)
{
unsigned long hThread = 0;
uint32_t arg_value = 0;
@@ -357,13 +368,13 @@ int main(void)
RS485_Set_Interface("COM4");
RS485_Set_Baud_Rate(38400);
RS485_Initialize();
#if 0
#if 0
/* create a task for synchronous transmit */
hThread = _beginthread(test_transmit_task,4096,&arg_value);
hThread = _beginthread(test_transmit_task, 4096, &arg_value);
if (hThread == 0) {
fprintf(stderr, "Failed to start transmit task\n");
}
#endif
#endif
/* receive task */
for (;;) {
if (!ReadFile(RS485_Handle, lpBuf, sizeof(lpBuf), &dwRead, NULL)) {
@@ -374,12 +385,11 @@ int main(void)
/* print any characters received */
if (dwRead) {
for (i = 0; i < dwRead; i++) {
fprintf(stderr,"%02X ",lpBuf[i]);
fprintf(stderr, "%02X ", lpBuf[i]);
}
}
dwRead = 0;
}
}
}
#endif /* TEST_ABORT */
#endif /* TEST_ABORT */
+14 -8
View File
@@ -41,22 +41,28 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void RS485_Set_Interface(char *ifname);
void RS485_Set_Interface(
char *ifname);
void RS485_Initialize(void);
void RS485_Initialize(
void);
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
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) */
uint16_t nbytes); /* number of bytes of data (up to 501) */
void RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
void RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
uint32_t RS485_Get_Baud_Rate(void);
bool RS485_Set_Baud_Rate(uint32_t baud);
uint32_t RS485_Get_Baud_Rate(
void);
bool RS485_Set_Baud_Rate(
uint32_t baud);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+32 -31
View File
@@ -56,23 +56,27 @@ 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)
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)
{
(void)pArg;
(void) pArg;
for (;;) {
Sleep(1);
dlmstp_millisecond_timer();
@@ -85,28 +89,28 @@ void *milliseconds_task(void *pArg)
uint16_t MSTP_Put_Receive(
volatile struct mstp_port_struct_t *mstp_port)
{
(void)mstp_port;
(void) mstp_port;
return 0;
}
/* 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;
}
@@ -131,27 +135,25 @@ static void print_received_packet(
mstp_port->DestinationAddress,
mstp_port->SourceAddress,
HI_BYTE(mstp_port->DataLength),
LO_BYTE(mstp_port->DataLength),
mstp_port->HeaderCRCActual);
LO_BYTE(mstp_port->DataLength), mstp_port->HeaderCRCActual);
if (mstp_port->DataLength) {
for (i = 0; i < mstp_port->DataLength; i++) {
fprintf(stderr,"%02X ",
mstp_port->InputBuffer[i]);
fprintf(stderr, "%02X ", mstp_port->InputBuffer[i]);
}
fprintf(stderr,
"%02X %02X ",
mstp_port->DataCRCActualMSB,
mstp_port->DataCRCActualLSB);
"%02X %02X ",
mstp_port->DataCRCActualMSB, mstp_port->DataCRCActualLSB);
}
fprintf(stderr,"%s",
mstptext_frame_type(mstp_port->FrameType));
fprintf(stderr,"\n");
fprintf(stderr, "%s", mstptext_frame_type(mstp_port->FrameType));
fprintf(stderr, "\n");
}
static char *Network_Interface = NULL;
/* 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;
@@ -168,7 +170,7 @@ int main(int argc, char *argv[])
if (argc > 2) {
my_mac = strtol(argv[2], NULL, 0);
if (my_mac > 127)
my_mac = 127;
my_mac = 127;
}
/* initialize our interface */
RS485_Set_Interface(Network_Interface);
@@ -186,7 +188,7 @@ int main(int argc, char *argv[])
MSTP_Init(&MSTP_Port);
mstp_port->Lurking = true;
/* start our MilliSec task */
hThread = _beginthread(milliseconds_task,4096,&arg_value);
hThread = _beginthread(milliseconds_task, 4096, &arg_value);
if (hThread == 0) {
fprintf(stderr, "Failed to start timer task\n");
}
@@ -207,4 +209,3 @@ int main(int argc, char *argv[])
//return 0;
}
+5 -5
View File
@@ -11,7 +11,7 @@ typedef signed char int8_t; /* 1 byte -127 to 127 */
typedef unsigned short uint16_t; /* 2 bytes 0 to 65535 */
typedef signed short int16_t; /* 2 bytes -32767 to 32767 */
/*typedef unsigned short long uint24_t; // 3 bytes 0 to 16777215 */
typedef unsigned uint32_t; /* 4 bytes 0 to 4294967295 */
typedef unsigned uint32_t; /* 4 bytes 0 to 4294967295 */
typedef int int32_t; /* 4 bytes -2147483647 to 2147483647 */
/* typedef signed long long int64_t; */
/* typedef unsigned long long uint64_t; */
@@ -24,8 +24,8 @@ typedef int int32_t; /* 4 bytes -2147483647 to 2147483647 */
#define INT16_MAX 32767
#define INT32_MAX 2147483647
#define UINT8_MAX 0xff /* 255U */
#define UINT16_MAX 0xffff /* 65535U */
#define UINT32_MAX 0xffffffff /* 4294967295U */
#define UINT8_MAX 0xff /* 255U */
#define UINT16_MAX 0xffff /* 65535U */
#define UINT32_MAX 0xffffffff /* 4294967295U */
#endif /* STDINT_H */
#endif /* STDINT_H */