This commit is contained in:
skarg
2007-04-02 20:58:17 +00:00
parent af939531ce
commit aefe3dccd0
21 changed files with 0 additions and 4377 deletions
-29
View File
@@ -1,29 +0,0 @@
// $Id$
// File: 18f252.lkr
// Sample linker script for the PIC18F252 processor
LIBPATH .
FILES c018i.o
FILES clib.lib
FILES p18f252.lib
CODEPAGE NAME=vectors START=0x0 END=0x29 PROTECTED
CODEPAGE NAME=page START=0x2A END=0x7FFF
CODEPAGE NAME=idlocs START=0x200000 END=0x200007 PROTECTED
CODEPAGE NAME=config START=0x300000 END=0x30000D PROTECTED
CODEPAGE NAME=devid START=0x3FFFFE END=0x3FFFFF PROTECTED
CODEPAGE NAME=eedata START=0xF00000 END=0xF000FF PROTECTED
ACCESSBANK NAME=accessram START=0x0 END=0x7F
DATABANK NAME=gpr0 START=0x80 END=0xFF
DATABANK NAME=gpr1 START=0x100 END=0x1FF
DATABANK NAME=gpr2 START=0x200 END=0x2FF
DATABANK NAME=gpr3 START=0x300 END=0x3FF
DATABANK NAME=gpr4 START=0x400 END=0x4FF
DATABANK NAME=gpr5 START=0x500 END=0x5FF
ACCESSBANK NAME=accesssfr START=0xF80 END=0xFFF PROTECTED
SECTION NAME=CONFIG ROM=config
STACK SIZE=0x100 RAM=gpr5
-131
View File
@@ -1,131 +0,0 @@
[HEADER]
magic_cookie={66E99B07-E706-4689-9E80-9B2582898A13}
file_version=1.0
[PATH_INFO]
dir_src=
dir_bin=
dir_tmp=
dir_sin=
dir_inc=C:\code\bacnet-stack;C:\code\bacnet-stack\demo\handler;C:\code\bacnet-stack\demo\object;C:\code\bacnet-stack\ports\pic18
dir_lib=C:\mcc18\lib
dir_lkr=
[CAT_FILTERS]
filter_src=*.asm;*.c
filter_inc=*.h;*.inc
filter_obj=*.o
filter_lib=*.lib
filter_lkr=*.lkr
[OTHER_FILES]
file_000=no
file_001=no
file_002=no
file_003=no
file_004=no
file_005=no
file_006=no
file_007=no
file_008=no
file_009=no
file_010=no
file_011=no
file_012=no
file_013=no
file_014=no
file_015=no
file_016=no
file_017=no
file_018=no
file_019=no
file_020=no
file_021=no
file_022=no
file_023=no
file_024=no
file_025=no
file_026=no
file_027=no
file_028=no
file_029=no
file_030=no
file_031=no
file_032=no
file_033=no
file_034=no
file_035=no
file_036=no
file_037=no
file_038=no
file_039=no
file_040=no
file_041=no
file_042=no
file_043=no
file_044=no
file_045=no
file_046=no
file_047=no
file_048=no
file_049=no
file_050=no
file_051=no
[FILE_INFO]
file_000=C:\code\bacnet-stack\abort.c
file_001=C:\code\bacnet-stack\apdu.c
file_002=C:\code\bacnet-stack\bacapp.c
file_003=C:\code\bacnet-stack\bacdcode.c
file_004=C:\code\bacnet-stack\bacerror.c
file_005=C:\code\bacnet-stack\bacstr.c
file_006=C:\code\bacnet-stack\crc.c
file_007=C:\code\bacnet-stack\datalink.c
file_008=C:\code\bacnet-stack\dcc.c
file_009=C:\code\bacnet-stack\iam.c
file_010=C:\code\bacnet-stack\mstp.c
file_011=C:\code\bacnet-stack\npdu.c
file_012=C:\code\bacnet-stack\rd.c
file_013=C:\code\bacnet-stack\reject.c
file_014=C:\code\bacnet-stack\rp.c
file_015=C:\code\bacnet-stack\whois.c
file_016=C:\code\bacnet-stack\demo\handler\h_dcc.c
file_017=C:\code\bacnet-stack\demo\handler\h_rd.c
file_018=main.c
file_019=dlmstp.c
file_020=rs485.c
file_021=device.c
file_022=C:\code\bacnet-stack\wp.h
file_023=C:\code\bacnet-stack\abort.h
file_024=C:\code\bacnet-stack\apdu.h
file_025=C:\code\bacnet-stack\bacapp.h
file_026=C:\code\bacnet-stack\bacdcode.h
file_027=C:\code\bacnet-stack\bacdef.h
file_028=C:\code\bacnet-stack\bacenum.h
file_029=C:\code\bacnet-stack\bacerror.h
file_030=C:\code\bacnet-stack\bacstr.h
file_031=C:\code\bacnet-stack\config.h
file_032=C:\code\bacnet-stack\crc.h
file_033=C:\code\bacnet-stack\datalink.h
file_034=C:\code\bacnet-stack\dcc.h
file_035=C:\code\bacnet-stack\dlmstp.h
file_036=C:\code\bacnet-stack\iam.h
file_037=C:\code\bacnet-stack\mstp.h
file_038=C:\code\bacnet-stack\npdu.h
file_039=C:\code\bacnet-stack\rd.h
file_040=C:\code\bacnet-stack\reject.h
file_041=C:\code\bacnet-stack\rp.h
file_042=C:\code\bacnet-stack\rs485.h
file_043=C:\code\bacnet-stack\whois.h
file_044=C:\code\bacnet-stack\demo\handler\client.h
file_045=C:\code\bacnet-stack\demo\handler\handlers.h
file_046=C:\code\bacnet-stack\demo\object\ai.h
file_047=C:\code\bacnet-stack\demo\object\ao.h
file_048=C:\code\bacnet-stack\demo\object\device.h
file_049=stdbool.h
file_050=stdint.h
file_051=hardware.h
[SUITE_INFO]
suite_guid={5B7D72DD-9861-47BD-9F60-2BE967BF8416}
suite_state=
[TOOL_SETTINGS]
TS{DD2213A8-6310-47B1-8376-9430CDFC013F}=
TS{BFD27FBA-4A02-4C0E-A5E5-B812F3E7707C}=/o"$(TARGETBASE).cof" /M"$(BINDIR_)$(TARGETBASE).map"
TS{C2AF05E7-1416-4625-923D-E114DB6E2B96}=-DPRINT_ENABLED=0 -DBACDL_MSTP -DBIG_ENDIAN=1 -mL -Ls -Ou- -Ot- -Ob- -Op- -Or- -Od- -Opa-
TS{ADE93A55-C7C7-4D4D-A4BA-59305F7D0391}=
Binary file not shown.
-151
View File
@@ -1,151 +0,0 @@
[HEADER]
magic_cookie={66E99B07-E706-4689-9E80-9B2582898A13}
file_version=1.0
[PATH_INFO]
dir_src=
dir_bin=
dir_tmp=
dir_sin=
dir_inc=c:\mcc18\h;c:\code\bacnet-stack;c:\code\bacnet-stack\ports\pic18;c:\code\bacnet-stack\demo\object;c:\code\bacnet-stack\demo\handler
dir_lib=c:\mcc18\lib
dir_lkr=
[CAT_FILTERS]
filter_src=*.asm;*.c
filter_inc=*.h;*.inc
filter_obj=*.o
filter_lib=*.lib
filter_lkr=*.lkr
[OTHER_FILES]
file_000=no
file_001=no
file_002=no
file_003=no
file_004=no
file_005=no
file_006=no
file_007=no
file_008=no
file_009=no
file_010=no
file_011=no
file_012=no
file_013=no
file_014=no
file_015=no
file_016=no
file_017=no
file_018=no
file_019=no
file_020=no
file_021=no
file_022=no
file_023=no
file_024=no
file_025=no
file_026=no
file_027=no
file_028=no
file_029=no
file_030=no
file_031=no
file_032=no
file_033=no
file_034=no
file_035=no
file_036=no
file_037=no
file_038=no
file_039=no
file_040=no
file_041=no
file_042=no
file_043=no
file_044=no
file_045=no
file_046=no
file_047=no
file_048=no
file_049=no
file_050=no
file_051=no
file_052=no
file_053=no
file_054=no
file_055=no
file_056=no
file_057=no
file_058=no
[FILE_INFO]
file_000=rs485.c
file_001=main.c
file_002=init.c
file_003=isr.c
file_004=timer.c
file_005=C:\code\bacnet-stack\rp.c
file_006=C:\code\bacnet-stack\whois.c
file_007=C:\code\bacnet-stack\abort.c
file_008=C:\code\bacnet-stack\apdu.c
file_009=C:\code\bacnet-stack\bacdcode.c
file_010=C:\code\bacnet-stack\bacerror.c
file_011=C:\code\bacnet-stack\crc.c
file_012=C:\code\bacnet-stack\datalink.c
file_013=C:\code\bacnet-stack\iam.c
file_014=C:\code\bacnet-stack\mstp.c
file_015=C:\code\bacnet-stack\npdu.c
file_016=C:\code\bacnet-stack\reject.c
file_017=C:\code\bacnet-stack\dcc.c
file_018=C:\code\bacnet-stack\bacstr.c
file_019=C:\code\bacnet-stack\bacapp.c
file_020=device.c
file_021=dlmstp.c
file_022=C:\code\bacnet-stack\demo\handler\h_rd.c
file_023=C:\code\bacnet-stack\demo\handler\h_dcc.c
file_024=C:\code\bacnet-stack\rd.c
file_025=C:\code\bacnet-stack\demo\handler\txbuf.c
file_026=C:\code\bacnet-stack\demo\handler\h_whois.c
file_027=C:\code\bacnet-stack\demo\handler\noserv.c
file_028=stdbool.h
file_029=stdint.h
file_030=init.h
file_031=timer.h
file_032=C:\code\bacnet-stack\whois.h
file_033=C:\code\bacnet-stack\abort.h
file_034=C:\code\bacnet-stack\apdu.h
file_035=C:\code\bacnet-stack\bacdcode.h
file_036=C:\code\bacnet-stack\bacdef.h
file_037=C:\code\bacnet-stack\bacenum.h
file_038=C:\code\bacnet-stack\bacerror.h
file_039=C:\code\bacnet-stack\bigend.h
file_040=C:\code\bacnet-stack\bits.h
file_041=C:\code\bacnet-stack\bytes.h
file_042=C:\code\bacnet-stack\config.h
file_043=C:\code\bacnet-stack\crc.h
file_044=C:\code\bacnet-stack\datalink.h
file_045=C:\code\bacnet-stack\dlmstp.h
file_046=C:\code\bacnet-stack\mstp.h
file_047=C:\code\bacnet-stack\npdu.h
file_048=C:\code\bacnet-stack\reject.h
file_049=C:\code\bacnet-stack\ringbuf.h
file_050=C:\code\bacnet-stack\rs485.h
file_051=C:\code\bacnet-stack\demo\object\ai.h
file_052=C:\code\bacnet-stack\demo\object\ao.h
file_053=C:\code\bacnet-stack\demo\object\device.h
file_054=C:\code\bacnet-stack\dcc.h
file_055=C:\code\bacnet-stack\bacstr.h
file_056=C:\code\bacnet-stack\bacapp.h
file_057=C:\code\bacnet-stack\rd.h
file_058=18f252.lkr
[SUITE_INFO]
suite_guid={5B7D72DD-9861-47BD-9F60-2BE967BF8416}
suite_state=
[TOOL_SETTINGS]
TS{DD2213A8-6310-47B1-8376-9430CDFC013F}=
TS{BFD27FBA-4A02-4C0E-A5E5-B812F3E7707C}=/m"$(BINDIR_)$(TARGETBASE).map" /o"$(TARGETBASE).cof"
TS{C2AF05E7-1416-4625-923D-E114DB6E2B96}=-DTSM_ENABLED=0 -DPRINT_ENABLED=0 -DBACDL_MSTP=1 -mL -pa=1
TS{ADE93A55-C7C7-4D4D-A4BA-59305F7D0391}=
TS{DD2213A8-6310-47B1-8376-9430CDFC013F}001=
TS{BFD27FBA-4A02-4C0E-A5E5-B812F3E7707C}001=/o"$(TARGETBASE).cof"
TS{C2AF05E7-1416-4625-923D-E114DB6E2B96}001=-Ou- -Ot- -Ob- -Op- -Or- -Od- -Opa-
TS{ADE93A55-C7C7-4D4D-A4BA-59305F7D0391}001=
[ACTIVE_FILE_SETTINGS]
TS{C2AF05E7-1416-4625-923D-E114DB6E2B96}001_active=yes
Binary file not shown.
-408
View File
@@ -1,408 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005,2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "apdu.h"
#include "device.h" /* me */
/* note: you really only need to define variables for
properties that are writable or that may change.
The properties that are constant can be hard coded
into the read-property encoding. */
static uint32_t Object_Instance_Number = 0;
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
static uint16_t APDU_Timeout = 3000;
static uint8_t Number_Of_APDU_Retries = 3;
/* methods to manipulate the data */
uint32_t Device_Object_Instance_Number(void)
{
return Object_Instance_Number;
}
bool Device_Set_Object_Instance_Number(uint32_t object_id)
{
bool status = true; /* return value */
if (object_id <= BACNET_MAX_INSTANCE)
Object_Instance_Number = object_id;
else
status = false;
return status;
}
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)
{
return System_Status;
}
void Device_Set_System_Status(BACNET_DEVICE_STATUS status)
{
/* FIXME: bounds check? */
System_Status = status;
}
/* FIXME: put your vendor ID here! */
uint16_t Device_Vendor_Identifier(void)
{
return 0;
}
uint8_t Device_Protocol_Version(void)
{
return 1;
}
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)
{
return MAX_APDU;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
{
return SEGMENTATION_NONE;
}
uint16_t Device_APDU_Timeout(void)
{
return APDU_Timeout;
}
/* in milliseconds */
void Device_Set_APDU_Timeout(uint16_t timeout)
{
APDU_Timeout = timeout;
}
uint8_t Device_Number_Of_APDU_Retries(void)
{
return Number_Of_APDU_Retries;
}
void Device_Set_Number_Of_APDU_Retries(uint8_t retries)
{
Number_Of_APDU_Retries = retries;
}
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 count = 1;
return count;
}
bool Device_Object_List_Identifier(unsigned array_index,
int *object_type, uint32_t * instance)
{
bool status = false;
unsigned object_index = 0;
unsigned object_count = 0;
/* device object */
if (array_index == 1) {
*object_type = OBJECT_DEVICE;
*instance = Object_Instance_Number;
status = true;
}
return status;
}
/* return the length of the apdu encoded or -1 for error or
-2 for abort */
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)
{
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;
int object_type = 0;
uint32_t instance = 0;
unsigned count = 0;
/* FIXME: change the hardcoded names to suit your application */
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
characterstring_init_ansi(&char_string, (char *) "TD");
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, (char *) "Tiny");
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_SYSTEM_STATUS:
apdu_len =
encode_tagged_enumerated(&apdu[0], Device_System_Status());
break;
case PROP_VENDOR_NAME:
characterstring_init_ansi(&char_string, (char *) "ASHRAE");
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_tagged_unsigned(&apdu[0], Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
characterstring_init_ansi(&char_string, (char *) "GNU");
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, (char *) "1.0");
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
characterstring_init_ansi(&char_string, (char *) "1.0");
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_PROTOCOL_VERSION:
apdu_len =
encode_tagged_unsigned(&apdu[0], Device_Protocol_Version());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_tagged_unsigned(&apdu[0], Device_Protocol_Revision());
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_tagged_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_tagged_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);
apdu_len = encode_tagged_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_tagged_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_tagged_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 = -2;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_OTHER;
apdu_len = -1;
break;
}
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_tagged_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_tagged_unsigned(&apdu[0],
Device_Max_APDU_Length_Accepted());
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_tagged_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_tagged_unsigned(&apdu[0], APDU_Timeout);
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_tagged_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_tagged_unsigned(&apdu[0], Device_Database_Revision());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testDevice(Test * pTest)
{
bool status = false;
const char *name = "Patricia";
status = Device_Set_Object_Instance_Number(0);
ct_test(pTest, Device_Object_Instance_Number() == 0);
ct_test(pTest, status == true);
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
ct_test(pTest, Device_Object_Instance_Number() == BACNET_MAX_INSTANCE);
ct_test(pTest, status == true);
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE / 2);
ct_test(pTest,
Device_Object_Instance_Number() == (BACNET_MAX_INSTANCE / 2));
ct_test(pTest, status == true);
status = Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE + 1);
ct_test(pTest,
Device_Object_Instance_Number() != (BACNET_MAX_INSTANCE + 1));
ct_test(pTest, status == false);
return;
}
#ifdef TEST_DEVICE
/* stubs to dependencies to keep unit test simple */
char *Analog_Input_Name(uint32_t object_instance)
{
(void) object_instance;
return "";
}
unsigned Analog_Input_Count(void)
{
return 0;
}
uint32_t Analog_Input_Index_To_Instance(unsigned index)
{
return index;
}
char *Analog_Output_Name(uint32_t object_instance)
{
(void) object_instance;
return "";
}
unsigned Analog_Output_Count(void)
{
return 0;
}
uint32_t Analog_Output_Index_To_Instance(unsigned index)
{
return index;
}
int main(void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Tiny Device", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testDevice);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif /* TEST_DEVICE */
#endif /* TEST */
-328
View File
@@ -1,328 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#if PRINT_ENABLED
#include <stdio.h>
#endif
#include "bacdef.h"
#include "mstp.h"
#include "dlmstp.h"
#include "rs485.h"
#include "npdu.h"
#include "eeprom.h"
/* Number of MS/TP Packets Rx/Tx
*/
uint16_t MSTP_Packets = 0;
/* receive buffer */
#pragma udata MSTP_RxData
static DLMSTP_PACKET Receive_Buffer;
/* temp buffer for NPDU insertion */
/* local MS/TP port data - shared with RS-485 */
#pragma udata MSTP_PortData
volatile struct mstp_port_struct_t MSTP_Port;
#pragma udata
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
/* This defines the number of edit fields for this module
*/
#define MAX_EDIT_FIELD 1
static uint8_t EditField = 0;
/* *************************************************************************
DESCRIPTION: This function handles incrementing or decrementing our
EditField
RETURN: none
ALGORITHM: none
NOTES: Pass a #>0 to increment #<0 to decrement
*************************************************************************** */
void dlmstp_SetEditField(signed char state)
{ /* direction our editfield is moving */
if (state > 0) {
if (++EditField > MAX_EDIT_FIELD)
EditField = 0;
} else if (state < 0) {
if (EditField)
EditField--;
else
EditField = MAX_EDIT_FIELD;
} else
EditField = 0;
}
/* *************************************************************************
DESCRIPTION: Gets the current edit field for this module
RETURN: the current edit field
ALGORITHM: none
NOTES: none
*************************************************************************** */
uint8_t dlmstp_GetEditField(void)
{
return (EditField);
}
void dlmstp_millisecond_timer(void)
{
INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer);
}
void dlmstp_reinit(void)
{
RS485_Reinit();
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
}
void dlmstp_init(void)
{
uint8_t data;
/* initialize buffer */
Receive_Buffer.ready = false;
Receive_Buffer.pdu_len = 0;
/* initialize hardware */
RS485_Initialize();
MSTP_Port.InputBuffer = &Receive_Buffer.pdu[0];
MSTP_Init(&MSTP_Port);
data = 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);
data = I2C_Read_Byte(EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_MASTER_ADDR);
if (data <= 127)
MSTP_Port.Nmax_master = data;
else
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
MSTP_Port.Nmax_info_frames =
I2C_Read_Byte(EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_INFO_FRAMES_ADDR);
}
void dlmstp_cleanup(void)
{
/* nothing to do for static buffers */
}
/* returns number of bytes sent on success, zero on failure */
int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* 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 */
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;
/* load destination MAC address */
if (dest && dest->mac_len == 1) {
destination = dest->mac[0];
} else {
return -2;
}
dlmstp_get_my_address(&src);
if ((8 /* header len */ + pdu_len) > MAX_MPDU) {
return -4;
}
bytes_sent = MSTP_Create_Frame(
(uint8_t *) & MSTP_Port.TxBuffer[0],
sizeof(MSTP_Port.TxBuffer),
MSTP_Port.TxFrameType,
destination, MSTP_Port.This_Station, pdu, pdu_len);
MSTP_Port.TxLength = bytes_sent;
MSTP_Port.TxReady = true;
MSTP_Packets++;
}
return bytes_sent;
}
void dlmstp_task(void)
{
uint8_t bytes_remaining;
bool received_frame;
/* only do receive state machine while we don't have a frame */
if ((MSTP_Port.ReceivedValidFrame == false) &&
(MSTP_Port.ReceivedInvalidFrame == false)) {
do {
bytes_remaining = RS485_Check_UART_Data(&MSTP_Port);
MSTP_Receive_Frame_FSM(&MSTP_Port);
received_frame = MSTP_Port.ReceivedValidFrame ||
MSTP_Port.ReceivedInvalidFrame;
if (received_frame)
break;
} while (bytes_remaining);
}
/* only do master state machine while rx is idle */
if (MSTP_Port.receive_state == MSTP_RECEIVE_STATE_IDLE) {
while (MSTP_Master_Node_FSM(&MSTP_Port)) {
};
/*MSTP_Master_Node_FSM(&MSTP_Port);
*/
}
/* see if there is a packet available, and a place
to put the reply (if necessary) and process it */
if (Receive_Buffer.ready && !MSTP_Port.TxReady) {
if (Receive_Buffer.pdu_len) {
MSTP_Packets++;
npdu_handler(&Receive_Buffer.address,
&Receive_Buffer.pdu[0], Receive_Buffer.pdu_len);
}
Receive_Buffer.ready = false;
}
return;
}
void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_address)
{
int i = 0;
if (mstp_address == MSTP_BROADCAST_ADDRESS) {
/* mac_len = 0 if broadcast address */
src->mac_len = 0;
src->mac[0] = 0;
} else {
src->mac_len = 1;
src->mac[0] = mstp_address;
}
/* fill with 0's starting with index 1; index 0 filled above */
for (i = 1; i < MAX_MAC_LEN; i++) {
src->mac[i] = 0;
}
src->net = 0;
src->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
src->adr[i] = 0;
}
}
/* 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 pdu_len)
{ /* 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)
{
/* Master Nodes can only have address 0-127 */
if (mac_address <= 127)
MSTP_Port.This_Station = mac_address;
return;
}
uint8_t dlmstp_my_address(void)
{
return MSTP_Port.This_Station;
}
/* This parameter represents the value of the Max_Info_Frames property of */
/* the node's Device object. The value of Max_Info_Frames specifies the */
/* maximum number of information frames the node may send before it must */
/* pass the token. Max_Info_Frames may have different values on different */
/* 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)
{
MSTP_Port.Nmax_info_frames = max_info_frames;
return;
}
unsigned dlmstp_max_info_frames(void)
{
return MSTP_Port.Nmax_info_frames;
}
/* 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)
{
if (max_master <= 127)
MSTP_Port.Nmax_master = max_master;
return;
}
uint8_t dlmstp_max_master(void)
{
return MSTP_Port.Nmax_master;
}
void dlmstp_get_my_address(BACNET_ADDRESS * my_address)
{
int i = 0; /* counter */
my_address->mac_len = 1;
my_address->mac[0] = MSTP_Port.This_Station;
my_address->net = 0; /* local only, no routing */
my_address->len = 0;
for (i = 0; i < MAX_MAC_LEN; i++) {
my_address->adr[i] = 0;
}
return;
}
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 */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
}
-250
View File
@@ -1,250 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2003 Mark Norton and Steve Karg
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Functional
* Description: Defines the hardware implementation for the Microchip
* microprocessor used in the Synergy lighting control project.
*
*********************************************************************/
#ifndef HARDWARE_H
#define HARDWARE_H
#include <p18F452.h>
#include <portb.h>
#include <timers.h>
/****************************************************************************
* Card IO *
****************************************************************************/
/*
TRIS masks are:
0 = OUTPUT
1 = INPUT
The IO on this card is as follows:
RA0 - SDA - SEEPROM (input)
RA1 - SCL - SEEPROM (input)
RA2 - not used (input)
RA3 - not used (input)
RA4 - LK2a - jumper (input)
RA5 - LK2b - jumper (input)
TRISA - 0011 1111 - 3Fh
RB0 - INT - Zero Cross Interrupt (input)
RB1 - LED - I2C Bus Indication (output)
RB2 - LED - Labeled 'DATA' (output)
RB3 - not used (input)
RB4 - CTS input for RS-232 (not used unless LT1180A chip is there)
RB5 - RTS output for RS-232 (not used unless LT1180A chip is there)
RB6 - PGC - in circuit programming (input)
RB7 - PGD - in circuit programming (input)
TRISB - 1101 1001 - D9h
RC0 - QH of 74165 shift register (input)
RC1 - SHIFTREG_CKL of 74165 shift register (output)
RC2 - SHIFTREG_LOAD of 74165 shift register (output)
RC3 - SCL for I2C bus (input)
RC4 - SDA for I2C bus (input)
RC5 - RS-485 TXEN (or RS232) (output)
RC6 - RS-485 TXD (or RS232) (output)
RC7 - RS-485 RXD (or RS232) (input)
TRISC - 1001 1001 - 99h
*/
#define PORT_A_TRIS_MASK 0x3F
#define PORT_B_TRIS_MASK 0xD9
#define PORT_C_TRIS_MASK 0x99
/* hardware mapping of functionality */
#define DATA_LED_ON() PORTBbits.RB2=0
#define DATA_LED_OFF() PORTBbits.RB2=1
#define ABUS_LED_ON() PORTBbits.RB1=0
#define ABUS_LED_OFF() PORTBbits.RB1=1
#define RS485_TRANSMIT_DISABLE() PORTCbits.RC5=0
#define RS485_TRANSMIT_ENABLE() PORTCbits.RC5=1
/* note: board is inverted logic */
#define JUMPER_LK2_TOP_OFF() PORTAbits.RA4
#define JUMPER_LK2_TOP_ON() (!PORTAbits.RA4)
#define JUMPER_LK2_BOTTOM_OFF() PORTAbits.RA5
#define JUMPER_LK2_BOTTOM_ON() (!PORTAbits.RA5)
#define ZERO_CROSS PORTBbits.RB0
#define I2C_CLK_LATCH LATCbits.LATC3
#define I2C_DATA_LATCH LATCbits.LATC4
#define I2C_CLK PORTCbits.RC3
#define I2C_DATA PORTCbits.RC4
#define I2C_CLK_HI_Z TRISCbits.TRISC3
#define I2C_SDA_HI_Z TRISCbits.TRISC4
#define EEPROM_DATA_LATCH LATAbits.LATA0
#define EEPROM_CLK_LATCH LATAbits.LATA1
#define EEPROM_SDA PORTAbits.RA0
#define EEPROM_CLK PORTAbits.RA1
#define EEPROM_SDA_HI_Z TRISAbits.TRISA0
#define EEPROM_CLK_HI_Z TRISAbits.TRISA1
#define SHIFTREG_LOAD PORTCbits.RC2
#define SHIFTREG_CLK PORTCbits.RC1
#define SHIFTREG_DATA PORTCbits.RC0
#define NO_ANALOGS 0x06 /* None */
#define ALL_ANALOG 0x00 /* RA0 RA1 RA2 RA3 RA5 RE0 RE1 RE2 Ref=Vdd */
#define ANALOG_RA3_REF 0x01 /* RA0 RA1 RA2 RA5 RE0 RE1 RE2 Ref=RA3 */
#define A_ANALOG 0x02 /* RA0 RA1 RA2 RA3 RA5 Ref=Vdd */
#define A_ANALOG_RA3_REF 0x03 /* RA0 RA1 RA2 RA5 Ref=RA3 */
#define RA0_RA1_RA3_ANALOG 0x04 /* RA0 RA1 RA3 Ref=Vdd */
#define RA0_RA1_ANALOG_RA3_REF 0x05 /* RA0 RA1 Ref=RA3 */
#define ANALOG_RA3_RA2_REF 0x08
#define ANALOG_NOT_RE1_RE2 0x09
#define ANALOG_NOT_RE1_RE2_REF_RA3 0x0A
#define ANALOG_NOT_RE1_RE2_REF_RA3_RA2 0x0B
#define A_ANALOG_RA3_RA2_REF 0x0C
#define RA0_RA1_ANALOG_RA3_RA2_REF 0x0D
#define RA0_ANALOG 0x0E
#define RA0_ANALOG_RA3_RA2_REF 0x0F
/* Constants used for SETUP_ADC() are: */
#define ADC_OFF 0
#define ADC_START 4
#define ADC_CLOCK_DIV_2 1
#define ADC_CLOCK_DIV_4 0x101
#define ADC_CLOCK_DIV_8 0x41
#define ADC_CLOCK_DIV_16 0x141
#define ADC_CLOCK_DIV_32 0x81
#define ADC_CLOCK_DIV_64 0x181
#define ADC_CLOCK_INTERNAL 0xc1
#define ADC_DONE_MASK 0x04
#define SET_ADC_CHAN(x) ADCON0 = (ADC_CLOCK_DIV_32 | ((x) << 3))
#define T1_DISABLED 0
#define T1_INTERNAL 0x85
#define T1_EXTERNAL 0x87
#define T1_EXTERNAL_SYNC 0x83
#define T1_CLK_OUT 8
#define T1_DIV_BY_1 0
#define T1_DIV_BY_2 0x10
#define T1_DIV_BY_4 0x20
#define T1_DIV_BY_8 0x30
#define SETUP_TIMER1(mode) T1CON = (mode)
#define T2_DISABLED 0
#define T2_DIV_BY_1 4
#define T2_DIV_BY_4 5
#define T2_DIV_BY_16 6
#define SETUP_TIMER2(mode, period, postscale) \
{ \
T2CON = ((mode) | ((postscale)-1)<<3); \
PR2 = (period); \
}
#define T3_DISABLED 0
#define T3_INTERNAL 0x85
#define T3_EXTERNAL 0x87
#define T3_EXTERNAL_SYNC 0x83
#define T3_DIV_BY_1 0
#define T3_DIV_BY_2 0x10
#define T3_DIV_BY_4 0x20
#define T3_DIV_BY_8 0x30
#define SETUP_TIMER3(mode) T3CON = (mode)
#define CCP_OFF 0
#define CCP_CAPTURE_FE 4
#define CCP_CAPTURE_RE 5
#define CCP_CAPTURE_DIV_4 6
#define CCP_CAPTURE_DIV_16 7
#define CCP_COMPARE_SET_ON_MATCH 8
#define CCP_COMPARE_CLR_ON_MATCH 9
#define CCP_COMPARE_INT 0xA
#define CCP_COMPARE_RESET_TIMER 0xB
#define CCP_PWM 0xC
#define CCP_PWM_PLUS_1 0x1c
#define CCP_PWM_PLUS_2 0x2c
#define CCP_PWM_PLUS_3 0x3c
#define SETUP_CCP1(mode) CCP1CON = (mode)
#define SETUP_CCP2(mode) CCP2CON = (mode)
#define WATCHDOG_TIMER() \
{ \
_asm \
CLRWDT \
_endasm \
}
#define GLOBAL_INT_ENABLE() INTCONbits.GIE = 1
#define GLOBAL_INT_DISABLE() INTCONbits.GIE = 0
#define PERIPHERAL_INT_ENABLE() INTCONbits.PEIE = 1
#define PERIPHERAL_INT_DISABLE() INTCONbits.PEIE = 0
#define TIMER0_INT_ENABLE() INTCONbits.TMR0IE = 1
#define TIMER0_INT_DISABLE() INTCONbits.TMR0IE = 0
#define TIMER2_INT_ENABLE() PIE1bits.TMR2IE = 1
#define TIMER2_INT_DISABLE() PIE1bits.TMR2IE = 0
#define CCP2_INT_ENABLE() PIE2bits.CCP2IE = 1
#define CCP2_INT_DISABLE() PIE2bits.CCP2IE = 0
#define CCP1_INT_ENABLE() PIE1bits.CCP1IE = 1
#define CCP1_INT_DISABLE() PIE1bits.CCP1IE = 0
#define ABUS_INT_ENABLE() PIE1bits.SSPIE = 1
#define ABUS_INT_DISABLE() PIE1bits.SSPIE = 0
#define ABUS_INT_FLAG_CLEAR() PIR1bits.SSPIF = 0
#define USART_RX_INT_DISABLE() PIE1bits.RCIE = 0
#define USART_RX_INT_ENABLE() PIE1bits.RCIE = 1
#define USART_TX_INTERRUPT() PIE1bits.TXIE
#define USART_TX_INT_DISABLE() PIE1bits.TXIE = 0
#define USART_TX_INT_ENABLE() PIE1bits.TXIE = 1
#define USART_TX_ENABLE() TXSTAbits.TXEN = 1
#define USART_TX_INT_FLAG_CLEAR() PIR1bits.TXIF = 0
#define USART_TX_EMPTY() TXSTAbits.TRMT
#define USART_CONTINUOUS_RX_ENABLE() RCSTAbits.CREN = 1
#define USART_CONTINUOUS_RX_DISABLE() RCSTAbits.CREN = 0
#define USART_RX_COMPLETE() PIR1bits.RCIF
#define USART_RX_STATUS() RCSTAbits
#define USART_RX_STATUS() RCSTAbits
#define USART_TRANSMIT(x) TXREG = (x)
#define USART_RECEIVE() RCREG
#define USART_RX_FRAME_ERROR() rcstabits.FERR
/* combine the sequence correctly */
#define USART_RX_SETUP() PIE1bits.RCIE = 1; RCSTAbits.CREN = 1
#define USART_TX_SETUP() PIE1bits.TXIE = 1; TXSTAbits.TXEN = 1
#endif /* HARDWARE_H */
-130
View File
@@ -1,130 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2003 Mark Norton
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Functional
* Description: Handles the init code for the Microchip microprocessor
*
*********************************************************************/
#include <string.h>
#include <stdint.h>
#include "hardware.h"
/* define this to enable ICD */
/*#define USE_ICD */
/* Configuration Bits */
#pragma config OSC = HS
#pragma config PWRT = ON
#pragma config BOR = ON, BORV = 42
#pragma config CCP2MUX = ON
#pragma config STVR = ON
#pragma config LVP = OFF
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CP2 = OFF
#pragma config CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRT2 = OFF
#pragma config WRT3 = OFF
#pragma config WRTB = OFF
#pragma config WRTC = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTR2 = OFF
#pragma config EBTR3 = OFF
#pragma config EBTRB = OFF
#ifdef USE_ICD
#pragma config WDT = OFF, WDTPS = 128
#pragma config DEBUG = ON
#else
#pragma config WDT = ON, WDTPS = 128
#pragma config DEBUG = OFF
#endif /* USE_ICD */
#pragma romdata
/****************************************************************************
* DESCRIPTION: Initializes the PIC, its timers, WDT, etc.
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void init_hardware(void)
{
/* If the processor gets a power on reset then we can do something. */
/* We should not get a reset unless there has been */
/* some kind of power line disturbance. */
if (RCONbits.POR) {
/*do something special! */
}
GLOBAL_INT_DISABLE();
/* Setup PORT A */
TRISA = PORT_A_TRIS_MASK;
/* PORT A can have analog inputs or digital IO */
ADCON1 = NO_ANALOGS;
/* Setup PORT B */
TRISB = PORT_B_TRIS_MASK;
/* Setup PORT C */
TRISC = PORT_C_TRIS_MASK;
/* setup zero cross interrupt to trigger on a low to high edge */
INTCON2bits.INTEDG0 = 1;
/* setup ABUS */
/*ABUS_LED_OFF(); */
/*SSPADD = ABUS_DEFAULT_ADDR; */
/*SSPCON1 = (ABUS_SLAVE_MASK | ABUS_CLK_ENABLE | ABUS_MODE_SETUP); */
/*ABUS_Clear_SSPBUF(); */
/* setup timer2 to reset every 1ms */
CloseTimer2();
PR2 = 250;
OpenTimer2(T2_PS_1_4 & T2_POST_1_5 & 0x7F);
/* Setup our interrupt priorities ---------> all low priority */
RCONbits.IPEN = 1;
IPR1 = 0;
IPR2 = 0;
INTCON2bits.TMR0IP = 0;
INTCON2bits.RBIP = 0;
INTCON3 = 0;
/* Enable interrupts */
TIMER2_INT_ENABLE();
PERIPHERAL_INT_ENABLE();
GLOBAL_INT_ENABLE();
/* Turn on the Zero cross interrupt */
INTCONbits.INT0F = 0;
INTCONbits.INT0E = 1;
}
-33
View File
@@ -1,33 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef INIT_H
#define INIT_H
void init_hardware(void);
#endif
-165
View File
@@ -1,165 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2003 Mark Norton and Steve Karg
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Functional
* Description: Defines the interrupt service routines (ISR) for the
* Microchip microprocessor used in the Synergy lighting
* control project.
*
*********************************************************************/
#include <stdint.h>
#include "hardware.h"
#include "timer.h"
/* interrupt service routines */
extern void RS485_Receive_Interrupt(void);
extern void RS485_Transmit_Interrupt(void);
/****************************************************************************
* DESCRIPTION: High priority interrupt routine
* PARAMETERS: none
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
#pragma interruptlow InterruptHandlerLow save=PROD, section(".tmpdata")
void InterruptHandlerLow(void)
{
/* check for timer0 interrupt */
if ((INTCONbits.TMR0IF) && (INTCONbits.TMR0IE)) {
/* clear interrupt flag */
INTCONbits.TMR0IF = 0;
/* call interrupt handler */
}
/*check for timer1 interrupt */
if ((PIR1bits.TMR1IF) && (PIE1bits.TMR1IE)) {
PIR1bits.TMR1IF = 0;
/* call interrupt handler */
}
/*check for timer2 interrupt */
if ((PIR1bits.TMR2IF) && (PIE1bits.TMR2IE)) {
PIR1bits.TMR2IF = 0;
Timer_Millisecond_Interrupt();
}
/*check for timer3 interrupt */
if ((PIR2bits.TMR3IF) && (PIE2bits.TMR3IE)) {
PIR2bits.TMR3IF = 0;
/* call interrupt handler */
}
/*check for compare 1 int */
if ((PIR1bits.CCP1IF) && (PIE1bits.CCP1IE)) {
PIR1bits.CCP1IF = 0;
/* call interrupt handler */
}
/*check for compare 2 int */
if ((PIR2bits.CCP2IF) && (PIE2bits.CCP2IE)) {
PIR2bits.CCP2IF = 0;
/* call interrupt handler */
}
/*check for USART Rx int */
if ((PIR2bits.EEIF) && (PIE2bits.EEIE)) {
PIR2bits.EEIF = 0; /*clear interrupt flag */
EECON1bits.WREN = 0; /* disable writes */
/* call interrupt handler */
}
/*check for USART Tx int */
if ((PIR1bits.TXIF) && (PIE1bits.TXIE)) {
/* call interrupt handler */
RS485_Transmit_Interrupt();
}
/*check for USART Rx int */
if ((PIR1bits.RCIF) && (PIE1bits.RCIE)) {
/* call interrupt handler */
RS485_Receive_Interrupt();
}
/*check for AD int */
if ((PIR1bits.ADIF) && (PIE1bits.ADIE)) {
/* call interrupt handler */
PIR1bits.ADIF = 0;
}
/*check for I2C receive int (MSSP int) */
if ((PIR1bits.SSPIF) && (PIE1bits.SSPIE)) {
PIR1bits.SSPIF = 0;
/* call interrupt handler */
}
return;
}
/****************************************************************************
* DESCRIPTION: High priority interrupt routine
* PARAMETERS: none
* RETURN: none
* ALGORITHM: none
* NOTES: don't call functions from this function because registers are
* not saved, and saving registers is slower.
*****************************************************************************/
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh(void)
{
/*check for external int */
if ((INTCONbits.INT0IF) && (INTCONbits.INT0IE)) {
/* Test to ensure that we are not getting a false trigger on the
falling edge. Only trigger on Rising edge. */
if (ZERO_CROSS) {
/* timer used to determine when power is gone (no zero crosses) */
/* Power_Timeout = 30; */
/* if (ABUS_Current_Status.Zerox_Fail) */
/* { */
/* ABUS_Flags.SendStatus = TRUE; */
/* ABUS_Current_Status.Zerox_Fail = FALSE; */
/* } */
/* if we get here it means power is good */
/* System_Flags.PowerFail = FALSE; */
}
INTCONbits.INT0IF = 0;
}
return;
}
/****************************************************************************
* DESCRIPTION: High priority interrupt vector
* PARAMETERS: none
* RETURN: none
* ALGORITHM: none
* NOTES: ISRs not here because we would only have 0x10 bytes for code
*****************************************************************************/
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void)
{
_asm goto InterruptHandlerHigh /*jump to interrupt routine */
_endasm}
#pragma code
/****************************************************************************
* DESCRIPTION: Low priority interrupt vector
* PARAMETERS: none
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow(void)
{
_asm goto InterruptHandlerLow /*jump to interrupt routine */
_endasm}
#pragma code
-192
View File
@@ -1,192 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include "mstp.h"
#include "bytes.h"
#include "crc.h"
#include "rs485.h"
#include "init.h"
#include "timer.h"
#include "datalink.h"
#include "handlers.h"
#include "device.h"
#include "hardware.h"
#include "iam.h"
/* for readproperty handler */
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
#include "rp.h"
/* buffer used for encoding RP apdu */
static uint8_t Temp_Buf[MAX_APDU];
/* buffer used for receiving */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* address where message came from */
static BACNET_ADDRESS src;
/* address used to send */
static BACNET_ADDRESS my_address;
/* see demo/handler/h_rp.c for a more complete example */
void My_Read_Property_Handler(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
int pdu_len = 0;
bool send = false;
bool error = false;
int bytes_sent = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_NPDU_DATA npdu_data;
BACNET_ADDRESS my_address;
len = rp_decode_service_request(service_request, service_len, &data);
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], src,
&my_address, &npdu_data);
/* bad decoding - send an abort */
if (len < 0) {
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
} else if (service_data->segmented_message) {
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
} else {
switch (data.object_type) {
case OBJECT_DEVICE:
/* FIXME: probably need a length limitation sent with encode */
if (data.object_instance == Device_Object_Instance_Number()) {
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);
} else
error = true;
} else
error = true;
break;
default:
error = true;
break;
}
}
if (error) {
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
}
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
return;
}
/****************************************************************************
* DESCRIPTION: Handles our calling our module level milisecond counters
* PARAMETERS: none
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
static void Check_Timer_Milliseconds(void)
{
/* We might have missed some so keep doing it until we have got them all */
while (Milliseconds) {
dlmstp_millisecond_timer();
Milliseconds--;
}
}
void main(void)
{
unsigned timeout = 100; /* milliseconds */
uint16_t pdu_len = 0;
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
My_Read_Property_Handler);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler
(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
Device_Set_Object_Instance_Number(5);
dlmstp_set_my_address(0x05);
dlmstp_init();
init_hardware();
/* broadcast an I-Am on startup */
iam_send(&Handler_Transmit_Buffer[0]);
/* loop forever */
for (;;) {
WATCHDOG_TIMER();
/* input */
Check_Timer_Milliseconds();
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* output */
}
return;
}
File diff suppressed because it is too large Load Diff
-246
View File
@@ -1,246 +0,0 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2004 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef MSTP_H
#define MSTP_H
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "bacdef.h"
#include "dlmstp.h"
/* The value 255 is used to denote broadcast when used as a */
/* destination address but is not allowed as a value for a station. */
/* Station addresses for master nodes can be 0-127. */
/* Station addresses for slave nodes can be 127-254. */
#define MSTP_BROADCAST_ADDRESS 255
/* MS/TP Frame Type */
/* Frame Types 8 through 127 are reserved by ASHRAE. */
#define FRAME_TYPE_TOKEN 0
#define FRAME_TYPE_POLL_FOR_MASTER 1
#define FRAME_TYPE_REPLY_TO_POLL_FOR_MASTER 2
#define FRAME_TYPE_TEST_REQUEST 3
#define FRAME_TYPE_TEST_RESPONSE 4
#define FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY 5
#define FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY 6
#define FRAME_TYPE_REPLY_POSTPONED 7
/* Frame Types 128 through 255: Proprietary Frames */
/* These frames are available to vendors as proprietary (non-BACnet) frames. */
/* The first two octets of the Data field shall specify the unique vendor */
/* identification code, most significant octet first, for the type of */
/* vendor-proprietary frame to be conveyed. The length of the data portion */
/* of a Proprietary frame shall be in the range of 2 to 501 octets. */
#define FRAME_TYPE_PROPRIETARY_MIN 128
#define FRAME_TYPE_PROPRIETARY_MAX 255
/* The initial CRC16 checksum value */
#define CRC16_INITIAL_VALUE (0xFFFF)
/* receive FSM states */
typedef enum {
MSTP_RECEIVE_STATE_IDLE = 0,
MSTP_RECEIVE_STATE_PREAMBLE = 1,
MSTP_RECEIVE_STATE_HEADER = 2,
MSTP_RECEIVE_STATE_HEADER_CRC = 3,
MSTP_RECEIVE_STATE_DATA = 4
} MSTP_RECEIVE_STATE;
/* master node FSM states */
typedef enum {
MSTP_MASTER_STATE_INITIALIZE = 0,
MSTP_MASTER_STATE_IDLE = 1,
MSTP_MASTER_STATE_USE_TOKEN = 2,
MSTP_MASTER_STATE_WAIT_FOR_REPLY = 3,
MSTP_MASTER_STATE_DONE_WITH_TOKEN = 4,
MSTP_MASTER_STATE_PASS_TOKEN = 5,
MSTP_MASTER_STATE_NO_TOKEN = 6,
MSTP_MASTER_STATE_POLL_FOR_MASTER = 7,
MSTP_MASTER_STATE_ANSWER_DATA_REQUEST = 8
} MSTP_MASTER_STATE;
struct mstp_port_struct_t {
MSTP_RECEIVE_STATE receive_state;
/* When a master node is powered up or reset, */
/* it shall unconditionally enter the INITIALIZE state. */
MSTP_MASTER_STATE master_state;
/* A Boolean flag set to TRUE by the Receive State Machine */
/* if an error is detected during the reception of a frame. */
/* Set to FALSE by the main state machine. */
unsigned ReceiveError:1;
/* There is data in the buffer */
unsigned DataAvailable:1;
unsigned ReceivedInvalidFrame:1;
/* A Boolean flag set to TRUE by the Receive State Machine */
/* if a valid frame is received. */
/* Set to FALSE by the main state machine. */
unsigned ReceivedValidFrame:1;
/* A Boolean flag set to TRUE by the master machine if this node is the */
/* only known master node. */
unsigned SoleMaster:1;
/* stores the latest received data */
uint8_t DataRegister;
/* Used to accumulate the CRC on the data field of a frame. */
uint16_t DataCRC;
/* Used to store the data length of a received frame. */
unsigned DataLength;
/* Used to store the destination address of a received frame. */
uint8_t DestinationAddress;
/* Used to count the number of received octets or errors. */
/* This is used in the detection of link activity. */
/* Compared to Nmin_octets */
uint8_t EventCount;
/* Used to store the frame type of a received frame. */
uint8_t FrameType;
/* The number of frames sent by this node during a single token hold. */
/* When this counter reaches the value Nmax_info_frames, the node must */
/* pass the token. */
unsigned FrameCount;
/* Used to accumulate the CRC on the header of a frame. */
uint8_t HeaderCRC;
/* Used as an index by the Receive State Machine, up to a maximum value of */
/* InputBufferSize. */
unsigned Index;
/* An array of octets, used to store octets as they are received. */
/* InputBuffer is indexed from 0 to InputBufferSize-1. */
/* The maximum size of a frame is 501 octets. */
uint8_t *InputBuffer;
/* "Next Station," the MAC address of the node to which This Station passes */
/* the token. If the Next_Station is unknown, Next_Station shall be equal to */
/* This_Station. */
uint8_t Next_Station;
/* "Poll Station," the MAC address of the node to which This Station last */
/* sent a Poll For Master. This is used during token maintenance. */
uint8_t Poll_Station;
/* A counter of transmission retries used for Token and Poll For Master */
/* transmission. */
unsigned RetryCount;
/* A timer with nominal 5 millisecond resolution used to measure and */
/* generate silence on the medium between octets. It is incremented by a */
/* timer process and is cleared by the Receive State Machine when activity */
/* is detected and by the SendFrame procedure as each octet is transmitted. */
/* Since the timer resolution is limited and the timer is not necessarily */
/* synchronized to other machine events, a timer value of N will actually */
/* denote intervals between N-1 and N */
uint16_t SilenceTimer;
/* A timer used to measure and generate Reply Postponed frames. It is */
/* incremented by a timer process and is cleared by the Master Node State */
/* Machine when a Data Expecting Reply Answer activity is completed. */
/* note: we always send a reply postponed since a message other than
the reply may be in the transmit queue */
/* uint16_t ReplyPostponedTimer; */
/* Used to store the Source Address of a received frame. */
uint8_t SourceAddress;
/* The number of tokens received by this node. When this counter reaches the */
/* value Npoll, the node polls the address range between TS and NS for */
/* additional master nodes. TokenCount is set to zero at the end of the */
/* polling process. */
unsigned TokenCount;
/* "This Station," the MAC address of this node. TS is generally read from a */
/* hardware DIP switch, or from nonvolatile memory. Valid values for TS are */
/* 0 to 254. The value 255 is used to denote broadcast when used as a */
/* destination address but is not allowed as a value for TS. */
uint8_t This_Station;
/* This parameter represents the value of the Max_Info_Frames property of */
/* the node's Device object. The value of Max_Info_Frames specifies the */
/* maximum number of information frames the node may send before it must */
/* pass the token. Max_Info_Frames may have different values on different */
/* 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. */
unsigned Nmax_info_frames;
/* 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. */
unsigned Nmax_master;
/* An array of octets, used to store PDU octets prior to being transmitted. */
/* 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 */
uint8_t TxFrameType; /* type of message - needed by MS/TP */
};
#define DEFAULT_MAX_INFO_FRAMES 1
#define DEFAULT_MAX_MASTER 127
#define DEFAULT_MAC_ADDRESS 127
/* The minimum time after the end of the stop bit of the final octet of a */
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
/* 40 bits is 4 octets including a start and stop bit with each octet */
#define Tturnaround 40
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
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
*mstp_port);
/* returns true if line is active */
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port);
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 */
unsigned data_len); /* number of bytes of data (up to 501) */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
-44
View File
@@ -1,44 +0,0 @@
BACnet Stack - SourceForge.net
Build for MPLAB IDE
These are some settings that are important when building
the BACnet Stack using MPLAB IDE and MCC18 Compiler,
1. Add the files to the project that you need:
abort.c, apdu.c, bacapp.c, bacdcode.c, bacerror.c,
bacstr.c, crc.c, datetime.c, dcc.c, iam.c,
npdu.c, rd.c, reject.c, rp.c, whois.c, wp.c
From ports/picxx: isr.c, main.c, rs485.c, mstp.c, dlmstp.c
From demo/object/: device.c or dev_tiny.c
objects as needed: ai.c, ao.c, etc.
From demo/handler/: txbuf.c, h_dcc.c, h_rd.c, h_rp.c or h_rp_tiny.c
Additional handlers as needed: h_wp.c
2. Project->Options->Project
General Tab: Include Path:
C:\code\bacnet-stack\;C:\code\bacnet-stack\demo\handler\;C:\code\bacnet-stack\demo\object\;C:\code\bacnet-stack\ports\pic18\
MPLAB C18 Tab: Memory Model:
Code: Large Code Model
Data: Large Data Model
Stack: Multi-bank Model
MPLAB C18 Tab: General: Macro Definitions:
PRINT_ENABLED=0
BACDL_MSTP=1
TSM_ENABLED=0
BIG_ENDIAN=0
3. The linker script must reserve some extra stack space.
//DATABANK NAME=gpr12 START=0xC00 END=0xCFF
//DATABANK NAME=gpr13 START=0xD00 END=0xDFF
DATABANK NAME=stackreg START=0xC00 END=0xDFF PROTECTED
//STACK SIZE=0x100 RAM=gpr13
STACK SIZE=0x200 RAM=stackreg
-365
View File
@@ -1,365 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* The module handles sending data out the RS-485 port */
/* and handles receiving data from the RS-485 port. */
/* Customize this file for your specific hardware */
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "hardware.h"
#include "mstp.h"
#include "comm.h"
#include "eeprom.h"
/* public port info */
extern volatile struct mstp_port_struct_t MSTP_Port;
/* the baud rate is adjustable */
uint32_t RS485_Baud_Rate = 9600;
/* the ISR and other use this for status and control */
COMSTAT RS485_Comstat;
/*#pragma udata MSTPPortData */
/* the buffer for receiving characters */
volatile uint8_t RS485_Rx_Buffer[MAX_MPDU];
/* UART transmission buffer and index */
volatile uint8_t RS485_Tx_Buffer[MAX_MPDU];
/****************************************************************************
* DESCRIPTION: Transmits a frame using the UART
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
uint16_t nbytes)
{ /* number of bytes of data (up to 501) */
uint16_t i = 0; /* loop counter */
uint8_t turnaround_time;
if (!buffer)
return;
/* bounds check */
if (nbytes >= sizeof(RS485_Tx_Buffer))
return;
/* buffer is full. Wait for ISR to transmit. */
while (RS485_Comstat.Tx_Bytes) {
};
/* wait 40 bit times since reception */
if (RS485_Baud_Rate == 9600)
turnaround_time = 4;
else if (RS485_Baud_Rate == 19200)
turnaround_time = 2;
else
turnaround_time = 1;
while (mstp_port->SilenceTimer < turnaround_time) {
};
RS485_Comstat.TxHead = 0;
memcpy((void *) &RS485_Tx_Buffer[0], (void *) buffer, nbytes);
/*for (i = 0; i < nbytes; i++) { */
/* /* put the data into the buffer */ */
/* RS485_Tx_Buffer[i] = *buffer; */
/* buffer++; */
/*} */
RS485_Comstat.Tx_Bytes = nbytes;
/* disable the receiver */
PIE3bits.RC2IE = 0;
RCSTA2bits.CREN = 0;
/* enable the transceiver */
RS485_TX_ENABLE = 1;
RS485_RX_DISABLE = 1;
/* enable the transmitter */
TXSTA2bits.TXEN = 1;
PIE3bits.TX2IE = 1;
/* per MSTP spec, sort of */
mstp_port->SilenceTimer = 0;
return;
}
/****************************************************************************
* DESCRIPTION: Checks for data on the receive UART, and handles errors
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *
mstp_port)
{
/* check for data */
if (RS485_Comstat.Rx_Bytes) {
mstp_port->DataRegister = RS485_Rx_Buffer[RS485_Comstat.RxTail];
if (RS485_Comstat.RxTail >= (sizeof(RS485_Rx_Buffer) - 1))
RS485_Comstat.RxTail = 0;
else
RS485_Comstat.RxTail++;
RS485_Comstat.Rx_Bytes--;
/* errors? let the state machine know */
if (RS485_Comstat.Rx_Bufferoverrun) {
RS485_Comstat.Rx_Bufferoverrun = FALSE;
mstp_port->ReceiveError = TRUE;
}
/* We read a good byte */
else
mstp_port->DataAvailable = TRUE;
}
return RS485_Comstat.Rx_Bytes;
}
/* *************************************************************************
DESCRIPTION: Receives RS485 data stream
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void RS485_Interrupt_Rx(void)
{
char dummy;
if ((RCSTA2bits.FERR) || (RCSTA2bits.OERR)) {
/* Clear the error */
RCSTA2bits.CREN = 0;
RCSTA2bits.CREN = 1;
RS485_Comstat.Rx_Bufferoverrun = TRUE;
dummy = RCREG2;
} else if (RS485_Comstat.Rx_Bytes < sizeof(RS485_Rx_Buffer)) {
RS485_Rx_Buffer[RS485_Comstat.RxHead] = RCREG2;
if (RS485_Comstat.RxHead >= (sizeof(RS485_Rx_Buffer) - 1))
RS485_Comstat.RxHead = 0;
else
RS485_Comstat.RxHead++;
RS485_Comstat.Rx_Bytes++;
} else {
RS485_Comstat.Rx_Bufferoverrun = TRUE;
dummy = RCREG2;
(void) dummy;
}
}
/* *************************************************************************
DESCRIPTION: Transmits a byte using the UART out the RS485 port
RETURN: none
ALGORITHM: none
NOTES: none
*************************************************************************** */
void RS485_Interrupt_Tx(void)
{
if (RS485_Comstat.Tx_Bytes) {
/* Get the data byte */
TXREG2 = RS485_Tx_Buffer[RS485_Comstat.TxHead];
/* point to the next byte */
RS485_Comstat.TxHead++;
/* reduce the buffer size */
RS485_Comstat.Tx_Bytes--;
} else {
/* wait for the USART to be empty */
while (!TXSTA2bits.TRMT);
/* disable this interrupt */
PIE3bits.TX2IE = 0;
/* enable the receiver */
RS485_TX_ENABLE = 0;
RS485_RX_DISABLE = 0;
/* FIXME: might not be necessary */
PIE3bits.RC2IE = 1;
RCSTA2bits.CREN = 1;
}
}
/****************************************************************************
* DESCRIPTION: Returns the baud rate that we are currently running at
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
{
return RS485_Baud_Rate;
}
/****************************************************************************
* DESCRIPTION: Sets the baud rate for the chip USART
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Set_Baud_Rate(uint32_t baud)
{
if (baud < 19200)
RS485_Baud_Rate = 9600;
else if (baud < 38400)
RS485_Baud_Rate = 19200;
else if (baud < 57600)
RS485_Baud_Rate = 38400;
else if (baud < 57600)
RS485_Baud_Rate = 57600;
else if (baud < 115200)
RS485_Baud_Rate = 76800;
else
RS485_Baud_Rate = 115200;
I2C_Write_Block(EEPROM_DEVICE_ADDRESS,
(char *) &RS485_Baud_Rate,
sizeof(RS485_Baud_Rate), EEPROM_MSTP_BAUD_RATE_ADDR);
}
/****************************************************************************
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
* receive mode.
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize_Port(void)
{
/* Reset USART registers to POR state */
TXSTA2 = 0;
RCSTA2 = 0;
/* configure USART for receiving */
/* since the TX will handle setting up for transmit */
RCSTA2bits.CREN = 1;
/* Interrupt on receipt */
PIE3bits.RC2IE = 1;
/* enable the transmitter, disable its interrupt */
TXSTA2bits.TXEN = 1;
PIE3bits.TX2IE = 0;
/* setup USART Baud Rate Generator */
/* see BAUD RATES FOR ASYNCHRONOUS MODE in Data Book */
/* Fosc=20MHz
BRGH=1 BRGH=0
Rate SPBRG Rate SPBRG
------- ----- ------- -----
9615 129 9469 32
19230 64 19530 15
37878 32 78130 3
56818 21 104200 2
113630 10 312500 0
250000 4
625000 1
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;
}
/* select async mode */
TXSTA2bits.SYNC = 0;
/* enable transmitter */
TXSTA2bits.TXEN = 1;
/* serial port enable */
RCSTA2bits.SPEN = 1;
/* since we are using RS485,
we need to explicitly say
transmit enable or not */
RS485_RX_DISABLE = 0;
RS485_TX_ENABLE = 0;
}
/****************************************************************************
* DESCRIPTION: Disables the RS485 hardware
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Disable_Port(void)
{
RCSTA2 &= 0x4F; /* Disable the receiver */
TXSTA2bits.TXEN = 0; /* and transmitter */
PIE3 &= 0xCF; /* Disable both interrupts */
}
void RS485_Reinit(void)
{
RS485_Set_Baud_Rate(9600);
}
/****************************************************************************
* DESCRIPTION: Initializes the data and the port
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize(void)
{
/* Init the Rs485 buffers */
RS485_Comstat.RxHead = 0;
RS485_Comstat.RxTail = 0;
RS485_Comstat.Rx_Bytes = 0;
RS485_Comstat.Rx_Bufferoverrun = FALSE;
RS485_Comstat.TxHead = 0;
RS485_Comstat.TxTail = 0;
RS485_Comstat.Tx_Bytes = 0;
I2C_Read_Block(EEPROM_DEVICE_ADDRESS,
(char *) &RS485_Baud_Rate,
sizeof(RS485_Baud_Rate), EEPROM_MSTP_BAUD_RATE_ADDR);
RS485_Initialize_Port();
}
-74
View File
@@ -1,74 +0,0 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2004 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef RS485_H
#define RS485_H
#include <stdint.h>
#include "mstp.h"
#include "comm.h"
extern COMSTAT RS485_Comstat;
extern volatile uint8_t RS485_Rx_Buffer[MAX_MPDU];
extern volatile uint8_t RS485_Tx_Buffer[MAX_MPDU];
extern uint32_t RS485_Baud_Rate;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void RS485_Reinit(void);
void RS485_Initialize(void);
void RS485_Disable(void);
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 */
void RS485_Interrupt_Rx(void);
void RS485_Interrupt_Tx(void);
uint32_t RS485_Get_Baud_Rate(void);
void RS485_Set_Baud_Rate(uint32_t baud);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
-28
View File
@@ -1,28 +0,0 @@
#ifndef STDBOOL_H
#define STDBOOL_H
/* C99 Boolean types for compilers without C99 support */
#ifndef __cplusplus
typedef char _Bool;
#ifndef bool
#define bool _Bool
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
#define __bool_true_false_are_defined 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#endif
-18
View File
@@ -1,18 +0,0 @@
/* Defines the standard integer types that are used in code */
#ifndef STDINT_H
#define STDINT_H 1
#include <stddef.h>
typedef unsigned char uint8_t; /* 1 byte 0 to 255 */
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 long uint32_t; /* 4 bytes 0 to 4294967295 */
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 */
-45
View File
@@ -1,45 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
*********************************************************************/
#include <stdint.h>
volatile uint8_t Milliseconds; /* used for timing stuff - counts up to 0xFF. */
/****************************************************************************
* DESCRIPTION: Timer is set to go off every 1ms. We increment the counter,
* and the main task will decrement the counter.
* PARAMETERS: none
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void Timer_Millisecond_Interrupt(void)
{
/* Global Milisecond timer */
if (Milliseconds < 0xFF)
Milliseconds++;
return;
}
-34
View File
@@ -1,34 +0,0 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef TIMER_H
#define TIMER_H
/* used for timing stuff - counts up to 0xFF. */
extern volatile uint8_t Milliseconds;
void Timer_Millisecond_Interrupt(void);
#endif